#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
{
- if (mfp_configured(p) && p->mfpr_lpm != p->mfpr_run)
- mfpr_writel(p->mfpr_off, p->mfpr_lpm);
+ if (mfp_configured(p)) {
+ unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
+ if (mfpr_clr != p->mfpr_run)
+ mfpr_writel(p->mfpr_off, mfpr_clr);
+ if (p->mfpr_lpm != mfpr_clr)
+ mfpr_writel(p->mfpr_off, p->mfpr_lpm);
+ }
}
void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
mfp_table[i].config = -1;
}
+
+#ifdef CONFIG_PM
+/*
+ * Configure the MFPs appropriately for suspend/resume.
+ * FIXME: this should probably depend on which system state we're
+ * entering - for instance, we might not want to place MFP pins in
+ * a pull-down mode if they're an active low chip select, and we're
+ * just entering standby.
+ */
+static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+{
+ int pin;
+
+ for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+ struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+ __mfp_config_lpm(p);
+ }
+ return 0;
+}
+
+static int pxa3xx_mfp_resume(struct sys_device *d)
+{
+ int pin;
+
+ for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+ struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+ __mfp_config_run(p);
+ }
+ return 0;
+}
+
+static struct sysdev_class mfp_sysclass = {
+ set_kset_name("mfp"),
+ .suspend = pxa3xx_mfp_suspend,
+ .resume = pxa3xx_mfp_resume,
+};
+
+static struct sys_device mfp_device = {
+ .id = 0,
+ .cls = &mfp_sysclass,
+};
+
+static int __init mfp_init_devicefs(void)
+{
+ sysdev_class_register(&mfp_sysclass);
+ return sysdev_register(&mfp_device);
+}
+device_initcall(mfp_init_devicefs);
+#endif