Skip to contentSkip to conversation

iio: adc: add STMPE ADC driver using IIO framework

PATCH In review Philippe Schenker 3 participants 9 messages Nov 6, 2018 – Nov 17, 2018

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 iio: adc: add STMPE ADC driver using IIO framework

From: Stefan Agner <[email protected]>

This adds an ADC driver for the STMPE device using the industrial input/output interface. The driver supports raw reading of values. The driver depends on the MFD STMPE driver. If the touchscreen block is enabled too, only four of the 8 ADC channels are available.

---
 drivers/iio/adc/Kconfig              |   7 +
 drivers/iio/adc/Makefile             |   1 +
 drivers/iio/adc/stmpe-adc.c          | 383 +++++++++++++++++++++++++++
 drivers/input/touchscreen/stmpe-ts.c |  11 -
 drivers/mfd/Kconfig                  |   3 +-
 drivers/mfd/stmpe.c                  |  27 ++
 include/linux/mfd/stmpe.h            |  11 +
 7 files changed, 431 insertions(+), 12 deletions(-)
 create mode 100644 drivers/iio/adc/stmpe-adc.c
drivers/iio/adc/Kconfig +7 -0
index a52fea8749a9..d2845472b6c2 100644
@@ -734,6 +734,13 @@ config STM32_DFSDM_ADC
 	  This driver can also be built as a module.  If so, the module
 	  will be called stm32-dfsdm-adc.
 
+config STMPE_ADC
+	tristate "STMicroelectronics STMPE ADC driver"
+	depends on (OF || COMPILE_TEST || MFD_STMPE)
+	help
+	  Say yes here to build support for ST Microelectronics STMPE
+	  built in ADC block (stmpe811).
+
 config STX104
 	tristate "Apex Embedded Systems STX104 driver"
 	depends on PC104 && X86
drivers/iio/adc/Makefile +1 -0
index a6e6a0b659e2..cba889c30bf9 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
 obj-$(CONFIG_STM32_ADC) += stm32-adc.o
 obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
 obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
+obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
 obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
drivers/iio/adc/stmpe-adc.c new file +383 -0

383 lines not on this page · raw message

drivers/input/touchscreen/stmpe-ts.c +0 -11
index 2a78e27b4495..05674e0e233f 100644
@@ -49,17 +49,6 @@
 
 #define STMPE_IRQ_TOUCH_DET		0
 
-#define SAMPLE_TIME(x)			((x & 0xf) << 4)
-#define MOD_12B(x)			((x & 0x1) << 3)
-#define REF_SEL(x)			((x & 0x1) << 1)
-#define ADC_FREQ(x)			(x & 0x3)
-#define AVE_CTRL(x)			((x & 0x3) << 6)
-#define DET_DELAY(x)			((x & 0x7) << 3)
-#define SETTLING(x)			(x & 0x7)
-#define FRACTION_Z(x)			(x & 0x7)
-#define I_DRIVE(x)			(x & 0x1)
-#define OP_MODE(x)			((x & 0x7) << 1)
-
 #define STMPE_TS_NAME			"stmpe-ts"
 #define XY_MASK				0xfff
 
drivers/mfd/Kconfig +2 -1
index 8c5dfdce4326..bba159e8eaa4 100644
@@ -1204,7 +1204,7 @@ config MFD_STMPE
 
 	  Currently supported devices are:
 
-		STMPE811: GPIO, Touchscreen
+		STMPE811: GPIO, Touchscreen, ADC
 		STMPE1601: GPIO, Keypad
 		STMPE1801: GPIO, Keypad
 		STMPE2401: GPIO, Keypad
@@ -1217,6 +1217,7 @@ config MFD_STMPE
 		GPIO: stmpe-gpio
 		Keypad: stmpe-keypad
 		Touchscreen: stmpe-ts
+		ADC: stmpe-adc
 
 menu "STMicroelectronics STMPE Interface Drivers"
 depends on MFD_STMPE
drivers/mfd/stmpe.c +27 -0
index 566caca4efd8..00b98f75f7dd 100644
@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = {
 	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
 };
 
+/*
+ * ADC (STMPE811)
+ */
+
+static struct resource stmpe_adc_resources[] = {
+	{
+		.name	= "STMPE_TEMP_SENS",
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "STMPE_ADC",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static const struct mfd_cell stmpe_adc_cell = {
+	.name		= "stmpe-adc",
+	.of_compatible	= "st,stmpe-adc",
+	.resources	= stmpe_adc_resources,
+	.num_resources	= ARRAY_SIZE(stmpe_adc_resources),
+};
+
 /*
  * STMPE811 or STMPE610
  */
@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
 		.irq	= STMPE811_IRQ_TOUCH_DET,
 		.block	= STMPE_BLOCK_TOUCHSCREEN,
 	},
+	{
+		.cell	= &stmpe_adc_cell,
+		.irq	= STMPE811_IRQ_TEMP_SENS,
+		.block	= STMPE_BLOCK_ADC,
+	},
 };
 
 static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
include/linux/mfd/stmpe.h +11 -0
index 4a827af17e59..90700013f56d 100644
@@ -10,6 +10,17 @@
 
 #include <linux/mutex.h>
 
+#define SAMPLE_TIME(x)		((x & 0xf) << 4)
+#define MOD_12B(x)		((x & 0x1) << 3)
+#define REF_SEL(x)		((x & 0x1) << 1)
+#define ADC_FREQ(x)		(x & 0x3)
+#define AVE_CTRL(x)		((x & 0x3) << 6)
+#define DET_DELAY(x)		((x & 0x7) << 3)
+#define SETTLING(x)		(x & 0x7)
+#define FRACTION_Z(x)		(x & 0x7)
+#define I_DRIVE(x)		(x & 0x1)
+#define OP_MODE(x)		((x & 0x7) << 1)
+
 struct device;
 struct regulator;
 
Signature · 1 line
2.19.1
#1 lore raw

PATCH 2/3 iio: adc: add STMPE ADC devicetree bindings

From: Stefan Agner <[email protected]>

This adds the devicetree bindings for the STMPE ADC.

---
 .../devicetree/bindings/iio/adc/stmpe-adc.txt | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +34 -0
new file mode 100644
index 000000000000..752ef35a794d
@@ -0,0 +1,34 @@
+STMPE ADC driver
+----------------
+
+Required properties:
+ - compatible: "st,stmpe-adc"
+
+Optional properties:
+Note that the ADC is shared with the STMPE touchscreen, so if using both the
+settings should be the same.
+If the settings are not the same, the settings of the driver initialized last
+will be active.
+- st,sample-time: ADC conversion time in number of clock. (0 -> 36 clocks,
+  1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks,
+  5 -> 96 clocks, 6 -> 144 clocks), recommended is 4.
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)
+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
+- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
+  requestable due to different usage (e.g. touch)
+
+Node name must be stmpe_adc and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_adc {
+		compatible = "st,stmpe-adc";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
+	};
Signature · 1 line
2.19.1
maintainer
#2 lore raw

Re: [PATCH 2/3] iio: adc: add STMPE ADC devicetree bindings

Quoted 18 lines · On Tue, 6 Nov 2018 17:41:15 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>

This adds the devicetree bindings for the STMPE ADC.

---
 .../devicetree/bindings/iio/adc/stmpe-adc.txt | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +0 -0
new file mode 100644
index 000000000000..752ef35a794d

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 9

Quoted 9 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +9 -0
@@ -0,0 +1,34 @@
+STMPE ADC driver
+----------------
+
+Required properties:
+ - compatible: "st,stmpe-adc"
+
+Optional properties:
+Note that the ADC is shared with the STMPE touchscreen, so if using both the
+settings should be the same.

Ah, guessing there is already a binding in place for that which we need to closely match. Should there be one overarching device with both as children though if it is the same hardware?

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 14

Quoted 5 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +5 -0
+If the settings are not the same, the settings of the driver initialized last
+will be active.
+- st,sample-time: ADC conversion time in number of clock. (0 -> 36 clocks,
+  1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks,
+  5 -> 96 clocks, 6 -> 144 clocks), recommended is 4.

Could of questions here. Is this a hardware dictated limit or is it dependent on application? Basically I'm asking if it should be in userspace rather than here.

Ideally I'd love to see it in a unit of time, but failing that can we have it in clock cycles please rather than an enum? Always nice if a binding is human readable. st,sample-clock-cycles would be a better name.

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 17

Quoted 3 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +3 -0
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)

If there is an external reference, I'd expect to see a regulator providing it. Usually the mere presence of such an optional regulator does the job of saying if it should be used.

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 18

Quoted 1 line
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +1 -0
+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)

So this is some internal clock? What dictates the right setting? I.e. how should anyone know which one to pick?

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 20

Quoted 2 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +2 -0
+- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
+  requestable due to different usage (e.g. touch)

That's a little bit ugly. Would prefer to see an explicit set of channels brought out as children in DT. There are some patches around standardising some properties for doing that under review at the moment.

[PATCH v4 2/4] dt-bindings: iio: adc: Add common ADCs properties to a separate file

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 27

Quoted 7 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+
+Node name must be stmpe_adc and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_adc {

adc {
is the moderately standard naming for ADCS.

Quoted 7 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+		compatible = "st,stmpe-adc";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
+	};
#3 lore raw

Re: [PATCH 2/3] iio: adc: add STMPE ADC devicetree bindings

Quoted 25 lines · On Sun, 11 Nov 2018 15:42:07 +0000 Jonathan Cameron <[email protected]> wrote:
Quoted 22 lines · On Tue, 6 Nov 2018 17:41:15 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>

This adds the devicetree bindings for the STMPE ADC.

---
 .../devicetree/bindings/iio/adc/stmpe-adc.txt | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +4 -0
new file mode 100644
index 000000000000..752ef35a794d
@@ -0,0 +1,34 @@
+STMPE ADC driver
+----------------
+
+Required properties:
Quoted 8 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 9

Quoted 5 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +5 -0
+ - compatible: "st,stmpe-adc"
+
+Optional properties:
+Note that the ADC is shared with the STMPE touchscreen, so if using both the
+settings should be the same.  

Ah, guessing there is already a binding in place for that which we need to closely match. Should there be one overarching device with both as children though if it is the same hardware?

ah, there is an mfd, can these become elements of the binding for that so they are only in one place? It's a bit ugly to do that given there are other children, but certainly better than having them replicated like this...

Quoted 55 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 14

Quoted 6 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +5 -0
+If the settings are not the same, the settings of the driver initialized last
+will be active.
+- st,sample-time: ADC conversion time in number of clock. (0 -> 36 clocks,
+  1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks,
+  5 -> 96 clocks, 6 -> 144 clocks), recommended is 4.  

Could of questions here. Is this a hardware dictated limit or is it dependent on application? Basically I'm asking if it should be in userspace rather than here.

Ideally I'd love to see it in a unit of time, but failing that can we have it in clock cycles please rather than an enum? Always nice if a binding is human readable. st,sample-clock-cycles would be a better name.

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 17

Quoted 3 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +3 -0
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)  

If there is an external reference, I'd expect to see a regulator providing it. Usually the mere presence of such an optional regulator does the job of saying if it should be used.

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 18

Quoted 1 line
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +1 -0
+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)  

So this is some internal clock? What dictates the right setting? I.e. how should anyone know which one to pick?

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 20

Quoted 2 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +2 -0
+- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
+  requestable due to different usage (e.g. touch)  

That's a little bit ugly. Would prefer to see an explicit set of channels brought out as children in DT. There are some patches around standardising some properties for doing that under review at the moment.

[PATCH v4 2/4] dt-bindings: iio: adc: Add common ADCs properties to a separate file

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 27

Quoted 7 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+
+Node name must be stmpe_adc and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_adc {  

adc {
is the moderately standard naming for ADCS.

Quoted 7 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+		compatible = "st,stmpe-adc";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
+	};  
#4 lore raw

Re: [PATCH 2/3] iio: adc: add STMPE ADC devicetree bindings

In reply to Jonathan Cameron
Quoted 28 lines · Jonathan Cameron
Quoted 25 lines · On Tue, 6 Nov 2018 17:41:15 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>

This adds the devicetree bindings for the STMPE ADC.

---
 .../devicetree/bindings/iio/adc/stmpe-adc.txt | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +6 -0
new file mode 100644
index 000000000000..752ef35a794d
@@ -0,0 +1,34 @@
+STMPE ADC driver
+----------------
+
+Required properties:
+ - compatible: "st,stmpe-adc"
+
Quoted 8 lines
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +2 -0
+Optional properties:
+Note that the ADC is shared with the STMPE touchscreen, so if using both

the
+settings should be the same.

Ah, guessing there is already a binding in place for that which we need to closely
match. Should there be one overarching device with both as children though if it is the same hardware?

I moved ADC settings to the mfd...

Quoted 12 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 14

Quoted 7 lines

+If the settings are not the same, the settings of the driver initialized last

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +4 -0
+will be active.
+- st,sample-time: ADC conversion time in number of clock. (0 -> 36 clocks,
+  1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks,
+  5 -> 96 clocks, 6 -> 144 clocks), recommended is 4.

Could of questions here. Is this a hardware dictated limit or is it dependent on
application? Basically I'm asking if it should be in userspace rather than here.

Quoted 4 lines

Ideally I'd love to see it in a unit of time, but failing that can we have it in clock cycles please rather than an enum? Always nice if a binding is human readable. st,sample-clock-cycles would be a better name.

This is none of our design-decision. We did it the same way as it was already in drivers/input/touchscreen/stmpe-ts.c.

Quoted 9 lines
Quoted 4 lines
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)

If there is an external reference, I'd expect to see a regulator providing it. Usually the mere presence of such an optional regulator does the job of saying if
it should be used.

Same here, we did it the same way as it was in stmpe-ts.c

Quoted 6 lines
Quoted 4 lines

+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)

So this is some internal clock? What dictates the right setting? I.e. how should anyone know which one to pick?

I think as a user of this driver at this point you need to read the datasheet anyway, to be able to decide which parameters you need for the application.

Quoted 9 lines
Quoted 3 lines
+- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
+  requestable due to different usage (e.g. touch)

That's a little bit ugly. Would prefer to see an explicit set of channels brought out as children in DT. There are some patches around standardising some properties for doing that under review at the moment.

[PATCH v4 2/4] dt-bindings: iio: adc: Add common ADCs properties to a separate file

This is also implemented with the "norequest-mask" in stmpe-ts.c. That's why we did it the same way and I don't like to break others devicetree by changing stmpe-ts.c

Quoted 11 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 27

Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+
+Node name must be stmpe_adc and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_adc {

adc {
is the moderately standard naming for ADCS.

This is none of our naming decisions please see line 1311 in drivers/mfd/stmpe.c

Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+		compatible = "st,stmpe-adc";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
+	};
maintainer
#5 lore raw

Re: [PATCH 2/3] iio: adc: add STMPE ADC devicetree bindings

Quoted 108 lines · On Thu, 15 Nov 2018 10:38:03 +0100 Philippe Schenker <[email protected]> wrote:
Quoted 28 lines · Jonathan Cameron
Quoted 25 lines · On Tue, 6 Nov 2018 17:41:15 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>

This adds the devicetree bindings for the STMPE ADC.

---
 .../devicetree/bindings/iio/adc/stmpe-adc.txt | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +6 -0
new file mode 100644
index 000000000000..752ef35a794d
@@ -0,0 +1,34 @@
+STMPE ADC driver
+----------------
+
+Required properties:
+ - compatible: "st,stmpe-adc"
+
Quoted 8 lines
Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +2 -0
+Optional properties:
+Note that the ADC is shared with the STMPE touchscreen, so if using both

the
+settings should be the same.

Ah, guessing there is already a binding in place for that which we need to closely
match. Should there be one overarching device with both as children though if it is the same hardware?

I moved ADC settings to the mfd...

Quoted 12 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 14

Quoted 7 lines

+If the settings are not the same, the settings of the driver initialized last

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +4 -0
+will be active.
+- st,sample-time: ADC conversion time in number of clock. (0 -> 36 clocks,
+  1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks,
+  5 -> 96 clocks, 6 -> 144 clocks), recommended is 4.  

Could of questions here. Is this a hardware dictated limit or is it dependent on
application? Basically I'm asking if it should be in userspace rather than here.

Quoted 4 lines

Ideally I'd love to see it in a unit of time, but failing that can we have it in clock cycles please rather than an enum? Always nice if a binding is human readable. st,sample-clock-cycles would be a better name.

This is none of our design-decision. We did it the same way as it was already in drivers/input/touchscreen/stmpe-ts.c.

Quoted 9 lines
Quoted 4 lines
  
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)  

If there is an external reference, I'd expect to see a regulator providing it. Usually the mere presence of such an optional regulator does the job of saying if
it should be used.

Same here, we did it the same way as it was in stmpe-ts.c

Quoted 6 lines
Quoted 4 lines
  
+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 ->
6.5 MHz)  

So this is some internal clock? What dictates the right setting? I.e. how should anyone know which one to pick?

I think as a user of this driver at this point you need to read the datasheet anyway, to be able to decide which parameters you need for the application.

Quoted 9 lines
Quoted 3 lines
  
+- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
+  requestable due to different usage (e.g. touch)  

That's a little bit ugly. Would prefer to see an explicit set of channels brought out as children in DT. There are some patches around standardising some properties for doing that under review at the moment.

[PATCH v4 2/4] dt-bindings: iio: adc: Add common ADCs properties to a separate file

This is also implemented with the "norequest-mask" in stmpe-ts.c. That's why we did it the same way and I don't like to break others devicetree by changing stmpe-ts.c

Quoted 11 lines

Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt line 27

Quoted 8 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+
+Node name must be stmpe_adc and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_adc {  

adc {
is the moderately standard naming for ADCS.

Quoted 1 line

This is none of our naming decisions please see line 1311 in drivers/mfd/stmpe.c

Fair enough on all these - we are stuck with less than ideal legacy :(

Jonathan

Quoted 10 lines
Quoted 9 lines
Quoted 9 lines
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt new file +7 -0
+		compatible = "st,stmpe-adc";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
+	};  
#6 lore raw

PATCH 3/3 ARM: dts: Add stmpe-adc driver to relevant devicetrees

In reply to Philippe Schenker

From: Philippe Schenker <[email protected]>

Activate the stmpe-adc driver as found on Apalis/Colibri iMX6/T30 modules

---
 arch/arm/boot/dts/imx6qdl-apalis.dtsi  | 14 ++++++++++++++
 arch/arm/boot/dts/imx6qdl-colibri.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/tegra30-apalis.dtsi  | 14 ++++++++++++++
 arch/arm/boot/dts/tegra30-colibri.dtsi | 14 ++++++++++++++
 4 files changed, 56 insertions(+)
arch/arm/boot/dts/imx6qdl-apalis.dtsi +14 -0
index 3dc99dd8dde1..10ba925be35a 100644
@@ -356,6 +356,20 @@
 			/* 5 ms touch detect interrupt delay */
 			st,touch-det-delay = <5>;
 		};
+
+		stmpe_adc {
+			compatible = "st,stmpe-adc";
+			/* 3.25 MHz ADC clock speed */
+			st,adc-freq = <1>;
+			/* 12-bit ADC */
+			st,mod-12b = <1>;
+			/* internal ADC reference */
+			st,ref-sel = <0>;
+			/* ADC converstion time: 80 clocks */
+			st,sample-time = <4>;
+			/* forbid to use ADC channels 3-0 (touch) */
+			st,norequest-mask = <0x0F>;
+		};
 	};
 };
 
arch/arm/boot/dts/imx6qdl-colibri.dtsi +14 -0
index 87e15e7cb32b..2c11dc33526c 100644
@@ -287,6 +287,20 @@
 			/* 5 ms touch detect interrupt delay */
 			st,touch-det-delay = <5>;
 		};
+
+		stmpe_adc {
+			compatible = "st,stmpe-adc";
+			/* 3.25 MHz ADC clock speed */
+			st,adc-freq = <1>;
+			/* 12-bit ADC */
+			st,mod-12b = <1>;
+			/* internal ADC reference */
+			st,ref-sel = <0>;
+			/* ADC converstion time: 80 clocks */
+			st,sample-time = <4>;
+			/* forbid to use ADC channels 3-0 (touch) */
+			st,norequest-mask = <0x0F>;
+		};
 	};
 };
 
arch/arm/boot/dts/tegra30-apalis.dtsi +14 -0
index 7f112f192fe9..1fd3c1f60478 100644
@@ -1001,6 +1001,20 @@
 				/* 5 ms touch detect interrupt delay */
 				st,touch-det-delay = <5>;
 			};
+
+			stmpe_adc {
+				compatible = "st,stmpe-adc";
+				/* 3.25 MHz ADC clock speed */
+				st,adc-freq = <1>;
+				/* 12-bit ADC */
+				st,mod-12b = <1>;
+				/* internal ADC reference */
+				st,ref-sel = <0>;
+				/* ADC converstion time: 80 clocks */
+				st,sample-time = <4>;
+				/* forbid to use ADC channels 3-0 (touch) */
+				st,norequest-mask = <0x0F>;
+			};
 		};
 
 		/*
arch/arm/boot/dts/tegra30-colibri.dtsi +14 -0
index 35af03ca9e90..d9fe112eb5ad 100644
@@ -870,6 +870,20 @@
 				/* 5 ms touch detect interrupt delay */
 				st,touch-det-delay = <5>;
 			};
+
+			stmpe_adc {
+				compatible = "st,stmpe-adc";
+				/* 3.25 MHz ADC clock speed */
+				st,adc-freq = <1>;
+				/* 12-bit ADC */
+				st,mod-12b = <1>;
+				/* internal ADC reference */
+				st,ref-sel = <0>;
+				/* ADC converstion time: 80 clocks */
+				st,sample-time = <4>;
+				/* forbid to use ADC channels 3-0 (touch) */
+				st,norequest-mask = <0x0F>;
+			};
 		};
 
 		/*
Signature · 1 line
2.19.1
maintainer
#7 lore raw
In reply to Philippe Schenker
Quoted 10 lines · On Tue, 6 Nov 2018 17:41:14 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>
=20
This adds an ADC driver for the STMPE device using the industrial input/output interface. The driver supports raw reading of values. The driver depends on the MFD STMPE driver. If the touchscreen block is enabled too, only four of the 8 ADC channels are available. =20

We are a bit limited in here I think by how it interacts with the mfd and most of my comments are about the related DT bindings.

A few comments inline.

thanks,

Jonathan

Quoted 61 lines
---
 drivers/iio/adc/Kconfig              |   7 +
 drivers/iio/adc/Makefile             |   1 +
 drivers/iio/adc/stmpe-adc.c          | 383 +++++++++++++++++++++++++++
 drivers/input/touchscreen/stmpe-ts.c |  11 -
 drivers/mfd/Kconfig                  |   3 +-
 drivers/mfd/stmpe.c                  |  27 ++
 include/linux/mfd/stmpe.h            |  11 +
 7 files changed, 431 insertions(+), 12 deletions(-)
 create mode 100644 drivers/iio/adc/stmpe-adc.c

=20

drivers/iio/adc/Kconfig +0 -0
index a52fea8749a9..d2845472b6c2 100644
@@ -734,6 +734,13 @@ config STM32_DFSDM_ADC
 	  This driver can also be built as a module.  If so, the module
 	  will be called stm32-dfsdm-adc.

=20

drivers/iio/adc/Kconfig +7 -0
+config STMPE_ADC
+	tristate "STMicroelectronics STMPE ADC driver"
+	depends on (OF || COMPILE_TEST || MFD_STMPE)
+	help
+	  Say yes here to build support for ST Microelectronics STMPE
+	  built in ADC block (stmpe811).
+
 config STX104
 	tristate "Apex Embedded Systems STX104 driver"
 	depends on PC104 && X86
drivers/iio/adc/Makefile +1 -0
index a6e6a0b659e2..cba889c30bf9 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_STM32_ADC_CORE) +=3D stm32-adc-core.o
 obj-$(CONFIG_STM32_ADC) +=3D stm32-adc.o
 obj-$(CONFIG_STM32_DFSDM_CORE) +=3D stm32-dfsdm-core.o
 obj-$(CONFIG_STM32_DFSDM_ADC) +=3D stm32-dfsdm-adc.o
+obj-$(CONFIG_STMPE_ADC) +=3D stmpe-adc.o
 obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) +=3D ti-adc0832.o
 obj-$(CONFIG_TI_ADC084S021) +=3D ti-adc084s021.o
drivers/iio/adc/stmpe-adc.c new file +14 -0
new file mode 100644
index 000000000000..891ad838ab3c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  STMicroelectronics STMPE811 IIO ADC Driver
+ *
+ *  4 channel, 10/12-bit ADC
+ *
+ *  Copyright (C) 2013-2018 Toradex AG <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iio/events.h>

drivers/iio/adc/stmpe-adc.c line 24

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>

Not seeing any regulators in here. Please do a quick sanity check on the other headers as well. This is a long list for a fairly short bit of code!

drivers/iio/adc/stmpe-adc.c line 37

Quoted 13 lines
drivers/iio/adc/stmpe-adc.c new file +13 -0
+#include <linux/slab.h>
+
+#define STMPE_REG_INT_STA	0x0B
+#define STMPE_REG_ADC_INT_EN	0x0E
+#define STMPE_REG_ADC_INT_STA	0x0F
+
+#define STMPE_REG_ADC_CTRL1	0x20
+#define STMPE_REG_ADC_CTRL2	0x21
+#define STMPE_REG_ADC_CAPT	0x22
+#define STMPE_REG_ADC_DATA_CH(channel)	(0x30 + 2 * (channel))
+
+#define STMPE_REG_TEMP_CTRL	0x60
+#define STMPE_START_ONE_TEMP_CONV (0x08 + 0x02 + 0x01)

This is oddly put.. Is it a mask or 3 things we can otherwise define?

drivers/iio/adc/stmpe-adc.c line 44

Quoted 7 lines
drivers/iio/adc/stmpe-adc.c new file +7 -0
+#define STMPE_REG_TEMP_DATA	0x61
+#define STMPE_REG_TEMP_TH	0x63
+#define STMPE_MAX_ADC_CH	8
+
+#define STMPE_ADC_CH(channel)	((1 << (channel)) & 0xff)
+
+#define STMPE_ADC_TIMEOUT	(msecs_to_jiffies(1000))

Outer brackets don't add anything that I can see.

drivers/iio/adc/stmpe-adc.c line 46

Quoted 2 lines
drivers/iio/adc/stmpe-adc.c new file +2 -0
+
+struct stmpe_adc {

personally I always think aligning structure elements is a bad idea as breaks far too often with later additions. Still I don't care that much if you really want to do this...

Quoted 27 lines
drivers/iio/adc/stmpe-adc.c new file +27 -0
+	struct stmpe		*stmpe;
+	struct clk		*clk;
+	struct device		*dev;
+
+	struct iio_chan_spec	stmpe_adc_iio_channels[STMPE_MAX_ADC_CH];
+
+	struct completion	completion;
+
+	u8			channel;
+	u32			value;
+	u8			sample_time;
+	u8			mod_12b;
+	u8			ref_sel;
+	u8			adc_freq;
+	u32			norequest_mask;
+};
+
+static int stmpe_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val,
+				int *val2,
+				long mask)
+{
+	struct stmpe_adc *info =3D iio_priv(indio_dev);
+	long ret;
+
+	switch (mask) {

drivers/iio/adc/stmpe-adc.c line 83

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+
+		mutex_lock(&indio_dev->mlock);
+
+		info->channel =3D (u8)chan->channel;
+
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			if (info->channel > 7)

lock held.

drivers/iio/adc/stmpe-adc.c

Quoted 13 lines
drivers/iio/adc/stmpe-adc.c new file +13 -0
+				return -ENOENT;
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
+					STMPE_ADC_CH(info->channel));
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
+					STMPE_ADC_CH(info->channel));
+
+			*val =3D info->value;
+			break;
+
+		case IIO_TEMP:
+			if (info->channel !=3D 8)

lock held...

Quoted 66 lines
drivers/iio/adc/stmpe-adc.c new file +66 -0
+				return -ENOENT;
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
+					STMPE_START_ONE_TEMP_CONV);
+			break;
+		default:
+			mutex_unlock(&indio_dev->mlock);
+			return -EINVAL;
+		}
+
+		ret =3D wait_for_completion_interruptible_timeout
+			(&info->completion, STMPE_ADC_TIMEOUT);
+
+		if (ret <=3D 0) {
+			mutex_unlock(&indio_dev->mlock);
+			if (ret =3D=3D 0)
+				return -ETIMEDOUT;
+			else
+				return ret;
+		}
+
+
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			*val =3D info->value;
+			break;
+
+		case IIO_TEMP:
+			/*
+			 * absolute temp =3D +V3.3 * value /7.51 [K]
+			 * scale to [milli =C2=B0C]
+			 */
+			*val =3D ((449960l * info->value) / 1024l) - 273150;
+			break;
+		default:
+			break;
+		}
+
+		mutex_unlock(&indio_dev->mlock);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val =3D 3300;
+		*val2 =3D info->mod_12b ? 12 : 10;
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
+{
+	struct stmpe_adc *info =3D (struct stmpe_adc *)dev_id;
+	u8 data[2];
+
+	if (info->channel > 8)
+		return IRQ_NONE;
+
+	if (info->channel < 8) {
+		int int_sta;
+
+		int_sta =3D stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
+

drivers/iio/adc/stmpe-adc.c

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+		/* Is the interrupt relevant */
+		if (!(int_sta & STMPE_ADC_CH(info->channel)))
+			return IRQ_NONE;
+
+		/* Read value */
+		stmpe_block_read(info->stmpe,
+			STMPE_REG_ADC_DATA_CH(info->channel), 2, data);
+
+		stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
+	} else if (info->channel =3D=3D 8) {

That 8 is pretty magic, perhaps a define given it keeps being used?

Quoted 87 lines
drivers/iio/adc/stmpe-adc.c new file +87 -0
+		/* Read value */
+		stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2, data);
+	}
+
+	info->value =3D ((u32)data[0] << 8) + data[1];
+	complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_info stmpe_adc_iio_info =3D {
+	.read_raw =3D &stmpe_read_raw,
+};
+
+static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan)
+{
+	ics->type =3D IIO_VOLTAGE;
+	ics->info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW);
+	ics->info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE);
+	ics->indexed =3D 1;
+	ics->channel =3D chan;
+}
+
+static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan)
+{
+	ics->type =3D IIO_TEMP;
+	ics->info_mask_separate =3D BIT(IIO_CHAN_INFO_PROCESSED);
+	ics->indexed =3D 1;
+	ics->channel =3D chan;
+}
+
+static int stmpe_adc_init_hw(struct stmpe_adc *adc)
+{
+	int ret;
+	u8 adc_ctrl1, adc_ctrl1_mask;
+	struct stmpe *stmpe =3D adc->stmpe;
+	struct device *dev =3D adc->dev;
+
+	ret =3D stmpe_enable(stmpe, STMPE_BLOCK_ADC);
+	if (ret) {
+		dev_err(dev, "Could not enable clock for ADC\n");
+		goto err_adc;
+	}
+
+	adc_ctrl1 =3D SAMPLE_TIME(adc->sample_time) | MOD_12B(adc->mod_12b) |
+			REF_SEL(adc->ref_sel);
+	adc_ctrl1_mask =3D SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
+
+	ret =3D stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+			adc_ctrl1_mask, adc_ctrl1);
+	if (ret) {
+		dev_err(dev, "Could not setup ADC\n");
+		goto err_adc;
+	}
+
+	ret =3D stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+			ADC_FREQ(0xff), ADC_FREQ(adc->adc_freq));
+	if (ret) {
+		dev_err(dev, "Could not setup ADC\n");
+		goto err_adc;
+	}
+
+	/* use temp irq for each conversion completion */
+	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
+	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
+
+	return 0;
+err_adc:
+	stmpe_disable(stmpe, STMPE_BLOCK_ADC);
+
+	return ret;
+}
+
+static void stmpe_adc_get_platform_info(struct platform_device *pdev,
+					struct stmpe_adc *adc)
+{
+	struct stmpe *stmpe =3D dev_get_drvdata(pdev->dev.parent);
+	struct device_node *np =3D pdev->dev.of_node;
+	u32 val;
+
+	adc->stmpe =3D stmpe;
+
+	if (!np) {
+		dev_err(&pdev->dev, "no device tree node found\n");
+		return;
+	}
+

drivers/iio/adc/stmpe-adc.c

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	if (!of_property_read_u32(np, "st,sample-time", &val))
+		adc->sample_time =3D val;
+	if (!of_property_read_u32(np, "st,mod-12b", &val))
+		adc->mod_12b =3D val;
+	if (!of_property_read_u32(np, "st,ref-sel", &val))
+		adc->ref_sel =3D val;
+	if (!of_property_read_u32(np, "st,adc-freq", &val))
+		adc->adc_freq =3D val;
+	if (!of_property_read_u32(np, "st,norequest-mask", &val))
+		adc->norequest_mask =3D val;

I commented on these in the dt-binding patch, so I won't mention them any more here.

Quoted 6 lines
drivers/iio/adc/stmpe-adc.c new file +6 -0
+}
+
+static int stmpe_adc_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev =3D NULL;
+	struct stmpe_adc *info =3D NULL;

drivers/iio/adc/stmpe-adc.c

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	int irq_temp, irq_adc;
+	int num_chan =3D 0;
+	int i =3D 0;
+	int ret;
+
+	irq_adc =3D platform_get_irq_byname(pdev, "STMPE_ADC");
+	if (irq_adc < 0)
+		return irq_adc;
+
+	indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc=

));

Quoted 16 lines
drivers/iio/adc/stmpe-adc.c new file +16 -0
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	info =3D iio_priv(indio_dev);
+
+	init_completion(&info->completion);
+	ret =3D devm_request_threaded_irq(&pdev->dev, irq_adc, NULL,
+					stmpe_adc_isr, IRQF_ONESHOT,
+					"stmpe-adc", info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed requesting irq, irq =3D %d\n",
+				irq_adc);
+		return ret;
+	}

drivers/iio/adc/stmpe-adc.c line 311

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+
+	irq_temp =3D platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
+	if (irq_temp >=3D 0) {
+		ret =3D devm_request_threaded_irq(&pdev->dev, irq_temp, NULL,
+						stmpe_adc_isr, IRQF_ONESHOT,
+						"stmpe-adc", info);
+		if (ret < 0)
+			dev_warn(&pdev->dev, "failed requesting irq for"
+					" temp sensor, irq =3D %d\n", irq_temp);
+	}

I'd like a comment here that perhaps says what the result of not having an irq for the temperature sensor is?

Quoted 17 lines
drivers/iio/adc/stmpe-adc.c new file +17 -0
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	indio_dev->name =3D dev_name(&pdev->dev);
+	indio_dev->dev.parent =3D &pdev->dev;
+	indio_dev->info =3D &stmpe_adc_iio_info;
+	indio_dev->modes =3D INDIO_DIRECT_MODE;
+
+	stmpe_adc_get_platform_info(pdev, info);
+
+	for_each_clear_bit(i, (unsigned long *) &info->norequest_mask,
+				STMPE_MAX_ADC_CH) {
+		stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i);
+		num_chan++;
+	}
+	stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i);
+	num_chan++;

drivers/iio/adc/stmpe-adc.c line 338

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	indio_dev->channels =3D info->stmpe_adc_iio_channels;
+	indio_dev->num_channels =3D num_chan;
+
+	ret =3D stmpe_adc_init_hw(info);
+	if (ret)
+		return ret;
+
+	ret =3D iio_device_register(indio_dev);
+	if (ret)
+		return ret;

one blank line is plenty.

drivers/iio/adc/stmpe-adc.c line 341

Quoted 3 lines
drivers/iio/adc/stmpe-adc.c new file +3 -0
+
+
+	dev_info(&pdev->dev, "Initialized\n");

This is just noise in the log. There are lots of ways of finding out if this came up if you actually want to so no need for the print here.

drivers/input/touchsc=

Quoted 43 lines
drivers/iio/adc/stmpe-adc.c new file +42 -0
+
+	return 0;
+}
+
+static int stmpe_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev =3D platform_get_drvdata(pdev);
+	struct stmpe_adc *info =3D iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	stmpe_disable(info->stmpe, STMPE_BLOCK_ADC);
+
+	return 0;
+}
+
+static int __maybe_unused stmpe_adc_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev =3D dev_get_drvdata(dev);
+	struct stmpe_adc *info =3D iio_priv(indio_dev);
+
+	stmpe_adc_init_hw(info);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
+
+static struct platform_driver stmpe_adc_driver =3D {
+	.probe		=3D stmpe_adc_probe,
+	.remove		=3D stmpe_adc_remove,
+	.driver		=3D {
+		.name	=3D "stmpe-adc",
+		.pm	=3D &stmpe_adc_pm_ops,
+	},
+};
+
+module_platform_driver(stmpe_adc_driver);
+
+MODULE_AUTHOR("Stefan Agner <[email protected]>");
+MODULE_DESCRIPTION("STMPEXXX ADC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:stmpe-adc");
drivers/input/touchsc= renamed from drivers/input/touchscreen/stmpe-ts.c +0 -0

reen/stmpe-ts.c

Quoted 8 lines

index 2a78e27b4495..05674e0e233f 100644

drivers/input/touchscreen/stmpe-ts.c +0 -0
@@ -49,17 +49,6 @@

=20
#define STMPE_IRQ_TOUCH_DET 0
=20

drivers/input/touchscreen/stmpe-ts.c +0 -1
-#define SAMPLE_TIME(x)			((x & 0xf) << 4)

drivers/input/touchscreen/stmpe-ts.c line 62

Quoted 10 lines
drivers/input/touchscreen/stmpe-ts.c +0 -10
-#define MOD_12B(x)			((x & 0x1) << 3)
-#define REF_SEL(x)			((x & 0x1) << 1)
-#define ADC_FREQ(x)			(x & 0x3)
-#define AVE_CTRL(x)			((x & 0x3) << 6)
-#define DET_DELAY(x)			((x & 0x7) << 3)
-#define SETTLING(x)			(x & 0x7)
-#define FRACTION_Z(x)			(x & 0x7)
-#define I_DRIVE(x)			(x & 0x1)
-#define OP_MODE(x)			((x & 0x7) << 1)
-

Given the need for prefixes in the header (see below) I would do this move as a precursor patch including renames in the touchscreen driver...

drivers/mfd/stmpe.c static struct stmpe_variant_block stmpe811_blocks[] =

Quoted 58 lines

#define STMPE_TS_NAME "stmpe-ts"
#define XY_MASK 0xfff
=20

drivers/mfd/Kconfig +0 -0
index 8c5dfdce4326..bba159e8eaa4 100644
@@ -1204,7 +1204,7 @@ config MFD_STMPE

=20
Currently supported devices are:
=20

drivers/mfd/Kconfig +2 -1
-		STMPE811: GPIO, Touchscreen
+		STMPE811: GPIO, Touchscreen, ADC
 		STMPE1601: GPIO, Keypad
 		STMPE1801: GPIO, Keypad
 		STMPE2401: GPIO, Keypad
@@ -1217,6 +1217,7 @@ config MFD_STMPE
 		GPIO: stmpe-gpio
 		Keypad: stmpe-keypad
 		Touchscreen: stmpe-ts
+		ADC: stmpe-adc

=20
menu "STMicroelectronics STMPE Interface Drivers" depends on MFD_STMPE

drivers/mfd/stmpe.c +0 -0
index 566caca4efd8..00b98f75f7dd 100644
@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell =3D {
 	.num_resources	=3D ARRAY_SIZE(stmpe_ts_resources),
 };

=20

drivers/mfd/stmpe.c +22 -0
+/*
+ * ADC (STMPE811)
+ */
+
+static struct resource stmpe_adc_resources[] =3D {
+	{
+		.name	=3D "STMPE_TEMP_SENS",
+		.flags	=3D IORESOURCE_IRQ,
+	},
+	{
+		.name	=3D "STMPE_ADC",
+		.flags	=3D IORESOURCE_IRQ,
+	},
+};
+
+static const struct mfd_cell stmpe_adc_cell =3D {
+	.name		=3D "stmpe-adc",
+	.of_compatible	=3D "st,stmpe-adc",
+	.resources	=3D stmpe_adc_resources,
+	.num_resources	=3D ARRAY_SIZE(stmpe_adc_resources),
+};
+
 /*
  * STMPE811 or STMPE610
  */
@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] =

=3D {

Quoted 19 lines
drivers/mfd/stmpe.c +5 -0
 		.irq	=3D STMPE811_IRQ_TOUCH_DET,
 		.block	=3D STMPE_BLOCK_TOUCHSCREEN,
 	},
+	{
+		.cell	=3D &stmpe_adc_cell,
+		.irq	=3D STMPE811_IRQ_TEMP_SENS,
+		.block	=3D STMPE_BLOCK_ADC,
+	},
 };

=20
static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,

include/linux/mfd/stmpe.h +0 -0
index 4a827af17e59..90700013f56d 100644
@@ -10,6 +10,17 @@

=20
#include <linux/mutex.h>
=20

include/linux/mfd/stmpe.h line 22

Quoted 10 lines
include/linux/mfd/stmpe.h +10 -0
+#define SAMPLE_TIME(x)		((x & 0xf) << 4)
+#define MOD_12B(x)		((x & 0x1) << 3)
+#define REF_SEL(x)		((x & 0x1) << 1)
+#define ADC_FREQ(x)		(x & 0x3)
+#define AVE_CTRL(x)		((x & 0x3) << 6)
+#define DET_DELAY(x)		((x & 0x7) << 3)
+#define SETTLING(x)		(x & 0x7)
+#define FRACTION_Z(x)		(x & 0x7)
+#define I_DRIVE(x)		(x & 0x1)
+#define OP_MODE(x)		((x & 0x7) << 1)

I assumed that these were in keeping with naming in this file but they aren't. Should have a prefix to avoid potential name clashes in the future.

STMPE_SAMPlE_TIME etc would make sense.

Quoted 4 lines

+
struct device;
struct regulator;
=20

#8 lore raw
Quoted 13 lines · Jonathan Cameron
Quoted 10 lines · On Tue, 6 Nov 2018 17:41:14 +0100 Philippe Schenker <[email protected]> wrote:

From: Stefan Agner <[email protected]>

This adds an ADC driver for the STMPE device using the industrial input/output interface. The driver supports raw reading of values. The driver depends on the MFD STMPE driver. If the touchscreen block is enabled too, only four of the 8 ADC channels are available.

Quoted 8 lines

We are a bit limited in here I think by how it interacts with the mfd and most of my comments are about the related DT bindings.

A few comments inline.

thanks,

Jonathan

Thank you for these comments. I am preparing a v2 right now with your suggestions. Please see my comments inline. As soon I have v2 ready I will send it.

Philippe

Quoted 376 lines
Quoted 62 lines
---
 drivers/iio/adc/Kconfig              |   7 +
 drivers/iio/adc/Makefile             |   1 +
 drivers/iio/adc/stmpe-adc.c          | 383 +++++++++++++++++++++++++++
 drivers/input/touchscreen/stmpe-ts.c |  11 -
 drivers/mfd/Kconfig                  |   3 +-
 drivers/mfd/stmpe.c                  |  27 ++
 include/linux/mfd/stmpe.h            |  11 +
 7 files changed, 431 insertions(+), 12 deletions(-)
 create mode 100644 drivers/iio/adc/stmpe-adc.c
drivers/iio/adc/Kconfig +7 -0
index a52fea8749a9..d2845472b6c2 100644
@@ -734,6 +734,13 @@ config STM32_DFSDM_ADC
 	  This driver can also be built as a module.  If so, the module
 	  will be called stm32-dfsdm-adc.
 
+config STMPE_ADC
+	tristate "STMicroelectronics STMPE ADC driver"
+	depends on (OF || COMPILE_TEST || MFD_STMPE)
+	help
+	  Say yes here to build support for ST Microelectronics STMPE
+	  built in ADC block (stmpe811).
+
 config STX104
 	tristate "Apex Embedded Systems STX104 driver"
 	depends on PC104 && X86
drivers/iio/adc/Makefile +1 -0
index a6e6a0b659e2..cba889c30bf9 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
 obj-$(CONFIG_STM32_ADC) += stm32-adc.o
 obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
 obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
+obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
 obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
drivers/iio/adc/stmpe-adc.c new file +14 -0
new file mode 100644
index 000000000000..891ad838ab3c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  STMicroelectronics STMPE811 IIO ADC Driver
+ *
+ *  4 channel, 10/12-bit ADC
+ *
+ *  Copyright (C) 2013-2018 Toradex AG <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iio/events.h>

drivers/iio/adc/stmpe-adc.c line 24

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>

Not seeing any regulators in here. Please do a quick sanity check on the other headers as well. This is a long list for a fairly short bit of code!

drivers/iio/adc/stmpe-adc.c line 37

Quoted 13 lines
drivers/iio/adc/stmpe-adc.c new file +13 -0
+#include <linux/slab.h>
+
+#define STMPE_REG_INT_STA	0x0B
+#define STMPE_REG_ADC_INT_EN	0x0E
+#define STMPE_REG_ADC_INT_STA	0x0F
+
+#define STMPE_REG_ADC_CTRL1	0x20
+#define STMPE_REG_ADC_CTRL2	0x21
+#define STMPE_REG_ADC_CAPT	0x22
+#define STMPE_REG_ADC_DATA_CH(channel)	(0x30 + 2 * (channel))
+
+#define STMPE_REG_TEMP_CTRL	0x60
+#define STMPE_START_ONE_TEMP_CONV (0x08 + 0x02 + 0x01)

This is oddly put.. Is it a mask or 3 things we can otherwise define?

drivers/iio/adc/stmpe-adc.c line 44

Quoted 7 lines
drivers/iio/adc/stmpe-adc.c new file +7 -0
+#define STMPE_REG_TEMP_DATA	0x61
+#define STMPE_REG_TEMP_TH	0x63
+#define STMPE_MAX_ADC_CH	8
+
+#define STMPE_ADC_CH(channel)	((1 << (channel)) & 0xff)
+
+#define STMPE_ADC_TIMEOUT	(msecs_to_jiffies(1000))

Outer brackets don't add anything that I can see.

drivers/iio/adc/stmpe-adc.c line 46

Quoted 2 lines
drivers/iio/adc/stmpe-adc.c new file +2 -0
+
+struct stmpe_adc {

personally I always think aligning structure elements is a bad idea as breaks far too often with later additions. Still I don't care that much if you really want to do this...

Quoted 27 lines
drivers/iio/adc/stmpe-adc.c new file +27 -0
+	struct stmpe		*stmpe;
+	struct clk		*clk;
+	struct device		*dev;
+
+	struct iio_chan_spec	stmpe_adc_iio_channels[STMPE_MAX_ADC_CH];
+
+	struct completion	completion;
+
+	u8			channel;
+	u32			value;
+	u8			sample_time;
+	u8			mod_12b;
+	u8			ref_sel;
+	u8			adc_freq;
+	u32			norequest_mask;
+};
+
+static int stmpe_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val,
+				int *val2,
+				long mask)
+{
+	struct stmpe_adc *info = iio_priv(indio_dev);
+	long ret;
+
+	switch (mask) {

drivers/iio/adc/stmpe-adc.c line 83

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+
+		mutex_lock(&indio_dev->mlock);
+
+		info->channel = (u8)chan->channel;
+
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			if (info->channel > 7)

lock held.

drivers/iio/adc/stmpe-adc.c line 96

Quoted 13 lines
drivers/iio/adc/stmpe-adc.c new file +13 -0
+				return -ENOENT;
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
+					STMPE_ADC_CH(info->channel));
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
+					STMPE_ADC_CH(info->channel));
+
+			*val = info->value;
+			break;
+
+		case IIO_TEMP:
+			if (info->channel != 8)

lock held...

Quoted 66 lines
drivers/iio/adc/stmpe-adc.c new file +66 -0
+				return -ENOENT;
+
+			stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
+					STMPE_START_ONE_TEMP_CONV);
+			break;
+		default:
+			mutex_unlock(&indio_dev->mlock);
+			return -EINVAL;
+		}
+
+		ret = wait_for_completion_interruptible_timeout
+			(&info->completion, STMPE_ADC_TIMEOUT);
+
+		if (ret <= 0) {
+			mutex_unlock(&indio_dev->mlock);
+			if (ret == 0)
+				return -ETIMEDOUT;
+			else
+				return ret;
+		}
+
+
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			*val = info->value;
+			break;
+
+		case IIO_TEMP:
+			/*
+			 * absolute temp = +V3.3 * value /7.51 [K]
+			 * scale to [milli °C]
+			 */
+			*val = ((449960l * info->value) / 1024l) - 273150;
+			break;
+		default:
+			break;
+		}
+
+		mutex_unlock(&indio_dev->mlock);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = 3300;
+		*val2 = info->mod_12b ? 12 : 10;
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
+{
+	struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
+	u8 data[2];
+
+	if (info->channel > 8)
+		return IRQ_NONE;
+
+	if (info->channel < 8) {
+		int int_sta;
+
+		int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
+

drivers/iio/adc/stmpe-adc.c line 172

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+		/* Is the interrupt relevant */
+		if (!(int_sta & STMPE_ADC_CH(info->channel)))
+			return IRQ_NONE;
+
+		/* Read value */
+		stmpe_block_read(info->stmpe,
+			STMPE_REG_ADC_DATA_CH(info->channel), 2, data);
+
+		stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
+	} else if (info->channel == 8) {

That 8 is pretty magic, perhaps a define given it keeps being used?

Quoted 87 lines
drivers/iio/adc/stmpe-adc.c new file +87 -0
+		/* Read value */
+		stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2, data);
+	}
+
+	info->value = ((u32)data[0] << 8) + data[1];
+	complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_info stmpe_adc_iio_info = {
+	.read_raw = &stmpe_read_raw,
+};
+
+static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan)
+{
+	ics->type = IIO_VOLTAGE;
+	ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+	ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+	ics->indexed = 1;
+	ics->channel = chan;
+}
+
+static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan)
+{
+	ics->type = IIO_TEMP;
+	ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
+	ics->indexed = 1;
+	ics->channel = chan;
+}
+
+static int stmpe_adc_init_hw(struct stmpe_adc *adc)
+{
+	int ret;
+	u8 adc_ctrl1, adc_ctrl1_mask;
+	struct stmpe *stmpe = adc->stmpe;
+	struct device *dev = adc->dev;
+
+	ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC);
+	if (ret) {
+		dev_err(dev, "Could not enable clock for ADC\n");
+		goto err_adc;
+	}
+
+	adc_ctrl1 = SAMPLE_TIME(adc->sample_time) | MOD_12B(adc->mod_12b) |
+			REF_SEL(adc->ref_sel);
+	adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
+
+	ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+			adc_ctrl1_mask, adc_ctrl1);
+	if (ret) {
+		dev_err(dev, "Could not setup ADC\n");
+		goto err_adc;
+	}
+
+	ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+			ADC_FREQ(0xff), ADC_FREQ(adc->adc_freq));
+	if (ret) {
+		dev_err(dev, "Could not setup ADC\n");
+		goto err_adc;
+	}
+
+	/* use temp irq for each conversion completion */
+	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
+	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
+
+	return 0;
+err_adc:
+	stmpe_disable(stmpe, STMPE_BLOCK_ADC);
+
+	return ret;
+}
+
+static void stmpe_adc_get_platform_info(struct platform_device *pdev,
+					struct stmpe_adc *adc)
+{
+	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *np = pdev->dev.of_node;
+	u32 val;
+
+	adc->stmpe = stmpe;
+
+	if (!np) {
+		dev_err(&pdev->dev, "no device tree node found\n");
+		return;
+	}
+

drivers/iio/adc/stmpe-adc.c line 269

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	if (!of_property_read_u32(np, "st,sample-time", &val))
+		adc->sample_time = val;
+	if (!of_property_read_u32(np, "st,mod-12b", &val))
+		adc->mod_12b = val;
+	if (!of_property_read_u32(np, "st,ref-sel", &val))
+		adc->ref_sel = val;
+	if (!of_property_read_u32(np, "st,adc-freq", &val))
+		adc->adc_freq = val;
+	if (!of_property_read_u32(np, "st,norequest-mask", &val))
+		adc->norequest_mask = val;

I commented on these in the dt-binding patch, so I won't mention them any more here.

Quoted 36 lines
drivers/iio/adc/stmpe-adc.c new file +36 -0
+}
+
+static int stmpe_adc_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = NULL;
+	struct stmpe_adc *info = NULL;
+	int irq_temp, irq_adc;
+	int num_chan = 0;
+	int i = 0;
+	int ret;
+
+	irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC");
+	if (irq_adc < 0)
+		return irq_adc;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc));
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	info = iio_priv(indio_dev);
+
+	init_completion(&info->completion);
+	ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL,
+					stmpe_adc_isr, IRQF_ONESHOT,
+					"stmpe-adc", info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
+				irq_adc);
+		return ret;
+	}
+
+	irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
+	if (irq_temp >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL,
Quoted 8 lines

drivers/iio/adc/stmpe-adc.c line 311

Quoted 6 lines
drivers/iio/adc/stmpe-adc.c new file +6 -0
+						stmpe_adc_isr, IRQF_ONESHOT,
+						"stmpe-adc", info);
+		if (ret < 0)
+			dev_warn(&pdev->dev, "failed requesting irq for"
+					" temp sensor, irq = %d\n", irq_temp);
+	}

I'd like a comment here that perhaps says what the result of not having an irq for the temperature sensor is?

Basically the STMPE device has only one hardware interrupt. This is initialized in drivers/mfd/stmpe.c (1171). So if there is no error in mfd, we can expect it to work in here.

Quoted 201 lines
Quoted 19 lines
drivers/iio/adc/stmpe-adc.c new file +13 -0
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &stmpe_adc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	stmpe_adc_get_platform_info(pdev, info);
+
+	for_each_clear_bit(i, (unsigned long *) &info->norequest_mask,
+				STMPE_MAX_ADC_CH) {
+		stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan],

i);

drivers/iio/adc/stmpe-adc.c new file +4 -0
+		num_chan++;
+	}
+	stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i);
+	num_chan++;

drivers/iio/adc/stmpe-adc.c line 338

Quoted 10 lines
drivers/iio/adc/stmpe-adc.c new file +10 -0
+	indio_dev->channels = info->stmpe_adc_iio_channels;
+	indio_dev->num_channels = num_chan;
+
+	ret = stmpe_adc_init_hw(info);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		return ret;

one blank line is plenty.

drivers/iio/adc/stmpe-adc.c line 341

Quoted 3 lines
drivers/iio/adc/stmpe-adc.c new file +3 -0
+
+
+	dev_info(&pdev->dev, "Initialized\n");

This is just noise in the log. There are lots of ways of finding out if this came up if you actually want to so no need for the print here.

Quoted 52 lines
drivers/iio/adc/stmpe-adc.c new file +42 -0
+
+	return 0;
+}
+
+static int stmpe_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct stmpe_adc *info = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	stmpe_disable(info->stmpe, STMPE_BLOCK_ADC);
+
+	return 0;
+}
+
+static int __maybe_unused stmpe_adc_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct stmpe_adc *info = iio_priv(indio_dev);
+
+	stmpe_adc_init_hw(info);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
+
+static struct platform_driver stmpe_adc_driver = {
+	.probe		= stmpe_adc_probe,
+	.remove		= stmpe_adc_remove,
+	.driver		= {
+		.name	= "stmpe-adc",
+		.pm	= &stmpe_adc_pm_ops,
+	},
+};
+
+module_platform_driver(stmpe_adc_driver);
+
+MODULE_AUTHOR("Stefan Agner <[email protected]>");
+MODULE_DESCRIPTION("STMPEXXX ADC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:stmpe-adc");
drivers/input/touchscreen/stmpe-ts.c +0 -1
index 2a78e27b4495..05674e0e233f 100644
@@ -49,17 +49,6 @@
 
 #define STMPE_IRQ_TOUCH_DET		0
 
-#define SAMPLE_TIME(x)			((x & 0xf) << 4)

drivers/input/touchscreen/stmpe-ts.c line 62

Quoted 10 lines
drivers/input/touchscreen/stmpe-ts.c +0 -10
-#define MOD_12B(x)			((x & 0x1) << 3)
-#define REF_SEL(x)			((x & 0x1) << 1)
-#define ADC_FREQ(x)			(x & 0x3)
-#define AVE_CTRL(x)			((x & 0x3) << 6)
-#define DET_DELAY(x)			((x & 0x7) << 3)
-#define SETTLING(x)			(x & 0x7)
-#define FRACTION_Z(x)			(x & 0x7)
-#define I_DRIVE(x)			(x & 0x1)
-#define OP_MODE(x)			((x & 0x7) << 1)
-

Given the need for prefixes in the header (see below) I would do this move as a precursor patch including renames in the touchscreen driver...

Quoted 77 lines
drivers/input/touchscreen/stmpe-ts.c +0 -0
 #define STMPE_TS_NAME			"stmpe-ts"
 #define XY_MASK				0xfff
 
drivers/mfd/Kconfig +2 -1
index 8c5dfdce4326..bba159e8eaa4 100644
@@ -1204,7 +1204,7 @@ config MFD_STMPE
 
 	  Currently supported devices are:
 
-		STMPE811: GPIO, Touchscreen
+		STMPE811: GPIO, Touchscreen, ADC
 		STMPE1601: GPIO, Keypad
 		STMPE1801: GPIO, Keypad
 		STMPE2401: GPIO, Keypad
@@ -1217,6 +1217,7 @@ config MFD_STMPE
 		GPIO: stmpe-gpio
 		Keypad: stmpe-keypad
 		Touchscreen: stmpe-ts
+		ADC: stmpe-adc
 
 menu "STMicroelectronics STMPE Interface Drivers"
 depends on MFD_STMPE
drivers/mfd/stmpe.c +27 -0
index 566caca4efd8..00b98f75f7dd 100644
@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = {
 	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
 };
 
+/*
+ * ADC (STMPE811)
+ */
+
+static struct resource stmpe_adc_resources[] = {
+	{
+		.name	= "STMPE_TEMP_SENS",
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "STMPE_ADC",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static const struct mfd_cell stmpe_adc_cell = {
+	.name		= "stmpe-adc",
+	.of_compatible	= "st,stmpe-adc",
+	.resources	= stmpe_adc_resources,
+	.num_resources	= ARRAY_SIZE(stmpe_adc_resources),
+};
+
 /*
  * STMPE811 or STMPE610
  */
@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
 		.irq	= STMPE811_IRQ_TOUCH_DET,
 		.block	= STMPE_BLOCK_TOUCHSCREEN,
 	},
+	{
+		.cell	= &stmpe_adc_cell,
+		.irq	= STMPE811_IRQ_TEMP_SENS,
+		.block	= STMPE_BLOCK_ADC,
+	},
 };
 
 static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
include/linux/mfd/stmpe.h +0 -0
index 4a827af17e59..90700013f56d 100644
@@ -10,6 +10,17 @@
 
 #include <linux/mutex.h>
 

include/linux/mfd/stmpe.h line 22

Quoted 10 lines
include/linux/mfd/stmpe.h +10 -0
+#define SAMPLE_TIME(x)		((x & 0xf) << 4)
+#define MOD_12B(x)		((x & 0x1) << 3)
+#define REF_SEL(x)		((x & 0x1) << 1)
+#define ADC_FREQ(x)		(x & 0x3)
+#define AVE_CTRL(x)		((x & 0x3) << 6)
+#define DET_DELAY(x)		((x & 0x7) << 3)
+#define SETTLING(x)		(x & 0x7)
+#define FRACTION_Z(x)		(x & 0x7)
+#define I_DRIVE(x)		(x & 0x1)
+#define OP_MODE(x)		((x & 0x7) << 1)

I assumed that these were in keeping with naming in this file but they aren't. Should have a prefix to avoid potential name clashes in the future.

STMPE_SAMPlE_TIME etc would make sense.

Quoted 4 lines
include/linux/mfd/stmpe.h +1 -0
+
 struct device;
 struct regulator;