0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/types.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/list.h>
0012 #include <linux/timer.h>
0013 #include <linux/init.h>
0014 #include <linux/device.h>
0015 #include <linux/syscore_ops.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/io.h>
0018
0019 #include <asm/cacheflush.h>
0020 #include <asm/irq.h>
0021
0022 #include "irqs.h"
0023 #include "regs-gpio.h"
0024
0025 #include "cpu.h"
0026 #include "pm.h"
0027 #include "wakeup-mask.h"
0028
0029 #include "regs-dsc-s3c24xx.h"
0030 #include "s3c2412-power.h"
0031
0032 extern void s3c2412_sleep_enter(void);
0033
0034 static int s3c2412_cpu_suspend(unsigned long arg)
0035 {
0036 unsigned long tmp;
0037
0038
0039
0040 tmp = __raw_readl(S3C2412_PWRCFG);
0041 tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
0042 __raw_writel(tmp, S3C2412_PWRCFG);
0043
0044 s3c2412_sleep_enter();
0045
0046 pr_info("Failed to suspend the system\n");
0047 return 1;
0048 }
0049
0050
0051 static const struct samsung_wakeup_mask wake_irqs[] = {
0052 { .irq = IRQ_RTC, .bit = S3C2412_PWRCFG_RTC_MASKIRQ, },
0053 };
0054
0055 static void s3c2412_pm_prepare(void)
0056 {
0057 samsung_sync_wakemask(S3C2412_PWRCFG,
0058 wake_irqs, ARRAY_SIZE(wake_irqs));
0059 }
0060
0061 static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
0062 {
0063 pm_cpu_prep = s3c2412_pm_prepare;
0064 pm_cpu_sleep = s3c2412_cpu_suspend;
0065
0066 return 0;
0067 }
0068
0069 static struct sleep_save s3c2412_sleep[] = {
0070 SAVE_ITEM(S3C2412_DSC0),
0071 SAVE_ITEM(S3C2412_DSC1),
0072 SAVE_ITEM(S3C2413_GPJDAT),
0073 SAVE_ITEM(S3C2413_GPJCON),
0074 SAVE_ITEM(S3C2413_GPJUP),
0075
0076
0077
0078 SAVE_ITEM(S3C2412_PWRCFG),
0079
0080
0081
0082
0083 SAVE_ITEM(S3C2412_GPBSLPCON),
0084 SAVE_ITEM(S3C2412_GPCSLPCON),
0085 SAVE_ITEM(S3C2412_GPDSLPCON),
0086 SAVE_ITEM(S3C2412_GPFSLPCON),
0087 SAVE_ITEM(S3C2412_GPGSLPCON),
0088 SAVE_ITEM(S3C2412_GPHSLPCON),
0089 SAVE_ITEM(S3C2413_GPJSLPCON),
0090 };
0091
0092 static struct subsys_interface s3c2412_pm_interface = {
0093 .name = "s3c2412_pm",
0094 .subsys = &s3c2412_subsys,
0095 .add_dev = s3c2412_pm_add,
0096 };
0097
0098 static __init int s3c2412_pm_init(void)
0099 {
0100 return subsys_interface_register(&s3c2412_pm_interface);
0101 }
0102
0103 arch_initcall(s3c2412_pm_init);
0104
0105 static int s3c2412_pm_suspend(void)
0106 {
0107 s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
0108 return 0;
0109 }
0110
0111 static void s3c2412_pm_resume(void)
0112 {
0113 unsigned long tmp;
0114
0115 tmp = __raw_readl(S3C2412_PWRCFG);
0116 tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
0117 tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
0118 __raw_writel(tmp, S3C2412_PWRCFG);
0119
0120 s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
0121 }
0122
0123 struct syscore_ops s3c2412_pm_syscore_ops = {
0124 .suspend = s3c2412_pm_suspend,
0125 .resume = s3c2412_pm_resume,
0126 };