* [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs
@ 2026-09-29 12:42 Prabhakar
2026-09-29 12:42 ` [PATCH 1/8] dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N support Prabhakar
` (7 more replies)
0 siblings, 8 replies; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Hi all,
This patch series aims to add ADC support for the RZ/V2H(P) and RZ/V2N
SoCs. The ADC IP on these SoCs is similar to the one found on the RZ/T2H
SoC but varies slightly in terms of available channels and configuration
options.
Cheers,
Prabhakar
Lad Prabhakar (8):
dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N
support
iio: adc: rzt2h: Wait for the analog part to stop after a forced stop
iio: adc: rzt2h: Add chip-specific configuration
iio: adc: rzt2h: Add optional reset support
iio: adc: rzt2h: Prepare for SoCs without sample state registers
iio: adc: rzt2h: Prepare for SoCs with different ADC info
iio: adc: rzt2h: Use scan type for ADC scale
iio: adc: rzt2h: Add support for RZ/V2H(P) SoC
.../iio/adc/renesas,r9a09g077-adc.yaml | 38 ++-
drivers/iio/adc/Kconfig | 3 +-
drivers/iio/adc/rzt2h_adc.c | 321 ++++++++++++++++--
3 files changed, 335 insertions(+), 27 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/8] dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N support
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-29 12:42 ` [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop Prabhakar
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Extend the ADC binding for the RZ/V2H(P) and RZ/V2N SoCs to describe the
ADC variant used by these SoCs and its differences from RZ/T2H.
The RZ/V2H(P) ADC provides 8 channels, has a fixed conversion time of
20 ADCLK cycles, does not support calibration, and supports selectable
12-bit and 8-bit conversion resolution.
Add RZ/V2N with RZ/V2H(P) as its fallback compatible, as the ADC IP is
identical between the two SoCs.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
.../iio/adc/renesas,r9a09g077-adc.yaml | 38 +++++++++++++++++--
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,r9a09g077-adc.yaml b/Documentation/devicetree/bindings/iio/adc/renesas,r9a09g077-adc.yaml
index 5b496729022e..a0fed2f31370 100644
--- a/Documentation/devicetree/bindings/iio/adc/renesas,r9a09g077-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/renesas,r9a09g077-adc.yaml
@@ -18,10 +18,14 @@ description: |
properties:
compatible:
oneOf:
+ - enum:
+ - renesas,r9a09g057-adc # RZ/V2H(P)
+ - renesas,r9a09g077-adc # RZ/T2H
- items:
- - const: renesas,r9a09g087-adc # RZ/N2H
- - const: renesas,r9a09g077-adc # RZ/T2H
+ - const: renesas,r9a09g056-adc # RZ/V2N
+ - const: renesas,r9a09g057-adc # RZ/V2H(P)
- items:
+ - const: renesas,r9a09g087-adc # RZ/N2H
- const: renesas,r9a09g077-adc # RZ/T2H
reg:
@@ -55,19 +59,22 @@ properties:
dmas:
minItems: 1
- maxItems: 3
+ maxItems: 5
description:
Must contain a list of references to DMA RX specifiers.
dma-names:
minItems: 1
- maxItems: 3
+ maxItems: 5
items:
const: rx
power-domains:
maxItems: 1
+ resets:
+ maxItems: 1
+
'#address-cells':
const: 1
@@ -101,6 +108,29 @@ required:
- clock-names
- power-domains
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,r9a09g057-adc
+ then:
+ required:
+ - resets
+ patternProperties:
+ "^channel@[8-f]$": false
+ "^channel@[0-7]$":
+ properties:
+ reg:
+ maximum: 7
+ else:
+ properties:
+ dmas:
+ maxItems: 3
+ dma-names:
+ maxItems: 3
+ resets: false
+
additionalProperties: false
examples:
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
2026-09-29 12:42 ` [PATCH 1/8] dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N support Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-30 9:23 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration Prabhakar
` (5 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
When ADCSR.ADST is cleared to forcibly stop a conversion, the analog part
of the A/D converter can take up to 2 ADCLK cycles to stop operating.
Wait for the write to ADCSR to complete and allow the analog part to stop
before reconfiguring or restarting the converter.
Fixes: fc3b97dd71ab ("iio: adc: add RZ/T2H / RZ/N2H ADC driver")
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/rzt2h_adc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index 8ba7b0fde8a1..d53888730f00 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kthread.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -58,6 +59,7 @@
#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
struct rzt2h_adc_dma {
struct dma_chan *chan;
@@ -124,6 +126,13 @@ static void rzt2h_adc_stop(struct rzt2h_adc *adc)
reg &= ~(RZT2H_ADCSR_ADIE_MASK | RZT2H_ADCSR_ADST_MASK);
writew(reg, adc->base + RZT2H_ADCSR_REG);
+
+ /*
+ * When a conversion is forcibly stopped, the analog part of the A/D
+ * converter takes up to 2 ADCLK cycles to stop operating.
+ */
+ ndelay(DIV_ROUND_UP_ULL((u64)RZT2H_ADC_STOP_CYCLES * NSEC_PER_SEC,
+ adc->adclk_rate));
}
static void rzt2h_adc_set_sst(struct rzt2h_adc *adc, unsigned int ch, u8 sst)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
2026-09-29 12:42 ` [PATCH 1/8] dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N support Prabhakar
2026-09-29 12:42 ` [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-30 9:26 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 4/8] iio: adc: rzt2h: Add optional reset support Prabhakar
` (4 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
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@bp.renesas.com>
---
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
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/8] iio: adc: rzt2h: Add optional reset support
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
` (2 preceding siblings ...)
2026-09-29 12:42 ` [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-29 12:42 ` [PATCH 5/8] iio: adc: rzt2h: Prepare for SoCs without sample state registers Prabhakar
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Prepare the driver for RZ/V2H(P), where the ADC has a module reset line
that is not present on RZ/T2H.
Assert the optional reset when the ADC is runtime-suspended and deassert it
on runtime resume before performing calibration. Assert the reset again if
calibration fails.
Use a shared reset control to support SoCs such as RZ/V2N where the reset
line is shared between multiple ADC instances.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/rzt2h_adc.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index f1a830da6f9b..4726f892da23 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
+#include <linux/reset.h>
#define RZT2H_ADCSR_REG 0x00
#define RZT2H_ADCSR_ADIE_MASK BIT(12)
@@ -90,6 +91,7 @@ struct rzt2h_adc {
void __iomem *base;
struct device *dev;
const struct rzt2h_adc_chip_info *chip_info;
+ struct reset_control *rstc;
phys_addr_t phys_base;
struct rzt2h_adc_dma dma;
@@ -706,6 +708,10 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, adc);
+ adc->rstc = devm_reset_control_get_optional_shared(dev, NULL);
+ if (IS_ERR(adc->rstc))
+ return PTR_ERR(adc->rstc);
+
ret = rzt2h_adc_parse_properties(adc);
if (ret)
return ret;
@@ -767,10 +773,22 @@ static const struct of_device_id rzt2h_adc_match[] = {
};
MODULE_DEVICE_TABLE(of, rzt2h_adc_match);
+static int rzt2h_adc_pm_runtime_suspend(struct device *dev)
+{
+ struct rzt2h_adc *adc = dev_get_drvdata(dev);
+
+ return reset_control_assert(adc->rstc);
+}
+
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;
+ int ret;
+
+ ret = reset_control_deassert(adc->rstc);
+ if (ret)
+ return ret;
if (!(chip_info->features & RZT2H_ADC_FEATURE_CALIBRATION))
return 0;
@@ -782,11 +800,15 @@ static int rzt2h_adc_pm_runtime_resume(struct device *dev)
*/
fsleep(1);
- return rzt2h_adc_calibrate(adc);
+ ret = rzt2h_adc_calibrate(adc);
+ if (ret)
+ reset_control_assert(adc->rstc);
+
+ return ret;
}
static const struct dev_pm_ops rzt2h_adc_pm_ops = {
- RUNTIME_PM_OPS(NULL, rzt2h_adc_pm_runtime_resume, NULL)
+ RUNTIME_PM_OPS(rzt2h_adc_pm_runtime_suspend, rzt2h_adc_pm_runtime_resume, NULL)
};
static struct platform_driver rzt2h_adc_driver = {
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/8] iio: adc: rzt2h: Prepare for SoCs without sample state registers
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
` (3 preceding siblings ...)
2026-09-29 12:42 ` [PATCH 4/8] iio: adc: rzt2h: Add optional reset support Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-29 12:42 ` [PATCH 6/8] iio: adc: rzt2h: Prepare for SoCs with different ADC info Prabhakar
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Prepare the driver for SoCs that use the same ADC IP without the
per-channel sample state registers present on RZ/T2H.
Add a feature flag for the sample state registers and make the sampling
frequency handling conditional on their presence. Allow each SoC to
provide its own sampling frequency calculation and configure the existing
RZ/T2H support to use the sample state registers and corresponding
calculation.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/rzt2h_adc.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index 4726f892da23..cf34895928f1 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -60,9 +60,13 @@
#define RZT2H_ADC_STOP_CYCLES 2
#define RZT2H_ADC_FEATURE_CALIBRATION BIT(0)
+#define RZT2H_ADC_FEATURE_SAMPLE_STATE BIT(1)
+
+struct rzt2h_adc;
struct rzt2h_adc_chip_info {
const struct iio_chan_spec *chan_template;
+ int (*sst_to_freq)(struct rzt2h_adc *adc, u8 sst);
unsigned int num_channels;
u8 features;
};
@@ -146,6 +150,9 @@ static void rzt2h_adc_stop(struct rzt2h_adc *adc)
static void rzt2h_adc_set_sst(struct rzt2h_adc *adc, unsigned int ch, u8 sst)
{
+ if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_SAMPLE_STATE))
+ return;
+
writeb(sst, adc->base + RZT2H_ADSSTRn(ch));
}
@@ -526,7 +533,7 @@ static int rzt2h_adc_read_raw(struct iio_dev *indio_dev,
*val2 = 12;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
- *val = rzt2h_adc_sst_to_freq(adc, adc->sst[chan->channel]);
+ *val = adc->chip_info->sst_to_freq(adc, adc->sst[chan->channel]);
return IIO_VAL_INT;
default:
return -EINVAL;
@@ -541,6 +548,8 @@ static int rzt2h_adc_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ: {
+ if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_SAMPLE_STATE))
+ return -EINVAL;
if (val <= 0)
return -EINVAL;
@@ -730,9 +739,11 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
if (!adc->adclk_rate)
return dev_err_probe(dev, -EINVAL, "invalid adclk rate\n");
- adc->samp_freq_avail[0] = rzt2h_adc_sst_to_freq(adc, RZT2H_ADC_SST_MAX);
- adc->samp_freq_avail[1] = 1;
- adc->samp_freq_avail[2] = rzt2h_adc_sst_to_freq(adc, RZT2H_ADC_SST_MIN);
+ if (chip_info->features & RZT2H_ADC_FEATURE_SAMPLE_STATE) {
+ adc->samp_freq_avail[0] = chip_info->sst_to_freq(adc, RZT2H_ADC_SST_MAX);
+ adc->samp_freq_avail[1] = 1;
+ adc->samp_freq_avail[2] = chip_info->sst_to_freq(adc, RZT2H_ADC_SST_MIN);
+ }
pm_runtime_set_autosuspend_delay(dev, 300);
pm_runtime_use_autosuspend(dev);
@@ -763,8 +774,9 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
static const struct rzt2h_adc_chip_info rzt2h_adc_info = {
.chan_template = &rzt2h_adc_chan_template,
+ .sst_to_freq = rzt2h_adc_sst_to_freq,
.num_channels = 16,
- .features = RZT2H_ADC_FEATURE_CALIBRATION,
+ .features = RZT2H_ADC_FEATURE_CALIBRATION | RZT2H_ADC_FEATURE_SAMPLE_STATE,
};
static const struct of_device_id rzt2h_adc_match[] = {
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 6/8] iio: adc: rzt2h: Prepare for SoCs with different ADC info
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
` (4 preceding siblings ...)
2026-09-29 12:42 ` [PATCH 5/8] iio: adc: rzt2h: Prepare for SoCs without sample state registers Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-29 12:42 ` [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale Prabhakar
2026-09-29 12:42 ` [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC Prabhakar
7 siblings, 0 replies; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Prepare the driver for RZ/V2H(P) support, where the ADC supports 8-bit and
12-bit conversion modes with channel configurations that differ from
RZ/T2H.
Allow each SoC to provide its own IIO info structure and use the
chip-specific configuration when registering the IIO device.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/rzt2h_adc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index cf34895928f1..26028856b175 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -67,6 +67,7 @@ struct rzt2h_adc;
struct rzt2h_adc_chip_info {
const struct iio_chan_spec *chan_template;
int (*sst_to_freq)(struct rzt2h_adc *adc, u8 sst);
+ const struct iio_info *info;
unsigned int num_channels;
u8 features;
};
@@ -760,7 +761,7 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
return ret;
indio_dev->name = "rzt2h-adc";
- indio_dev->info = &rzt2h_adc_iio_info;
+ indio_dev->info = chip_info->info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adc->channels;
indio_dev->num_channels = adc->num_channels;
@@ -775,6 +776,7 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
static const struct rzt2h_adc_chip_info rzt2h_adc_info = {
.chan_template = &rzt2h_adc_chan_template,
.sst_to_freq = rzt2h_adc_sst_to_freq,
+ .info = &rzt2h_adc_iio_info,
.num_channels = 16,
.features = RZT2H_ADC_FEATURE_CALIBRATION | RZT2H_ADC_FEATURE_SAMPLE_STATE,
};
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
` (5 preceding siblings ...)
2026-09-29 12:42 ` [PATCH 6/8] iio: adc: rzt2h: Prepare for SoCs with different ADC info Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-30 9:28 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC Prabhakar
7 siblings, 1 reply; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Prepare the driver for RZ/V2H(P) support, where the ADC supports both
12-bit and 8-bit conversion resolutions.
Use the current IIO scan type to determine the ADC resolution when
reporting the scale instead of assuming a fixed 12-bit resolution.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/rzt2h_adc.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index 26028856b175..953736b5475a 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -59,6 +59,8 @@
RZT2H_ADC_DMA_PERIOD_SAMPLES)
#define RZT2H_ADC_STOP_CYCLES 2
+#define RZT2H_ADC_VREF_MV 1800
+
#define RZT2H_ADC_FEATURE_CALIBRATION BIT(0)
#define RZT2H_ADC_FEATURE_SAMPLE_STATE BIT(1)
@@ -529,10 +531,18 @@ static int rzt2h_adc_read_raw(struct iio_dev *indio_dev,
return rzt2h_adc_read_single(adc, chan->channel, val);
}
- case IIO_CHAN_INFO_SCALE:
- *val = 1800;
- *val2 = 12;
+ case IIO_CHAN_INFO_SCALE: {
+ const struct iio_scan_type *scan_type;
+
+ scan_type = iio_get_current_scan_type(indio_dev, chan);
+ if (IS_ERR(scan_type))
+ return PTR_ERR(scan_type);
+
+ *val = RZT2H_ADC_VREF_MV;
+ *val2 = scan_type->realbits;
+
return IIO_VAL_FRACTIONAL_LOG2;
+ }
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adc->chip_info->sst_to_freq(adc, adc->sst[chan->channel]);
return IIO_VAL_INT;
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
` (6 preceding siblings ...)
2026-09-29 12:42 ` [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale Prabhakar
@ 2026-09-29 12:42 ` Prabhakar
2026-09-30 9:35 ` Andy Shevchenko
7 siblings, 1 reply; 13+ messages in thread
From: Prabhakar @ 2026-09-29 12:42 UTC (permalink / raw)
To: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio
Cc: linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Add support for the ADC found on the Renesas RZ/V2H(P) SoC, which shares
the RZ/T2H ADC IP but differs in channel count, sampling, calibration and
resolution support.
The RZ/V2H(P) ADC provides 8 channels, has a fixed conversion time of
20 ADCLK cycles, does not support calibration, and supports selectable
12-bit and 8-bit conversion resolution.
Expose the fixed sampling frequency as a read-only attribute and allow
the conversion resolution to be changed through the scale attribute.
Use extended scan types so the reported scan type follows the selected
resolution, and prevent resolution changes while buffered capture is
active.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/iio/adc/Kconfig | 3 +-
drivers/iio/adc/rzt2h_adc.c | 201 +++++++++++++++++++++++++++++++++++-
2 files changed, 200 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a802d8ee4dd9..052bc018e97d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1592,9 +1592,10 @@ config RZT2H_ADC
select IIO_ADC_HELPER
select IIO_BUFFER
select IIO_KFIFO_BUF
+ select POWER_SEQUENCING
help
Say yes here to build support for the ADC found in Renesas
- RZ/T2H / RZ/N2H SoCs.
+ RZ/T2H / RZ/N2H (and similar SoCs).
To compile this driver as a module, choose M here: the
module will be called rzt2h_adc.
diff --git a/drivers/iio/adc/rzt2h_adc.c b/drivers/iio/adc/rzt2h_adc.c
index 953736b5475a..0db936097740 100644
--- a/drivers/iio/adc/rzt2h_adc.c
+++ b/drivers/iio/adc/rzt2h_adc.c
@@ -20,7 +20,9 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/reset.h>
+#include <linux/units.h>
#define RZT2H_ADCSR_REG 0x00
#define RZT2H_ADCSR_ADIE_MASK BIT(12)
@@ -32,6 +34,11 @@
#define RZT2H_ADANSA0_REG 0x04
#define RZT2H_ADANSA0_CH_MASK(x) BIT(x)
+#define RZT2H_ADCER_REG 0x0e
+#define RZT2H_ADCER_ADPRC_MASK GENMASK(2, 1)
+#define RZT2H_ADCER_ADPRC_12BIT 0b00
+#define RZT2H_ADCER_ADPRC_8BIT 0b10
+
#define RZT2H_ADDR_REG(x) (0x20 + 0x2 * (x))
#define RZT2H_ADSSTRn(n) (0xe0 + 0x1 * (n))
@@ -59,13 +66,29 @@
RZT2H_ADC_DMA_PERIOD_SAMPLES)
#define RZT2H_ADC_STOP_CYCLES 2
+/*
+ * RZ/V2H has no sample state register, each A/D channel conversion takes a
+ * fixed 20 ADCLK cycles (sampling + comparison), giving a conversion rate of
+ * ADCLK / 20.
+ */
+#define RZV2H_ADC_CONV_CYCLES 20
+
#define RZT2H_ADC_VREF_MV 1800
#define RZT2H_ADC_FEATURE_CALIBRATION BIT(0)
#define RZT2H_ADC_FEATURE_SAMPLE_STATE BIT(1)
+/* Selectable 12-bit / 8-bit conversion (ADCER.ADPRC) */
+#define RZT2H_ADC_FEATURE_RES_SELECT BIT(2)
+/* Power-down mode controlled by the SYS power sequencer (SY_MSTP_ADA) */
+#define RZT2H_ADC_FEATURE_POWER_DOWN BIT(3)
struct rzt2h_adc;
+enum rzt2h_adc_resolution {
+ RZT2H_ADC_RES_12BIT,
+ RZT2H_ADC_RES_8BIT,
+};
+
struct rzt2h_adc_chip_info {
const struct iio_chan_spec *chan_template;
int (*sst_to_freq)(struct rzt2h_adc *adc, u8 sst);
@@ -99,6 +122,7 @@ struct rzt2h_adc {
struct device *dev;
const struct rzt2h_adc_chip_info *chip_info;
struct reset_control *rstc;
+ struct pwrseq_desc *pwrseq;
phys_addr_t phys_base;
struct rzt2h_adc_dma dma;
@@ -107,6 +131,7 @@ struct rzt2h_adc {
struct mutex lock;
const struct iio_chan_spec *channels;
+ enum rzt2h_adc_resolution resolution;
unsigned int num_channels;
u16 buf[RZT2H_ADC_MAX_CHANNELS];
@@ -117,6 +142,11 @@ struct rzt2h_adc {
int irq;
};
+static const int rzv2h_adc_scale_avail[] = {
+ RZT2H_ADC_VREF_MV, 12,
+ RZT2H_ADC_VREF_MV, 8,
+};
+
static void rzt2h_adc_start(struct rzt2h_adc *adc, unsigned int conversion_type)
{
u16 reg;
@@ -159,6 +189,23 @@ static void rzt2h_adc_set_sst(struct rzt2h_adc *adc, unsigned int ch, u8 sst)
writeb(sst, adc->base + RZT2H_ADSSTRn(ch));
}
+static void rzt2h_adc_set_resolution(struct rzt2h_adc *adc)
+{
+ u16 reg;
+
+ if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_RES_SELECT))
+ return;
+
+ reg = readw(adc->base + RZT2H_ADCER_REG);
+
+ if (adc->resolution == RZT2H_ADC_RES_8BIT)
+ FIELD_MODIFY(RZT2H_ADCER_ADPRC_MASK, ®, RZT2H_ADCER_ADPRC_8BIT);
+ else
+ FIELD_MODIFY(RZT2H_ADCER_ADPRC_MASK, ®, RZT2H_ADCER_ADPRC_12BIT);
+
+ writew(reg, adc->base + RZT2H_ADCER_REG);
+}
+
static int rzt2h_adc_read_single(struct rzt2h_adc *adc, unsigned int ch, int *val)
{
int ret;
@@ -175,12 +222,14 @@ static int rzt2h_adc_read_single(struct rzt2h_adc *adc, unsigned int ch, int *va
writew(RZT2H_ADANSA0_CH_MASK(ch), adc->base + RZT2H_ADANSA0_REG);
rzt2h_adc_set_sst(adc, ch, adc->sst[ch]);
+ rzt2h_adc_set_resolution(adc);
rzt2h_adc_start(adc, RZT2H_ADCSR_ADCS_SINGLE);
/*
* Conversion can take up to ~4.3us at the maximum configurable ADSSTRn
- * (ADSSTRn + 13 cycles at 62.5 MHz), which rounds up to 1 jiffy. A bare
+ * (ADSSTRn + 13 cycles at 62.5 MHz) on RZ/T2H, and up to 4.0us (20
+ * cycles at 5 MHz) on RZ/V2H, which rounds up to 1 jiffy. A bare
* 1-jiffy timeout can expire almost immediately if it's armed right
* before a tick, so add one more jiffy to guarantee the conversion time
* actually elapses.
@@ -468,6 +517,8 @@ static int rzt2h_adc_buffer_postenable(struct iio_dev *indio_dev)
writew(val, adc->base + RZT2H_ADANSA0_REG);
+ rzt2h_adc_set_resolution(adc);
+
adc->dma.period_index = 0;
atomic_set(&adc->dma.pending_periods, 0);
@@ -505,6 +556,11 @@ static int rzt2h_adc_sst_to_freq(struct rzt2h_adc *adc, u8 sst)
return adc->adclk_rate / (RZT2H_ADC_CONV_CYCLES_BASE + sst);
}
+static int rzv2h_adc_sst_to_freq(struct rzt2h_adc *adc, u8 sst)
+{
+ return DIV_ROUND_CLOSEST(adc->adclk_rate, RZV2H_ADC_CONV_CYCLES);
+}
+
static u8 rzt2h_adc_freq_to_sst(struct rzt2h_adc *adc, int freq)
{
unsigned int cycles;
@@ -517,6 +573,46 @@ static u8 rzt2h_adc_freq_to_sst(struct rzt2h_adc *adc, int freq)
return cycles - RZT2H_ADC_CONV_CYCLES_BASE;
}
+static int rzt2h_adc_get_current_scan_type(const struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct rzt2h_adc *adc = iio_priv(indio_dev);
+
+ return adc->resolution;
+}
+
+static int rzt2h_adc_write_scale(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2)
+{
+ struct rzt2h_adc *adc = iio_priv(indio_dev);
+ unsigned int i;
+ u64 scale;
+ u32 rem;
+
+ if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_RES_SELECT))
+ return -EINVAL;
+
+ for (i = 0; i < chan->num_ext_scan_type; i++) {
+ scale = (u64)RZT2H_ADC_VREF_MV * NANO >>
+ chan->ext_scan_type[i].realbits;
+ if (div_u64_rem(scale, NANO, &rem) == val && rem == val2)
+ break;
+ }
+
+ if (i == chan->num_ext_scan_type)
+ return -EINVAL;
+
+ /* The scan type changes with the resolution. */
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_FAILED(claim))
+ return -EBUSY;
+
+ adc->resolution = i;
+
+ return 0;
+}
+
static int rzt2h_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -572,11 +668,25 @@ static int rzt2h_adc_write_raw(struct iio_dev *indio_dev,
return 0;
}
+ case IIO_CHAN_INFO_SCALE:
+ return rzt2h_adc_write_scale(indio_dev, chan, val, val2);
default:
return -EINVAL;
}
}
+static int rzt2h_adc_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
static int rzt2h_adc_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
@@ -590,6 +700,11 @@ static int rzt2h_adc_read_avail(struct iio_dev *indio_dev,
*type = IIO_VAL_INT;
*length = ARRAY_SIZE(adc->samp_freq_avail);
return IIO_AVAIL_RANGE;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = rzv2h_adc_scale_avail;
+ *type = IIO_VAL_FRACTIONAL_LOG2;
+ *length = ARRAY_SIZE(rzv2h_adc_scale_avail);
+ return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
@@ -606,6 +721,14 @@ static const struct iio_info rzt2h_adc_iio_info = {
.read_avail = rzt2h_adc_read_avail,
};
+static const struct iio_info rzv2h_adc_iio_info = {
+ .read_raw = rzt2h_adc_read_raw,
+ .write_raw = rzt2h_adc_write_raw,
+ .write_raw_get_fmt = rzt2h_adc_write_raw_get_fmt,
+ .read_avail = rzt2h_adc_read_avail,
+ .get_current_scan_type = rzt2h_adc_get_current_scan_type,
+};
+
static irqreturn_t rzt2h_adc_isr(int irq, void *private)
{
struct rzt2h_adc *adc = private;
@@ -630,6 +753,33 @@ static const struct iio_chan_spec rzt2h_adc_chan_template = {
},
};
+static const struct iio_scan_type rzv2h_adc_scan_types[] = {
+ [RZT2H_ADC_RES_12BIT] = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ [RZT2H_ADC_RES_8BIT] = {
+ .sign = 'u',
+ .realbits = 8,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+};
+
+static const struct iio_chan_spec rzv2h_adc_chan_template = {
+ .indexed = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .type = IIO_VOLTAGE,
+ .has_ext_scan_type = 1,
+ .ext_scan_type = rzv2h_adc_scan_types,
+ .num_ext_scan_type = ARRAY_SIZE(rzv2h_adc_scan_types),
+};
+
static int rzt2h_adc_parse_properties(struct rzt2h_adc *adc)
{
struct iio_chan_spec *chan_array;
@@ -698,6 +848,21 @@ static int rzt2h_adc_setup_dma(struct iio_dev *indio_dev)
&rzt2h_adc_buffer_setup_ops, NULL);
}
+static int rzt2h_adc_get_pwrseq(struct rzt2h_adc *adc)
+{
+ struct device *dev = adc->dev;
+
+ if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_POWER_DOWN))
+ return 0;
+
+ adc->pwrseq = devm_pwrseq_get(dev, "adc-power");
+ if (IS_ERR(adc->pwrseq))
+ return dev_err_probe(dev, PTR_ERR(adc->pwrseq),
+ "failed to get power sequencer\n");
+
+ return 0;
+}
+
static int rzt2h_adc_probe(struct platform_device *pdev)
{
const struct rzt2h_adc_chip_info *chip_info;
@@ -732,6 +897,10 @@ static int rzt2h_adc_probe(struct platform_device *pdev)
if (IS_ERR(adc->rstc))
return PTR_ERR(adc->rstc);
+ ret = rzt2h_adc_get_pwrseq(adc);
+ if (ret)
+ return ret;
+
ret = rzt2h_adc_parse_properties(adc);
if (ret)
return ret;
@@ -783,6 +952,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 rzv2h_adc_info = {
+ .chan_template = &rzv2h_adc_chan_template,
+ .sst_to_freq = rzv2h_adc_sst_to_freq,
+ .info = &rzv2h_adc_iio_info,
+ .num_channels = 8,
+ .features = RZT2H_ADC_FEATURE_RES_SELECT | RZT2H_ADC_FEATURE_POWER_DOWN,
+};
+
static const struct rzt2h_adc_chip_info rzt2h_adc_info = {
.chan_template = &rzt2h_adc_chan_template,
.sst_to_freq = rzt2h_adc_sst_to_freq,
@@ -792,6 +969,7 @@ static const struct rzt2h_adc_chip_info rzt2h_adc_info = {
};
static const struct of_device_id rzt2h_adc_match[] = {
+ { .compatible = "renesas,r9a09g057-adc", .data = &rzv2h_adc_info },
{ .compatible = "renesas,r9a09g077-adc", .data = &rzt2h_adc_info },
{ }
};
@@ -800,8 +978,17 @@ MODULE_DEVICE_TABLE(of, rzt2h_adc_match);
static int rzt2h_adc_pm_runtime_suspend(struct device *dev)
{
struct rzt2h_adc *adc = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pwrseq_disable(adc->pwrseq);
+ if (ret)
+ return ret;
+
+ ret = reset_control_assert(adc->rstc);
+ if (ret)
+ pwrseq_enable(adc->pwrseq);
- return reset_control_assert(adc->rstc);
+ return ret;
}
static int rzt2h_adc_pm_runtime_resume(struct device *dev)
@@ -814,6 +1001,12 @@ static int rzt2h_adc_pm_runtime_resume(struct device *dev)
if (ret)
return ret;
+ ret = pwrseq_enable(adc->pwrseq);
+ if (ret) {
+ reset_control_assert(adc->rstc);
+ return ret;
+ }
+
if (!(chip_info->features & RZT2H_ADC_FEATURE_CALIBRATION))
return 0;
@@ -825,8 +1018,10 @@ static int rzt2h_adc_pm_runtime_resume(struct device *dev)
fsleep(1);
ret = rzt2h_adc_calibrate(adc);
- if (ret)
+ if (ret) {
+ pwrseq_disable(adc->pwrseq);
reset_control_assert(adc->rstc);
+ }
return ret;
}
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop
2026-09-29 12:42 ` [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop Prabhakar
@ 2026-09-30 9:23 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-09-30 9:23 UTC (permalink / raw)
To: Prabhakar
Cc: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio,
linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
On Tue, Sep 29, 2026 at 01:42:42PM +0100, Prabhakar wrote:
> When ADCSR.ADST is cleared to forcibly stop a conversion, the analog part
> of the A/D converter can take up to 2 ADCLK cycles to stop operating.
>
> Wait for the write to ADCSR to complete and allow the analog part to stop
> before reconfiguring or restarting the converter.
...
> + /*
> + * When a conversion is forcibly stopped, the analog part of the A/D
> + * converter takes up to 2 ADCLK cycles to stop operating.
> + */
> + ndelay(DIV_ROUND_UP_ULL((u64)RZT2H_ADC_STOP_CYCLES * NSEC_PER_SEC,
> + adc->adclk_rate));
I do not see the point in having _ULL (64-bit) division. Do you?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration
2026-09-29 12:42 ` [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration Prabhakar
@ 2026-09-30 9:26 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-09-30 9:26 UTC (permalink / raw)
To: Prabhakar
Cc: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio,
linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
On Tue, Sep 29, 2026 at 01:42:43PM +0100, Prabhakar wrote:
> 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.
...
> +struct rzt2h_adc_chip_info {
> + const struct iio_chan_spec *chan_template;
__counted_by_ptr() ?
> + unsigned int num_channels;
> + u8 features;
> +};
...
> + chip_info = device_get_match_data(dev);
> + if (!chip_info)
> + return -ENODEV;
-ENODATA
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale
2026-09-29 12:42 ` [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale Prabhakar
@ 2026-09-30 9:28 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-09-30 9:28 UTC (permalink / raw)
To: Prabhakar
Cc: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio,
linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
On Tue, Sep 29, 2026 at 01:42:47PM +0100, Prabhakar wrote:
> Prepare the driver for RZ/V2H(P) support, where the ADC supports both
> 12-bit and 8-bit conversion resolutions.
>
> Use the current IIO scan type to determine the ADC resolution when
> reporting the scale instead of assuming a fixed 12-bit resolution.
...
> +#define RZT2H_ADC_VREF_MV 1800
_mV (yes, as it's called officially for millivolts).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC
2026-09-29 12:42 ` [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC Prabhakar
@ 2026-09-30 9:35 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-09-30 9:35 UTC (permalink / raw)
To: Prabhakar
Cc: Cosmin Tanislav, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm, linux-iio,
linux-renesas-soc, devicetree, linux-kernel, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
On Tue, Sep 29, 2026 at 01:42:48PM +0100, Prabhakar wrote:
> Add support for the ADC found on the Renesas RZ/V2H(P) SoC, which shares
> the RZ/T2H ADC IP but differs in channel count, sampling, calibration and
> resolution support.
>
> The RZ/V2H(P) ADC provides 8 channels, has a fixed conversion time of
> 20 ADCLK cycles, does not support calibration, and supports selectable
> 12-bit and 8-bit conversion resolution.
>
> Expose the fixed sampling frequency as a read-only attribute and allow
> the conversion resolution to be changed through the scale attribute.
> Use extended scan types so the reported scan type follows the selected
> resolution, and prevent resolution changes while buffered capture is
> active.
...
> help
> Say yes here to build support for the ADC found in Renesas
> - RZ/T2H / RZ/N2H SoCs.
> + RZ/T2H / RZ/N2H (and similar SoCs).
This wording is good for the summary above, but here please list what the
similar SoCs are. Something like
in Renesas SoCs:
- RZ/N2H
- RZ/T2H
- ...specify "similar SoCs" here...
> To compile this driver as a module, choose M here: the
> module will be called rzt2h_adc.
...
> +static int rzt2h_adc_write_scale(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val, int val2)
> +{
> + struct rzt2h_adc *adc = iio_priv(indio_dev);
> + unsigned int i;
> + u64 scale;
> + u32 rem;
> +
> + if (!(adc->chip_info->features & RZT2H_ADC_FEATURE_RES_SELECT))
> + return -EINVAL;
> +
> + for (i = 0; i < chan->num_ext_scan_type; i++) {
> + scale = (u64)RZT2H_ADC_VREF_MV * NANO >>
> + chan->ext_scan_type[i].realbits;
> + if (div_u64_rem(scale, NANO, &rem) == val && rem == val2)
> + break;
> + }
> +
Blank line here is not needed.
> + if (i == chan->num_ext_scan_type)
> + return -EINVAL;
> +
> + /* The scan type changes with the resolution. */
> + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
> + if (IIO_DEV_ACQUIRE_FAILED(claim))
> + return -EBUSY;
> +
> + adc->resolution = i;
> +
> + return 0;
> +}
...
> + case IIO_CHAN_INFO_SCALE:
> + *vals = rzv2h_adc_scale_avail;
> + *type = IIO_VAL_FRACTIONAL_LOG2;
> + *length = ARRAY_SIZE(rzv2h_adc_scale_avail);
Check if array_size.h is included.
> + return IIO_AVAIL_LIST;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-09-30 9:35 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 12:42 [PATCH 0/8] Add ADC support for RZ/V2H(P) and RZ/V2N SoCs Prabhakar
2026-09-29 12:42 ` [PATCH 1/8] dt-bindings: iio: adc: renesas,r9a09g077-adc: Add RZ/V2H(P) and RZ/V2N support Prabhakar
2026-09-29 12:42 ` [PATCH 2/8] iio: adc: rzt2h: Wait for the analog part to stop after a forced stop Prabhakar
2026-09-30 9:23 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 3/8] iio: adc: rzt2h: Add chip-specific configuration Prabhakar
2026-09-30 9:26 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 4/8] iio: adc: rzt2h: Add optional reset support Prabhakar
2026-09-29 12:42 ` [PATCH 5/8] iio: adc: rzt2h: Prepare for SoCs without sample state registers Prabhakar
2026-09-29 12:42 ` [PATCH 6/8] iio: adc: rzt2h: Prepare for SoCs with different ADC info Prabhakar
2026-09-29 12:42 ` [PATCH 7/8] iio: adc: rzt2h: Use scan type for ADC scale Prabhakar
2026-09-30 9:28 ` Andy Shevchenko
2026-09-29 12:42 ` [PATCH 8/8] iio: adc: rzt2h: Add support for RZ/V2H(P) SoC Prabhakar
2026-09-30 9:35 ` Andy Shevchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®