* [PATCH v5 0/4] iio: adc: sama5d2_adc hw triggers and buffers
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
This patch implements the hardware triggers support and buffer management
for sama5d2.
The DT modifications ( [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained:
enable ADTRG pin) are for demonstration purposes of the feature,
setting the pinctrl for the ADC hw trigger pin,should go through
at91 maintainers.
As discussed on the mailing list, since we have a single external trigger
namely the ADTRG, but three different possible edges that can trigger it,
will have a single trigger in the IIO subsystem and three possible edges
which can be selected from the device tree.
Thus I created new bindings in the device tree for having the possible
edge types for the ADTRG pin.
The documentation for the bindings is in the patch
[PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add adtrg
trigger binding
The modifications in the DT are in the patch
[PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger
The new property must be set with the values from interrupt edge types, as this
pin is effectively an internal interrupt.
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Modified bindings to be similar with interrupts
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
- Modified trigger name length to 64
Eugen Hristev (4):
ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
ARM: dts: at91: sama5d2: add ADC hw trigger edge type
iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
.../bindings/iio/adc/at91-sama5d2_adc.txt | 6 +
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +-
arch/arm/boot/dts/sama5d2.dtsi | 1 +
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++-
4 files changed, 254 insertions(+), 6 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 0/4] iio: adc: sama5d2_adc hw triggers and buffers
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
jic23-DgEjT+Ai2ygdnm+yROfE0A, robh-DgEjT+Ai2ygdnm+yROfE0A
Cc: eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA
This patch implements the hardware triggers support and buffer management
for sama5d2.
The DT modifications ( [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained:
enable ADTRG pin) are for demonstration purposes of the feature,
setting the pinctrl for the ADC hw trigger pin,should go through
at91 maintainers.
As discussed on the mailing list, since we have a single external trigger
namely the ADTRG, but three different possible edges that can trigger it,
will have a single trigger in the IIO subsystem and three possible edges
which can be selected from the device tree.
Thus I created new bindings in the device tree for having the possible
edge types for the ADTRG pin.
The documentation for the bindings is in the patch
[PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add adtrg
trigger binding
The modifications in the DT are in the patch
[PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger
The new property must be set with the values from interrupt edge types, as this
pin is effectively an internal interrupt.
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Modified bindings to be similar with interrupts
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
- Modified trigger name length to 64
Eugen Hristev (4):
ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
ARM: dts: at91: sama5d2: add ADC hw trigger edge type
iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
.../bindings/iio/adc/at91-sama5d2_adc.txt | 6 +
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +-
arch/arm/boot/dts/sama5d2.dtsi | 1 +
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++-
4 files changed, 254 insertions(+), 6 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 0/4] iio: adc: sama5d2_adc hw triggers and buffers
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: linux-arm-kernel
This patch implements the hardware triggers support and buffer management
for sama5d2.
The DT modifications ( [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained:
enable ADTRG pin) are for demonstration purposes of the feature,
setting the pinctrl for the ADC hw trigger pin,should go through
at91 maintainers.
As discussed on the mailing list, since we have a single external trigger
namely the ADTRG, but three different possible edges that can trigger it,
will have a single trigger in the IIO subsystem and three possible edges
which can be selected from the device tree.
Thus I created new bindings in the device tree for having the possible
edge types for the ADTRG pin.
The documentation for the bindings is in the patch
[PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add adtrg
trigger binding
The modifications in the DT are in the patch
[PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger
The new property must be set with the values from interrupt edge types, as this
pin is effectively an internal interrupt.
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Modified bindings to be similar with interrupts
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
- Modified trigger name length to 64
Eugen Hristev (4):
ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
ARM: dts: at91: sama5d2: add ADC hw trigger edge type
iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
.../bindings/iio/adc/at91-sama5d2_adc.txt | 6 +
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +-
arch/arm/boot/dts/sama5d2.dtsi | 1 +
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++-
4 files changed, 254 insertions(+), 6 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 0bef9e0..04754b1 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -303,7 +303,7 @@
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc_default>;
+ pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
status = "okay";
};
@@ -322,6 +322,20 @@
bias-disable;
};
+ /*
+ * The ADTRG pin can work on any edge type.
+ * In here it's being pulled up, so need to
+ * connect it to ground to get an edge e.g.
+ * Trigger can be configured on falling, rise
+ * or any edge, and the pull-up can be changed
+ * to pull-down or left floating according to
+ * needs.
+ */
+ pinctrl_adtrg_default: adtrg_default {
+ pinmux = <PIN_PD31__ADTRG>;
+ bias-pull-up;
+ };
+
pinctrl_charger_chglev: charger_chglev {
pinmux = <PIN_PA12__GPIO>;
bias-disable;
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
jic23-DgEjT+Ai2ygdnm+yROfE0A, robh-DgEjT+Ai2ygdnm+yROfE0A
Cc: eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA
Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
---
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 0bef9e0..04754b1 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -303,7 +303,7 @@
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc_default>;
+ pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
status = "okay";
};
@@ -322,6 +322,20 @@
bias-disable;
};
+ /*
+ * The ADTRG pin can work on any edge type.
+ * In here it's being pulled up, so need to
+ * connect it to ground to get an edge e.g.
+ * Trigger can be configured on falling, rise
+ * or any edge, and the pull-up can be changed
+ * to pull-down or left floating according to
+ * needs.
+ */
+ pinctrl_adtrg_default: adtrg_default {
+ pinmux = <PIN_PD31__ADTRG>;
+ bias-pull-up;
+ };
+
pinctrl_charger_chglev: charger_chglev {
pinmux = <PIN_PA12__GPIO>;
bias-disable;
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: linux-arm-kernel
Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 0bef9e0..04754b1 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -303,7 +303,7 @@
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc_default>;
+ pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
status = "okay";
};
@@ -322,6 +322,20 @@
bias-disable;
};
+ /*
+ * The ADTRG pin can work on any edge type.
+ * In here it's being pulled up, so need to
+ * connect it to ground to get an edge e.g.
+ * Trigger can be configured on falling, rise
+ * or any edge, and the pull-up can be changed
+ * to pull-down or left floating according to
+ * needs.
+ */
+ pinctrl_adtrg_default: adtrg_default {
+ pinmux = <PIN_PD31__ADTRG>;
+ bias-pull-up;
+ };
+
pinctrl_charger_chglev: charger_chglev {
pinmux = <PIN_PA12__GPIO>;
bias-disable;
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Add property for the edge type of the hardware trigger pin ADTRG
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v4:
- Modified bindings to be similar with interrupts
Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
index 3223684..552e7a8 100644
--- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
@@ -11,6 +11,11 @@ Required properties:
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
+ - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
+ trigger pin. When the specific edge type is detected, the conversion will
+ start. Possible values are rising, falling, or both.
+ This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
+ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
Example:
@@ -25,4 +30,5 @@ adc: adc@fc030000 {
atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
jic23-DgEjT+Ai2ygdnm+yROfE0A, robh-DgEjT+Ai2ygdnm+yROfE0A
Cc: eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA
Add property for the edge type of the hardware trigger pin ADTRG
Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
---
Changes in v4:
- Modified bindings to be similar with interrupts
Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
index 3223684..552e7a8 100644
--- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
@@ -11,6 +11,11 @@ Required properties:
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
+ - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
+ trigger pin. When the specific edge type is detected, the conversion will
+ start. Possible values are rising, falling, or both.
+ This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
+ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
Example:
@@ -25,4 +30,5 @@ adc: adc@fc030000 {
atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: linux-arm-kernel
Add property for the edge type of the hardware trigger pin ADTRG
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v4:
- Modified bindings to be similar with interrupts
Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
index 3223684..552e7a8 100644
--- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
@@ -11,6 +11,11 @@ Required properties:
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
+ - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
+ trigger pin. When the specific edge type is detected, the conversion will
+ start. Possible values are rising, falling, or both.
+ This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
+ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
Example:
@@ -25,4 +30,5 @@ adc: adc at fc030000 {
atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
2017-06-15 13:24 ` Eugen Hristev
(?)
@ 2017-06-15 13:24 ` Eugen Hristev
-1 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Added ADTRG edge type property as interrupt edge type value
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v4:
- Modified bindings to be similar with interrupts
arch/arm/boot/dts/sama5d2.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 8067c71..483a387 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -1267,6 +1267,7 @@
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
status = "disabled";
};
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Added ADTRG edge type property as interrupt edge type value
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v4:
- Modified bindings to be similar with interrupts
arch/arm/boot/dts/sama5d2.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 8067c71..483a387 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -1267,6 +1267,7 @@
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
status = "disabled";
};
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: linux-arm-kernel
Added ADTRG edge type property as interrupt edge type value
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v4:
- Modified bindings to be similar with interrupts
arch/arm/boot/dts/sama5d2.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 8067c71..483a387 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -1267,6 +1267,7 @@
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
+ atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
status = "disabled";
};
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
2017-06-15 13:24 ` Eugen Hristev
(?)
@ 2017-06-15 13:24 ` Eugen Hristev
-1 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Added support for the external hardware trigger on pin ADTRG,
integrated the three possible edges into the driver
and created buffer management for data retrieval
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
1 file changed, 232 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index e10dca3..1773a5d 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -25,6 +25,10 @@
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h>
/* Control Register */
@@ -132,6 +136,17 @@
#define AT91_SAMA5D2_PRESSR 0xbc
/* Trigger Register */
#define AT91_SAMA5D2_TRGR 0xc0
+/* Mask for TRGMOD field of TRGR register */
+#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
+/* No trigger, only software trigger can start conversions */
+#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
+/* Trigger Mode external trigger rising edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
+/* Trigger Mode external trigger falling edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
+/* Trigger Mode external trigger any edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
+
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
@@ -145,14 +160,29 @@
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
+#define AT91_SAMA5D2_HW_TRIG_CNT 3
+#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
+#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
+
+/*
+ * Maximum number of bytes to hold conversion from all channels
+ * plus the timestamp
+ */
+#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
+ AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
+
+#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
+
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
.address = addr, \
+ .scan_index = num, \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -168,9 +198,11 @@
.channel = num, \
.channel2 = num2, \
.address = addr, \
+ .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -188,6 +220,12 @@ struct at91_adc_soc_info {
unsigned max_sample_rate;
};
+struct at91_adc_trigger {
+ char *name;
+ unsigned int trgmod_value;
+ unsigned int edge_type;
+};
+
struct at91_adc_state {
void __iomem *base;
int irq;
@@ -195,11 +233,14 @@ struct at91_adc_state {
struct regulator *reg;
struct regulator *vref;
int vref_uv;
+ struct iio_trigger *trig;
+ const struct at91_adc_trigger *selected_trig;
const struct iio_chan_spec *chan;
bool conversion_done;
u32 conversion_value;
struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available;
+ u16 buffer[AT91_BUFFER_MAX_HWORDS];
/*
* lock to prevent concurrent 'single conversion' requests through
* sysfs.
@@ -207,6 +248,24 @@ struct at91_adc_state {
struct mutex lock;
};
+static const struct at91_adc_trigger at91_adc_trigger_list[] = {
+ {
+ .name = "external_rising",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
+ .edge_type = IRQ_TYPE_EDGE_RISING,
+ },
+ {
+ .name = "external_falling",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
+ .edge_type = IRQ_TYPE_EDGE_FALLING,
+ },
+ {
+ .name = "external_any",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
+ .edge_type = IRQ_TYPE_EDGE_BOTH,
+ },
+};
+
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
@@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
+ IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
+ + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
+};
+
+static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+ u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
+ u8 bit;
+
+ /* clear TRGMOD */
+ status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
+
+ if (state)
+ status |= st->selected_trig->trgmod_value;
+
+ /* set/unset hw trigger */
+ at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ if (state) {
+ at91_adc_writel(st, AT91_SAMA5D2_CHER,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_IER,
+ BIT(chan->channel));
+ } else {
+ at91_adc_writel(st, AT91_SAMA5D2_IDR,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_CHDR,
+ BIT(chan->channel));
+ }
+ }
+
+ return 0;
+}
+
+static int at91_adc_reenable_trigger(struct iio_trigger *trig)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+
+ enable_irq(st->irq);
+
+ /* Needed to ACK the DRDY interruption */
+ at91_adc_readl(st, AT91_SAMA5D2_LCDR);
+ return 0;
+}
+
+static const struct iio_trigger_ops at91_adc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &at91_adc_configure_trigger,
+ .try_reenable = &at91_adc_reenable_trigger,
};
+static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
+ char *trigger_name)
+{
+ struct iio_trigger *trig;
+ int ret;
+
+ trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
+ indio->id, trigger_name);
+ if (!trig)
+ return NULL;
+
+ trig->dev.parent = indio->dev.parent;
+ iio_trigger_set_drvdata(trig, indio);
+ trig->ops = &at91_adc_trigger_ops;
+
+ ret = devm_iio_trigger_register(&indio->dev, trig);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return trig;
+}
+
+static int at91_adc_trigger_init(struct iio_dev *indio)
+{
+ struct at91_adc_state *st = iio_priv(indio);
+
+ st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
+ if (IS_ERR(st->trig)) {
+ dev_err(&indio->dev,
+ "could not allocate trigger\n");
+ return PTR_ERR(st->trig);
+ }
+
+ return 0;
+}
+
+static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio = pf->indio_dev;
+ struct at91_adc_state *st = iio_priv(indio);
+ int i = 0;
+ u8 bit;
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ st->buffer[i] = at91_adc_readl(st, chan->address);
+ i++;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
+
+ iio_trigger_notify_done(indio->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int at91_adc_buffer_init(struct iio_dev *indio)
+{
+ return devm_iio_triggered_buffer_setup(&indio->dev, indio,
+ &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, NULL);
+}
+
static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz)
{
@@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
- if (status & imr) {
+ if (!(status & imr))
+ return IRQ_NONE;
+
+ if (iio_buffer_enabled(indio)) {
+ disable_irq_nosync(irq);
+ iio_trigger_poll(indio->trig);
+ } else {
st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available);
- return IRQ_HANDLED;
}
-
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static int at91_adc_read_raw(struct iio_dev *indio_dev,
@@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ /* we cannot use software trigger if hw trigger enabled */
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
mutex_lock(&st->lock);
st->chan = chan;
@@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
mutex_unlock(&st->lock);
+
+ iio_device_release_direct_mode(indio_dev);
return ret;
case IIO_CHAN_INFO_SCALE:
@@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
- int ret;
+ int ret, i;
+ u32 edge_type;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
@@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "atmel,trigger-edge-type", &edge_type);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,trigger-edge-type\n");
+ return ret;
+ }
+
+ st->selected_trig = NULL;
+
+ for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
+ if (at91_adc_trigger_list[i].edge_type == edge_type) {
+ st->selected_trig = &at91_adc_trigger_list[i];
+ break;
+ }
+
+ if (!st->selected_trig) {
+ dev_err(&pdev->dev, "invalid external trigger edge value\n");
+ return -EINVAL;
+ }
+
init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock);
@@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
+ ret = at91_adc_buffer_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
+ goto per_clk_disable_unprepare;
+ }
+
+ ret = at91_adc_trigger_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't setup the triggers.\n");
+ goto per_clk_disable_unprepare;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
+ dev_info(&pdev->dev, "setting up trigger as %s\n",
+ st->selected_trig->name);
+
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
jic23, robh
Cc: eugen.hristev
Added support for the external hardware trigger on pin ADTRG,
integrated the three possible edges into the driver
and created buffer management for data retrieval
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
1 file changed, 232 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index e10dca3..1773a5d 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -25,6 +25,10 @@
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h>
/* Control Register */
@@ -132,6 +136,17 @@
#define AT91_SAMA5D2_PRESSR 0xbc
/* Trigger Register */
#define AT91_SAMA5D2_TRGR 0xc0
+/* Mask for TRGMOD field of TRGR register */
+#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
+/* No trigger, only software trigger can start conversions */
+#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
+/* Trigger Mode external trigger rising edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
+/* Trigger Mode external trigger falling edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
+/* Trigger Mode external trigger any edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
+
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
@@ -145,14 +160,29 @@
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
+#define AT91_SAMA5D2_HW_TRIG_CNT 3
+#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
+#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
+
+/*
+ * Maximum number of bytes to hold conversion from all channels
+ * plus the timestamp
+ */
+#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
+ AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
+
+#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
+
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
.address = addr, \
+ .scan_index = num, \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -168,9 +198,11 @@
.channel = num, \
.channel2 = num2, \
.address = addr, \
+ .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -188,6 +220,12 @@ struct at91_adc_soc_info {
unsigned max_sample_rate;
};
+struct at91_adc_trigger {
+ char *name;
+ unsigned int trgmod_value;
+ unsigned int edge_type;
+};
+
struct at91_adc_state {
void __iomem *base;
int irq;
@@ -195,11 +233,14 @@ struct at91_adc_state {
struct regulator *reg;
struct regulator *vref;
int vref_uv;
+ struct iio_trigger *trig;
+ const struct at91_adc_trigger *selected_trig;
const struct iio_chan_spec *chan;
bool conversion_done;
u32 conversion_value;
struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available;
+ u16 buffer[AT91_BUFFER_MAX_HWORDS];
/*
* lock to prevent concurrent 'single conversion' requests through
* sysfs.
@@ -207,6 +248,24 @@ struct at91_adc_state {
struct mutex lock;
};
+static const struct at91_adc_trigger at91_adc_trigger_list[] = {
+ {
+ .name = "external_rising",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
+ .edge_type = IRQ_TYPE_EDGE_RISING,
+ },
+ {
+ .name = "external_falling",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
+ .edge_type = IRQ_TYPE_EDGE_FALLING,
+ },
+ {
+ .name = "external_any",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
+ .edge_type = IRQ_TYPE_EDGE_BOTH,
+ },
+};
+
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
@@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
+ IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
+ + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
+};
+
+static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+ u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
+ u8 bit;
+
+ /* clear TRGMOD */
+ status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
+
+ if (state)
+ status |= st->selected_trig->trgmod_value;
+
+ /* set/unset hw trigger */
+ at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ if (state) {
+ at91_adc_writel(st, AT91_SAMA5D2_CHER,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_IER,
+ BIT(chan->channel));
+ } else {
+ at91_adc_writel(st, AT91_SAMA5D2_IDR,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_CHDR,
+ BIT(chan->channel));
+ }
+ }
+
+ return 0;
+}
+
+static int at91_adc_reenable_trigger(struct iio_trigger *trig)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+
+ enable_irq(st->irq);
+
+ /* Needed to ACK the DRDY interruption */
+ at91_adc_readl(st, AT91_SAMA5D2_LCDR);
+ return 0;
+}
+
+static const struct iio_trigger_ops at91_adc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &at91_adc_configure_trigger,
+ .try_reenable = &at91_adc_reenable_trigger,
};
+static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
+ char *trigger_name)
+{
+ struct iio_trigger *trig;
+ int ret;
+
+ trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
+ indio->id, trigger_name);
+ if (!trig)
+ return NULL;
+
+ trig->dev.parent = indio->dev.parent;
+ iio_trigger_set_drvdata(trig, indio);
+ trig->ops = &at91_adc_trigger_ops;
+
+ ret = devm_iio_trigger_register(&indio->dev, trig);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return trig;
+}
+
+static int at91_adc_trigger_init(struct iio_dev *indio)
+{
+ struct at91_adc_state *st = iio_priv(indio);
+
+ st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
+ if (IS_ERR(st->trig)) {
+ dev_err(&indio->dev,
+ "could not allocate trigger\n");
+ return PTR_ERR(st->trig);
+ }
+
+ return 0;
+}
+
+static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio = pf->indio_dev;
+ struct at91_adc_state *st = iio_priv(indio);
+ int i = 0;
+ u8 bit;
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ st->buffer[i] = at91_adc_readl(st, chan->address);
+ i++;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
+
+ iio_trigger_notify_done(indio->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int at91_adc_buffer_init(struct iio_dev *indio)
+{
+ return devm_iio_triggered_buffer_setup(&indio->dev, indio,
+ &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, NULL);
+}
+
static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz)
{
@@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
- if (status & imr) {
+ if (!(status & imr))
+ return IRQ_NONE;
+
+ if (iio_buffer_enabled(indio)) {
+ disable_irq_nosync(irq);
+ iio_trigger_poll(indio->trig);
+ } else {
st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available);
- return IRQ_HANDLED;
}
-
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static int at91_adc_read_raw(struct iio_dev *indio_dev,
@@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ /* we cannot use software trigger if hw trigger enabled */
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
mutex_lock(&st->lock);
st->chan = chan;
@@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
mutex_unlock(&st->lock);
+
+ iio_device_release_direct_mode(indio_dev);
return ret;
case IIO_CHAN_INFO_SCALE:
@@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
- int ret;
+ int ret, i;
+ u32 edge_type;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
@@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "atmel,trigger-edge-type", &edge_type);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,trigger-edge-type\n");
+ return ret;
+ }
+
+ st->selected_trig = NULL;
+
+ for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
+ if (at91_adc_trigger_list[i].edge_type == edge_type) {
+ st->selected_trig = &at91_adc_trigger_list[i];
+ break;
+ }
+
+ if (!st->selected_trig) {
+ dev_err(&pdev->dev, "invalid external trigger edge value\n");
+ return -EINVAL;
+ }
+
init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock);
@@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
+ ret = at91_adc_buffer_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
+ goto per_clk_disable_unprepare;
+ }
+
+ ret = at91_adc_trigger_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't setup the triggers.\n");
+ goto per_clk_disable_unprepare;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
+ dev_info(&pdev->dev, "setting up trigger as %s\n",
+ st->selected_trig->name);
+
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
@ 2017-06-15 13:24 ` Eugen Hristev
0 siblings, 0 replies; 33+ messages in thread
From: Eugen Hristev @ 2017-06-15 13:24 UTC (permalink / raw)
To: linux-arm-kernel
Added support for the external hardware trigger on pin ADTRG,
integrated the three possible edges into the driver
and created buffer management for data retrieval
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
Changes in v5:
- Moved DRDY ack in tryreenable function
- Used PTR_ERR to pass error code to probe
Changes in v4:
- Used iio claim direct to make sure buffer is not enabled when someone might
try to use a software triggered conversion
Changes in v3:
- No longer have all three possible triggers registered in the subsystem and
available in the sysfs. Only registering one trigger, and the possible edge
is being read from the device tree. In the device tree, any possible edge
can be set. There are three already made nodes for each possible edge which
can be selected.
- Fixed a bug where software triggered conversion could be started even if
the hardware trigger was enabled.
- Preallocate enough space for the buffer, considering all the channels
and timestamp
Changes in v2:
- Moved buffer allocation and freeing into the preenable and postdisable
callbacks.
We have a total of scan bytes that can vary a lot depending on each channel
enabled at a certain point.
- made the at91 trigger list part of state structure
- made the iio trigger list preallocated in state structure
- moved irq enabling/disabling into the try_reenable callback
- on trigger disable must write disable registries as well
drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
1 file changed, 232 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index e10dca3..1773a5d 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -25,6 +25,10 @@
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h>
/* Control Register */
@@ -132,6 +136,17 @@
#define AT91_SAMA5D2_PRESSR 0xbc
/* Trigger Register */
#define AT91_SAMA5D2_TRGR 0xc0
+/* Mask for TRGMOD field of TRGR register */
+#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
+/* No trigger, only software trigger can start conversions */
+#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
+/* Trigger Mode external trigger rising edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
+/* Trigger Mode external trigger falling edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
+/* Trigger Mode external trigger any edge */
+#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
+
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
@@ -145,14 +160,29 @@
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
+#define AT91_SAMA5D2_HW_TRIG_CNT 3
+#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
+#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
+
+/*
+ * Maximum number of bytes to hold conversion from all channels
+ * plus the timestamp
+ */
+#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
+ AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
+
+#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
+
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
.address = addr, \
+ .scan_index = num, \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -168,9 +198,11 @@
.channel = num, \
.channel2 = num2, \
.address = addr, \
+ .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
+ .storagebits = 16, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -188,6 +220,12 @@ struct at91_adc_soc_info {
unsigned max_sample_rate;
};
+struct at91_adc_trigger {
+ char *name;
+ unsigned int trgmod_value;
+ unsigned int edge_type;
+};
+
struct at91_adc_state {
void __iomem *base;
int irq;
@@ -195,11 +233,14 @@ struct at91_adc_state {
struct regulator *reg;
struct regulator *vref;
int vref_uv;
+ struct iio_trigger *trig;
+ const struct at91_adc_trigger *selected_trig;
const struct iio_chan_spec *chan;
bool conversion_done;
u32 conversion_value;
struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available;
+ u16 buffer[AT91_BUFFER_MAX_HWORDS];
/*
* lock to prevent concurrent 'single conversion' requests through
* sysfs.
@@ -207,6 +248,24 @@ struct at91_adc_state {
struct mutex lock;
};
+static const struct at91_adc_trigger at91_adc_trigger_list[] = {
+ {
+ .name = "external_rising",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
+ .edge_type = IRQ_TYPE_EDGE_RISING,
+ },
+ {
+ .name = "external_falling",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
+ .edge_type = IRQ_TYPE_EDGE_FALLING,
+ },
+ {
+ .name = "external_any",
+ .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
+ .edge_type = IRQ_TYPE_EDGE_BOTH,
+ },
+};
+
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
@@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
+ IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
+ + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
+};
+
+static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+ u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
+ u8 bit;
+
+ /* clear TRGMOD */
+ status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
+
+ if (state)
+ status |= st->selected_trig->trgmod_value;
+
+ /* set/unset hw trigger */
+ at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ if (state) {
+ at91_adc_writel(st, AT91_SAMA5D2_CHER,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_IER,
+ BIT(chan->channel));
+ } else {
+ at91_adc_writel(st, AT91_SAMA5D2_IDR,
+ BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_CHDR,
+ BIT(chan->channel));
+ }
+ }
+
+ return 0;
+}
+
+static int at91_adc_reenable_trigger(struct iio_trigger *trig)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+
+ enable_irq(st->irq);
+
+ /* Needed to ACK the DRDY interruption */
+ at91_adc_readl(st, AT91_SAMA5D2_LCDR);
+ return 0;
+}
+
+static const struct iio_trigger_ops at91_adc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &at91_adc_configure_trigger,
+ .try_reenable = &at91_adc_reenable_trigger,
};
+static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
+ char *trigger_name)
+{
+ struct iio_trigger *trig;
+ int ret;
+
+ trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
+ indio->id, trigger_name);
+ if (!trig)
+ return NULL;
+
+ trig->dev.parent = indio->dev.parent;
+ iio_trigger_set_drvdata(trig, indio);
+ trig->ops = &at91_adc_trigger_ops;
+
+ ret = devm_iio_trigger_register(&indio->dev, trig);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return trig;
+}
+
+static int at91_adc_trigger_init(struct iio_dev *indio)
+{
+ struct at91_adc_state *st = iio_priv(indio);
+
+ st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
+ if (IS_ERR(st->trig)) {
+ dev_err(&indio->dev,
+ "could not allocate trigger\n");
+ return PTR_ERR(st->trig);
+ }
+
+ return 0;
+}
+
+static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio = pf->indio_dev;
+ struct at91_adc_state *st = iio_priv(indio);
+ int i = 0;
+ u8 bit;
+
+ for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
+ struct iio_chan_spec const *chan = indio->channels + bit;
+
+ st->buffer[i] = at91_adc_readl(st, chan->address);
+ i++;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
+
+ iio_trigger_notify_done(indio->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int at91_adc_buffer_init(struct iio_dev *indio)
+{
+ return devm_iio_triggered_buffer_setup(&indio->dev, indio,
+ &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, NULL);
+}
+
static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz)
{
@@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
- if (status & imr) {
+ if (!(status & imr))
+ return IRQ_NONE;
+
+ if (iio_buffer_enabled(indio)) {
+ disable_irq_nosync(irq);
+ iio_trigger_poll(indio->trig);
+ } else {
st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available);
- return IRQ_HANDLED;
}
-
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static int at91_adc_read_raw(struct iio_dev *indio_dev,
@@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ /* we cannot use software trigger if hw trigger enabled */
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
mutex_lock(&st->lock);
st->chan = chan;
@@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
mutex_unlock(&st->lock);
+
+ iio_device_release_direct_mode(indio_dev);
return ret;
case IIO_CHAN_INFO_SCALE:
@@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
- int ret;
+ int ret, i;
+ u32 edge_type;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
@@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "atmel,trigger-edge-type", &edge_type);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,trigger-edge-type\n");
+ return ret;
+ }
+
+ st->selected_trig = NULL;
+
+ for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
+ if (at91_adc_trigger_list[i].edge_type == edge_type) {
+ st->selected_trig = &at91_adc_trigger_list[i];
+ break;
+ }
+
+ if (!st->selected_trig) {
+ dev_err(&pdev->dev, "invalid external trigger edge value\n");
+ return -EINVAL;
+ }
+
init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock);
@@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
+ ret = at91_adc_buffer_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
+ goto per_clk_disable_unprepare;
+ }
+
+ ret = at91_adc_trigger_init(indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "couldn't setup the triggers.\n");
+ goto per_clk_disable_unprepare;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
+ dev_info(&pdev->dev, "setting up trigger as %s\n",
+ st->selected_trig->name);
+
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
--
2.7.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-20 16:53 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:53 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
robh
On Thu, 15 Jun 2017 16:24:55 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Add property for the edge type of the hardware trigger pin ADTRG
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> index 3223684..552e7a8 100644
> --- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> +++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> @@ -11,6 +11,11 @@ Required properties:
> - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
> - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
> - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
> + - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
> + trigger pin. When the specific edge type is detected, the conversion will
> + start. Possible values are rising, falling, or both.
> + This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
> + IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
>
> Example:
>
> @@ -25,4 +30,5 @@ adc: adc@fc030000 {
> atmel,startup-time-ms = <4>;
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-20 16:53 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:53 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On Thu, 15 Jun 2017 16:24:55 +0300
Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
> Add property for the edge type of the hardware trigger pin ADTRG
>
> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> index 3223684..552e7a8 100644
> --- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> +++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> @@ -11,6 +11,11 @@ Required properties:
> - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
> - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
> - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
> + - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
> + trigger pin. When the specific edge type is detected, the conversion will
> + start. Possible values are rising, falling, or both.
> + This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
> + IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
>
> Example:
>
> @@ -25,4 +30,5 @@ adc: adc@fc030000 {
> atmel,startup-time-ms = <4>;
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding
@ 2017-06-20 16:53 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:53 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Jun 2017 16:24:55 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Add property for the edge type of the hardware trigger pin ADTRG
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> index 3223684..552e7a8 100644
> --- a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> +++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
> @@ -11,6 +11,11 @@ Required properties:
> - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
> - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
> - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
> + - atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
> + trigger pin. When the specific edge type is detected, the conversion will
> + start. Possible values are rising, falling, or both.
> + This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
> + IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
>
> Example:
>
> @@ -25,4 +30,5 @@ adc: adc at fc030000 {
> atmel,startup-time-ms = <4>;
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
robh
On Thu, 15 Jun 2017 16:24:57 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Added support for the external hardware trigger on pin ADTRG,
> integrated the three possible edges into the driver
> and created buffer management for data retrieval
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Applied to the togreg branch of iio.git and pushed out as
testing for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v5:
> - Moved DRDY ack in tryreenable function
> - Used PTR_ERR to pass error code to probe
>
> Changes in v4:
> - Used iio claim direct to make sure buffer is not enabled when someone might
> try to use a software triggered conversion
>
> Changes in v3:
> - No longer have all three possible triggers registered in the subsystem and
> available in the sysfs. Only registering one trigger, and the possible edge
> is being read from the device tree. In the device tree, any possible edge
> can be set. There are three already made nodes for each possible edge which
> can be selected.
> - Fixed a bug where software triggered conversion could be started even if
> the hardware trigger was enabled.
> - Preallocate enough space for the buffer, considering all the channels
> and timestamp
>
> Changes in v2:
> - Moved buffer allocation and freeing into the preenable and postdisable
> callbacks.
> We have a total of scan bytes that can vary a lot depending on each channel
> enabled at a certain point.
> - made the at91 trigger list part of state structure
> - made the iio trigger list preallocated in state structure
> - moved irq enabling/disabling into the try_reenable callback
> - on trigger disable must write disable registries as well
>
> drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 232 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
> index e10dca3..1773a5d 100644
> --- a/drivers/iio/adc/at91-sama5d2_adc.c
> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
> @@ -25,6 +25,10 @@
> #include <linux/wait.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> #include <linux/regulator/consumer.h>
>
> /* Control Register */
> @@ -132,6 +136,17 @@
> #define AT91_SAMA5D2_PRESSR 0xbc
> /* Trigger Register */
> #define AT91_SAMA5D2_TRGR 0xc0
> +/* Mask for TRGMOD field of TRGR register */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
> +/* No trigger, only software trigger can start conversions */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
> +/* Trigger Mode external trigger rising edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
> +/* Trigger Mode external trigger falling edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
> +/* Trigger Mode external trigger any edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
> +
> /* Correction Select Register */
> #define AT91_SAMA5D2_COSR 0xd0
> /* Correction Value Register */
> @@ -145,14 +160,29 @@
> /* Version Register */
> #define AT91_SAMA5D2_VERSION 0xfc
>
> +#define AT91_SAMA5D2_HW_TRIG_CNT 3
> +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
> +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
> +
> +/*
> + * Maximum number of bytes to hold conversion from all channels
> + * plus the timestamp
> + */
> +#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
> + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
> +
> +#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
> +
> #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
> { \
> .type = IIO_VOLTAGE, \
> .channel = num, \
> .address = addr, \
> + .scan_index = num, \
> .scan_type = { \
> .sign = 'u', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -168,9 +198,11 @@
> .channel = num, \
> .channel2 = num2, \
> .address = addr, \
> + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
> .scan_type = { \
> .sign = 's', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -188,6 +220,12 @@ struct at91_adc_soc_info {
> unsigned max_sample_rate;
> };
>
> +struct at91_adc_trigger {
> + char *name;
> + unsigned int trgmod_value;
> + unsigned int edge_type;
> +};
> +
> struct at91_adc_state {
> void __iomem *base;
> int irq;
> @@ -195,11 +233,14 @@ struct at91_adc_state {
> struct regulator *reg;
> struct regulator *vref;
> int vref_uv;
> + struct iio_trigger *trig;
> + const struct at91_adc_trigger *selected_trig;
> const struct iio_chan_spec *chan;
> bool conversion_done;
> u32 conversion_value;
> struct at91_adc_soc_info soc_info;
> wait_queue_head_t wq_data_available;
> + u16 buffer[AT91_BUFFER_MAX_HWORDS];
> /*
> * lock to prevent concurrent 'single conversion' requests through
> * sysfs.
> @@ -207,6 +248,24 @@ struct at91_adc_state {
> struct mutex lock;
> };
>
> +static const struct at91_adc_trigger at91_adc_trigger_list[] = {
> + {
> + .name = "external_rising",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
> + .edge_type = IRQ_TYPE_EDGE_RISING,
> + },
> + {
> + .name = "external_falling",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
> + .edge_type = IRQ_TYPE_EDGE_FALLING,
> + },
> + {
> + .name = "external_any",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
> + .edge_type = IRQ_TYPE_EDGE_BOTH,
> + },
> +};
> +
> static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
> AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
> @@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
> AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
> AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
> + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
> + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
> +};
> +
> +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
> + u8 bit;
> +
> + /* clear TRGMOD */
> + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
> +
> + if (state)
> + status |= st->selected_trig->trgmod_value;
> +
> + /* set/unset hw trigger */
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + if (state) {
> + at91_adc_writel(st, AT91_SAMA5D2_CHER,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_IER,
> + BIT(chan->channel));
> + } else {
> + at91_adc_writel(st, AT91_SAMA5D2_IDR,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_CHDR,
> + BIT(chan->channel));
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int at91_adc_reenable_trigger(struct iio_trigger *trig)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + enable_irq(st->irq);
> +
> + /* Needed to ACK the DRDY interruption */
> + at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> + return 0;
> +}
> +
> +static const struct iio_trigger_ops at91_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> + .set_trigger_state = &at91_adc_configure_trigger,
> + .try_reenable = &at91_adc_reenable_trigger,
> };
>
> +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
> + char *trigger_name)
> +{
> + struct iio_trigger *trig;
> + int ret;
> +
> + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
> + indio->id, trigger_name);
> + if (!trig)
> + return NULL;
> +
> + trig->dev.parent = indio->dev.parent;
> + iio_trigger_set_drvdata(trig, indio);
> + trig->ops = &at91_adc_trigger_ops;
> +
> + ret = devm_iio_trigger_register(&indio->dev, trig);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return trig;
> +}
> +
> +static int at91_adc_trigger_init(struct iio_dev *indio)
> +{
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
> + if (IS_ERR(st->trig)) {
> + dev_err(&indio->dev,
> + "could not allocate trigger\n");
> + return PTR_ERR(st->trig);
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio = pf->indio_dev;
> + struct at91_adc_state *st = iio_priv(indio);
> + int i = 0;
> + u8 bit;
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + st->buffer[i] = at91_adc_readl(st, chan->address);
> + i++;
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
> +
> + iio_trigger_notify_done(indio->trig);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int at91_adc_buffer_init(struct iio_dev *indio)
> +{
> + return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> + &iio_pollfunc_store_time,
> + &at91_adc_trigger_handler, NULL);
> +}
> +
> static unsigned at91_adc_startup_time(unsigned startup_time_min,
> unsigned adc_clk_khz)
> {
> @@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
> u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
>
> - if (status & imr) {
> + if (!(status & imr))
> + return IRQ_NONE;
> +
> + if (iio_buffer_enabled(indio)) {
> + disable_irq_nosync(irq);
> + iio_trigger_poll(indio->trig);
> + } else {
> st->conversion_value = at91_adc_readl(st, st->chan->address);
> st->conversion_done = true;
> wake_up_interruptible(&st->wq_data_available);
> - return IRQ_HANDLED;
> }
> -
> - return IRQ_NONE;
> + return IRQ_HANDLED;
> }
>
> static int at91_adc_read_raw(struct iio_dev *indio_dev,
> @@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
>
> switch (mask) {
> case IIO_CHAN_INFO_RAW:
> + /* we cannot use software trigger if hw trigger enabled */
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> +
> mutex_lock(&st->lock);
>
> st->chan = chan;
> @@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
> at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
>
> mutex_unlock(&st->lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> return ret;
>
> case IIO_CHAN_INFO_SCALE:
> @@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
> struct iio_dev *indio_dev;
> struct at91_adc_state *st;
> struct resource *res;
> - int ret;
> + int ret, i;
> + u32 edge_type;
>
> indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
> if (!indio_dev)
> @@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
> return ret;
> }
>
> + ret = of_property_read_u32(pdev->dev.of_node,
> + "atmel,trigger-edge-type", &edge_type);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "invalid or missing value for atmel,trigger-edge-type\n");
> + return ret;
> + }
> +
> + st->selected_trig = NULL;
> +
> + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
> + if (at91_adc_trigger_list[i].edge_type == edge_type) {
> + st->selected_trig = &at91_adc_trigger_list[i];
> + break;
> + }
> +
> + if (!st->selected_trig) {
> + dev_err(&pdev->dev, "invalid external trigger edge value\n");
> + return -EINVAL;
> + }
> +
> init_waitqueue_head(&st->wq_data_available);
> mutex_init(&st->lock);
>
> @@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> + ret = at91_adc_buffer_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> + ret = at91_adc_trigger_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't setup the triggers.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> ret = iio_device_register(indio_dev);
> if (ret < 0)
> goto per_clk_disable_unprepare;
>
> + dev_info(&pdev->dev, "setting up trigger as %s\n",
> + st->selected_trig->name);
> +
> dev_info(&pdev->dev, "version: %x\n",
> readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On Thu, 15 Jun 2017 16:24:57 +0300
Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
> Added support for the external hardware trigger on pin ADTRG,
> integrated the three possible edges into the driver
> and created buffer management for data retrieval
>
> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Applied to the togreg branch of iio.git and pushed out as
testing for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v5:
> - Moved DRDY ack in tryreenable function
> - Used PTR_ERR to pass error code to probe
>
> Changes in v4:
> - Used iio claim direct to make sure buffer is not enabled when someone might
> try to use a software triggered conversion
>
> Changes in v3:
> - No longer have all three possible triggers registered in the subsystem and
> available in the sysfs. Only registering one trigger, and the possible edge
> is being read from the device tree. In the device tree, any possible edge
> can be set. There are three already made nodes for each possible edge which
> can be selected.
> - Fixed a bug where software triggered conversion could be started even if
> the hardware trigger was enabled.
> - Preallocate enough space for the buffer, considering all the channels
> and timestamp
>
> Changes in v2:
> - Moved buffer allocation and freeing into the preenable and postdisable
> callbacks.
> We have a total of scan bytes that can vary a lot depending on each channel
> enabled at a certain point.
> - made the at91 trigger list part of state structure
> - made the iio trigger list preallocated in state structure
> - moved irq enabling/disabling into the try_reenable callback
> - on trigger disable must write disable registries as well
>
> drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 232 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
> index e10dca3..1773a5d 100644
> --- a/drivers/iio/adc/at91-sama5d2_adc.c
> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
> @@ -25,6 +25,10 @@
> #include <linux/wait.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> #include <linux/regulator/consumer.h>
>
> /* Control Register */
> @@ -132,6 +136,17 @@
> #define AT91_SAMA5D2_PRESSR 0xbc
> /* Trigger Register */
> #define AT91_SAMA5D2_TRGR 0xc0
> +/* Mask for TRGMOD field of TRGR register */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
> +/* No trigger, only software trigger can start conversions */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
> +/* Trigger Mode external trigger rising edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
> +/* Trigger Mode external trigger falling edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
> +/* Trigger Mode external trigger any edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
> +
> /* Correction Select Register */
> #define AT91_SAMA5D2_COSR 0xd0
> /* Correction Value Register */
> @@ -145,14 +160,29 @@
> /* Version Register */
> #define AT91_SAMA5D2_VERSION 0xfc
>
> +#define AT91_SAMA5D2_HW_TRIG_CNT 3
> +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
> +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
> +
> +/*
> + * Maximum number of bytes to hold conversion from all channels
> + * plus the timestamp
> + */
> +#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
> + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
> +
> +#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
> +
> #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
> { \
> .type = IIO_VOLTAGE, \
> .channel = num, \
> .address = addr, \
> + .scan_index = num, \
> .scan_type = { \
> .sign = 'u', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -168,9 +198,11 @@
> .channel = num, \
> .channel2 = num2, \
> .address = addr, \
> + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
> .scan_type = { \
> .sign = 's', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -188,6 +220,12 @@ struct at91_adc_soc_info {
> unsigned max_sample_rate;
> };
>
> +struct at91_adc_trigger {
> + char *name;
> + unsigned int trgmod_value;
> + unsigned int edge_type;
> +};
> +
> struct at91_adc_state {
> void __iomem *base;
> int irq;
> @@ -195,11 +233,14 @@ struct at91_adc_state {
> struct regulator *reg;
> struct regulator *vref;
> int vref_uv;
> + struct iio_trigger *trig;
> + const struct at91_adc_trigger *selected_trig;
> const struct iio_chan_spec *chan;
> bool conversion_done;
> u32 conversion_value;
> struct at91_adc_soc_info soc_info;
> wait_queue_head_t wq_data_available;
> + u16 buffer[AT91_BUFFER_MAX_HWORDS];
> /*
> * lock to prevent concurrent 'single conversion' requests through
> * sysfs.
> @@ -207,6 +248,24 @@ struct at91_adc_state {
> struct mutex lock;
> };
>
> +static const struct at91_adc_trigger at91_adc_trigger_list[] = {
> + {
> + .name = "external_rising",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
> + .edge_type = IRQ_TYPE_EDGE_RISING,
> + },
> + {
> + .name = "external_falling",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
> + .edge_type = IRQ_TYPE_EDGE_FALLING,
> + },
> + {
> + .name = "external_any",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
> + .edge_type = IRQ_TYPE_EDGE_BOTH,
> + },
> +};
> +
> static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
> AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
> @@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
> AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
> AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
> + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
> + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
> +};
> +
> +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
> + u8 bit;
> +
> + /* clear TRGMOD */
> + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
> +
> + if (state)
> + status |= st->selected_trig->trgmod_value;
> +
> + /* set/unset hw trigger */
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + if (state) {
> + at91_adc_writel(st, AT91_SAMA5D2_CHER,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_IER,
> + BIT(chan->channel));
> + } else {
> + at91_adc_writel(st, AT91_SAMA5D2_IDR,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_CHDR,
> + BIT(chan->channel));
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int at91_adc_reenable_trigger(struct iio_trigger *trig)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + enable_irq(st->irq);
> +
> + /* Needed to ACK the DRDY interruption */
> + at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> + return 0;
> +}
> +
> +static const struct iio_trigger_ops at91_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> + .set_trigger_state = &at91_adc_configure_trigger,
> + .try_reenable = &at91_adc_reenable_trigger,
> };
>
> +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
> + char *trigger_name)
> +{
> + struct iio_trigger *trig;
> + int ret;
> +
> + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
> + indio->id, trigger_name);
> + if (!trig)
> + return NULL;
> +
> + trig->dev.parent = indio->dev.parent;
> + iio_trigger_set_drvdata(trig, indio);
> + trig->ops = &at91_adc_trigger_ops;
> +
> + ret = devm_iio_trigger_register(&indio->dev, trig);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return trig;
> +}
> +
> +static int at91_adc_trigger_init(struct iio_dev *indio)
> +{
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
> + if (IS_ERR(st->trig)) {
> + dev_err(&indio->dev,
> + "could not allocate trigger\n");
> + return PTR_ERR(st->trig);
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio = pf->indio_dev;
> + struct at91_adc_state *st = iio_priv(indio);
> + int i = 0;
> + u8 bit;
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + st->buffer[i] = at91_adc_readl(st, chan->address);
> + i++;
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
> +
> + iio_trigger_notify_done(indio->trig);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int at91_adc_buffer_init(struct iio_dev *indio)
> +{
> + return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> + &iio_pollfunc_store_time,
> + &at91_adc_trigger_handler, NULL);
> +}
> +
> static unsigned at91_adc_startup_time(unsigned startup_time_min,
> unsigned adc_clk_khz)
> {
> @@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
> u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
>
> - if (status & imr) {
> + if (!(status & imr))
> + return IRQ_NONE;
> +
> + if (iio_buffer_enabled(indio)) {
> + disable_irq_nosync(irq);
> + iio_trigger_poll(indio->trig);
> + } else {
> st->conversion_value = at91_adc_readl(st, st->chan->address);
> st->conversion_done = true;
> wake_up_interruptible(&st->wq_data_available);
> - return IRQ_HANDLED;
> }
> -
> - return IRQ_NONE;
> + return IRQ_HANDLED;
> }
>
> static int at91_adc_read_raw(struct iio_dev *indio_dev,
> @@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
>
> switch (mask) {
> case IIO_CHAN_INFO_RAW:
> + /* we cannot use software trigger if hw trigger enabled */
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> +
> mutex_lock(&st->lock);
>
> st->chan = chan;
> @@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
> at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
>
> mutex_unlock(&st->lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> return ret;
>
> case IIO_CHAN_INFO_SCALE:
> @@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
> struct iio_dev *indio_dev;
> struct at91_adc_state *st;
> struct resource *res;
> - int ret;
> + int ret, i;
> + u32 edge_type;
>
> indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
> if (!indio_dev)
> @@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
> return ret;
> }
>
> + ret = of_property_read_u32(pdev->dev.of_node,
> + "atmel,trigger-edge-type", &edge_type);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "invalid or missing value for atmel,trigger-edge-type\n");
> + return ret;
> + }
> +
> + st->selected_trig = NULL;
> +
> + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
> + if (at91_adc_trigger_list[i].edge_type == edge_type) {
> + st->selected_trig = &at91_adc_trigger_list[i];
> + break;
> + }
> +
> + if (!st->selected_trig) {
> + dev_err(&pdev->dev, "invalid external trigger edge value\n");
> + return -EINVAL;
> + }
> +
> init_waitqueue_head(&st->wq_data_available);
> mutex_init(&st->lock);
>
> @@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> + ret = at91_adc_buffer_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> + ret = at91_adc_trigger_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't setup the triggers.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> ret = iio_device_register(indio_dev);
> if (ret < 0)
> goto per_clk_disable_unprepare;
>
> + dev_info(&pdev->dev, "setting up trigger as %s\n",
> + st->selected_trig->name);
> +
> dev_info(&pdev->dev, "version: %x\n",
> readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Jun 2017 16:24:57 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Added support for the external hardware trigger on pin ADTRG,
> integrated the three possible edges into the driver
> and created buffer management for data retrieval
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Applied to the togreg branch of iio.git and pushed out as
testing for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> Changes in v5:
> - Moved DRDY ack in tryreenable function
> - Used PTR_ERR to pass error code to probe
>
> Changes in v4:
> - Used iio claim direct to make sure buffer is not enabled when someone might
> try to use a software triggered conversion
>
> Changes in v3:
> - No longer have all three possible triggers registered in the subsystem and
> available in the sysfs. Only registering one trigger, and the possible edge
> is being read from the device tree. In the device tree, any possible edge
> can be set. There are three already made nodes for each possible edge which
> can be selected.
> - Fixed a bug where software triggered conversion could be started even if
> the hardware trigger was enabled.
> - Preallocate enough space for the buffer, considering all the channels
> and timestamp
>
> Changes in v2:
> - Moved buffer allocation and freeing into the preenable and postdisable
> callbacks.
> We have a total of scan bytes that can vary a lot depending on each channel
> enabled at a certain point.
> - made the at91 trigger list part of state structure
> - made the iio trigger list preallocated in state structure
> - moved irq enabling/disabling into the try_reenable callback
> - on trigger disable must write disable registries as well
>
> drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 232 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
> index e10dca3..1773a5d 100644
> --- a/drivers/iio/adc/at91-sama5d2_adc.c
> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
> @@ -25,6 +25,10 @@
> #include <linux/wait.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> #include <linux/regulator/consumer.h>
>
> /* Control Register */
> @@ -132,6 +136,17 @@
> #define AT91_SAMA5D2_PRESSR 0xbc
> /* Trigger Register */
> #define AT91_SAMA5D2_TRGR 0xc0
> +/* Mask for TRGMOD field of TRGR register */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
> +/* No trigger, only software trigger can start conversions */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
> +/* Trigger Mode external trigger rising edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
> +/* Trigger Mode external trigger falling edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
> +/* Trigger Mode external trigger any edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
> +
> /* Correction Select Register */
> #define AT91_SAMA5D2_COSR 0xd0
> /* Correction Value Register */
> @@ -145,14 +160,29 @@
> /* Version Register */
> #define AT91_SAMA5D2_VERSION 0xfc
>
> +#define AT91_SAMA5D2_HW_TRIG_CNT 3
> +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
> +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
> +
> +/*
> + * Maximum number of bytes to hold conversion from all channels
> + * plus the timestamp
> + */
> +#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
> + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
> +
> +#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
> +
> #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
> { \
> .type = IIO_VOLTAGE, \
> .channel = num, \
> .address = addr, \
> + .scan_index = num, \
> .scan_type = { \
> .sign = 'u', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -168,9 +198,11 @@
> .channel = num, \
> .channel2 = num2, \
> .address = addr, \
> + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
> .scan_type = { \
> .sign = 's', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -188,6 +220,12 @@ struct at91_adc_soc_info {
> unsigned max_sample_rate;
> };
>
> +struct at91_adc_trigger {
> + char *name;
> + unsigned int trgmod_value;
> + unsigned int edge_type;
> +};
> +
> struct at91_adc_state {
> void __iomem *base;
> int irq;
> @@ -195,11 +233,14 @@ struct at91_adc_state {
> struct regulator *reg;
> struct regulator *vref;
> int vref_uv;
> + struct iio_trigger *trig;
> + const struct at91_adc_trigger *selected_trig;
> const struct iio_chan_spec *chan;
> bool conversion_done;
> u32 conversion_value;
> struct at91_adc_soc_info soc_info;
> wait_queue_head_t wq_data_available;
> + u16 buffer[AT91_BUFFER_MAX_HWORDS];
> /*
> * lock to prevent concurrent 'single conversion' requests through
> * sysfs.
> @@ -207,6 +248,24 @@ struct at91_adc_state {
> struct mutex lock;
> };
>
> +static const struct at91_adc_trigger at91_adc_trigger_list[] = {
> + {
> + .name = "external_rising",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
> + .edge_type = IRQ_TYPE_EDGE_RISING,
> + },
> + {
> + .name = "external_falling",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
> + .edge_type = IRQ_TYPE_EDGE_FALLING,
> + },
> + {
> + .name = "external_any",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
> + .edge_type = IRQ_TYPE_EDGE_BOTH,
> + },
> +};
> +
> static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
> AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
> @@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
> AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
> AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
> + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
> + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
> +};
> +
> +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
> + u8 bit;
> +
> + /* clear TRGMOD */
> + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
> +
> + if (state)
> + status |= st->selected_trig->trgmod_value;
> +
> + /* set/unset hw trigger */
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + if (state) {
> + at91_adc_writel(st, AT91_SAMA5D2_CHER,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_IER,
> + BIT(chan->channel));
> + } else {
> + at91_adc_writel(st, AT91_SAMA5D2_IDR,
> + BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_CHDR,
> + BIT(chan->channel));
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int at91_adc_reenable_trigger(struct iio_trigger *trig)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + enable_irq(st->irq);
> +
> + /* Needed to ACK the DRDY interruption */
> + at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> + return 0;
> +}
> +
> +static const struct iio_trigger_ops at91_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> + .set_trigger_state = &at91_adc_configure_trigger,
> + .try_reenable = &at91_adc_reenable_trigger,
> };
>
> +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
> + char *trigger_name)
> +{
> + struct iio_trigger *trig;
> + int ret;
> +
> + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
> + indio->id, trigger_name);
> + if (!trig)
> + return NULL;
> +
> + trig->dev.parent = indio->dev.parent;
> + iio_trigger_set_drvdata(trig, indio);
> + trig->ops = &at91_adc_trigger_ops;
> +
> + ret = devm_iio_trigger_register(&indio->dev, trig);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return trig;
> +}
> +
> +static int at91_adc_trigger_init(struct iio_dev *indio)
> +{
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
> + if (IS_ERR(st->trig)) {
> + dev_err(&indio->dev,
> + "could not allocate trigger\n");
> + return PTR_ERR(st->trig);
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio = pf->indio_dev;
> + struct at91_adc_state *st = iio_priv(indio);
> + int i = 0;
> + u8 bit;
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + st->buffer[i] = at91_adc_readl(st, chan->address);
> + i++;
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
> +
> + iio_trigger_notify_done(indio->trig);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int at91_adc_buffer_init(struct iio_dev *indio)
> +{
> + return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> + &iio_pollfunc_store_time,
> + &at91_adc_trigger_handler, NULL);
> +}
> +
> static unsigned at91_adc_startup_time(unsigned startup_time_min,
> unsigned adc_clk_khz)
> {
> @@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
> u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
>
> - if (status & imr) {
> + if (!(status & imr))
> + return IRQ_NONE;
> +
> + if (iio_buffer_enabled(indio)) {
> + disable_irq_nosync(irq);
> + iio_trigger_poll(indio->trig);
> + } else {
> st->conversion_value = at91_adc_readl(st, st->chan->address);
> st->conversion_done = true;
> wake_up_interruptible(&st->wq_data_available);
> - return IRQ_HANDLED;
> }
> -
> - return IRQ_NONE;
> + return IRQ_HANDLED;
> }
>
> static int at91_adc_read_raw(struct iio_dev *indio_dev,
> @@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
>
> switch (mask) {
> case IIO_CHAN_INFO_RAW:
> + /* we cannot use software trigger if hw trigger enabled */
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> +
> mutex_lock(&st->lock);
>
> st->chan = chan;
> @@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
> at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
>
> mutex_unlock(&st->lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> return ret;
>
> case IIO_CHAN_INFO_SCALE:
> @@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
> struct iio_dev *indio_dev;
> struct at91_adc_state *st;
> struct resource *res;
> - int ret;
> + int ret, i;
> + u32 edge_type;
>
> indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
> if (!indio_dev)
> @@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
> return ret;
> }
>
> + ret = of_property_read_u32(pdev->dev.of_node,
> + "atmel,trigger-edge-type", &edge_type);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "invalid or missing value for atmel,trigger-edge-type\n");
> + return ret;
> + }
> +
> + st->selected_trig = NULL;
> +
> + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
> + if (at91_adc_trigger_list[i].edge_type == edge_type) {
> + st->selected_trig = &at91_adc_trigger_list[i];
> + break;
> + }
> +
> + if (!st->selected_trig) {
> + dev_err(&pdev->dev, "invalid external trigger edge value\n");
> + return -EINVAL;
> + }
> +
> init_waitqueue_head(&st->wq_data_available);
> mutex_init(&st->lock);
>
> @@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> + ret = at91_adc_buffer_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> + ret = at91_adc_trigger_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't setup the triggers.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> ret = iio_device_register(indio_dev);
> if (ret < 0)
> goto per_clk_disable_unprepare;
>
> + dev_info(&pdev->dev, "setting up trigger as %s\n",
> + st->selected_trig->name);
> +
> dev_info(&pdev->dev, "version: %x\n",
> readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
robh
On Thu, 15 Jun 2017 16:24:54 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
The driver changes are on their way upstream.
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> index 0bef9e0..04754b1 100644
> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> @@ -303,7 +303,7 @@
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> pinctrl-names = "default";
> - pinctrl-0 = <&pinctrl_adc_default>;
> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
> status = "okay";
> };
>
> @@ -322,6 +322,20 @@
> bias-disable;
> };
>
> + /*
> + * The ADTRG pin can work on any edge type.
> + * In here it's being pulled up, so need to
> + * connect it to ground to get an edge e.g.
> + * Trigger can be configured on falling, rise
> + * or any edge, and the pull-up can be changed
> + * to pull-down or left floating according to
> + * needs.
> + */
> + pinctrl_adtrg_default: adtrg_default {
> + pinmux = <PIN_PD31__ADTRG>;
> + bias-pull-up;
> + };
> +
> pinctrl_charger_chglev: charger_chglev {
> pinmux = <PIN_PA12__GPIO>;
> bias-disable;
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On Thu, 15 Jun 2017 16:24:54 +0300
Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>
> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
The driver changes are on their way upstream.
Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> index 0bef9e0..04754b1 100644
> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> @@ -303,7 +303,7 @@
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> pinctrl-names = "default";
> - pinctrl-0 = <&pinctrl_adc_default>;
> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
> status = "okay";
> };
>
> @@ -322,6 +322,20 @@
> bias-disable;
> };
>
> + /*
> + * The ADTRG pin can work on any edge type.
> + * In here it's being pulled up, so need to
> + * connect it to ground to get an edge e.g.
> + * Trigger can be configured on falling, rise
> + * or any edge, and the pull-up can be changed
> + * to pull-down or left floating according to
> + * needs.
> + */
> + pinctrl_adtrg_default: adtrg_default {
> + pinmux = <PIN_PD31__ADTRG>;
> + bias-pull-up;
> + };
> +
> pinctrl_charger_chglev: charger_chglev {
> pinmux = <PIN_PA12__GPIO>;
> bias-disable;
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-20 16:55 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:55 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Jun 2017 16:24:54 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
The driver changes are on their way upstream.
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> index 0bef9e0..04754b1 100644
> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
> @@ -303,7 +303,7 @@
> vddana-supply = <&vdd_3v3_lp_reg>;
> vref-supply = <&vdd_3v3_lp_reg>;
> pinctrl-names = "default";
> - pinctrl-0 = <&pinctrl_adc_default>;
> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
> status = "okay";
> };
>
> @@ -322,6 +322,20 @@
> bias-disable;
> };
>
> + /*
> + * The ADTRG pin can work on any edge type.
> + * In here it's being pulled up, so need to
> + * connect it to ground to get an edge e.g.
> + * Trigger can be configured on falling, rise
> + * or any edge, and the pull-up can be changed
> + * to pull-down or left floating according to
> + * needs.
> + */
> + pinctrl_adtrg_default: adtrg_default {
> + pinmux = <PIN_PD31__ADTRG>;
> + bias-pull-up;
> + };
> +
> pinctrl_charger_chglev: charger_chglev {
> pinmux = <PIN_PA12__GPIO>;
> bias-disable;
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-20 16:56 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:56 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre, alexandre.belloni, linux-iio, lars,
linux-arm-kernel, devicetree, linux-kernel, ludovic.desroches,
robh
On Thu, 15 Jun 2017 16:24:56 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Added ADTRG edge type property as interrupt edge type value
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Driver support heading upstream.
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> arch/arm/boot/dts/sama5d2.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 8067c71..483a387 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -1267,6 +1267,7 @@
> atmel,min-sample-rate-hz = <200000>;
> atmel,max-sample-rate-hz = <20000000>;
> atmel,startup-time-ms = <4>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
> status = "disabled";
> };
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-20 16:56 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:56 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On Thu, 15 Jun 2017 16:24:56 +0300
Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
> Added ADTRG edge type property as interrupt edge type value
>
> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Driver support heading upstream.
Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> arch/arm/boot/dts/sama5d2.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 8067c71..483a387 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -1267,6 +1267,7 @@
> atmel,min-sample-rate-hz = <200000>;
> atmel,max-sample-rate-hz = <20000000>;
> atmel,startup-time-ms = <4>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
> status = "disabled";
> };
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-20 16:56 ` Jonathan Cameron
0 siblings, 0 replies; 33+ messages in thread
From: Jonathan Cameron @ 2017-06-20 16:56 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Jun 2017 16:24:56 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Added ADTRG edge type property as interrupt edge type value
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Driver support heading upstream.
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
> Changes in v4:
> - Modified bindings to be similar with interrupts
>
> arch/arm/boot/dts/sama5d2.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 8067c71..483a387 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -1267,6 +1267,7 @@
> atmel,min-sample-rate-hz = <200000>;
> atmel,max-sample-rate-hz = <20000000>;
> atmel,startup-time-ms = <4>;
> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
> status = "disabled";
> };
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-21 7:50 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:50 UTC (permalink / raw)
To: Eugen Hristev, alexandre.belloni
Cc: Jonathan Cameron, linux-iio, lars, linux-arm-kernel, devicetree,
linux-kernel, ludovic.desroches, robh
On 20/06/2017 at 18:55, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:54 +0300
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
>
>> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
> The driver changes are on their way upstream.
>
> Acked-by: Jonathan Cameron <jic23@kernel.org>
Thanks Jonathan,
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Eugen, note that we may need to wait for 4.14 as our changes for 4.13
are already queued in arm-soc...
Best regards,
>> ---
>> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
>> 1 file changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> index 0bef9e0..04754b1 100644
>> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> @@ -303,7 +303,7 @@
>> vddana-supply = <&vdd_3v3_lp_reg>;
>> vref-supply = <&vdd_3v3_lp_reg>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&pinctrl_adc_default>;
>> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
>> status = "okay";
>> };
>>
>> @@ -322,6 +322,20 @@
>> bias-disable;
>> };
>>
>> + /*
>> + * The ADTRG pin can work on any edge type.
>> + * In here it's being pulled up, so need to
>> + * connect it to ground to get an edge e.g.
>> + * Trigger can be configured on falling, rise
>> + * or any edge, and the pull-up can be changed
>> + * to pull-down or left floating according to
>> + * needs.
>> + */
>> + pinctrl_adtrg_default: adtrg_default {
>> + pinmux = <PIN_PD31__ADTRG>;
>> + bias-pull-up;
>> + };
>> +
>> pinctrl_charger_chglev: charger_chglev {
>> pinmux = <PIN_PA12__GPIO>;
>> bias-disable;
>
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-21 7:50 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:50 UTC (permalink / raw)
To: Eugen Hristev, alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: Jonathan Cameron, linux-iio-u79uwXL29TY76Z2rM5mHXA,
lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On 20/06/2017 at 18:55, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:54 +0300
> Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
>
>> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
>> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> The driver changes are on their way upstream.
>
> Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Thanks Jonathan,
Acked-by: Nicolas Ferre <nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Eugen, note that we may need to wait for 4.14 as our changes for 4.13
are already queued in arm-soc...
Best regards,
>> ---
>> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
>> 1 file changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> index 0bef9e0..04754b1 100644
>> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> @@ -303,7 +303,7 @@
>> vddana-supply = <&vdd_3v3_lp_reg>;
>> vref-supply = <&vdd_3v3_lp_reg>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&pinctrl_adc_default>;
>> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
>> status = "okay";
>> };
>>
>> @@ -322,6 +322,20 @@
>> bias-disable;
>> };
>>
>> + /*
>> + * The ADTRG pin can work on any edge type.
>> + * In here it's being pulled up, so need to
>> + * connect it to ground to get an edge e.g.
>> + * Trigger can be configured on falling, rise
>> + * or any edge, and the pull-up can be changed
>> + * to pull-down or left floating according to
>> + * needs.
>> + */
>> + pinctrl_adtrg_default: adtrg_default {
>> + pinmux = <PIN_PD31__ADTRG>;
>> + bias-pull-up;
>> + };
>> +
>> pinctrl_charger_chglev: charger_chglev {
>> pinmux = <PIN_PA12__GPIO>;
>> bias-disable;
>
>
--
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin
@ 2017-06-21 7:50 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:50 UTC (permalink / raw)
To: linux-arm-kernel
On 20/06/2017 at 18:55, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:54 +0300
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
>
>> Enable pinctrl for ADTRG pin (PD31) for ADC hardware trigger support.
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
> The driver changes are on their way upstream.
>
> Acked-by: Jonathan Cameron <jic23@kernel.org>
Thanks Jonathan,
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Eugen, note that we may need to wait for 4.14 as our changes for 4.13
are already queued in arm-soc...
Best regards,
>> ---
>> arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 +++++++++++++++-
>> 1 file changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> index 0bef9e0..04754b1 100644
>> --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
>> @@ -303,7 +303,7 @@
>> vddana-supply = <&vdd_3v3_lp_reg>;
>> vref-supply = <&vdd_3v3_lp_reg>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&pinctrl_adc_default>;
>> + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
>> status = "okay";
>> };
>>
>> @@ -322,6 +322,20 @@
>> bias-disable;
>> };
>>
>> + /*
>> + * The ADTRG pin can work on any edge type.
>> + * In here it's being pulled up, so need to
>> + * connect it to ground to get an edge e.g.
>> + * Trigger can be configured on falling, rise
>> + * or any edge, and the pull-up can be changed
>> + * to pull-down or left floating according to
>> + * needs.
>> + */
>> + pinctrl_adtrg_default: adtrg_default {
>> + pinmux = <PIN_PD31__ADTRG>;
>> + bias-pull-up;
>> + };
>> +
>> pinctrl_charger_chglev: charger_chglev {
>> pinmux = <PIN_PA12__GPIO>;
>> bias-disable;
>
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-21 7:51 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:51 UTC (permalink / raw)
To: Jonathan Cameron, Eugen Hristev, alexandre.belloni
Cc: linux-iio, lars, linux-arm-kernel, devicetree, linux-kernel,
ludovic.desroches, robh
On 20/06/2017 at 18:56, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:56 +0300
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
>
>> Added ADTRG edge type property as interrupt edge type value
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
> Driver support heading upstream.
>
> Acked-by: Jonathan Cameron <jic23@kernel.org>
Thanks,
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
>> ---
>> Changes in v4:
>> - Modified bindings to be similar with interrupts
>>
>> arch/arm/boot/dts/sama5d2.dtsi | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
>> index 8067c71..483a387 100644
>> --- a/arch/arm/boot/dts/sama5d2.dtsi
>> +++ b/arch/arm/boot/dts/sama5d2.dtsi
>> @@ -1267,6 +1267,7 @@
>> atmel,min-sample-rate-hz = <200000>;
>> atmel,max-sample-rate-hz = <20000000>;
>> atmel,startup-time-ms = <4>;
>> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
>> status = "disabled";
>> };
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-21 7:51 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:51 UTC (permalink / raw)
To: Jonathan Cameron, Eugen Hristev,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
robh-DgEjT+Ai2ygdnm+yROfE0A
On 20/06/2017 at 18:56, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:56 +0300
> Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
>
>> Added ADTRG edge type property as interrupt edge type value
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
>> Acked-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Driver support heading upstream.
>
> Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Thanks,
Acked-by: Nicolas Ferre <nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
>> ---
>> Changes in v4:
>> - Modified bindings to be similar with interrupts
>>
>> arch/arm/boot/dts/sama5d2.dtsi | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
>> index 8067c71..483a387 100644
>> --- a/arch/arm/boot/dts/sama5d2.dtsi
>> +++ b/arch/arm/boot/dts/sama5d2.dtsi
>> @@ -1267,6 +1267,7 @@
>> atmel,min-sample-rate-hz = <200000>;
>> atmel,max-sample-rate-hz = <20000000>;
>> atmel,startup-time-ms = <4>;
>> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
>> status = "disabled";
>> };
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type
@ 2017-06-21 7:51 ` Nicolas Ferre
0 siblings, 0 replies; 33+ messages in thread
From: Nicolas Ferre @ 2017-06-21 7:51 UTC (permalink / raw)
To: linux-arm-kernel
On 20/06/2017 at 18:56, Jonathan Cameron wrote:
> On Thu, 15 Jun 2017 16:24:56 +0300
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
>
>> Added ADTRG edge type property as interrupt edge type value
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
> Driver support heading upstream.
>
> Acked-by: Jonathan Cameron <jic23@kernel.org>
Thanks,
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
>> ---
>> Changes in v4:
>> - Modified bindings to be similar with interrupts
>>
>> arch/arm/boot/dts/sama5d2.dtsi | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
>> index 8067c71..483a387 100644
>> --- a/arch/arm/boot/dts/sama5d2.dtsi
>> +++ b/arch/arm/boot/dts/sama5d2.dtsi
>> @@ -1267,6 +1267,7 @@
>> atmel,min-sample-rate-hz = <200000>;
>> atmel,max-sample-rate-hz = <20000000>;
>> atmel,startup-time-ms = <4>;
>> + atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
>> status = "disabled";
>> };
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2017-06-21 7:51 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-15 13:24 [PATCH v5 0/4] iio: adc: sama5d2_adc hw triggers and buffers Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` [PATCH v5 1/4] ARM: dts: at91: sama5d2_xplained: enable ADTRG pin Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-20 16:55 ` Jonathan Cameron
2017-06-20 16:55 ` Jonathan Cameron
2017-06-20 16:55 ` Jonathan Cameron
2017-06-21 7:50 ` Nicolas Ferre
2017-06-21 7:50 ` Nicolas Ferre
2017-06-21 7:50 ` Nicolas Ferre
2017-06-15 13:24 ` [PATCH v5 2/4] Documentation: dt: iio: at91-sama5d2_adc: add hw trigger edge binding Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-20 16:53 ` Jonathan Cameron
2017-06-20 16:53 ` Jonathan Cameron
2017-06-20 16:53 ` Jonathan Cameron
2017-06-15 13:24 ` [PATCH v5 3/4] ARM: dts: at91: sama5d2: add ADC hw trigger edge type Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-20 16:56 ` Jonathan Cameron
2017-06-20 16:56 ` Jonathan Cameron
2017-06-20 16:56 ` Jonathan Cameron
2017-06-21 7:51 ` Nicolas Ferre
2017-06-21 7:51 ` Nicolas Ferre
2017-06-21 7:51 ` Nicolas Ferre
2017-06-15 13:24 ` [PATCH v5 4/4] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-15 13:24 ` Eugen Hristev
2017-06-20 16:55 ` Jonathan Cameron
2017-06-20 16:55 ` Jonathan Cameron
2017-06-20 16:55 ` Jonathan Cameron
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.