* [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework
2024-06-25 15:07 [PATCH v2 0/8] iio: adc: dfsdm: add scaling support Olivier Moysan
@ 2024-06-25 15:07 ` Olivier Moysan
2024-06-28 21:35 ` Rob Herring
2024-06-25 15:07 ` [PATCH v2 6/8] iio: adc: stm32-dfsdm: adopt generic channels bindings Olivier Moysan
2024-06-25 15:07 ` [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm Olivier Moysan
2 siblings, 1 reply; 9+ messages in thread
From: Olivier Moysan @ 2024-06-25 15:07 UTC (permalink / raw)
To: fabrice.gasnier, Olivier Moysan, Arnaud Pouliquen,
Jonathan Cameron, Lars-Peter Clausen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue
Cc: alsa-devel, linux-iio, devicetree, linux-stm32, linux-arm-kernel,
linux-kernel
Change the DFSDM binding to use the new IIO backend framework,
along with the adoption of IIO generic channels.
This binding change allows to add scaling support to the DFSDM.
Keep the legacy binding as deprecated for backward compatibility.
The io-backends property is supported only in generic IIO channel
binding.
- Channel description with the generic binding (Audio and Analog):
Properties superseded by generic properties:
st,adc-channels: becomes "reg" property in channel node
st,adc-channel-names: becomes "label" property in channel node
Properties moved to channel child node:
st,adc-channel-types: becomes st,adc-channel-type
st,adc-channel-clk-src, st,adc-alt-channel
- Analog binding:
DFSDM filter channel is configured as an IIO backend consumer.
Add io-backends property in channel child nodes.
DFSDM is no more configured as a channel consumer from SD modulator.
Use of io-channels in DFSDM node is deprecated.
- Audio binding:
DFSDM audio DAI is configured as a channel consumer from DFSDM filter.
No change compare to legacy.
Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
---
.../bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 157 +++++++++++++++++-
1 file changed, 151 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
index c1b1324fa132..1802120b16b0 100644
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
@@ -102,9 +102,11 @@ patternProperties:
items:
minimum: 0
maximum: 7
+ deprecated: true
st,adc-channel-names:
description: List of single-ended channel names.
+ deprecated: true
st,filter-order:
description: |
@@ -118,6 +120,12 @@ patternProperties:
"#io-channel-cells":
const: 1
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
st,adc-channel-types:
description: |
Single-ended channel input type.
@@ -128,6 +136,7 @@ patternProperties:
items:
enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
+ deprecated: true
st,adc-channel-clk-src:
description: |
@@ -139,6 +148,7 @@ patternProperties:
items:
enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
+ deprecated: true
st,adc-alt-channel:
description:
@@ -147,6 +157,7 @@ patternProperties:
If not set, channel n is connected to SPI input n.
If set, channel n is connected to SPI input n + 1.
type: boolean
+ deprecated: true
st,filter0-sync:
description:
@@ -165,11 +176,64 @@ patternProperties:
- compatible
- reg
- interrupts
- - st,adc-channels
- - st,adc-channel-names
- st,filter-order
- "#io-channel-cells"
+ patternProperties:
+ "^channel@([0-9]|1[0-9])$":
+ type: object
+ $ref: adc.yaml
+ description: Represents the external channels which are connected to the DFSDM.
+
+ properties:
+ reg:
+ items:
+ minimum: 0
+ maximum: 8
+
+ label:
+ description:
+ Unique name to identify which channel this is.
+
+ st,adc-channel-type:
+ description: |
+ Single-ended channel input type.
+ - "SPI_R": SPI with data on rising edge (default)
+ - "SPI_F": SPI with data on falling edge
+ - "MANCH_R": manchester codec, rising edge = logic 0, falling edge = logic 1
+ - "MANCH_F": manchester codec, rising edge = logic 1, falling edge = logic 0
+ items:
+ enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
+ $ref: /schemas/types.yaml#/definitions/string
+
+ st,adc-channel-clk-src:
+ description: |
+ Conversion clock source.
+ - "CLKIN": external SPI clock (CLKIN x)
+ - "CLKOUT": internal SPI clock (CLKOUT) (default)
+ - "CLKOUT_F": internal SPI clock divided by 2 (falling edge).
+ - "CLKOUT_R": internal SPI clock divided by 2 (rising edge).
+ items:
+ enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
+ $ref: /schemas/types.yaml#/definitions/string
+
+ st,adc-alt-channel:
+ description:
+ Must be defined if two sigma delta modulators are
+ connected on same SPI input.
+ If not set, channel n is connected to SPI input n.
+ If set, channel n is connected to SPI input n + 1.
+ type: boolean
+
+ io-backends:
+ description:
+ Used to pipe external sigma delta modulator or internal ADC backend to DFSDM channel.
+
+ required:
+ - reg
+
+ additionalProperties: false
+
allOf:
- if:
properties:
@@ -199,9 +263,19 @@ patternProperties:
description:
From common IIO binding. Used to pipe external sigma delta
modulator or internal ADC output to DFSDM channel.
+ deprecated: true
- required:
- - io-channels
+ if:
+ required:
+ - st,adc-channels
+ then:
+ required:
+ - io-channels
+
+ patternProperties:
+ "^channel@([0-9]|1[0-9])$":
+ required:
+ - io-backends
- if:
properties:
@@ -294,7 +368,77 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
+ // Example 1: Audio use case with generic binding
dfsdm0: filter@0 {
+ compatible = "st,stm32-dfsdm-dmic";
+ reg = <0>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmamux1 101 0x400 0x01>;
+ dma-names = "rx";
+ #io-channel-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ st,filter-order = <5>;
+
+ channel@1 {
+ reg = <1>;
+ label = "dmic0";
+ st,adc-channel-type = "SPI_R";
+ st,adc-channel-clk-src = "CLKOUT";
+ st,adc-alt-channel;
+ };
+
+ asoc_pdm0: dfsdm-dai {
+ compatible = "st,stm32h7-dfsdm-dai";
+ #sound-dai-cells = <0>;
+ io-channels = <&dfsdm0 0>;
+ };
+ };
+
+ // Example 1: Analog use case with generic binding
+ dfsdm1: filter@1 {
+ compatible = "st,stm32-dfsdm-adc";
+ reg = <1>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmamux1 102 0x400 0x01>;
+ dma-names = "rx";
+ st,filter-order = <1>;
+ #io-channel-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@2 {
+ reg = <2>;
+ label = "in2";
+ st,adc-channel-type = "SPI_F";
+ st,adc-channel-clk-src = "CLKOUT";
+ st,adc-alt-channel;
+ io-backends = <&sd_adc2>;
+ };
+
+ channel@3 {
+ reg = <3>;
+ label = "in3";
+ st,adc-channel-type = "SPI_R";
+ st,adc-channel-clk-src = "CLKOUT";
+ io-backends = <&sd_adc3>;
+ };
+ };
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/stm32mp1-clks.h>
+ dfsdm_2: dfsdm@4400d000 {
+ compatible = "st,stm32mp1-dfsdm";
+ reg = <0x4400d000 0x800>;
+ clocks = <&rcc DFSDM_K>, <&rcc ADFSDM_K>;
+ clock-names = "dfsdm", "audio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ // Example 3: Audio use case with legacy binding
+ dfsdm0_2: filter@0 {
compatible = "st,stm32-dfsdm-dmic";
reg = <0>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
@@ -307,14 +451,15 @@ examples:
st,adc-channel-clk-src = "CLKOUT";
st,filter-order = <5>;
- asoc_pdm0: dfsdm-dai {
+ asoc_pdm0_2: dfsdm-dai {
compatible = "st,stm32h7-dfsdm-dai";
#sound-dai-cells = <0>;
io-channels = <&dfsdm0 0>;
};
};
- dfsdm_pdm1: filter@1 {
+ // Example 3: Analog use case with legacy binding
+ dfsdm1_2: filter@1 {
compatible = "st,stm32-dfsdm-adc";
reg = <1>;
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework
2024-06-25 15:07 ` [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework Olivier Moysan
@ 2024-06-28 21:35 ` Rob Herring
2024-07-03 8:28 ` Olivier MOYSAN
0 siblings, 1 reply; 9+ messages in thread
From: Rob Herring @ 2024-06-28 21:35 UTC (permalink / raw)
To: Olivier Moysan
Cc: fabrice.gasnier, Arnaud Pouliquen, Jonathan Cameron,
Lars-Peter Clausen, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, alsa-devel, linux-iio,
devicetree, linux-stm32, linux-arm-kernel, linux-kernel
On Tue, Jun 25, 2024 at 05:07:12PM +0200, Olivier Moysan wrote:
> Change the DFSDM binding to use the new IIO backend framework,
> along with the adoption of IIO generic channels.
> This binding change allows to add scaling support to the DFSDM.
>
> Keep the legacy binding as deprecated for backward compatibility.
>
> The io-backends property is supported only in generic IIO channel
> binding.
>
> - Channel description with the generic binding (Audio and Analog):
>
> Properties superseded by generic properties:
> st,adc-channels: becomes "reg" property in channel node
> st,adc-channel-names: becomes "label" property in channel node
> Properties moved to channel child node:
> st,adc-channel-types: becomes st,adc-channel-type
> st,adc-channel-clk-src, st,adc-alt-channel
>
> - Analog binding:
>
> DFSDM filter channel is configured as an IIO backend consumer.
> Add io-backends property in channel child nodes.
>
> DFSDM is no more configured as a channel consumer from SD modulator.
> Use of io-channels in DFSDM node is deprecated.
>
> - Audio binding:
>
> DFSDM audio DAI is configured as a channel consumer from DFSDM filter.
> No change compare to legacy.
>
> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
> ---
> .../bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 157 +++++++++++++++++-
> 1 file changed, 151 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
> index c1b1324fa132..1802120b16b0 100644
> --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
> @@ -102,9 +102,11 @@ patternProperties:
> items:
> minimum: 0
> maximum: 7
> + deprecated: true
>
> st,adc-channel-names:
> description: List of single-ended channel names.
> + deprecated: true
>
> st,filter-order:
> description: |
> @@ -118,6 +120,12 @@ patternProperties:
> "#io-channel-cells":
> const: 1
>
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 0
> +
> st,adc-channel-types:
> description: |
> Single-ended channel input type.
> @@ -128,6 +136,7 @@ patternProperties:
> items:
> enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
> $ref: /schemas/types.yaml#/definitions/non-unique-string-array
> + deprecated: true
>
> st,adc-channel-clk-src:
> description: |
> @@ -139,6 +148,7 @@ patternProperties:
> items:
> enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
> $ref: /schemas/types.yaml#/definitions/non-unique-string-array
> + deprecated: true
>
> st,adc-alt-channel:
> description:
> @@ -147,6 +157,7 @@ patternProperties:
> If not set, channel n is connected to SPI input n.
> If set, channel n is connected to SPI input n + 1.
> type: boolean
> + deprecated: true
>
> st,filter0-sync:
> description:
> @@ -165,11 +176,64 @@ patternProperties:
> - compatible
> - reg
> - interrupts
> - - st,adc-channels
> - - st,adc-channel-names
> - st,filter-order
> - "#io-channel-cells"
>
> + patternProperties:
> + "^channel@([0-9]|1[0-9])$":
Unit-addresses are normally hex. And according to reg below, the max
value is 8.
> + type: object
> + $ref: adc.yaml
> + description: Represents the external channels which are connected to the DFSDM.
> +
> + properties:
> + reg:
> + items:
> + minimum: 0
> + maximum: 8
More than 1 reg entry valid? Either way, you need maxItems. Or you can
just drop 'items'
> +
> + label:
> + description:
> + Unique name to identify which channel this is.
> +
> + st,adc-channel-type:
> + description: |
> + Single-ended channel input type.
> + - "SPI_R": SPI with data on rising edge (default)
> + - "SPI_F": SPI with data on falling edge
> + - "MANCH_R": manchester codec, rising edge = logic 0, falling edge = logic 1
> + - "MANCH_F": manchester codec, rising edge = logic 1, falling edge = logic 0
> + items:
'items' is for arrays, but...
> + enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
> + $ref: /schemas/types.yaml#/definitions/string
not an array.
> +
> + st,adc-channel-clk-src:
> + description: |
> + Conversion clock source.
> + - "CLKIN": external SPI clock (CLKIN x)
> + - "CLKOUT": internal SPI clock (CLKOUT) (default)
> + - "CLKOUT_F": internal SPI clock divided by 2 (falling edge).
> + - "CLKOUT_R": internal SPI clock divided by 2 (rising edge).
> + items:
ditto
> + enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
> + $ref: /schemas/types.yaml#/definitions/string
> +
> + st,adc-alt-channel:
> + description:
> + Must be defined if two sigma delta modulators are
> + connected on same SPI input.
> + If not set, channel n is connected to SPI input n.
> + If set, channel n is connected to SPI input n + 1.
> + type: boolean
> +
> + io-backends:
> + description:
> + Used to pipe external sigma delta modulator or internal ADC backend to DFSDM channel.
How many entries (maxItems)?
> +
> + required:
> + - reg
> +
> + additionalProperties: false
Put this next to the $ref for the node. And switch to
unevaluatedProperties and drop 'label' from here.
> +
> allOf:
> - if:
> properties:
> @@ -199,9 +263,19 @@ patternProperties:
> description:
> From common IIO binding. Used to pipe external sigma delta
> modulator or internal ADC output to DFSDM channel.
> + deprecated: true
>
> - required:
> - - io-channels
> + if:
> + required:
> + - st,adc-channels
> + then:
> + required:
> + - io-channels
> +
> + patternProperties:
> + "^channel@([0-9]|1[0-9])$":
> + required:
> + - io-backends
Don't think this is needed here. If channel node is present, the
io-backends should always be required, right? Then this can go under the
node schema.
Rob
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework
2024-06-28 21:35 ` Rob Herring
@ 2024-07-03 8:28 ` Olivier MOYSAN
0 siblings, 0 replies; 9+ messages in thread
From: Olivier MOYSAN @ 2024-07-03 8:28 UTC (permalink / raw)
To: Rob Herring
Cc: fabrice.gasnier, Arnaud Pouliquen, Jonathan Cameron,
Lars-Peter Clausen, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, alsa-devel, linux-iio,
devicetree, linux-stm32, linux-arm-kernel, linux-kernel
Hi Rob,
On 6/28/24 23:35, Rob Herring wrote:
> On Tue, Jun 25, 2024 at 05:07:12PM +0200, Olivier Moysan wrote:
>> Change the DFSDM binding to use the new IIO backend framework,
>> along with the adoption of IIO generic channels.
>> This binding change allows to add scaling support to the DFSDM.
>>
>> Keep the legacy binding as deprecated for backward compatibility.
>>
>> The io-backends property is supported only in generic IIO channel
>> binding.
>>
>> - Channel description with the generic binding (Audio and Analog):
>>
>> Properties superseded by generic properties:
>> st,adc-channels: becomes "reg" property in channel node
>> st,adc-channel-names: becomes "label" property in channel node
>> Properties moved to channel child node:
>> st,adc-channel-types: becomes st,adc-channel-type
>> st,adc-channel-clk-src, st,adc-alt-channel
>>
>> - Analog binding:
>>
>> DFSDM filter channel is configured as an IIO backend consumer.
>> Add io-backends property in channel child nodes.
>>
>> DFSDM is no more configured as a channel consumer from SD modulator.
>> Use of io-channels in DFSDM node is deprecated.
>>
>> - Audio binding:
>>
>> DFSDM audio DAI is configured as a channel consumer from DFSDM filter.
>> No change compare to legacy.
>>
>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
>> ---
>> .../bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 157 +++++++++++++++++-
>> 1 file changed, 151 insertions(+), 6 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
>> index c1b1324fa132..1802120b16b0 100644
>> --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
>> @@ -102,9 +102,11 @@ patternProperties:
>> items:
>> minimum: 0
>> maximum: 7
>> + deprecated: true
>>
>> st,adc-channel-names:
>> description: List of single-ended channel names.
>> + deprecated: true
>>
>> st,filter-order:
>> description: |
>> @@ -118,6 +120,12 @@ patternProperties:
>> "#io-channel-cells":
>> const: 1
>>
>> + '#address-cells':
>> + const: 1
>> +
>> + '#size-cells':
>> + const: 0
>> +
>> st,adc-channel-types:
>> description: |
>> Single-ended channel input type.
>> @@ -128,6 +136,7 @@ patternProperties:
>> items:
>> enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
>> $ref: /schemas/types.yaml#/definitions/non-unique-string-array
>> + deprecated: true
>>
>> st,adc-channel-clk-src:
>> description: |
>> @@ -139,6 +148,7 @@ patternProperties:
>> items:
>> enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
>> $ref: /schemas/types.yaml#/definitions/non-unique-string-array
>> + deprecated: true
>>
>> st,adc-alt-channel:
>> description:
>> @@ -147,6 +157,7 @@ patternProperties:
>> If not set, channel n is connected to SPI input n.
>> If set, channel n is connected to SPI input n + 1.
>> type: boolean
>> + deprecated: true
>>
>> st,filter0-sync:
>> description:
>> @@ -165,11 +176,64 @@ patternProperties:
>> - compatible
>> - reg
>> - interrupts
>> - - st,adc-channels
>> - - st,adc-channel-names
>> - st,filter-order
>> - "#io-channel-cells"
>>
>> + patternProperties:
>> + "^channel@([0-9]|1[0-9])$":
>
> Unit-addresses are normally hex. And according to reg below, the max
> value is 8.
>
Right. The maximum number of serial interfaces is 8.
So, the pattern can be reduced to "^channel@([0-7])$":
>> + type: object
>> + $ref: adc.yaml
>> + description: Represents the external channels which are connected to the DFSDM.
>> +
>> + properties:
>> + reg:
>> + items:
>> + minimum: 0
>> + maximum: 8
>
> More than 1 reg entry valid? Either way, you need maxItems. Or you can
> just drop 'items'
>
Added "maxItems: 1" and dropped items.
>> +
>> + label:
>> + description:
>> + Unique name to identify which channel this is.
>> +
>> + st,adc-channel-type:
>> + description: |
>> + Single-ended channel input type.
>> + - "SPI_R": SPI with data on rising edge (default)
>> + - "SPI_F": SPI with data on falling edge
>> + - "MANCH_R": manchester codec, rising edge = logic 0, falling edge = logic 1
>> + - "MANCH_F": manchester codec, rising edge = logic 1, falling edge = logic 0
>> + items:
>
> 'items' is for arrays, but...
>
Removed items
>> + enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
>> + $ref: /schemas/types.yaml#/definitions/string
>
> not an array.
>
>> +
>> + st,adc-channel-clk-src:
>> + description: |
>> + Conversion clock source.
>> + - "CLKIN": external SPI clock (CLKIN x)
>> + - "CLKOUT": internal SPI clock (CLKOUT) (default)
>> + - "CLKOUT_F": internal SPI clock divided by 2 (falling edge).
>> + - "CLKOUT_R": internal SPI clock divided by 2 (rising edge).
>> + items:
>
> ditto
>
Done
>> + enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
>> + $ref: /schemas/types.yaml#/definitions/string
>> +
>> + st,adc-alt-channel:
>> + description:
>> + Must be defined if two sigma delta modulators are
>> + connected on same SPI input.
>> + If not set, channel n is connected to SPI input n.
>> + If set, channel n is connected to SPI input n + 1.
>> + type: boolean
>> +
>> + io-backends:
>> + description:
>> + Used to pipe external sigma delta modulator or internal ADC backend to DFSDM channel.
>
> How many entries (maxItems)?
>
>> +
>> + required:
>> + - reg
>> +
>> + additionalProperties: false
>
> Put this next to the $ref for the node. And switch to
> unevaluatedProperties and drop 'label' from here.
>
Done
>> +
>> allOf:
>> - if:
>> properties:
>> @@ -199,9 +263,19 @@ patternProperties:
>> description:
>> From common IIO binding. Used to pipe external sigma delta
>> modulator or internal ADC output to DFSDM channel.
>> + deprecated: true
>>
>> - required:
>> - - io-channels
>> + if:
>> + required:
>> + - st,adc-channels
>> + then:
>> + required:
>> + - io-channels
>> +
>> + patternProperties:
>> + "^channel@([0-9]|1[0-9])$":
>> + required:
>> + - io-backends
>
> Don't think this is needed here. If channel node is present, the
> io-backends should always be required, right? Then this can go under the
> node schema.
>
The io-backends property is required only when we use st,stm32-dfsdm-adc
compatible. In other words, when we are in an analog use case. In this
case the channel is a consumer of a backend (typically a sd modulator)
In an audio use case (compatible st,stm32-dfsdm-dmic) the backend is not
required.
BRs
Olivier
> Rob
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 6/8] iio: adc: stm32-dfsdm: adopt generic channels bindings
2024-06-25 15:07 [PATCH v2 0/8] iio: adc: dfsdm: add scaling support Olivier Moysan
2024-06-25 15:07 ` [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework Olivier Moysan
@ 2024-06-25 15:07 ` Olivier Moysan
2024-06-29 19:03 ` Jonathan Cameron
2024-06-25 15:07 ` [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm Olivier Moysan
2 siblings, 1 reply; 9+ messages in thread
From: Olivier Moysan @ 2024-06-25 15:07 UTC (permalink / raw)
To: fabrice.gasnier, Jonathan Cameron, Lars-Peter Clausen,
Maxime Coquelin, Alexandre Torgue
Cc: Olivier Moysan, linux-iio, linux-stm32, linux-arm-kernel,
linux-kernel
Move to generic channels binding to ease new backend framework adoption
and prepare the convergence with MDF IP support on STM32MP2 SoC family.
Legacy binding:
DFSDM is an IIO channel consumer.
SD modulator is an IIO channels provider.
The channel phandles are provided in DT through io-channels property
and channel indexes through st,adc-channels property.
New binding:
DFSDM is an IIO channel provider.
The channel indexes are given by reg property in channel child node.
This new binding is intended to be used with SD modulator IIO backends.
It does not support SD modulator legacy IIO devices.
The st,adc-channels property presence is used to discriminate
between legacy and backend bindings.
The support of the DFSDM legacy channels and SD modulator IIO devices
is kept for backward compatibility.
Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
---
drivers/iio/adc/stm32-dfsdm-adc.c | 208 ++++++++++++++++++++++++------
1 file changed, 171 insertions(+), 37 deletions(-)
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index fabd654245f5..0df28c9dfa40 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -666,6 +666,64 @@ static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm,
return 0;
}
+static int stm32_dfsdm_generic_channel_parse_of(struct stm32_dfsdm *dfsdm,
+ struct iio_dev *indio_dev,
+ struct iio_chan_spec *ch,
+ struct fwnode_handle *node)
+{
+ struct stm32_dfsdm_channel *df_ch;
+ const char *of_str;
+ int ret, val;
+
+ ret = fwnode_property_read_u32(node, "reg", &ch->channel);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
+ return ret;
+ }
+
+ if (ch->channel >= dfsdm->num_chs) {
+ dev_err(&indio_dev->dev, " Error bad channel number %d (max = %d)\n",
+ ch->channel, dfsdm->num_chs);
+ return -EINVAL;
+ }
+
+ ret = fwnode_property_read_string(node, "label", &ch->datasheet_name);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev,
+ " Error parsing 'label' for idx %d\n", ch->channel);
+ return ret;
+ }
+
+ df_ch = &dfsdm->ch_list[ch->channel];
+ df_ch->id = ch->channel;
+
+ ret = fwnode_property_read_string(node, "st,adc-channel-type", &of_str);
+ if (!ret) {
+ val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_type);
+ if (val < 0)
+ return val;
+ } else {
+ val = 0;
+ }
+ df_ch->type = val;
+
+ ret = fwnode_property_read_string(node, "st,adc-channel-clk-src", &of_str);
+ if (!ret) {
+ val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_src);
+ if (val < 0)
+ return val;
+ } else {
+ val = 0;
+ }
+ df_ch->src = val;
+
+ ret = fwnode_property_read_u32(node, "st,adc-alt-channel", &df_ch->alt_si);
+ if (ret != -EINVAL)
+ df_ch->alt_si = 0;
+
+ return 0;
+}
+
static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev,
uintptr_t priv,
const struct iio_chan_spec *chan,
@@ -1227,7 +1285,8 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
- ret = iio_hw_consumer_enable(adc->hwc);
+ if (adc->hwc)
+ ret = iio_hw_consumer_enable(adc->hwc);
if (ret < 0) {
dev_err(&indio_dev->dev,
"%s: IIO enable failed (channel %d)\n",
@@ -1236,7 +1295,8 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
return ret;
}
ret = stm32_dfsdm_single_conv(indio_dev, chan, val);
- iio_hw_consumer_disable(adc->hwc);
+ if (adc->hwc)
+ iio_hw_consumer_disable(adc->hwc);
if (ret < 0) {
dev_err(&indio_dev->dev,
"%s: Conversion failed (channel %d)\n",
@@ -1362,15 +1422,20 @@ static int stm32_dfsdm_dma_request(struct device *dev,
return 0;
}
-static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
- struct iio_chan_spec *ch)
+static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, struct iio_chan_spec *ch,
+ struct fwnode_handle *child)
{
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
int ret;
- ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch);
- if (ret < 0)
+ if (child)
+ ret = stm32_dfsdm_generic_channel_parse_of(adc->dfsdm, indio_dev, ch, child);
+ else /* Legacy binding */
+ ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to parse channel\n");
return ret;
+ }
ch->type = IIO_VOLTAGE;
ch->indexed = 1;
@@ -1385,6 +1450,7 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
if (adc->dev_data->type == DFSDM_AUDIO) {
ch->ext_info = dfsdm_adc_audio_ext_info;
+ ch->scan_index = 0;
} else {
ch->scan_type.shift = 8;
}
@@ -1392,8 +1458,51 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
ch->scan_type.realbits = 24;
ch->scan_type.storagebits = 32;
- return stm32_dfsdm_chan_configure(adc->dfsdm,
- &adc->dfsdm->ch_list[ch->channel]);
+ return stm32_dfsdm_chan_configure(adc->dfsdm, &adc->dfsdm->ch_list[ch->channel]);
+}
+
+static int stm32_dfsdm_chan_init(struct iio_dev *indio_dev, struct iio_chan_spec *channels)
+{
+ int num_ch = indio_dev->num_channels;
+ int chan_idx = 0, ret = 0;
+
+ for (chan_idx = 0; chan_idx < num_ch; chan_idx++) {
+ channels[chan_idx].scan_index = chan_idx;
+ ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &channels[chan_idx], NULL);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Channels init failed\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int stm32_dfsdm_generic_chan_init(struct iio_dev *indio_dev, struct iio_chan_spec *channels)
+{
+ struct fwnode_handle *child;
+ int chan_idx = 0, ret;
+
+ device_for_each_child_node(&indio_dev->dev, child) {
+ /* Skip DAI node in DFSDM audio nodes */
+ if (fwnode_property_present(child, "compatible"))
+ continue;
+
+ channels[chan_idx].scan_index = chan_idx;
+ ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &channels[chan_idx], child);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Channels init failed\n");
+ goto err;
+ }
+
+ chan_idx++;
+ }
+ return chan_idx;
+
+err:
+ fwnode_handle_put(child);
+
+ return ret;
}
static int stm32_dfsdm_audio_init(struct device *dev, struct iio_dev *indio_dev)
@@ -1401,15 +1510,26 @@ static int stm32_dfsdm_audio_init(struct device *dev, struct iio_dev *indio_dev)
struct iio_chan_spec *ch;
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
struct stm32_dfsdm_channel *d_ch;
- int ret;
+ bool legacy = false;
+ int num_ch, ret;
+
+ /* If st,adc-channels is defined legacy binding is used. Else assume generic binding. */
+ num_ch = of_property_count_u32_elems(indio_dev->dev.of_node, "st,adc-channels");
+ if (num_ch == 1)
+ legacy = true;
ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL);
if (!ch)
return -ENOMEM;
- ch->scan_index = 0;
+ indio_dev->num_channels = 1;
+ indio_dev->channels = ch;
+
+ if (legacy)
+ ret = stm32_dfsdm_chan_init(indio_dev, ch);
+ else
+ ret = stm32_dfsdm_generic_chan_init(indio_dev, ch);
- ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch);
if (ret < 0) {
dev_err(&indio_dev->dev, "Channels init failed\n");
return ret;
@@ -1420,9 +1540,6 @@ static int stm32_dfsdm_audio_init(struct device *dev, struct iio_dev *indio_dev)
if (d_ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
adc->spi_freq = adc->dfsdm->spi_master_freq;
- indio_dev->num_channels = 1;
- indio_dev->channels = ch;
-
return stm32_dfsdm_dma_request(dev, indio_dev);
}
@@ -1430,43 +1547,60 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev)
{
struct iio_chan_spec *ch;
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
- int num_ch;
- int ret, chan_idx;
+ int num_ch, ret;
+ bool legacy = false;
adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp);
if (ret < 0)
return ret;
- num_ch = of_property_count_u32_elems(indio_dev->dev.of_node,
- "st,adc-channels");
- if (num_ch < 0 || num_ch > adc->dfsdm->num_chs) {
- dev_err(&indio_dev->dev, "Bad st,adc-channels\n");
- return num_ch < 0 ? num_ch : -EINVAL;
+ num_ch = device_get_child_node_count(&indio_dev->dev);
+ if (!num_ch) {
+ /* No channels nodes found. Assume legacy binding */
+ num_ch = of_property_count_u32_elems(indio_dev->dev.of_node, "st,adc-channels");
+ if (num_ch < 0) {
+ dev_err(&indio_dev->dev, "Bad st,adc-channels\n");
+ return num_ch;
+ }
+
+ legacy = true;
}
- /* Bind to SD modulator IIO device */
- adc->hwc = devm_iio_hw_consumer_alloc(&indio_dev->dev);
- if (IS_ERR(adc->hwc))
- return -EPROBE_DEFER;
+ if (num_ch > adc->dfsdm->num_chs) {
+ dev_err(&indio_dev->dev, "Number of channel [%d] exceeds [%d]\n",
+ num_ch, adc->dfsdm->num_chs);
+ return -EINVAL;
+ }
+ indio_dev->num_channels = num_ch;
- ch = devm_kcalloc(&indio_dev->dev, num_ch, sizeof(*ch),
- GFP_KERNEL);
- if (!ch)
- return -ENOMEM;
+ if (legacy) {
+ /* Bind to SD modulator IIO device. */
+ adc->hwc = devm_iio_hw_consumer_alloc(&indio_dev->dev);
+ if (IS_ERR(adc->hwc))
+ return -EPROBE_DEFER;
+ } else {
+ /* Generic binding. SD modulator IIO device not used. Use SD modulator backend. */
+ adc->hwc = NULL;
- for (chan_idx = 0; chan_idx < num_ch; chan_idx++) {
- ch[chan_idx].scan_index = chan_idx;
- ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &ch[chan_idx]);
- if (ret < 0) {
- dev_err(&indio_dev->dev, "Channels init failed\n");
- return ret;
- }
+ adc->backend = devm_kzalloc(&indio_dev->dev, sizeof(*adc->backend) * num_ch,
+ GFP_KERNEL);
+ if (!adc->backend)
+ return -ENOMEM;
}
- indio_dev->num_channels = num_ch;
+ ch = devm_kcalloc(&indio_dev->dev, num_ch, sizeof(*ch), GFP_KERNEL);
+ if (!ch)
+ return -ENOMEM;
indio_dev->channels = ch;
+ if (legacy)
+ ret = stm32_dfsdm_chan_init(indio_dev, ch);
+ else
+ ret = stm32_dfsdm_generic_chan_init(indio_dev, ch);
+ if (ret < 0)
+ return ret;
+
init_completion(&adc->completion);
/* Optionally request DMA */
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 6/8] iio: adc: stm32-dfsdm: adopt generic channels bindings
2024-06-25 15:07 ` [PATCH v2 6/8] iio: adc: stm32-dfsdm: adopt generic channels bindings Olivier Moysan
@ 2024-06-29 19:03 ` Jonathan Cameron
0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2024-06-29 19:03 UTC (permalink / raw)
To: Olivier Moysan
Cc: fabrice.gasnier, Lars-Peter Clausen, Maxime Coquelin,
Alexandre Torgue, linux-iio, linux-stm32, linux-arm-kernel,
linux-kernel
On Tue, 25 Jun 2024 17:07:14 +0200
Olivier Moysan <olivier.moysan@foss.st.com> wrote:
> Move to generic channels binding to ease new backend framework adoption
> and prepare the convergence with MDF IP support on STM32MP2 SoC family.
>
> Legacy binding:
> DFSDM is an IIO channel consumer.
> SD modulator is an IIO channels provider.
> The channel phandles are provided in DT through io-channels property
> and channel indexes through st,adc-channels property.
>
> New binding:
> DFSDM is an IIO channel provider.
> The channel indexes are given by reg property in channel child node.
>
> This new binding is intended to be used with SD modulator IIO backends.
> It does not support SD modulator legacy IIO devices.
> The st,adc-channels property presence is used to discriminate
> between legacy and backend bindings.
>
> The support of the DFSDM legacy channels and SD modulator IIO devices
> is kept for backward compatibility.
>
> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
Hi Olivier
Some minor comments inline.
thanks,
Jonathan
> @@ -1362,15 +1422,20 @@ static int stm32_dfsdm_dma_request(struct device *dev,
> return 0;
> }
>
> -static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
> - struct iio_chan_spec *ch)
> +static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, struct iio_chan_spec *ch,
> + struct fwnode_handle *child)
> {
> struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> int ret;
>
> - ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch);
> - if (ret < 0)
> + if (child)
> + ret = stm32_dfsdm_generic_channel_parse_of(adc->dfsdm, indio_dev, ch, child);
> + else /* Legacy binding */
> + ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch);
> + if (ret < 0) {
> + dev_err(&indio_dev->dev, "Failed to parse channel\n");
> return ret;
return dev_err_probe() assuming only called from probe() which I think is the case
but haven't actually checked.
> + }
>
> ch->type = IIO_VOLTAGE;
> ch->indexed = 1;
> @@ -1385,6 +1450,7 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
>
> if (adc->dev_data->type == DFSDM_AUDIO) {
> ch->ext_info = dfsdm_adc_audio_ext_info;
> + ch->scan_index = 0;
> } else {
> ch->scan_type.shift = 8;
> }
> @@ -1392,8 +1458,51 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
> ch->scan_type.realbits = 24;
> ch->scan_type.storagebits = 32;
>
> - return stm32_dfsdm_chan_configure(adc->dfsdm,
> - &adc->dfsdm->ch_list[ch->channel]);
> + return stm32_dfsdm_chan_configure(adc->dfsdm, &adc->dfsdm->ch_list[ch->channel]);
Is there a change here? If it's just a line wrap don't do that in same patch
making real changes.
> +}
> +
> +static int stm32_dfsdm_chan_init(struct iio_dev *indio_dev, struct iio_chan_spec *channels)
> +{
> + int num_ch = indio_dev->num_channels;
> + int chan_idx = 0, ret = 0;
int ret;
> +
> + for (chan_idx = 0; chan_idx < num_ch; chan_idx++) {
> + channels[chan_idx].scan_index = chan_idx;
> + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &channels[chan_idx], NULL);
> + if (ret < 0) {
> + dev_err(&indio_dev->dev, "Channels init failed\n");
> + return ret;
return dev_err_probe()
(I think this is only called from probe?)
> + }
> + }
> +
> + return ret;
return 0;
at least I assume it can't be positive?
> +}
> +
> +static int stm32_dfsdm_generic_chan_init(struct iio_dev *indio_dev, struct iio_chan_spec *channels)
> +{
> + struct fwnode_handle *child;
> + int chan_idx = 0, ret;
> +
> + device_for_each_child_node(&indio_dev->dev, child) {
device_for_each_child_node_scoped() as then you can do direct returns.
> + /* Skip DAI node in DFSDM audio nodes */
> + if (fwnode_property_present(child, "compatible"))
> + continue;
> +
> + channels[chan_idx].scan_index = chan_idx;
> + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &channels[chan_idx], child);
> + if (ret < 0) {
> + dev_err(&indio_dev->dev, "Channels init failed\n");
> + goto err;
return dev_err_probe() once using scoped above.
> + }
> +
> + chan_idx++;
> + }
> + return chan_idx;
> +
> +err:
> + fwnode_handle_put(child);
> +
> + return ret;
> }
>
>
> @@ -1430,43 +1547,60 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev)
> - ch = devm_kcalloc(&indio_dev->dev, num_ch, sizeof(*ch),
> - GFP_KERNEL);
> - if (!ch)
> - return -ENOMEM;
> + if (legacy) {
> + /* Bind to SD modulator IIO device. */
> + adc->hwc = devm_iio_hw_consumer_alloc(&indio_dev->dev);
> + if (IS_ERR(adc->hwc))
> + return -EPROBE_DEFER;
Obviously in the legacy path, but worth a dev_err_probe() because
if we defer, debug info gets stashed away so it is easy to see
why a driver is continuing to defer.
> + } else {
> + /* Generic binding. SD modulator IIO device not used. Use SD modulator backend. */
> + adc->hwc = NULL;
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm
2024-06-25 15:07 [PATCH v2 0/8] iio: adc: dfsdm: add scaling support Olivier Moysan
2024-06-25 15:07 ` [PATCH v2 4/8] dt-bindings: iio: dfsdm: move to backend framework Olivier Moysan
2024-06-25 15:07 ` [PATCH v2 6/8] iio: adc: stm32-dfsdm: adopt generic channels bindings Olivier Moysan
@ 2024-06-25 15:07 ` Olivier Moysan
2024-06-26 8:59 ` Nuno Sá
2 siblings, 1 reply; 9+ messages in thread
From: Olivier Moysan @ 2024-06-25 15:07 UTC (permalink / raw)
To: fabrice.gasnier, Jonathan Cameron, Lars-Peter Clausen,
Maxime Coquelin, Alexandre Torgue
Cc: Olivier Moysan, Nuno Sa, linux-iio, linux-kernel, linux-stm32,
linux-arm-kernel
Add scaling support to STM32 DFSDM.
When used in an analog context, a DFSDM filter typically converts the data
from a sigma delta modulator. The IIO device associated to the DFSDM
filter provides these data as raw data.
The IIO device can provide scaling information (voltage and offset) to
allow conversion of raw data into physical values.
With the new binding based on IIO backend framework, the sigma delta
modulators are defined as backends providing scaling information.
The scaling is not supported with legacy binding.
Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
Acked-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/Kconfig | 1 +
drivers/iio/adc/stm32-dfsdm-adc.c | 94 ++++++++++++++++++++++++++++++-
2 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 634dc9842fb7..352ad585c534 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1223,6 +1223,7 @@ config STM32_DFSDM_ADC
select IIO_BUFFER
select IIO_BUFFER_HW_CONSUMER
select IIO_TRIGGERED_BUFFER
+ select IIO_BACKEND
help
Select this option to support ADCSigma delta modulator for
STMicroelectronics STM32 digital filter for sigma delta converter.
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 0df28c9dfa40..6a84ef3f32fd 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -9,6 +9,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/iio/adc/stm32-dfsdm-adc.h>
+#include <linux/iio/backend.h>
#include <linux/iio/buffer.h>
#include <linux/iio/hw-consumer.h>
#include <linux/iio/sysfs.h>
@@ -78,6 +79,7 @@ struct stm32_dfsdm_adc {
/* ADC specific */
unsigned int oversamp;
struct iio_hw_consumer *hwc;
+ struct iio_backend **backend;
struct completion completion;
u32 *buffer;
@@ -672,6 +674,8 @@ static int stm32_dfsdm_generic_channel_parse_of(struct stm32_dfsdm *dfsdm,
struct fwnode_handle *node)
{
struct stm32_dfsdm_channel *df_ch;
+ struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+ struct iio_backend *backend;
const char *of_str;
int ret, val;
@@ -721,6 +725,14 @@ static int stm32_dfsdm_generic_channel_parse_of(struct stm32_dfsdm *dfsdm,
if (ret != -EINVAL)
df_ch->alt_si = 0;
+ if (adc->dev_data->type == DFSDM_IIO) {
+ backend = devm_iio_backend_fwnode_get(&indio_dev->dev, NULL, node);
+ if (IS_ERR(backend))
+ return dev_err_probe(&indio_dev->dev, PTR_ERR(backend),
+ "Failed to get backend\n");
+ adc->backend[ch->scan_index] = backend;
+ }
+
return 0;
}
@@ -1056,6 +1068,7 @@ static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev,
static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
{
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+ int i = 0;
int ret;
/* Reset adc buffer index */
@@ -1067,6 +1080,15 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
return ret;
}
+ if (adc->backend) {
+ while (adc->backend[i]) {
+ ret = iio_backend_enable(adc->backend[i]);
+ if (ret < 0)
+ return ret;
+ i++;
+ }
+ }
+
ret = stm32_dfsdm_start_dfsdm(adc->dfsdm);
if (ret < 0)
goto err_stop_hwc;
@@ -1099,6 +1121,7 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
{
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+ int i = 0;
stm32_dfsdm_stop_conv(indio_dev);
@@ -1106,6 +1129,13 @@ static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
stm32_dfsdm_stop_dfsdm(adc->dfsdm);
+ if (adc->backend) {
+ while (adc->backend[i]) {
+ iio_backend_disable(adc->backend[i]);
+ i++;
+ }
+ }
+
if (adc->hwc)
iio_hw_consumer_disable(adc->hwc);
@@ -1278,7 +1308,14 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
int *val2, long mask)
{
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
- int ret;
+
+ struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+ struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
+ u32 max = flo->max << (flo->lshift - chan->scan_type.shift);
+ int ret, idx = chan->scan_index;
+
+ if (flo->lshift < chan->scan_type.shift)
+ max = flo->max >> (chan->scan_type.shift - flo->lshift);
switch (mask) {
case IIO_CHAN_INFO_RAW:
@@ -1287,6 +1324,8 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
return ret;
if (adc->hwc)
ret = iio_hw_consumer_enable(adc->hwc);
+ if (adc->backend[idx])
+ ret = iio_backend_enable(adc->backend[idx]);
if (ret < 0) {
dev_err(&indio_dev->dev,
"%s: IIO enable failed (channel %d)\n",
@@ -1297,6 +1336,8 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
ret = stm32_dfsdm_single_conv(indio_dev, chan, val);
if (adc->hwc)
iio_hw_consumer_disable(adc->hwc);
+ if (adc->backend[idx])
+ iio_backend_disable(adc->backend[idx]);
if (ret < 0) {
dev_err(&indio_dev->dev,
"%s: Conversion failed (channel %d)\n",
@@ -1316,6 +1357,46 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
*val = adc->sample_freq;
return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ /*
+ * Scale is expressed in mV.
+ * When fast mode is disabled, actual resolution may be lower
+ * than 2^n, where n = realbits - 1.
+ * This leads to underestimating the input voltage.
+ * To compensate this deviation, the voltage reference can be
+ * corrected with a factor = realbits resolution / actual max
+ */
+ if (adc->backend[idx]) {
+ iio_backend_read_raw(adc->backend[idx], chan, val, val2, mask);
+
+ *val = div_u64((u64)*val * (u64)BIT(DFSDM_DATA_RES - 1), max);
+ *val2 = chan->scan_type.realbits;
+ if (chan->differential)
+ *val *= 2;
+ }
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ case IIO_CHAN_INFO_OFFSET:
+ /*
+ * DFSDM output data are in the range [-2^n, 2^n],
+ * with n = realbits - 1.
+ * - Differential modulator:
+ * Offset correspond to SD modulator offset.
+ * - Single ended modulator:
+ * Input is in [0V, Vref] range,
+ * where 0V corresponds to -2^n, and Vref to 2^n.
+ * Add 2^n to offset. (i.e. middle of input range)
+ * offset = offset(sd) * vref / res(sd) * max / vref.
+ */
+ if (adc->backend[idx]) {
+ iio_backend_read_raw(adc->backend[idx], chan, val, val2, mask);
+
+ *val = div_u64((u64)max * *val, BIT(*val2 - 1));
+ if (!chan->differential)
+ *val += max;
+ }
+ return IIO_VAL_INT;
}
return -EINVAL;
@@ -1444,7 +1525,15 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, struct iio_c
* IIO_CHAN_INFO_RAW: used to compute regular conversion
* IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling
*/
- ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ if (child) {
+ ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET);
+ } else {
+ /* Legacy. Scaling not supported */
+ ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ }
+
ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
@@ -1811,3 +1900,4 @@ module_platform_driver(stm32_dfsdm_adc_driver);
MODULE_DESCRIPTION("STM32 sigma delta ADC");
MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_BACKEND);
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm
2024-06-25 15:07 ` [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm Olivier Moysan
@ 2024-06-26 8:59 ` Nuno Sá
2024-06-26 16:15 ` Olivier MOYSAN
0 siblings, 1 reply; 9+ messages in thread
From: Nuno Sá @ 2024-06-26 8:59 UTC (permalink / raw)
To: Olivier Moysan, fabrice.gasnier, Jonathan Cameron,
Lars-Peter Clausen, Maxime Coquelin, Alexandre Torgue
Cc: Nuno Sa, linux-iio, linux-kernel, linux-stm32, linux-arm-kernel
Hi Olivier,
One thing that I just noticed...
On Tue, 2024-06-25 at 17:07 +0200, Olivier Moysan wrote:
> Add scaling support to STM32 DFSDM.
>
> When used in an analog context, a DFSDM filter typically converts the data
> from a sigma delta modulator. The IIO device associated to the DFSDM
> filter provides these data as raw data.
> The IIO device can provide scaling information (voltage and offset) to
> allow conversion of raw data into physical values.
>
> With the new binding based on IIO backend framework, the sigma delta
> modulators are defined as backends providing scaling information.
>
> The scaling is not supported with legacy binding.
>
> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
> Acked-by: Nuno Sa <nuno.sa@analog.com>
> ---
>
...
> +
> + case IIO_CHAN_INFO_SCALE:
> + /*
> + * Scale is expressed in mV.
> + * When fast mode is disabled, actual resolution may be lower
> + * than 2^n, where n = realbits - 1.
> + * This leads to underestimating the input voltage.
> + * To compensate this deviation, the voltage reference can be
> + * corrected with a factor = realbits resolution / actual max
> + */
> + if (adc->backend[idx]) {
> + iio_backend_read_raw(adc->backend[idx], chan, val,
> val2, mask);
Eve if it does not matter for your usecase, you should still do error handling
as iio_backend_read_raw() can return an error.
> + *val = div_u64((u64)*val * (u64)BIT(DFSDM_DATA_RES -
> 1), max);
> + *val2 = chan->scan_type.realbits;
> + if (chan->differential)
> + *val *= 2;
> + }
> + return IIO_VAL_FRACTIONAL_LOG2;
> +
> + case IIO_CHAN_INFO_OFFSET:
> + /*
> + * DFSDM output data are in the range [-2^n, 2^n],
> + * with n = realbits - 1.
> + * - Differential modulator:
> + * Offset correspond to SD modulator offset.
> + * - Single ended modulator:
> + * Input is in [0V, Vref] range,
> + * where 0V corresponds to -2^n, and Vref to 2^n.
> + * Add 2^n to offset. (i.e. middle of input range)
> + * offset = offset(sd) * vref / res(sd) * max / vref.
> + */
> + if (adc->backend[idx]) {
> + iio_backend_read_raw(adc->backend[idx], chan, val,
> val2, mask);
Same...
- Nuno Sá
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 8/8] iio: adc: stm32-dfsdm: add scaling support to dfsdm
2024-06-26 8:59 ` Nuno Sá
@ 2024-06-26 16:15 ` Olivier MOYSAN
0 siblings, 0 replies; 9+ messages in thread
From: Olivier MOYSAN @ 2024-06-26 16:15 UTC (permalink / raw)
To: Nuno Sá, fabrice.gasnier, Jonathan Cameron,
Lars-Peter Clausen, Maxime Coquelin, Alexandre Torgue
Cc: Nuno Sa, linux-iio, linux-kernel, linux-stm32, linux-arm-kernel
Hi Nuno,
On 6/26/24 10:59, Nuno Sá wrote:
> Hi Olivier,
>
> One thing that I just noticed...
>
> On Tue, 2024-06-25 at 17:07 +0200, Olivier Moysan wrote:
>> Add scaling support to STM32 DFSDM.
>>
>> When used in an analog context, a DFSDM filter typically converts the data
>> from a sigma delta modulator. The IIO device associated to the DFSDM
>> filter provides these data as raw data.
>> The IIO device can provide scaling information (voltage and offset) to
>> allow conversion of raw data into physical values.
>>
>> With the new binding based on IIO backend framework, the sigma delta
>> modulators are defined as backends providing scaling information.
>>
>> The scaling is not supported with legacy binding.
>>
>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
>> Acked-by: Nuno Sa <nuno.sa@analog.com>
>> ---
>>
>
> ...
>
>> +
>> + case IIO_CHAN_INFO_SCALE:
>> + /*
>> + * Scale is expressed in mV.
>> + * When fast mode is disabled, actual resolution may be lower
>> + * than 2^n, where n = realbits - 1.
>> + * This leads to underestimating the input voltage.
>> + * To compensate this deviation, the voltage reference can be
>> + * corrected with a factor = realbits resolution / actual max
>> + */
>> + if (adc->backend[idx]) {
>> + iio_backend_read_raw(adc->backend[idx], chan, val,
>> val2, mask);
>
> Eve if it does not matter for your usecase, you should still do error handling
> as iio_backend_read_raw() can return an error.
>
Ack. On the same occasion, I will switch to a dedicated API.
Olivier
>> + *val = div_u64((u64)*val * (u64)BIT(DFSDM_DATA_RES -
>> 1), max);
>> + *val2 = chan->scan_type.realbits;
>> + if (chan->differential)
>> + *val *= 2;
>> + }
>> + return IIO_VAL_FRACTIONAL_LOG2;
>> +
>> + case IIO_CHAN_INFO_OFFSET:
>> + /*
>> + * DFSDM output data are in the range [-2^n, 2^n],
>> + * with n = realbits - 1.
>> + * - Differential modulator:
>> + * Offset correspond to SD modulator offset.
>> + * - Single ended modulator:
>> + * Input is in [0V, Vref] range,
>> + * where 0V corresponds to -2^n, and Vref to 2^n.
>> + * Add 2^n to offset. (i.e. middle of input range)
>> + * offset = offset(sd) * vref / res(sd) * max / vref.
>> + */
>> + if (adc->backend[idx]) {
>> + iio_backend_read_raw(adc->backend[idx], chan, val,
>> val2, mask);
>
> Same...
>
> - Nuno Sá
^ permalink raw reply [flat|nested] 9+ messages in thread