mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-05-09 21:11:16 +00:00
034e54254f
runtime tested on beaglebone Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
412 lines
13 KiB
Diff
412 lines
13 KiB
Diff
From 7cb067cd1bd237a7a9978747fc4f96fa90b5d146 Mon Sep 17 00:00:00 2001
|
|
From: Joel A Fernandes <joelagnel@ti.com>
|
|
Date: Wed, 30 Nov 2011 15:00:40 +0100
|
|
Subject: [PATCH 08/16] tscadc: Add general purpose mode, untested with
|
|
touchscreen functionality
|
|
|
|
Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
|
|
|
|
Conflicts:
|
|
|
|
drivers/input/touchscreen/ti_tscadc.c
|
|
[Fixed by Koen - needs review]
|
|
---
|
|
arch/arm/mach-omap2/board-am335xevm.c | 2 +
|
|
arch/arm/mach-omap2/mux33xx.c | 12 ++
|
|
arch/arm/mach-omap2/mux33xx.h | 4 +
|
|
drivers/input/touchscreen/ti_tscadc.c | 209 +++++++++++++++++++++++++--------
|
|
include/linux/input/ti_tscadc.h | 4 +
|
|
5 files changed, 180 insertions(+), 51 deletions(-)
|
|
|
|
diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
|
|
index 87ccf14..c7bb091 100644
|
|
--- a/arch/arm/mach-omap2/board-am335xevm.c
|
|
+++ b/arch/arm/mach-omap2/board-am335xevm.c
|
|
@@ -2182,6 +2182,7 @@ static struct evm_dev_cfg beaglebone_old_dev_cfg[] = {
|
|
{i2c2_init, DEV_ON_BASEBOARD, PROFILE_NONE},
|
|
{mmc0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
|
|
{boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
|
|
+ {tsc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
|
|
{NULL, 0, 0},
|
|
};
|
|
|
|
@@ -2194,6 +2195,7 @@ static struct evm_dev_cfg beaglebone_dev_cfg[] = {
|
|
{i2c2_init, DEV_ON_BASEBOARD, PROFILE_NONE},
|
|
{mmc0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
|
|
{boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
|
|
+ {tsc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
|
|
{NULL, 0, 0},
|
|
};
|
|
|
|
diff --git a/arch/arm/mach-omap2/mux33xx.c b/arch/arm/mach-omap2/mux33xx.c
|
|
index 36bb10a..e4cd407 100644
|
|
--- a/arch/arm/mach-omap2/mux33xx.c
|
|
+++ b/arch/arm/mach-omap2/mux33xx.c
|
|
@@ -584,6 +584,18 @@ static struct omap_mux __initdata am33xx_muxmodes[] = {
|
|
_AM33XX_MUXENTRY(AIN3, 0,
|
|
"ain3", NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL),
|
|
+ _AM33XX_MUXENTRY(AIN4, 0,
|
|
+ "ain4", NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL),
|
|
+ _AM33XX_MUXENTRY(AIN5, 0,
|
|
+ "ain5", NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL),
|
|
+ _AM33XX_MUXENTRY(AIN6, 0,
|
|
+ "ain6", NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL),
|
|
+ _AM33XX_MUXENTRY(AIN7, 0,
|
|
+ "ain7", NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL),
|
|
_AM33XX_MUXENTRY(VREFP, 0,
|
|
"vrefp", NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL),
|
|
diff --git a/arch/arm/mach-omap2/mux33xx.h b/arch/arm/mach-omap2/mux33xx.h
|
|
index 70a3012..348c8e5 100644
|
|
--- a/arch/arm/mach-omap2/mux33xx.h
|
|
+++ b/arch/arm/mach-omap2/mux33xx.h
|
|
@@ -228,6 +228,10 @@
|
|
#define AM33XX_CONTROL_PADCONF_DDR_DQSN1_OFFSET 0x0AFC
|
|
#define AM33XX_CONTROL_PADCONF_DDR_VREF_OFFSET 0x0B00
|
|
#define AM33XX_CONTROL_PADCONF_DDR_VTP_OFFSET 0x0B04
|
|
+#define AM33XX_CONTROL_PADCONF_AIN7_OFFSET 0x0B10
|
|
+#define AM33XX_CONTROL_PADCONF_AIN6_OFFSET 0x0B14
|
|
+#define AM33XX_CONTROL_PADCONF_AIN5_OFFSET 0x0B18
|
|
+#define AM33XX_CONTROL_PADCONF_AIN4_OFFSET 0x0B1C
|
|
#define AM33XX_CONTROL_PADCONF_AIN3_OFFSET 0x0B20
|
|
#define AM33XX_CONTROL_PADCONF_AIN2_OFFSET 0x0B24
|
|
#define AM33XX_CONTROL_PADCONF_AIN1_OFFSET 0x0B28
|
|
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
|
|
index e3b5775..699503d 100644
|
|
--- a/drivers/input/touchscreen/ti_tscadc.c
|
|
+++ b/drivers/input/touchscreen/ti_tscadc.c
|
|
@@ -27,6 +27,8 @@
|
|
#include <linux/input/ti_tscadc.h>
|
|
#include <linux/delay.h>
|
|
|
|
+/* Memory mapped registers here have incorrect offsets!
|
|
+ * Correct after referring TRM */
|
|
#define TSCADC_REG_IRQEOI 0x020
|
|
#define TSCADC_REG_RAWIRQSTATUS 0x024
|
|
#define TSCADC_REG_IRQSTATUS 0x028
|
|
@@ -54,12 +56,18 @@
|
|
|
|
/* Register Bitfields */
|
|
#define TSCADC_IRQWKUP_ENB BIT(0)
|
|
-#define TSCADC_STPENB_STEPENB 0x7FFF
|
|
+#define TSCADC_STPENB_STEPENB_TOUCHSCREEN 0x7FFF
|
|
+#define TSCADC_STPENB_STEPENB_GENERAL 0x0400
|
|
#define TSCADC_IRQENB_FIFO0THRES BIT(2)
|
|
+#define TSCADC_IRQENB_FIFO0OVERRUN BIT(3)
|
|
#define TSCADC_IRQENB_FIFO1THRES BIT(5)
|
|
+#define TSCADC_IRQENB_EOS BIT(1)
|
|
#define TSCADC_IRQENB_PENUP BIT(9)
|
|
-#define TSCADC_STEPCONFIG_MODE_HWSYNC 0x2
|
|
+#define TSCADC_STEPCONFIG_MODE_HWSYNC 0x2
|
|
+#define TSCADC_STEPCONFIG_MODE_SWCONT 0x1
|
|
+#define TSCADC_STEPCONFIG_MODE_SWONESHOT 0x0
|
|
#define TSCADC_STEPCONFIG_2SAMPLES_AVG (1 << 4)
|
|
+#define TSCADC_STEPCONFIG_NO_AVG 0
|
|
#define TSCADC_STEPCONFIG_XPP BIT(5)
|
|
#define TSCADC_STEPCONFIG_XNN BIT(6)
|
|
#define TSCADC_STEPCONFIG_YPP BIT(7)
|
|
@@ -105,6 +113,7 @@ struct tscadc {
|
|
int analog_input;
|
|
int x_plate_resistance;
|
|
struct clk *tsc_ick;
|
|
+ int mode;
|
|
int irq;
|
|
void __iomem *tsc_base;
|
|
};
|
|
@@ -120,6 +129,86 @@ static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
|
|
writel(val, tsc->tsc_base + reg);
|
|
}
|
|
|
|
+static void tsc_adc_step_config(struct tscadc *ts_dev)
|
|
+{
|
|
+ unsigned int stepconfig = 0, delay = 0, chargeconfig = 0;
|
|
+
|
|
+ /*
|
|
+ * Step Configuration
|
|
+ * software-enabled continous mode
|
|
+ * 2 sample averaging
|
|
+ * sample channel 1 (SEL_INP mux bits = 0)
|
|
+ */
|
|
+ stepconfig = TSCADC_STEPCONFIG_MODE_SWONESHOT |
|
|
+ TSCADC_STEPCONFIG_2SAMPLES_AVG |
|
|
+ (0x7 << 19);
|
|
+
|
|
+ delay = TSCADC_STEPCONFIG_SAMPLEDLY | TSCADC_STEPCONFIG_OPENDLY;
|
|
+
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG(10), stepconfig);
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY(10), delay);
|
|
+
|
|
+ /* Get the ball rolling, this will trigger the FSM to step through
|
|
+ * as soon as TSC_ADC_SS is turned on */
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
|
|
+}
|
|
+
|
|
+static irqreturn_t tsc_adc_interrupt(int irq, void *dev)
|
|
+{
|
|
+ struct tscadc *ts_dev = (struct tscadc *)dev;
|
|
+ struct input_dev *input_dev = ts_dev->input;
|
|
+ unsigned int status, irqclr = 0;
|
|
+ int i;
|
|
+ int fsm = 0, fifo0count = 0, fifo1count = 0;
|
|
+ unsigned int read_sample = 0, ready1 = 0;
|
|
+ unsigned int prev_val_x = ~0, prev_val_y = ~0;
|
|
+ unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
|
|
+ unsigned int cur_diff_x = 0, cur_diff_y = 0;
|
|
+ unsigned int val_x = 0, val_y = 0, diffx = 0, diffy = 0;
|
|
+
|
|
+ status = tscadc_readl(ts_dev, TSCADC_REG_IRQSTATUS);
|
|
+
|
|
+ printk("interrupt! status=%x\n", status);
|
|
+ // if (status & TSCADC_IRQENB_EOS) {
|
|
+ // irqclr |= TSCADC_IRQENB_EOS;
|
|
+ // }
|
|
+
|
|
+ if (status & TSCADC_IRQENB_FIFO0THRES) {
|
|
+ fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO0CNT);
|
|
+ printk("fifo 0 count = %d\n", fifo1count);
|
|
+
|
|
+ for (i = 0; i < fifo1count; i++) {
|
|
+ read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO0);
|
|
+ printk("sample: %d: %x\n", i, read_sample);
|
|
+ }
|
|
+ irqclr |= TSCADC_IRQENB_FIFO0THRES;
|
|
+ }
|
|
+
|
|
+
|
|
+ if (status & TSCADC_IRQENB_FIFO1THRES) {
|
|
+ fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO1CNT);
|
|
+
|
|
+ for (i = 0; i < fifo1count; i++) {
|
|
+ read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO1);
|
|
+ // read_sample = read_sample & 0xfff;
|
|
+ printk("sample: %d: %d\n", i, read_sample);
|
|
+ panic("sample read from fifo1!");
|
|
+ }
|
|
+ irqclr |= TSCADC_IRQENB_FIFO1THRES;
|
|
+ }
|
|
+
|
|
+ mdelay(500);
|
|
+
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_IRQSTATUS, irqclr);
|
|
+
|
|
+ /* check pending interrupts */
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
|
|
+
|
|
+ /* Turn on Step 1 again */
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
static void tsc_step_config(struct tscadc *ts_dev)
|
|
{
|
|
unsigned int stepconfigx = 0, stepconfigy = 0;
|
|
@@ -224,7 +313,7 @@ static void tsc_step_config(struct tscadc *ts_dev)
|
|
tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG14, stepconfigz2);
|
|
tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY14, delay);
|
|
|
|
- tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
|
|
}
|
|
|
|
static void tsc_idle_config(struct tscadc *ts_config)
|
|
@@ -242,7 +331,7 @@ static void tsc_idle_config(struct tscadc *ts_config)
|
|
tscadc_writel(ts_config, TSCADC_REG_IDLECONFIG, idleconfig);
|
|
}
|
|
|
|
-static irqreturn_t tscadc_interrupt(int irq, void *dev)
|
|
+static irqreturn_t tsc_interrupt(int irq, void *dev)
|
|
{
|
|
struct tscadc *ts_dev = (struct tscadc *)dev;
|
|
struct input_dev *input_dev = ts_dev->input;
|
|
@@ -362,7 +451,7 @@ static irqreturn_t tscadc_interrupt(int irq, void *dev)
|
|
/* check pending interrupts */
|
|
tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
|
|
|
|
- tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
@@ -400,13 +489,15 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
|
|
return -ENODEV;
|
|
}
|
|
|
|
- input_dev = input_allocate_device();
|
|
- if (!input_dev) {
|
|
- dev_err(&pdev->dev, "failed to allocate input device.\n");
|
|
- err = -ENOMEM;
|
|
- goto err_free_mem;
|
|
+ if(pdata->mode == TI_TSCADC_TSCMODE) {
|
|
+ input_dev = input_allocate_device();
|
|
+ if (!input_dev) {
|
|
+ dev_err(&pdev->dev, "failed to allocate input device.\n");
|
|
+ err = -ENOMEM;
|
|
+ goto err_free_mem;
|
|
+ }
|
|
+ ts_dev->input = input_dev;
|
|
}
|
|
- ts_dev->input = input_dev;
|
|
|
|
res = request_mem_region(res->start, resource_size(res), pdev->name);
|
|
if (!res) {
|
|
@@ -422,8 +513,15 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
|
|
goto err_release_mem;
|
|
}
|
|
|
|
- err = request_irq(ts_dev->irq, tscadc_interrupt, IRQF_DISABLED,
|
|
- pdev->dev.driver->name, ts_dev);
|
|
+ if(pdata->mode == TI_TSCADC_TSCMODE) {
|
|
+ err = request_irq(ts_dev->irq, tsc_interrupt, IRQF_DISABLED,
|
|
+ pdev->dev.driver->name, ts_dev);
|
|
+ }
|
|
+ else {
|
|
+ err = request_irq(ts_dev->irq, tsc_adc_interrupt, IRQF_DISABLED,
|
|
+ pdev->dev.driver->name, ts_dev);
|
|
+ }
|
|
+
|
|
if (err) {
|
|
dev_err(&pdev->dev, "failed to allocate irq.\n");
|
|
goto err_unmap_regs;
|
|
@@ -443,11 +541,17 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
|
|
goto err_free_irq;
|
|
}
|
|
clock_rate = clk_get_rate(clk);
|
|
+
|
|
+ /* clk_value of atleast 21MHz required
|
|
+ * Clock verified on BeagleBone to be 24MHz */
|
|
+
|
|
+
|
|
clk_value = clock_rate / ADC_CLK;
|
|
if (clk_value < 7) {
|
|
dev_err(&pdev->dev, "clock input less than min clock requirement\n");
|
|
goto err_fail;
|
|
}
|
|
+
|
|
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
|
|
clk_value = clk_value - 1;
|
|
tscadc_writel(ts_dev, TSCADC_REG_CLKDIV, clk_value);
|
|
@@ -458,57 +562,60 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
|
|
ts_dev->wires = pdata->wires;
|
|
ts_dev->analog_input = pdata->analog_input;
|
|
ts_dev->x_plate_resistance = pdata->x_plate_resistance;
|
|
+ ts_dev->mode = pdata->mode;
|
|
|
|
- /* Set the control register bits */
|
|
+ /* Set the control register bits - 12.5.44 TRM */
|
|
ctrl = TSCADC_CNTRLREG_STEPCONFIGWRT |
|
|
- TSCADC_CNTRLREG_TSCENB |
|
|
- TSCADC_CNTRLREG_STEPID;
|
|
- switch (ts_dev->wires) {
|
|
- case 4:
|
|
- ctrl |= TSCADC_CNTRLREG_4WIRE;
|
|
- break;
|
|
- case 5:
|
|
- ctrl |= TSCADC_CNTRLREG_5WIRE;
|
|
- break;
|
|
- case 8:
|
|
- ctrl |= TSCADC_CNTRLREG_8WIRE;
|
|
- break;
|
|
+ TSCADC_CNTRLREG_STEPID;
|
|
+ if(pdata->mode == TI_TSCADC_TSCMODE) {
|
|
+ ctrl |= TSCADC_CNTRLREG_TSCENB;
|
|
+ switch (ts_dev->wires) {
|
|
+ case 4:
|
|
+ ctrl |= TSCADC_CNTRLREG_4WIRE;
|
|
+ break;
|
|
+ case 5:
|
|
+ ctrl |= TSCADC_CNTRLREG_5WIRE;
|
|
+ break;
|
|
+ case 8:
|
|
+ ctrl |= TSCADC_CNTRLREG_8WIRE;
|
|
+ break;
|
|
+ }
|
|
}
|
|
tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
|
|
|
|
- /* Set register bits for Idel Config Mode */
|
|
- tsc_idle_config(ts_dev);
|
|
-
|
|
- /* IRQ Enable */
|
|
- irqenable = TSCADC_IRQENB_FIFO1THRES;
|
|
+ /* Touch screen / ADC configuration */
|
|
+ if(pdata->mode == TI_TSCADC_TSCMODE) {
|
|
+ tsc_idle_config(ts_dev);
|
|
+ tsc_step_config(ts_dev);
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
|
|
+ irqenable = TSCADC_IRQENB_FIFO1THRES;
|
|
+ /* Touch screen also needs an input_dev */
|
|
+ input_dev->name = "ti-tsc-adcc";
|
|
+ input_dev->dev.parent = &pdev->dev;
|
|
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
|
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
|
+ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
|
|
+ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
|
|
+ /* register to the input system */
|
|
+ err = input_register_device(input_dev);
|
|
+ if (err)
|
|
+ goto err_fail;
|
|
+ }
|
|
+ else {
|
|
+ tsc_adc_step_config(ts_dev);
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_FIFO0THR, 0);
|
|
+ irqenable = TSCADC_IRQENB_FIFO0THRES;
|
|
+ }
|
|
tscadc_writel(ts_dev, TSCADC_REG_IRQENABLE, irqenable);
|
|
|
|
- tsc_step_config(ts_dev);
|
|
-
|
|
- tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
|
|
-
|
|
ctrl |= TSCADC_CNTRLREG_TSCSSENB;
|
|
- tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
|
|
-
|
|
- input_dev->name = "ti-tsc-adcc";
|
|
- input_dev->dev.parent = &pdev->dev;
|
|
-
|
|
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
|
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
|
-
|
|
- input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
|
|
- input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
|
|
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
|
|
-
|
|
- /* register to the input system */
|
|
- err = input_register_device(input_dev);
|
|
- if (err)
|
|
- goto err_fail;
|
|
+ tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl); /* Turn on TSC_ADC */
|
|
|
|
platform_set_drvdata(pdev, ts_dev);
|
|
return 0;
|
|
|
|
err_fail:
|
|
+ printk(KERN_ERR "Fatal error, shutting down TSC_ADC\n");
|
|
clk_disable(ts_dev->tsc_ick);
|
|
clk_put(ts_dev->tsc_ick);
|
|
err_free_irq:
|
|
diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
|
|
index 2c547bb..850cd4b 100644
|
|
--- a/include/linux/input/ti_tscadc.h
|
|
+++ b/include/linux/input/ti_tscadc.h
|
|
@@ -14,8 +14,12 @@
|
|
* @x_plate_resistance: X plate resistance.
|
|
*/
|
|
|
|
+#define TI_TSCADC_TSCMODE 0
|
|
+#define TI_TSCADC_GENMODE 1
|
|
+
|
|
struct tsc_data {
|
|
int wires;
|
|
int analog_input;
|
|
int x_plate_resistance;
|
|
+ int mode;
|
|
};
|
|
--
|
|
1.7.7.5
|
|
|