diff options
author | eric miao <eric.miao@marvell.com> | 2008-03-10 21:46:28 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-04-19 06:29:05 -0400 |
commit | c0a596d6a138ea281bed4ff3018c07c45dd245a2 (patch) | |
tree | ab3c25663433bf8c3f16026d969f9722d4ecff92 | |
parent | 9b02b2df0099c083ea40ba8c7068e3dcbe381302 (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.c | 93 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 31 | ||||
-rw-r--r-- | include/asm-arm/arch-pxa/mfp-pxa27x.h | 1 | ||||
-rw-r--r-- | include/asm-arm/arch-pxa/mfp-pxa2xx.h | 11 |
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 | ||
31 | static struct { | 31 | struct 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 | |||
39 | static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1]; | ||
38 | 40 | ||
39 | static inline int __mfp_config_gpio(unsigned gpio, unsigned long c) | 41 | static 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 | ||
118 | int 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 |
124 | static int __init pxa25x_mfp_init(void) | 158 | static 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 |
144 | static int pxa27x_pkwr_gpio[] __initdata = { | 178 | static 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 | ||
183 | int 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 | |||
149 | static int __init pxa27x_mfp_init(void) | 204 | static 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) {} | |||
230 | static int pxa25x_set_wake(unsigned int irq, unsigned int on) | 231 | static 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 | |||
296 | static int pxa27x_set_wake(unsigned int irq, unsigned int on) | 290 | static 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 | ||
332 | set_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 | ||
431 | extern 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 | ||
130 | extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num); | 130 | extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num); |
131 | extern int gpio_set_wake(unsigned int gpio, unsigned int on); | ||
131 | #endif /* __ASM_ARCH_MFP_PXA2XX_H */ | 132 | #endif /* __ASM_ARCH_MFP_PXA2XX_H */ |