0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/suspend.h>
0016 #include <linux/errno.h>
0017 #include <linux/slab.h>
0018
0019 #include "pm.h"
0020
0021 struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
0022 static unsigned long *sleep_save;
0023
0024 int pxa_pm_enter(suspend_state_t state)
0025 {
0026 unsigned long sleep_save_checksum = 0, checksum = 0;
0027 int i;
0028
0029 #ifdef CONFIG_IWMMXT
0030
0031 if (elf_hwcap & HWCAP_IWMMXT)
0032 iwmmxt_task_disable(NULL);
0033 #endif
0034
0035
0036 if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->save) {
0037 pxa_cpu_pm_fns->save(sleep_save);
0038
0039 for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
0040 sleep_save_checksum += sleep_save[i];
0041 }
0042
0043
0044 pxa_cpu_pm_fns->enter(state);
0045
0046 if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {
0047
0048 for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
0049 checksum += sleep_save[i];
0050
0051
0052 if (checksum != sleep_save_checksum) {
0053
0054 lubbock_set_hexled(0xbadbadc5);
0055
0056 while (1)
0057 pxa_cpu_pm_fns->enter(state);
0058 }
0059 pxa_cpu_pm_fns->restore(sleep_save);
0060 }
0061
0062 pr_debug("*** made it back from resume\n");
0063
0064 return 0;
0065 }
0066
0067 EXPORT_SYMBOL_GPL(pxa_pm_enter);
0068
0069 static int pxa_pm_valid(suspend_state_t state)
0070 {
0071 if (pxa_cpu_pm_fns)
0072 return pxa_cpu_pm_fns->valid(state);
0073
0074 return -EINVAL;
0075 }
0076
0077 int pxa_pm_prepare(void)
0078 {
0079 int ret = 0;
0080
0081 if (pxa_cpu_pm_fns && pxa_cpu_pm_fns->prepare)
0082 ret = pxa_cpu_pm_fns->prepare();
0083
0084 return ret;
0085 }
0086
0087 void pxa_pm_finish(void)
0088 {
0089 if (pxa_cpu_pm_fns && pxa_cpu_pm_fns->finish)
0090 pxa_cpu_pm_fns->finish();
0091 }
0092
0093 static const struct platform_suspend_ops pxa_pm_ops = {
0094 .valid = pxa_pm_valid,
0095 .enter = pxa_pm_enter,
0096 .prepare = pxa_pm_prepare,
0097 .finish = pxa_pm_finish,
0098 };
0099
0100 static int __init pxa_pm_init(void)
0101 {
0102 if (!pxa_cpu_pm_fns) {
0103 printk(KERN_ERR "no valid pxa_cpu_pm_fns defined\n");
0104 return -EINVAL;
0105 }
0106
0107 sleep_save = kmalloc_array(pxa_cpu_pm_fns->save_count,
0108 sizeof(*sleep_save),
0109 GFP_KERNEL);
0110 if (!sleep_save)
0111 return -ENOMEM;
0112
0113 suspend_set_ops(&pxa_pm_ops);
0114 return 0;
0115 }
0116
0117 device_initcall(pxa_pm_init);