iio: adc: stm32: add support for stm32mp23 and stm32mp25
Subsystems (3)
cover iio: adc: stm32: add support for stm32mp23 and stm32mp25
Add support for STM32MP23 and STM32MP25 Analog to Digital Converter. It's a variant of other supported STM32MP ADCs. Add the DT bindings, driver, SOC DTS and an example on stm32mp257f-ev1 board.
---
Cheick Traore (1):
arm64: dts: st: add ADC nodes on stm32mp231
Fabrice Gasnier (4):
dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
arm64: dts: st: add ADC nodes on stm32mp251
arm64: dts: st: add ADC support on stm32mp257f-ev1 board
Olivier Moysan (1):
iio: adc: stm32-adc: manage characterization voltage diversity
Patrice Chotard (2):
arm64: dts: st: add vrefint calibration on stm32mp23
arm64: dts: st: add vrefint calibration on stm32mp25
.../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++- arch/arm64/boot/dts/st/stm32mp231.dtsi | 117 ++++++ arch/arm64/boot/dts/st/stm32mp251.dtsi | 119 ++++++ arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 22 + drivers/iio/adc/stm32-adc-core.c | 91 ++++- drivers/iio/adc/stm32-adc-core.h | 23 ++ drivers/iio/adc/stm32-adc.c | 444 ++++++++++++++++++++- 7 files changed, 880 insertions(+), 42 deletions(-)
---
base-commit: 6d31021b7ce470983aeee0727f7417272c0a1cad
change-id: 20260911-adc-stm32mp25-v1-2ac7328559d9
Best regards,
Signature · 1 line
Fabrice Gasnier <[email protected]>
PATCH 1/8 dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.
New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +94 -12
@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items: + - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items: + - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-core reg: maxItems: 1
@@ -78,6 +85,9 @@ properties: Phandle to the vdd input voltage. It can be used to supply ADC analog input switches on stm32mp1. + power-domains: + maxItems: 1 + st,syscfg: description: Phandle to system configuration controller. It can be used to control the
@@ -215,6 +225,33 @@ allOf: maximum: 75000000 default: 75000000 + - if: + properties: + compatible: + contains: + enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + + then: + properties: + clocks: + maxItems: 1 + + clock-names: + const: adc + + interrupts: + items: + - description: interrupt line for ADC1 or ADC3 + - description: interrupt line for ADC2 + minItems: 1 + + st,max-clk-rate-hz: + minimum: 700000 + maximum: 70000000 + default: 70000000 + additionalProperties: false required:
@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items: + - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adc + - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adc reg: description: |
@@ -294,8 +338,8 @@ patternProperties: List of single-ended channels muxed for this ADC. It can have up to: - 16 channels, numbered from 0 to 15 (for in0..in15) on stm32f4 - 19 channels, numbered from 0 to 18 (for in0..in18) on stm32mp13. - - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7 and - stm32mp1. + - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7, + stm32mp1, stm32mp23 and stm32mp25. $ref: /schemas/types.yaml#/definitions/uint32-array deprecated: true
@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefint + st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + default: 0 + patternProperties: "^channel@([0-9]|1[0-9])$": type: object
@@ -486,6 +536,38 @@ patternProperties: maxItems: 19 items: minimum: 40 + + - if: + properties: + compatible: + contains: + enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + + then: + properties: + reg: + enum: + - 0x0 + - 0x100 + + interrupts: + minimum: 0 + maximum: 1 + + assigned-resolution-bits: + enum: [6, 8, 10, 12] + default: 12 + + channel@19: false + st,adc-channels: false + st,adc-diff-channels: false + st,min-sample-time-nsecs: false + + required: + - st,adc-trigger-sel + additionalProperties: false required:
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [Low] Documentation for the deprecated `st,adc-channels` property explicitly lists `stm32mp23` and…
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Low] Documentation for the deprecated st,adc-channels property explicitly lists stm32mp23 and stm32mp25 as supporting up to 20 channels, but the property is explicitly forbidden in the schema for these compatibles.
- [Low] The st,adc-trigger-sel property specifies default: 0 but is also strictly required for the stm32mp23 and stm32mp25 variants.
- [Low] The schema attempts to restrict channel 19 using channel@19: false, which fails to prevent the usage of channel 19 in reg or diff-channels within other channel nodes.
--
commit 928337c3337781d9cd13fb9cf442caeafdde7db6
Author: Fabrice Gasnier <[email protected]>
dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +0
-0
[ ... ]
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 344
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +2
-2@@ -294,8 +338,8 @@ patternProperties: List of single-ended channels muxed for this ADC. It can have up to: - 16 channels, numbered from 0 to 15 (for in0..in15) on stm32f4 - 19 channels, numbered from 0 to 18 (for in0..in18) on stm32mp13. - - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7 and - stm32mp1. + - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7, + stm32mp1, stm32mp23 and stm32mp25. $ref: /schemas/types.yaml#/definitions/uint32-array deprecated: true
[Severity: Low]
The description explicitly adds stm32mp23 and stm32mp25 to the list of SoCs supporting this deprecated property, but the if-then block below enforces st,adc-channels: false for these variants. Does the documentation need to be updated to clarify this property is not supported on these new SoCs?
[ ... ]
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 396
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefint + st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + default: 0 +
[Severity: Low]
Does declaring a default value here make sense since this property is strictly required by the schema block below? A required property must be explicitly present in the device tree for validation to pass, which renders this default declaration useless.
[ ... ]
Quoted 19 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +15
-0@@ -486,6 +536,38 @@ patternProperties: maxItems: 19 items: minimum: 40 + + - if: + properties: + compatible: + contains: + enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + + then: + properties: + reg: + enum: + - 0x0 + - 0x100
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 563
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +10
-0+ + interrupts: + minimum: 0 + maximum: 1 + + assigned-resolution-bits: + enum: [6, 8, 10, 12] + default: 12 + + channel@19: false
[Severity: Low]
The commit message mentions restricting the last channel (19) as it is wired directly to ADC Vref+. However, setting channel@19: false only prevents a node explicitly named channel@19. Could a user still bypass this restriction by using diff-channels = <X 19>; or reg = <19> inside another channel node name?
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0+ st,adc-channels: false + st,adc-diff-channels: false + st,min-sample-time-nsecs: false + + required: + - st,adc-trigger-sel
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
In reply to Fabrice GasnierQuoted 9 lines · Fabrice Gasnier
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel "
No need for space before "
Quoted 2 lines
allow to make the difference between
the ADCs and to apply the correct trigger configuration.
I think "st,adc-trigger-sel" needs an example in the example bindings below.
Quoted 1 line
STM32 ADC may be in a power domain: allow a single 'power-domains'.
[...]
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 395
Quoted 5 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +5
-0+ st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + default: 0
What does 0 and 1 mean ?
[...]
Jonathan Cameron
maintainerRe: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
In reply to Fabrice GasnierQuoted 19 lines · On Fri, 11 Sep 2026 17:51:23 +0200 Fabrice Gasnier…
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>
Hi Fabrice, all,
Quoted 19 lines
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +2
-5@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items:
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml maintainers: · line 37
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +10
-0+ - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items: + - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-core
What is this? Given these all vary in features
why would we fallback to a generic match for
these new compatibles?
Quoted 14 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +2
-5additionalProperties: false required:@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items:
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 290
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +10
-0+ - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adc + - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adc
Similar to above, what is this?
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 394
Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefint + st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1]
Magic value that is meaningless to see in a dts. If they are effectively not compatible, give them different compatibles and drop this property. I'm unconvinced this property is more useful than that given just how opaque the description is.
Re: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Quoted 55 lines · Jonathan Cameron
Quoted 19 lines · On Fri, 11 Sep 2026 17:51:23 +0200 Fabrice Gasnier…
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>Hi Fabrice, all,
Quoted 25 lines
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +8
-5@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items: + - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items:
Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml maintainers: · line 37
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-coreWhat is this? Given these all vary in features
why would we fallback to a generic match for
these new compatibles?
Hi Jonathan, all
Ack, I'll drop it in v2,
Quoted 21 lines
Quoted 21 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-5additionalProperties: false required:@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items: + - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adc
Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 290
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0+ - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adcSimilar to above, what is this?
same,
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +0
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefint
Quoted 9 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 394
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1]Magic value that is meaningless to see in a dts. If they are effectively not compatible, give them different compatibles and drop this property. I'm unconvinced this property is more useful than that given just how opaque the description is.
That's exactly what I was wondering about. As you suggest, I can remove this property, and introduce dedicated compatibles in V2, to clearly identify the differences.
Need to distinguish:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Triggers are different between them. The purpose of st,adc-trigger-sel was to identify that.
Also MP23 and MP25 are also different (trigger list). Combining this would lead to introduce four compatibles, I'm thinking of:
- st,stm32mp23-adc12
- st,stm32mp23-adc3
- st,stm32mp25-adc12
- st,stm32mp25-adc3
I plan to update it in v2.
Thanks,
Fabrice
Quoted 3 lines
Jonathan Cameron
maintainerRe: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Quoted 127 lines · On Tue, 15 Sep 2026 09:49:01 +0200 Fabrice Gasnier…
Quoted 55 lines · Jonathan Cameron
Quoted 19 lines · On Fri, 11 Sep 2026 17:51:23 +0200 Fabrice Gasnier…
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>Hi Fabrice, all,
Quoted 25 lines
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +8
-5@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items: + - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items:Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml maintainers: · line 37
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-coreWhat is this? Given these all vary in features
why would we fallback to a generic match for
these new compatibles?Hi Jonathan, all
Ack, I'll drop it in v2,
Quoted 21 lines
Quoted 21 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-5additionalProperties: false required:@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items: + - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adcQuoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 290
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0+ - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adcSimilar to above, what is this?
same,
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +0
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefintQuoted 9 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 394
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1]Magic value that is meaningless to see in a dts. If they are effectively not compatible, give them different compatibles and drop this property. I'm unconvinced this property is more useful than that given just how opaque the description is.
That's exactly what I was wondering about. As you suggest, I can remove this property, and introduce dedicated compatibles in V2, to clearly identify the differences.
Need to distinguish:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Triggers are different between them. The purpose of st,adc-trigger-sel was to identify that.
Quoted 7 lines
Also MP23 and MP25 are also different (trigger list). Combining this would lead to introduce four compatibles, I'm thinking of:
- st,stm32mp23-adc12
- st,stm32mp23-adc3
- st,stm32mp25-adc12
- st,stm32mp25-adc3
Naming wise, I wonder if it looks too much like adc twelve? Not sure how to avoid that cleanly as adc1-2 seems odd too.
Quoted 9 lines
I plan to update it in v2.
Thanks,
FabriceQuoted 3 lines
Re: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Quoted 137 lines · Jonathan Cameron
Quoted 127 lines · On Tue, 15 Sep 2026 09:49:01 +0200 Fabrice Gasnier…
Quoted 55 lines · Jonathan Cameron
Quoted 19 lines · On Fri, 11 Sep 2026 17:51:23 +0200 Fabrice Gasnier…
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>Hi Fabrice, all,
Quoted 25 lines
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +8
-5@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items: + - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items:Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml maintainers: · line 37
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-coreWhat is this? Given these all vary in features
why would we fallback to a generic match for
these new compatibles?Hi Jonathan, all
Ack, I'll drop it in v2,
Quoted 21 lines
Quoted 21 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-5additionalProperties: false required:@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items: + - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adcQuoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 290
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0+ - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adcSimilar to above, what is this?
same,
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +0
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefintQuoted 9 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 394
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1]Magic value that is meaningless to see in a dts. If they are effectively not compatible, give them different compatibles and drop this property. I'm unconvinced this property is more useful than that given just how opaque the description is.
That's exactly what I was wondering about. As you suggest, I can remove this property, and introduce dedicated compatibles in V2, to clearly identify the differences.
Need to distinguish:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Triggers are different between them. The purpose of st,adc-trigger-sel was to identify that.Quoted 7 lines
Also MP23 and MP25 are also different (trigger list). Combining this would lead to introduce four compatibles, I'm thinking of:
- st,stm32mp23-adc12
- st,stm32mp23-adc3
- st,stm32mp25-adc12
- st,stm32mp25-adc3
Quoted 2 lines
Naming wise, I wonder if it looks too much like adc twelve? Not sure how to avoid that cleanly as adc1-2 seems odd too.
Hi Jonathan,
Indeed, so could introduce one compatible per Soc/ADC ?
+ - st,stm32mp23-adc1 + - st,stm32mp23-adc2 + - st,stm32mp23-adc3 + - st,stm32mp25-adc1 + - st,stm32mp25-adc2 + - st,stm32mp25-adc3
There are some other differences between adc1 and adc2, e.g. in the reference manual:
- ADC1 is connected to 18 external channels + 2 internal channels
- ADC2 is connected to 14 external channels + 6 internal channels
- ADC3 is connected to 14 external channels + 6 internal channels
This is resolved currently by channels child nodes with labels for internal channels. So maybe better to name all of them (future proof) ?
Please advise,
Best Regards,
Fabrice
Quoted 11 lines
Quoted 10 lines
I plan to update it in v2.
Thanks,
FabriceQuoted 3 lines
Jonathan Cameron
maintainerRe: [PATCH 1/8] dt-bindings: iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Quoted 152 lines · On Thu, 17 Sep 2026 09:27:10 +0200 Fabrice Gasnier…
Quoted 137 lines · Jonathan Cameron
Quoted 127 lines · On Tue, 15 Sep 2026 09:49:01 +0200 Fabrice Gasnier…
Quoted 55 lines · Jonathan Cameron
Quoted 19 lines · On Fri, 11 Sep 2026 17:51:23 +0200 Fabrice Gasnier…
Add stm32mp23 and stm32mp25 compatibles. Three ADCs can be found on these SoCs, split into two blocks:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential.New property "st,adc-trigger-sel " allow to make the difference between the ADCs and to apply the correct trigger configuration.
STM32 ADC may be in a power domain: allow a single 'power-domains'.
Restrict the last channel (19), as it is wired directly to ADC Vref+. It's meaningless to have direct measurement. Internal Vref with calibration data from bsec (nvmem) must be used instead e.g. vrefint. Restrict deprecated properties (st,adc-channels, st,adc-diff-channels, st,min-sample-time-nsecs).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>Hi Fabrice, all,
Quoted 25 lines
--- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 106 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 12 deletions(-)Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +8
-5@@ -23,11 +23,18 @@ maintainers: properties: compatible: - enum: - - st,stm32f4-adc-core - - st,stm32h7-adc-core - - st,stm32mp1-adc-core - - st,stm32mp13-adc-core + oneOf: + - items: + - enum: + - st,stm32f4-adc-core + - st,stm32h7-adc-core + - st,stm32mp1-adc-core + - st,stm32mp13-adc-core + - items:Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml maintainers: · line 37
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ - enum: + - st,stm32mp23-adc-core + - st,stm32mp25-adc-core + - const: st,stm32-adc-coreWhat is this? Given these all vary in features
why would we fallback to a generic match for
these new compatibles?Hi Jonathan, all
Ack, I'll drop it in v2,
Quoted 21 lines
Quoted 21 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-5additionalProperties: false required:@@ -239,11 +276,18 @@ patternProperties: properties: compatible: - enum: - - st,stm32f4-adc - - st,stm32h7-adc - - st,stm32mp1-adc - - st,stm32mp13-adc + oneOf: + - items: + - enum: + - st,stm32f4-adc + - st,stm32h7-adc + - st,stm32mp1-adcQuoted 8 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 290
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +6
-0+ - st,stm32mp13-adc + - items: + - enum: + - st,stm32mp23-adc + - st,stm32mp25-adc + - const: st,stm32-adcSimilar to above, what is this?
same,
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +0
-0@@ -344,6 +388,12 @@ patternProperties: items: - const: vrefintQuoted 9 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml patternProperties: · line 394
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +4
-0+ st,adc-trigger-sel: + description: Selects the HW trigger configuration available on this ADC + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1]Magic value that is meaningless to see in a dts. If they are effectively not compatible, give them different compatibles and drop this property. I'm unconvinced this property is more useful than that given just how opaque the description is.
That's exactly what I was wondering about. As you suggest, I can remove this property, and introduce dedicated compatibles in V2, to clearly identify the differences.
Need to distinguish:
- ADC12 are tightly coupled (common registers).
- ADC3 is managed independently.
Triggers are different between them. The purpose of st,adc-trigger-sel was to identify that.Quoted 7 lines
Also MP23 and MP25 are also different (trigger list). Combining this would lead to introduce four compatibles, I'm thinking of:
- st,stm32mp23-adc12
- st,stm32mp23-adc3
- st,stm32mp25-adc12
- st,stm32mp25-adc3Quoted 2 lines
Naming wise, I wonder if it looks too much like adc twelve? Not sure how to avoid that cleanly as adc1-2 seems odd too.
Hi Jonathan,
Indeed, so could introduce one compatible per Soc/ADC ?
(quoted diff) +6
-0+ - st,stm32mp23-adc1 + - st,stm32mp23-adc2 + - st,stm32mp23-adc3 + - st,stm32mp25-adc1 + - st,stm32mp25-adc2 + - st,stm32mp25-adc3
Quoted 8 lines
There are some other differences between adc1 and adc2, e.g. in the reference manual:
- ADC1 is connected to 18 external channels + 2 internal channels
- ADC2 is connected to 14 external channels + 6 internal channels
- ADC3 is connected to 14 external channels + 6 internal channelsThis is resolved currently by channels child nodes with labels for internal channels. So maybe better to name all of them (future proof) ?
Yes. Ideally the binding would be constraining the channel nodes and we'd need the compatible to do that.
Seems like we have a winner - separate compatibles :)
Jonathan
Quoted 18 lines
Please advise,
Best Regards,
FabriceQuoted 11 lines
Quoted 10 lines
I plan to update it in v2.
Thanks,
FabriceQuoted 3 lines
PATCH 2/8 iio: adc: stm32-adc: manage characterization voltage diversity
In reply to Fabrice GasnierFrom: Olivier Moysan <[email protected]>
The characterization voltage used to calibrate vrefint depends on SoC family. Add vref_charac field in stm32_adc_cfg structure to store the characterization voltage for each SoC, and use it in vref computation formula.
--- drivers/iio/adc/stm32-adc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/iio/adc/stm32-adc.c +7 -2
@@ -43,7 +43,6 @@#define STM32_ADC_TIMEOUT_US 100000#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))#define STM32_ADC_HW_STOP_DELAY_MS 100 -#define STM32_ADC_VREFINT_VOLTAGE 3300#define STM32_DMA_BUFFER_SIZE PAGE_SIZE
@@ -211,6 +210,7 @@ struct stm32_adc;* @set_ovs: routine to set oversampling configuration * @smp_cycles: programmable sampling time (ADC clock cycles) * @ts_int_ch: pointer to array of internal channels minimum sampling time in ns +* @vref_charac: Vref characterization voltage (mv) used to measure vrefint calibration value */ struct stm32_adc_cfg {const struct stm32_adc_regspec *regs;
@@ -230,6 +230,7 @@ struct stm32_adc_cfg {void (*set_ovs)(struct iio_dev *indio_dev,u32 ovs_idx);const unsigned int *smp_cycles;const unsigned int *ts_int_ch; +const int vref_charac; };/**
@@ -1610,7 +1611,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, ret = -EINVAL ;if (mask ==IIO_CHAN_INFO_PROCESSED ) - *val =STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val; + *val = adc->cfg->vref_charac * adc->vrefint.vrefint_cal / *val;iio_device_release_direct (indio_dev);return ret;
@@ -2702,6 +2703,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { .stop_conv = stm32f4_adc_stop_conv, .smp_cycles = stm32f4_adc_smp_cycles, .irq_clear = stm32f4_adc_irq_clear, + .vref_charac = 3300, };static const unsigned int stm32_adc_min_ts_h7[] = {0 ,0 ,0 ,4300 ,9000 };
@@ -2723,6 +2725,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_h7, .set_ovs = stm32h7_adc_set_ovs, + .vref_charac = 3300, };static const unsigned int stm32_adc_min_ts_mp1[] = {100 ,100 ,100 ,4300 ,9800 };
@@ -2745,6 +2748,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_mp1, .set_ovs = stm32h7_adc_set_ovs, + .vref_charac = 3300, };static const unsigned int stm32_adc_min_ts_mp13[] = {100 ,0 ,0 ,4300 ,9800 };
@@ -2763,6 +2767,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = { .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_mp13, .set_ovs = stm32mp13_adc_set_ovs, + .vref_charac = 3300, };static const struct of_device_id stm32_adc_of_match[] = {
Signature · 1 line
2.43.0
Re: [PATCH 2/8] iio: adc: stm32-adc: manage characterization voltage diversity
Quoted 4 lines · Fabrice Gasnier
The characterization voltage used to calibrate vrefint depends on SoC family. Add
vref_characfield instm32_adc_cfgstructure to store the characterization voltage for each SoC, and use it in vref computation formula.
Vref
...
Quoted 1 line
+ * @vref_charac: Vref characterization voltage (mv) used to measure vrefint calibration value
vref_char_mV or alike
(use unit suffix and you may drop that mv in the parentheses).
...
drivers/iio/adc/stm32-adc.c struct stm32_adc_cfg { · line 233
Quoted 1 line
drivers/iio/adc/stm32-adc.c +1
-0+const int vref_charac;
What does const buy you here?
Signature · 2 lines
With Best Regards, Andy Shevchenko
[email protected]
AI reviewRe: [PATCH 2/8] iio: adc: stm32-adc: manage characterization voltage diversity
In reply to Fabrice GasnierThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missing error check after ADC conversion allows division by zero or division by uninitialized memory if the conversion fails or returns zero. --
commit 0d19a7183285228478d5cfa82a3785b87f3e1bd1
Author: Olivier Moysan <[email protected]>
iio: adc: stm32-adc: manage characterization voltage diversity
This commit introduces a vref_charac field in stm32_adc_cfg to store SoC-specific characterization voltage. It updates the stm32_adc_read_raw function to use this field in the vref computation formula.
Quoted 3 lines
drivers/iio/adc/stm32-adc.c +0
-0
[ ... ]
drivers/iio/adc/stm32-adc.c static int stm32_adc_read_raw(struct iio_dev *indio_dev, · line 1614
Quoted 6 lines
drivers/iio/adc/stm32-adc.c +1
-1@@ -1610,7 +1611,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, ret = -EINVAL ;if (mask ==IIO_CHAN_INFO_PROCESSED ) - *val =STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val; + *val = adc->cfg->vref_charac * adc->vrefint.vrefint_cal / *val;
[Severity: Critical]
This isn't a bug introduced by this patch, but does this division need to check if the conversion actually succeeded?
Looking at the preceding code in stm32_adc_read_raw():
if (chan->type == IIO_VOLTAGE)
ret = stm32_adc_single_conv(indio_dev, chan, val);
else
ret = -EINVAL;If a sysfs read (such as in_voltageX_input) is interrupted by a signal, stm32_adc_single_conv() can abort via wait_for_completion_interruptible_timeout() and return an error like -ERESTARTSYS. When this happens, *val remains uninitialized.
Since there is no error check on ret before the division, this code will proceed to divide by the uninitialized *val. If the kernel is compiled with CONFIG_INIT_STACK_ALL_ZERO=y, the uninitialized stack variable will be 0, which could lead to a division by zero kernel panic.
Should we verify that ret indicates success and that *val is non-zero before attempting the scaling calculation?
Quoted 3 lines
drivers/iio/adc/stm32-adc.c +0
-0iio_device_release_direct (indio_dev);return ret;
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH 3/8 iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
In reply to Fabrice GasnierAdd support for STM32MP23 STM32MP25 SoCs. They have 3 ADCs, split into two blocks:
- ADC12 (ADC1 & ADC2) are tightly coupled.
- ADC3 is managed independently.
Trigger list slightly changes between STM32MP23 and STM32MP25.
Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential. ADC resolution ranges from 6 to 12 bits.
It introduces diversity regarding IRQs, clocks, software calibration procedure, internal voltage channels, sampling time (prescaler) and trigger list. Most of the architecture, and the driver engine remains similar. So, handle the differences w.r.t. other STM32 ADCs family with a dedicated compatible and compatible data.
Trigger list depends on ADC instance, retrieved with "st,adc-trigger-sel" property.
Add support for vddcpu and vddgpu internal channels on stm32mp25. These channels are enabled by using ADC option register.
Add VDDGPU to the list of supported channels in this driver and made available on stm32mp25. So update sampling information for all variants (with zero'ed data when it's not available).
--- drivers/iio/adc/stm32-adc-core.c | 91 ++++++-- drivers/iio/adc/stm32-adc-core.h | 23 +++ drivers/iio/adc/stm32-adc.c | 435 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 521 insertions(+), 28 deletions(-)
drivers/iio/adc/stm32-adc-core.c +75 -16
@@ -50,6 +50,8 @@* @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n * @ier: interrupt enable register offset for each adc * @eocie_msk: end of conversion interrupt enable mask in @ier +* @presc_msk: prescaler mask in ccr +* @presc_shift: prescaler bit shift in ccr */ struct stm32_adc_common_regs {u32 csr;
@@ -58,6 +60,8 @@ struct stm32_adc_common_regs {u32 ovr_msk[STM32_ADC_MAX_ADCS ];u32 ier;u32 eocie_msk; +u32 presc_msk; +u32 presc_shift; };struct stm32_adc_priv ;
@@ -66,6 +70,8 @@ struct stm32_adc_priv;* struct stm32_adc_priv_cfg - stm32 core compatible configuration data * @regs: common registers for all instances * @clk_sel: clock selection routine +* @presc: clock prescaler array +* @num_presc: number of clock prescalers in presc array * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) * @ipid: adc identification number * @has_syscfg: SYSCFG capability flags
@@ -75,6 +81,8 @@ struct stm32_adc_priv;struct stm32_adc_priv_cfg {const struct stm32_adc_common_regs *regs;int (*clk_sel)(struct platform_device *,struct stm32_adc_priv *); +int *presc; +int num_presc;u32 max_clk_rate_hz;u32 ipid;unsigned int has_syscfg;
@@ -86,6 +94,7 @@ struct stm32_adc_priv_cfg {* struct stm32_adc_priv - stm32 ADC core private data * @irq: irq(s) for ADC block * @nb_adc_max: actual maximum number of instance per ADC block +* @nb_irqs: number of IRQs in the ADC block * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used
@@ -104,6 +113,7 @@ struct stm32_adc_priv_cfg {struct stm32_adc_priv {int irq[STM32_ADC_MAX_ADCS ];unsigned int nb_adc_max; +unsigned int nb_irqs;struct irq_domain *domain;struct clk *aclk;struct clk *bclk;
@@ -128,20 +138,23 @@ static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)/* STM32F4 ADC internal common clock prescaler division ratios */ static int stm32f4_pclk_div[] = {2 ,4 ,6 ,8 }; +/* STM32MP25 ADC internal common clock prescaler division ratios */ +static int stm32mp25_presc_div[] = {1 ,2 ,4 ,6 ,8 ,10 ,12 ,16 ,32 ,64 ,128 ,256 }; +/** -* stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler +* stm32_adc_clk_sel() - Select stm32f4 ADC common clock prescaler * @pdev: platform device * @priv: stm32 ADC core private data * Select clock prescaler used for analog conversions, before using ADC. */ -static int stm32f4_adc_clk_sel (struct platform_device *pdev, -struct stm32_adc_priv *priv) +static int stm32_adc_clk_sel (struct platform_device *pdev, +struct stm32_adc_priv *priv) {unsigned long rate;u32 val;int i; -/* stm32f4 has one clk input for analog (mandatory), enforce it here */ +/* stm32f4/mp25 has one clk input for analog (mandatory), enforce it here */ if (!priv->aclk) {dev_err (&pdev->dev,"No 'adc' clock found\n" );return -ENOENT ;
@@ -153,20 +166,20 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,return -EINVAL ; } -for (i =0 ; i <ARRAY_SIZE (stm32f4_pclk_div); i++) { -if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate) +for (i =0 ; i < priv->cfg->num_presc; i++) { +if ((rate / priv->cfg->presc[i]) <= priv->max_clk_rate)break ; } -if (i >=ARRAY_SIZE (stm32f4_pclk_div)) { +if (i >= priv->cfg->num_presc) {dev_err (&pdev->dev,"adc clk selection failed\n" );return -EINVAL ; } - priv->common.rate = rate / stm32f4_pclk_div[i]; - val =readl_relaxed (priv->common.base +STM32F4_ADC_CCR ); - val &= ~STM32F4_ADC_ADCPRE_MASK ; - val |= i <<STM32F4_ADC_ADCPRE_SHIFT ; -writel_relaxed (val, priv->common.base +STM32F4_ADC_CCR ); + priv->common.rate = rate / priv->cfg->presc[i]; + val =readl_relaxed (priv->common.base + priv->cfg->regs->ccr); + val &= ~priv->cfg->regs->presc_msk; + val |= i << priv->cfg->regs->presc_shift; +writel_relaxed (val, priv->common.base + priv->cfg->regs->ccr);dev_dbg (&pdev->dev,"Using analog clock source at %ld kHz\n" , priv->common.rate /1000 );
@@ -314,6 +327,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3 }, .ier = STM32F4_ADC_CR1, .eocie_msk = STM32F4_EOCIE, + .presc_msk = STM32F4_ADC_ADCPRE_MASK, + .presc_shift = STM32F4_ADC_ADCPRE_SHIFT, };/* STM32H7 common registers definitions */
@@ -336,6 +351,18 @@ static const struct stm32_adc_common_regs stm32mp13_adc_common_regs = { .eocie_msk = STM32H7_EOCIE, }; +/* STM32MP25 common registers definitions */ +static const struct stm32_adc_common_regs stm32mp25_adc_common_regs = { + .csr =STM32H7_ADC_CSR , + .ccr =STM32H7_ADC_CCR , + .eoc_msk = {STM32H7_EOC_MST ,STM32H7_EOC_SLV }, + .ovr_msk = {STM32H7_OVR_MST ,STM32H7_OVR_SLV }, + .ier =STM32H7_ADC_IER , + .eocie_msk =STM32H7_EOCIE , + .presc_msk =STM32H7_PRESC_MASK , + .presc_shift =STM32H7_PRESC_SHIFT , +}; +static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS ] = {0 ,STM32_ADC_OFFSET ,STM32_ADC_OFFSET *2 , };
@@ -413,8 +440,10 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,* Interrupt(s) must be provided, depending on the compatible: * - stm32f4/h7 shares a common interrupt line. * - stm32mp1, has one line per ADC +* - stm32mp25, has a dual ADC12 and standalone ADC3. Each ADC has an IRQ +* (two for ADC12, one for ADC3) */ -for (i =0 ; i < priv->cfg->num_irqs; i++) { +for (i =0 ; i < priv->nb_irqs; i++) { priv->irq[i] =platform_get_irq (pdev, i);if (priv->irq[i] <0 )return priv->irq[i];
@@ -429,7 +458,7 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,return -ENOMEM ; } -for (i =0 ; i < priv->cfg->num_irqs; i++) +for (i =0 ; i < priv->nb_irqs; i++)irq_set_chained_handler_and_data (priv->irq[i], stm32_adc_irq_handler, priv);
@@ -446,7 +475,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,irq_dispose_mapping (irq_find_mapping (priv->domain, hwirq));irq_domain_remove (priv->domain); -for (i =0 ; i < priv->cfg->num_irqs; i++) +for (i =0 ; i < priv->nb_irqs; i++)irq_set_chained_handler (priv->irq[i],NULL ); }
@@ -693,6 +722,17 @@ static int stm32_adc_probe_identification(struct platform_device *pdev,return -EINVAL ; } +if (priv->cfg->ipid ==STM32MP25_IPIDR_NUMBER ) { +/* +* ADC diversity on STM32MP25 is handled here. There may be: +* - 2 IRQs for ADC12 block +* - 1 IRQ for ADC3 block. +* There cannot be more IRQs than the actual number of ADCs. +*/ +if (priv->nb_irqs > priv->nb_adc_max) + priv->nb_irqs = priv->nb_adc_max; + } + val =readl_relaxed (priv->common.base +STM32MP1_ADC_VERR ); dev_dbg(&pdev->dev, "ADC version: %lu.%lu\n", FIELD_GET(STM32MP1_MAJREV_MASK, val),
@@ -720,6 +760,7 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->cfg =device_get_match_data (dev); priv->nb_adc_max = priv->cfg->num_adcs; + priv->nb_irqs = priv->cfg->num_irqs;spin_lock_init (&priv->common.lock); priv->common.base =devm_platform_get_and_ioremap_resource (pdev,0 , &res);
@@ -850,7 +891,9 @@ static DEFINE_RUNTIME_DEV_PM_OPS(stm32_adc_core_pm_ops,static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { .regs = &stm32f4_adc_common_regs, - .clk_sel = stm32f4_adc_clk_sel, + .clk_sel = stm32_adc_clk_sel, + .presc = stm32f4_pclk_div, + .num_presc =ARRAY_SIZE (stm32f4_pclk_div), .max_clk_rate_hz =36000000 , .num_irqs =1 , .num_adcs =3 ,
@@ -882,6 +925,16 @@ static const struct stm32_adc_priv_cfg stm32mp13_adc_priv_cfg = { .num_irqs = 1, }; +static const struct stm32_adc_priv_cfg stm32mp25_adc_priv_cfg = { + .regs = &stm32mp25_adc_common_regs, + .clk_sel = stm32_adc_clk_sel, + .presc = stm32mp25_presc_div, + .num_presc =ARRAY_SIZE (stm32mp25_presc_div), + .max_clk_rate_hz =70000000 , + .ipid =STM32MP25_IPIDR_NUMBER , + .num_irqs =2 ,/* 2 IRQs for ADC12, 1 irq for ADC3 */ +}; +static const struct of_device_id stm32_adc_of_match[] = { { .compatible ="st,stm32f4-adc-core" ,
@@ -895,6 +948,12 @@ static const struct of_device_id stm32_adc_of_match[] = { }, { .compatible = "st,stm32mp13-adc-core", .data = (void *)&stm32mp13_adc_priv_cfg + }, { + .compatible = "st,stm32mp23-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg + }, { + .compatible = "st,stm32mp25-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg }, { }, };
drivers/iio/adc/stm32-adc-core.h +23 -0
@@ -121,6 +121,9 @@#define STM32MP13_ADC_CALFACT 0xB4#define STM32MP13_ADC2_OR 0xC8 +/* STM32MP25 - ADC2 and ADC3 option register */ +#define STM32MP25_ADC23_OR 0xD0 +/* STM32H7 - common registers for all ADC instances */ #define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
@@ -257,8 +260,28 @@ enum stm32h7_adc_dmngt {#define STM32MP13_OP1 BIT(1)#define STM32MP13_OP0 BIT(0) +/* STM32MP25 - Registers for each ADC instance */ +#define STM32MP25_ADC_CALFACT 0xC4 + +/* STM32MP25_ADC_CALFACT - bit fields */ +#define STM32MP25_CALFACT_CALADDOS BIT(31) +#define STM32MP25_CALFACT_D_MASK GENMASK(24, 16) +#define STM32MP25_CALFACT_S_MASK GENMASK(8, 0) + +/* STM32MP25_ADC_CFGR specific bit fields */ +#define STM32MP25_RES_SHIFT 2 +#define STM32MP25_RES_MASK GENMASK(3, 2) + +/* STM32MP25_ADC23_OR - specific bit fields */ +#define STM32MP25_VDDGPUEN BIT(4) +#define STM32MP25_VDDCPUEN BIT(3) +#define STM32MP25_VDDCOREEN BIT(2) +#define STM32MP25_SELBG BIT(1) +#define STM32MP25_SELREF BIT(0) +#define STM32MP15_IPIDR_NUMBER 0x00110005#define STM32MP13_IPIDR_NUMBER 0x00110006 +#define STM32MP25_IPIDR_NUMBER 0x00110008/** * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
drivers/iio/adc/stm32-adc.c +423 -12
627 lines not on this page · raw message
Signature · 1 line
2.43.0
Re: [PATCH 3/8] iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
Quoted 24 lines · Fabrice Gasnier
Add support for STM32MP23 STM32MP25 SoCs. They have 3 ADCs, split into two blocks:
- ADC12 (ADC1 & ADC2) are tightly coupled.
- ADC3 is managed independently.
Trigger list slightly changes between STM32MP23 and STM32MP25.Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential. ADC resolution ranges from 6 to 12 bits.
It introduces diversity regarding IRQs, clocks, software calibration procedure, internal voltage channels, sampling time (prescaler) and trigger list. Most of the architecture, and the driver engine remains similar. So, handle the differences w.r.t. other STM32 ADCs family with a dedicated compatible and compatible data.
Trigger list depends on ADC instance, retrieved with "st,adc-trigger-sel" property.
Add support for vddcpu and vddgpu internal channels on stm32mp25. These channels are enabled by using ADC option register.
Add VDDGPU to the list of supported channels in this driver and made available on stm32mp25. So update sampling information for all variants (with zero'ed data when it's not available).
...
drivers/iio/adc/stm32-adc-core.c struct stm32_adc_priv; · line 85
Quoted 5 lines
+ * @presc: clock prescaler array
+ * @num_presc: number of clock prescalers in presc arraydrivers/iio/adc/stm32-adc-core.c +2
-0+int *presc; +int num_presc;
Why are they signed? I do not see any justification in the kernel doc.
...
Quoted 11 lines
static const struct
stm32_adc_priv_cfgstm32f4_adc_priv_cfg= {(quoted diff) +3
-1.regs = &stm32f4_adc_common_regs, - .clk_sel = stm32f4_adc_clk_sel, + .clk_sel = stm32_adc_clk_sel, + .presc = stm32f4_pclk_div, + .num_presc = ARRAY_SIZE(stm32f4_pclk_div), .max_clk_rate_hz = 36000000, .num_irqs = 1, .num_adcs = 3, };
Review
Quoted 10 lines
(quoted diff) +9
-0+static const struct stm32_adc_priv_cfg stm32mp25_adc_priv_cfg = { + .regs = &stm32mp25_adc_common_regs, + .clk_sel = stm32_adc_clk_sel, + .presc = stm32mp25_presc_div, + .num_presc = ARRAY_SIZE(stm32mp25_presc_div), + .max_clk_rate_hz = 70000000, + .ipid = STM32MP25_IPIDR_NUMBER, + .num_irqs = 2, /* 2 IRQs for ADC12, 1 irq for ADC3 */ +};
Split this patch to two. One prepares the infrastructure for prescaller, and the other adds a new HW support.
Quoted 16 lines
static const struct
of_device_idstm32_adc_of_match[] = {drivers/iio/adc/stm32-adc-core.c +6
-0{ .compatible = "st,stm32f4-adc-core",@@ -895,6 +948,12 @@ static const struct of_device_id stm32_adc_of_match[] = { }, { .compatible = "st,stm32mp13-adc-core", .data = (void *)&stm32mp13_adc_priv_cfg + }, { + .compatible = "st,stm32mp23-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg + }, { + .compatible = "st,stm32mp25-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg }, { }, };
...
drivers/iio/adc/stm32-adc.c struct stm32_adc; · line 234
Quoted 6 lines
struct
stm32_adc_cfg{drivers/iio/adc/stm32-adc.c +1
-1const struct stm32_adc_regspec *regs;const struct stm32_adc_info *adc_info; -const struct stm32_adc_trig_info *trigs; +const struct stm32_adc_trig_info *trigs[2 ];
Indentation looks suspicious. I would use just a single space.
Quoted 10 lines
drivers/iio/adc/stm32-adc.c +1
-0bool clk_required;bool has_vregready;bool has_boostmode;bool has_linearcal;bool has_presel;bool has_oversampling; +bool has_vregen;int (*prepare)(struct iio_dev *);void (*start_conv)(struct iio_dev *,bool dma);void (*stop_conv)(struct iio_dev *);
...
drivers/iio/adc/stm32-adc.c struct stm32_adc { · line 310
Quoted 6 lines
struct
stm32_adc{drivers/iio/adc/stm32-adc.c +1
-0int int_ch[STM32_ADC_INT_CH_NB ];int nsmps;int ovs_idx; +const struct stm32_adc_trig_info *trigs;
Ditto. And this shows exactly why the tab formatting is not good. Just a single space makes it consistent independently on the future development.
Quoted 1 line
};
...
Quoted 16 lines
drivers/iio/adc/stm32-adc.c +16
-0+/* STM32MP23 external trigger sources for ADC12 */ +static struct stm32_adc_trig_info stm32mp23_adc12_trigs[] = { + {TIM1_TRGO ,STM32_EXT0 }, + {TIM1_TRGO2 ,STM32_EXT1 }, + {TIM8_TRGO ,STM32_EXT2 }, + {TIM8_TRGO2 ,STM32_EXT3 }, + {TIM2_TRGO ,STM32_EXT6 }, + {TIM3_TRGO ,STM32_EXT7 }, + {TIM4_TRGO ,STM32_EXT8 }, + {TIM5_TRGO ,STM32_EXT9 }, + {TIM6_TRGO ,STM32_EXT10 }, + {TIM15_TRGO ,STM32_EXT11 }, + {TIM1_CH1 ,STM32_EXT12 }, + {TIM1_CH2 ,STM32_EXT13 }, + {TIM1_CH3 ,STM32_EXT14 }, + {TIM2_CH2 ,STM32_EXT18 },
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_regspec stm32h7_adc_regspec = { · line 606
Quoted 10 lines
drivers/iio/adc/stm32-adc.c +10
-0+ { TIM3_CH4, STM32_EXT19 }, + { TIM4_CH4, STM32_EXT20 }, + { TIM5_CH1, STM32_EXT21 }, + { TIM12_CH1, STM32_EXT22 }, + { LPTIM1_CH1, STM32_EXT24 }, + { LPTIM2_CH1, STM32_EXT25 }, + { LPTIM3_CH1, STM32_EXT26 }, + { LPTIM4_CH1, STM32_EXT27 }, + { LPTIM5_OUT, STM32_EXT28 }, + {},
The style of the terminator entry is no comma and likely a space inside, but the latter is optional for custom arrays (the requirement is strong for the ID tables in IIO).
Ditto for other similar cases. Looking at which I would recommend split the second patch mentioned above on per-compatible basis, so make it 1 preparatory, 1 with a new HW with some possible additional modifications, and 1 per each additional compatible line.
Quoted 1 line
+};
...
drivers/iio/adc/stm32-adc.c static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · line 1518
Quoted 13 lines
drivers/iio/adc/stm32-adc.c +13
-0+/* +* STM32MP25 offset calibration software procedure. Basically the calibration routine is +* expected to average (for example) 8 samples in calibration mode, for single-ended and +* differential channels, to calibrate the zero offset. In case offset is "negative", an +* additional offset can be added, to determine calibration factor. It must be kept later +* for all conversions. +*/ +static int stm32mp25_adc_calib_get_average_data (struct iio_dev *indio_dev,u32 *average) +{ +struct stm32_adc *adc =iio_priv (indio_dev); +const struct stm32_adc_regspec *regs = adc->cfg->regs; +u32 val, avg =0 ; +int i, ret;
Why is 'i' signed?
drivers/iio/adc/stm32-adc.c static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · line 1521
Quoted 3 lines
drivers/iio/adc/stm32-adc.c +3
-0+ +/* Repeat several conversions in calibration mode, average the results */ +for (i =0 ; i <STM32MP25_CALIB_LOOP ; i++) {
Also I don't see the problem with
for (unsigned int i = 0; i < STM32MP25_CALIB_LOOP; i++) {Quoted 19 lines
drivers/iio/adc/stm32-adc.c +19
-0+stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADSTART ); + ret =stm32_adc_readl_poll_timeout (STM32H7_ADC_CR , val, + !(val & (STM32H7_ADSTART )), +100 ,STM32_ADC_TIMEOUT_US ); +if (ret) { +dev_err (&indio_dev->dev,"calibration average error %d\n" , ret); +return ret; + } + + val =stm32_adc_readl (adc, regs->dr); +dev_vdbg (&indio_dev->dev,"dr[%d]=0x%08x\n" , i, val); + avg += val; + } + + *average =DIV_ROUND_CLOSEST (avg,STM32MP25_CALIB_LOOP ); +dev_vdbg (&indio_dev->dev,"average=0x%08x\n" , *average); + +return 0 ; +}
...
Quoted 20 lines
drivers/iio/adc/stm32-adc.c +20
-0+static int stm32mp25_adc_calib (struct iio_dev *indio_dev) +{ +struct stm32_adc *adc =iio_priv (indio_dev); +u32 calfact =0 , average; +int ret; + +stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADCAL ); +/* Clears CALADDOS (and old calibration data if any) */ +stm32_adc_writel (adc,STM32MP25_ADC_CALFACT ,0 ); +/* Select single ended input calibration */ +stm32_adc_clr_bits (adc,STM32H7_ADC_CR ,STM32H7_ADCALDIF ); +/* Use default resolution (e.g. 12 bits) */ +stm32_adc_clr_bits (adc,STM32H7_ADC_CFGR ,STM32MP25_RES_MASK ); + +retry: + ret =stm32mp25_adc_calib_get_average_data (indio_dev, &average); +if (ret) + goto out; + +/* If the averaged data is zero, retry with additional offset (set CALADDOS) */
drivers/iio/adc/stm32-adc.c static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · line 1571
Quoted 10 lines
drivers/iio/adc/stm32-adc.c +10
-0+if (!average) { +if (!calfact) { +/* Averaged data is zero, retry with additional offset */ + calfact =STM32MP25_CALFACT_CALADDOS ; +stm32_adc_writel (adc,STM32MP25_ADC_CALFACT , calfact); + goto retry; + } +/* Averaged data is still zero with additional offset, just warn about it */ +dev_warn (&indio_dev->dev,"Single-ended calibration average: 0\n" ); + }
OMG, try to refactor this to avoid this twisted goto chain.
Quoted 41 lines
drivers/iio/adc/stm32-adc.c +41
-0+ calfact |=FIELD_PREP (STM32MP25_CALFACT_S_MASK , average); + +/* Select differential input calibration (keep previous CALADDOS value) */ +stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADCALDIF ); + ret =stm32mp25_adc_calib_get_average_data (indio_dev, &average); +if (ret) + goto out; + +/* +* If the averaged data is below 0x800 (half value in 12-bits mode), +* retry with additional offset +*/ +if (average <BIT (adc->cfg->adc_info->resolutions[0 ] -1 )) { +if (!(calfact &STM32MP25_CALFACT_CALADDOS )) { +/* Retry the whole calibration with additional offset */ +stm32_adc_clr_bits (adc,STM32H7_ADC_CR ,STM32H7_ADCALDIF ); + calfact =STM32MP25_CALFACT_CALADDOS ; +stm32_adc_writel (adc,STM32MP25_ADC_CALFACT , calfact); + goto retry; + } +/* +* Averaged data is still below center value. It needs to be clamped to zero, +* so don't use the result here, warn about it. +*/ +dev_warn (&indio_dev->dev,"Differential calibration clamped(0): 0x%x\n" , average); + }else { + calfact |=FIELD_PREP (STM32MP25_CALFACT_D_MASK , average); + } + +stm32_adc_writel (adc,STM32MP25_ADC_CALFACT , calfact); + +dev_dbg (&indio_dev->dev,"set calfact_s=0x%03lx, calfact_d=0x%03lx, calados=%ld\n" , +FIELD_GET (STM32MP25_CALFACT_S_MASK , calfact), +FIELD_GET (STM32MP25_CALFACT_D_MASK , calfact), +FIELD_GET (STM32MP25_CALFACT_CALADDOS , calfact)); +out: +stm32_adc_clr_bits (adc,STM32H7_ADC_CR ,STM32H7_ADCAL ); +stm32_adc_set_res (adc); + +return ret; +}
...
drivers/iio/adc/stm32-adc.c static int stm32_adc_probe(struct platform_device *pdev) · line 2918
Quoted 2 lines
drivers/iio/adc/stm32-adc.c +2
-0+if (device_property_present (&pdev->dev,"st,adc-trigger-sel" )) { + ret =device_property_read_u32 (dev,"st,adc-trigger-sel" , &trig_id);
Why the first parameter is inconsistent in two device property API calls?
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (ret) + return ret;
No 'else' for the default?
Quoted 1 line
(quoted diff) +1
-0+ }
...
drivers/iio/adc/stm32-adc.c static const struct dev_pm_ops stm32_adc_pm_ops = { · line 3068
Quoted 5 lines
static const struct
stm32_adc_cfgstm32f4_adc_cfg= {drivers/iio/adc/stm32-adc.c +1
-1.regs = &stm32f4_adc_regspec, .adc_info = &stm32f4_adc_info, - .trigs = stm32f4_adc_trigs, + .trigs = { stm32f4_adc_trigs, },
When a single line the inner trailing comma is not needed.
drivers/iio/adc/stm32-adc.c static const struct dev_pm_ops stm32_adc_pm_ops = {
Quoted 6 lines
drivers/iio/adc/stm32-adc.c +0
-0.clk_required = true, .start_conv = stm32f4_adc_start_conv, .stop_conv = stm32f4_adc_stop_conv, .vref_charac = 3300, };
...
Overall feeling that this patch is cumbersome of several changes. Please, split.
Signature · 2 lines
With Best Regards, Andy Shevchenko
[email protected]
AI reviewRe: [PATCH 3/8] iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
In reply to Fabrice GasnierThank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] Missing bounds check on the st,adc-trigger-sel device tree property allows an out-of-bounds array read when indexing adc->cfg->trigs.
- [Medium] Missing ADC stop (ADSTP) on calibration timeout error path leaves ADC in a locked state.
Pre-existing issues:
- [High] Configuring an unsupported internal channel does not abort setup, leading to errant read-modify-write operations on register offset 0 (ISR), which silently clears unrelated pending interrupts. --
commit 07a141434d979402aadc3f3eaff7d932ee702232
Author: Fabrice Gasnier <[email protected]>
iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
This commit adds support for the STM32MP23 and STM32MP25 SoCs to the stm32-adc driver. It introduces support for diversity in IRQs, clocks, internal voltage channels, and trigger lists by utilizing a dedicated compatible string and configuration data.
Quoted 2 lines
drivers/iio/adc/stm32-adc.c +0
-0
[ ... ]
Quoted 1 line
drivers/iio/adc/stm32-adc.c +0
-0@@ -1503,6 +1503,163 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
[ ... ]
Quoted 20 lines
drivers/iio/adc/stm32-adc.c +20
-0+static int stm32mp25_adc_prepare (struct iio_dev *indio_dev) +{ +struct stm32_adc *adc =iio_priv (indio_dev); +int ret; + + ret =stm32h7_adc_exit_pwr_down (indio_dev); +if (ret) +return ret; + +/* Must enable the ADC before running software-assisted calibration */ + ret =stm32h7_adc_enable (indio_dev); +if (ret) + goto pwr_dwn; + +/* Always run offset calibration */ + ret =stm32mp25_adc_calib (indio_dev); +if (ret) + goto adc_dis; + +stm32_adc_int_ch_enable (indio_dev);
drivers/iio/adc/stm32-adc.c static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · line 1644
Quoted 10 lines
drivers/iio/adc/stm32-adc.c +10
-0+ +stm32_adc_writel (adc, adc->cfg->regs->difsel.reg, adc->difsel); + +if (adc->cfg->has_presel) +stm32_adc_writel (adc,STM32H7_ADC_PCSEL , adc->pcsel); + +return 0 ; + +adc_dis: +stm32h7_adc_disable (indio_dev);
[Severity: Medium]
If calibration times out, does this error path leave the ADC in a locked state?
If stm32mp25_adc_calib() times out waiting for ADSTART to clear, it returns an error that jumps to adc_dis. The error path directly calls stm32h7_adc_disable(), which tries to disable the ADC by setting ADDIS.
However, the hardware specification generally prohibits setting ADDIS while ADSTART=1. Should the driver first abort the conversion using an stm32h7_adc_stop_conv() call to set ADSTP and wait for ADSTART to clear before disabling the hardware?
[ ... ]
Quoted 12 lines
drivers/iio/adc/stm32-adc.c +5
-0@@ -2641,6 +2641,11 @@ static int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_ndev_warn (&indio_dev->dev,"%s channel not available\n" , ch_name);break ; +case STM32_ADC_INT_CH_VDDGPU : +if (!adc->cfg->regs->or_vddgpu.reg) +dev_warn (&indio_dev->dev, +"%s channel not available\n" , ch_name); +break ; }if (stm32_adc_ic[i].idx !=STM32_ADC_INT_CH_VREFINT ) {
drivers/iio/adc/stm32-adc.c
Quoted 3 lines
drivers/iio/adc/stm32-adc.c +0
-0adc->int_ch[i] = chan;break ; }
[Severity: High]
This is a pre-existing issue, but does this warning branch fail to abort channel registration?
If an unsupported internal channel like vddgpu is requested, the driver prints a warning but falls through and assigns it a valid int_ch below.
This causes a problem later during setup:
stm32_adc_int_ch_enable() {
...
case STM32_ADC_INT_CH_VDDGPU:
stm32_adc_set_bits(adc, adc->cfg->regs->or_vddgpu.reg,
adc->cfg->regs->or_vddgpu.mask);
...
}Because the register offset is uninitialized (0), this performs a read-modify-write on offset 0, which corresponds to the ISR register. Since the ISR has read-clear-write-1 semantics, this will silently clear all currently pending unrelated interrupts.
[ ... ]
drivers/iio/adc/stm32-adc.c static int stm32_adc_probe(struct platform_device *pdev) · line 2923
Quoted 11 lines
drivers/iio/adc/stm32-adc.c +7
-0@@ -2914,6 +2914,18 @@ static int stm32_adc_probe(struct platform_device *pdev)if (ret <0 )return ret; +if (device_property_present (&pdev->dev,"st,adc-trigger-sel" )) { + ret =device_property_read_u32 (dev,"st,adc-trigger-sel" , &trig_id); +if (ret) +return ret; + } + + adc->trigs = adc->cfg->trigs[trig_id];
[Severity: High]
Could an invalid st,adc-trigger-sel value lead to an out-of-bounds read here?
The st,adc-trigger-sel property is read directly into trig_id and immediately used to index the adc->cfg->trigs array, which has a fixed size of 2.
If a malformed Device Tree provides a larger value, this skips bounds validation and might cause a memory safety issue by dereferencing invalid pointers.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Jonathan Cameron
maintainerRe: [PATCH 3/8] iio: adc: stm32-adc: add support for stm32mp23 and stm32mp25
In reply to Fabrice GasnierQuoted 25 lines · On Fri, 11 Sep 2026 17:51:25 +0200 Fabrice Gasnier…
Add support for STM32MP23 STM32MP25 SoCs. They have 3 ADCs, split into two blocks:
- ADC12 (ADC1 & ADC2) are tightly coupled.
- ADC3 is managed independently.
Trigger list slightly changes between STM32MP23 and STM32MP25.Each ADC is a 12-bits successive approximation analog-to-digital converter, with up to 20 multiplexed channels that can be configured as single ended or differential. ADC resolution ranges from 6 to 12 bits.
It introduces diversity regarding IRQs, clocks, software calibration procedure, internal voltage channels, sampling time (prescaler) and trigger list. Most of the architecture, and the driver engine remains similar. So, handle the differences w.r.t. other STM32 ADCs family with a dedicated compatible and compatible data.
Trigger list depends on ADC instance, retrieved with "st,adc-trigger-sel" property.
Add support for vddcpu and vddgpu internal channels on stm32mp25. These channels are enabled by using ADC option register.
Add VDDGPU to the list of supported channels in this driver and made available on stm32mp25. So update sampling information for all variants (with zero'ed data when it's not available).
Quoted 5 lines
Co-developed-by Cheick Traore <[email protected]>Signed-off-by Cheick Traore <[email protected]>Co-developed-by Olivier Moysan <[email protected]>Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>
Hi. various comment inline. Some stuff will change if the two compatible solution works out instead of the trigger array stuff. There are also some bits I'd like as enabling refactors where you add the new stuff to support extra variability before bringing in a the device support that uses it. Tends to end up more readble.
drivers/iio/adc/stm32-adc-core.c static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) · line 142
Quoted 5 lines
/* STM32F4 ADC internal common clock prescaler division ratios */ static int stm32f4_pclk_div[] = {2, 4, 6, 8};
drivers/iio/adc/stm32-adc-core.c +2
-0+/* STM32MP25 ADC internal common clock prescaler division ratios */ +static int stm32mp25_presc_div[] = {1 ,2 ,4 ,6 ,8 ,10 ,12 ,16 ,32 ,64 ,128 ,256 };
Spaces after { and before }
I don't mind the line being a bit longer. Hmm. Local style so maybe leave it for now.
Quoted 34 lines
drivers/iio/adc/stm32-adc-core.c +8
-7+/** -* stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler +* stm32_adc_clk_sel() - Select stm32f4 ADC common clock prescaler * @pdev: platform device * @priv: stm32 ADC core private data * Select clock prescaler used for analog conversions, before using ADC. */ -static int stm32f4_adc_clk_sel (struct platform_device *pdev, -struct stm32_adc_priv *priv) +static int stm32_adc_clk_sel (struct platform_device *pdev, +struct stm32_adc_priv *priv) {unsigned long rate;u32 val;int i; -/* stm32f4 has one clk input for analog (mandatory), enforce it here */ +/* stm32f4/mp25 has one clk input for analog (mandatory), enforce it here */ if (!priv->aclk) {dev_err (&pdev->dev,"No 'adc' clock found\n" );return -ENOENT ;@@ -153,20 +166,20 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,return -EINVAL ; } -for (i =0 ; i <ARRAY_SIZE (stm32f4_pclk_div); i++) { -if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate) +for (i =0 ; i < priv->cfg->num_presc; i++) { +if ((rate / priv->cfg->presc[i]) <= priv->max_clk_rate)break ; } -if (i >=ARRAY_SIZE (stm32f4_pclk_div)) { +if (i >= priv->cfg->num_presc) {
drivers/iio/adc/stm32-adc-core.c static int stm32f4_adc_clk_sel(struct platform_device *pdev, · line 178
Quoted 10 lines
drivers/iio/adc/stm32-adc-core.c +1
-5dev_err (&pdev->dev,"adc clk selection failed\n" );return -EINVAL ; } - priv->common.rate = rate / stm32f4_pclk_div[i]; - val =readl_relaxed (priv->common.base +STM32F4_ADC_CCR ); - val &= ~STM32F4_ADC_ADCPRE_MASK ; - val |= i <<STM32F4_ADC_ADCPRE_SHIFT ; -writel_relaxed (val, priv->common.base +STM32F4_ADC_CCR ); + priv->common.rate = rate / priv->cfg->presc[i];
Where a refactor is needed do it first in an enabling patch with no new device support, then follow up with the new devices stuff.
You might want to break that enabling up into a couple of patches as there are multiple things that need to become configurable and it will get complex in one patch.
Quoted 22 lines
drivers/iio/adc/stm32-adc-core.c +7
-0+ val =readl_relaxed (priv->common.base + priv->cfg->regs->ccr); + val &= ~priv->cfg->regs->presc_msk; + val |= i << priv->cfg->regs->presc_shift; +writel_relaxed (val, priv->common.base + priv->cfg->regs->ccr);dev_dbg (&pdev->dev,"Using analog clock source at %ld kHz\n" , priv->common.rate /1000 );@@ -314,6 +327,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3 }, .ier = STM32F4_ADC_CR1, .eocie_msk = STM32F4_EOCIE, + .presc_msk = STM32F4_ADC_ADCPRE_MASK, + .presc_shift = STM32F4_ADC_ADCPRE_SHIFT, }; + static const struct of_device_id stm32_adc_of_match[] = { { .compatible = "st,stm32f4-adc-core",@@ -895,6 +948,12 @@ static const struct of_device_id stm32_adc_of_match[] = { }, {
drivers/iio/adc/stm32-adc-core.c static const struct of_device_id stm32_adc_of_match[] = { · line 958
Quoted 10 lines
drivers/iio/adc/stm32-adc-core.c +6
-0.compatible = "st,stm32mp13-adc-core", .data = (void *)&stm32mp13_adc_priv_cfg + }, { + .compatible = "st,stm32mp23-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg + }, { + .compatible = "st,stm32mp25-adc-core", + .data = (void *)&stm32mp25_adc_priv_cfg }, { },
Feel free to delete this trailing comma whilst you are here.
Quoted 10 lines
(quoted diff) +0
-0};drivers/iio/adc/stm32-adc.c +0
-0enum stm32_adc_int_ch {
drivers/iio/adc/stm32-adc.c enum stm32_adc_int_ch { · line 101
Quoted 5 lines
drivers/iio/adc/stm32-adc.c +1
-0@@ -86,6 +97,7 @@ enum stm32_adc_int_ch {STM32_ADC_INT_CH_VDDQ_DDR ,STM32_ADC_INT_CH_VREFINT ,STM32_ADC_INT_CH_VBAT , +STM32_ADC_INT_CH_VDDGPU , STM32_ADC_INT_CH_NB,
That one shouldn't have a comma as it's just there for counting and must always be last. Feel free to tidy that up whilst you are here!
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = { · line 120
Quoted 7 lines
drivers/iio/adc/stm32-adc.c +1
-0};@@ -105,6 +117,7 @@ static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = { { "vddq_ddr", STM32_ADC_INT_CH_VDDQ_DDR }, { "vrefint", STM32_ADC_INT_CH_VREFINT }, { "vbat", STM32_ADC_INT_CH_VBAT }, + { "vddgpu", STM32_ADC_INT_CH_VDDGPU },
A precursor making all these arrays use
[STM32_ADC_INT_CH_VBAT] = { "...." } would help avoid the need for static
magic below.
Quoted 1 line
drivers/iio/adc/stm32-adc.c +0
-0};
...
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_regspec stm32h7_adc_regspec = { · line 669
Quoted 7 lines
drivers/iio/adc/stm32-adc.c +6
-0+/* STM32MP25 external trigger sources for ADC12 */ +static struct stm32_adc_trig_info stm32mp25_adc12_trigs[] = { + {TIM1_TRGO ,STM32_EXT0 }, + {TIM1_TRGO2 ,STM32_EXT1 }, + {LPTIM5_OUT ,STM32_EXT28 }, + {},
As below. Look for others.
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_regspec stm32h7_adc_regspec = { · line 702
Quoted 11 lines
drivers/iio/adc/stm32-adc.c +10
-0+}; + +/* STM32MP25 external trigger sources for ADC3 */ +static struct stm32_adc_trig_info stm32mp25_adc3_trigs[] = { + {LPTIM1_CH1 ,STM32_EXT24 }, + {LPTIM2_CH1 ,STM32_EXT25 }, + {LPTIM3_CH1 ,STM32_EXT26 }, + {LPTIM4_CH1 ,STM32_EXT27 }, + {LPTIM5_OUT ,STM32_EXT28 }, + {},
No comma on terminating entries like this +
{ }preferred as style for IIO drivers. (random choice but I'd like consistency across drivers eventually!)
drivers/iio/adc/stm32-adc.c static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) · line 1165
Quoted 8 lines
drivers/iio/adc/stm32-adc.c +2
-1+};@@ -970,7 +1162,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)/* Exit deep power down, then enable ADC voltage regulator */ stm32_adc_clr_bits (adc,STM32H7_ADC_CR ,STM32H7_DEEPPWD ); -stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADVREGEN ); +if (adc->cfg->has_vregen)
I'd prefer this extra flag came in during a percursor patch (and was always set during that). Will reduce the complexity of this patch a touch.
Quoted 14 lines
drivers/iio/adc/stm32-adc.c +7
-0+stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADVREGEN );if (adc->cfg->has_boostmode && adc->common->rate >STM32H7_BOOST_CLKRATE )@@ -1310,6 +1503,163 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)stm32h7_adc_enter_pwr_down (adc); } +/* +* STM32MP25 offset calibration software procedure. Basically the calibration routine is +* expected to average (for example) 8 samples in calibration mode, for single-ended and +* differential channels, to calibrate the zero offset. In case offset is "negative", an +* additional offset can be added, to determine calibration factor. It must be kept later +* for all conversions.
drivers/iio/adc/stm32-adc.c static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · line 1521
Quoted 10 lines
drivers/iio/adc/stm32-adc.c +10
-0+*/ +static int stm32mp25_adc_calib_get_average_data (struct iio_dev *indio_dev,u32 *average) +{ +struct stm32_adc *adc =iio_priv (indio_dev); +const struct stm32_adc_regspec *regs = adc->cfg->regs; +u32 val, avg =0 ; +int i, ret; + +/* Repeat several conversions in calibration mode, average the results */ +for (i =0 ; i <STM32MP25_CALIB_LOOP ; i++) {
for (unsigned int i = 0; i...
Look for other cases of this that can be simplified given this style is now allowed in the kernel (has been for last few years).
Quoted 19 lines
drivers/iio/adc/stm32-adc.c +19
-0+stm32_adc_set_bits (adc,STM32H7_ADC_CR ,STM32H7_ADSTART ); + ret =stm32_adc_readl_poll_timeout (STM32H7_ADC_CR , val, + !(val & (STM32H7_ADSTART )), +100 ,STM32_ADC_TIMEOUT_US ); +if (ret) { +dev_err (&indio_dev->dev,"calibration average error %d\n" , ret); +return ret; + } + + val =stm32_adc_readl (adc, regs->dr); +dev_vdbg (&indio_dev->dev,"dr[%d]=0x%08x\n" , i, val); + avg += val; + } + + *average =DIV_ROUND_CLOSEST (avg,STM32MP25_CALIB_LOOP ); +dev_vdbg (&indio_dev->dev,"average=0x%08x\n" , *average); + +return 0 ; +}
...
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_cfg stm32f4_adc_cfg = { · line 3079
Quoted 5 lines
drivers/iio/adc/stm32-adc.c +2
-1-static const unsigned int stm32_adc_min_ts_h7[] = {0 ,0 ,0 ,4300 ,9000 }; +/* Internal channel indexes are mapped on stm32_adc_int_ch enum */ +static const unsigned int stm32_adc_min_ts_h7[] = {0 ,0 ,0 ,4300 ,9000 ,0 };static_assert (ARRAY_SIZE (stm32_adc_min_ts_h7) ==STM32_ADC_INT_CH_NB );
Given we only care about some entries, maybe we should have a precursor that drops all these static asserts and instead does
static const unsigned int stm32_adc_min_ts_h7[STM32_ADC_INT_CH_NB] = {
[STM32_ADC_INT_CH_VDDQ_DDR] = 4300,
.. Only the ones that need to be non 0.
};drivers/iio/adc/stm32-adc.c static const struct stm32_adc_cfg stm32h7_adc_cfg = { · line 3101
Quoted 6 lines
drivers/iio/adc/stm32-adc.c +1
-1@@ -2728,18 +3098,19 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { .vref_charac = 3300, }; -static const unsigned int stm32_adc_min_ts_mp1[] = {100 ,100 ,100 ,4300 ,9800 }; +static const unsigned int stm32_adc_min_ts_mp1[] = {100 ,0 ,0 ,4300 ,9800 ,0 };
As below. If these need to change for some reason, precursor patch. If it were just the extra entry that would be fine but numbers are changing for earlier entries.
Quoted 17 lines
drivers/iio/adc/stm32-adc.c +2
-1static_assert (ARRAY_SIZE (stm32_adc_min_ts_mp1) ==STM32_ADC_INT_CH_NB );static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .regs = &stm32mp1_adc_regspec, .adc_info = &stm32h7_adc_info, - .trigs = stm32h7_adc_trigs, + .trigs = { stm32h7_adc_trigs, }, .has_vregready = true, .has_boostmode = true, .has_linearcal = true, .has_presel = true, .has_oversampling = true, + .has_vregen = true, .start_conv = stm32h7_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare,
drivers/iio/adc/stm32-adc.c static const struct stm32_adc_cfg stm32mp1_adc_cfg = { · line 3125
Quoted 5 lines
drivers/iio/adc/stm32-adc.c +1
-1@@ -2751,14 +3122,15 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .vref_charac = 3300, }; -static const unsigned int stm32_adc_min_ts_mp13[] = {100 ,0 ,0 ,4300 ,9800 }; +static const unsigned int stm32_adc_min_ts_mp13[] = {1000 ,1000 ,1000 ,4300 ,9800 ,0 };
Why is this existing entry changing?
Quoted 15 lines
drivers/iio/adc/stm32-adc.c +2
-1static_assert (ARRAY_SIZE (stm32_adc_min_ts_mp13) ==STM32_ADC_INT_CH_NB );static const struct stm32_adc_cfg stm32mp13_adc_cfg = { .regs = &stm32mp13_adc_regspec, .adc_info = &stm32mp13_adc_info, - .trigs = stm32h7_adc_trigs, + .trigs = { stm32h7_adc_trigs, }, .has_oversampling = true, + .has_vregen = true, .start_conv = stm32mp13_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare,@@ -2770,11 +3142,50 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = { .vref_charac = 3300, };
PATCH 4/8 arm64: dts: st: add vrefint calibration on stm32mp23
In reply to Fabrice GasnierFrom: Patrice Chotard <[email protected]>
Describe vrefint calibration cell to be retrieved by ADCs through bsec, on STM32MP23.
--- arch/arm64/boot/dts/st/stm32mp231.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm64/boot/dts/st/stm32mp231.dtsi +4 -0
@@ -790,6 +790,10 @@ part-number-otp@24 { reg = <0x24 0x4>; }; + vrefint: vrefin-cal@1b8 { + reg = <0x1b8 0x2>; + }; + package-otp@1e8 { reg = <0x1e8 0x1>; bits = <0 3>;
Signature · 1 line
2.43.0
Re: [PATCH 4/8] arm64: dts: st: add vrefint calibration on stm32mp23
Quoted 8 lines · Fabrice Gasnier
From: Patrice Chotard <[email protected]>
Describe vrefint calibration cell to be retrieved by ADCs through bsec, on STM32MP23.
Signed-off-by Olivier Moysan <[email protected]>Signed-off-by Patrice Chotard <[email protected]>Signed-off-by Fabrice Gasnier <[email protected]>
You have to implant Co-developed-by into this , please fix globally.
PATCH 5/8 arm64: dts: st: add vrefint calibration on stm32mp25
In reply to Fabrice GasnierFrom: Patrice Chotard <[email protected]>
Describe vrefint calibration cell to be retrieved by ADCs through bsec, on STM32MP25.
--- arch/arm64/boot/dts/st/stm32mp251.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm64/boot/dts/st/stm32mp251.dtsi +4 -0
@@ -1777,6 +1777,10 @@ part-number-otp@24 { reg = <0x24 0x4>; }; + vrefint: vrefin-cal@1b8 { + reg = <0x1b8 0x2>; + }; + package-otp@1e8 { reg = <0x1e8 0x1>; bits = <0 3>;
Signature · 1 line
2.43.0
PATCH 6/8 arm64: dts: st: add ADC nodes on stm32mp231
In reply to Fabrice GasnierFrom: Cheick Traore <[email protected]>
Add analog-to-digital converter support on STM32MP23 SoC. It has 3 ADCs, split into two blocks:
- ADC12 (ADC1 & ADC2) are tightly coupled.
- ADC3 is managed independently.
Define internal voltage channels in the SOC dtsi file, exception made of vbat/4 channel (to avoid undesired load on it, in case no conversion is needed on this channel). Choice is let to board implementation (via DT) to define it.
--- arch/arm64/boot/dts/st/stm32mp231.dtsi | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+)
arch/arm64/boot/dts/st/stm32mp231.dtsi +113 -0
@@ -646,6 +646,119 @@ uart7: serial@40370000 { status = "disabled"; }; + adc_12: adc@404e0000 { + compatible = "st,stm32mp23-adc-core", "st,stm32-adc-core"; + reg = <0x404e0000 0x400>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc CK_KER_ADC12>; + clock-names = "adc"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + access-controllers = <&rifsc 58>; + status = "disabled"; + + adc1: adc@0 { + compatible = "st,stm32mp23-adc", "st,stm32-adc"; + reg = <0x0>; + interrupt-parent = <&adc_12>; + interrupts = <0>; + dmas = <&hpdma 81 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <0>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + }; + + adc2: adc@100 { + compatible = "st,stm32mp23-adc", "st,stm32-adc"; + reg = <0x100>; + interrupt-parent = <&adc_12>; + interrupts = <1>; + dmas = <&hpdma 82 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <0>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + channel@15 { + reg = <15>; + label = "vddcore"; + }; + channel@17 { + reg = <17>; + label = "vddcpu"; + }; + channel@18 { + reg = <18>; + label = "vddgpu"; + }; + }; + }; + + adc_3: adc@404f0000 { + compatible = "st,stm32mp23-adc-core", "st,stm32-adc-core"; + reg = <0x404f0000 0x400>; + interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc CK_KER_ADC3>; + clock-names = "adc"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + access-controllers = <&rifsc 59>; + status = "disabled"; + + adc3: adc@0 { + compatible = "st,stm32mp23-adc", "st,stm32-adc"; + reg = <0x0>; + interrupt-parent = <&adc_3>; + interrupts = <0>; + dmas = <&hpdma 83 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <1>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + channel@15 { + reg = <15>; + label = "vddcore"; + }; + channel@17 { + reg = <17>; + label = "vddcpu"; + }; + channel@18 { + reg = <18>; + label = "vddgpu"; + }; + }; + }; + rng: rng@42020000 { compatible = "st,stm32mp25-rng"; reg = <0x42020000 0x400>;
Signature · 1 line
2.43.0
PATCH 7/8 arm64: dts: st: add ADC nodes on stm32mp251
In reply to Fabrice GasnierAdd analog-to-digital converter support on STM32MP25 SoC. It has 3 ADCs, split into two blocks:
- ADC12 (ADC1 & ADC2) are tightly coupled.
- ADC3 is managed independently.
Define internal voltage channels in the SOC dtsi file, exception made of vbat/4 channel (to avoid undesired load on it, in case no conversion is needed on this channel). Choice is let to board implementation (via DT) to define it.
--- arch/arm64/boot/dts/st/stm32mp251.dtsi | 115 +++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
arch/arm64/boot/dts/st/stm32mp251.dtsi +115 -0
@@ -1450,6 +1450,121 @@ uart8: serial@40380000 { status = "disabled"; }; + adc_12: adc@404e0000 { + compatible = "st,stm32mp25-adc-core", "st,stm32-adc-core"; + reg = <0x404e0000 0x400>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc CK_KER_ADC12>; + clock-names = "adc"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&CLUSTER_PD>; + access-controllers = <&rifsc 58>; + status = "disabled"; + + adc1: adc@0 { + compatible = "st,stm32mp25-adc", "st,stm32-adc"; + reg = <0x0>; + interrupt-parent = <&adc_12>; + interrupts = <0>; + dmas = <&hpdma 81 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <0>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + }; + + adc2: adc@100 { + compatible = "st,stm32mp25-adc", "st,stm32-adc"; + reg = <0x100>; + interrupt-parent = <&adc_12>; + interrupts = <1>; + dmas = <&hpdma 82 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <0>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + channel@15 { + reg = <15>; + label = "vddcore"; + }; + channel@17 { + reg = <17>; + label = "vddcpu"; + }; + channel@18 { + reg = <18>; + label = "vddgpu"; + }; + }; + }; + + adc_3: adc@404f0000 { + compatible = "st,stm32mp25-adc-core", "st,stm32-adc-core"; + reg = <0x404f0000 0x400>; + interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc CK_KER_ADC3>; + clock-names = "adc"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + access-controllers = <&rifsc 59>; + power-domains = <&CLUSTER_PD>; + status = "disabled"; + + adc3: adc@0 { + compatible = "st,stm32mp25-adc", "st,stm32-adc"; + reg = <0x0>; + interrupt-parent = <&adc_3>; + interrupts = <0>; + dmas = <&hpdma 83 0x20 0x12>; + dma-names = "rx"; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + st,adc-trigger-sel = <1>; + status = "disabled"; + channel@14 { + reg = <14>; + label = "vrefint"; + }; + channel@15 { + reg = <15>; + label = "vddcore"; + }; + channel@17 { + reg = <17>; + label = "vddcpu"; + }; + channel@18 { + reg = <18>; + label = "vddgpu"; + }; + }; + }; + rng: rng@42020000 { compatible = "st,stm32mp25-rng"; reg = <0x42020000 0x400>;
Signature · 1 line
2.43.0
PATCH 8/8 arm64: dts: st: add ADC support on stm32mp257f-ev1 board
In reply to Fabrice GasnierAdd ADC support on stm32mp257f-ev1 board. ANA0 dedicated pin is wired on mikroBUS connector, through a resistor divided and operational amplifier. Configure adc1 channel0, and voltage divider in the DT. Keep it disabled by default, to allow ADC to be used freely for other purpose.
--> | 470K | -+-- > | OpAmp (gain = 1) | --> ANA0 (to ADC1, ADC2 or ADC3)
|
v
| 560K |
|
v
---
GND--- arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts +22 -0
@@ -160,6 +160,28 @@ mm_ospi1: mm-ospi@60000000 { no-map; }; }; + + vdiv_ana0: voltage-divider-ana0 { + compatible = "voltage-divider"; + io-channels = <&adc1 0>; + output-ohms = <560000>; + full-ohms = <1030000>; + status = "disabled"; + }; +}; + +&adc_12 { + /* Don't need a pinctrl for ANA0 dedicated pin e.g. Channel@0 */ + vdda-supply = <&scmi_vdda18adc>; + vref-supply = <&scmi_v1v8>; + status = "disabled"; + adc1: adc@0 { + status = "okay"; + channel@0 { + reg = <0>; + st,min-sample-time-ns = <400>; + }; + }; }; &arm_wdt {
Signature · 1 line
2.43.0