aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/mfp-pxa2xx.c
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 /arch/arm/mach-pxa/mfp-pxa2xx.c
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>
Diffstat (limited to 'arch/arm/mach-pxa/mfp-pxa2xx.c')
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c93
1 files changed, 74 insertions, 19 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;