aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordipen <dpatel@marvell.com>2012-11-06 11:09:39 -0500
committerLubomir Rintel <lkundrak@v3.sk>2019-07-22 19:40:01 +0200
commit6bdc96ab767c346857391862991e080406a14f0e (patch)
treeef27e1933eac27284dcc5d010b0acf6c5d476811
parentd65835b81ecc9f0646b136a280893e157c678c73 (diff)
downloadlinux-mmp3-dell-ariel-6bdc96ab767c346857391862991e080406a14f0e.tar.gz
MMP3: QSEVEN adding support to touch screen gpio wake up from d2 state. patch will also address issue of touch screen hang during bootup time touches by adding write fifo empty isr in i2c and powerdown mode in touch driver
Signed-off-by: dipen <dpatel@marvell.com>
-rw-r--r--arch/arm/mach-mmp/mmp3.c2
-rw-r--r--arch/arm/plat-pxa/include/plat/mfp.h2
-rw-r--r--arch/arm/plat-pxa/mfp.c19
-rw-r--r--drivers/i2c/busses/i2c-pxa.c8
-rw-r--r--drivers/input/touchscreen/tsc2007.c63
5 files changed, 86 insertions, 8 deletions
diff --git a/arch/arm/mach-mmp/mmp3.c b/arch/arm/mach-mmp/mmp3.c
index e13b27938b2e4..db2f25e28c723 100644
--- a/arch/arm/mach-mmp/mmp3.c
+++ b/arch/arm/mach-mmp/mmp3.c
@@ -156,7 +156,7 @@ static void __init mmp3_init_gpio(void)
for (i = 0; i < 6; i++)
__raw_writel(0xffffffff, APMASK(i));
- pxa_init_gpio(IRQ_MMP3_GPIO, 0, 167, NULL);
+ pxa_init_gpio(IRQ_MMP3_GPIO, 0, 167, mmp3_set_wake);
}
#ifdef CONFIG_REGDUMP
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
index fb8185d5d75c8..05672867fd61c 100644
--- a/arch/arm/plat-pxa/include/plat/mfp.h
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -644,6 +644,8 @@ void mfp_config(unsigned long *mfp_cfgs, int num);
void mfp_config_run(void);
void mfp_config_lpm(void);
void lpm_mfpr_edge_config(int mfp, unsigned long val);
+void lpm_mfpr_edge_detect_config(int mfp, unsigned long val);
+void lpm_mfpr_edge_detect_clear_config(int mfp);
#endif /* CONFIG_PXA3xx || CONFIG_PXA93x || CONFIG_PXA95x || CONFIG_ARCH_MMP */
#endif /* __ASM_PLAT_MFP_H */
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c
index 90bda3db7975a..aa41e8432a44c 100644
--- a/arch/arm/plat-pxa/mfp.c
+++ b/arch/arm/plat-pxa/mfp.c
@@ -231,7 +231,6 @@ void mfp_config_run(void)
for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++)
__mfp_config_run(p);
}
-
void lpm_mfpr_edge_config(int mfp, unsigned long val)
{
mfp_cfg_t m;
@@ -241,3 +240,21 @@ void lpm_mfpr_edge_config(int mfp, unsigned long val)
m |= mfpr_edge[MFP_LPM_EDGE(val)];
mfp_write(mfp, m);
}
+void lpm_mfpr_edge_detect_config(int mfp, unsigned long val)
+{
+ mfp_cfg_t m;
+ m = mfp_read(mfp);
+ m &= ~(MFPR_EDGE_CLEAR | MFPR_SLEEP_OE_N | MFPR_EDGE_FALL_EN
+ | MFPR_SLEEP_SEL | MFPR_EDGE_RISE_EN);
+ m |= val;
+ mfp_write(mfp, m);
+}
+void lpm_mfpr_edge_detect_clear_config(int mfp)
+{
+ mfp_cfg_t m;
+ m = mfp_read(mfp);
+ m &= ~(MFPR_SLEEP_SEL | MFPR_SLEEP_OE_N | MFPR_EDGE_CLEAR
+ | MFPR_EDGE_FALL_EN | MFPR_EDGE_RISE_EN);
+ m |= MFPR_EDGE_CLEAR;
+ mfp_write(mfp, m);
+}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 60f605a7566a1..54cdb2f81aa79 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -698,7 +698,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
* Step 2: initiate the write.
*/
icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
- writel(icr | ICR_START | ICR_TB, _ICR(i2c));
+ writel(icr | ICR_START | ICR_TB | ICR_ITEIE, _ICR(i2c));
}
static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
@@ -856,7 +856,7 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
if (!timeout && i2c->msg_num) {
i2c_pxa_scream_blue_murder(i2c, "timeout");
- ret = I2C_RETRY;
+ return I2C_RETRY;
}
out:
@@ -965,7 +965,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
*/
writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
- icr |= ICR_ALDIE | ICR_TB;
+ icr |= ICR_ALDIE | ICR_TB | ICR_ITEIE;
/*
* If this is the last byte of the last message, send
@@ -999,7 +999,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
* And trigger a repeated start, and send the byte.
*/
icr &= ~ICR_ALDIE;
- icr |= ICR_START | ICR_TB;
+ icr |= ICR_START | ICR_TB | ICR_ITEIE;
} else {
if (i2c->msg->len == 0) {
/*
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 9607c65937e96..9445c52f45311 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -26,6 +26,9 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>
+#include <linux/pm_wakeup.h>
+#include <linux/pm.h>
+#include <plat/mfp.h>
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
#define TSC2007_MEASURE_AUX (0x2 << 4)
@@ -57,6 +60,9 @@
#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X)
#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
+static bool wake_en;
+#define DEFINE_WAKE_UP
+
struct ts_event {
u16 x;
u16 y;
@@ -107,6 +113,7 @@ static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
{
+ tsc2007_xfer(tsc, PWRDOWN);
/* y- still on; turn on only y+ (and ADC) */
tc->y = tsc2007_xfer(tsc, READ_Y);
@@ -182,7 +189,9 @@ static void tsc2007_work(struct work_struct *work)
dev_dbg(&ts->client->dev, "pen is still down\n");
}
+ disable_irq(ts->irq);
tsc2007_read_values(ts, &tc);
+ enable_irq(ts->irq);
rt = tsc2007_calculate_pressure(ts, &tc);
if (rt > ts->max_rt) {
@@ -324,7 +333,13 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
dev_err(&client->dev, "irq %d busy?\n", ts->irq);
goto err_free_mem;
}
-
+#ifdef DEFINE_WAKE_UP
+ err = device_init_wakeup(&client->dev, 1);
+ if (err < 0) {
+ pr_info("Touch screen did not init as wake up source......\n");
+ goto err_free_mem;
+ }
+#endif
/* Prepare for touch readings - power down ADC and enable PENIRQ */
err = tsc2007_xfer(ts, PWRDOWN);
if (err < 0)
@@ -371,10 +386,54 @@ static const struct i2c_device_id tsc2007_idtable[] = {
MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
+#ifdef CONFIG_PM
+static int tsc2007_suspend(struct device *dev)
+{
+ pr_info("Touch screen is going to suspend....\n");
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsc2007 *ts = i2c_get_clientdata(client);
+
+#ifdef DEFINE_WAKE_UP
+ if (device_may_wakeup(&client->dev) && !wake_en) {
+ if (enable_irq_wake(ts->irq) == 0) {
+ unsigned long val = 0;
+ val = MFPR_SLEEP_OE_N
+ | MFPR_EDGE_FALL_EN | MFPR_SLEEP_SEL;
+ lpm_mfpr_edge_detect_config(MFP_PIN_GPIO78, val);
+ pr_info("Touch screen irq is set as wake up source\n");
+ wake_en = true;
+ } else
+ dev_err(&client->dev, "enable_irq_wake failed\n");
+ }
+#endif
+ return 0;
+}
+static int tsc2007_resume(struct device *dev)
+{
+ pr_info("Touch screen is going to resume....\n");
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsc2007 *ts = i2c_get_clientdata(client);
+#ifdef DEFINE_WAKE_UP
+ if (device_may_wakeup(&client->dev) && wake_en) {
+ disable_irq_wake(ts->irq);
+ lpm_mfpr_edge_detect_clear_config(MFP_PIN_GPIO78);
+ pr_info("Touch screen irq is disbled as wake up source");
+ wake_en = false;
+ }
+#endif
+ return 0;
+}
+static SIMPLE_DEV_PM_OPS(tsc2007_pm, tsc2007_suspend, tsc2007_resume);
+#endif
+
static struct i2c_driver tsc2007_driver = {
.driver = {
.owner = THIS_MODULE,
- .name = "tsc2007"
+ .name = "tsc2007",
+#ifdef CONFIG_PM
+ .pm = &tsc2007_pm,
+#endif
+
},
.id_table = tsc2007_idtable,
.probe = tsc2007_probe,