linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
@ 2013-09-19 12:22 Juergen Beisert
  2013-09-19 12:22 ` [PATCH 1/7] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC Juergen Beisert
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

The following series replaces the current busy loop touchscreen implementation
for i.MX28/i.MX23 SoCs by a fully interrupt driven implementation.

Since i.MX23 and i.MX28 silicon differs, the existing implementation can
be used for the i.MX28 SoC only.

So, the first two patches of this series move the i.MX28 specific definitions
out of the way. The third patch simplifies the register access to make it easier
to add the i.MX23 support. Then the i.MX23 specific definitions are added, also
the code to distinguish both SoCs at run-time.
Up to here the existing touchscreen driver will now run on an i.MX23 Soc as well.

When the i.MX23 SoC is running from battery it seems not to be a good idea to
run a busy loop to detect touches and their location. The fourth patch adds a
fully interrupt driven implementation which makes use of the built-in delay
and multiple sample features of the touchscreen controller. This will reduce
the interrupt load to a minimum.

The next to last patch in this series just removes the existing busy loop
implementation.

The last patch adds a devicetree bindings proposal (to be discussed).

Some restrictions/questions:

- the touchscreen part is yet tested on i.MX23 SoC only
- has someone a good idea how to implement a reliable pressure measurement if
  the resistances of the touchscreen's plates are unknown?

Changes since v4:

- honor Jonathan's comments about function names
- honor Dmitry's comments about workqueue canceling and interrupts
- adding devicetree bindings proposal

Changes since v3:

- split adding register access functions and i.MX23 support into two patches

Changes since v2:

- useless debug output removed

Changes since v1:

- adding register access functions to make the existing code more readable
- adding some functions to distinguish the SoCs at run-time to avoid if-else
  contructs whenever differences in the register layout between i.MX23 and
  i.MX28 must be handled

Comments are welcome.

Juergen

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/7] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-19 12:22 ` [PATCH 2/7] Staging/iio/adc/touchscreen/MXS: separate i.MX28 specific register bits Juergen Beisert
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

The LRADC units in i.MX23 and i.MX28 differ and we need to distinguish both
SoC variants in order to make the touchscreen work on i.MX23

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index a08c173..dffca90 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -174,6 +174,8 @@ struct mxs_lradc {
 
 	struct input_dev	*ts_input;
 	struct work_struct	ts_work;
+
+	enum mxs_lradc_id	soc;
 };
 
 #define	LRADC_CTRL0				0x00
@@ -920,6 +922,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	}
 
 	lradc = iio_priv(iio);
+	lradc->soc = (enum mxs_lradc_id)of_id->data;
 
 	/* Grab the memory area */
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/7] Staging/iio/adc/touchscreen/MXS: separate i.MX28 specific register bits
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
  2013-09-19 12:22 ` [PATCH 1/7] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-19 12:22 ` [PATCH 3/7] Staging/iio/adc/touchscreen/MXS: simplify register access Juergen Beisert
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

In order to support i.MX23 and i.MX28 within one driver we need to separate the
register definitions which differ in both SoC variants.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 61 ++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index dffca90..5535fed 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -179,24 +179,29 @@ struct mxs_lradc {
 };
 
 #define	LRADC_CTRL0				0x00
-#define	LRADC_CTRL0_TOUCH_DETECT_ENABLE		(1 << 23)
-#define	LRADC_CTRL0_TOUCH_SCREEN_TYPE		(1 << 22)
-#define	LRADC_CTRL0_YNNSW	/* YM */	(1 << 21)
-#define	LRADC_CTRL0_YPNSW	/* YP */	(1 << 20)
-#define	LRADC_CTRL0_YPPSW	/* YP */	(1 << 19)
-#define	LRADC_CTRL0_XNNSW	/* XM */	(1 << 18)
-#define	LRADC_CTRL0_XNPSW	/* XM */	(1 << 17)
-#define	LRADC_CTRL0_XPPSW	/* XP */	(1 << 16)
-#define	LRADC_CTRL0_PLATE_MASK			(0x3f << 16)
+# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE	(1 << 23)
+# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE	(1 << 22)
+# define LRADC_CTRL0_MX28_YNNSW	/* YM */	(1 << 21)
+# define LRADC_CTRL0_MX28_YPNSW	/* YP */	(1 << 20)
+# define LRADC_CTRL0_MX28_YPPSW	/* YP */	(1 << 19)
+# define LRADC_CTRL0_MX28_XNNSW	/* XM */	(1 << 18)
+# define LRADC_CTRL0_MX28_XNPSW	/* XM */	(1 << 17)
+# define LRADC_CTRL0_MX28_XPPSW	/* XP */	(1 << 16)
+
+# define LRADC_CTRL0_MX28_PLATE_MASK \
+		(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \
+		LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \
+		LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \
+		LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW)
 
 #define	LRADC_CTRL1				0x10
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ_EN		(1 << 24)
 #define	LRADC_CTRL1_LRADC_IRQ_EN(n)		(1 << ((n) + 16))
-#define	LRADC_CTRL1_LRADC_IRQ_EN_MASK		(0x1fff << 16)
+#define	LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK	(0x1fff << 16)
 #define	LRADC_CTRL1_LRADC_IRQ_EN_OFFSET		16
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ		(1 << 8)
 #define	LRADC_CTRL1_LRADC_IRQ(n)		(1 << (n))
-#define	LRADC_CTRL1_LRADC_IRQ_MASK		0x1fff
+#define	LRADC_CTRL1_MX28_LRADC_IRQ_MASK		0x1fff
 #define	LRADC_CTRL1_LRADC_IRQ_OFFSET		0
 
 #define	LRADC_CTRL2				0x20
@@ -264,7 +269,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 	 * Virtual channel 0 is always used here as the others are always not
 	 * used if doing raw sampling.
 	 */
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 
@@ -319,9 +324,9 @@ static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
 	uint32_t reg;
 
 	/* Enable touch detection. */
-	writel(LRADC_CTRL0_PLATE_MASK,
+	writel(LRADC_CTRL0_MX28_PLATE_MASK,
 		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
 		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
 
 	msleep(LRADC_TS_SAMPLE_DELAY_MS);
@@ -367,21 +372,21 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
 	 */
 	switch (plate) {
 	case LRADC_SAMPLE_X:
-		ctrl0 = LRADC_CTRL0_XPPSW | LRADC_CTRL0_XNNSW;
+		ctrl0 = LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
 		chan = 3;
 		break;
 	case LRADC_SAMPLE_Y:
-		ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_YNNSW;
+		ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
 		chan = 4;
 		break;
 	case LRADC_SAMPLE_PRESSURE:
-		ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_XNNSW;
+		ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
 		chan = 5;
 		break;
 	}
 
 	if (change) {
-		writel(LRADC_CTRL0_PLATE_MASK,
+		writel(LRADC_CTRL0_MX28_PLATE_MASK,
 			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 		writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
 
@@ -442,7 +447,7 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work)
 
 	while (mxs_lradc_ts_touched(lradc)) {
 		/* Disable touch detector so we can sample the touchscreen. */
-		writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+		writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
 			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 
 		if (likely(valid)) {
@@ -491,7 +496,7 @@ static int mxs_lradc_ts_open(struct input_dev *dev)
 	lradc->stop_touchscreen = false;
 
 	/* Enable the touch-detect circuitry. */
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
 		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
 
 	/* Enable the touch-detect IRQ. */
@@ -517,7 +522,7 @@ static void mxs_lradc_ts_close(struct input_dev *dev)
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 
 	/* Power-down touchscreen touch-detect circuitry. */
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
+	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
 		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 }
 
@@ -581,7 +586,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 		LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
 		LRADC_CTRL1_TOUCH_DETECT_IRQ;
 
-	if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK))
+	if (!(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK))
 		return IRQ_NONE;
 
 	/*
@@ -601,7 +606,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
 		complete(&lradc->completion);
 
-	writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK,
+	writel(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK,
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 
 	return IRQ_HANDLED;
@@ -722,7 +727,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
 	if (ret < 0)
 		goto err_buf;
 
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 
@@ -763,7 +768,7 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
 		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
 
 	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 
 	kfree(lradc->buffer);
@@ -867,11 +872,11 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
 	writel(0, lradc->base + LRADC_DELAY(3));
 
 	/* Configure the touchscreen type */
-	writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
+	writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
 		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 
 	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) {
-		writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
+		writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
 			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
 	}
 
@@ -885,7 +890,7 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
 {
 	int i;
 
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
 
 	for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/7] Staging/iio/adc/touchscreen/MXS: simplify register access
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
  2013-09-19 12:22 ` [PATCH 1/7] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC Juergen Beisert
  2013-09-19 12:22 ` [PATCH 2/7] Staging/iio/adc/touchscreen/MXS: separate i.MX28 specific register bits Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-19 12:22 ` [PATCH 4/7] Staging/iio/adc/touchscreen/MXS: add i.MX23 support to the LRADC touchscreen driver Juergen Beisert
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual register access by a few shared access function to make the
code easier to read and in order to add the i.MX23 SoC in the next step.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 204 +++++++++++++++++++++---------------
 1 file changed, 120 insertions(+), 84 deletions(-)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 5535fed..43d5ce4 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -235,6 +235,56 @@ struct mxs_lradc {
 #define LRADC_RESOLUTION			12
 #define LRADC_SINGLE_SAMPLE_MASK		((1 << LRADC_RESOLUTION) - 1)
 
+static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg + STMP_OFFSET_REG_SET);
+}
+
+static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR);
+}
+
+static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg);
+}
+
+static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL0_MX28_PLATE_MASK;
+}
+
+static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
+}
+
+static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL1_MX28_LRADC_IRQ_MASK;
+}
+
+static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE;
+}
+
+static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
+}
+
+static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
+}
+
+static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
+{
+	return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
+}
+
 /*
  * Raw I/O operations
  */
@@ -269,21 +319,19 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 	 * Virtual channel 0 is always used here as the others are always not
 	 * used if doing raw sampling.
 	 */
-	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+			LRADC_CTRL1);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
 	/* Clean the slot's previous content, then set new one. */
-	writel(LRADC_CTRL4_LRADCSELECT_MASK(0),
-		lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-	writel(chan->channel, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4);
 
-	writel(0, lradc->base + LRADC_CH(0));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0));
 
 	/* Enable the IRQ and start sampling the channel. */
-	writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
-	writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0);
 
 	/* Wait for completion on the channel, 1 second max. */
 	ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
@@ -297,8 +345,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 	ret = IIO_VAL_INT;
 
 err:
-	writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
 
 	mutex_unlock(&lradc->lock);
 
@@ -324,10 +371,9 @@ static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
 	uint32_t reg;
 
 	/* Enable touch detection. */
-	writel(LRADC_CTRL0_MX28_PLATE_MASK,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
+								LRADC_CTRL0);
 
 	msleep(LRADC_TS_SAMPLE_DELAY_MS);
 
@@ -372,32 +418,33 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
 	 */
 	switch (plate) {
 	case LRADC_SAMPLE_X:
-		ctrl0 = LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
+		ctrl0 = mxs_lradc_drive_x_plate(lradc);
 		chan = 3;
 		break;
 	case LRADC_SAMPLE_Y:
-		ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
+		ctrl0 = mxs_lradc_drive_y_plate(lradc);
 		chan = 4;
 		break;
 	case LRADC_SAMPLE_PRESSURE:
-		ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
+		ctrl0 = mxs_lradc_drive_pressure(lradc);
 		chan = 5;
 		break;
 	}
 
 	if (change) {
-		writel(LRADC_CTRL0_MX28_PLATE_MASK,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-		writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
-
-		writel(LRADC_CTRL4_LRADCSELECT_MASK(slot),
-			lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-		writel(chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot),
-			lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
+		mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc),
+						LRADC_CTRL0);
+		mxs_lradc_reg_set(lradc, ctrl0, LRADC_CTRL0);
+
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(slot),
+						LRADC_CTRL4);
+		mxs_lradc_reg_set(lradc,
+				chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot),
+				LRADC_CTRL4);
 	}
 
-	writel(0xffffffff, lradc->base + LRADC_CH(slot) + STMP_OFFSET_REG_CLR);
-	writel(1 << slot, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, 0xffffffff, LRADC_CH(slot));
+	mxs_lradc_reg_set(lradc, 1 << slot, LRADC_CTRL0);
 
 	delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS);
 	do {
@@ -407,8 +454,7 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
 			break;
 	} while (time_before(jiff, delay));
 
-	writel(LRADC_CTRL1_LRADC_IRQ(slot),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(slot), LRADC_CTRL1);
 
 	if (time_after_eq(jiff, delay))
 		return -ETIMEDOUT;
@@ -447,8 +493,8 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work)
 
 	while (mxs_lradc_ts_touched(lradc)) {
 		/* Disable touch detector so we can sample the touchscreen. */
-		writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+		mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc),
+						LRADC_CTRL0);
 
 		if (likely(valid)) {
 			input_report_abs(lradc->ts_input, ABS_X, val_x);
@@ -482,10 +528,8 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work)
 		return;
 
 	/* Restart the touchscreen interrupts. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
 static int mxs_lradc_ts_open(struct input_dev *dev)
@@ -496,12 +540,11 @@ static int mxs_lradc_ts_open(struct input_dev *dev)
 	lradc->stop_touchscreen = false;
 
 	/* Enable the touch-detect circuitry. */
-	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
+						LRADC_CTRL0);
 
 	/* Enable the touch-detect IRQ. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 
 	return 0;
 }
@@ -518,12 +561,11 @@ static void mxs_lradc_ts_close(struct input_dev *dev)
 	cancel_work_sync(&lradc->ts_work);
 
 	/* Disable touchscreen touch-detect IRQ. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+						LRADC_CTRL1);
 
 	/* Power-down touchscreen touch-detect circuitry. */
-	writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), LRADC_CTRL0);
 }
 
 static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
@@ -586,7 +628,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 		LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
 		LRADC_CTRL1_TOUCH_DETECT_IRQ;
 
-	if (!(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK))
+	if (!(reg & mxs_lradc_irq_mask(lradc)))
 		return IRQ_NONE;
 
 	/*
@@ -595,8 +637,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 	 * it ASAP
 	 */
 	if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) {
-		writel(ts_irq_mask,
-			lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+		mxs_lradc_reg_clear(lradc, ts_irq_mask, LRADC_CTRL1);
 		if (!lradc->stop_touchscreen)
 			schedule_work(&lradc->ts_work);
 	}
@@ -606,8 +647,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
 		complete(&lradc->completion);
 
-	writel(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
 
 	return IRQ_HANDLED;
 }
@@ -626,7 +666,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
 
 	for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
 		lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
-		writel(chan_value, lradc->base + LRADC_CH(j));
+		mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j));
 		lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
 		lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP;
 		j++;
@@ -651,7 +691,7 @@ static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state)
 	struct mxs_lradc *lradc = iio_priv(iio);
 	const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
 
-	writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st);
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st);
 
 	return 0;
 }
@@ -727,29 +767,26 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
 	if (ret < 0)
 		goto err_buf;
 
-	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+							LRADC_CTRL1);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
 	for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
 		ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
 		ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs);
 		ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
-		writel(chan_value, lradc->base + LRADC_CH(ofs));
+		mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs));
 		bitmap_set(&enable, ofs, 1);
 		ofs++;
 	}
 
-	writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
-
-	writel(ctrl4_clr, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-	writel(ctrl4_set, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
-
-	writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
-
-	writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
+					LRADC_DELAY_KICK, LRADC_DELAY(0));
+	mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
+					LRADC_DELAY(0));
 
 	return 0;
 
@@ -764,12 +801,12 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
 {
 	struct mxs_lradc *lradc = iio_priv(iio);
 
-	writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
+					LRADC_DELAY_KICK, LRADC_DELAY(0));
 
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+					LRADC_CTRL1);
 
 	kfree(lradc->buffer);
 	mutex_unlock(&lradc->lock);
@@ -864,24 +901,24 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
 		return ret;
 
 	/* Configure DELAY CHANNEL 0 for generic ADC sampling. */
-	writel(adc_cfg, lradc->base + LRADC_DELAY(0));
+	mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0));
 
 	/* Disable remaining DELAY CHANNELs */
-	writel(0, lradc->base + LRADC_DELAY(1));
-	writel(0, lradc->base + LRADC_DELAY(2));
-	writel(0, lradc->base + LRADC_DELAY(3));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
 
 	/* Configure the touchscreen type */
-	writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+							LRADC_CTRL0);
 
-	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) {
-		writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
+		mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+				LRADC_CTRL0);
 	}
 
 	/* Start internal temperature sensing. */
-	writel(0, lradc->base + LRADC_CTRL2);
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2);
 
 	return 0;
 }
@@ -890,11 +927,10 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
 {
 	int i;
 
-	writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1);
 
 	for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
-		writel(0, lradc->base + LRADC_DELAY(i));
+		mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
 }
 
 static const struct of_device_id mxs_lradc_dt_ids[] = {
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/7] Staging/iio/adc/touchscreen/MXS: add i.MX23 support to the LRADC touchscreen driver
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
                   ` (2 preceding siblings ...)
  2013-09-19 12:22 ` [PATCH 3/7] Staging/iio/adc/touchscreen/MXS: simplify register access Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-19 12:22 ` [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection Juergen Beisert
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

Distinguish i.MX23 and i.MX28 at runtime and do the same for both SoC at least
for the 4 wire touchscreen.

Note: support for the remaining LRADC channels is not tested on an
i.MX23 yet.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 66 ++++++++++++++++++++++++++++++-------
 1 file changed, 55 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 43d5ce4..c70c31f 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -188,20 +188,33 @@ struct mxs_lradc {
 # define LRADC_CTRL0_MX28_XNPSW	/* XM */	(1 << 17)
 # define LRADC_CTRL0_MX28_XPPSW	/* XP */	(1 << 16)
 
+# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE	(1 << 20)
+# define LRADC_CTRL0_MX23_YM			(1 << 19)
+# define LRADC_CTRL0_MX23_XM			(1 << 18)
+# define LRADC_CTRL0_MX23_YP			(1 << 17)
+# define LRADC_CTRL0_MX23_XP			(1 << 16)
+
 # define LRADC_CTRL0_MX28_PLATE_MASK \
 		(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \
 		LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \
 		LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \
 		LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW)
 
+# define LRADC_CTRL0_MX23_PLATE_MASK \
+		(LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \
+		LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \
+		LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP)
+
 #define	LRADC_CTRL1				0x10
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ_EN		(1 << 24)
 #define	LRADC_CTRL1_LRADC_IRQ_EN(n)		(1 << ((n) + 16))
 #define	LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK	(0x1fff << 16)
+#define	LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK	(0x01ff << 16)
 #define	LRADC_CTRL1_LRADC_IRQ_EN_OFFSET		16
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ		(1 << 8)
 #define	LRADC_CTRL1_LRADC_IRQ(n)		(1 << (n))
 #define	LRADC_CTRL1_MX28_LRADC_IRQ_MASK		0x1fff
+#define	LRADC_CTRL1_MX23_LRADC_IRQ_MASK		0x01ff
 #define	LRADC_CTRL1_LRADC_IRQ_OFFSET		0
 
 #define	LRADC_CTRL2				0x20
@@ -252,37 +265,58 @@ static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg)
 
 static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL0_MX28_PLATE_MASK;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_PLATE_MASK;
+	else
+		return LRADC_CTRL0_MX28_PLATE_MASK;
 }
 
 static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
+	else
+		return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
 }
 
 static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL1_MX28_LRADC_IRQ_MASK;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL1_MX23_LRADC_IRQ_MASK;
+	else
+		return LRADC_CTRL1_MX28_LRADC_IRQ_MASK;
 }
 
 static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE;
+	else
+		return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE;
 }
 
 static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM;
+	else
+		return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
 }
 
 static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM;
+	else
+		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
 }
 
 static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
 {
-	return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM;
+	else
+		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
 }
 
 /*
@@ -319,7 +353,8 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 	 * Virtual channel 0 is always used here as the others are always not
 	 * used if doing raw sampling.
 	 */
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 			LRADC_CTRL1);
 	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
@@ -767,7 +802,8 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
 	if (ret < 0)
 		goto err_buf;
 
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 							LRADC_CTRL1);
 	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
@@ -805,7 +841,8 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
 					LRADC_DELAY_KICK, LRADC_DELAY(0));
 
 	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
 					LRADC_CTRL1);
 
 	kfree(lradc->buffer);
@@ -909,7 +946,8 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
 	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
 
 	/* Configure the touchscreen type */
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+	if (lradc->soc == IMX28_LRADC) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
 							LRADC_CTRL0);
 
 	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
@@ -987,6 +1025,12 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 		dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n",
 				ts_wires);
 
+	if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) {
+		dev_warn(dev, "No support for 5 wire touches on i.MX23\n");
+		dev_warn(dev, "Falling back to 4 wire\n");
+		ts_wires = 4;
+	}
+
 	/* Grab all IRQ sources */
 	for (i = 0; i < of_cfg->irq_count; i++) {
 		lradc->irq[i] = platform_get_irq(pdev, i);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
                   ` (3 preceding siblings ...)
  2013-09-19 12:22 ` [PATCH 4/7] Staging/iio/adc/touchscreen/MXS: add i.MX23 support to the LRADC touchscreen driver Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-21 12:36   ` Jonathan Cameron
  2013-09-19 12:22 ` [PATCH 6/7] Staging/iio/adc/touchscreen/MXS: Remove old touchscreen detection implementation Juergen Beisert
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

For battery driven systems it is a very bad idea to collect the touchscreen
data within a kernel busy loop.

This change uses the features of the hardware to delay and accumulate samples in
hardware to avoid a high interrupt and CPU load.

Note: this is only tested on an i.MX23 SoC yet.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 532 ++++++++++++++++++++++++++++++++----
 1 file changed, 476 insertions(+), 56 deletions(-)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index c70c31f..9f3f367 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -129,6 +129,17 @@ enum mxs_lradc_ts {
 	MXS_LRADC_TOUCHSCREEN_5WIRE,
 };
 
+/*
+ * Touchscreen handling
+ */
+enum lradc_ts_plate {
+	LRADC_TOUCH = 0,
+	LRADC_SAMPLE_X,
+	LRADC_SAMPLE_Y,
+	LRADC_SAMPLE_PRESSURE,
+	LRADC_SAMPLE_VALID,
+};
+
 struct mxs_lradc {
 	struct device		*dev;
 	void __iomem		*base;
@@ -169,13 +180,25 @@ struct mxs_lradc {
 #define CHAN_MASK_TOUCHSCREEN_4WIRE	(0xf << 2)
 #define CHAN_MASK_TOUCHSCREEN_5WIRE	(0x1f << 2)
 	enum mxs_lradc_ts	use_touchscreen;
-	bool			stop_touchscreen;
 	bool			use_touchbutton;
 
 	struct input_dev	*ts_input;
 	struct work_struct	ts_work;
 
 	enum mxs_lradc_id	soc;
+	enum lradc_ts_plate	cur_plate; /* statemachine */
+	bool			ts_valid;
+	unsigned		ts_x_pos;
+	unsigned		ts_y_pos;
+	unsigned		ts_pressure;
+
+	/* handle touchscreen's physical behaviour */
+	/* samples per coordinate */
+	unsigned		over_sample_cnt;
+	/* time clocks between samples */
+	unsigned		over_sample_delay;
+	/* time in clocks to wait after the plates where switched */
+	unsigned		settling_delay;
 };
 
 #define	LRADC_CTRL0				0x00
@@ -227,19 +250,33 @@ struct mxs_lradc {
 #define	LRADC_CH_ACCUMULATE			(1 << 29)
 #define	LRADC_CH_NUM_SAMPLES_MASK		(0x1f << 24)
 #define	LRADC_CH_NUM_SAMPLES_OFFSET		24
+#define	LRADC_CH_NUM_SAMPLES(x) \
+				((x) << LRADC_CH_NUM_SAMPLES_OFFSET)
 #define	LRADC_CH_VALUE_MASK			0x3ffff
 #define	LRADC_CH_VALUE_OFFSET			0
 
 #define	LRADC_DELAY(n)				(0xd0 + (0x10 * (n)))
 #define	LRADC_DELAY_TRIGGER_LRADCS_MASK		(0xff << 24)
 #define	LRADC_DELAY_TRIGGER_LRADCS_OFFSET	24
+#define	LRADC_DELAY_TRIGGER(x) \
+				(((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \
+				LRADC_DELAY_TRIGGER_LRADCS_MASK)
 #define	LRADC_DELAY_KICK			(1 << 20)
 #define	LRADC_DELAY_TRIGGER_DELAYS_MASK		(0xf << 16)
 #define	LRADC_DELAY_TRIGGER_DELAYS_OFFSET	16
+#define	LRADC_DELAY_TRIGGER_DELAYS(x) \
+				(((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \
+				LRADC_DELAY_TRIGGER_DELAYS_MASK)
 #define	LRADC_DELAY_LOOP_COUNT_MASK		(0x1f << 11)
 #define	LRADC_DELAY_LOOP_COUNT_OFFSET		11
+#define	LRADC_DELAY_LOOP(x) \
+				(((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \
+				LRADC_DELAY_LOOP_COUNT_MASK)
 #define	LRADC_DELAY_DELAY_MASK			0x7ff
 #define	LRADC_DELAY_DELAY_OFFSET		0
+#define	LRADC_DELAY_DELAY(x) \
+				(((x) << LRADC_DELAY_DELAY_OFFSET) & \
+				LRADC_DELAY_DELAY_MASK)
 
 #define	LRADC_CTRL4				0x140
 #define	LRADC_CTRL4_LRADCSELECT_MASK(n)		(0xf << ((n) * 4))
@@ -319,6 +356,404 @@ static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
 		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
 }
 
+static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
+{
+	return !!(readl(lradc->base + LRADC_STATUS) &
+					LRADC_STATUS_TOUCH_DETECT_RAW);
+}
+
+static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
+{
+	/*
+	 * prepare for oversampling conversion
+	 *
+	 * from the datasheet:
+	 * "The ACCUMULATE bit in the appropriate channel register
+	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
+	 * otherwise, the IRQs will not fire."
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE |
+			LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1),
+			LRADC_CH(ch));
+
+	/* from the datasheet:
+	 * "Software must clear this register in preparation for a
+	 * multi-cycle accumulation.
+	 */
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch));
+
+	/* prepare the delay/loop unit according to the oversampling count */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) |
+		LRADC_DELAY_TRIGGER_DELAYS(0) |
+		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
+		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
+			LRADC_DELAY(3));
+
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
+			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
+			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+
+	/* wake us again, when the complete conversion is done */
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
+	/*
+	 * after changing the touchscreen plates setting
+	 * the signals need some initial time to settle. Start the
+	 * SoC's delay unit and start the conversion later
+	 * and automatically.
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
+		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+		LRADC_DELAY_KICK |
+		LRADC_DELAY_DELAY(lradc->settling_delay),
+			LRADC_DELAY(2));
+}
+
+/*
+ * Pressure detection is special:
+ * We want to do both required measurements for the pressure detection in
+ * one turn. Use the hardware features to chain both conversions and let the
+ * hardware report one interrupt if both conversions are done
+ */
+static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
+							unsigned ch2)
+{
+	u32 reg;
+
+	/*
+	 * prepare for oversampling conversion
+	 *
+	 * from the datasheet:
+	 * "The ACCUMULATE bit in the appropriate channel register
+	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
+	 * otherwise, the IRQs will not fire."
+	 */
+	reg = LRADC_CH_ACCUMULATE |
+		LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1);
+	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1));
+	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2));
+
+	/* from the datasheet:
+	 * "Software must clear this register in preparation for a
+	 * multi-cycle accumulation.
+	 */
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1));
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2));
+
+	/* prepare the delay/loop unit according to the oversampling count */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) |
+		LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */
+		LRADC_DELAY_TRIGGER_DELAYS(0) |
+		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
+		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
+					LRADC_DELAY(3));
+
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
+			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
+			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+
+	/* wake us again, when the conversions are done */
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
+	/*
+	 * after changing the touchscreen plates setting
+	 * the signals need some initial time to settle. Start the
+	 * SoC's delay unit and start the conversion later
+	 * and automatically.
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
+		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+		LRADC_DELAY_KICK |
+		LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2));
+}
+
+static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc,
+							unsigned channel)
+{
+	u32 reg;
+	unsigned num_samples, val;
+
+	reg = readl(lradc->base + LRADC_CH(channel));
+	if (reg & LRADC_CH_ACCUMULATE)
+		num_samples = lradc->over_sample_cnt;
+	else
+		num_samples = 1;
+
+	val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET;
+	return val / num_samples;
+}
+
+static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
+						unsigned ch1, unsigned ch2)
+{
+	u32 reg, mask;
+	unsigned pressure, m1, m2;
+
+	mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2);
+	reg = readl(lradc->base + LRADC_CTRL1) & mask;
+
+	while (reg != mask) {
+		reg = readl(lradc->base + LRADC_CTRL1) & mask;
+		dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg);
+	}
+
+	m1 = mxs_lradc_read_raw_channel(lradc, ch1);
+	m2 = mxs_lradc_read_raw_channel(lradc, ch2);
+
+	if (m2 == 0) {
+		dev_warn(lradc->dev, "Cannot calculate pressure\n");
+		return 1 << (LRADC_RESOLUTION - 1);
+	}
+
+	/* simply scale the value from 0 ... max ADC resolution */
+	pressure = m1;
+	pressure *= (1 << LRADC_RESOLUTION);
+	pressure /= m2;
+
+	dev_dbg(lradc->dev, "Pressure = %u\n", pressure);
+	return pressure;
+}
+
+#define TS_CH_XP 2
+#define TS_CH_YP 3
+#define TS_CH_XM 4
+#define TS_CH_YM 5
+
+static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
+{
+	u32 reg;
+	int val;
+
+	reg = readl(lradc->base + LRADC_CTRL1);
+
+	/* only channels 3 to 5 are of interest here */
+	if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
+	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
+	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
+	} else {
+		return -EIO;
+	}
+
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
+
+	return val;
+}
+
+/*
+ * YP(open)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ *    YM(-)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *         XP(weak+)        XM(open)
+ *
+ * "weak+" means 200k Ohm VDDIO
+ * (-) means GND
+ */
+static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc)
+{
+	/*
+	 * In order to detect a touch event the 'touch detect enable' bit
+	 * enables:
+	 *  - a weak pullup to the X+ connector
+	 *  - a strong ground at the Y- connector
+	 */
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
+				LRADC_CTRL0);
+}
+
+/*
+ * YP(meas)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ * YM(open)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *           XP(+)          XM(-)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_X;
+	mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
+}
+
+/*
+ *   YP(+)--+-------------+
+ *          |             |--+
+ *          |             |  |
+ *   YM(-)--+-------------+  |
+ *            +--------------+
+ *            |              |
+ *         XP(open)        XM(meas)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_Y;
+	mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
+}
+
+/*
+ *    YP(+)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ * YM(meas)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *          XP(meas)        XM(-)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
+	mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+}
+
+static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
+{
+	mxs_lradc_setup_touch_detection(lradc);
+
+	lradc->cur_plate = LRADC_TOUCH;
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
+				LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+}
+
+static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
+{
+	input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
+	input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos);
+	input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure);
+	input_report_key(lradc->ts_input, BTN_TOUCH, 1);
+	input_sync(lradc->ts_input);
+}
+
+static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
+{
+	mxs_lradc_setup_touch_detection(lradc);
+	lradc->cur_plate = LRADC_SAMPLE_VALID;
+	/*
+	 * start a dummy conversion to burn time to settle the signals
+	 * note: we are not interested in the conversion's value
+	 */
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
+		LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
+			LRADC_DELAY(2));
+}
+
+/*
+ * in order to avoid false measurements, report only samples where
+ * the surface is still touched after the position measurement
+ */
+static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
+{
+	/* if it is still touched, report the sample */
+	if (valid && mxs_lradc_check_touch_event(lradc)) {
+		lradc->ts_valid = true;
+		mxs_lradc_report_ts_event(lradc);
+	}
+
+	/* if it is even still touched, continue with the next measurement */
+	if (mxs_lradc_check_touch_event(lradc)) {
+		mxs_lradc_prepare_y_pos(lradc);
+		return;
+	}
+
+	if (lradc->ts_valid) {
+		/* signal the release */
+		lradc->ts_valid = false;
+		input_report_key(lradc->ts_input, BTN_TOUCH, 0);
+		input_sync(lradc->ts_input);
+	}
+
+	/* if it is released, wait for the next touch via IRQ */
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+}
+
+/* touchscreen's state machine */
+static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
+{
+	int val;
+
+	switch (lradc->cur_plate) {
+	case LRADC_TOUCH:
+		/*
+		 * start with the Y-pos, because it uses nearly the same plate
+		 * settings like the touch detection
+		 */
+		if (mxs_lradc_check_touch_event(lradc)) {
+			mxs_lradc_reg_clear(lradc,
+					LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+					LRADC_CTRL1);
+			mxs_lradc_prepare_y_pos(lradc);
+		}
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
+					LRADC_CTRL1);
+		return;
+
+	case LRADC_SAMPLE_Y:
+		val = mxs_lradc_read_ts_channel(lradc);
+		if (val < 0) {
+			mxs_lradc_enable_touch_detection(lradc); /* re-start */
+			return;
+		}
+		lradc->ts_y_pos = val;
+		mxs_lradc_prepare_x_pos(lradc);
+		return;
+
+	case LRADC_SAMPLE_X:
+		val = mxs_lradc_read_ts_channel(lradc);
+		if (val < 0) {
+			mxs_lradc_enable_touch_detection(lradc); /* re-start */
+			return;
+		}
+		lradc->ts_x_pos = val;
+		mxs_lradc_prepare_pressure(lradc);
+		return;
+
+	case LRADC_SAMPLE_PRESSURE:
+		lradc->ts_pressure =
+			mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+		mxs_lradc_complete_touch_event(lradc);
+		return;
+
+	case LRADC_SAMPLE_VALID:
+		val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
+		mxs_lradc_finish_touch_event(lradc, 1);
+		break;
+	}
+}
+
 /*
  * Raw I/O operations
  */
@@ -392,15 +827,6 @@ static const struct iio_info mxs_lradc_iio_info = {
 	.read_raw		= mxs_lradc_read_raw,
 };
 
-/*
- * Touchscreen handling
- */
-enum lradc_ts_plate {
-	LRADC_SAMPLE_X,
-	LRADC_SAMPLE_Y,
-	LRADC_SAMPLE_PRESSURE,
-};
-
 static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
 {
 	uint32_t reg;
@@ -558,10 +984,6 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work)
 	input_report_key(lradc->ts_input, BTN_TOUCH, 0);
 	input_sync(lradc->ts_input);
 
-	/* Do not restart the TS IRQ if the driver is shutting down. */
-	if (lradc->stop_touchscreen)
-		return;
-
 	/* Restart the touchscreen interrupts. */
 	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
 	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
@@ -571,36 +993,29 @@ static int mxs_lradc_ts_open(struct input_dev *dev)
 {
 	struct mxs_lradc *lradc = input_get_drvdata(dev);
 
-	/* The touchscreen is starting. */
-	lradc->stop_touchscreen = false;
-
 	/* Enable the touch-detect circuitry. */
-	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
-						LRADC_CTRL0);
-
-	/* Enable the touch-detect IRQ. */
-	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+	mxs_lradc_enable_touch_detection(lradc);
 
 	return 0;
 }
 
-static void mxs_lradc_ts_close(struct input_dev *dev)
+static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
 {
-	struct mxs_lradc *lradc = input_get_drvdata(dev);
-
-	/* Indicate the touchscreen is stopping. */
-	lradc->stop_touchscreen = true;
-	mb();
+	/* stop all interrupts from firing */
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
+		LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
+		LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
+		LRADC_CTRL1);
 
-	/* Wait until touchscreen thread finishes any possible remnants. */
-	cancel_work_sync(&lradc->ts_work);
+	/* Power-down touchscreen touch-detect circuitry. */
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+}
 
-	/* Disable touchscreen touch-detect IRQ. */
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-						LRADC_CTRL1);
+static void mxs_lradc_ts_close(struct input_dev *dev)
+{
+	struct mxs_lradc *lradc = input_get_drvdata(dev);
 
-	/* Power-down touchscreen touch-detect circuitry. */
-	mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), LRADC_CTRL0);
+	mxs_lradc_disable_ts(lradc);
 }
 
 static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
@@ -646,8 +1061,7 @@ static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
 	if (!lradc->use_touchscreen)
 		return;
 
-	cancel_work_sync(&lradc->ts_work);
-
+	mxs_lradc_disable_ts(lradc);
 	input_unregister_device(lradc->ts_input);
 }
 
@@ -660,30 +1074,23 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
 	struct mxs_lradc *lradc = iio_priv(iio);
 	unsigned long reg = readl(lradc->base + LRADC_CTRL1);
 	const uint32_t ts_irq_mask =
-		LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
-		LRADC_CTRL1_TOUCH_DETECT_IRQ;
+		LRADC_CTRL1_TOUCH_DETECT_IRQ |
+		LRADC_CTRL1_LRADC_IRQ(2) |
+		LRADC_CTRL1_LRADC_IRQ(3) |
+		LRADC_CTRL1_LRADC_IRQ(4) |
+		LRADC_CTRL1_LRADC_IRQ(5);
 
 	if (!(reg & mxs_lradc_irq_mask(lradc)))
 		return IRQ_NONE;
 
-	/*
-	 * Touchscreen IRQ handling code has priority and therefore
-	 * is placed here. In case touchscreen IRQ arrives, disable
-	 * it ASAP
-	 */
-	if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) {
-		mxs_lradc_reg_clear(lradc, ts_irq_mask, LRADC_CTRL1);
-		if (!lradc->stop_touchscreen)
-			schedule_work(&lradc->ts_work);
-	}
+	if (lradc->use_touchscreen && (reg & ts_irq_mask))
+		mxs_lradc_handle_touch(lradc);
 
 	if (iio_buffer_enabled(iio))
 		iio_trigger_poll(iio->trig, iio_get_time_ns());
 	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
 		complete(&lradc->completion);
 
-	mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
-
 	return IRQ_HANDLED;
 }
 
@@ -978,6 +1385,17 @@ static const struct of_device_id mxs_lradc_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
 
+static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
+						struct device_node *lradc_node)
+{
+	/* TODO retrieve from device tree */
+	lradc->over_sample_cnt = 4;
+	lradc->over_sample_delay = 2;
+	lradc->settling_delay = 10;
+
+	return 0;
+}
+
 static int mxs_lradc_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -990,7 +1408,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	struct iio_dev *iio;
 	struct resource *iores;
 	uint32_t ts_wires = 0;
-	int ret = 0;
+	int ret = 0, touch_ret;
 	int i;
 
 	/* Allocate the IIO device. */
@@ -1010,7 +1428,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	if (IS_ERR(lradc->base))
 		return PTR_ERR(lradc->base);
 
-	INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work);
+	touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
 	/* Check if touchscreen is enabled in DT. */
 	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
@@ -1073,9 +1491,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 		goto err_dev;
 
 	/* Register the touchscreen input device. */
-	ret = mxs_lradc_ts_register(lradc);
-	if (ret)
-		goto err_dev;
+	if (touch_ret == 0) {
+		ret = mxs_lradc_ts_register(lradc);
+		if (ret)
+			goto err_dev;
+	}
 
 	/* Register IIO device. */
 	ret = iio_device_register(iio);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/7] Staging/iio/adc/touchscreen/MXS: Remove old touchscreen detection implementation
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
                   ` (4 preceding siblings ...)
  2013-09-19 12:22 ` [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-19 12:22 ` [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption Juergen Beisert
  2013-09-22 23:55 ` [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Marek Vasut
  7 siblings, 0 replies; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/mxs-lradc.c | 163 ------------------------------------
 1 file changed, 163 deletions(-)

diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 9f3f367..122475f 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -183,7 +183,6 @@ struct mxs_lradc {
 	bool			use_touchbutton;
 
 	struct input_dev	*ts_input;
-	struct work_struct	ts_work;
 
 	enum mxs_lradc_id	soc;
 	enum lradc_ts_plate	cur_plate; /* statemachine */
@@ -827,168 +826,6 @@ static const struct iio_info mxs_lradc_iio_info = {
 	.read_raw		= mxs_lradc_read_raw,
 };
 
-static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
-{
-	uint32_t reg;
-
-	/* Enable touch detection. */
-	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
-	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
-								LRADC_CTRL0);
-
-	msleep(LRADC_TS_SAMPLE_DELAY_MS);
-
-	reg = readl(lradc->base + LRADC_STATUS);
-
-	return reg & LRADC_STATUS_TOUCH_DETECT_RAW;
-}
-
-static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
-				enum lradc_ts_plate plate, int change)
-{
-	unsigned long delay, jiff;
-	uint32_t reg, ctrl0 = 0, chan = 0;
-	/* The touchscreen always uses CTRL4 slot #7. */
-	const uint8_t slot = 7;
-	uint32_t val;
-
-	/*
-	 * There are three correct configurations of the controller sampling
-	 * the touchscreen, each of these configuration provides different
-	 * information from the touchscreen.
-	 *
-	 * The following table describes the sampling configurations:
-	 * +-------------+-------+-------+-------+
-	 * | Wire \ Axis |   X   |   Y   |   Z   |
-	 * +---------------------+-------+-------+
-	 * |   X+ (CH2)  |   HI  |   TS  |   TS  |
-	 * +-------------+-------+-------+-------+
-	 * |   X- (CH4)  |   LO  |   SH  |   HI  |
-	 * +-------------+-------+-------+-------+
-	 * |   Y+ (CH3)  |   SH  |   HI  |   HI  |
-	 * +-------------+-------+-------+-------+
-	 * |   Y- (CH5)  |   TS  |   LO  |   SH  |
-	 * +-------------+-------+-------+-------+
-	 *
-	 * HI ... strong '1'  ; LO ... strong '0'
-	 * SH ... sample here ; TS ... tri-state
-	 *
-	 * There are a few other ways of obtaining the Z coordinate
-	 * (aka. pressure), but the one in the table seems to be the
-	 * most reliable one.
-	 */
-	switch (plate) {
-	case LRADC_SAMPLE_X:
-		ctrl0 = mxs_lradc_drive_x_plate(lradc);
-		chan = 3;
-		break;
-	case LRADC_SAMPLE_Y:
-		ctrl0 = mxs_lradc_drive_y_plate(lradc);
-		chan = 4;
-		break;
-	case LRADC_SAMPLE_PRESSURE:
-		ctrl0 = mxs_lradc_drive_pressure(lradc);
-		chan = 5;
-		break;
-	}
-
-	if (change) {
-		mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc),
-						LRADC_CTRL0);
-		mxs_lradc_reg_set(lradc, ctrl0, LRADC_CTRL0);
-
-		mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(slot),
-						LRADC_CTRL4);
-		mxs_lradc_reg_set(lradc,
-				chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot),
-				LRADC_CTRL4);
-	}
-
-	mxs_lradc_reg_clear(lradc, 0xffffffff, LRADC_CH(slot));
-	mxs_lradc_reg_set(lradc, 1 << slot, LRADC_CTRL0);
-
-	delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS);
-	do {
-		jiff = jiffies;
-		reg = readl_relaxed(lradc->base + LRADC_CTRL1);
-		if (reg & LRADC_CTRL1_LRADC_IRQ(slot))
-			break;
-	} while (time_before(jiff, delay));
-
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(slot), LRADC_CTRL1);
-
-	if (time_after_eq(jiff, delay))
-		return -ETIMEDOUT;
-
-	val = readl(lradc->base + LRADC_CH(slot));
-	val &= LRADC_CH_VALUE_MASK;
-
-	return val;
-}
-
-static int32_t mxs_lradc_ts_sample_filter(struct mxs_lradc *lradc,
-				enum lradc_ts_plate plate)
-{
-	int32_t val, tot = 0;
-	int i;
-
-	val = mxs_lradc_ts_sample(lradc, plate, 1);
-
-	/* Delay a bit so the touchscreen is stable. */
-	mdelay(2);
-
-	for (i = 0; i < LRADC_TS_SAMPLE_AMOUNT; i++) {
-		val = mxs_lradc_ts_sample(lradc, plate, 0);
-		tot += val;
-	}
-
-	return tot / LRADC_TS_SAMPLE_AMOUNT;
-}
-
-static void mxs_lradc_ts_work(struct work_struct *ts_work)
-{
-	struct mxs_lradc *lradc = container_of(ts_work,
-				struct mxs_lradc, ts_work);
-	int val_x, val_y, val_p;
-	bool valid = false;
-
-	while (mxs_lradc_ts_touched(lradc)) {
-		/* Disable touch detector so we can sample the touchscreen. */
-		mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc),
-						LRADC_CTRL0);
-
-		if (likely(valid)) {
-			input_report_abs(lradc->ts_input, ABS_X, val_x);
-			input_report_abs(lradc->ts_input, ABS_Y, val_y);
-			input_report_abs(lradc->ts_input, ABS_PRESSURE, val_p);
-			input_report_key(lradc->ts_input, BTN_TOUCH, 1);
-			input_sync(lradc->ts_input);
-		}
-
-		valid = false;
-
-		val_x = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_X);
-		if (val_x < 0)
-			continue;
-		val_y = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_Y);
-		if (val_y < 0)
-			continue;
-		val_p = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_PRESSURE);
-		if (val_p < 0)
-			continue;
-
-		valid = true;
-	}
-
-	input_report_abs(lradc->ts_input, ABS_PRESSURE, 0);
-	input_report_key(lradc->ts_input, BTN_TOUCH, 0);
-	input_sync(lradc->ts_input);
-
-	/* Restart the touchscreen interrupts. */
-	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
-	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
-}
-
 static int mxs_lradc_ts_open(struct input_dev *dev)
 {
 	struct mxs_lradc *lradc = input_get_drvdata(dev);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
                   ` (5 preceding siblings ...)
  2013-09-19 12:22 ` [PATCH 6/7] Staging/iio/adc/touchscreen/MXS: Remove old touchscreen detection implementation Juergen Beisert
@ 2013-09-19 12:22 ` Juergen Beisert
  2013-09-21 12:42   ` Jonathan Cameron
  2013-09-22 23:55 ` [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Marek Vasut
  7 siblings, 1 reply; 22+ messages in thread
From: Juergen Beisert @ 2013-09-19 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

This is an RFC for the new touchscreen properties.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
CC: linux-arm-kernel at lists.infradead.org
CC: devel at driverdev.osuosl.org
CC: Marek Vasut <marex@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Jonathan Cameron <jic23@cam.ac.uk>
CC: devicetree-discuss at lists.ozlabs.org
---
 .../bindings/staging/iio/adc/mxs-lradc.txt         | 36 ++++++++++++--
 drivers/staging/iio/adc/mxs-lradc.c                | 57 ++++++++++++++--------
 2 files changed, 67 insertions(+), 26 deletions(-)

diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
index 4688205..ee05dc3 100644
--- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
@@ -1,7 +1,8 @@
 * Freescale i.MX28 LRADC device driver
 
 Required properties:
-- compatible: Should be "fsl,imx28-lradc"
+- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
+              for i.MX28 SoC
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the LRADC interrupts
 
@@ -9,13 +10,38 @@ Optional properties:
 - fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
                                to LRADC. Valid value is either 4 or 5. If this
                                property is not present, then the touchscreen is
-                               disabled.
+                               disabled. 5 wires is valid for i.MX28 SoC only.
+- fsl,ave-ctrl: number of samples per direction to calculate an average value.
+                Allowed value is 1 ... 31, default is 4
+- fsl,ave-delay: delay between consecutive samples. Allowed value is
+                 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
+                 2 kHz and its default is 2 (= 1 ms)
+- fsl,settling: delay between plate switch to next sample. Allowed value is
+                1 ... 2047. It counts at 2 kHz and its default is
+                10 (= 5 ms)
 
-Examples:
+Example for i.MX23 SoC:
+
+	lradc at 80050000 {
+		compatible = "fsl,imx23-lradc";
+		reg = <0x80050000 0x2000>;
+		interrupts = <36 37 38 39 40 41 42 43 44>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <4>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
+	};
+
+Example for i.MX28 SoC:
 
 	lradc at 80050000 {
 		compatible = "fsl,imx28-lradc";
 		reg = <0x80050000 0x2000>;
-		interrupts = <10 14 15 16 17 18 19
-				20 21 22 23 24 25>;
+		interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <5>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
 	};
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 122475f..ffcb0dd 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -1225,10 +1225,45 @@ MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
 static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
 						struct device_node *lradc_node)
 {
-	/* TODO retrieve from device tree */
+	int ret;
+	u32 ts_wires = 0, adapt;
+
+	ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires",
+				&ts_wires);
+	if (ret)
+		return -ENODEV; /* touchscreen feature disabled */
+
+	switch (ts_wires) {
+	case 4:
+		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
+		break;
+	case 5:
+		if (lradc->soc == IMX28_LRADC) {
+			lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
+			break;
+		}
+		/* fall through an error message for i.MX23 */
+	default:
+		dev_err(lradc->dev,
+			"Unsupported number of touchscreen wires (%d)\n",
+			ts_wires);
+		return -EINVAL;
+	}
+
 	lradc->over_sample_cnt = 4;
+	ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt);
+	if (ret == 0)
+		lradc->over_sample_cnt = adapt;
+
 	lradc->over_sample_delay = 2;
+	ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt);
+	if (ret == 0)
+		lradc->over_sample_delay = adapt;
+
 	lradc->settling_delay = 10;
+	ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt);
+	if (ret == 0)
+		lradc->settling_delay = adapt;
 
 	return 0;
 }
@@ -1244,7 +1279,6 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	struct mxs_lradc *lradc;
 	struct iio_dev *iio;
 	struct resource *iores;
-	uint32_t ts_wires = 0;
 	int ret = 0, touch_ret;
 	int i;
 
@@ -1267,25 +1301,6 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 
 	touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
-	/* Check if touchscreen is enabled in DT. */
-	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
-				&ts_wires);
-	if (ret)
-		dev_info(dev, "Touchscreen not enabled.\n");
-	else if (ts_wires == 4)
-		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
-	else if (ts_wires == 5)
-		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
-	else
-		dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n",
-				ts_wires);
-
-	if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) {
-		dev_warn(dev, "No support for 5 wire touches on i.MX23\n");
-		dev_warn(dev, "Falling back to 4 wire\n");
-		ts_wires = 4;
-	}
-
 	/* Grab all IRQ sources */
 	for (i = 0; i < of_cfg->irq_count; i++) {
 		lradc->irq[i] = platform_get_irq(pdev, i);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection
  2013-09-19 12:22 ` [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection Juergen Beisert
@ 2013-09-21 12:36   ` Jonathan Cameron
  0 siblings, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2013-09-21 12:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/19/13 13:22, Juergen Beisert wrote:
> For battery driven systems it is a very bad idea to collect the touchscreen
> data within a kernel busy loop.
> 
> This change uses the features of the hardware to delay and accumulate samples in
> hardware to avoid a high interrupt and CPU load.
> 
> Note: this is only tested on an i.MX23 SoC yet.
> 
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> CC: linux-arm-kernel at lists.infradead.org
> CC: devel at driverdev.osuosl.org
> CC: Marek Vasut <marex@denx.de>
> CC: Fabio Estevam <fabio.estevam@freescale.com>
> CC: Jonathan Cameron <jic23@cam.ac.uk>

Please repost with Dmitry Torokhov and the linux input list cc'd.

Whilst this looks fine to me, it is definitely an input patch even if
the code resides in iio.

Also, I'm not going to take this series until we have confirmation from Marek
or someone else that we aren't introducing regressions into the i.MX23 support.

> ---
>  drivers/staging/iio/adc/mxs-lradc.c | 532 ++++++++++++++++++++++++++++++++----
>  1 file changed, 476 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
> index c70c31f..9f3f367 100644
> --- a/drivers/staging/iio/adc/mxs-lradc.c
> +++ b/drivers/staging/iio/adc/mxs-lradc.c
> @@ -129,6 +129,17 @@ enum mxs_lradc_ts {
>  	MXS_LRADC_TOUCHSCREEN_5WIRE,
>  };
>  
> +/*
> + * Touchscreen handling
> + */
> +enum lradc_ts_plate {
> +	LRADC_TOUCH = 0,
> +	LRADC_SAMPLE_X,
> +	LRADC_SAMPLE_Y,
> +	LRADC_SAMPLE_PRESSURE,
> +	LRADC_SAMPLE_VALID,
> +};
> +
>  struct mxs_lradc {
>  	struct device		*dev;
>  	void __iomem		*base;
> @@ -169,13 +180,25 @@ struct mxs_lradc {
>  #define CHAN_MASK_TOUCHSCREEN_4WIRE	(0xf << 2)
>  #define CHAN_MASK_TOUCHSCREEN_5WIRE	(0x1f << 2)
>  	enum mxs_lradc_ts	use_touchscreen;
> -	bool			stop_touchscreen;
>  	bool			use_touchbutton;
>  
>  	struct input_dev	*ts_input;
>  	struct work_struct	ts_work;
>  
>  	enum mxs_lradc_id	soc;
> +	enum lradc_ts_plate	cur_plate; /* statemachine */
> +	bool			ts_valid;
> +	unsigned		ts_x_pos;
> +	unsigned		ts_y_pos;
> +	unsigned		ts_pressure;
> +
> +	/* handle touchscreen's physical behaviour */
> +	/* samples per coordinate */
> +	unsigned		over_sample_cnt;
> +	/* time clocks between samples */
> +	unsigned		over_sample_delay;
> +	/* time in clocks to wait after the plates where switched */
> +	unsigned		settling_delay;
>  };
>  
>  #define	LRADC_CTRL0				0x00
> @@ -227,19 +250,33 @@ struct mxs_lradc {
>  #define	LRADC_CH_ACCUMULATE			(1 << 29)
>  #define	LRADC_CH_NUM_SAMPLES_MASK		(0x1f << 24)
>  #define	LRADC_CH_NUM_SAMPLES_OFFSET		24
> +#define	LRADC_CH_NUM_SAMPLES(x) \
> +				((x) << LRADC_CH_NUM_SAMPLES_OFFSET)
>  #define	LRADC_CH_VALUE_MASK			0x3ffff
>  #define	LRADC_CH_VALUE_OFFSET			0
>  
>  #define	LRADC_DELAY(n)				(0xd0 + (0x10 * (n)))
>  #define	LRADC_DELAY_TRIGGER_LRADCS_MASK		(0xff << 24)
>  #define	LRADC_DELAY_TRIGGER_LRADCS_OFFSET	24
> +#define	LRADC_DELAY_TRIGGER(x) \
> +				(((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \
> +				LRADC_DELAY_TRIGGER_LRADCS_MASK)
>  #define	LRADC_DELAY_KICK			(1 << 20)
>  #define	LRADC_DELAY_TRIGGER_DELAYS_MASK		(0xf << 16)
>  #define	LRADC_DELAY_TRIGGER_DELAYS_OFFSET	16
> +#define	LRADC_DELAY_TRIGGER_DELAYS(x) \
> +				(((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \
> +				LRADC_DELAY_TRIGGER_DELAYS_MASK)
>  #define	LRADC_DELAY_LOOP_COUNT_MASK		(0x1f << 11)
>  #define	LRADC_DELAY_LOOP_COUNT_OFFSET		11
> +#define	LRADC_DELAY_LOOP(x) \
> +				(((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \
> +				LRADC_DELAY_LOOP_COUNT_MASK)
>  #define	LRADC_DELAY_DELAY_MASK			0x7ff
>  #define	LRADC_DELAY_DELAY_OFFSET		0
> +#define	LRADC_DELAY_DELAY(x) \
> +				(((x) << LRADC_DELAY_DELAY_OFFSET) & \
> +				LRADC_DELAY_DELAY_MASK)
>  
>  #define	LRADC_CTRL4				0x140
>  #define	LRADC_CTRL4_LRADCSELECT_MASK(n)		(0xf << ((n) * 4))
> @@ -319,6 +356,404 @@ static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
>  		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
>  }
>  
> +static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
> +{
> +	return !!(readl(lradc->base + LRADC_STATUS) &
> +					LRADC_STATUS_TOUCH_DETECT_RAW);
> +}
> +
> +static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
> +{
> +	/*
> +	 * prepare for oversampling conversion
> +	 *
> +	 * from the datasheet:
> +	 * "The ACCUMULATE bit in the appropriate channel register
> +	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
> +	 * otherwise, the IRQs will not fire."
> +	 */
> +	mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE |
> +			LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1),
> +			LRADC_CH(ch));
> +
> +	/* from the datasheet:
> +	 * "Software must clear this register in preparation for a
> +	 * multi-cycle accumulation.
> +	 */
> +	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch));
> +
> +	/* prepare the delay/loop unit according to the oversampling count */
> +	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) |
> +		LRADC_DELAY_TRIGGER_DELAYS(0) |
> +		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
> +		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
> +			LRADC_DELAY(3));
> +
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
> +			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
> +			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
> +
> +	/* wake us again, when the complete conversion is done */
> +	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
> +	/*
> +	 * after changing the touchscreen plates setting
> +	 * the signals need some initial time to settle. Start the
> +	 * SoC's delay unit and start the conversion later
> +	 * and automatically.
> +	 */
> +	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
> +		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
> +		LRADC_DELAY_KICK |
> +		LRADC_DELAY_DELAY(lradc->settling_delay),
> +			LRADC_DELAY(2));
> +}
> +
> +/*
> + * Pressure detection is special:
> + * We want to do both required measurements for the pressure detection in
> + * one turn. Use the hardware features to chain both conversions and let the
> + * hardware report one interrupt if both conversions are done
> + */
> +static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
> +							unsigned ch2)
> +{
> +	u32 reg;
> +
> +	/*
> +	 * prepare for oversampling conversion
> +	 *
> +	 * from the datasheet:
> +	 * "The ACCUMULATE bit in the appropriate channel register
> +	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
> +	 * otherwise, the IRQs will not fire."
> +	 */
> +	reg = LRADC_CH_ACCUMULATE |
> +		LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1);
> +	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1));
> +	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2));
> +
> +	/* from the datasheet:
> +	 * "Software must clear this register in preparation for a
> +	 * multi-cycle accumulation.
> +	 */
> +	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1));
> +	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2));
> +
> +	/* prepare the delay/loop unit according to the oversampling count */
> +	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) |
> +		LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */
> +		LRADC_DELAY_TRIGGER_DELAYS(0) |
> +		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
> +		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
> +					LRADC_DELAY(3));
> +
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
> +			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
> +			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
> +
> +	/* wake us again, when the conversions are done */
> +	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
> +	/*
> +	 * after changing the touchscreen plates setting
> +	 * the signals need some initial time to settle. Start the
> +	 * SoC's delay unit and start the conversion later
> +	 * and automatically.
> +	 */
> +	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
> +		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
> +		LRADC_DELAY_KICK |
> +		LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2));
> +}
> +
> +static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc,
> +							unsigned channel)
> +{
> +	u32 reg;
> +	unsigned num_samples, val;
> +
> +	reg = readl(lradc->base + LRADC_CH(channel));
> +	if (reg & LRADC_CH_ACCUMULATE)
> +		num_samples = lradc->over_sample_cnt;
> +	else
> +		num_samples = 1;
> +
> +	val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET;
> +	return val / num_samples;
> +}
> +
> +static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
> +						unsigned ch1, unsigned ch2)
> +{
> +	u32 reg, mask;
> +	unsigned pressure, m1, m2;
> +
> +	mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2);
> +	reg = readl(lradc->base + LRADC_CTRL1) & mask;
> +
> +	while (reg != mask) {
> +		reg = readl(lradc->base + LRADC_CTRL1) & mask;
> +		dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg);
> +	}
> +
> +	m1 = mxs_lradc_read_raw_channel(lradc, ch1);
> +	m2 = mxs_lradc_read_raw_channel(lradc, ch2);
> +
> +	if (m2 == 0) {
> +		dev_warn(lradc->dev, "Cannot calculate pressure\n");
> +		return 1 << (LRADC_RESOLUTION - 1);
> +	}
> +
> +	/* simply scale the value from 0 ... max ADC resolution */
> +	pressure = m1;
> +	pressure *= (1 << LRADC_RESOLUTION);
> +	pressure /= m2;
> +
> +	dev_dbg(lradc->dev, "Pressure = %u\n", pressure);
> +	return pressure;
> +}
> +
> +#define TS_CH_XP 2
> +#define TS_CH_YP 3
> +#define TS_CH_XM 4
> +#define TS_CH_YM 5
> +
> +static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
> +{
> +	u32 reg;
> +	int val;
> +
> +	reg = readl(lradc->base + LRADC_CTRL1);
> +
> +	/* only channels 3 to 5 are of interest here */
> +	if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
> +		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
> +			LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
> +		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
> +	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
> +		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
> +			LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
> +		val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
> +	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
> +		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
> +			LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
> +		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
> +	} else {
> +		return -EIO;
> +	}
> +
> +	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
> +	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
> +
> +	return val;
> +}
> +
> +/*
> + * YP(open)--+-------------+
> + *           |             |--+
> + *           |             |  |
> + *    YM(-)--+-------------+  |
> + *             +--------------+
> + *             |              |
> + *         XP(weak+)        XM(open)
> + *
> + * "weak+" means 200k Ohm VDDIO
> + * (-) means GND
> + */
> +static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc)
> +{
> +	/*
> +	 * In order to detect a touch event the 'touch detect enable' bit
> +	 * enables:
> +	 *  - a weak pullup to the X+ connector
> +	 *  - a strong ground at the Y- connector
> +	 */
> +	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
> +	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
> +				LRADC_CTRL0);
> +}
> +
> +/*
> + * YP(meas)--+-------------+
> + *           |             |--+
> + *           |             |  |
> + * YM(open)--+-------------+  |
> + *             +--------------+
> + *             |              |
> + *           XP(+)          XM(-)
> + *
> + * (+) means here 1.85 V
> + * (-) means here GND
> + */
> +static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
> +{
> +	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
> +	mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
> +
> +	lradc->cur_plate = LRADC_SAMPLE_X;
> +	mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
> +}
> +
> +/*
> + *   YP(+)--+-------------+
> + *          |             |--+
> + *          |             |  |
> + *   YM(-)--+-------------+  |
> + *            +--------------+
> + *            |              |
> + *         XP(open)        XM(meas)
> + *
> + * (+) means here 1.85 V
> + * (-) means here GND
> + */
> +static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
> +{
> +	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
> +	mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
> +
> +	lradc->cur_plate = LRADC_SAMPLE_Y;
> +	mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
> +}
> +
> +/*
> + *    YP(+)--+-------------+
> + *           |             |--+
> + *           |             |  |
> + * YM(meas)--+-------------+  |
> + *             +--------------+
> + *             |              |
> + *          XP(meas)        XM(-)
> + *
> + * (+) means here 1.85 V
> + * (-) means here GND
> + */
> +static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
> +{
> +	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
> +	mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
> +
> +	lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
> +	mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
> +}
> +
> +static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
> +{
> +	mxs_lradc_setup_touch_detection(lradc);
> +
> +	lradc->cur_plate = LRADC_TOUCH;
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
> +				LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
> +	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
> +}
> +
> +static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
> +{
> +	input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
> +	input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos);
> +	input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure);
> +	input_report_key(lradc->ts_input, BTN_TOUCH, 1);
> +	input_sync(lradc->ts_input);
> +}
> +
> +static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
> +{
> +	mxs_lradc_setup_touch_detection(lradc);
> +	lradc->cur_plate = LRADC_SAMPLE_VALID;
> +	/*
> +	 * start a dummy conversion to burn time to settle the signals
> +	 * note: we are not interested in the conversion's value
> +	 */
> +	mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
> +	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
> +	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
> +		LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
> +			LRADC_DELAY(2));
> +}
> +
> +/*
> + * in order to avoid false measurements, report only samples where
> + * the surface is still touched after the position measurement
> + */
> +static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
> +{
> +	/* if it is still touched, report the sample */
> +	if (valid && mxs_lradc_check_touch_event(lradc)) {
> +		lradc->ts_valid = true;
> +		mxs_lradc_report_ts_event(lradc);
> +	}
> +
> +	/* if it is even still touched, continue with the next measurement */
> +	if (mxs_lradc_check_touch_event(lradc)) {
> +		mxs_lradc_prepare_y_pos(lradc);
> +		return;
> +	}
> +
> +	if (lradc->ts_valid) {
> +		/* signal the release */
> +		lradc->ts_valid = false;
> +		input_report_key(lradc->ts_input, BTN_TOUCH, 0);
> +		input_sync(lradc->ts_input);
> +	}
> +
> +	/* if it is released, wait for the next touch via IRQ */
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
> +	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
> +}
> +
> +/* touchscreen's state machine */
> +static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
> +{
> +	int val;
> +
> +	switch (lradc->cur_plate) {
> +	case LRADC_TOUCH:
> +		/*
> +		 * start with the Y-pos, because it uses nearly the same plate
> +		 * settings like the touch detection
> +		 */
> +		if (mxs_lradc_check_touch_event(lradc)) {
> +			mxs_lradc_reg_clear(lradc,
> +					LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
> +					LRADC_CTRL1);
> +			mxs_lradc_prepare_y_pos(lradc);
> +		}
> +		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
> +					LRADC_CTRL1);
> +		return;
> +
> +	case LRADC_SAMPLE_Y:
> +		val = mxs_lradc_read_ts_channel(lradc);
> +		if (val < 0) {
> +			mxs_lradc_enable_touch_detection(lradc); /* re-start */
> +			return;
> +		}
> +		lradc->ts_y_pos = val;
> +		mxs_lradc_prepare_x_pos(lradc);
> +		return;
> +
> +	case LRADC_SAMPLE_X:
> +		val = mxs_lradc_read_ts_channel(lradc);
> +		if (val < 0) {
> +			mxs_lradc_enable_touch_detection(lradc); /* re-start */
> +			return;
> +		}
> +		lradc->ts_x_pos = val;
> +		mxs_lradc_prepare_pressure(lradc);
> +		return;
> +
> +	case LRADC_SAMPLE_PRESSURE:
> +		lradc->ts_pressure =
> +			mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
> +		mxs_lradc_complete_touch_event(lradc);
> +		return;
> +
> +	case LRADC_SAMPLE_VALID:
> +		val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
> +		mxs_lradc_finish_touch_event(lradc, 1);
> +		break;
> +	}
> +}
> +
>  /*
>   * Raw I/O operations
>   */
> @@ -392,15 +827,6 @@ static const struct iio_info mxs_lradc_iio_info = {
>  	.read_raw		= mxs_lradc_read_raw,
>  };
>  
> -/*
> - * Touchscreen handling
> - */
> -enum lradc_ts_plate {
> -	LRADC_SAMPLE_X,
> -	LRADC_SAMPLE_Y,
> -	LRADC_SAMPLE_PRESSURE,
> -};
> -
>  static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
>  {
>  	uint32_t reg;
> @@ -558,10 +984,6 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work)
>  	input_report_key(lradc->ts_input, BTN_TOUCH, 0);
>  	input_sync(lradc->ts_input);
>  
> -	/* Do not restart the TS IRQ if the driver is shutting down. */
> -	if (lradc->stop_touchscreen)
> -		return;
> -
>  	/* Restart the touchscreen interrupts. */
>  	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
>  	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
> @@ -571,36 +993,29 @@ static int mxs_lradc_ts_open(struct input_dev *dev)
>  {
>  	struct mxs_lradc *lradc = input_get_drvdata(dev);
>  
> -	/* The touchscreen is starting. */
> -	lradc->stop_touchscreen = false;
> -
>  	/* Enable the touch-detect circuitry. */
> -	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
> -						LRADC_CTRL0);
> -
> -	/* Enable the touch-detect IRQ. */
> -	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
> +	mxs_lradc_enable_touch_detection(lradc);
>  
>  	return 0;
>  }
>  
> -static void mxs_lradc_ts_close(struct input_dev *dev)
> +static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
>  {
> -	struct mxs_lradc *lradc = input_get_drvdata(dev);
> -
> -	/* Indicate the touchscreen is stopping. */
> -	lradc->stop_touchscreen = true;
> -	mb();
> +	/* stop all interrupts from firing */
> +	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
> +		LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
> +		LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
> +		LRADC_CTRL1);
>  
> -	/* Wait until touchscreen thread finishes any possible remnants. */
> -	cancel_work_sync(&lradc->ts_work);
> +	/* Power-down touchscreen touch-detect circuitry. */
> +	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
> +}
>  
> -	/* Disable touchscreen touch-detect IRQ. */
> -	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
> -						LRADC_CTRL1);
> +static void mxs_lradc_ts_close(struct input_dev *dev)
> +{
> +	struct mxs_lradc *lradc = input_get_drvdata(dev);
>  
> -	/* Power-down touchscreen touch-detect circuitry. */
> -	mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), LRADC_CTRL0);
> +	mxs_lradc_disable_ts(lradc);
>  }
>  
>  static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
> @@ -646,8 +1061,7 @@ static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
>  	if (!lradc->use_touchscreen)
>  		return;
>  
> -	cancel_work_sync(&lradc->ts_work);
> -
> +	mxs_lradc_disable_ts(lradc);
>  	input_unregister_device(lradc->ts_input);
>  }
>  
> @@ -660,30 +1074,23 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
>  	struct mxs_lradc *lradc = iio_priv(iio);
>  	unsigned long reg = readl(lradc->base + LRADC_CTRL1);
>  	const uint32_t ts_irq_mask =
> -		LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
> -		LRADC_CTRL1_TOUCH_DETECT_IRQ;
> +		LRADC_CTRL1_TOUCH_DETECT_IRQ |
> +		LRADC_CTRL1_LRADC_IRQ(2) |
> +		LRADC_CTRL1_LRADC_IRQ(3) |
> +		LRADC_CTRL1_LRADC_IRQ(4) |
> +		LRADC_CTRL1_LRADC_IRQ(5);
>  
>  	if (!(reg & mxs_lradc_irq_mask(lradc)))
>  		return IRQ_NONE;
>  
> -	/*
> -	 * Touchscreen IRQ handling code has priority and therefore
> -	 * is placed here. In case touchscreen IRQ arrives, disable
> -	 * it ASAP
> -	 */
> -	if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) {
> -		mxs_lradc_reg_clear(lradc, ts_irq_mask, LRADC_CTRL1);
> -		if (!lradc->stop_touchscreen)
> -			schedule_work(&lradc->ts_work);
> -	}
> +	if (lradc->use_touchscreen && (reg & ts_irq_mask))
> +		mxs_lradc_handle_touch(lradc);
>  
>  	if (iio_buffer_enabled(iio))
>  		iio_trigger_poll(iio->trig, iio_get_time_ns());
>  	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
>  		complete(&lradc->completion);
>  
> -	mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
> -
>  	return IRQ_HANDLED;
>  }
>  
> @@ -978,6 +1385,17 @@ static const struct of_device_id mxs_lradc_dt_ids[] = {
>  };
>  MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
>  
> +static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
> +						struct device_node *lradc_node)
> +{
> +	/* TODO retrieve from device tree */
> +	lradc->over_sample_cnt = 4;
> +	lradc->over_sample_delay = 2;
> +	lradc->settling_delay = 10;
> +
> +	return 0;
> +}
> +
>  static int mxs_lradc_probe(struct platform_device *pdev)
>  {
>  	const struct of_device_id *of_id =
> @@ -990,7 +1408,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>  	struct iio_dev *iio;
>  	struct resource *iores;
>  	uint32_t ts_wires = 0;
> -	int ret = 0;
> +	int ret = 0, touch_ret;
>  	int i;
>  
>  	/* Allocate the IIO device. */
> @@ -1010,7 +1428,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>  	if (IS_ERR(lradc->base))
>  		return PTR_ERR(lradc->base);
>  
> -	INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work);
> +	touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
>  
>  	/* Check if touchscreen is enabled in DT. */
>  	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
> @@ -1073,9 +1491,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>  		goto err_dev;
>  
>  	/* Register the touchscreen input device. */
> -	ret = mxs_lradc_ts_register(lradc);
> -	if (ret)
> -		goto err_dev;
> +	if (touch_ret == 0) {
> +		ret = mxs_lradc_ts_register(lradc);
> +		if (ret)
> +			goto err_dev;
> +	}
>  
>  	/* Register IIO device. */
>  	ret = iio_device_register(iio);
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption
  2013-09-19 12:22 ` [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption Juergen Beisert
@ 2013-09-21 12:42   ` Jonathan Cameron
  2013-09-23  7:42     ` Jürgen Beisert
  0 siblings, 1 reply; 22+ messages in thread
From: Jonathan Cameron @ 2013-09-21 12:42 UTC (permalink / raw)
  To: linux-arm-kernel

The device tree list has moved, so I've changed the cc.

Few comments inline.  Basically I'd go for longer more
descriptive names when the abreviation isn't a really
well known common one.


Note I'm not all that familiar with device tree conventions
so may be barking up the wrong tree ;)
On 09/19/13 13:22, Juergen Beisert wrote:
> This is an RFC for the new touchscreen properties.
> 
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> CC: linux-arm-kernel at lists.infradead.org
> CC: devel at driverdev.osuosl.org
> CC: Marek Vasut <marex@denx.de>
> CC: Fabio Estevam <fabio.estevam@freescale.com>
> CC: Jonathan Cameron <jic23@cam.ac.uk>
> CC: devicetree-discuss at lists.ozlabs.org
> ---
>  .../bindings/staging/iio/adc/mxs-lradc.txt         | 36 ++++++++++++--
>  drivers/staging/iio/adc/mxs-lradc.c                | 57 ++++++++++++++--------
>  2 files changed, 67 insertions(+), 26 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> index 4688205..ee05dc3 100644
> --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> @@ -1,7 +1,8 @@
>  * Freescale i.MX28 LRADC device driver
>  
>  Required properties:
> -- compatible: Should be "fsl,imx28-lradc"
> +- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
> +              for i.MX28 SoC
>  - reg: Address and length of the register set for the device
>  - interrupts: Should contain the LRADC interrupts
>  
> @@ -9,13 +10,38 @@ Optional properties:
>  - fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
>                                 to LRADC. Valid value is either 4 or 5. If this
>                                 property is not present, then the touchscreen is
> -                               disabled.
Do we want that lradc prefix on these other properties?
> +                               disabled. 5 wires is valid for i.MX28 SoC only.
> +- fsl,ave-ctrl: number of samples per direction to calculate an average value.
> +                Allowed value is 1 ... 31, default is 4
This naming seems less than informative, what about fsl,average_num_samples of average_count
(ave isn't all that obvious an abrevaition of average).

> +- fsl,ave-delay: delay between consecutive samples. Allowed value is
> +                 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
> +                 2 kHz and its default is 2 (= 1 ms)
fsl,average_intersample_delay (I assume any limit of device tree property names is longer than that?)

> +- fsl,settling: delay between plate switch to next sample. Allowed value is
> +                1 ... 2047. It counts at 2 kHz and its default is
> +                10 (= 5 ms)
>  
> -Examples:
> +Example for i.MX23 SoC:
> +
> +	lradc at 80050000 {
> +		compatible = "fsl,imx23-lradc";
> +		reg = <0x80050000 0x2000>;
> +		interrupts = <36 37 38 39 40 41 42 43 44>;
> +		status = "okay";
> +		fsl,lradc-touchscreen-wires = <4>;
> +		fsl,ave-ctrl = <4>;
> +		fsl,ave-delay = <2>;
> +		fsl,settling = <10>;
> +	};
> +
> +Example for i.MX28 SoC:
>  
>  	lradc at 80050000 {
>  		compatible = "fsl,imx28-lradc";
>  		reg = <0x80050000 0x2000>;
> -		interrupts = <10 14 15 16 17 18 19
> -				20 21 22 23 24 25>;
> +		interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
> +		status = "okay";
> +		fsl,lradc-touchscreen-wires = <5>;
> +		fsl,ave-ctrl = <4>;
> +		fsl,ave-delay = <2>;
> +		fsl,settling = <10>;
>  	};
> diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
> index 122475f..ffcb0dd 100644
> --- a/drivers/staging/iio/adc/mxs-lradc.c
> +++ b/drivers/staging/iio/adc/mxs-lradc.c
> @@ -1225,10 +1225,45 @@ MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
>  static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
>  						struct device_node *lradc_node)
>  {
> -	/* TODO retrieve from device tree */
> +	int ret;
> +	u32 ts_wires = 0, adapt;
> +
> +	ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires",
> +				&ts_wires);
> +	if (ret)
> +		return -ENODEV; /* touchscreen feature disabled */
> +
> +	switch (ts_wires) {
> +	case 4:
> +		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
> +		break;
> +	case 5:
> +		if (lradc->soc == IMX28_LRADC) {
> +			lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
> +			break;
> +		}
> +		/* fall through an error message for i.MX23 */
> +	default:
> +		dev_err(lradc->dev,
> +			"Unsupported number of touchscreen wires (%d)\n",
> +			ts_wires);
> +		return -EINVAL;
> +	}
> +
>  	lradc->over_sample_cnt = 4;
> +	ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt);
> +	if (ret == 0)
> +		lradc->over_sample_cnt = adapt;
> +
>  	lradc->over_sample_delay = 2;
> +	ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt);
> +	if (ret == 0)
> +		lradc->over_sample_delay = adapt;
> +
>  	lradc->settling_delay = 10;
> +	ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt);
> +	if (ret == 0)
> +		lradc->settling_delay = adapt;
>  
>  	return 0;
>  }
> @@ -1244,7 +1279,6 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>  	struct mxs_lradc *lradc;
>  	struct iio_dev *iio;
>  	struct resource *iores;
> -	uint32_t ts_wires = 0;
>  	int ret = 0, touch_ret;
>  	int i;
>  
> @@ -1267,25 +1301,6 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>  
>  	touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
>  
> -	/* Check if touchscreen is enabled in DT. */
> -	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
> -				&ts_wires);
> -	if (ret)
> -		dev_info(dev, "Touchscreen not enabled.\n");
> -	else if (ts_wires == 4)
> -		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
> -	else if (ts_wires == 5)
> -		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
> -	else
> -		dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n",
> -				ts_wires);
> -
> -	if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) {
> -		dev_warn(dev, "No support for 5 wire touches on i.MX23\n");
> -		dev_warn(dev, "Falling back to 4 wire\n");
> -		ts_wires = 4;
> -	}
> -
>  	/* Grab all IRQ sources */
>  	for (i = 0; i < of_cfg->irq_count; i++) {
>  		lradc->irq[i] = platform_get_irq(pdev, i);
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
                   ` (6 preceding siblings ...)
  2013-09-19 12:22 ` [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption Juergen Beisert
@ 2013-09-22 23:55 ` Marek Vasut
  2013-09-23  7:55   ` Jürgen Beisert
  7 siblings, 1 reply; 22+ messages in thread
From: Marek Vasut @ 2013-09-22 23:55 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Juergen Beisert,

> The following series replaces the current busy loop touchscreen
> implementation for i.MX28/i.MX23 SoCs by a fully interrupt driven
> implementation.
> 
> Since i.MX23 and i.MX28 silicon differs, the existing implementation can
> be used for the i.MX28 SoC only.
> 
> So, the first two patches of this series move the i.MX28 specific
> definitions out of the way. The third patch simplifies the register access
> to make it easier to add the i.MX23 support. Then the i.MX23 specific
> definitions are added, also the code to distinguish both SoCs at run-time.
> Up to here the existing touchscreen driver will now run on an i.MX23 Soc as
> well.
> 
> When the i.MX23 SoC is running from battery it seems not to be a good idea
> to run a busy loop to detect touches and their location. The fourth patch
> adds a fully interrupt driven implementation which makes use of the
> built-in delay and multiple sample features of the touchscreen controller.
> This will reduce the interrupt load to a minimum.
> 
> The next to last patch in this series just removes the existing busy loop
> implementation.
> 
> The last patch adds a devicetree bindings proposal (to be discussed).
> 
> Some restrictions/questions:
> 
> - the touchscreen part is yet tested on i.MX23 SoC only
> - has someone a good idea how to implement a reliable pressure measurement
> if the resistances of the touchscreen's plates are unknown?
> 
> Changes since v4:
> 
> - honor Jonathan's comments about function names
> - honor Dmitry's comments about workqueue canceling and interrupts
> - adding devicetree bindings proposal
> 
> Changes since v3:
> 
> - split adding register access functions and i.MX23 support into two
> patches
> 
> Changes since v2:
> 
> - useless debug output removed
> 
> Changes since v1:
> 
> - adding register access functions to make the existing code more readable
> - adding some functions to distinguish the SoCs at run-time to avoid
> if-else contructs whenever differences in the register layout between
> i.MX23 and i.MX28 must be handled

Just tested this on M28EVK, the touchscreen is dead. I do not get any touch 
events when I use ts_calibrate and when I hd /dev/input/eventX , I get nothing 
either.

Right now, I'm somehow on a tight schedule, but I'd like to see this resolved 
ASAP. Do you have any hint for me ?

btw. the touchscreen connection on M28EVK is pretty much the same as on MX28EVK.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption
  2013-09-21 12:42   ` Jonathan Cameron
@ 2013-09-23  7:42     ` Jürgen Beisert
  0 siblings, 0 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jonathan,

On Saturday 21 September 2013 14:42:37 Jonathan Cameron wrote:
> The device tree list has moved, so I've changed the cc.
>
> Few comments inline.  Basically I'd go for longer more
> descriptive names when the abreviation isn't a really
> well known common one.
>
> Note I'm not all that familiar with device tree conventions
> so may be barking up the wrong tree ;)
>
> > [...]
> > @@ -9,13 +10,38 @@ Optional properties:
> >  - fsl,lradc-touchscreen-wires: Number of wires used to connect the
> > touchscreen to LRADC. Valid value is either 4 or 5. If this property is
> > not present, then the touchscreen is -                              
> > disabled.
>
> Do we want that lradc prefix on these other properties?

The question is, if we want to keep it. This is the currently used binding.

> > +                               disabled. 5 wires is valid for i.MX28 SoC only.
> > +- fsl,ave-ctrl: number of samples per direction to calculate an average value.
> > +                Allowed value is 1 ... 31, default is 4 
>
> This naming seems less than informative, what about fsl,average_num_samples
> of average_count (ave isn't all that obvious an abrevaition of average).

I used already existing names from
"Documentation/devicetree/bindings/input/touchscreen/stmpe.txt".

> > +- fsl,ave-delay: delay between consecutive samples. Allowed value is
> > +                 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
> > +                 2 kHz and its default is 2 (= 1 ms)
>
> fsl,average_intersample_delay (I assume any limit of device tree property
> names is longer than that?)

If the parameter description in "Documentation/devicetree/bindings" is useful,
we don't need long parameter names. If there is no useful parameter
description, we will need long names ;)

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-22 23:55 ` [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Marek Vasut
@ 2013-09-23  7:55   ` Jürgen Beisert
  2013-09-23  9:25     ` Lothar Waßmann
  2013-09-23 10:35     ` Jürgen Beisert
  0 siblings, 2 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23  7:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marek,

On Monday 23 September 2013 01:55:04 Marek Vasut wrote:
> > The following series replaces the current busy loop touchscreen
> > implementation for i.MX28/i.MX23 SoCs by a fully interrupt driven
> > implementation.
> >
> > Since i.MX23 and i.MX28 silicon differs, the existing implementation can
> > be used for the i.MX28 SoC only.
> >
> > So, the first two patches of this series move the i.MX28 specific
> > definitions out of the way. The third patch simplifies the register
> > access to make it easier to add the i.MX23 support. Then the i.MX23
> > specific definitions are added, also the code to distinguish both SoCs at
> > run-time. Up to here the existing touchscreen driver will now run on an
> > i.MX23 Soc as well.
> >
> > When the i.MX23 SoC is running from battery it seems not to be a good
> > idea to run a busy loop to detect touches and their location. The fourth
> > patch adds a fully interrupt driven implementation which makes use of the
> > built-in delay and multiple sample features of the touchscreen
> > controller. This will reduce the interrupt load to a minimum.
> >
> > The next to last patch in this series just removes the existing busy loop
> > implementation.
> >
> > The last patch adds a devicetree bindings proposal (to be discussed).
> >
> > Some restrictions/questions:
> >
> > - the touchscreen part is yet tested on i.MX23 SoC only
> > - has someone a good idea how to implement a reliable pressure
> > measurement if the resistances of the touchscreen's plates are unknown?
> >
> > Changes since v4:
> >
> > - honor Jonathan's comments about function names
> > - honor Dmitry's comments about workqueue canceling and interrupts
> > - adding devicetree bindings proposal
> >
> > Changes since v3:
> >
> > - split adding register access functions and i.MX23 support into two
> > patches
> >
> > Changes since v2:
> >
> > - useless debug output removed
> >
> > Changes since v1:
> >
> > - adding register access functions to make the existing code more
> > readable - adding some functions to distinguish the SoCs at run-time to
> > avoid if-else contructs whenever differences in the register layout
> > between i.MX23 and i.MX28 must be handled
>
> Just tested this on M28EVK, the touchscreen is dead. I do not get any touch
> events when I use ts_calibrate and when I hd /dev/input/eventX , I get
> nothing either.
>
> Right now, I'm somehow on a tight schedule, but I'd like to see this
> resolved ASAP. Do you have any hint for me ?

Seems the very first touch detection does not work. A colleague just told me, 
we have an i.MX28 based hardware here and maybe a touchscreen from a different 
platform which maybe can be used with the i.MX28 platform. Stay tuned...

> btw. the touchscreen connection on M28EVK is pretty much the same as on
> MX28EVK.

I think the touchscreen connection on MX28EVK is exactly the same as on 
MX28EVK! ;) (/me needs more coffee as well)

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23  7:55   ` Jürgen Beisert
@ 2013-09-23  9:25     ` Lothar Waßmann
  2013-09-23 10:35     ` Jürgen Beisert
  1 sibling, 0 replies; 22+ messages in thread
From: Lothar Waßmann @ 2013-09-23  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

J?rgen Beisert writes:
> Hi Marek,
> 
> Seems the very first touch detection does not work. A colleague just told me, 
> we have an i.MX28 based hardware here and maybe a touchscreen from a different 
> platform which maybe can be used with the i.MX28 platform. Stay tuned...
> 
> > btw. the touchscreen connection on M28EVK is pretty much the same as on
> > MX28EVK.
> 
> I think the touchscreen connection on MX28EVK is exactly the same as on 
> MX28EVK! ;) (/me needs more coffee as well)
> 
Just tested the touchscreen driver on our TX28 module and I could not
find any problems.


Lothar Wa?mann
-- 
___________________________________________________________

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
___________________________________________________________

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23  7:55   ` Jürgen Beisert
  2013-09-23  9:25     ` Lothar Waßmann
@ 2013-09-23 10:35     ` Jürgen Beisert
  2013-09-23 10:36       ` Marek Vasut
  2013-09-23 12:12       ` Lothar Waßmann
  1 sibling, 2 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23 10:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marek,

On Monday 23 September 2013 09:55:58 J?rgen Beisert wrote:
> On Monday 23 September 2013 01:55:04 Marek Vasut wrote:
> > > The following series replaces the current busy loop touchscreen
> > > implementation for i.MX28/i.MX23 SoCs by a fully interrupt driven
> > > implementation.
> > >
> > > Since i.MX23 and i.MX28 silicon differs, the existing implementation
> > > can be used for the i.MX28 SoC only.
> > >
> > > So, the first two patches of this series move the i.MX28 specific
> > > definitions out of the way. The third patch simplifies the register
> > > access to make it easier to add the i.MX23 support. Then the i.MX23
> > > specific definitions are added, also the code to distinguish both SoCs
> > > at run-time. Up to here the existing touchscreen driver will now run on
> > > an i.MX23 Soc as well.
> > >
> > > When the i.MX23 SoC is running from battery it seems not to be a good
> > > idea to run a busy loop to detect touches and their location. The
> > > fourth patch adds a fully interrupt driven implementation which makes
> > > use of the built-in delay and multiple sample features of the
> > > touchscreen controller. This will reduce the interrupt load to a
> > > minimum.
> > >
> > > The next to last patch in this series just removes the existing busy
> > > loop implementation.
> > >
> > > The last patch adds a devicetree bindings proposal (to be discussed).
> > >
> > > Some restrictions/questions:
> > >
> > > - the touchscreen part is yet tested on i.MX23 SoC only
> > > - has someone a good idea how to implement a reliable pressure
> > > measurement if the resistances of the touchscreen's plates are unknown?
> > >
> > > Changes since v4:
> > >
> > > - honor Jonathan's comments about function names
> > > - honor Dmitry's comments about workqueue canceling and interrupts
> > > - adding devicetree bindings proposal
> > >
> > > Changes since v3:
> > >
> > > - split adding register access functions and i.MX23 support into two
> > > patches
> > >
> > > Changes since v2:
> > >
> > > - useless debug output removed
> > >
> > > Changes since v1:
> > >
> > > - adding register access functions to make the existing code more
> > > readable - adding some functions to distinguish the SoCs at run-time to
> > > avoid if-else contructs whenever differences in the register layout
> > > between i.MX23 and i.MX28 must be handled
> >
> > Just tested this on M28EVK, the touchscreen is dead. I do not get any
> > touch events when I use ts_calibrate and when I hd /dev/input/eventX , I
> > get nothing either.
> >
> > Right now, I'm somehow on a tight schedule, but I'd like to see this
> > resolved ASAP. Do you have any hint for me ?
>
> Seems the very first touch detection does not work. A colleague just told
> me, we have an i.MX28 based hardware here and maybe a touchscreen from a
> different platform which maybe can be used with the i.MX28 platform. Stay
> tuned...

I also found an MX28EVK with a touchscreen here and: yes it does not work with 
the modified driver. But now I'm confused, because of Lothar's statement about 
the TX28 platform.

@Lothar: What kernel revision did you use? I had to go back to 3.9 to get a 
working kernel on the MX28EVK. More recent vanilla kernels stop working (MMC 
and network fail here).

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 10:35     ` Jürgen Beisert
@ 2013-09-23 10:36       ` Marek Vasut
  2013-09-23 11:57         ` Jürgen Beisert
  2013-09-23 12:12       ` Lothar Waßmann
  1 sibling, 1 reply; 22+ messages in thread
From: Marek Vasut @ 2013-09-23 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

Dear J?rgen Beisert,

> Hi Marek,
> 
> On Monday 23 September 2013 09:55:58 J?rgen Beisert wrote:
> > On Monday 23 September 2013 01:55:04 Marek Vasut wrote:
> > > > The following series replaces the current busy loop touchscreen
> > > > implementation for i.MX28/i.MX23 SoCs by a fully interrupt driven
> > > > implementation.
> > > > 
> > > > Since i.MX23 and i.MX28 silicon differs, the existing implementation
> > > > can be used for the i.MX28 SoC only.
> > > > 
> > > > So, the first two patches of this series move the i.MX28 specific
> > > > definitions out of the way. The third patch simplifies the register
> > > > access to make it easier to add the i.MX23 support. Then the i.MX23
> > > > specific definitions are added, also the code to distinguish both
> > > > SoCs at run-time. Up to here the existing touchscreen driver will
> > > > now run on an i.MX23 Soc as well.
> > > > 
> > > > When the i.MX23 SoC is running from battery it seems not to be a good
> > > > idea to run a busy loop to detect touches and their location. The
> > > > fourth patch adds a fully interrupt driven implementation which makes
> > > > use of the built-in delay and multiple sample features of the
> > > > touchscreen controller. This will reduce the interrupt load to a
> > > > minimum.
> > > > 
> > > > The next to last patch in this series just removes the existing busy
> > > > loop implementation.
> > > > 
> > > > The last patch adds a devicetree bindings proposal (to be discussed).
> > > > 
> > > > Some restrictions/questions:
> > > > 
> > > > - the touchscreen part is yet tested on i.MX23 SoC only
> > > > - has someone a good idea how to implement a reliable pressure
> > > > measurement if the resistances of the touchscreen's plates are
> > > > unknown?
> > > > 
> > > > Changes since v4:
> > > > 
> > > > - honor Jonathan's comments about function names
> > > > - honor Dmitry's comments about workqueue canceling and interrupts
> > > > - adding devicetree bindings proposal
> > > > 
> > > > Changes since v3:
> > > > 
> > > > - split adding register access functions and i.MX23 support into two
> > > > patches
> > > > 
> > > > Changes since v2:
> > > > 
> > > > - useless debug output removed
> > > > 
> > > > Changes since v1:
> > > > 
> > > > - adding register access functions to make the existing code more
> > > > readable - adding some functions to distinguish the SoCs at run-time
> > > > to avoid if-else contructs whenever differences in the register
> > > > layout between i.MX23 and i.MX28 must be handled
> > > 
> > > Just tested this on M28EVK, the touchscreen is dead. I do not get any
> > > touch events when I use ts_calibrate and when I hd /dev/input/eventX ,
> > > I get nothing either.
> > > 
> > > Right now, I'm somehow on a tight schedule, but I'd like to see this
> > > resolved ASAP. Do you have any hint for me ?
> > 
> > Seems the very first touch detection does not work. A colleague just told
> > me, we have an i.MX28 based hardware here and maybe a touchscreen from a
> > different platform which maybe can be used with the i.MX28 platform. Stay
> > tuned...
> 
> I also found an MX28EVK with a touchscreen here and: yes it does not work
> with the modified driver. But now I'm confused, because of Lothar's
> statement about the TX28 platform.
> 
> @Lothar: What kernel revision did you use? I had to go back to 3.9 to get a
> working kernel on the MX28EVK. More recent vanilla kernels stop working
> (MMC and network fail here).

Can you fix the SD and Network or at least show the fail log ?

btw. I use 3.12-rc1 (next/master) to test the touchscreen on M28EVK. I don't 
have the LCD module attached to MX28EVK, so I can't test there.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 10:36       ` Marek Vasut
@ 2013-09-23 11:57         ` Jürgen Beisert
  0 siblings, 0 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23 11:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marek,

On Monday 23 September 2013 12:36:27 Marek Vasut wrote:
> > [...]
> > I also found an MX28EVK with a touchscreen here and: yes it does not work
> > with the modified driver. But now I'm confused, because of Lothar's
> > statement about the TX28 platform.
> >
> > @Lothar: What kernel revision did you use? I had to go back to 3.9 to get
> > a working kernel on the MX28EVK. More recent vanilla kernels stop working
> > (MMC and network fail here).
>
> Can you fix the SD and Network or at least show the fail log ?

Arrgh. My fault. I used the wrong devicetree. (imx28-m28evk.dt instead of 
imx28-evk.dtb). I still need more coffee...

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 10:35     ` Jürgen Beisert
  2013-09-23 10:36       ` Marek Vasut
@ 2013-09-23 12:12       ` Lothar Waßmann
  2013-09-23 13:24         ` Jürgen Beisert
  1 sibling, 1 reply; 22+ messages in thread
From: Lothar Waßmann @ 2013-09-23 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

J?rgen Beisert writes:
> Hi Marek,
> 
> On Monday 23 September 2013 09:55:58 J?rgen Beisert wrote:
> > On Monday 23 September 2013 01:55:04 Marek Vasut wrote:
> > > > The following series replaces the current busy loop touchscreen
> > > > implementation for i.MX28/i.MX23 SoCs by a fully interrupt driven
> > > > implementation.
> > > >
> > > > Since i.MX23 and i.MX28 silicon differs, the existing implementation
> > > > can be used for the i.MX28 SoC only.
> > > >
> > > > So, the first two patches of this series move the i.MX28 specific
> > > > definitions out of the way. The third patch simplifies the register
> > > > access to make it easier to add the i.MX23 support. Then the i.MX23
> > > > specific definitions are added, also the code to distinguish both SoCs
> > > > at run-time. Up to here the existing touchscreen driver will now run on
> > > > an i.MX23 Soc as well.
> > > >
> > > > When the i.MX23 SoC is running from battery it seems not to be a good
> > > > idea to run a busy loop to detect touches and their location. The
> > > > fourth patch adds a fully interrupt driven implementation which makes
> > > > use of the built-in delay and multiple sample features of the
> > > > touchscreen controller. This will reduce the interrupt load to a
> > > > minimum.
> > > >
> > > > The next to last patch in this series just removes the existing busy
> > > > loop implementation.
> > > >
> > > > The last patch adds a devicetree bindings proposal (to be discussed).
> > > >
> > > > Some restrictions/questions:
> > > >
> > > > - the touchscreen part is yet tested on i.MX23 SoC only
> > > > - has someone a good idea how to implement a reliable pressure
> > > > measurement if the resistances of the touchscreen's plates are unknown?
> > > >
> > > > Changes since v4:
> > > >
> > > > - honor Jonathan's comments about function names
> > > > - honor Dmitry's comments about workqueue canceling and interrupts
> > > > - adding devicetree bindings proposal
> > > >
> > > > Changes since v3:
> > > >
> > > > - split adding register access functions and i.MX23 support into two
> > > > patches
> > > >
> > > > Changes since v2:
> > > >
> > > > - useless debug output removed
> > > >
> > > > Changes since v1:
> > > >
> > > > - adding register access functions to make the existing code more
> > > > readable - adding some functions to distinguish the SoCs at run-time to
> > > > avoid if-else contructs whenever differences in the register layout
> > > > between i.MX23 and i.MX28 must be handled
> > >
> > > Just tested this on M28EVK, the touchscreen is dead. I do not get any
> > > touch events when I use ts_calibrate and when I hd /dev/input/eventX , I
> > > get nothing either.
> > >
> > > Right now, I'm somehow on a tight schedule, but I'd like to see this
> > > resolved ASAP. Do you have any hint for me ?
> >
> > Seems the very first touch detection does not work. A colleague just told
> > me, we have an i.MX28 based hardware here and maybe a touchscreen from a
> > different platform which maybe can be used with the i.MX28 platform. Stay
> > tuned...
> 
> I also found an MX28EVK with a touchscreen here and: yes it does not work with 
> the modified driver. But now I'm confused, because of Lothar's statement about 
> the TX28 platform.
> 
> @Lothar: What kernel revision did you use? I had to go back to 3.9 to get a 
> 
Current linux-next (3.12-rc1).

> working kernel on the MX28EVK. More recent vanilla kernels stop working (MMC 
> and network fail here).
>
I'm seeing some messages:
|mxs-mmc 80010000.ssp: dummy supplies not allowed
|fec 800f0000.ethernet: dummy supplies not allowed
But without any apparent consequences. Maybe that's a problem with the
MX28EVK?


Lothar Wa?mann
-- 
___________________________________________________________

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
___________________________________________________________

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 12:12       ` Lothar Waßmann
@ 2013-09-23 13:24         ` Jürgen Beisert
  2013-09-23 13:40           ` Lothar Waßmann
  2013-09-23 13:40           ` Jürgen Beisert
  0 siblings, 2 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23 13:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lothar,

On Monday 23 September 2013 14:12:02 Lothar Wa?mann wrote:
> [...]
> > @Lothar: What kernel revision did you use? I had to go back to 3.9 to get
> > a
>
> Current linux-next (3.12-rc1).

Okay.

> > working kernel on the MX28EVK. More recent vanilla kernels stop working
> > (MMC and network fail here).
>
> I'm seeing some messages:
> |mxs-mmc 80010000.ssp: dummy supplies not allowed
> |fec 800f0000.ethernet: dummy supplies not allowed

It was my fault. I'm also working with 3.12-rc1 now.

> But without any apparent consequences. Maybe that's a problem with the
> MX28EVK?

It seems the LRADC delay feature does not work. The touch detection interrupt 
happens and the driver switches to the Y plate measurement, arms the LRADC 
delay unit ... and nothing more happens. The LRADC delay unit should start a 
conversion on ADC channel 4. But it does not. Never.

The i.MX28 manual says the LRADC delay unit is driven by a 2 kHz clock, but 
does not say what kind of clock it is (or is derived from). I guess now, this 
clock isn't enabled and thus the delay unit can't work. At least on the 
MX28EVK. On your TX28 platform the clock seems enabled and the delay unit can 
do its job and drive the state machine.

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 13:24         ` Jürgen Beisert
@ 2013-09-23 13:40           ` Lothar Waßmann
  2013-09-23 14:05             ` Jürgen Beisert
  2013-09-23 13:40           ` Jürgen Beisert
  1 sibling, 1 reply; 22+ messages in thread
From: Lothar Waßmann @ 2013-09-23 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

J?rgen Beisert writes:
> The i.MX28 manual says the LRADC delay unit is driven by a 2 kHz clock, but 
> does not say what kind of clock it is (or is derived from). I guess now, this 
> clock isn't enabled and thus the delay unit can't work. At least on the 
> MX28EVK. On your TX28 platform the clock seems enabled and the delay unit can 
> do its job and drive the state machine.
>
The i.MX28 Ref Manual states in chapter 38.5.14 LRADC Scheduling Delay:
| This counter operates on a 2KHz clock derived from crystal clock.
Thus the clock should always be enabled.


Lothar Wa?mann
-- 
___________________________________________________________

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
___________________________________________________________

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 13:24         ` Jürgen Beisert
  2013-09-23 13:40           ` Lothar Waßmann
@ 2013-09-23 13:40           ` Jürgen Beisert
  1 sibling, 0 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23 13:40 UTC (permalink / raw)
  To: linux-arm-kernel


On Monday 23 September 2013 15:24:37 J?rgen Beisert wrote:
> Hi Lothar,
>
> On Monday 23 September 2013 14:12:02 Lothar Wa?mann wrote:
> > [...]
> >
> > > @Lothar: What kernel revision did you use? I had to go back to 3.9 to
> > > get a
> >
> > Current linux-next (3.12-rc1).
>
> Okay.
>
> > > working kernel on the MX28EVK. More recent vanilla kernels stop working
> > > (MMC and network fail here).
> >
> > I'm seeing some messages:
> > |mxs-mmc 80010000.ssp: dummy supplies not allowed
> > |fec 800f0000.ethernet: dummy supplies not allowed
>
> It was my fault. I'm also working with 3.12-rc1 now.
>
> > But without any apparent consequences. Maybe that's a problem with the
> > MX28EVK?
>
> It seems the LRADC delay feature does not work. The touch detection
> interrupt happens and the driver switches to the Y plate measurement, arms
> the LRADC delay unit ... and nothing more happens. The LRADC delay unit
> should start a conversion on ADC channel 4. But it does not. Never.
>
> The i.MX28 manual says the LRADC delay unit is driven by a 2 kHz clock, but
> does not say what kind of clock it is (or is derived from). I guess now,
> this clock isn't enabled and thus the delay unit can't work. At least on
> the MX28EVK. On your TX28 platform the clock seems enabled and the delay
> unit can do its job and drive the state machine.

Hmmm: 24 MHz / 750  = CLK_32K / 16 = CLK_LRADC2K

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| Phone: +49-5121-206917-5128 |
Peiner Str. 6-8, 31137 Hildesheim, Germany ? ?| Fax: ? +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 ? ? ? ? ? ? ?| http://www.pengutronix.de/ ?|

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation
  2013-09-23 13:40           ` Lothar Waßmann
@ 2013-09-23 14:05             ` Jürgen Beisert
  0 siblings, 0 replies; 22+ messages in thread
From: Jürgen Beisert @ 2013-09-23 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lothar,

On Monday 23 September 2013 15:40:18 Lothar Wa?mann wrote:
> J?rgen Beisert writes:
> > The i.MX28 manual says the LRADC delay unit is driven by a 2 kHz clock,
> > but does not say what kind of clock it is (or is derived from). I guess
> > now, this clock isn't enabled and thus the delay unit can't work. At
> > least on the MX28EVK. On your TX28 platform the clock seems enabled and
> > the delay unit can do its job and drive the state machine.
>
> The i.MX28 Ref Manual states in chapter 38.5.14 LRADC Scheduling Delay:
> | This counter operates on a 2KHz clock derived from crystal clock.
>
> Thus the clock should always be enabled.

But it isn't always on. I have now added the correct clock_get() call to the 
LRADC driver and the touchscreen works again on the MX28EVK. New patch series 
will follow. Same is required for i.MX23.

Regards,
Juergen

-- 
Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| Juergen Beisert ? ? ? ? ? ? |
Linux Solutions for Science and Industry ? ? ?| http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-09-23 14:05 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-19 12:22 [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Juergen Beisert
2013-09-19 12:22 ` [PATCH 1/7] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC Juergen Beisert
2013-09-19 12:22 ` [PATCH 2/7] Staging/iio/adc/touchscreen/MXS: separate i.MX28 specific register bits Juergen Beisert
2013-09-19 12:22 ` [PATCH 3/7] Staging/iio/adc/touchscreen/MXS: simplify register access Juergen Beisert
2013-09-19 12:22 ` [PATCH 4/7] Staging/iio/adc/touchscreen/MXS: add i.MX23 support to the LRADC touchscreen driver Juergen Beisert
2013-09-19 12:22 ` [PATCH 5/7] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection Juergen Beisert
2013-09-21 12:36   ` Jonathan Cameron
2013-09-19 12:22 ` [PATCH 6/7] Staging/iio/adc/touchscreen/MXS: Remove old touchscreen detection implementation Juergen Beisert
2013-09-19 12:22 ` [PATCH 7/7] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption Juergen Beisert
2013-09-21 12:42   ` Jonathan Cameron
2013-09-23  7:42     ` Jürgen Beisert
2013-09-22 23:55 ` [PATCHv5] staging/iio/adc: change the MXS touchscreen driver implementation Marek Vasut
2013-09-23  7:55   ` Jürgen Beisert
2013-09-23  9:25     ` Lothar Waßmann
2013-09-23 10:35     ` Jürgen Beisert
2013-09-23 10:36       ` Marek Vasut
2013-09-23 11:57         ` Jürgen Beisert
2013-09-23 12:12       ` Lothar Waßmann
2013-09-23 13:24         ` Jürgen Beisert
2013-09-23 13:40           ` Lothar Waßmann
2013-09-23 14:05             ` Jürgen Beisert
2013-09-23 13:40           ` Jürgen Beisert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).