static int s3c2410_pm_enter(suspend_state_t state) { unsigned long regs_save[16]; unsigned long tmp; /* ensure the debug is initialised (if enabled) */ s3c2410_pm_debug_init(); DBG("s3c2410_pm_enter(%d)\n", state); if (state != PM_SUSPEND_MEM) { printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); return -EINVAL; } /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) */ if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR PFX "No sources enabled for wake-up!\n"); printk(KERN_ERR PFX "Aborting sleep\n"); return -EINVAL; } /* prepare check area if configured */ s3c2410_pm_check_prepare(); /* store the physical address of the register recovery block */ s3c2410_sleep_save_phys = virt_to_phys(regs_save); DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys); /* ensure at least GESTATUS3 has the resume address */ __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3); DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3)); DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4)); /* save all necessary core registers not covered by the drivers */ s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); /* set the irq configuration for wake */ s3c2410_pm_configure_extint(); DBG("sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK); __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK); /* ack any outstanding external interrupts before we go to sleep */ __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); /* flush cache back to ram */ arm920_flush_kern_cache_all(); s3c2410_pm_check_store(); // need to make some form of time-delta /* send the cpu to sleep... */ __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */ s3c2410_cpu_suspend(regs_save); /* unset the return-from-sleep flag, to ensure reset */ tmp = __raw_readl(S3C2410_GSTATUS2); tmp &= S3C2410_GSTATUS2_OFFRESET; __raw_writel(tmp, S3C2410_GSTATUS2); /* restore the system state */ s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s3c2410_pm_debug_init(); /* check what irq (if any) restored the system */ DBG("post sleep: IRQs 0x%08x, 0x%08x\n", __raw_readl(S3C2410_SRCPND), __raw_readl(S3C2410_EINTPEND)); s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND), s3c_irqwake_intmask); s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND), s3c_irqwake_eintmask); DBG("post sleep, preparing to return\n"); s3c2410_pm_check_restore(); /* ok, let's return from sleep */ DBG("S3C2410 PM Resume (post-restore)\n"); return 0; }
static int s3c2410_pm_enter(suspend_state_t state) { unsigned long regs_save[16]; /* ensure the debug is initialised (if enabled) */ s3c2410_pm_debug_init(); DBG("s3c2410_pm_enter(%d)\n", state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR PFX "error: no cpu sleep functions set\n"); return -EINVAL; } /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) */ if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR PFX "No sources enabled for wake-up!\n"); printk(KERN_ERR PFX "Aborting sleep\n"); return -EINVAL; } /* prepare check area if configured */ s3c2410_pm_check_prepare(); /* store the physical address of the register recovery block */ s3c2410_sleep_save_phys = virt_to_phys(regs_save); DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); /* set the irq configuration for wake */ s3c2410_pm_configure_extint(); DBG("sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK); __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK); /* ack any outstanding external interrupts before we go to sleep */ __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND); __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND); /* call cpu specific preparation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c2410_pm_check_store(); /* send the cpu to sleep... */ __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */ /* s3c2410_cpu_save will also act as our return point from when * we resume as it saves its own register state, so use the return * code to differentiate return from save and return from sleep */ if (s3c2410_cpu_save(regs_save) == 0) { flush_cache_all(); pm_cpu_sleep(); } /* restore the cpu state */ cpu_init(); /* restore the system state */ s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s3c2410_pm_debug_init(); /* check what irq (if any) restored the system */ DBG("post sleep: IRQs 0x%08x, 0x%08x\n", __raw_readl(S3C2410_SRCPND), __raw_readl(S3C2410_EINTPEND)); s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND), s3c_irqwake_intmask); s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND), s3c_irqwake_eintmask); DBG("post sleep, preparing to return\n"); s3c2410_pm_check_restore(); /* ok, let's return from sleep */ DBG("S3C2410 PM Resume (post-restore)\n"); return 0; }