aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.26/0090-fix-lis302dl-suspend-gpio.patch.patch
blob: 9a9c6051d26a96090d47dcb9c3c1c4abdafeb60b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
From f97c81869175362f755488bd50ddf85570236ce8 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:02 +0100
Subject: [PATCH] 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>
---
 arch/arm/mach-s3c2440/mach-gta02.c |   28 +++++++++++++++++++++++++++-
 drivers/input/misc/lis302dl.c      |   15 +++++++++++++++
 include/linux/lis302dl.h           |    1 +
 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 5bd68a6..99206ee 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 36bdcf7..2be816a 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 2dea813..0d6b4c4 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 {
-- 
1.5.6.3