[PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration
From: Prabhakar
Date: Tue Sep 29 2026 - 08:43:27 EST
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
Prepare the driver for supporting SoCs with ADC IP that is similar to the
RZ/T2H ADC but may have different channel configurations.
Introduce chip-specific configuration for the channel template and number
of channels, and use it when setting up the IIO channels and DMA layout.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
drivers/iio/adc/rzt2h_adc.c | 49 ++++++++++++++++++++++++++++---------
1 file changed, 38 insertions(+), 11 deletions(-)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index d53888730f00..f1a830da6f9b 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -56,15 +56,21 @@
#define RZT2H_ADC_DMA_PERIODS 64
#define RZT2H_ADC_DMA_BUFFER_SAMPLES (RZT2H_ADC_DMA_PERIODS * \
RZT2H_ADC_DMA_PERIOD_SAMPLES)
-#define RZT2H_ADC_DMA_BUFFER_SIZE (RZT2H_ADC_DMA_BUFFER_SAMPLES * \
- RZT2H_ADC_MAX_CHANNELS * \
- RZT2H_ADC_CHANNEL_BYTES)
#define RZT2H_ADC_STOP_CYCLES 2
+#define RZT2H_ADC_FEATURE_CALIBRATION BIT(0)
+
+struct rzt2h_adc_chip_info {
+ const struct iio_chan_spec *chan_template;
+ unsigned int num_channels;
+ u8 features;
+};
+
struct rzt2h_adc_dma {
struct dma_chan *chan;
u16 *buf;
dma_addr_t addr;
+ size_t buf_size;
unsigned int period_index;
unsigned int period_bytes;
@@ -83,6 +89,7 @@ struct rzt2h_adc_dma {
struct rzt2h_adc {
void __iomem *base;
struct device *dev;
+ const struct rzt2h_adc_chip_info *chip_info;
phys_addr_t phys_base;
struct rzt2h_adc_dma dma;
@@ -325,7 +332,8 @@ static void rzt2h_adc_dma_callback(void *data)
static void rzt2h_adc_dma_calc_layout(struct iio_dev *indio_dev)
{
struct rzt2h_adc *adc = iio_priv(indio_dev);
- unsigned int hi = 0, lo = RZT2H_ADC_MAX_CHANNELS - 1;
+ const struct rzt2h_adc_chip_info *chip_info = adc->chip_info;
+ unsigned int hi = 0, lo = chip_info->num_channels - 1;
const struct iio_chan_spec *chan;
unsigned int sample_chans;
unsigned int first_chan;
@@ -346,7 +354,7 @@ static void rzt2h_adc_dma_calc_layout(struct iio_dev *indio_dev)
* width, so pick the smallest power-of-two-aligned block of channels
* that covers all enabled channels.
*/
- for (sample_chans = 1; sample_chans < RZT2H_ADC_MAX_CHANNELS; sample_chans <<= 1) {
+ for (sample_chans = 1; sample_chans < chip_info->num_channels; sample_chans <<= 1) {
first_chan = round_down(lo, sample_chans);
if (first_chan + sample_chans > hi)
@@ -606,8 +614,8 @@ static int rzt2h_adc_parse_properties(struct rzt2h_adc *adc)
int ret;
ret = devm_iio_adc_device_alloc_chaninfo_se(adc->dev,
- &rzt2h_adc_chan_template,
- RZT2H_ADC_MAX_CHANNELS - 1,
+ adc->chip_info->chan_template,
+ adc->chip_info->num_channels - 1,
&chan_array);
if (ret < 0)
return dev_err_probe(adc->dev, ret, "Failed to read channel info");
@@ -628,7 +636,7 @@ static void rzt2h_adc_free_dma_buf(void *p)
{
struct rzt2h_adc *adc = p;
- dma_free_noncoherent(adc->dev, RZT2H_ADC_DMA_BUFFER_SIZE,
+ dma_free_noncoherent(adc->dev, adc->dma.buf_size,
adc->dma.buf, adc->dma.addr, DMA_FROM_DEVICE);
}
@@ -648,13 +656,16 @@ static int rzt2h_adc_setup_dma(struct iio_dev *indio_dev)
return 0;
}
- adc->dma.buf = dma_alloc_noncoherent(dev, RZT2H_ADC_DMA_BUFFER_SIZE,
+ adc->dma.buf_size = adc->chip_info->num_channels *
+ RZT2H_ADC_DMA_BUFFER_SAMPLES *
+ RZT2H_ADC_CHANNEL_BYTES;
+ adc->dma.buf = dma_alloc_noncoherent(dev, adc->dma.buf_size,
&adc->dma.addr, DMA_FROM_DEVICE,
GFP_KERNEL);
if (!adc->dma.buf)
return -ENOMEM;
- dma_sync_single_for_device(dev, adc->dma.addr, RZT2H_ADC_DMA_BUFFER_SIZE,
+ dma_sync_single_for_device(dev, adc->dma.addr, adc->dma.buf_size,
DMA_FROM_DEVICE);
ret = devm_add_action_or_reset(dev, rzt2h_adc_free_dma_buf, adc);
@@ -667,6 +678,7 @@ static int rzt2h_adc_setup_dma(struct iio_dev *indio_dev)
static int rzt2h_adc_probe(struct platform_device *pdev)
{
+ const struct rzt2h_adc_chip_info *chip_info;
struct device *dev = &pdev->dev;
struct iio_dev *indio_dev;
struct rzt2h_adc *adc;
@@ -674,11 +686,16 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
struct clk *adclk;
int ret;
+ chip_info = device_get_match_data(dev);
+ if (!chip_info)
+ return -ENODEV;
+
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
+ adc->chip_info = chip_info;
adc->dev = dev;
init_completion(&adc->completion);
init_waitqueue_head(&adc->dma.wq);
@@ -738,8 +755,14 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
return devm_iio_device_register(dev, indio_dev);
}
+static const struct rzt2h_adc_chip_info rzt2h_adc_info = {
+ .chan_template = &rzt2h_adc_chan_template,
+ .num_channels = 16,
+ .features = RZT2H_ADC_FEATURE_CALIBRATION,
+};
+
static const struct of_device_id rzt2h_adc_match[] = {
- { .compatible = "renesas,r9a09g077-adc" },
+ { .compatible = "renesas,r9a09g077-adc", .data = &rzt2h_adc_info },
{ }
};
MODULE_DEVICE_TABLE(of, rzt2h_adc_match);
@@ -747,6 +770,10 @@ MODULE_DEVICE_TABLE(of, rzt2h_adc_match);
static int rzt2h_adc_pm_runtime_resume(struct device *dev)
{
struct rzt2h_adc *adc = dev_get_drvdata(dev);
+ const struct rzt2h_adc_chip_info *chip_info = adc->chip_info;
+
+ if (!(chip_info->features & RZT2H_ADC_FEATURE_CALIBRATION))
+ return 0;
/*
* Datasheet Page 2810, Section 41.5.6:
--
2.55.0