static int s3c6410_pm_wake(suspend_state_t state) { if (bml_resume_fp) bml_resume_fp(NULL, 0); return 0; }
static int s3c6410_pm_enter(suspend_state_t state) { unsigned long regs_save[16]; unsigned int tmp; unsigned int wakeup_stat = 0x0; unsigned int eint0pend = 0x0; /* ensure the debug is initialised (if enabled) */ DBG("s3c6410_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; } /* prepare check area if configured */ s3c6410_pm_check_prepare(); /* store the physical address of the register recovery block */ s3c6410_sleep_save_phys = virt_to_phys(regs_save); DBG("s3c6410_sleep_save_phys=0x%08lx\n", s3c6410_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c6410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); s3c6410_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); s3c6410_pm_do_save(core_save, ARRAY_SIZE(core_save)); s3c6410_pm_do_save(sromc_save, ARRAY_SIZE(sromc_save)); s3c6410_pm_do_save(onenand_save, ARRAY_SIZE(onenand_save)); s3c6410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); /* ensure INF_REG0 has the resume address */ __raw_writel(virt_to_phys(s3c6410_cpu_resume), S3C_INFORM0); /* set the irq configuration for wake */ s3c6410_pm_configure_extint(); /* call cpu specific preperation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c6410_pm_check_store(); s3c_config_sleep_gpio(); tmp = __raw_readl(S3C64XX_SPCONSLP); tmp &= ~(0x3 << 12); __raw_writel(tmp | (0x1 << 12), S3C64XX_SPCONSLP); /* send the cpu to sleep... */ __raw_writel(0xffffffff, S3C64XX_VIC0INTENCLEAR); __raw_writel(0xffffffff, S3C64XX_VIC1INTENCLEAR); __raw_writel(0xffffffff, S3C64XX_VIC0SOFTINTCLEAR); __raw_writel(0xffffffff, S3C64XX_VIC1SOFTINTCLEAR); /* Unmask clock gating and block power turn on */ __raw_writel(0x43E00041, S3C_HCLK_GATE); __raw_writel(0xF2040000, S3C_PCLK_GATE); __raw_writel(0x80000011, S3C_SCLK_GATE); __raw_writel(0x00000000, S3C_MEM0_CLK_GATE); __raw_writel(0x1, S3C_OSC_STABLE); __raw_writel(0x3, S3C_PWR_STABLE); /* Set WFI instruction to SLEEP mode */ tmp = __raw_readl(S3C_PWR_CFG); tmp &= ~(0x3<<5); tmp |= (0x3<<5); __raw_writel(tmp, S3C_PWR_CFG); tmp = __raw_readl(S3C_SLEEP_CFG); tmp &= ~(0x61<<0); __raw_writel(tmp, S3C_SLEEP_CFG); __raw_writel(0x2, S3C64XX_SLPEN); /* Clear WAKEUP_STAT register for next wakeup -jc.lee */ /* If this register do not be cleared, Wakeup will be failed */ __raw_writel(__raw_readl(S3C_WAKEUP_STAT), S3C_WAKEUP_STAT); /* s3c6410_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 (s3c6410_cpu_save(regs_save) == 0) { flush_cache_all(); pm_cpu_sleep(); } /* restore the cpu state */ cpu_init(); __raw_writel(s3c_eint_mask_val, S3C_EINT_MASK); /* restore the system state */ s3c6410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); s3c6410_pm_do_restore(sromc_save, ARRAY_SIZE(sromc_save)); s3c6410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s3c6410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); s3c6410_pm_do_restore(onenand_save, ARRAY_SIZE(onenand_save)); s3c6410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); __raw_writel(0x0, S3C64XX_SLPEN); wakeup_stat = __raw_readl(S3C_WAKEUP_STAT); eint0pend = __raw_readl(S3C64XX_EINT0PEND); __raw_writel(eint0pend, S3C64XX_EINT0PEND); DBG("post sleep, preparing to return\n"); s3c6410_pm_check_restore(); extra_eint0pend = eint0pend; pr_info("%s: WAKEUP_STAT(0x%08x), EINT0PEND(0x%08x)\n", __func__, wakeup_stat, eint0pend); s3c_config_wakeup_gpio(); if (bml_resume_fp) bml_resume_fp(NULL, 0); /* ok, let's return from sleep */ DBG("S3C6410 PM Resume (post-restore)\n"); return 0; }