aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-pxa/mfp.c59
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
88static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) 89static 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
94void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) 100void 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 */
207static 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
218static 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
229static struct sysdev_class mfp_sysclass = {
230 set_kset_name("mfp"),
231 .suspend = pxa3xx_mfp_suspend,
232 .resume = pxa3xx_mfp_resume,
233};
234
235static struct sys_device mfp_device = {
236 .id = 0,
237 .cls = &mfp_sysclass,
238};
239
240static int __init mfp_init_devicefs(void)
241{
242 sysdev_class_register(&mfp_sysclass);
243 return sysdev_register(&mfp_device);
244}
245device_initcall(mfp_init_devicefs);
246#endif