aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreric miao <eric.miao@marvell.com>2008-03-10 21:46:28 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-04-19 06:29:05 -0400
commitc0a596d6a138ea281bed4ff3018c07c45dd245a2 (patch)
treeab3c25663433bf8c3f16026d969f9722d4ecff92
parent9b02b2df0099c083ea40ba8c7068e3dcbe381302 (diff)
[ARM] pxa: allow dynamic enable/disable of GPIO wakeup for pxa{25x,27x}
Changes include: 1. rename MFP_LPM_WAKEUP_ENABLE into MFP_LPM_CAN_WAKEUP to indicate the board capability of this pin to wakeup the system 2. add gpio_set_wake() and keypad_set_wake() to allow dynamically enable/disable wakeup from GPIOs and keypad GPIO * these functions are currently kept in mfp-pxa2xx.c due to their dependency to the MFP configuration 3. pxa2xx_mfp_config() only gives early warning if MFP_LPM_CAN_WAKEUP is set on incorrect pins So that the GPIO's wakeup capability is now decided by the following: a) processor's capability: (only those GPIOs which have dedicated bits within PWER/PRER/PFER can wakeup the system), this is initialized by pxa{25x,27x}_init_mfp() b) board design decides: - whether the pin is designed to wakeup the system (some of the GPIOs are configured as other functions, which is not intended to be a wakeup source), by OR'ing the pin config with MFP_LPM_CAN_WAKEUP - which edge the pin is designed to wakeup the system, this may depends on external peripherals/connections, which is totally board specific; this is indicated by MFP_LPM_EDGE_* c) the corresponding device's (most likely the gpio_keys.c) wakeup attribute: Signed-off-by: eric miao <eric.miao@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c93
-rw-r--r--arch/arm/mach-pxa/pxa25x.c23
-rw-r--r--arch/arm/mach-pxa/pxa27x.c31
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa27x.h1
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa2xx.h11
5 files changed, 91 insertions, 68 deletions
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index f85f681c0393..22097a1707cc 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -28,15 +28,17 @@
28 28
29#define PWER_WE35 (1 << 24) 29#define PWER_WE35 (1 << 24)
30 30
31static struct { 31struct gpio_desc {
32 unsigned valid : 1; 32 unsigned valid : 1;
33 unsigned can_wakeup : 1; 33 unsigned can_wakeup : 1;
34 unsigned keypad_gpio : 1; 34 unsigned keypad_gpio : 1;
35 unsigned int mask; /* bit mask in PWER or PKWR */ 35 unsigned int mask; /* bit mask in PWER or PKWR */
36 unsigned long config; 36 unsigned long config;
37} gpio_desc[MFP_PIN_GPIO127 + 1]; 37};
38
39static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
38 40
39static inline int __mfp_config_gpio(unsigned gpio, unsigned long c) 41static int __mfp_config_gpio(unsigned gpio, unsigned long c)
40{ 42{
41 unsigned long gafr, mask = GPIO_bit(gpio); 43 unsigned long gafr, mask = GPIO_bit(gpio);
42 int fn; 44 int fn;
@@ -70,26 +72,19 @@ static inline int __mfp_config_gpio(unsigned gpio, unsigned long c)
70 return -EINVAL; 72 return -EINVAL;
71 } 73 }
72 74
73 /* wakeup enabling */ 75 /* give early warning if MFP_LPM_CAN_WAKEUP is set on the
74 if ((c & MFP_LPM_WAKEUP_ENABLE) == 0) 76 * configurations of those pins not able to wakeup
75 return 0; 77 */
76 78 if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) {
77 if (!gpio_desc[gpio].can_wakeup || c & MFP_DIR_OUT) {
78 pr_warning("%s: GPIO%d unable to wakeup\n", 79 pr_warning("%s: GPIO%d unable to wakeup\n",
79 __func__, gpio); 80 __func__, gpio);
80 return -EINVAL; 81 return -EINVAL;
81 } 82 }
82 83
83 if (gpio_desc[gpio].keypad_gpio) 84 if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) {
84 PKWR |= gpio_desc[gpio].mask; 85 pr_warning("%s: output GPIO%d unable to wakeup\n",
85 else { 86 __func__, gpio);
86 PWER |= gpio_desc[gpio].mask; 87 return -EINVAL;
87
88 if (c & MFP_LPM_EDGE_RISE)
89 PRER |= gpio_desc[gpio].mask;
90
91 if (c & MFP_LPM_EDGE_FALL)
92 PFER |= gpio_desc[gpio].mask;
93 } 88 }
94 89
95 return 0; 90 return 0;
@@ -120,6 +115,45 @@ void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
120 } 115 }
121} 116}
122 117
118int gpio_set_wake(unsigned int gpio, unsigned int on)
119{
120 struct gpio_desc *d;
121 unsigned long c;
122
123 if (gpio > mfp_to_gpio(MFP_PIN_GPIO127))
124 return -EINVAL;
125
126 d = &gpio_desc[gpio];
127 c = d->config;
128
129 if (!d->valid)
130 return -EINVAL;
131
132 if (d->keypad_gpio)
133 return -EINVAL;
134
135 if (d->can_wakeup && (c & MFP_LPM_CAN_WAKEUP)) {
136 if (on) {
137 PWER |= d->mask;
138
139 if (c & MFP_LPM_EDGE_RISE)
140 PRER |= d->mask;
141 else
142 PRER &= ~d->mask;
143
144 if (c & MFP_LPM_EDGE_FALL)
145 PFER |= d->mask;
146 else
147 PFER &= ~d->mask;
148 } else {
149 PWER &= ~d->mask;
150 PRER &= ~d->mask;
151 PFER &= ~d->mask;
152 }
153 }
154 return 0;
155}
156
123#ifdef CONFIG_PXA25x 157#ifdef CONFIG_PXA25x
124static int __init pxa25x_mfp_init(void) 158static int __init pxa25x_mfp_init(void)
125{ 159{
@@ -141,11 +175,32 @@ postcore_initcall(pxa25x_mfp_init);
141#endif /* CONFIG_PXA25x */ 175#endif /* CONFIG_PXA25x */
142 176
143#ifdef CONFIG_PXA27x 177#ifdef CONFIG_PXA27x
144static int pxa27x_pkwr_gpio[] __initdata = { 178static int pxa27x_pkwr_gpio[] = {
145 13, 16, 17, 34, 36, 37, 38, 39, 90, 91, 93, 94, 179 13, 16, 17, 34, 36, 37, 38, 39, 90, 91, 93, 94,
146 95, 96, 97, 98, 99, 100, 101, 102 180 95, 96, 97, 98, 99, 100, 101, 102
147}; 181};
148 182
183int keypad_set_wake(unsigned int on)
184{
185 unsigned int i, gpio, mask = 0;
186
187 if (!on) {
188 PKWR = 0;
189 return 0;
190 }
191
192 for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
193
194 gpio = pxa27x_pkwr_gpio[i];
195
196 if (gpio_desc[gpio].config & MFP_LPM_CAN_WAKEUP)
197 mask |= gpio_desc[gpio].mask;
198 }
199
200 PKWR = mask;
201 return 0;
202}
203
149static int __init pxa27x_mfp_init(void) 204static int __init pxa27x_mfp_init(void)
150{ 205{
151 int i, gpio; 206 int i, gpio;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 653a3b63d073..c486c3055cfb 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -26,6 +26,7 @@
26#include <asm/hardware.h> 26#include <asm/hardware.h>
27#include <asm/arch/irqs.h> 27#include <asm/arch/irqs.h>
28#include <asm/arch/pxa-regs.h> 28#include <asm/arch/pxa-regs.h>
29#include <asm/arch/mfp-pxa25x.h>
29#include <asm/arch/pm.h> 30#include <asm/arch/pm.h>
30#include <asm/arch/dma.h> 31#include <asm/arch/dma.h>
31 32
@@ -230,24 +231,10 @@ static inline void pxa25x_init_pm(void) {}
230static int pxa25x_set_wake(unsigned int irq, unsigned int on) 231static int pxa25x_set_wake(unsigned int irq, unsigned int on)
231{ 232{
232 int gpio = IRQ_TO_GPIO(irq); 233 int gpio = IRQ_TO_GPIO(irq);
233 uint32_t gpio_bit, mask = 0; 234 uint32_t mask = 0;
234 235
235 if (gpio >= 0 && gpio <= 15) { 236 if (gpio >= 0 && gpio < 85)
236 gpio_bit = GPIO_bit(gpio); 237 return gpio_set_wake(gpio, on);
237 mask = gpio_bit;
238 if (on) {
239 if (GRER(gpio) | gpio_bit)
240 PRER |= gpio_bit;
241 else
242 PRER &= ~gpio_bit;
243
244 if (GFER(gpio) | gpio_bit)
245 PFER |= gpio_bit;
246 else
247 PFER &= ~gpio_bit;
248 }
249 goto set_pwer;
250 }
251 238
252 if (irq == IRQ_RTCAlrm) { 239 if (irq == IRQ_RTCAlrm) {
253 mask = PWER_RTC; 240 mask = PWER_RTC;
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 87ade40865f1..b230af22ae05 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -23,6 +23,7 @@
23#include <asm/arch/irqs.h> 23#include <asm/arch/irqs.h>
24#include <asm/arch/pxa-regs.h> 24#include <asm/arch/pxa-regs.h>
25#include <asm/arch/pxa2xx-regs.h> 25#include <asm/arch/pxa2xx-regs.h>
26#include <asm/arch/mfp-pxa27x.h>
26#include <asm/arch/ohci.h> 27#include <asm/arch/ohci.h>
27#include <asm/arch/pm.h> 28#include <asm/arch/pm.h>
28#include <asm/arch/dma.h> 29#include <asm/arch/dma.h>
@@ -286,37 +287,16 @@ static inline void pxa27x_init_pm(void) {}
286/* PXA27x: Various gpios can issue wakeup events. This logic only 287/* PXA27x: Various gpios can issue wakeup events. This logic only
287 * handles the simple cases, not the WEMUX2 and WEMUX3 options 288 * handles the simple cases, not the WEMUX2 and WEMUX3 options
288 */ 289 */
289#define PXA27x_GPIO_NOWAKE_MASK \
290 ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
291#define WAKEMASK(gpio) \
292 (((gpio) <= 15) \
293 ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
294 : ((gpio == 35) ? (1 << 24) : 0))
295
296static int pxa27x_set_wake(unsigned int irq, unsigned int on) 290static int pxa27x_set_wake(unsigned int irq, unsigned int on)
297{ 291{
298 int gpio = IRQ_TO_GPIO(irq); 292 int gpio = IRQ_TO_GPIO(irq);
299 uint32_t mask; 293 uint32_t mask;
300 294
301 if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) { 295 if (gpio >= 0 && gpio < 128)
302 if (WAKEMASK(gpio) == 0) 296 return gpio_set_wake(gpio, on);
303 return -EINVAL;
304
305 mask = WAKEMASK(gpio);
306
307 if (on) {
308 if (GRER(gpio) | GPIO_bit(gpio))
309 PRER |= mask;
310 else
311 PRER &= ~mask;
312 297
313 if (GFER(gpio) | GPIO_bit(gpio)) 298 if (irq == IRQ_KEYPAD)
314 PFER |= mask; 299 return keypad_set_wake(on);
315 else
316 PFER &= ~mask;
317 }
318 goto set_pwer;
319 }
320 300
321 switch (irq) { 301 switch (irq) {
322 case IRQ_RTCAlrm: 302 case IRQ_RTCAlrm:
@@ -329,7 +309,6 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
329 return -EINVAL; 309 return -EINVAL;
330 } 310 }
331 311
332set_pwer:
333 if (on) 312 if (on)
334 PWER |= mask; 313 PWER |= mask;
335 else 314 else
diff --git a/include/asm-arm/arch-pxa/mfp-pxa27x.h b/include/asm-arm/arch-pxa/mfp-pxa27x.h
index 65dfaa9109f3..eb6eaa174f8d 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa27x.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa27x.h
@@ -428,4 +428,5 @@
428#define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2) 428#define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2)
429#define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW) 429#define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
430 430
431extern int keypad_set_wake(unsigned int on);
431#endif /* __ASM_ARCH_MFP_PXA27X_H */ 432#endif /* __ASM_ARCH_MFP_PXA27X_H */
diff --git a/include/asm-arm/arch-pxa/mfp-pxa2xx.h b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
index bec6acfcc8cf..db8d890d237c 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
@@ -24,13 +24,13 @@
24#define MFP_DIR_MASK (0x1 << 23) 24#define MFP_DIR_MASK (0x1 << 23)
25#define MFP_DIR(x) (((x) >> 23) & 0x1) 25#define MFP_DIR(x) (((x) >> 23) & 0x1)
26 26
27#define MFP_LPM_WAKEUP_ENABLE (0x1 << 24) 27#define MFP_LPM_CAN_WAKEUP (0x1 << 24)
28#define WAKEUP_ON_EDGE_RISE (MFP_LPM_WAKEUP_ENABLE | MFP_LPM_EDGE_RISE) 28#define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
29#define WAKEUP_ON_EDGE_FALL (MFP_LPM_WAKEUP_ENABLE | MFP_LPM_EDGE_FALL) 29#define WAKEUP_ON_EDGE_FALL (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL)
30#define WAKEUP_ON_EDGE_BOTH (MFP_LPM_WAKEUP_ENABLE | MFP_LPM_EDGE_BOTH) 30#define WAKEUP_ON_EDGE_BOTH (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH)
31 31
32/* specifically for enabling wakeup on keypad GPIOs */ 32/* specifically for enabling wakeup on keypad GPIOs */
33#define WAKEUP_ON_LEVEL_HIGH (MFP_LPM_WAKEUP_ENABLE) 33#define WAKEUP_ON_LEVEL_HIGH (MFP_LPM_CAN_WAKEUP)
34 34
35#define MFP_CFG_IN(pin, af) \ 35#define MFP_CFG_IN(pin, af) \
36 ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\ 36 ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\
@@ -128,4 +128,5 @@
128#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0) 128#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0)
129 129
130extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num); 130extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
131extern int gpio_set_wake(unsigned int gpio, unsigned int on);
131#endif /* __ASM_ARCH_MFP_PXA2XX_H */ 132#endif /* __ASM_ARCH_MFP_PXA2XX_H */