imx25 adc and touchscreen driver
Subsystems (7)
v5 cover imx25 adc and touchscreen driver
Hi,
This series adds a driver for the Freescale i.MX25 SoC internal ADC unit which is used for touchscreen and ADC. The driver consists of three parts, the MFD driver which handles interrupts and some central configuration registers, the ADC driver and the touchscreen driver.
The last couple of versions of this series were pushed by Denis, thanks. Now I tried to work on the comments of the last version v4 of last year.
v5 has a lot of smaller changes, listed below. I also fixed the touchscreen driver to reduce the number of interrupts. The drivers first version was designed to start a new conversion whenever we got a conversion done or a pendown was detected. This lead to a lot of interrupts. Instead we use the ability of the hardware unit to repeat a conversion queue automatically with a repeat wait timer. This is done in hardware and configured only once in software to a constant value.
Best regards,
Markus
Changes in v5:
- Removed module owner assingments from all drivers
- Added missing kconfig dependencies
- Separated DT binding documentation
- Fixed locking for the gcq driver
- Fixed a lot of style issues with the newer checkpatch tool, e.g. alignment of breaked lines
Denis Carikli (2):
ARM: dts: imx25: Add TSC and ADC support
ARM: imx_v4_v5_defconfig: Add I.MX25 Touchscreen controller and ADC
support.
Markus Pargmann (4):
mfd: fsl imx25 Touchscreen ADC driver
ARM: dt: Binding documentation for imx25 ADC/TSC
iio: adc: fsl,imx25-gcq driver
input: touchscreen: imx25 tcq driver
.../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 51 ++ .../bindings/input/touchscreen/fsl-mx25-tcq.txt | 29 + .../devicetree/bindings/mfd/fsl-imx25-tsadc.txt | 46 ++ arch/arm/boot/dts/imx25.dtsi | 30 +- arch/arm/configs/imx_v4_v5_defconfig | 4 + drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 369 +++++++++++++ drivers/input/touchscreen/Kconfig | 6 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/fsl-imx25-tcq.c | 587 +++++++++++++++++++++ drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 2 + drivers/mfd/fsl-imx25-tsadc.c | 167 ++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 11 + include/linux/mfd/imx25-tsadc.h | 140 +++++ 16 files changed, 1458 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt create mode 100644 Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c create mode 100644 drivers/input/touchscreen/fsl-imx25-tcq.c create mode 100644 drivers/mfd/fsl-imx25-tsadc.c create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.h create mode 100644 include/linux/mfd/imx25-tsadc.h
Signature · 1 line
2.1.4
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
This is the core driver for imx25 touchscreen/adc driver. The module has one shared ADC and two different conversion queues which use the ADC. The two queues are identical. Both can be used for general purpose ADC but one is meant to be used for touchscreens.
This driver is the core which manages the central components and registers of the TSC/ADC unit. It manages the IRQs and forwards them to the correct components.
---
Notes:
Changes in v5:
- Remove ifdef CONFIG_OF as this driver is only for DT usage
- Remove module owner
- Add Kconfig dependencies ARCH_MX25 and OF
@Jonathan Cameron:
I left your acked-by on the patch as these were small changes. If it should be removed, please say so. Thanks
drivers/mfd/Kconfig | 10 +++ drivers/mfd/Makefile | 2 + drivers/mfd/fsl-imx25-tsadc.c | 167 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/imx25-tsadc.h | 140 +++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 drivers/mfd/fsl-imx25-tsadc.c create mode 100644 include/linux/mfd/imx25-tsadc.h
drivers/mfd/Kconfig +10 -0
@@ -232,6 +232,16 @@ config MFD_MC13XXX_I2C help Select this if your MC13xxx is connected via an I2C bus. +config MFD_MX25_TSADC + tristate "Freescale i.MX25 integrated Touchscreen and ADC unit" + select REGMAP_MMIO + depends on SOC_IMX25 + depends on OF + help + Enable support for the integrated Touchscreen and ADC unit of the + i.MX25 processors. They consist of a conversion queue for general + purpose ADC and a queue for Touchscreens. + config MFD_HI6421_PMIC tristate "HiSilicon Hi6421 PMU/Codec IC" depends on OF
drivers/mfd/Makefile +2 -0
@@ -78,6 +78,8 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o obj-$(CONFIG_TWL6040_CORE) += twl6040.o +obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o + obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
drivers/mfd/fsl-imx25-tsadc.c new file +167 -0
167 lines not on this page · raw message
include/linux/mfd/imx25-tsadc.h new file +140 -0
140 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 95 lines · Markus Pargmann
This is the core driver for imx25 touchscreen/adc driver. The module has one shared ADC and two different conversion queues which use the ADC. The two queues are identical. Both can be used for general purpose ADC but one is meant to be used for touchscreens.
This driver is the core which manages the central components and registers of the TSC/ADC unit. It manages the IRQs and forwards them to the correct components.
Signed-off-by Markus Pargmann <[email protected]>Signed-off-by Denis Carikli <[email protected]>Acked-by Jonathan Cameron <[email protected]>---
Notes:
Changes in v5:
- Remove ifdefCONFIG_OFas this driver is only for DT usage
- Remove module owner
- AddKconfigdependenciesARCH_MX25and OF@Jonathan Cameron:
I left your acked-by on the patch as these were small changes. If it should be removed, please say so. Thanksdrivers/mfd/Kconfig | 10 +++ drivers/mfd/Makefile | 2 + drivers/mfd/fsl-imx25-tsadc.c | 167 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/imx25-tsadc.h | 140 +++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 drivers/mfd/fsl-imx25-tsadc.c create mode 100644 include/linux/mfd/imx25-tsadc.hdrivers/mfd/Kconfig +10
-0@@ -232,6 +232,16 @@ config MFD_MC13XXX_I2C help Select this if your MC13xxx is connected via an I2C bus. +config MFD_MX25_TSADC + tristate "Freescale i.MX25 integrated Touchscreen and ADC unit" + select REGMAP_MMIO + depends on SOC_IMX25 + depends on OF + help + Enable support for the integrated Touchscreen and ADC unit of the + i.MX25 processors. They consist of a conversion queue for general + purpose ADC and a queue for Touchscreens. + config MFD_HI6421_PMIC tristate "HiSilicon Hi6421 PMU/Codec IC" depends on OFdrivers/mfd/Makefile +2
-0@@ -78,6 +78,8 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o obj-$(CONFIG_TWL6040_CORE) += twl6040.o +obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o + obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.odrivers/mfd/fsl-imx25-tsadc.c new file +23
-0@@ -0,0 +1,167 @@ +/* +* Copyright 2014 Markus Pargmann, Pengutronix <[email protected]> +* +* The code contained herein is licensed under the GNU General Public +* License. You may obtain a copy of the GNU General Public License +* Version 2 or later at the following locations: +* +* http://www.opensource.org/licenses/gpl-license.html +* http://www.gnu.org/copyleft/gpl.html +*/ + +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/irqdesc.h> +#include <linux/irqdomain.h> +#include <linux/irq.h> +#include <linux/mfd/imx25-tsadc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/regmap.h>
[...]
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {
What if 0 is returned?
Quoted 23 lines
drivers/mfd/fsl-imx25-tsadc.c new file +16
-0+dev_err (dev,"Failed to get irq\n" ); +return irq; + } + + tsadc->domain =irq_domain_add_simple (np,2 ,0 , &mx25_tsadc_domain_ops, + tsadc); +if (!tsadc->domain) { +dev_err (dev,"Failed to add irq domain\n" ); +return -ENOMEM ; + } + +irq_set_chained_handler (irq, mx25_tsadc_irq_handler); +irq_set_handler_data (irq, tsadc); + +return 0 ; +}include/linux/mfd/imx25-tsadc.h new file +0
-0
include/linux/mfd/imx25-tsadc.h line 2
Quoted 2 lines
include/linux/mfd/imx25-tsadc.h new file +2
-0@@ -0,0 +1,140 @@ +#ifndef _LINUX_INCLUDE_INPUT_IMX25_TSADC_H_ +#define _LINUX_INCLUDE_INPUT_IMX25_TSADC_H_
INPUT?
Signature · 4 lines
Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
Fabio Estevam
reviewerPATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 11 lines · Lee Jones
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {What if 0 is returned?
Then imx25.dtsi would be passing irq=0 for the ADC, which would be totally wrong.
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 14 lines · Fabio Estevam
Quoted 11 lines · Lee Jones
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {What if 0 is returned?
Quoted 2 lines
Then
imx25.dtsiwould be passing irq=0 for the ADC, which would be totally wrong.
Exactly, so it should be <=.
Signature · 4 lines
Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
Fabio Estevam
reviewerPATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 16 lines · Lee Jones
Quoted 14 lines · Fabio Estevam
Quoted 11 lines · Lee Jones
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {What if 0 is returned?
Quoted 4 lines
Quoted 2 lines
Then
imx25.dtsiwould be passing irq=0 for the ADC, which would be totally wrong.Exactly, so it should be <=.
imx25.dtsi passes interrupts = <46>; for the touch screen controller, so the irq number will never be zero.
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 17 lines · Fabio Estevam
Quoted 16 lines · Lee Jones
Quoted 14 lines · Fabio Estevam
Quoted 11 lines · Lee Jones
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {What if 0 is returned?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Then
imx25.dtsiwould be passing irq=0 for the ADC, which would be totally wrong.Exactly, so it should be <=.
imx25.dtsipasses interrupts = <46>; for the touch screen controller, so the irq number will never be zero.
It doesn't matter what happens to be passed at the moment. The correct thing to do is enforce correct/full error checking. Yes <0 is an error, but so is =0, so encompass it in the checks.
Signature · 4 lines
Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Quoted 22 lines · Lee Jones
Quoted 20 lines · Fabio Estevam
Quoted 19 lines · Lee Jones
Quoted 16 lines · Fabio Estevam
Quoted 11 lines · Lee Jones
drivers/mfd/fsl-imx25-tsadc.c line 78
Quoted 9 lines
drivers/mfd/fsl-imx25-tsadc.c new file +9
-0+static int mx25_tsadc_setup_irq (struct platform_device *pdev, +struct mx25_tsadc *tsadc) +{ +struct device *dev = &pdev->dev; +struct device_node *np = dev->of_node; +int irq; + + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) {What if 0 is returned?
Then
imx25.dtsiwould be passing irq=0 for the ADC, which would be totally wrong.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Exactly, so it should be <=.
imx25.dtsipasses interrupts = <46>; for the touch screen controller, so the irq number will never be zero.It doesn't matter what happens to be passed at the moment. The correct thing to do is enforce correct/full error checking. Yes <0 is an error, but so is =0, so encompass it in the checks.
I now changed all irq < 0 checks to irq <= 0 under the assumption that irq 0 is always an error.
Thanks,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150226/1944dc3f/attachment.sig>
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
In reply to Markus PargmannHello Markus,
drivers/mfd/Kconfig config MFD_MC13XXX_I2C · line 238
Quoted 4 lines · Markus Pargmann
drivers/mfd/Kconfig +4
-0+config MFD_MX25_TSADC + tristate "Freescale i.MX25 integrated Touchscreen and ADC unit" + select REGMAP_MMIO + depends on SOC_IMX25
Can you make that:
depends on SOC_IMX25 || COMPILE_TEST
?
Quoted 3 lines
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
Which version of the GPL is your code licensed under?
drivers/mfd/fsl-imx25-tsadc.c line 91
Quoted 5 lines
drivers/mfd/fsl-imx25-tsadc.c new file +4
-0+static int mx25_tsadc_setup_irq(struct platform_device *pdev, + struct mx25_tsadc *tsadc) + irq_set_chained_handler(irq, mx25_tsadc_irq_handler); +irq_set_handler_data (irq ,tsadc );
Do you need to reverse the order of these two calls to prevent the handler being called while handler_data is still unset?
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH v5 1/6 mfd: fsl imx25 Touchscreen ADC driver
Hi,
Quoted 9 lines · Uwe Kleine-K?nig
Hello Markus,
drivers/mfd/Kconfig config MFD_MC13XXX_I2C · line 238
Quoted 4 lines · Markus Pargmann
drivers/mfd/Kconfig +4
-0+config MFD_MX25_TSADC + tristate "Freescale i.MX25 integrated Touchscreen and ADC unit" + select REGMAP_MMIO + depends on SOC_IMX25Can you make that:
Quoted 3 lines
depends on SOC_IMX25 || COMPILE_TEST?
Yes, changed.
Quoted 5 lines
Quoted 4 lines
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:Which version of the GPL is your code licensed under?
GPLv2 as described by MODULE_LICENSE. Will change the header accordingly.
Quoted 8 lines
drivers/mfd/fsl-imx25-tsadc.c line 91
Quoted 6 lines
drivers/mfd/fsl-imx25-tsadc.c new file +4
-0+static int mx25_tsadc_setup_irq(struct platform_device *pdev, + struct mx25_tsadc *tsadc) + irq_set_chained_handler(irq, mx25_tsadc_irq_handler); +irq_set_handler_data (irq ,tsadc );Do you need to reverse the order of these two calls to prevent the handler being called while
handler_datais still unset?
Yes that's probably better although the subdevices which may cause interrupts here are not populated at this point.
Thanks,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150302/29932a84/attachment.sig>
PATCH v5 2/6 ARM: dt: Binding documentation for imx25 ADC/TSC
In reply to Markus PargmannThis documentation describes the devicetree bindings for the ADC/Touchscreen unit of the i.MX25 SoC.
--- .../devicetree/bindings/mfd/fsl-imx25-tsadc.txt | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt
Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt new file +46 -0
@@ -0,0 +1,46 @@ +Freescale mx25 ADC/TSC multifunction device + +This device combines two general purpose conversion queues one used for general +ADC and the other used for touchscreens. + +Required properties: + - compatible: Should be "fsl,imx25-tsadc". + - reg: Memory range of the device. + - interrupts: Interrupt for this device as described in + interrupts/interrupts.txt + - clocks: An 'ipg' clock defined as described in clocks/clock.txt + - interrupt-controller: This device is an interrupt controller. It controls + the interrupts of both conversion queues. + - #interrupt-cells: Should be '<1>'. + - #address-cells: Should be '<1>'. + - #size-cells: Should be '<1>'. + - ranges + +This device includes two conversion queues which can be added as subnodes. +The first queue is for the touchscreen, the second for general purpose ADC. + +Example: + tscadc: tscadc at 50030000 { + compatible = "fsl,imx25-tsadc"; + reg = <0x50030000 0xc>; + interrupts = <46>; + clocks = <&clks 119>; + clock-names = "ipg"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + tsc: tcq at 50030400 { + compatible = "fsl,imx25-tcq"; + reg = <0x50030400 0x60>; + ... + }; + + adc: gcq at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + ... + }; + };
Signature · 1 line
2.1.4
PATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
In reply to Markus PargmannThis is a conversion queue driver for the mx25 SoC. It uses the central ADC which is used by two seperate independent queues. This driver prepares different conversion configurations for each possible input. For a conversion it creates a conversionqueue of one item with the correct configuration for the chosen channel. It then executes the queue once and disables the conversion queue afterwards.
The reference voltages are configurable through devicetree subnodes, depending on the connections of the ADC inputs.
---
Notes:
Changes in v5:
- Fixed locking
- Removed module owner
.../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 51 +++ drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 369 +++++++++++++++++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 11 + 5 files changed, 439 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.h
Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt new file +51 -0
@@ -0,0 +1,51 @@ +Freescale i.MX25 ADC GCQ device + +This is a generic conversion queue device that can convert any of the +analog inputs using the ADC unit of the i.MX25. + +Required properties: + - compatible: Should be "fsl,imx25-gcq". + - reg: Should be the register range of the module. + - interrupts: Should be the interrupt number of the module. + Typically this is <1>. + - interrupt-parent: phandle to the tsadc module of the i.MX25. + - #address-cells: Should be <1> (setting for the subnodes) + - #size-cells: Should be <0> (setting for the subnodes) + +Optional properties: + - vref-supply: The regulator supplying the ADC reference voltage. + Required when at least one subnode uses the external reference. + +Sub-nodes: +Optionally you can define subnodes which define the reference voltage +for the analog inputs. + +Required properties for subnodes: + - reg: Should be the number of the analog input. + 0: xp + 1: yp + 2: xn + 3: yn + 4: wiper + 5: inaux0 + 6: inaux1 + 7: inaux2 + - fsl,adc-ref: specifies the reference input as defined in + <dt-bindings/iio/adc/fsl-imx25-gcq.h> + MX25_ADC_REF_INT and MX25_ADC_REF_EXT flags are supported. + +Example: + + adc: adc at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + + inaux at 5 { + reg = <5>; + fsl,adc-ref = <MX25_ADC_REF_INT>; + }; + };
drivers/iio/adc/Kconfig +7 -0
@@ -143,6 +143,13 @@ config EXYNOS_ADC of SoCs for drivers such as the touchscreen and hwmon to use to share this resource. +config FSL_MX25_ADC + tristate "Freescale MX25 ADC driver" + depends on MFD_MX25_TSADC + help + Generic Conversion Queue driver used for general purpose ADC in the + MX25. This driver supports single measurements using the MX25 ADC. + config LP8788_ADC tristate "LP8788 ADC driver" depends on MFD_LP8788
drivers/iio/adc/Makefile +1 -0
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o
drivers/iio/adc/fsl-imx25-gcq.c new file +369 -0
369 lines not on this page · raw message
include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +11 -0
@@ -0,0 +1,11 @@ +/* +* This header provides constants for configuring the I.MX25 ADC +*/ + +#ifndef _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H +#define _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H + +#define MX25_ADC_REF_INT 0/* Internal voltage reference */ +#define MX25_ADC_REF_EXT 1/* External voltage reference */ + +#endif
Signature · 1 line
2.1.4
Jonathan Cameron
maintainerPATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
Quoted 7 lines · Markus Pargmann
This is a conversion queue driver for the mx25 SoC. It uses the central ADC which is used by two seperate independent queues. This driver prepares different conversion configurations for each possible input. For a conversion it creates a conversionqueue of one item with the correct configuration for the chosen channel. It then executes the queue once and disables the conversion queue afterwards.
Quoted 5 lines
The reference voltages are configurable through devicetree subnodes, depending on the connections of the ADC inputs.
Signed-off-by Markus Pargmann <[email protected]>Signed-off-by Denis Carikli <[email protected]>
A couple of queries inline.
Quoted 245 lines
---
Notes:
Changes in v5:
- Fixed locking
- Removed module owner.../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 51 +++ drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 369 +++++++++++++++++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 11 + 5 files changed, 439 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.hDocumentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt new file +51
-0@@ -0,0 +1,51 @@ +Freescale i.MX25 ADC GCQ device + +This is a generic conversion queue device that can convert any of the +analog inputs using the ADC unit of the i.MX25. + +Required properties: + - compatible: Should be "fsl,imx25-gcq". + - reg: Should be the register range of the module. + - interrupts: Should be the interrupt number of the module. + Typically this is <1>. + - interrupt-parent: phandle to the tsadc module of the i.MX25. + - #address-cells: Should be <1> (setting for the subnodes) + - #size-cells: Should be <0> (setting for the subnodes) + +Optional properties: + - vref-supply: The regulator supplying the ADC reference voltage. + Required when at least one subnode uses the external reference. + +Sub-nodes: +Optionally you can define subnodes which define the reference voltage +for the analog inputs. + +Required properties for subnodes: + - reg: Should be the number of the analog input. + 0: xp + 1: yp + 2: xn + 3: yn + 4: wiper + 5: inaux0 + 6: inaux1 + 7: inaux2 + - fsl,adc-ref: specifies the reference input as defined in + <dt-bindings/iio/adc/fsl-imx25-gcq.h> + MX25_ADC_REF_INT and MX25_ADC_REF_EXT flags are supported. + +Example: + + adc: adc at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + + inaux at 5 { + reg = <5>; + fsl,adc-ref = <MX25_ADC_REF_INT>; + }; + };drivers/iio/adc/Kconfig +7
-0@@ -143,6 +143,13 @@ config EXYNOS_ADC of SoCs for drivers such as the touchscreen and hwmon to use to share this resource. +config FSL_MX25_ADC + tristate "Freescale MX25 ADC driver" + depends on MFD_MX25_TSADC + help + Generic Conversion Queue driver used for general purpose ADC in the + MX25. This driver supports single measurements using the MX25 ADC. + config LP8788_ADC tristate "LP8788 ADC driver" depends on MFD_LP8788drivers/iio/adc/Makefile +1
-0@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.odrivers/iio/adc/fsl-imx25-gcq.c new file +135
-0@@ -0,0 +1,369 @@ +/* +* Copyright 2014 Markus Pargmann, Pengutronix <[email protected]> +* +* The code contained herein is licensed under the GNU General Public +* License. You may obtain a copy of the GNU General Public License +* Version 2 or later at the following locations: +* +* http://www.opensource.org/licenses/gpl-license.html +* http://www.gnu.org/copyleft/gpl.html +* +* This is the driver for the imx25 GCQ (Generic Conversion Queue) +* connected to the imx25 ADC. +*/ + +#include <dt-bindings/iio/adc/fsl-imx25-gcq.h> +#include <linux/clk.h> +#include <linux/iio/iio.h> +#include <linux/interrupt.h> +#include <linux/mfd/imx25-tsadc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000)) + +enum mx25_gcq_cfgs { +MX25_CFG_XP =0 , +MX25_CFG_YP , +MX25_CFG_XN , +MX25_CFG_YN , +MX25_CFG_WIPER , +MX25_CFG_INAUX0 , +MX25_CFG_INAUX1 , +MX25_CFG_INAUX2 , +MX25_NUM_CFGS , +}; + +struct mx25_gcq_priv { +struct regmap *regs; +struct completion completed; +unsigned int settling_time; +struct clk *clk; +int irq; +struct regulator *ext_vref; +u32 channel_vref_mv[MX25_NUM_CFGS ]; +}; + +#define MX25_CQG_CHAN (chan, id) {\ + .type = IIO_VOLTAGE,\ + .indexed = 1,\ + .channel = chan,\ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .datasheet_name = id,\ +} + +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS ] = { +MX25_CQG_CHAN (0 ,"xp" ), +MX25_CQG_CHAN (1 ,"yp" ), +MX25_CQG_CHAN (2 ,"xn" ), +MX25_CQG_CHAN (3 ,"yn" ), +MX25_CQG_CHAN (4 ,"wiper" ), +MX25_CQG_CHAN (5 ,"inaux0" ), +MX25_CQG_CHAN (6 ,"inaux1" ), +MX25_CQG_CHAN (7 ,"inaux2" ), +}; + +static void mx25_gcq_disable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR ,MX25_ADCQ_MR_EOQ_IRQ , +MX25_ADCQ_MR_EOQ_IRQ ); +} + +static void mx25_gcq_enable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR , +MX25_ADCQ_MR_EOQ_IRQ ,0 ); +} + +static irqreturn_t mx25_gcq_irq (int irq,void *data) +{ +struct mx25_gcq_priv *priv = data; +u32 stats; + +regmap_read (priv->regs,MX25_ADCQ_SR , &stats); + +if (stats &MX25_ADCQ_SR_EOQ ) { +mx25_gcq_disable_eoq (priv); +complete (&priv->completed); + } + +/* Disable conversion queue run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS ,0 ); + +/* Acknowledge all possible irqs */ +regmap_write (priv->regs,MX25_ADCQ_SR ,MX25_ADCQ_SR_FRR | +MX25_ADCQ_SR_FUR |MX25_ADCQ_SR_FOR | +MX25_ADCQ_SR_EOQ |MX25_ADCQ_SR_PD ); + +return IRQ_HANDLED ; +} + +static int mx25_gcq_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan,int *val, +int *val2,long mask) +{ +struct mx25_gcq_priv *priv =iio_priv (indio_dev); +long timeout; +u32 data; +int ret =0 ; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +mutex_lock (&indio_dev->mlock); + +/* Setup the configuration we want to use */ +regmap_write (priv->regs,MX25_ADCQ_ITEM_7_0 , +MX25_ADCQ_ITEM (0 , chan->channel)); + +mx25_gcq_enable_eoq (priv); + +/* Trigger queue for one run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS , +MX25_ADCQ_CR_FQS ); + + timeout =wait_for_completion_interruptible_timeout ( + &priv->completed,MX25_GCQ_TIMEOUT ); +if (timeout <0 ) { +dev_err (&indio_dev->dev, +"ADC wait for measurement failed\n" ); + ret = timeout; + goto info_raw_out; + }else if (timeout ==0 ) {
drivers/iio/adc/fsl-imx25-gcq.c line 145
Quoted 10 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +10
-0+dev_err (&indio_dev->dev,"ADC timed out\n" ); + ret = -ETIMEDOUT ; + goto info_raw_out; + } + +regmap_read (priv->regs,MX25_ADCQ_FIFO , &data); + + *val =MX25_ADCQ_FIFO_DATA (data); + ret =IIO_VAL_INT ; +info_raw_out:
Having this label and exit path in the middle is ugly. Perhaps break out this case statement content as a separate function?
Quoted 34 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +34
-0+mutex_unlock (&indio_dev->mlock); + +return ret; + +case IIO_CHAN_INFO_SCALE : + *val = priv->channel_vref_mv[chan->channel]; + *val2 =12 ; +return IIO_VAL_FRACTIONAL_LOG2 ; + +default : +return -EINVAL ; + } +} + +static const struct iio_info mx25_gcq_iio_info = { + .read_raw = mx25_gcq_read_raw, +}; + +static const struct regmap_config mx25_gcq_regconfig = { + .max_register =0x5c , + .reg_bits =32 , + .val_bits =32 , + .reg_stride =4 , +}; + +static int mx25_gcq_setup_cfgs (struct platform_device *pdev, +struct mx25_gcq_priv *priv) +{ +struct device_node *np = pdev->dev.of_node; +struct device_node *child; +struct device *dev = &pdev->dev; +int ret, i; + +/*
drivers/iio/adc/fsl-imx25-gcq.c line 189
Quoted 10 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +10
-0+* Setup all configurations registers with a default conversion +* configuration for each input +*/ +for (i =0 ; i <MX25_NUM_CFGS ; ++i) + regmap_write(priv->regs, MX25_ADCQ_CFG(i), + MX25_ADCQ_CFG_YPLL_OFF | + MX25_ADCQ_CFG_XNUR_OFF | + MX25_ADCQ_CFG_XPUL_OFF | + MX25_ADCQ_CFG_REFP_INT | + (i << 4) |
Again, given all the definitions i'd expect the shift to be a defined constant as well. Perhaps even a macro taking i as an arguement.
Quoted 45 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +45
-0+ MX25_ADCQ_CFG_REFN_NGND2); + +for_each_child_of_node (np, child) { +u32 reg; +u32 refp; +u32 adc_ref; + + ret =of_property_read_u32 (child,"reg" , ®); +if (ret) { +dev_err (dev,"Failed to get reg property\n" ); +return ret; + } + +if (reg >=MX25_NUM_CFGS ) { +dev_err (dev, +"reg value is greater than the number of available configuration registers\n" ); +return -EINVAL ; + } + + ret =of_property_read_u32 (child,"fsl,adc-ref" , &adc_ref); +if (ret) { +dev_err (dev,"Failed to get fsl,adc-ref property\n" ); +return ret; + } + +if (adc_ref !=MX25_ADC_REF_INT && + adc_ref !=MX25_ADC_REF_EXT ) { +dev_err (dev,"Invalid fsl,adc-refp property value %d\n" , + adc_ref); +return -EINVAL ; + } + +switch (adc_ref) { +case MX25_ADC_REF_EXT : +if (IS_ERR_OR_NULL (priv->ext_vref)) { +dev_err (dev, +"No regulator found for the external vref\n" ); +return -EINVAL ; + } + priv->channel_vref_mv[reg] = +regulator_get_voltage (priv->ext_vref); + refp =MX25_ADCQ_CFG_REFP_EXT ; +break ; +case MX25_ADC_REF_INT : + priv->channel_vref_mv[reg] =2500 ;
drivers/iio/adc/fsl-imx25-gcq.c line 244
Quoted 10 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +10
-0+ refp =MX25_ADCQ_CFG_REFP_INT ; +break ; +default : +return -EINVAL ; + } + +regmap_update_bits (priv->regs,MX25_ADCQ_CFG (reg), +MX25_ADCQ_CFG_REFP_MASK | +MX25_ADCQ_CFG_REFN_MASK , (refp <<7 ) | + (MX25_ADCQ_CFG_REFN_NGND <<2 ));
It's a little inconsistent to define constants for the masks, but not the shifts. Particularly given these constants are already shifted in their definitions... Is that a bug?
Quoted 131 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +125
-0+ } +regmap_update_bits (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST ); + +regmap_write (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_PDMSK | +MX25_ADCQ_CR_QSM_FQS ); + +return 0 ; +} + +static int mx25_gcq_probe (struct platform_device *pdev) +{ +struct iio_dev *indio_dev; +struct mx25_gcq_priv *priv; +struct mx25_tsadc *tsadc =dev_get_drvdata (pdev->dev.parent); +struct device *dev = &pdev->dev; +struct resource *res; +void __iomem *mem; +int ret; + + indio_dev =devm_iio_device_alloc (&pdev->dev,sizeof (*priv)); +if (!indio_dev) +return -ENOMEM ; + + priv =iio_priv (indio_dev); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + mem =devm_ioremap_resource (dev, res); +if (!mem) +return -ENOMEM ; + + priv->regs =devm_regmap_init_mmio (dev, mem, &mx25_gcq_regconfig); +if (IS_ERR (priv->regs)) { +dev_err (dev,"Failed to initialize regmap\n" ); +return PTR_ERR (priv->regs); + } + +init_completion (&priv->completed); + +/* Optional external regulator */ + priv->ext_vref =devm_regulator_get (&pdev->dev,"vref" ); +if (!IS_ERR_OR_NULL (priv->ext_vref)) { + ret =regulator_enable (priv->ext_vref); +if (ret) +return ret; + } + + ret =mx25_gcq_setup_cfgs (pdev, priv); +if (ret) +return ret; + + priv->clk = tsadc->clk; + ret =clk_prepare_enable (priv->clk); +if (ret) { +dev_err (dev,"Failed to enable clock\n" ); +return ret; + } + + priv->irq =platform_get_irq (pdev,0 ); +if (priv->irq <=0 ) { +dev_err (dev,"Failed to get IRQ\n" ); + ret = priv->irq; + goto err_clk_unprepare; + } + + ret =request_irq (priv->irq, mx25_gcq_irq,0 , pdev->name, priv); +if (ret) { +dev_err (dev,"Failed requesting IRQ\n" ); + goto err_clk_unprepare; + } + + indio_dev->dev.parent = &pdev->dev; + indio_dev->channels = mx25_gcq_channels; + indio_dev->num_channels =ARRAY_SIZE (mx25_gcq_channels); + indio_dev->info = &mx25_gcq_iio_info; + + ret =iio_device_register (indio_dev); +if (ret) { +dev_err (dev,"Failed to register iio device\n" ); + goto err_irq_free; + } + +platform_set_drvdata (pdev, priv); + +return 0 ; + +err_irq_free: +free_irq (priv->irq, (void *)priv); +err_clk_unprepare: +clk_disable_unprepare (priv->clk); +return ret; +} + +static int mx25_gcq_remove (struct platform_device *pdev) +{ +struct mx25_gcq_priv *priv =platform_get_drvdata (pdev); +struct iio_dev *indio_dev =iio_priv_to_dev (pdev); + +iio_device_unregister (indio_dev); +free_irq (priv->irq, priv); +clk_disable_unprepare (priv->clk); + +return 0 ; +} + +static struct of_device_id mx25_gcq_ids[] = { + { .compatible ="fsl,imx25-gcq" , }, + {/* Sentinel */ } +}; + +static struct platform_driver mx25_gcq_driver = { + .driver = { + .name ="mx25-gcq" , + .of_match_table = mx25_gcq_ids, + }, + .probe = mx25_gcq_probe, + .remove = mx25_gcq_remove, +}; +module_platform_driver (mx25_gcq_driver); + +MODULE_DESCRIPTION ("ADC driver for Freescale mx25" ); +MODULE_AUTHOR ("Markus Pargmann <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +0
-0
include/dt-bindings/iio/adc/fsl-imx25-gcq.h line 9
Quoted 9 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +9
-0@@ -0,0 +1,11 @@ +/* +* This header provides constants for configuring the I.MX25 ADC +*/ + +#ifndef _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H +#define _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H + +#define MX25_ADC_REF_INT 0/* Internal voltage reference */ +#define MX25_ADC_REF_EXT 1/* External voltage reference */
Seems to me that this could be dealt with using a boolean property. Afterall, we need to get a reference from somewhere, so if it isn't internal it must be external?
I'm far from a device tree expert however, so perhaps this is the preferred method.
Quoted 3 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +2
-0+ +#endif
PATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
Quoted 263 lines · Jonathan Cameron
Quoted 7 lines · Markus Pargmann
This is a conversion queue driver for the mx25 SoC. It uses the central ADC which is used by two seperate independent queues. This driver prepares different conversion configurations for each possible input. For a conversion it creates a conversionqueue of one item with the correct configuration for the chosen channel. It then executes the queue once and disables the conversion queue afterwards.
Quoted 5 lines
The reference voltages are configurable through devicetree subnodes, depending on the connections of the ADC inputs.
Signed-off-by Markus Pargmann <[email protected]>Signed-off-by Denis Carikli <[email protected]>A couple of queries inline.
Quoted 249 lines
---
Notes:
Changes in v5:
- Fixed locking
- Removed module owner.../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 51 +++ drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 369 +++++++++++++++++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 11 + 5 files changed, 439 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.hDocumentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt new file +51
-0@@ -0,0 +1,51 @@ +Freescale i.MX25 ADC GCQ device + +This is a generic conversion queue device that can convert any of the +analog inputs using the ADC unit of the i.MX25. + +Required properties: + - compatible: Should be "fsl,imx25-gcq". + - reg: Should be the register range of the module. + - interrupts: Should be the interrupt number of the module. + Typically this is <1>. + - interrupt-parent: phandle to the tsadc module of the i.MX25. + - #address-cells: Should be <1> (setting for the subnodes) + - #size-cells: Should be <0> (setting for the subnodes) + +Optional properties: + - vref-supply: The regulator supplying the ADC reference voltage. + Required when at least one subnode uses the external reference. + +Sub-nodes: +Optionally you can define subnodes which define the reference voltage +for the analog inputs. + +Required properties for subnodes: + - reg: Should be the number of the analog input. + 0: xp + 1: yp + 2: xn + 3: yn + 4: wiper + 5: inaux0 + 6: inaux1 + 7: inaux2 + - fsl,adc-ref: specifies the reference input as defined in + <dt-bindings/iio/adc/fsl-imx25-gcq.h> + MX25_ADC_REF_INT and MX25_ADC_REF_EXT flags are supported. + +Example: + + adc: adc at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + + inaux at 5 { + reg = <5>; + fsl,adc-ref = <MX25_ADC_REF_INT>; + }; + };drivers/iio/adc/Kconfig +7
-0@@ -143,6 +143,13 @@ config EXYNOS_ADC of SoCs for drivers such as the touchscreen and hwmon to use to share this resource. +config FSL_MX25_ADC + tristate "Freescale MX25 ADC driver" + depends on MFD_MX25_TSADC + help + Generic Conversion Queue driver used for general purpose ADC in the + MX25. This driver supports single measurements using the MX25 ADC. + config LP8788_ADC tristate "LP8788 ADC driver" depends on MFD_LP8788drivers/iio/adc/Makefile +1
-0@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.odrivers/iio/adc/fsl-imx25-gcq.c new file +139
-0@@ -0,0 +1,369 @@ +/* +* Copyright 2014 Markus Pargmann, Pengutronix <[email protected]> +* +* The code contained herein is licensed under the GNU General Public +* License. You may obtain a copy of the GNU General Public License +* Version 2 or later at the following locations: +* +* http://www.opensource.org/licenses/gpl-license.html +* http://www.gnu.org/copyleft/gpl.html +* +* This is the driver for the imx25 GCQ (Generic Conversion Queue) +* connected to the imx25 ADC. +*/ + +#include <dt-bindings/iio/adc/fsl-imx25-gcq.h> +#include <linux/clk.h> +#include <linux/iio/iio.h> +#include <linux/interrupt.h> +#include <linux/mfd/imx25-tsadc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000)) + +enum mx25_gcq_cfgs { +MX25_CFG_XP =0 , +MX25_CFG_YP , +MX25_CFG_XN , +MX25_CFG_YN , +MX25_CFG_WIPER , +MX25_CFG_INAUX0 , +MX25_CFG_INAUX1 , +MX25_CFG_INAUX2 , +MX25_NUM_CFGS , +}; + +struct mx25_gcq_priv { +struct regmap *regs; +struct completion completed; +unsigned int settling_time; +struct clk *clk; +int irq; +struct regulator *ext_vref; +u32 channel_vref_mv[MX25_NUM_CFGS ]; +}; + +#define MX25_CQG_CHAN (chan, id) {\ + .type = IIO_VOLTAGE,\ + .indexed = 1,\ + .channel = chan,\ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .datasheet_name = id,\ +} + +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS ] = { +MX25_CQG_CHAN (0 ,"xp" ), +MX25_CQG_CHAN (1 ,"yp" ), +MX25_CQG_CHAN (2 ,"xn" ), +MX25_CQG_CHAN (3 ,"yn" ), +MX25_CQG_CHAN (4 ,"wiper" ), +MX25_CQG_CHAN (5 ,"inaux0" ), +MX25_CQG_CHAN (6 ,"inaux1" ), +MX25_CQG_CHAN (7 ,"inaux2" ), +}; + +static void mx25_gcq_disable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR ,MX25_ADCQ_MR_EOQ_IRQ , +MX25_ADCQ_MR_EOQ_IRQ ); +} + +static void mx25_gcq_enable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR , +MX25_ADCQ_MR_EOQ_IRQ ,0 ); +} + +static irqreturn_t mx25_gcq_irq (int irq,void *data) +{ +struct mx25_gcq_priv *priv = data; +u32 stats; + +regmap_read (priv->regs,MX25_ADCQ_SR , &stats); + +if (stats &MX25_ADCQ_SR_EOQ ) { +mx25_gcq_disable_eoq (priv); +complete (&priv->completed); + } + +/* Disable conversion queue run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS ,0 ); + +/* Acknowledge all possible irqs */ +regmap_write (priv->regs,MX25_ADCQ_SR ,MX25_ADCQ_SR_FRR | +MX25_ADCQ_SR_FUR |MX25_ADCQ_SR_FOR | +MX25_ADCQ_SR_EOQ |MX25_ADCQ_SR_PD ); + +return IRQ_HANDLED ; +} + +static int mx25_gcq_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan,int *val, +int *val2,long mask) +{ +struct mx25_gcq_priv *priv =iio_priv (indio_dev); +long timeout; +u32 data; +int ret =0 ; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +mutex_lock (&indio_dev->mlock); + +/* Setup the configuration we want to use */ +regmap_write (priv->regs,MX25_ADCQ_ITEM_7_0 , +MX25_ADCQ_ITEM (0 , chan->channel)); + +mx25_gcq_enable_eoq (priv); + +/* Trigger queue for one run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS , +MX25_ADCQ_CR_FQS ); + + timeout =wait_for_completion_interruptible_timeout ( + &priv->completed,MX25_GCQ_TIMEOUT ); +if (timeout <0 ) { +dev_err (&indio_dev->dev, +"ADC wait for measurement failed\n" ); + ret = timeout; + goto info_raw_out; + }else if (timeout ==0 ) { +dev_err (&indio_dev->dev,"ADC timed out\n" ); + ret = -ETIMEDOUT ; + goto info_raw_out; + }
Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 145
Quoted 6 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +6
-0+ +regmap_read (priv->regs,MX25_ADCQ_FIFO , &data); + + *val =MX25_ADCQ_FIFO_DATA (data); + ret =IIO_VAL_INT ; +info_raw_out:Having this label and exit path in the middle is ugly. Perhaps break out this case statement content as a separate function?
Sounds like a good idea.
Quoted 39 lines
Quoted 39 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +39
-0+mutex_unlock (&indio_dev->mlock); + +return ret; + +case IIO_CHAN_INFO_SCALE : + *val = priv->channel_vref_mv[chan->channel]; + *val2 =12 ; +return IIO_VAL_FRACTIONAL_LOG2 ; + +default : +return -EINVAL ; + } +} + +static const struct iio_info mx25_gcq_iio_info = { + .read_raw = mx25_gcq_read_raw, +}; + +static const struct regmap_config mx25_gcq_regconfig = { + .max_register =0x5c , + .reg_bits =32 , + .val_bits =32 , + .reg_stride =4 , +}; + +static int mx25_gcq_setup_cfgs (struct platform_device *pdev, +struct mx25_gcq_priv *priv) +{ +struct device_node *np = pdev->dev.of_node; +struct device_node *child; +struct device *dev = &pdev->dev; +int ret, i; + +/* +* Setup all configurations registers with a default conversion +* configuration for each input +*/ +for (i =0 ; i <MX25_NUM_CFGS ; ++i) + regmap_write(priv->regs, MX25_ADCQ_CFG(i),
Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 189
Quoted 5 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +5
-0+MX25_ADCQ_CFG_YPLL_OFF | +MX25_ADCQ_CFG_XNUR_OFF | +MX25_ADCQ_CFG_XPUL_OFF | +MX25_ADCQ_CFG_REFP_INT | + (i << 4) |Again, given all the definitions i'd expect the shift to be a defined constant as well. Perhaps even a macro taking i as an arguement.
Added a macro that shifts the value.
Quoted 50 lines
Quoted 50 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +50
-0+ MX25_ADCQ_CFG_REFN_NGND2); + +for_each_child_of_node (np, child) { +u32 reg; +u32 refp; +u32 adc_ref; + + ret =of_property_read_u32 (child,"reg" , ®); +if (ret) { +dev_err (dev,"Failed to get reg property\n" ); +return ret; + } + +if (reg >=MX25_NUM_CFGS ) { +dev_err (dev, +"reg value is greater than the number of available configuration registers\n" ); +return -EINVAL ; + } + + ret =of_property_read_u32 (child,"fsl,adc-ref" , &adc_ref); +if (ret) { +dev_err (dev,"Failed to get fsl,adc-ref property\n" ); +return ret; + } + +if (adc_ref !=MX25_ADC_REF_INT && + adc_ref !=MX25_ADC_REF_EXT ) { +dev_err (dev,"Invalid fsl,adc-refp property value %d\n" , + adc_ref); +return -EINVAL ; + } + +switch (adc_ref) { +case MX25_ADC_REF_EXT : +if (IS_ERR_OR_NULL (priv->ext_vref)) { +dev_err (dev, +"No regulator found for the external vref\n" ); +return -EINVAL ; + } + priv->channel_vref_mv[reg] = +regulator_get_voltage (priv->ext_vref); + refp =MX25_ADCQ_CFG_REFP_EXT ; +break ; +case MX25_ADC_REF_INT : + priv->channel_vref_mv[reg] =2500 ; + refp =MX25_ADCQ_CFG_REFP_INT ; +break ; +default : +return -EINVAL ; + }
Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 244
Quoted 5 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +5
-0+ +regmap_update_bits (priv->regs,MX25_ADCQ_CFG (reg), +MX25_ADCQ_CFG_REFP_MASK | +MX25_ADCQ_CFG_REFN_MASK , (refp <<7 ) | + (MX25_ADCQ_CFG_REFN_NGND <<2 ));It's a little inconsistent to define constants for the masks, but not the shifts. Particularly given these constants are already shifted in their definitions... Is that a bug?
Yes that definetly looks like a bug, thanks. Fixed and added a macro for refp.
Quoted 135 lines
Quoted 135 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +125
-0+ } +regmap_update_bits (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST ); + +regmap_write (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_PDMSK | +MX25_ADCQ_CR_QSM_FQS ); + +return 0 ; +} + +static int mx25_gcq_probe (struct platform_device *pdev) +{ +struct iio_dev *indio_dev; +struct mx25_gcq_priv *priv; +struct mx25_tsadc *tsadc =dev_get_drvdata (pdev->dev.parent); +struct device *dev = &pdev->dev; +struct resource *res; +void __iomem *mem; +int ret; + + indio_dev =devm_iio_device_alloc (&pdev->dev,sizeof (*priv)); +if (!indio_dev) +return -ENOMEM ; + + priv =iio_priv (indio_dev); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + mem =devm_ioremap_resource (dev, res); +if (!mem) +return -ENOMEM ; + + priv->regs =devm_regmap_init_mmio (dev, mem, &mx25_gcq_regconfig); +if (IS_ERR (priv->regs)) { +dev_err (dev,"Failed to initialize regmap\n" ); +return PTR_ERR (priv->regs); + } + +init_completion (&priv->completed); + +/* Optional external regulator */ + priv->ext_vref =devm_regulator_get (&pdev->dev,"vref" ); +if (!IS_ERR_OR_NULL (priv->ext_vref)) { + ret =regulator_enable (priv->ext_vref); +if (ret) +return ret; + } + + ret =mx25_gcq_setup_cfgs (pdev, priv); +if (ret) +return ret; + + priv->clk = tsadc->clk; + ret =clk_prepare_enable (priv->clk); +if (ret) { +dev_err (dev,"Failed to enable clock\n" ); +return ret; + } + + priv->irq =platform_get_irq (pdev,0 ); +if (priv->irq <=0 ) { +dev_err (dev,"Failed to get IRQ\n" ); + ret = priv->irq; + goto err_clk_unprepare; + } + + ret =request_irq (priv->irq, mx25_gcq_irq,0 , pdev->name, priv); +if (ret) { +dev_err (dev,"Failed requesting IRQ\n" ); + goto err_clk_unprepare; + } + + indio_dev->dev.parent = &pdev->dev; + indio_dev->channels = mx25_gcq_channels; + indio_dev->num_channels =ARRAY_SIZE (mx25_gcq_channels); + indio_dev->info = &mx25_gcq_iio_info; + + ret =iio_device_register (indio_dev); +if (ret) { +dev_err (dev,"Failed to register iio device\n" ); + goto err_irq_free; + } + +platform_set_drvdata (pdev, priv); + +return 0 ; + +err_irq_free: +free_irq (priv->irq, (void *)priv); +err_clk_unprepare: +clk_disable_unprepare (priv->clk); +return ret; +} + +static int mx25_gcq_remove (struct platform_device *pdev) +{ +struct mx25_gcq_priv *priv =platform_get_drvdata (pdev); +struct iio_dev *indio_dev =iio_priv_to_dev (pdev); + +iio_device_unregister (indio_dev); +free_irq (priv->irq, priv); +clk_disable_unprepare (priv->clk); + +return 0 ; +} + +static struct of_device_id mx25_gcq_ids[] = { + { .compatible ="fsl,imx25-gcq" , }, + {/* Sentinel */ } +}; + +static struct platform_driver mx25_gcq_driver = { + .driver = { + .name ="mx25-gcq" , + .of_match_table = mx25_gcq_ids, + }, + .probe = mx25_gcq_probe, + .remove = mx25_gcq_remove, +}; +module_platform_driver (mx25_gcq_driver); + +MODULE_DESCRIPTION ("ADC driver for Freescale mx25" ); +MODULE_AUTHOR ("Markus Pargmann <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +4
-0@@ -0,0 +1,11 @@ +/* +* This header provides constants for configuring the I.MX25 ADC +*/ +
Quoted 8 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h line 9
Quoted 5 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +5
-0+#ifndef _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H +#define _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H + +#define MX25_ADC_REF_INT 0/* Internal voltage reference */ +#define MX25_ADC_REF_EXT 1/* External voltage reference */ Seems to me that this could be dealt with using a boolean property. Afterall, we need to get a reference from somewhere, so if it isn't internal it must be external?
The driver is currently very simple, the ADC itself is capable of much more combinations and complicated conversion queues. Internal and external references are not the only possible references. There is also YP and XP which are not supported by the driver yet. I will change this to the actual register values representing these references. At a second look on this it may also be better to change the DT-binding from 'fsl,adc-ref' to 'fsl,adc-refp' as it is actually the positive reference voltage. The negative reference is hardcoded in the driver for the moment but the DT-bindings could be extended later if necessary.
Added refp and refn now with all reference values.
Thanks,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150129/39e3e325/attachment-0001.sig>
Jonathan Cameron
maintainerPATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
Quoted 531 lines · Markus Pargmann
Quoted 263 lines · Jonathan Cameron
Quoted 7 lines · Markus Pargmann
This is a conversion queue driver for the mx25 SoC. It uses the central ADC which is used by two seperate independent queues. This driver prepares different conversion configurations for each possible input. For a conversion it creates a conversionqueue of one item with the correct configuration for the chosen channel. It then executes the queue once and disables the conversion queue afterwards.
Quoted 5 lines
The reference voltages are configurable through devicetree subnodes, depending on the connections of the ADC inputs.
Signed-off-by Markus Pargmann <[email protected]>Signed-off-by Denis Carikli <[email protected]>A couple of queries inline.
Quoted 249 lines
---
Notes:
Changes in v5:
- Fixed locking
- Removed module owner.../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 51 +++ drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 369 +++++++++++++++++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 11 + 5 files changed, 439 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.hDocumentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt new file +51
-0@@ -0,0 +1,51 @@ +Freescale i.MX25 ADC GCQ device + +This is a generic conversion queue device that can convert any of the +analog inputs using the ADC unit of the i.MX25. + +Required properties: + - compatible: Should be "fsl,imx25-gcq". + - reg: Should be the register range of the module. + - interrupts: Should be the interrupt number of the module. + Typically this is <1>. + - interrupt-parent: phandle to the tsadc module of the i.MX25. + - #address-cells: Should be <1> (setting for the subnodes) + - #size-cells: Should be <0> (setting for the subnodes) + +Optional properties: + - vref-supply: The regulator supplying the ADC reference voltage. + Required when at least one subnode uses the external reference. + +Sub-nodes: +Optionally you can define subnodes which define the reference voltage +for the analog inputs. + +Required properties for subnodes: + - reg: Should be the number of the analog input. + 0: xp + 1: yp + 2: xn + 3: yn + 4: wiper + 5: inaux0 + 6: inaux1 + 7: inaux2 + - fsl,adc-ref: specifies the reference input as defined in + <dt-bindings/iio/adc/fsl-imx25-gcq.h> + MX25_ADC_REF_INT and MX25_ADC_REF_EXT flags are supported. + +Example: + + adc: adc at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + + inaux at 5 { + reg = <5>; + fsl,adc-ref = <MX25_ADC_REF_INT>; + }; + };drivers/iio/adc/Kconfig +7
-0@@ -143,6 +143,13 @@ config EXYNOS_ADC of SoCs for drivers such as the touchscreen and hwmon to use to share this resource. +config FSL_MX25_ADC + tristate "Freescale MX25 ADC driver" + depends on MFD_MX25_TSADC + help + Generic Conversion Queue driver used for general purpose ADC in the + MX25. This driver supports single measurements using the MX25 ADC. + config LP8788_ADC tristate "LP8788 ADC driver" depends on MFD_LP8788drivers/iio/adc/Makefile +1
-0@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.odrivers/iio/adc/fsl-imx25-gcq.c new file +139
-0@@ -0,0 +1,369 @@ +/* +* Copyright 2014 Markus Pargmann, Pengutronix <[email protected]> +* +* The code contained herein is licensed under the GNU General Public +* License. You may obtain a copy of the GNU General Public License +* Version 2 or later at the following locations: +* +* http://www.opensource.org/licenses/gpl-license.html +* http://www.gnu.org/copyleft/gpl.html +* +* This is the driver for the imx25 GCQ (Generic Conversion Queue) +* connected to the imx25 ADC. +*/ + +#include <dt-bindings/iio/adc/fsl-imx25-gcq.h> +#include <linux/clk.h> +#include <linux/iio/iio.h> +#include <linux/interrupt.h> +#include <linux/mfd/imx25-tsadc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000)) + +enum mx25_gcq_cfgs { +MX25_CFG_XP =0 , +MX25_CFG_YP , +MX25_CFG_XN , +MX25_CFG_YN , +MX25_CFG_WIPER , +MX25_CFG_INAUX0 , +MX25_CFG_INAUX1 , +MX25_CFG_INAUX2 , +MX25_NUM_CFGS , +}; + +struct mx25_gcq_priv { +struct regmap *regs; +struct completion completed; +unsigned int settling_time; +struct clk *clk; +int irq; +struct regulator *ext_vref; +u32 channel_vref_mv[MX25_NUM_CFGS ]; +}; + +#define MX25_CQG_CHAN (chan, id) {\ + .type = IIO_VOLTAGE,\ + .indexed = 1,\ + .channel = chan,\ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .datasheet_name = id,\ +} + +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS ] = { +MX25_CQG_CHAN (0 ,"xp" ), +MX25_CQG_CHAN (1 ,"yp" ), +MX25_CQG_CHAN (2 ,"xn" ), +MX25_CQG_CHAN (3 ,"yn" ), +MX25_CQG_CHAN (4 ,"wiper" ), +MX25_CQG_CHAN (5 ,"inaux0" ), +MX25_CQG_CHAN (6 ,"inaux1" ), +MX25_CQG_CHAN (7 ,"inaux2" ), +}; + +static void mx25_gcq_disable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR ,MX25_ADCQ_MR_EOQ_IRQ , +MX25_ADCQ_MR_EOQ_IRQ ); +} + +static void mx25_gcq_enable_eoq (struct mx25_gcq_priv *priv) +{ +regmap_update_bits (priv->regs,MX25_ADCQ_MR , +MX25_ADCQ_MR_EOQ_IRQ ,0 ); +} + +static irqreturn_t mx25_gcq_irq (int irq,void *data) +{ +struct mx25_gcq_priv *priv = data; +u32 stats; + +regmap_read (priv->regs,MX25_ADCQ_SR , &stats); + +if (stats &MX25_ADCQ_SR_EOQ ) { +mx25_gcq_disable_eoq (priv); +complete (&priv->completed); + } + +/* Disable conversion queue run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS ,0 ); + +/* Acknowledge all possible irqs */ +regmap_write (priv->regs,MX25_ADCQ_SR ,MX25_ADCQ_SR_FRR | +MX25_ADCQ_SR_FUR |MX25_ADCQ_SR_FOR | +MX25_ADCQ_SR_EOQ |MX25_ADCQ_SR_PD ); + +return IRQ_HANDLED ; +} + +static int mx25_gcq_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan,int *val, +int *val2,long mask) +{ +struct mx25_gcq_priv *priv =iio_priv (indio_dev); +long timeout; +u32 data; +int ret =0 ; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +mutex_lock (&indio_dev->mlock); + +/* Setup the configuration we want to use */ +regmap_write (priv->regs,MX25_ADCQ_ITEM_7_0 , +MX25_ADCQ_ITEM (0 , chan->channel)); + +mx25_gcq_enable_eoq (priv); + +/* Trigger queue for one run */ +regmap_update_bits (priv->regs,MX25_ADCQ_CR ,MX25_ADCQ_CR_FQS , +MX25_ADCQ_CR_FQS ); + + timeout =wait_for_completion_interruptible_timeout ( + &priv->completed,MX25_GCQ_TIMEOUT ); +if (timeout <0 ) { +dev_err (&indio_dev->dev, +"ADC wait for measurement failed\n" ); + ret = timeout; + goto info_raw_out; + }else if (timeout ==0 ) { +dev_err (&indio_dev->dev,"ADC timed out\n" ); + ret = -ETIMEDOUT ; + goto info_raw_out; + }Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 145
Quoted 6 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +6
-0+ +regmap_read (priv->regs,MX25_ADCQ_FIFO , &data); + + *val =MX25_ADCQ_FIFO_DATA (data); + ret =IIO_VAL_INT ; +info_raw_out:Having this label and exit path in the middle is ugly. Perhaps break out this case statement content as a separate function?
Sounds like a good idea.
Quoted 39 lines
Quoted 39 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +39
-0+mutex_unlock (&indio_dev->mlock); + +return ret; + +case IIO_CHAN_INFO_SCALE : + *val = priv->channel_vref_mv[chan->channel]; + *val2 =12 ; +return IIO_VAL_FRACTIONAL_LOG2 ; + +default : +return -EINVAL ; + } +} + +static const struct iio_info mx25_gcq_iio_info = { + .read_raw = mx25_gcq_read_raw, +}; + +static const struct regmap_config mx25_gcq_regconfig = { + .max_register =0x5c , + .reg_bits =32 , + .val_bits =32 , + .reg_stride =4 , +}; + +static int mx25_gcq_setup_cfgs (struct platform_device *pdev, +struct mx25_gcq_priv *priv) +{ +struct device_node *np = pdev->dev.of_node; +struct device_node *child; +struct device *dev = &pdev->dev; +int ret, i; + +/* +* Setup all configurations registers with a default conversion +* configuration for each input +*/ +for (i =0 ; i <MX25_NUM_CFGS ; ++i) + regmap_write(priv->regs, MX25_ADCQ_CFG(i),Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 189
Quoted 5 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +5
-0+MX25_ADCQ_CFG_YPLL_OFF | +MX25_ADCQ_CFG_XNUR_OFF | +MX25_ADCQ_CFG_XPUL_OFF | +MX25_ADCQ_CFG_REFP_INT | + (i << 4) |Again, given all the definitions i'd expect the shift to be a defined constant as well. Perhaps even a macro taking i as an arguement.
Added a macro that shifts the value.
Quoted 50 lines
Quoted 50 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +50
-0+ MX25_ADCQ_CFG_REFN_NGND2); + +for_each_child_of_node (np, child) { +u32 reg; +u32 refp; +u32 adc_ref; + + ret =of_property_read_u32 (child,"reg" , ®); +if (ret) { +dev_err (dev,"Failed to get reg property\n" ); +return ret; + } + +if (reg >=MX25_NUM_CFGS ) { +dev_err (dev, +"reg value is greater than the number of available configuration registers\n" ); +return -EINVAL ; + } + + ret =of_property_read_u32 (child,"fsl,adc-ref" , &adc_ref); +if (ret) { +dev_err (dev,"Failed to get fsl,adc-ref property\n" ); +return ret; + } + +if (adc_ref !=MX25_ADC_REF_INT && + adc_ref !=MX25_ADC_REF_EXT ) { +dev_err (dev,"Invalid fsl,adc-refp property value %d\n" , + adc_ref); +return -EINVAL ; + } + +switch (adc_ref) { +case MX25_ADC_REF_EXT : +if (IS_ERR_OR_NULL (priv->ext_vref)) { +dev_err (dev, +"No regulator found for the external vref\n" ); +return -EINVAL ; + } + priv->channel_vref_mv[reg] = +regulator_get_voltage (priv->ext_vref); + refp =MX25_ADCQ_CFG_REFP_EXT ; +break ; +case MX25_ADC_REF_INT : + priv->channel_vref_mv[reg] =2500 ; + refp =MX25_ADCQ_CFG_REFP_INT ; +break ; +default : +return -EINVAL ; + }Quoted 8 lines
drivers/iio/adc/fsl-imx25-gcq.c line 244
Quoted 5 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +5
-0+ +regmap_update_bits (priv->regs,MX25_ADCQ_CFG (reg), +MX25_ADCQ_CFG_REFP_MASK | +MX25_ADCQ_CFG_REFN_MASK , (refp <<7 ) | + (MX25_ADCQ_CFG_REFN_NGND <<2 ));It's a little inconsistent to define constants for the masks, but not the shifts. Particularly given these constants are already shifted in their definitions... Is that a bug?
Yes that definetly looks like a bug, thanks. Fixed and added a macro for refp.
Quoted 135 lines
Quoted 135 lines
drivers/iio/adc/fsl-imx25-gcq.c new file +125
-0+ } +regmap_update_bits (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST , +MX25_ADCQ_CR_FRST |MX25_ADCQ_CR_QRST ); + +regmap_write (priv->regs,MX25_ADCQ_CR , +MX25_ADCQ_CR_PDMSK | +MX25_ADCQ_CR_QSM_FQS ); + +return 0 ; +} + +static int mx25_gcq_probe (struct platform_device *pdev) +{ +struct iio_dev *indio_dev; +struct mx25_gcq_priv *priv; +struct mx25_tsadc *tsadc =dev_get_drvdata (pdev->dev.parent); +struct device *dev = &pdev->dev; +struct resource *res; +void __iomem *mem; +int ret; + + indio_dev =devm_iio_device_alloc (&pdev->dev,sizeof (*priv)); +if (!indio_dev) +return -ENOMEM ; + + priv =iio_priv (indio_dev); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + mem =devm_ioremap_resource (dev, res); +if (!mem) +return -ENOMEM ; + + priv->regs =devm_regmap_init_mmio (dev, mem, &mx25_gcq_regconfig); +if (IS_ERR (priv->regs)) { +dev_err (dev,"Failed to initialize regmap\n" ); +return PTR_ERR (priv->regs); + } + +init_completion (&priv->completed); + +/* Optional external regulator */ + priv->ext_vref =devm_regulator_get (&pdev->dev,"vref" ); +if (!IS_ERR_OR_NULL (priv->ext_vref)) { + ret =regulator_enable (priv->ext_vref); +if (ret) +return ret; + } + + ret =mx25_gcq_setup_cfgs (pdev, priv); +if (ret) +return ret; + + priv->clk = tsadc->clk; + ret =clk_prepare_enable (priv->clk); +if (ret) { +dev_err (dev,"Failed to enable clock\n" ); +return ret; + } + + priv->irq =platform_get_irq (pdev,0 ); +if (priv->irq <=0 ) { +dev_err (dev,"Failed to get IRQ\n" ); + ret = priv->irq; + goto err_clk_unprepare; + } + + ret =request_irq (priv->irq, mx25_gcq_irq,0 , pdev->name, priv); +if (ret) { +dev_err (dev,"Failed requesting IRQ\n" ); + goto err_clk_unprepare; + } + + indio_dev->dev.parent = &pdev->dev; + indio_dev->channels = mx25_gcq_channels; + indio_dev->num_channels =ARRAY_SIZE (mx25_gcq_channels); + indio_dev->info = &mx25_gcq_iio_info; + + ret =iio_device_register (indio_dev); +if (ret) { +dev_err (dev,"Failed to register iio device\n" ); + goto err_irq_free; + } + +platform_set_drvdata (pdev, priv); + +return 0 ; + +err_irq_free: +free_irq (priv->irq, (void *)priv); +err_clk_unprepare: +clk_disable_unprepare (priv->clk); +return ret; +} + +static int mx25_gcq_remove (struct platform_device *pdev) +{ +struct mx25_gcq_priv *priv =platform_get_drvdata (pdev); +struct iio_dev *indio_dev =iio_priv_to_dev (pdev); + +iio_device_unregister (indio_dev); +free_irq (priv->irq, priv); +clk_disable_unprepare (priv->clk); + +return 0 ; +} + +static struct of_device_id mx25_gcq_ids[] = { + { .compatible ="fsl,imx25-gcq" , }, + {/* Sentinel */ } +}; + +static struct platform_driver mx25_gcq_driver = { + .driver = { + .name ="mx25-gcq" , + .of_match_table = mx25_gcq_ids, + }, + .probe = mx25_gcq_probe, + .remove = mx25_gcq_remove, +}; +module_platform_driver (mx25_gcq_driver); + +MODULE_DESCRIPTION ("ADC driver for Freescale mx25" ); +MODULE_AUTHOR ("Markus Pargmann <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +4
-0@@ -0,0 +1,11 @@ +/* +* This header provides constants for configuring the I.MX25 ADC +*/ +Quoted 8 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h line 9
Quoted 5 lines
include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file +5
-0+#ifndef _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H +#define _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H + +#define MX25_ADC_REF_INT 0/* Internal voltage reference */ +#define MX25_ADC_REF_EXT 1/* External voltage reference */ Seems to me that this could be dealt with using a boolean property. Afterall, we need to get a reference from somewhere, so if it isn't internal it must be external?
Quoted 3 lines
The driver is currently very simple, the ADC itself is capable of much more combinations and complicated conversion queues. Internal and external references are not the only possible references.
Fair enough then. Thanks for clarifying this!
Quoted 14 lines
There is also
YP and XP which are not supported by the driver yet. I will change this to the actual register values representing these references. At a second look on this it may also be better to change the DT-binding from 'fsl,adc-ref' to 'fsl,adc-refp' as it is actually the positive reference voltage. The negative reference is hardcoded in the driver for the moment but the DT-bindings could be extended later if necessary.Added refp and refn now with all reference values.
Thanks,
Markus
Fabio Estevam
reviewerPATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
In reply to Markus PargmannHi Markus,
drivers/iio/adc/fsl-imx25-gcq.c line 306
Quoted 2 lines · Markus Pargmann
drivers/iio/adc/fsl-imx25-gcq.c new file +2
-0+ priv->irq =platform_get_irq (pdev,0 ); +if (priv->irq <=0 ) {
This should be: if (priv->irq < 0) {
PATCH v5 3/6 iio: adc: fsl,imx25-gcq driver
Hi Fabio,
Quoted 8 lines · Fabio Estevam
Hi Markus,
drivers/iio/adc/fsl-imx25-gcq.c line 306
Quoted 2 lines · Markus Pargmann
drivers/iio/adc/fsl-imx25-gcq.c new file +2
-0+ priv->irq =platform_get_irq (pdev,0 ); +if (priv->irq <=0 ) {This should be: if (
priv->irq< 0) {
Thanks, fixed in both drivers.
Best regards,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150130/ad2b7ac8/attachment.sig>
PATCH v5 4/6 input: touchscreen: imx25 tcq driver
In reply to Markus PargmannThis is a driver for the imx25 ADC/TSC module. It controls the touchscreen conversion queue and creates a touchscreen input device. The driver currently only supports 4 wire touchscreens. The driver uses a simple conversion queue of precharge, touch detection, X measurement, Y measurement, precharge and another touch detection.
This driver uses the regmap from the parent to setup some touch specific settings in the core driver and setup a idle configuration with touch detection.
---
Notes:
Changes in v5:
- Fix signed/unsigned comparison
- Fix unused variable settling_time by putting it in the correct argument list
- Use continous conversion queue with the repeat feature and a proper repeat-wait. Previously the touchscreen caused massive number of interrupts.
.../bindings/input/touchscreen/fsl-mx25-tcq.txt | 29 + drivers/input/touchscreen/Kconfig | 6 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/fsl-imx25-tcq.c | 587 +++++++++++++++++++++ 4 files changed, 623 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt create mode 100644 drivers/input/touchscreen/fsl-imx25-tcq.c
Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt new file +29 -0
@@ -0,0 +1,29 @@ +Freescale mx25 TS conversion queue module + +mx25 touchscreen conversion queue module which controls the ADC unit of the +mx25 for attached touchscreens. + +Required properties: + - compatible: Should be "fsl,imx25-tcq". + - reg: Memory range of the device. + - interrupts: Should be the interrupt number associated with this module within + the tscadc unit (<0>). + - interrupt-parent: Should be a phandle to the tscadc unit. + - fsl,wires: Should be '<4>' or '<5>' + +Optional properties: + - fsl,pen-debounce: Pen debounce time. + - fsl,pen-threshold: Pen-down threshold for the touchscreen. + - fsl,settling-time: Settling time in nanoseconds. + +This device includes two conversion queues which can be added as subnodes. +The first queue is for the touchscreen, the second for general purpose ADC. + +Example: + tsc: tcq at 50030400 { + compatible = "fsl,imx25-tcq"; + reg = <0x50030400 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <0>; + fsl,wires = <4>; + };
drivers/input/touchscreen/Kconfig +6 -0
@@ -748,6 +748,12 @@ config TOUCHSCREEN_USB_COMPOSITE To compile this driver as a module, choose M here: the module will be called usbtouchscreen. +config TOUCHSCREEN_MX25 + tristate "Freescale i.MX25 touchscreen input driver" + depends on MFD_MX25_TSADC + help + Enable support for touchscreen connected to your i.MX25. + config TOUCHSCREEN_MC13783 tristate "Freescale MC13783 touchscreen input driver" depends on MFD_MC13XXX
drivers/input/touchscreen/Makefile +1 -0
@@ -41,6 +41,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o +obj-$(CONFIG_TOUCHSCREEN_MX25) += fsl-imx25-tcq.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
drivers/input/touchscreen/fsl-imx25-tcq.c new file +587 -0
587 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v5 5/6 ARM: dts: imx25: Add TSC and ADC support
In reply to Markus PargmannFrom: Denis Carikli <[email protected]>
--- arch/arm/boot/dts/imx25.dtsi | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
arch/arm/boot/dts/imx25.dtsi +27 -3
@@ -265,13 +265,37 @@ status = "disabled"; }; - tsc: tsc at 50030000 { - compatible = "fsl,imx25-adc", "fsl,imx21-tsc"; - reg = <0x50030000 0x4000>; + tscadc: tscadc at 50030000 { + compatible = "fsl,imx25-tsadc"; + reg = <0x50030000 0xc>; interrupts = <46>; clocks = <&clks 119>; clock-names = "ipg"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges; status = "disabled"; + + adc: adc at 50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + tsc: tcq at 50030400 { + compatible = "fsl,imx25-tcq"; + reg = <0x50030400 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <0>; + fsl,wires = <4>; + status = "disabled"; + }; }; ssi1: ssi at 50034000 {
Signature · 1 line
2.1.4
PATCH v5 6/6 ARM: imx_v4_v5_defconfig: Add I.MX25 Touchscreen controller and ADC support.
In reply to Markus PargmannFrom: Denis Carikli <[email protected]>
--- arch/arm/configs/imx_v4_v5_defconfig | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm/configs/imx_v4_v5_defconfig +4 -0
@@ -89,6 +89,7 @@ CONFIG_KEYBOARD_IMX=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_MX25=y CONFIG_TOUCHSCREEN_MC13783=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=m
@@ -108,6 +109,7 @@ CONFIG_HWMON=m CONFIG_SENSORS_MC13783_ADC=m CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y +CONFIG_MFD_MX25_TSADC=y CONFIG_MFD_MC13XXX_SPI=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -173,6 +175,8 @@ CONFIG_DMADEVICES=y CONFIG_IMX_SDMA=y CONFIG_IMX_DMA=y # CONFIG_IOMMU_SUPPORT is not set +CONFIG_IIO=y +CONFIG_FSL_MX25_ADC=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS=y
Signature · 1 line
2.1.4