diff options
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 | ||