diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-01-08 10:12:22 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-26 10:07:56 -0500 |
commit | d4fc858f9cfec5200a957c305d61ffc28c5d7796 (patch) | |
tree | 489836868e789f248cbff692d0403b6c590597dd /arch/arm | |
parent | 7f7c8a619253c83cf3b1071df3b001811d0c1a6c (diff) |
[ARM] pxa: program MFPs for low power mode when suspending
Hook the MFP code into the power management code so that the MFPs can
be reconfigured when suspending and resuming. However, note the FIXME
- low power mode MFP configuration may depend on the system state being
entered.
Also note that we have to clear any detected edge events prior to
entering a low power mode - otherwise we immediately wake up.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/mfp.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c index c66b1cd7df64..ec1b2d8f61c4 100644 --- a/arch/arm/mach-pxa/mfp.c +++ b/arch/arm/mach-pxa/mfp.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/sysdev.h> | ||
20 | 21 | ||
21 | #include <asm/hardware.h> | 22 | #include <asm/hardware.h> |
22 | #include <asm/arch/mfp.h> | 23 | #include <asm/arch/mfp.h> |
@@ -87,8 +88,13 @@ static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p) | |||
87 | 88 | ||
88 | static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) | 89 | static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) |
89 | { | 90 | { |
90 | if (mfp_configured(p) && p->mfpr_lpm != p->mfpr_run) | 91 | if (mfp_configured(p)) { |
91 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | 92 | unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; |
93 | if (mfpr_clr != p->mfpr_run) | ||
94 | mfpr_writel(p->mfpr_off, mfpr_clr); | ||
95 | if (p->mfpr_lpm != mfpr_clr) | ||
96 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | ||
97 | } | ||
92 | } | 98 | } |
93 | 99 | ||
94 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) | 100 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) |
@@ -189,3 +195,52 @@ void __init pxa3xx_init_mfp(void) | |||
189 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) | 195 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) |
190 | mfp_table[i].config = -1; | 196 | mfp_table[i].config = -1; |
191 | } | 197 | } |
198 | |||
199 | #ifdef CONFIG_PM | ||
200 | /* | ||
201 | * Configure the MFPs appropriately for suspend/resume. | ||
202 | * FIXME: this should probably depend on which system state we're | ||
203 | * entering - for instance, we might not want to place MFP pins in | ||
204 | * a pull-down mode if they're an active low chip select, and we're | ||
205 | * just entering standby. | ||
206 | */ | ||
207 | static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) | ||
208 | { | ||
209 | int pin; | ||
210 | |||
211 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
212 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
213 | __mfp_config_lpm(p); | ||
214 | } | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int pxa3xx_mfp_resume(struct sys_device *d) | ||
219 | { | ||
220 | int pin; | ||
221 | |||
222 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
223 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
224 | __mfp_config_run(p); | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static struct sysdev_class mfp_sysclass = { | ||
230 | set_kset_name("mfp"), | ||
231 | .suspend = pxa3xx_mfp_suspend, | ||
232 | .resume = pxa3xx_mfp_resume, | ||
233 | }; | ||
234 | |||
235 | static struct sys_device mfp_device = { | ||
236 | .id = 0, | ||
237 | .cls = &mfp_sysclass, | ||
238 | }; | ||
239 | |||
240 | static int __init mfp_init_devicefs(void) | ||
241 | { | ||
242 | sysdev_class_register(&mfp_sysclass); | ||
243 | return sysdev_register(&mfp_device); | ||
244 | } | ||
245 | device_initcall(mfp_init_devicefs); | ||
246 | #endif | ||