aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */