1 From b1f47a12474fdb7c00e2234a8a02a7e1a2031a1e Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Sun, 13 Apr 2008 07:25:51 +0100
4 Subject: [PATCH] fix-lis302dl-suspend-gpio.patch
5 Add platform stuff to deal with going in and out of suspend
6 so the motion sensor IO is not driving high into unpowered sensors
8 Signed-off-by: Andy Green <andy@openmoko.com>
10 arch/arm/mach-s3c2440/mach-gta02.c | 28 +++++++++++++++++++++++++++-
11 drivers/input/misc/lis302dl.c | 15 +++++++++++++++
12 include/linux/lis302dl.h | 1 +
13 3 files changed, 43 insertions(+), 1 deletions(-)
15 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
16 index 5bd68a6..99206ee 100644
17 --- a/arch/arm/mach-s3c2440/mach-gta02.c
18 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
19 @@ -887,7 +887,31 @@ void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis)
23 -struct lis302dl_platform_data lis302_pdata[] = {
24 +void gat02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
26 + struct lis302dl_platform_data *pdata = lis->pdata;
30 + * we don't want to power them with a high level
31 + * because GSENSOR_3V3 is not up during suspend
33 + s3c2410_gpio_setpin(pdata->pin_chip_select, 0);
34 + s3c2410_gpio_setpin(pdata->pin_clk, 0);
35 + s3c2410_gpio_setpin(pdata->pin_mosi, 0);
36 + /* misnomer: it is a pullDOWN in 2442 */
37 + s3c2410_gpio_pullup(pdata->pin_miso, 1);
41 + /* back to normal */
42 + s3c2410_gpio_setpin(pdata->pin_chip_select, 1);
43 + s3c2410_gpio_setpin(pdata->pin_clk, 1);
44 + /* misnomer: it is a pullDOWN in 2442 */
45 + s3c2410_gpio_pullup(pdata->pin_miso, 0);
48 +const struct lis302dl_platform_data lis302_pdata[] = {
50 .name = "lis302-1 (top)",
51 .pin_chip_select= S3C2410_GPD12,
52 @@ -896,6 +920,7 @@ struct lis302dl_platform_data lis302_pdata[] = {
53 .pin_miso = S3C2410_GPG5,
54 .open_drain = 1, /* altered at runtime by PCB rev */
55 .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
56 + .lis302dl_suspend_io = gat02_lis302dl_suspend_io,
58 .name = "lis302-2 (bottom)",
59 .pin_chip_select= S3C2410_GPD13,
60 @@ -904,6 +929,7 @@ struct lis302dl_platform_data lis302_pdata[] = {
61 .pin_miso = S3C2410_GPG5,
62 .open_drain = 1, /* altered at runtime by PCB rev */
63 .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
64 + .lis302dl_suspend_io = gat02_lis302dl_suspend_io,
68 diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
69 index 36bdcf7..2be816a 100644
70 --- a/drivers/input/misc/lis302dl.c
71 +++ b/drivers/input/misc/lis302dl.c
72 @@ -428,6 +428,15 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
73 disable_irq(lis->spi_dev->irq);
74 local_save_flags(flags);
77 + * When we share SPI over multiple sensors, there is a race here
78 + * that one or more sensors will lose. In that case, the shared
79 + * SPI bus GPIO will be in sleep mode and partially pulled down. So
80 + * we explicitly put our IO into "wake" mode here before the final
81 + * traffic to the sensor.
83 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
86 lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1);
87 lis->regs[LIS302DL_REG_CTRL2] = reg_read(lis, LIS302DL_REG_CTRL2);
88 @@ -467,6 +476,9 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
89 reg_write(lis, LIS302DL_REG_CTRL1, tmp);
92 + /* place our IO to the device in sleep-compatible states */
93 + (lis->pdata->lis302dl_suspend_io)(lis, 0);
95 local_irq_restore(flags);
98 @@ -479,6 +491,9 @@ static int lis302dl_resume(struct spi_device *spi)
100 local_save_flags(flags);
102 + /* get our IO to the device back in operational states */
103 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
105 /* restore registers after resume */
106 reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
107 reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]);
108 diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
109 index 2dea813..0d6b4c4 100644
110 --- a/include/linux/lis302dl.h
111 +++ b/include/linux/lis302dl.h
112 @@ -16,6 +16,7 @@ struct lis302dl_platform_data {
113 unsigned long pin_miso;
115 void (*lis302dl_bitbang_read)(struct lis302dl_info *);
116 + void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming);
119 struct lis302dl_info {