aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy@openmoko.com>2008-11-19 17:09:34 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-19 17:09:34 +0000
commit6b5297122074ac393720b826fb534a2a4ad25772 (patch)
tree8a069dbf63d6001201db542d882eb3078cc713d9
parentcd399d1273d3e3a3a3827ec70eaf23eacae61d74 (diff)
fix-lis302dl-suspend-gpio.patch
Add platform stuff to deal with going in and out of suspend so the motion sensor IO is not driving high into unpowered sensors Signed-off-by: Andy Green <andy@openmoko.com>
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c28
-rw-r--r--drivers/input/misc/lis302dl.c15
-rw-r--r--include/linux/lis302dl.h1
3 files changed, 43 insertions, 1 deletions
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 5bd68a69f49..99206eee663 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -887,7 +887,31 @@ void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis)
}
-struct lis302dl_platform_data lis302_pdata[] = {
+void gat02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
+{
+ struct lis302dl_platform_data *pdata = lis->pdata;
+
+ if (!resume) {
+ /*
+ * we don't want to power them with a high level
+ * because GSENSOR_3V3 is not up during suspend
+ */
+ s3c2410_gpio_setpin(pdata->pin_chip_select, 0);
+ s3c2410_gpio_setpin(pdata->pin_clk, 0);
+ s3c2410_gpio_setpin(pdata->pin_mosi, 0);
+ /* misnomer: it is a pullDOWN in 2442 */
+ s3c2410_gpio_pullup(pdata->pin_miso, 1);
+ return;
+ }
+
+ /* back to normal */
+ s3c2410_gpio_setpin(pdata->pin_chip_select, 1);
+ s3c2410_gpio_setpin(pdata->pin_clk, 1);
+ /* misnomer: it is a pullDOWN in 2442 */
+ s3c2410_gpio_pullup(pdata->pin_miso, 0);
+}
+
+const struct lis302dl_platform_data lis302_pdata[] = {
{
.name = "lis302-1 (top)",
.pin_chip_select= S3C2410_GPD12,
@@ -896,6 +920,7 @@ struct lis302dl_platform_data lis302_pdata[] = {
.pin_miso = S3C2410_GPG5,
.open_drain = 1, /* altered at runtime by PCB rev */
.lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
+ .lis302dl_suspend_io = gat02_lis302dl_suspend_io,
}, {
.name = "lis302-2 (bottom)",
.pin_chip_select= S3C2410_GPD13,
@@ -904,6 +929,7 @@ struct lis302dl_platform_data lis302_pdata[] = {
.pin_miso = S3C2410_GPG5,
.open_drain = 1, /* altered at runtime by PCB rev */
.lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
+ .lis302dl_suspend_io = gat02_lis302dl_suspend_io,
},
};
diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index 36bdcf79b02..2be816a2ebb 100644
--- a/drivers/input/misc/lis302dl.c
+++ b/drivers/input/misc/lis302dl.c
@@ -428,6 +428,15 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
disable_irq(lis->spi_dev->irq);
local_save_flags(flags);
+ /*
+ * When we share SPI over multiple sensors, there is a race here
+ * that one or more sensors will lose. In that case, the shared
+ * SPI bus GPIO will be in sleep mode and partially pulled down. So
+ * we explicitly put our IO into "wake" mode here before the final
+ * traffic to the sensor.
+ */
+ (lis->pdata->lis302dl_suspend_io)(lis, 1);
+
/* save registers */
lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1);
lis->regs[LIS302DL_REG_CTRL2] = reg_read(lis, LIS302DL_REG_CTRL2);
@@ -467,6 +476,9 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
reg_write(lis, LIS302DL_REG_CTRL1, tmp);
}
+ /* place our IO to the device in sleep-compatible states */
+ (lis->pdata->lis302dl_suspend_io)(lis, 0);
+
local_irq_restore(flags);
return 0;
@@ -479,6 +491,9 @@ static int lis302dl_resume(struct spi_device *spi)
local_save_flags(flags);
+ /* get our IO to the device back in operational states */
+ (lis->pdata->lis302dl_suspend_io)(lis, 1);
+
/* restore registers after resume */
reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]);
diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
index 2dea8130a24..0d6b4c48bcb 100644
--- a/include/linux/lis302dl.h
+++ b/include/linux/lis302dl.h
@@ -16,6 +16,7 @@ struct lis302dl_platform_data {
unsigned long pin_miso;
int open_drain;
void (*lis302dl_bitbang_read)(struct lis302dl_info *);
+ void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming);
};
struct lis302dl_info {