Skip to contentSkip to conversation

mx28: added LRADC and touchscreen support

PATCH New Peter Rusko 8 participants 14 messages Nov 24, 2011 – Jan 23, 2012

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

PATCH 1/1 mx28: added LRADC and touchscreen support

This patch is based on the Freescale SDK 2010.08. It supports the on-chip Low Resolution ADC and a capacitive touchscreen connected to it.

Tested on Ka-Ro TX28 module

---
 arch/arm/mach-mxs/devices-mx28.h                |    6 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-mxs-lradc.c  |   25 +
 arch/arm/mach-mxs/devices/platform-mxs-ts.c     |   34 +
 arch/arm/mach-mxs/include/mach/devices-common.h |   22 +
 arch/arm/mach-mxs/include/mach/lradc.h          |   61 ++
 arch/arm/mach-mxs/include/mach/mx28.h           |    4 +-
 arch/arm/mach-mxs/include/mach/regs-lradc.h     |  772 +++++++++++++++++++++++
 drivers/input/touchscreen/Kconfig               |   11 +
 drivers/input/touchscreen/Makefile              |    1 +
 drivers/input/touchscreen/mxs_ts.c              |  470 ++++++++++++++
 drivers/misc/Kconfig                            |    3 +
 drivers/misc/Makefile                           |    1 +
 drivers/misc/mxs_lradc.c                        |  381 +++++++++++
 15 files changed, 1793 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-lradc.c
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-ts.c
 create mode 100644 arch/arm/mach-mxs/include/mach/lradc.h
 create mode 100644 arch/arm/mach-mxs/include/mach/regs-lradc.h
 create mode 100644 drivers/input/touchscreen/mxs_ts.c
 create mode 100644 drivers/misc/mxs_lradc.c
arch/arm/mach-mxs/devices-mx28.h +6 -0
index c888710..b0efa25 100644
@@ -46,6 +46,12 @@ extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
 struct platform_device *__init mx28_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
 
+struct platform_device * __init mx28_add_lradc(
+		const struct mxs_lradc_plat_data *pdata);
+
+struct platform_device *__init mx28_add_ts(
+		const struct mxs_touchscreen_plat_data *pdata);
+
 extern const struct mxs_saif_data mx28_saif_data[] __initconst;
 #define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
 
arch/arm/mach-mxs/devices/Kconfig +3 -0
index 18b6bf5..58d1c1e 100644
@@ -15,6 +15,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
 config MXS_HAVE_PLATFORM_MXS_I2C
 	bool
 
+config MXS_HAVE_PLATFORM_MXS_LRADC
+	bool
+
 config MXS_HAVE_PLATFORM_MXS_MMC
 	bool
 
arch/arm/mach-mxs/devices/Makefile +1 -0
index f52e3e5..9ba66ed 100644
@@ -4,6 +4,7 @@ obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_LRADC) += platform-mxs-lradc.o platform-mxs-ts.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
 obj-y += platform-gpio-mxs.o
arch/arm/mach-mxs/devices/platform-mxs-lradc.c new file +25 -0
new file mode 100644
index 0000000..d1af2ec
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <mach/devices-common.h>
+#include <mach/mx28.h>
+
+struct platform_device * __init mx28_add_lradc(
+		const struct mxs_lradc_plat_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_LRADC_BASE_ADDR,
+			.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-lradc", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
arch/arm/mach-mxs/devices/platform-mxs-ts.c new file +34 -0
new file mode 100644
index 0000000..05343af
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <mach/devices-common.h>
+#include <mach/mx28.h>
+
+struct platform_device *__init mx28_add_ts(
+		const struct mxs_touchscreen_plat_data *pdata)
+{
+	struct resource res[] = {
+		{
+		 .flags = IORESOURCE_MEM,
+		 .start = MX28_LRADC_BASE_ADDR,
+		 .end   = MX28_LRADC_BASE_ADDR + 0x2000 - 1,
+		}, {
+		 .flags = IORESOURCE_IRQ,
+		 .start = MX28_INT_LRADC_TOUCH,
+		 .end   = MX28_INT_LRADC_TOUCH,
+		}, {
+		 .flags = IORESOURCE_IRQ,
+		 .start = MX28_INT_LRADC_CH5,
+		 .end   = MX28_INT_LRADC_CH5,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-ts", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+
+}
arch/arm/mach-mxs/include/mach/devices-common.h +22 -0
index a8080f4..e86b193 100644
@@ -76,6 +76,12 @@ struct mxs_mxs_i2c_data {
 struct platform_device * __init mxs_add_mxs_i2c(
 		const struct mxs_mxs_i2c_data *data);
 
+/* lradc */
+struct mxs_lradc_plat_data {
+	unsigned int vddio_voltage;
+	unsigned int battery_voltage;
+};
+
 /* mmc */
 #include <mach/mmc.h>
 struct mxs_mxs_mmc_data {
@@ -104,3 +110,19 @@ struct mxs_saif_data {
 
 struct platform_device *__init mxs_add_saif(
 		const struct mxs_saif_data *data);
+
+/* touchscreen */
+struct mxs_touchscreen_plat_data {
+	u8 x_plus_chan;
+	u8 x_minus_chan;
+	u8 y_plus_chan;
+	u8 y_minus_chan;
+	unsigned int x_plus_val;
+	unsigned int x_minus_val;
+	unsigned int y_plus_val;
+	unsigned int y_minus_val;
+	unsigned int x_plus_mask;
+	unsigned int x_minus_mask;
+	unsigned int y_plus_mask;
+	unsigned int y_minus_mask;
+};
arch/arm/mach-mxs/include/mach/lradc.h new file +61 -0

61 lines not on this page · raw message

arch/arm/mach-mxs/include/mach/mx28.h +2 -2
index 75d8611..30c7990 100644
@@ -104,8 +104,8 @@
 #define MX28_INT_CAN1			9
 #define MX28_INT_LRADC_TOUCH		10
 #define MX28_INT_HSADC			13
-#define MX28_INT_IRADC_THRESH0		14
-#define MX28_INT_IRADC_THRESH1		15
+#define MX28_INT_LRADC_THRESH0		14
+#define MX28_INT_LRADC_THRESH1		15
 #define MX28_INT_LRADC_CH0		16
 #define MX28_INT_LRADC_CH1		17
 #define MX28_INT_LRADC_CH2		18
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +772 -0

772 lines not on this page · raw message

drivers/input/touchscreen/Kconfig +11 -0
index 3488ffe..36bd3cf 100644
@@ -339,6 +339,17 @@ config TOUCHSCREEN_HP7XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_ts.
 
+config TOUCHSCREEN_MXS
+	tristate "MXS LRADC-based touchscreen"
+	depends on MXS_LRADC
+	select SERIO
+	help
+	  Say Y here if you want to enable touchscreen, connected to MXS
+	  Low-Resoulion ADC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mxs_ts.
+
 config TOUCHSCREEN_HTCPEN
 	tristate "HTC Shift X9500 touchscreen"
 	depends on ISA
drivers/input/touchscreen/Makefile +1 -0
index f957676..6c3728c 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MXS)		+= mxs_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
drivers/input/touchscreen/mxs_ts.c new file +470 -0

470 lines not on this page · raw message

drivers/misc/Kconfig +3 -0
index d593878..ab89b1b 100644
@@ -499,6 +499,9 @@ config USB_SWITCH_FSA9480
 	  stereo and mono audio, video, microphone and UART data to use
 	  a common connector port.
 
+config MXS_LRADC
+	tristate "ARM MXS LRADC Support"
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
drivers/misc/Makefile +1 -0
index b26495a..0ce0017 100644
@@ -47,4 +47,5 @@ obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
 obj-y				+= lis3lv02d/
 obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+obj-$(CONFIG_MXS_LRADC)		+= mxs_lradc.o
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
drivers/misc/mxs_lradc.c new file +381 -0

381 lines not on this page · raw message

Signature · 1 line
1.7.5.4
#1 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 21 lines · Peter Rusko

This patch is based on the Freescale SDK 2010.08. It supports the on-chip Low Resolution ADC and a capacitive touchscreen connected to it.

Tested on Ka-Ro TX28 module

---
 arch/arm/mach-mxs/devices-mx28.h                |    6 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-mxs-lradc.c  |   25 +
 arch/arm/mach-mxs/devices/platform-mxs-ts.c     |   34 +
 arch/arm/mach-mxs/include/mach/devices-common.h |   22 +
 arch/arm/mach-mxs/include/mach/lradc.h          |   61 ++
 arch/arm/mach-mxs/include/mach/mx28.h           |    4 +-
 arch/arm/mach-mxs/include/mach/regs-lradc.h     |  772 +++++++++++++++++++++++
 drivers/input/touchscreen/Kconfig               |   11 +
 drivers/input/touchscreen/Makefile              |    1 +
 drivers/input/touchscreen/mxs_ts.c              |  470 ++++++++++++++
 drivers/misc/Kconfig                            |    3 +
 drivers/misc/Makefile                           |    1 +
Quoted 9 lines
 drivers/misc/mxs_lradc.c                        |  381 +++++++++++
 15 files changed, 1793 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-lradc.c
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-ts.c
 create mode 100644 arch/arm/mach-mxs/include/mach/lradc.h
 create mode 100644 arch/arm/mach-mxs/include/mach/regs-lradc.h
 create mode 100644 drivers/input/touchscreen/mxs_ts.c
 create mode 100644 drivers/misc/mxs_lradc.c

I think this patch should probably be split into 4.

* lradc drivers/staging/iio/adc/ (rather than drivers/misc/) part
* lradc arch/arm/mach-mxs part
* touchscreen drivers/input/touchscreen part
* touchscreen arch/arm/mach-mxs part

And you need to look into MAINTAINERS for the mailing list and people that the 'drivers' part should be sent to.

Signature · 2 lines
Regards,
Shawn
#2 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 10 lines

I think this patch should probably be split into 4.

* lradc drivers/staging/iio/adc/ (rather than drivers/misc/) part
* lradc arch/arm/mach-mxs part
* touchscreen drivers/input/touchscreen part
* touchscreen arch/arm/mach-mxs part

And you need to look into MAINTAINERS for the mailing list and people that the 'drivers' part should be sent to.

You're right, I'm working on it.

Shall I split the arch/arm/mach-mxs parts? In this patch I use HAVE_MXS_LRADC to compile both of them. I think they come together, the ADC supports the touchscreen, so there is no need to split them.

Signature · 10 lines
Rusk? P?ter
Fejleszt?m?rn?k

Prolan Zrt. / Prolan Co.
Hungary 2011 Budakal?sz, Szentendrei ?t 1-3.
Tel./Phone: +36 20 954 3118
Fax: +36 26 540 420
E-mail: rusko.peter at prolan.hu
Web: www.prolan.hu
Timezone:CET
#3 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 11 lines · Peter Rusko
Quoted 10 lines

I think this patch should probably be split into 4.

* lradc drivers/staging/iio/adc/ (rather than drivers/misc/) part
* lradc arch/arm/mach-mxs part
* touchscreen drivers/input/touchscreen part
* touchscreen arch/arm/mach-mxs part

And you need to look into MAINTAINERS for the mailing list and people that the 'drivers' part should be sent to.

Quoted 6 lines

You're right, I'm working on it.

Shall I split the arch/arm/mach-mxs parts? In this patch I use HAVE_MXS_LRADC to compile both of them. I think they come together, the ADC supports the touchscreen, so there is no need to split them.

But touchscreen is not the only one that ADC supports, right?

Signature · 2 lines
Regards,
Shawn
#4 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

In reply to Peter Rusko
Quoted 120 lines · Peter Rusko

This patch is based on the Freescale SDK 2010.08. It supports the on-chip Low Resolution ADC and a capacitive touchscreen connected to it.

Tested on Ka-Ro TX28 module

---
 arch/arm/mach-mxs/devices-mx28.h                |    6 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-mxs-lradc.c  |   25 +
 arch/arm/mach-mxs/devices/platform-mxs-ts.c     |   34 +
 arch/arm/mach-mxs/include/mach/devices-common.h |   22 +
 arch/arm/mach-mxs/include/mach/lradc.h          |   61 ++
 arch/arm/mach-mxs/include/mach/mx28.h           |    4 +-
 arch/arm/mach-mxs/include/mach/regs-lradc.h     |  772 +++++++++++++++++++++++
 drivers/input/touchscreen/Kconfig               |   11 +
 drivers/input/touchscreen/Makefile              |    1 +
 drivers/input/touchscreen/mxs_ts.c              |  470 ++++++++++++++
 drivers/misc/Kconfig                            |    3 +
 drivers/misc/Makefile                           |    1 +
 drivers/misc/mxs_lradc.c                        |  381 +++++++++++
 15 files changed, 1793 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-lradc.c
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-ts.c
 create mode 100644 arch/arm/mach-mxs/include/mach/lradc.h
 create mode 100644 arch/arm/mach-mxs/include/mach/regs-lradc.h
 create mode 100644 drivers/input/touchscreen/mxs_ts.c
 create mode 100644 drivers/misc/mxs_lradc.c
arch/arm/mach-mxs/devices-mx28.h +6 -0
index c888710..b0efa25 100644
@@ -46,6 +46,12 @@ extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
 struct platform_device *__init mx28_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
 
+struct platform_device * __init mx28_add_lradc(
+		const struct mxs_lradc_plat_data *pdata);
+
+struct platform_device *__init mx28_add_ts(
+		const struct mxs_touchscreen_plat_data *pdata);
+
 extern const struct mxs_saif_data mx28_saif_data[] __initconst;
 #define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
 
arch/arm/mach-mxs/devices/Kconfig +3 -0
index 18b6bf5..58d1c1e 100644
@@ -15,6 +15,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
 config MXS_HAVE_PLATFORM_MXS_I2C
 	bool
 
+config MXS_HAVE_PLATFORM_MXS_LRADC
+	bool
+
 config MXS_HAVE_PLATFORM_MXS_MMC
 	bool
 
arch/arm/mach-mxs/devices/Makefile +1 -0
index f52e3e5..9ba66ed 100644
@@ -4,6 +4,7 @@ obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_LRADC) += platform-mxs-lradc.o platform-mxs-ts.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
 obj-y += platform-gpio-mxs.o
arch/arm/mach-mxs/devices/platform-mxs-lradc.c new file +25 -0
new file mode 100644
index 0000000..d1af2ec
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <mach/devices-common.h>
+#include <mach/mx28.h>
+
+struct platform_device * __init mx28_add_lradc(
+		const struct mxs_lradc_plat_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_LRADC_BASE_ADDR,
+			.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-lradc", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
arch/arm/mach-mxs/devices/platform-mxs-ts.c new file +9 -0
new file mode 100644
index 0000000..05343af
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <mach/devices-common.h>

arch/arm/mach-mxs/devices/platform-mxs-ts.c line 19

Quoted 10 lines
arch/arm/mach-mxs/devices/platform-mxs-ts.c new file +10 -0
+#include <mach/mx28.h>
+
+struct platform_device *__init mx28_add_ts(
+		const struct mxs_touchscreen_plat_data *pdata)
+{
+	struct resource res[] = {
+		{
+		 .flags = IORESOURCE_MEM,
+		 .start = MX28_LRADC_BASE_ADDR,
+		 .end   = MX28_LRADC_BASE_ADDR + 0x2000 - 1,

'MX28_LRADC_BASE_ADDR + SZ_4K - 1' would be more than sufficient.

arch/arm/mach-mxs/devices/platform-mxs-ts.c line 27

Quoted 9 lines
arch/arm/mach-mxs/devices/platform-mxs-ts.c new file +8 -0
+		}, {
+		 .flags = IORESOURCE_IRQ,
+		 .start = MX28_INT_LRADC_TOUCH,
+		 .end   = MX28_INT_LRADC_TOUCH,
+		}, {
+		 .flags = IORESOURCE_IRQ,
+		 .start = MX28_INT_LRADC_CH5,
+		 .end   = MX28_INT_LRADC_CH5,

strange indentation.

Quoted 154 lines
arch/arm/mach-mxs/devices/platform-mxs-ts.c new file +5 -0
+
+	return mxs_add_platform_device("mxs-ts", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+
+}
arch/arm/mach-mxs/include/mach/devices-common.h +22 -0
index a8080f4..e86b193 100644
@@ -76,6 +76,12 @@ struct mxs_mxs_i2c_data {
 struct platform_device * __init mxs_add_mxs_i2c(
 		const struct mxs_mxs_i2c_data *data);
 
+/* lradc */
+struct mxs_lradc_plat_data {
+	unsigned int vddio_voltage;
+	unsigned int battery_voltage;
+};
+
 /* mmc */
 #include <mach/mmc.h>
 struct mxs_mxs_mmc_data {
@@ -104,3 +110,19 @@ struct mxs_saif_data {
 
 struct platform_device *__init mxs_add_saif(
 		const struct mxs_saif_data *data);
+
+/* touchscreen */
+struct mxs_touchscreen_plat_data {
+	u8 x_plus_chan;
+	u8 x_minus_chan;
+	u8 y_plus_chan;
+	u8 y_minus_chan;
+	unsigned int x_plus_val;
+	unsigned int x_minus_val;
+	unsigned int y_plus_val;
+	unsigned int y_minus_val;
+	unsigned int x_plus_mask;
+	unsigned int x_minus_mask;
+	unsigned int y_plus_mask;
+	unsigned int y_minus_mask;
+};
arch/arm/mach-mxs/include/mach/lradc.h new file +61 -0
new file mode 100644
index 0000000..c2c0a7d
@@ -0,0 +1,61 @@
+/*
+ * Freescale STMP37XX/STMP378X LRADC helper interface
+ *
+ * Embedded Alley Solutions, Inc <[email protected]>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * 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
+ */
+#ifndef __ASM_PLAT_LRADC_H
+#define __ASM_PLAT_LRADC_H
+
+int hw_lradc_use_channel(int);
+int hw_lradc_unuse_channel(int);
+extern u32 hw_lradc_vddio(void);
+void hw_lradc_set_delay_trigger_kick(int trigger, int value);
+void hw_lradc_configure_channel(int channel, int enable_div2,
+		int enable_acc, int samples);
+int hw_lradc_present(int channel);
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling);
+int hw_lradc_stop_ladder(int channel, int trigger);
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers, u32 loops, u32 delays);
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers);
+
+
+#define LRADC_CH0		0
+#define LRADC_CH1		1
+#define LRADC_CH2		2
+#define LRADC_CH3		3
+#define LRADC_CH4		4
+#define LRADC_CH5		5
+#define LRADC_CH6		6
+#define LRADC_CH7		7
+#define LRADC_TOUCH_X_PLUS	LRADC_CH2
+#define LRADC_TOUCH_Y_PLUS	LRADC_CH3
+#define LRADC_TOUCH_X_MINUS	LRADC_CH4
+#define LRADC_TOUCH_Y_MINUS	LRADC_CH5
+#define VDDIO_VOLTAGE_CH	LRADC_CH6
+#define BATTERY_VOLTAGE_CH	LRADC_CH7
+
+#define LRADC_CLOCK_6MHZ	0
+#define LRADC_CLOCK_4MHZ	1
+#define LRADC_CLOCK_3MHZ	2
+#define LRADC_CLOCK_2MHZ	3
+
+#define LRADC_DELAY_TRIGGER_BUTTON	0
+#define LRADC_DELAY_TRIGGER_BATTERY	1
+#define LRADC_DELAY_TRIGGER_TOUCHSCREEN	2
+#define LRADC_DELAY_TRIGGER_DIE		3
+
+#endif /* __ASM_PLAT_LRADC_H */
arch/arm/mach-mxs/include/mach/mx28.h +2 -2
index 75d8611..30c7990 100644
@@ -104,8 +104,8 @@
 #define MX28_INT_CAN1			9
 #define MX28_INT_LRADC_TOUCH		10
 #define MX28_INT_HSADC			13
-#define MX28_INT_IRADC_THRESH0		14
-#define MX28_INT_IRADC_THRESH1		15
+#define MX28_INT_LRADC_THRESH0		14
+#define MX28_INT_LRADC_THRESH1		15
 #define MX28_INT_LRADC_CH0		16
 #define MX28_INT_LRADC_CH1		17
 #define MX28_INT_LRADC_CH2		18
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +24 -0
new file mode 100644
index 0000000..d7906b9
@@ -0,0 +1,772 @@
+/*
+ * Freescale LRADC Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.50
+ * Template revision: 26195
+ */

arch/arm/mach-mxs/include/mach/regs-lradc.h line 34

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +10 -0
+
+#ifndef __ARCH_ARM___LRADC_H
+#define __ARCH_ARM___LRADC_H
+
+
+#define HW_LRADC_CTRL0	(0x00000000)
+#define HW_LRADC_CTRL0_SET	(0x00000004)
+#define HW_LRADC_CTRL0_CLR	(0x00000008)
+#define HW_LRADC_CTRL0_TOG	(0x0000000c)
+

useless parens.
more of these follow...
[...]

arch/arm/mach-mxs/include/mach/regs-lradc.h line 411

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +9 -0
+ *  multi-register-define name HW_LRADC_DELAYn
+ *              base 0x000000D0
+ *              count 4
+ *              offset 0x10
+ */
+#define HW_LRADC_DELAYn(n)	(0x000000d0 + (n) * 0x10)
+#define HW_LRADC_DELAYn_SET(n)	(0x000000d4 + (n) * 0x10)
+#define HW_LRADC_DELAYn_CLR(n)	(0x000000d8 + (n) * 0x10)
+#define HW_LRADC_DELAYn_TOG(n)	(0x000000dc + (n) * 0x10)

You should use MXS_SET_ADDR, MXS_CLR_ADDR, MXS_TOG_ADDR here. Thus:

|#define HW_LRADC_DELAYn_SET(n)		(HW_LRADC_DELAYn(n) + MXS_SET_ADDR)
|#define HW_LRADC_DELAYn_CLR(n)		(HW_LRADC_DELAYn(n) + MXS_CLR_ADDR)
|#define HW_LRADC_DELAYn_TOG(n)		(HW_LRADC_DELAYn(n) + MXS_TOG_ADDR)

or use the __mxs_setl(), __mxs_clrl(), __mxs_togl() functions instead.

Quoted 72 lines
drivers/input/touchscreen/Kconfig +11 -0
index 3488ffe..36bd3cf 100644
@@ -339,6 +339,17 @@ config TOUCHSCREEN_HP7XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_ts.
 
+config TOUCHSCREEN_MXS
+	tristate "MXS LRADC-based touchscreen"
+	depends on MXS_LRADC
+	select SERIO
+	help
+	  Say Y here if you want to enable touchscreen, connected to MXS
+	  Low-Resoulion ADC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mxs_ts.
+
 config TOUCHSCREEN_HTCPEN
 	tristate "HTC Shift X9500 touchscreen"
 	depends on ISA
drivers/input/touchscreen/Makefile +1 -0
index f957676..6c3728c 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MXS)		+= mxs_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
drivers/input/touchscreen/mxs_ts.c new file +31 -0
new file mode 100644
index 0000000..ad05c3f
@@ -0,0 +1,470 @@
+/*
+ * Freesclae MXS Touchscreen driver
+ *
+ * Author: Vitaly Wool <[email protected]>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/lradc.h>

drivers/input/touchscreen/mxs_ts.c line 41

Quoted 10 lines
drivers/input/touchscreen/mxs_ts.c new file +10 -0
+#include <mach/devices-common.h>
+#include <mach/regs-lradc.h>
+#include <mach/mxs.h>
+
+#define TOUCH_DEBOUNCE_TOLERANCE	100
+
+struct mxs_ts_info {
+	int touch_irq;
+	int device_irq;
+	unsigned int base;

void __iomem *base;

Quoted 28 lines
drivers/input/touchscreen/mxs_ts.c new file +27 -0
+	u8 x_plus_chan;
+	u8 x_minus_chan;
+	u8 y_plus_chan;
+	u8 y_minus_chan;
+
+	unsigned int x_plus_val;
+	unsigned int x_minus_val;
+	unsigned int y_plus_val;
+	unsigned int y_minus_val;
+	unsigned int x_plus_mask;
+	unsigned int x_minus_mask;
+	unsigned int y_plus_mask;
+	unsigned int y_minus_mask;
+
+	struct input_dev *idev;
+	enum {
+		TS_STATE_DISABLED,
+		TS_STATE_TOUCH_DETECT,
+		TS_STATE_TOUCH_VERIFY,
+		TS_STATE_X_PLANE,
+		TS_STATE_Y_PLANE,
+	} state;
+	u16 x;
+	u16 y;
+	int sample_count;
+};
+

drivers/input/touchscreen/mxs_ts.c line 78

Quoted 10 lines
drivers/input/touchscreen/mxs_ts.c new file +10 -0
+static inline void enter_state_touch_detect(struct mxs_ts_info *info)
+{
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_plus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->y_plus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_minus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->y_minus_chan));

writel() instead of __raw_writel()?
Also: writing a '0' to the regular register address would be clearer here:

	 writel(0, info->base + HW_LRADC_CHn(info->x_plus_chan));
Quoted 182 lines
drivers/input/touchscreen/mxs_ts.c new file +181 -0
+
+	__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << info->y_minus_chan,
+		     info->base + HW_LRADC_CTRL1_CLR);
+	__raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ,
+		     info->base + HW_LRADC_CTRL1_CLR);
+	/*
+	 * turn off the yplus and yminus pullup and pulldown, and turn off touch
+	 * detect (enables yminus, and xplus through a resistor.On a press,
+	 * xplus is pulled down)
+	 */
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_SET);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0);
+	info->state = TS_STATE_TOUCH_DETECT;
+	info->sample_count = 0;
+}
+
+static inline void enter_state_disabled(struct mxs_ts_info *info)
+{
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_CLR);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0);
+	info->state = TS_STATE_DISABLED;
+	info->sample_count = 0;
+}
+
+
+static inline void enter_state_x_plane(struct mxs_ts_info *info)
+{
+	__raw_writel(info->y_plus_val, info->base + HW_LRADC_CTRL0_SET);
+	__raw_writel(info->y_minus_val, info->base + HW_LRADC_CTRL0_SET);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_CLR);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+
+	info->state = TS_STATE_X_PLANE;
+	info->sample_count = 0;
+}
+
+static inline void enter_state_y_plane(struct mxs_ts_info *info)
+{
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_val, info->base + HW_LRADC_CTRL0_SET);
+	__raw_writel(info->x_minus_val, info->base + HW_LRADC_CTRL0_SET);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_CLR);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+	info->state = TS_STATE_Y_PLANE;
+	info->sample_count = 0;
+}
+
+static inline void enter_state_touch_verify(struct mxs_ts_info *info)
+{
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_SET);
+	info->state = TS_STATE_TOUCH_VERIFY;
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+	info->sample_count = 0;
+}
+
+static void process_lradc(struct mxs_ts_info *info, u16 x, u16 y,
+			int pressure)
+{
+	switch (info->state) {
+	case TS_STATE_X_PLANE:
+		pr_debug("%s: x plane state, sample_count %d\n", __func__,
+				info->sample_count);
+		if (info->sample_count < 2) {
+			info->x = x;
+			info->sample_count++;
+		} else {
+			if (abs(info->x - x) > TOUCH_DEBOUNCE_TOLERANCE)
+				info->sample_count = 1;
+			else {
+				u16 x_c = info->x * (info->sample_count - 1);
+				info->x = (x_c + x) / info->sample_count;
+				info->sample_count++;
+			}
+		}
+		if (info->sample_count > 4)
+			enter_state_y_plane(info);
+		else
+			hw_lradc_set_delay_trigger_kick(
+					LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+		break;
+
+	case TS_STATE_Y_PLANE:
+		pr_debug("%s: y plane state, sample_count %d\n", __func__,
+				info->sample_count);
+		if (info->sample_count < 2) {
+			info->y = y;
+			info->sample_count++;
+		} else {
+			if (abs(info->y - y) > TOUCH_DEBOUNCE_TOLERANCE)
+				info->sample_count = 1;
+			else {
+				u16 y_c = info->y * (info->sample_count - 1);
+				info->y = (y_c + y) / info->sample_count;
+				info->sample_count++;
+			}
+		}
+		if (info->sample_count > 4)
+			enter_state_touch_verify(info);
+		else
+			hw_lradc_set_delay_trigger_kick(
+					LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+		break;
+
+	case TS_STATE_TOUCH_VERIFY:
+		pr_debug("%s: touch verify state, sample_count %d\n", __func__,
+				info->sample_count);
+		pr_debug("%s: x %d, y %d\n", __func__, info->x, info->y);
+		input_report_abs(info->idev, ABS_X, info->x);
+		input_report_abs(info->idev, ABS_Y, info->y);
+		input_report_abs(info->idev, ABS_PRESSURE, pressure);
+		input_sync(info->idev);
+		/* fall through */
+	case TS_STATE_TOUCH_DETECT:
+		pr_debug("%s: touch detect state, sample_count %d\n", __func__,
+				info->sample_count);
+		if (pressure) {
+			input_report_abs(info->idev, ABS_PRESSURE, pressure);
+			enter_state_x_plane(info);
+			hw_lradc_set_delay_trigger_kick(
+					LRADC_DELAY_TRIGGER_TOUCHSCREEN, 1);
+		} else
+			enter_state_touch_detect(info);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: unknown touchscreen state %d\n", __func__,
+				info->state);
+	}
+}
+
+static irqreturn_t ts_handler(int irq, void *dev_id)
+{
+	struct mxs_ts_info *info = dev_id;
+	u16 x_plus, y_plus;
+	int pressure = 0;
+
+	if (irq == info->touch_irq)
+		__raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ,
+			     info->base + HW_LRADC_CTRL1_CLR);
+	else if (irq == info->device_irq)
+		__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << info->y_minus_chan,
+			     info->base + HW_LRADC_CTRL1_CLR);
+
+	/* get x, y values */
+	x_plus = __raw_readl(info->base + HW_LRADC_CHn(info->x_plus_chan)) &
+		BM_LRADC_CHn_VALUE;
+	y_plus = __raw_readl(info->base + HW_LRADC_CHn(info->y_plus_chan)) &
+		BM_LRADC_CHn_VALUE;
+
+	/* pressed? */
+	if (__raw_readl(info->base + HW_LRADC_STATUS) &
+	    BM_LRADC_STATUS_TOUCH_DETECT_RAW)
+		pressure = 1;
+
+	pr_debug("%s: irq %d, x_plus %d, y_plus %d, pressure %d\n",
+			__func__, irq, x_plus, y_plus, pressure);
+
+	process_lradc(info, x_plus, y_plus, pressure);
+
+	return IRQ_HANDLED;
+}

drivers/input/touchscreen/mxs_ts.c line 269

Quoted 10 lines
drivers/input/touchscreen/mxs_ts.c new file +10 -0
+
+static int __devinit mxs_ts_probe(struct platform_device *pdev)
+{
+	struct input_dev *idev;
+	struct mxs_ts_info *info;
+	int ret = 0;
+	struct resource *res;
+	struct mxs_touchscreen_plat_data *plat_data;
+
+	plat_data = (struct mxs_touchscreen_plat_data *)pdev->dev.platform_data;

useless type cast.

Quoted 35 lines
drivers/input/touchscreen/mxs_ts.c new file +34 -0
+	if (plat_data == NULL)
+		return -ENODEV;
+
+	idev = input_allocate_device();
+	if (idev == NULL)
+		return -ENOMEM;
+
+	info = kzalloc(sizeof(struct mxs_ts_info), GFP_KERNEL);
+	if (info == NULL) {
+		ret = -ENOMEM;
+		goto out_nomem_info;
+	}
+
+	idev->name = "MXS touchscreen";
+	idev->evbit[0] = BIT(EV_ABS);
+	input_set_abs_params(idev, ABS_X, 0, 0xFFF, 0, 0);
+	input_set_abs_params(idev, ABS_Y, 0, 0xFFF, 0, 0);
+	input_set_abs_params(idev, ABS_PRESSURE, 0, 1, 0, 0);
+
+	ret = input_register_device(idev);
+	if (ret)
+		goto out_nomem;
+
+	info->idev = idev;
+	info->x_plus_chan = plat_data->x_plus_chan;
+	info->x_minus_chan = plat_data->x_minus_chan;
+	info->y_plus_chan = plat_data->y_plus_chan;
+	info->y_minus_chan = plat_data->y_minus_chan;
+	info->x_plus_val = plat_data->x_plus_val;
+	info->x_minus_val = plat_data->x_minus_val;
+	info->y_plus_val = plat_data->y_plus_val;
+	info->y_minus_val = plat_data->y_minus_val;
+	info->x_plus_mask = plat_data->x_plus_mask;
+	info->x_minus_mask = plat_data->x_minus_mask;

drivers/input/touchscreen/mxs_ts.c line 313

Quoted 10 lines
drivers/input/touchscreen/mxs_ts.c new file +10 -0
+	info->y_plus_mask = plat_data->y_plus_mask;
+	info->y_minus_mask = plat_data->y_minus_mask;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		printk(KERN_ERR "%s: couldn't get MEM resource\n", __func__);
+		ret = -ENODEV;
+		goto out_nodev;
+	}
+	info->base = (unsigned int)MXS_IO_ADDRESS(res->start);

ioremap() please.

drivers/input/touchscreen/mxs_ts.c line 330

Quoted 2 lines
drivers/input/touchscreen/mxs_ts.c new file +1 -0
+	ret = request_irq(info->touch_irq, ts_handler, IRQF_DISABLED,

IRQF_DISABLED is a NOP nowadays and will be removed sooner or later.

drivers/input/touchscreen/mxs_ts.c line 361

Quoted 10 lines
drivers/input/touchscreen/mxs_ts.c new file +10 -0
+	/* Clear the accumulator & NUM_SAMPLES for the channels */
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_plus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_minus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->y_plus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->y_minus_chan));
+

see above.

Quoted 140 lines
drivers/input/touchscreen/mxs_ts.c new file +82 -0
+static int __devexit mxs_ts_remove(struct platform_device *pdev)
+{
+	struct mxs_ts_info *info = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	hw_lradc_unuse_channel(info->x_plus_chan);
+	hw_lradc_unuse_channel(info->x_minus_chan);
+	hw_lradc_unuse_channel(info->y_plus_chan);
+	hw_lradc_unuse_channel(info->y_minus_chan);
+
+	__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ_EN << info->y_minus_chan,
+		     info->base + HW_LRADC_CTRL1_CLR);
+	__raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+		     info->base + HW_LRADC_CTRL1_CLR);
+
+	free_irq(info->device_irq, info);
+	free_irq(info->touch_irq, info);
+	input_free_device(info->idev);
+
+	enter_state_disabled(info);
+	kfree(info->idev);
+	kfree(info);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxs_ts_suspend(struct platform_device *pdev,
+				pm_message_t state)
+{
+	struct mxs_ts_info *info = platform_get_drvdata(pdev);
+
+	if (!device_may_wakeup(&pdev->dev)) {
+		hw_lradc_unuse_channel(info->x_plus_chan);
+		hw_lradc_unuse_channel(info->x_minus_chan);
+		hw_lradc_unuse_channel(info->y_plus_chan);
+		hw_lradc_unuse_channel(info->y_minus_chan);
+	}
+	return 0;
+}
+
+static int mxs_ts_resume(struct platform_device *pdev)
+{
+	struct mxs_ts_info *info = platform_get_drvdata(pdev);
+
+	if (!device_may_wakeup(&pdev->dev)) {
+		hw_lradc_use_channel(info->x_plus_chan);
+		hw_lradc_use_channel(info->x_minus_chan);
+		hw_lradc_use_channel(info->y_plus_chan);
+		hw_lradc_use_channel(info->y_minus_chan);
+	}
+	return 0;
+}
+#endif
+
+static struct platform_driver mxs_ts_driver = {
+	.probe		= mxs_ts_probe,
+	.remove		= __devexit_p(mxs_ts_remove),
+#ifdef CONFIG_PM
+	.suspend	= mxs_ts_suspend,
+	.resume		= mxs_ts_resume,
+#endif
+	.driver		= {
+		.name	= "mxs-ts",
+	},
+};
+
+static int __init mxs_ts_init(void)
+{
+	return platform_driver_register(&mxs_ts_driver);
+}
+
+static void __exit mxs_ts_exit(void)
+{
+	platform_driver_unregister(&mxs_ts_driver);
+}
+
+module_init(mxs_ts_init);
+module_exit(mxs_ts_exit);
+
+MODULE_DESCRIPTION("MXS touchscreen driver");
+MODULE_LICENSE("GPL");
drivers/misc/Kconfig +3 -0
index d593878..ab89b1b 100644
@@ -499,6 +499,9 @@ config USB_SWITCH_FSA9480
 	  stereo and mono audio, video, microphone and UART data to use
 	  a common connector port.
 
+config MXS_LRADC
+	tristate "ARM MXS LRADC Support"
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
drivers/misc/Makefile +1 -0
index b26495a..0ce0017 100644
@@ -47,4 +47,5 @@ obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
 obj-y				+= lis3lv02d/
 obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+obj-$(CONFIG_MXS_LRADC)		+= mxs_lradc.o
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
drivers/misc/mxs_lradc.c new file +27 -0
new file mode 100644
index 0000000..cc32fac
@@ -0,0 +1,381 @@
+/*
+ * Freescale STMP37XX/STMP378X LRADC helper routines
+ *
+ * Embedded Alley Solutions, Inc <[email protected]>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/delay.h>

drivers/misc/mxs_lradc.c line 37

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <mach/mxs.h>
+#include <mach/regs-lradc.h>
+#include <mach/lradc.h>
+
+struct lradc_device {
+	struct sys_device sys;
+	unsigned int base;

void __iomem *base;

Quoted 4 lines
drivers/misc/mxs_lradc.c new file +3 -0
+	unsigned int vddio_voltage;
+	unsigned int battery_voltage;
+};

drivers/misc/mxs_lradc.c line 50

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+
+static int channels[8];
+
+static __refdata struct lradc_device mxs_lradc;
+
+int hw_lradc_use_channel(int channel)
+{
+	if (channel < 0 || channel > 7)
+		return -EINVAL;
+	channels[channel]++;

Missing locking to make the increment atomic.

drivers/misc/mxs_lradc.c line 59

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +9 -0
+	return 0;
+}
+EXPORT_SYMBOL(hw_lradc_use_channel);
+
+int hw_lradc_unuse_channel(int channel)
+{
+	if (channel < 0 || channel > 7)
+		return -EINVAL;
+	channels[channel]--;

Locking?

Quoted 41 lines
drivers/misc/mxs_lradc.c new file +40 -0
+void hw_lradc_reinit(int enable_ground_ref, unsigned freq)
+{
+	__raw_writel(BM_LRADC_CTRL0_SFTRST,
+		     mxs_lradc.base + HW_LRADC_CTRL0_SET);
+	udelay(1);
+	__raw_writel(BM_LRADC_CTRL0_SFTRST,
+		     mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+	/* Clear the Clock Gate for normal operation */
+	__raw_writel(BM_LRADC_CTRL0_CLKGATE,
+		     mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+	if (enable_ground_ref)
+		__raw_writel(BM_LRADC_CTRL0_ONCHIP_GROUNDREF,
+			     mxs_lradc.base + HW_LRADC_CTRL0_SET);
+	else
+		__raw_writel(BM_LRADC_CTRL0_ONCHIP_GROUNDREF,
+			    mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+	__raw_writel(BM_LRADC_CTRL3_CYCLE_TIME,
+		     mxs_lradc.base + HW_LRADC_CTRL3_CLR);
+	__raw_writel(BF_LRADC_CTRL3_CYCLE_TIME(freq),
+		     mxs_lradc.base + HW_LRADC_CTRL3_SET);
+
+	__raw_writel(BM_LRADC_CTRL4_LRADC6SELECT | BM_LRADC_CTRL4_LRADC7SELECT,
+		     mxs_lradc.base + HW_LRADC_CTRL4_CLR);
+	__raw_writel(BF_LRADC_CTRL4_LRADC6SELECT(mxs_lradc.vddio_voltage),
+		     mxs_lradc.base + HW_LRADC_CTRL4_SET);
+	__raw_writel(BF_LRADC_CTRL4_LRADC7SELECT(mxs_lradc.battery_voltage),
+		     mxs_lradc.base + HW_LRADC_CTRL4_SET);
+}
+
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling)
+{
+	/*
+	 * check if the lradc channel is present in this product
+	 */
+	if (!hw_lradc_present(channel))
+		return -ENODEV;
+

drivers/misc/mxs_lradc.c line 113

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+	hw_lradc_configure_channel(channel, !0 /* div2 */ ,
+				   0 /* acc */ ,
+				   0 /* num_samples */);
+
+	/* Setup the trigger loop forever */
+	hw_lradc_set_delay_trigger(trigger, 1 << channel,
+				   1 << trigger, 0, sampling);
+
+	/* Clear the accumulator & NUM_SAMPLES */
+	__raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel));

see above.

Quoted 23 lines
drivers/misc/mxs_lradc.c new file +22 -0
+	return 0;
+}
+EXPORT_SYMBOL(hw_lradc_init_ladder);
+
+int hw_lradc_stop_ladder(int channel, int trigger)
+{
+	/*
+	 * check if the lradc channel is present in this product
+	 */
+	if (!hw_lradc_present(channel))
+		return -ENODEV;
+	hw_lradc_clear_delay_trigger(trigger, 1 << channel, 1 << trigger);
+	return 0;
+}
+EXPORT_SYMBOL(hw_lradc_stop_ladder);
+
+int hw_lradc_present(int channel)
+{
+	if (channel < 0 || channel > 7)
+		return 0;
+	return __raw_readl(mxs_lradc.base + HW_LRADC_STATUS)
+	    & (1 << (16 + channel));
Quoted 1 line

From my point it is more readable to have the operator at the end of

the preceding line instead of at the beginning of a continuation line like:

	return __raw_readl(mxs_lradc.base + HW_LRADC_STATUS) &
		(1 << (16 + channel));
Also one of the following would be safer wrt the processing of the
result:
	return (__raw_readl(mxs_lradc.base + HW_LRADC_STATUS) >>
		(16 + channel)) & 1;
or:
	return !!(__raw_readl(mxs_lradc.base + HW_LRADC_STATUS) &
		(1 << (16 + channel)));
Quoted 5 lines
drivers/misc/mxs_lradc.c new file +4 -0
+EXPORT_SYMBOL(hw_lradc_present);
+
+void hw_lradc_configure_channel(int channel, int enable_div2,
+				int enable_acc, int samples)

drivers/misc/mxs_lradc.c line 150

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+{
+	if (enable_div2)
+		__raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel),
+			     mxs_lradc.base + HW_LRADC_CTRL2_SET);
+	else
+		__raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel),
+			     mxs_lradc.base + HW_LRADC_CTRL2_CLR);
+
+	/* Clear the accumulator & NUM_SAMPLES */
+	__raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel));

see above.

Quoted 61 lines
drivers/misc/mxs_lradc.c new file +60 -0
+	/* Sets NUM_SAMPLES bitfield of HW_LRADC_CHn register. */
+	__raw_writel(BM_LRADC_CHn_NUM_SAMPLES,
+		     mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+	__raw_writel(BF_LRADC_CHn_NUM_SAMPLES(samples),
+		     mxs_lradc.base + HW_LRADC_CHn_SET(channel));
+
+	if (enable_acc)
+		__raw_writel(BM_LRADC_CHn_ACCUMULATE,
+			     mxs_lradc.base + HW_LRADC_CHn_SET(channel));
+	else
+		__raw_writel(BM_LRADC_CHn_ACCUMULATE,
+			     mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+}
+EXPORT_SYMBOL(hw_lradc_configure_channel);
+
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+				u32 delay_triggers, u32 loops, u32 delays)
+{
+	/* set TRIGGER_LRADCS in HW_LRADC_DELAYn */
+	__raw_writel(BF_LRADC_DELAYn_TRIGGER_LRADCS(trigger_lradc),
+		     mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+	__raw_writel(BF_LRADC_DELAYn_TRIGGER_DELAYS(delay_triggers),
+		     mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+
+	__raw_writel(BM_LRADC_DELAYn_LOOP_COUNT | BM_LRADC_DELAYn_DELAY,
+		     mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+	__raw_writel(BF_LRADC_DELAYn_LOOP_COUNT(loops),
+		     mxs_lradc.base  + HW_LRADC_DELAYn_SET(trigger));
+	__raw_writel(BF_LRADC_DELAYn_DELAY(delays),
+		     mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+}
+EXPORT_SYMBOL(hw_lradc_set_delay_trigger);
+
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+				  u32 delay_triggers)
+{
+	__raw_writel(BF_LRADC_DELAYn_TRIGGER_LRADCS(trigger_lradc),
+		     mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+	__raw_writel(BF_LRADC_DELAYn_TRIGGER_DELAYS(delay_triggers),
+		     mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+}
+EXPORT_SYMBOL(hw_lradc_clear_delay_trigger);
+
+void hw_lradc_set_delay_trigger_kick(int trigger, int value)
+{
+	if (value)
+		__raw_writel(BM_LRADC_DELAYn_KICK,
+			     mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+	else
+		__raw_writel(BM_LRADC_DELAYn_KICK,
+			     mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+}
+EXPORT_SYMBOL(hw_lradc_set_delay_trigger_kick);
+
+u32 hw_lradc_vddio(void)
+{
+	/* Clear the Soft Reset and Clock Gate for normal operation */
+	__raw_writel(BM_LRADC_CTRL0_SFTRST | BM_LRADC_CTRL0_CLKGATE,
+		     mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+

drivers/misc/mxs_lradc.c line 221

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+	/*
+	 * Clear the divide by two for channel 6 since
+	 * it has a HW divide-by-two built in.
+	 */
+	__raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << VDDIO_VOLTAGE_CH),
+		     mxs_lradc.base + HW_LRADC_CTRL2_CLR);
+
+	/* Clear the accumulator & NUM_SAMPLES */
+	__raw_writel(0xFFFFFFFF,
+		     mxs_lradc.base + HW_LRADC_CHn_CLR(VDDIO_VOLTAGE_CH));

see above.

Quoted 8 lines
drivers/misc/mxs_lradc.c new file +7 -0
+
+	/* Clear the interrupt flag */
+	__raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ,
+		     mxs_lradc.base + HW_LRADC_CTRL1_CLR);
+
+	/*
+	 * Get VddIO; this is the max scale value for the button resistor

drivers/misc/mxs_lradc.c line 238

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+	 * ladder.
+	 * schedule ch 6:
+	 */
+	__raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << VDDIO_VOLTAGE_CH),
+		     mxs_lradc.base + HW_LRADC_CTRL0_SET);
+
+	/* wait for completion */
+	while ((__raw_readl(mxs_lradc.base + HW_LRADC_CTRL1)
+		& BM_LRADC_CTRL1_LRADC6_IRQ) != BM_LRADC_CTRL1_LRADC6_IRQ)
+		cpu_relax();

No endless loops depending solely on a HW bit please!

drivers/misc/mxs_lradc.c line 251

Quoted 12 lines
drivers/misc/mxs_lradc.c new file +12 -0
+	/* Clear the interrupt flag */
+	__raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ,
+		     mxs_lradc.base + HW_LRADC_CTRL1_CLR);
+
+	/* read ch 6 value. */
+	return __raw_readl(mxs_lradc.base + HW_LRADC_CHn(VDDIO_VOLTAGE_CH)) &
+			   BM_LRADC_CHn_VALUE;
+}
+EXPORT_SYMBOL(hw_lradc_vddio);
+
+#ifdef CONFIG_PM
+static u32 lradc_registers[0x16];
                              ^^^^

You are missing to save/restore the HW_LRADC_THRESHOLD1 register at offset 0x160.

Quoted 61 lines
drivers/misc/mxs_lradc.c new file +60 -0
+static int do_gate;
+
+static int hw_lradc_suspend(struct device *dev, pm_message_t state)
+{
+	int i;
+
+	do_gate = 1;
+	for (i = 0; i < ARRAY_SIZE(channels); i++)
+		if (channels[i] > 0) {
+			do_gate = 0;
+			break;
+		}
+
+	for (i = 0; i < ARRAY_SIZE(lradc_registers); i++)
+		lradc_registers[i] = __raw_readl(mxs_lradc.base + (i << 4));
+
+	if (do_gate)
+		__raw_writel(BM_LRADC_CTRL0_CLKGATE,
+			     mxs_lradc.base + HW_LRADC_CTRL0_SET);
+	return 0;
+}
+
+static int hw_lradc_resume(struct device *dev)
+{
+	int i;
+
+	if (do_gate) {
+		__raw_writel(BM_LRADC_CTRL0_SFTRST,
+			     mxs_lradc.base + HW_LRADC_CTRL0_SET);
+		udelay(10);
+		__raw_writel(BM_LRADC_CTRL0_SFTRST |
+			     BM_LRADC_CTRL0_CLKGATE,
+			     mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+	}
+	for (i = 0; i < ARRAY_SIZE(lradc_registers); i++)
+		__raw_writel(lradc_registers[i], mxs_lradc.base + (i << 4));
+	return 0;
+}
+
+#endif
+
+static struct sysdev_class mxs_lradc_sysclass = {
+	.name = "mxs-lradc",
+};
+
+static int lradc_freq = LRADC_CLOCK_6MHZ;
+
+static int __init lradc_freq_setup(char *str)
+{
+	long freq;
+
+	if (kstrtol(str, 0, &freq) < 0)
+		return 0;
+
+	if (freq < 0)
+		return 0;
+	if (freq >= 6)
+		lradc_freq = LRADC_CLOCK_6MHZ;
+	else if (freq >= 4)
+		lradc_freq = LRADC_CLOCK_4MHZ;

drivers/misc/mxs_lradc.c line 321

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+	else if (freq >= 3)
+		lradc_freq = LRADC_CLOCK_3MHZ;
+	else if (freq >= 2)
+		lradc_freq = LRADC_CLOCK_2MHZ;
+	else
+		return 0;
+	return 1;
+}
+
+__setup("lradc_freq=", lradc_freq_setup);

How do you set lradc_freq when the driver is compiled as a module? module_param() would work for the driver compiled as a module as well as built-in.

drivers/misc/mxs_lradc.c line 332

Quoted 11 lines
drivers/misc/mxs_lradc.c new file +10 -0
+static int __devinit mxs_lradc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct mxs_lradc_plat_data *plat_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENODEV;
+
+	plat_data = (struct mxs_lradc_plat_data *)(pdev->dev.platform_data);

useless type cast.

drivers/misc/mxs_lradc.c line 334

Quoted 3 lines
drivers/misc/mxs_lradc.c new file +2 -0
+	if (plat_data == NULL)
+		return -EFAULT;

-EFAULT indicates that a memory access from kernel to userspace memory failed. -ENODEV would be more appropriate here.

drivers/misc/mxs_lradc.c line 336

Quoted 2 lines
drivers/misc/mxs_lradc.c new file +1 -0
+	mxs_lradc.base = (unsigned int)MXS_IO_ADDRESS(res->start);

ioremap()

Quoted 21 lines
drivers/misc/mxs_lradc.c new file +20 -0
+	mxs_lradc.sys.id = -1;
+	mxs_lradc.sys.cls = &mxs_lradc_sysclass;
+	mxs_lradc.vddio_voltage = plat_data->vddio_voltage;
+	mxs_lradc.battery_voltage = plat_data->battery_voltage;
+	hw_lradc_reinit(0, lradc_freq);
+	return sysdev_register(&mxs_lradc.sys);
+}
+
+static int __devexit mxs_lradc_remove(struct platform_device *pdev)
+{
+	sysdev_unregister(&mxs_lradc.sys);
+	return 0;
+}
+
+static __refdata struct platform_driver mxs_lradc_drv = {
+	.probe = mxs_lradc_probe,
+	.remove = __devexit_p(mxs_lradc_remove),
+	.driver = {
+		.name = "mxs-lradc",
+		.owner = THIS_MODULE,

drivers/misc/mxs_lradc.c line 366

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+#ifdef CONFIG_PM
+		.suspend = hw_lradc_suspend,
+		.resume = hw_lradc_resume,
+#endif
+	}
+};
+
+static int __init hw_lradc_init(void)
+{
+	sysdev_class_register(&mxs_lradc_sysclass);

Does it make sense to go ahead and register the driver, if this fails?

drivers/misc/mxs_lradc.c line 368

Quoted 3 lines
drivers/misc/mxs_lradc.c new file +2 -0
+	platform_driver_register(&mxs_lradc_drv);
+	return 0;

return platform_driver_register(&mxs_lradc_drv);

Lothar Wa?mann

Signature · 9 lines
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________
reviewer
#5 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 21 lines · Lothar Wa?mann
Quoted 21 lines
(quoted diff) +21 -0
+static int lradc_freq = LRADC_CLOCK_6MHZ;
+
+static int __init lradc_freq_setup(char *str)
+{
+ ? ? long freq;
+
+ ? ? if (kstrtol(str, 0, &freq) < 0)
+ ? ? ? ? ? ? return 0;
+
+ ? ? if (freq < 0)
+ ? ? ? ? ? ? return 0;
+ ? ? if (freq >= 6)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_6MHZ;
+ ? ? else if (freq >= 4)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_4MHZ;
+ ? ? else if (freq >= 3)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_3MHZ;
+ ? ? else if (freq >= 2)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_2MHZ;
+ ? ? else
+ ? ? ? ? ? ? return 0;
Quoted 8 lines

drivers/misc/mxs_lradc.c line 321

Quoted 5 lines

+ ? ? return 1;

drivers/misc/mxs_lradc.c new file +3 -0
+}
+
+__setup("lradc_freq=", lradc_freq_setup);

How do you set lradc_freq when the driver is compiled as a module? module_param() would work for the driver compiled as a module as well as built-in

What about passing lradc_freq as platform data?

reviewer
#6 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Peter,

Quoted 32 lines · Fabio Estevam
Quoted 21 lines · Lothar Wa?mann
Quoted 21 lines
(quoted diff) +21 -0
+static int lradc_freq = LRADC_CLOCK_6MHZ;
+
+static int __init lradc_freq_setup(char *str)
+{
+ ? ? long freq;
+
+ ? ? if (kstrtol(str, 0, &freq) < 0)
+ ? ? ? ? ? ? return 0;
+
+ ? ? if (freq < 0)
+ ? ? ? ? ? ? return 0;
+ ? ? if (freq >= 6)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_6MHZ;
+ ? ? else if (freq >= 4)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_4MHZ;
+ ? ? else if (freq >= 3)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_3MHZ;
+ ? ? else if (freq >= 2)
+ ? ? ? ? ? ? lradc_freq = LRADC_CLOCK_2MHZ;
+ ? ? else
+ ? ? ? ? ? ? return 0;
Quoted 8 lines

drivers/misc/mxs_lradc.c line 321

Quoted 5 lines

+ ? ? return 1;

drivers/misc/mxs_lradc.c new file +3 -0
+}
+
+__setup("lradc_freq=", lradc_freq_setup);

How do you set lradc_freq when the driver is compiled as a module? module_param() would work for the driver compiled as a module as well as built-in

Quoted 1 line

What about passing lradc_freq as platform data?

You can also look at this AT91 ADC driver patch for reference:
http://www.spinics.net/lists/arm-kernel/msg148461.html

#7 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

In reply to Peter Rusko

arch/arm/mach-mxs/devices/platform-mxs-lradc.c line 21

Quoted 10 lines · Peter Rusko
arch/arm/mach-mxs/devices/platform-mxs-lradc.c new file +10 -0
+struct platform_device * __init mx28_add_lradc(
+		const struct mxs_lradc_plat_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_LRADC_BASE_ADDR,
+			.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};

I've pointed this out to people before, and I'll do it again. I wish people would take a moment to think about the code they write...

How the compiler can implement the above is as this equivalent C code:

static struct res_initializer[] = {
	{
		.start = MX28_LRADC_BASE_ADDR,
		.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
		.flags = IORESOURCE_MEM,
	},
};

struct platform_device * __init mx28_add_lradc(
const struct mxs_lradc_plat_data *pdata)

{
	struct resource res[ARRAY_SIZE(res_initializer)];
	memcpy(res, res_initializer, sizeof(res_initializer));

Or it can put the constants into the literal pool and manually build the structure on the stack using individual loads and stores.

So, you're not gaining any efficency by attempting this trick - in fact, your total data + code is larger than just this:

static struct res[] __initdata = {
	{
		.start = MX28_LRADC_BASE_ADDR,
		.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
		.flags = IORESOURCE_MEM,
	},
};

struct platform_device * __init mx28_add_lradc(
const struct mxs_lradc_plat_data *pdata)

{
	return mxs_add_platform_device("mxs-lradc", 0,
			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
}

because doing it this way eliminates the additional stack storage and manual or otherwise memcpy. Moreover, you can mark the struct resource __initdata and have it discarded at runtime.

Here's what I get with gcc 4.3.5 which illustrates the point:

   text    data     bss     dec     hex filename
    124       0       0     124      7c t.onstack.O2.o (-O2)
    122       0       0     122      7a t.onstack.Os.o (-Os)
     76      28       0     104      68 t.offstack.o

So, there's no need to make things more complex and bigger - just put the resource outside the function and mark it __initdata.

#8 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

In reply to Peter Rusko

arch/arm/mach-mxs/devices/platform-mxs-lradc.c line 20

Quoted 6 lines · Peter Rusko
arch/arm/mach-mxs/devices/platform-mxs-lradc.c new file +6 -0
+	struct resource res[] = {
+		{
+			.start = MX28_LRADC_BASE_ADDR,
+			.end = MX28_LRADC_BASE_ADDR + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},

The other thing which I forgot to mention is...

	struct resource res[] = {
		DEFINE_RES_MEM(MX28_LRADC_BASE_ADDR, SZ_16K),
	};

is much neater.

maintainer
#9 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

In reply to Peter Rusko

Hi Peter,

In addition to the good comments made by other people, here are some other high-level comments:

Quoted 21 lines · Peter Rusko

This patch is based on the Freescale SDK 2010.08. It supports the on-chip Low Resolution ADC and a capacitive touchscreen connected to it.

Tested on Ka-Ro TX28 module

---
 arch/arm/mach-mxs/devices-mx28.h                |    6 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-mxs-lradc.c  |   25 +
 arch/arm/mach-mxs/devices/platform-mxs-ts.c     |   34 +
 arch/arm/mach-mxs/include/mach/devices-common.h |   22 +
 arch/arm/mach-mxs/include/mach/lradc.h          |   61 ++
 arch/arm/mach-mxs/include/mach/mx28.h           |    4 +-
 arch/arm/mach-mxs/include/mach/regs-lradc.h     |  772 +++++++++++++++++++++++
 drivers/input/touchscreen/Kconfig               |   11 +
 drivers/input/touchscreen/Makefile              |    1 +
 drivers/input/touchscreen/mxs_ts.c              |  470 ++++++++++++++
 drivers/misc/Kconfig                            |    3 +
 drivers/misc/Makefile                           |    1 +
Quoted 8 lines
 drivers/misc/mxs_lradc.c                        |  381 +++++++++++
 15 files changed, 1793 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-lradc.c
 create mode 100644 arch/arm/mach-mxs/devices/platform-mxs-ts.c
 create mode 100644 arch/arm/mach-mxs/include/mach/lradc.h
 create mode 100644 arch/arm/mach-mxs/include/mach/regs-lradc.h
 create mode 100644 drivers/input/touchscreen/mxs_ts.c
 create mode 100644 drivers/misc/mxs_lradc.c

The driver layering seems to be suboptimal: You have a huge header file with register definitions and then two drivers including that. It would be much better to have all the low-level logic in the adc driver and put only the interface between the two drivers into the header file.

Quoted 27 lines
arch/arm/mach-mxs/include/mach/devices-common.h +12 -0
index a8080f4..e86b193 100644
@@ -76,6 +76,12 @@ struct mxs_mxs_i2c_data {
 struct platform_device * __init mxs_add_mxs_i2c(
 		const struct mxs_mxs_i2c_data *data);
 
+/* lradc */
+struct mxs_lradc_plat_data {
+	unsigned int vddio_voltage;
+	unsigned int battery_voltage;
+};
+
 /* mmc */
 #include <mach/mmc.h>
 struct mxs_mxs_mmc_data {
@@ -104,3 +110,19 @@ struct mxs_saif_data {
 
 struct platform_device *__init mxs_add_saif(
 		const struct mxs_saif_data *data);
+
+/* touchscreen */
+struct mxs_touchscreen_plat_data {
+	u8 x_plus_chan;
+	u8 x_minus_chan;
+	u8 y_plus_chan;

arch/arm/mach-mxs/include/mach/devices-common.h struct mxs_saif_data { · line 128

Quoted 10 lines
arch/arm/mach-mxs/include/mach/devices-common.h +10 -0
+	u8 y_minus_chan;
+	unsigned int x_plus_val;
+	unsigned int x_minus_val;
+	unsigned int y_plus_val;
+	unsigned int y_minus_val;
+	unsigned int x_plus_mask;
+	unsigned int x_minus_mask;
+	unsigned int y_plus_mask;
+	unsigned int y_minus_mask;
+};

Platform data nowadays is defined in include/linux/platform_data/. We are not at the point where we do mass-moves from arch directories there, but I think it would be useful to put new data into that location.

Quoted 8 lines
arch/arm/mach-mxs/include/mach/lradc.h new file +4 -0
new file mode 100644
index 0000000..c2c0a7d
 
+
+int hw_lradc_use_channel(int);
+int hw_lradc_unuse_channel(int);
+extern u32 hw_lradc_vddio(void);

arch/arm/mach-mxs/include/mach/lradc.h line 33

Quoted 10 lines
arch/arm/mach-mxs/include/mach/lradc.h new file +10 -0
+void hw_lradc_set_delay_trigger_kick(int trigger, int value);
+void hw_lradc_configure_channel(int channel, int enable_div2,
+		int enable_acc, int samples);
+int hw_lradc_present(int channel);
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling);
+int hw_lradc_stop_ladder(int channel, int trigger);
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers, u32 loops, u32 delays);
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers);

As indicated by Shawn, adding a new driver specific kernel-level ADC interface is not a good idea. IIRC, the result of the last discussion was that all ADC drivers should be part of IIO and you should use the IIO in-kernel interfaces. Not sure what the state of that code is, but if it's not in mainline yet, you should work with Jonathan to make sure it gets there. Having more users for that code can only speed up the process, and I'm going to refuse another ADC driver in drivers/misc or arch/arm/mach-*/.

Quoted 5 lines
arch/arm/mach-mxs/include/mach/mx28.h +0 -0
index 75d8611..30c7990 100644

arch/arm/mach-mxs/include/mach/mx28.h line 111

Quoted 10 lines
arch/arm/mach-mxs/include/mach/mx28.h +2 -2
@@ -104,8 +104,8 @@
 #define MX28_INT_CAN1			9
 #define MX28_INT_LRADC_TOUCH		10
 #define MX28_INT_HSADC			13
-#define MX28_INT_IRADC_THRESH0		14
-#define MX28_INT_IRADC_THRESH1		15
+#define MX28_INT_LRADC_THRESH0		14
+#define MX28_INT_LRADC_THRESH1		15
 #define MX28_INT_LRADC_CH0		16
 #define MX28_INT_LRADC_CH1		17
 #define MX28_INT_LRADC_CH2		18

This seems to be a cleanup of existing code. While useful, it is not part of the new driver submission, and would be better handled in a separate patch, either before or after the new driver (changing all users in the latter case).

arch/arm/mach-mxs/include/mach/regs-lradc.h line 2

Quoted 8 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +2 -0
new file mode 100644
index 0000000..d7906b9
@@ -0,0 +1,772 @@
+/*
+ * Freescale LRADC Register Definitions

As mentioned, just include the contents of this file in the low-level driver. Header files are for interfaces between source files.

arch/arm/mach-mxs/include/mach/regs-lradc.h line 36

Quoted 7 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +7 -0
+#define HW_LRADC_CTRL0	(0x00000000)
+#define HW_LRADC_CTRL0_SET	(0x00000004)
+#define HW_LRADC_CTRL0_CLR	(0x00000008)
+#define HW_LRADC_CTRL0_TOG	(0x0000000c)
+
+#define BM_LRADC_CTRL0_SFTRST	0x80000000
+#define BM_LRADC_CTRL0_CLKGATE	0x40000000

This device seems to follow the "stmp" pattern for which Wolfram has proposed an abstraction. I suppose you should be using that. Also, it would appear to be a useful addition to provide a set of inline functions for these registers like

stmp_reg_get(void __iomem *reg)

{
	return readl_relaxed(reg);
}

stmp_reg_set(void __iomem *reg, u32 mask)

{
	writel_relaxed(reg + 4, mask);
}

And then you can drop the four separate definitions for each register.

Quoted 6 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +6 -0
+#define BP_LRADC_CTRL0_RSRVD2	27
+#define BM_LRADC_CTRL0_RSRVD2	0x38000000
+#define BF_LRADC_CTRL0_RSRVD2(v)  \
+		(((v) << 27) & BM_LRADC_CTRL0_RSRVD2)
+#define BM_LRADC_CTRL0_ONCHIP_GROUNDREF	0x04000000
+#define BV_LRADC_CTRL0_ONCHIP_GROUNDREF__OFF 0x0

arch/arm/mach-mxs/include/mach/regs-lradc.h line 52

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +10 -0
+#define BV_LRADC_CTRL0_ONCHIP_GROUNDREF__ON  0x1
+#define BM_LRADC_CTRL0_BUTTON1_DETECT_ENABLE	0x02000000
+#define BV_LRADC_CTRL0_BUTTON1_DETECT_ENABLE__OFF 0x0
+#define BV_LRADC_CTRL0_BUTTON1_DETECT_ENABLE__ON  0x1
+#define BM_LRADC_CTRL0_BUTTON0_DETECT_ENABLE	0x01000000
+#define BV_LRADC_CTRL0_BUTTON0_DETECT_ENABLE__OFF 0x0
+#define BV_LRADC_CTRL0_BUTTON0_DETECT_ENABLE__ON  0x1
+#define BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE	0x00800000
+#define BV_LRADC_CTRL0_TOUCH_DETECT_ENABLE__OFF 0x0
+#define BV_LRADC_CTRL0_TOUCH_DETECT_ENABLE__ON  0x1

This is much more verbose than necessary, making it rather unreadable. Why not just like this:?

enum {
	LRADC_CTRL0_ONCHIP_GROUNDREF		= 0x04000000,
	LRADC_CTRL0_BUTTON1_DETECT_ENABLE	= 0x02000000,
	LRADC_CTRL0_BUTTON0_DETECT_ENABLE	= 0x01000000,
	LRADC_CTRL0_TOUCH_DETECT_ENABLE		= 0x00800000,
	LRADC_CTRL0_TOUCH_SCREEN_TYPE		= 0x00400000,
	...
};
Quoted 6 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +6 -0
+
+static inline void enter_state_touch_detect(struct mxs_ts_info *info)
+{
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_plus_chan));
+	__raw_writel(0xFFFFFFFF,

arch/arm/mach-mxs/include/mach/regs-lradc.h line 41

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +10 -0
+		     info->base + HW_LRADC_CHn_CLR(info->y_plus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->x_minus_chan));
+	__raw_writel(0xFFFFFFFF,
+		     info->base + HW_LRADC_CHn_CLR(info->y_minus_chan));
+
+	__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << info->y_minus_chan,
+		     info->base + HW_LRADC_CTRL1_CLR);
+	__raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ,
+		     info->base + HW_LRADC_CTRL1_CLR);

Don't use __raw_writel/__raw_readl in drivers. readl_relaxed is the right abstraction for non-DMA drivers with fixed-endian hardware registers. If you need the driver to support both big- and little- endian devices, roll your own hardware accessors as a wrapper around that.

Quoted 33 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +32 -0
+	/*
+	 * turn off the yplus and yminus pullup and pulldown, and turn off touch
+	 * detect (enables yminus, and xplus through a resistor.On a press,
+	 * xplus is pulled down)
+	 */
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_SET);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0);
+	info->state = TS_STATE_TOUCH_DETECT;
+	info->sample_count = 0;
+}
+
+static inline void enter_state_disabled(struct mxs_ts_info *info)
+{
+	__raw_writel(info->y_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->y_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_plus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(info->x_minus_mask, info->base + HW_LRADC_CTRL0_CLR);
+	__raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		     info->base + HW_LRADC_CTRL0_CLR);
+	hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0);
+	info->state = TS_STATE_DISABLED;
+	info->sample_count = 0;
+}
+
+static inline void enter_state_x_plane(struct mxs_ts_info *info)
+{
...
+}

arch/arm/mach-mxs/include/mach/regs-lradc.h

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +10 -0
+
+static inline void enter_state_y_plane(struct mxs_ts_info *info)
+{
+ ...
+}
+
+static inline void enter_state_touch_verify(struct mxs_ts_info *info)
+{
+ ...
+}

When you do six almost identical functions, the natural thing to do is to split out the common parts into a separate function.

Quoted 21 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +21 -0
+static irqreturn_t ts_handler(int irq, void *dev_id)
+{
+	struct mxs_ts_info *info = dev_id;
+	u16 x_plus, y_plus;
+	int pressure = 0;
+
+	if (irq == info->touch_irq)
+		__raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ,
+			     info->base + HW_LRADC_CTRL1_CLR);
+	else if (irq == info->device_irq)
+		__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << info->y_minus_chan,
+			     info->base + HW_LRADC_CTRL1_CLR);
+
+	/* get x, y values */
+	x_plus = __raw_readl(info->base + HW_LRADC_CHn(info->x_plus_chan)) &
+		BM_LRADC_CHn_VALUE;
+	y_plus = __raw_readl(info->base + HW_LRADC_CHn(info->y_plus_chan)) &
+		BM_LRADC_CHn_VALUE;
+
+	/* pressed? */
+	if (__raw_readl(info->base + HW_LRADC_STATUS) &

arch/arm/mach-mxs/include/mach/regs-lradc.h

Quoted 10 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +10 -0
+	    BM_LRADC_STATUS_TOUCH_DETECT_RAW)
+		pressure = 1;
+
+	pr_debug("%s: irq %d, x_plus %d, y_plus %d, pressure %d\n",
+			__func__, irq, x_plus, y_plus, pressure);
+
+	process_lradc(info, x_plus, y_plus, pressure);
+
+	return IRQ_HANDLED;
+}

The interrupt handler seems to be rather heavyweight (with process_lradc). Have you considered using a work queue or a threaded IRQ handler?

arch/arm/mach-mxs/include/mach/regs-lradc.h

Quoted 7 lines
arch/arm/mach-mxs/include/mach/regs-lradc.h new file +7 -0
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		printk(KERN_ERR "%s: couldn't get MEM resource\n", __func__);
+		ret = -ENODEV;
+		goto out_nodev;
+	}
+	info->base = (unsigned int)MXS_IO_ADDRESS(res->start);

One line, two bugs:

1. A base address is not an integer, it's a '(void __iomem *)' pointer, and so should be all variables you assign it to.
2. Never use MXS_IO_ADDRESS (or similar macros) in device drivers. Instead, call ioremap to get an iomem token for the physical address. Your code is non-portable and much more fragile in case the architecture code changes how it works with the mmio mapping.

Quoted 23 lines
drivers/misc/mxs_lradc.c new file +19 -0
@@ -0,0 +1,381 @@
 
+
+struct lradc_device {
+	struct sys_device sys;
+	unsigned int base;
+	unsigned int vddio_voltage;
+	unsigned int battery_voltage;
+};
+
+static int channels[8];
+
+static __refdata struct lradc_device mxs_lradc;
+
+int hw_lradc_use_channel(int channel)
+{
+	if (channel < 0 || channel > 7)
+		return -EINVAL;
+	channels[channel]++;
+	return 0;
+}

drivers/misc/mxs_lradc.c line 62

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+EXPORT_SYMBOL(hw_lradc_use_channel);
+
+int hw_lradc_unuse_channel(int channel)
+{
+	if (channel < 0 || channel > 7)
+		return -EINVAL;
+	channels[channel]--;
+	return 0;
+}
+EXPORT_SYMBOL(hw_lradc_unuse_channel);

As mentioned, the API will have to change with the move to IIO, but remember anyway to use EXPORT_SYMBOL_GPL() for new interfaces unless you have a good (and well-documented) reason not to.

Quoted 13 lines
drivers/misc/mxs_lradc.c new file +13 -0
+static int __init lradc_freq_setup(char *str)
+{
+	long freq;
+
+	if (kstrtol(str, 0, &freq) < 0)
+		return 0;
+
+	if (freq < 0)
+		return 0;
+	if (freq >= 6)
+		lradc_freq = LRADC_CLOCK_6MHZ;
+	else if (freq >= 4)
+		lradc_freq = LRADC_CLOCK_4MHZ;

drivers/misc/mxs_lradc.c line 321

Quoted 10 lines
drivers/misc/mxs_lradc.c new file +10 -0
+	else if (freq >= 3)
+		lradc_freq = LRADC_CLOCK_3MHZ;
+	else if (freq >= 2)
+		lradc_freq = LRADC_CLOCK_2MHZ;
+	else
+		return 0;
+	return 1;
+}
+
+__setup("lradc_freq=", lradc_freq_setup);

Why is this a command line argument? Can't you put it into the platform data or hardcode it?

Arnd

#10 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

...

Quoted 19 lines
Quoted 8 lines
arch/arm/mach-mxs/include/mach/lradc.h new file +4 -0
new file mode 100644
index 0000000..c2c0a7d
 
+
+int hw_lradc_use_channel(int);
+int hw_lradc_unuse_channel(int);
+extern u32 hw_lradc_vddio(void);

arch/arm/mach-mxs/include/mach/lradc.h line 33

Quoted 10 lines
arch/arm/mach-mxs/include/mach/lradc.h new file +10 -0
+void hw_lradc_set_delay_trigger_kick(int trigger, int value);
+void hw_lradc_configure_channel(int channel, int enable_div2,
+		int enable_acc, int samples);
+int hw_lradc_present(int channel);
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling);
+int hw_lradc_stop_ladder(int channel, int trigger);
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers, u32 loops, u32 delays);
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+		u32 delay_triggers);
Quoted 8 lines

As indicated by Shawn, adding a new driver specific kernel-level ADC interface is not a good idea. IIRC, the result of the last discussion was that all ADC drivers should be part of IIO and you should use the IIO in-kernel interfaces. Not sure what the state of that code is, but if it's not in mainline yet, you should work with Jonathan to make sure it gets there. Having more users for that code can only speed up the process, and I'm going to refuse another ADC driver in drivers/misc or arch/arm/mach-*/.

Quick summary of IIO status. Nothing is in mainline yet. Intent is to get the first set of core code (including in kernel pull interfaces) into linux-next fairly shortly (these have had enough postive feedback now I think). Doing push interfaces (as I think we would need here) is possible with existing patches on top of the stuff in the iio staging tree but there are some 'interesting' cases where both push and pull interfaces exist that still need addressing.

Also, note the push interface stuff (e.g. interrupt driven) requires a lot more of the IIO infrastructure to be in place (buffered support and the demux unit) so may still be some time. Personally my time is currently very restricted so all the help anyone can offer is most welcome!

Jonathan

maintainer
#11 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 17 lines · Jonathan Cameron
Quoted 8 lines

As indicated by Shawn, adding a new driver specific kernel-level ADC interface is not a good idea. IIRC, the result of the last discussion was that all ADC drivers should be part of IIO and you should use the IIO in-kernel interfaces. Not sure what the state of that code is, but if it's not in mainline yet, you should work with Jonathan to make sure it gets there. Having more users for that code can only speed up the process, and I'm going to refuse another ADC driver in drivers/misc or arch/arm/mach-*/.

Quick summary of IIO status. Nothing is in mainline yet. Intent is to get the first set of core code (including in kernel pull interfaces) into linux-next fairly shortly (these have had enough postive feedback now I think). Doing push interfaces (as I think we would need here) is possible with existing patches on top of the stuff in the iio staging tree but there are some 'interesting' cases where both push and pull interfaces exist that still need addressing.

Quoted 4 lines

Also, note the push interface stuff (e.g. interrupt driven) requires a lot more of the IIO infrastructure to be in place (buffered support and the demux unit) so may still be some time. Personally my time is currently very restricted so all the help anyone can offer is most welcome!

Ok, thanks for the summary!

Peter, I guess what this means for you is that it's best to first get your code working with the IIO/ADC stuff that is in staging, and get the touchscreen driver ready for merging, on top of that.

Ideally, you would also help out a bit on getting the IIO parts you need graduated from staging. Given Jonathan's explanation, I think my initial reaction was valid: we shouldn't take the ADC driver outside of IIO, because that ends up being more painful than getting the driver ready for inclusion now, and then rewriting it shortly after.

Arnd

#12 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 30 lines · Arnd Bergmann
Quoted 17 lines · Jonathan Cameron
Quoted 8 lines

As indicated by Shawn, adding a new driver specific kernel-level ADC interface is not a good idea. IIRC, the result of the last discussion was that all ADC drivers should be part of IIO and you should use the IIO in-kernel interfaces. Not sure what the state of that code is, but if it's not in mainline yet, you should work with Jonathan to make sure it gets there. Having more users for that code can only speed up the process, and I'm going to refuse another ADC driver in drivers/misc or arch/arm/mach-*/.

Quick summary of IIO status. Nothing is in mainline yet. Intent is to get the first set of core code (including in kernel pull interfaces) into linux-next fairly shortly (these have had enough postive feedback now I think). Doing push interfaces (as I think we would need here) is possible with existing patches on top of the stuff in the iio staging tree but there are some 'interesting' cases where both push and pull interfaces exist that still need addressing.

Quoted 4 lines

Also, note the push interface stuff (e.g. interrupt driven) requires a lot more of the IIO infrastructure to be in place (buffered support and the demux unit) so may still be some time. Personally my time is currently very restricted so all the help anyone can offer is most welcome!

Ok, thanks for the summary!

Peter, I guess what this means for you is that it's best to first get your code working with the IIO/ADC stuff that is in staging, and get the touchscreen driver ready for merging, on top of that.

Quoted 9 lines

Ideally, you would also help out a bit on getting the IIO parts you need graduated from staging. Given Jonathan's explanation, I think my initial reaction was valid: we shouldn't take the ADC driver outside of IIO, because that ends up being more painful than getting the driver ready for inclusion now, and then rewriting it shortly after.

Arnd

Thank you all for your comments. I'm now working on the interface change to iio, it may take some time...
I've also applied most of the suggestions, they'll be in the next patches.

Signature · 10 lines
Rusk? P?ter
Fejleszt?m?rn?k

Prolan Zrt. / Prolan Co.
Hungary 2011 Budakal?sz, Szentendrei ?t 1-3.
Tel./Phone: +36 20 954 3118
Fax: +36 26 540 420
E-mail: rusko.peter at prolan.hu
Web: www.prolan.hu
Timezone:CET
#13 lore raw

PATCH 1/1 mx28: added LRADC and touchscreen support

Quoted 38 lines · Arnd Bergmann
Quoted 37 lines · Jonathan Cameron
Quoted 17 lines
Quoted 8 lines

As indicated by Shawn, adding a new driver specific kernel-level ADC interface is not a good idea. IIRC, the result of the last discussion was that all ADC drivers should be part of IIO and you should use the IIO in-kernel interfaces. Not sure what the state of that code is, but if it's not in mainline yet, you should work with Jonathan to make sure it gets there. Having more users for that code can only speed up the process, and I'm going to refuse another ADC driver in drivers/misc or arch/arm/mach-*/.

Quick summary of IIO status. Nothing is in mainline yet. Intent is to get the first set of core code (including in kernel pull interfaces) into linux-next fairly shortly (these have had enough postive feedback now I think). Doing push interfaces (as I think we would need here) is possible with existing patches on top of the stuff in the iio staging tree but there are some 'interesting' cases where both push and pull interfaces exist that still need addressing.

Quoted 5 lines

Also, note the push interface stuff (e.g. interrupt driven) requires a lot more of the IIO infrastructure to be in place (buffered support and the demux unit) so may still be some time. Personally my time is currently very restricted so all the help anyone can offer is most welcome!

Ok, thanks for the summary!

Peter, I guess what this means for you is that it's best to first get your code working with the IIO/ADC stuff that is in staging, and get the touchscreen driver ready for merging, on top of that.

Ideally, you would also help out a bit on getting the IIO parts you need graduated from staging. Given Jonathan's explanation, I think my initial reaction was valid: we shouldn't take the ADC driver outside of IIO, because that ends up being more painful than getting the driver ready for inclusion now, and then rewriting it shortly after.

Quoted 6 lines
Quoted 1 line

Arnd

Thank you all for your comments. I'm now working on the interface change to iio, it may take some time...
I've also applied most of the suggestions, they'll be in the next patches.

Are there any updates here?

M