/* * Suspend */ int s3cfb_suspend(struct platform_device *dev, pm_message_t state) { struct fb_info *fbinfo = platform_get_drvdata(dev); s3cfb_info_t *info = fbinfo->par; s3cfb_stop_lcd(); #if defined(CONFIG_CPU_S5P6440) s5p6440_pm_do_save(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save)); #else s5pc1xx_pm_do_save(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save)); #endif /* sleep before disabling the clock, we need to ensure * the LCD DMA engine is not going to get back on the bus * before the clock goes off again (bjd) */ msleep(1); clk_disable(info->clk); return 0; }
static int s5pc1xx_pm_enter(suspend_state_t state) { unsigned long regs_save[16]; unsigned int tmp; /* ensure the debug is initialised (if enabled) */ DBG("s5pc1xx_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; } /* store the physical address of the register recovery block */ s5pc100_sleep_save_phys = virt_to_phys(regs_save); DBG("s5pc1xx_sleep_save_phys=0x%08lx\n", s5pc100_sleep_save_phys); s5pc1xx_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); s5pc1xx_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); s5pc1xx_pm_do_save(core_save, ARRAY_SIZE(core_save)); s5pc1xx_pm_do_save(sromc_save, ARRAY_SIZE(sromc_save)); s5pc1xx_pm_do_save(nand_save, ARRAY_SIZE(nand_save)); s5pc1xx_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); s5pc1xx_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); /* ensure INF_REG0 has the resume address */ __raw_writel(virt_to_phys(s5pc100_cpu_resume), S5P_INFORM0); /* call cpu specific preperation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); /* send the cpu to sleep... */ __raw_writel(0xffffffff, S5PC100_VIC0REG(VIC_INT_ENABLE_CLEAR)); __raw_writel(0xffffffff, S5PC100_VIC1REG(VIC_INT_ENABLE_CLEAR)); __raw_writel(0xffffffff, S5PC100_VIC2REG(VIC_INT_ENABLE_CLEAR)); __raw_writel(0xffffffff, S5PC100_VIC0REG(VIC_INT_SOFT_CLEAR)); __raw_writel(0xffffffff, S5PC100_VIC1REG(VIC_INT_SOFT_CLEAR)); __raw_writel(0xffffffff, S5PC100_VIC2REG(VIC_INT_SOFT_CLEAR)); /* Mask all wake up source */ tmp = __raw_readl(S5P_PWR_CFG); tmp &= ~(0x1 << 7); tmp |= (0x7ff << 8); /* unmask alarm wakeup source */ tmp &= ~(0x1 << 10); /* unmask keypad wakeup source */ tmp &= ~(0x1 << 8); __raw_writel(tmp , S5P_PWR_CFG); __raw_writel(0xffffffff , S5P_EINT_WAKEUP_MASK); /* Wake up source setting */ s5pc1xx_pm_configure_extint(); /* : USB Power Control */ /* - USB PHY Disable */ /* - Make USB Tranceiver PAD to Suspend */ tmp = __raw_readl(S5P_OTHERS); tmp &= ~(1<<16); /* USB Signal Mask Clear */ __raw_writel(tmp, S5P_OTHERS); tmp = __raw_readl(S5PC1XX_UHOST); tmp |= (1<<0); __raw_writel(tmp, S5PC1XX_UHOST); #ifdef CONFIG_S5P_DEEP_IDLE_TEST __raw_writel(((0x1 << 0) | (0x1a0 << 16)) ,S5P_CLAMP_STABLE); #endif /* Set WFI instruction to SLEEP mode */ tmp = __raw_readl(S5P_PWR_CFG); tmp &= S5P_CFG_WFI_CLEAN; #ifdef CONFIG_S5P_DEEP_IDLE_TEST tmp &= ~(0x1f << 27); tmp |= S5P_CFG_WFI_DEEPIDLE | (1 << 31) | (0xbff << 7) | (1 << 29); tmp &= ~(1<<17); DBG("Deep Idle mode\n"); #else tmp |= (S5P_CFG_WFI_SLEEP); printk("normal sleep mode\n"); #endif __raw_writel(tmp, S5P_PWR_CFG); /* Clear WAKEUP_STAT register for next wakeup */ tmp = __raw_readl(S5P_WAKEUP_STAT); __raw_writel(tmp, S5P_WAKEUP_STAT); /* Set Power Stable Count */ tmp = __raw_readl(S5P_OTHERS); tmp &=~(1 << S5P_OTHER_STA_TYPE); tmp |= (STA_TYPE_SFR << S5P_OTHER_STA_TYPE); __raw_writel(tmp , S5P_OTHERS); __raw_writel(((S5P_PWR_STABLE_COUNT << S5P_PWR_STA_CNT) | (1 << S5P_PWR_STA_EXP_SCALE)), S5P_PWR_STABLE); /* Set Syscon Interrupt */ tmp = __raw_readl(S5P_OTHERS); tmp |= (1 << S5P_OTHER_SYS_INT); __raw_writel(tmp, S5P_OTHERS); #ifndef CONFIG_S5P_DEEP_IDLE_TEST tmp = __raw_readl(S5P_SLEEP_CFG); tmp &= ~(1 << 0); __raw_writel(tmp, S5P_SLEEP_CFG); #endif /* s5pc1xx_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 (s5pc100_cpu_save(regs_save) == 0) { flush_cache_all(); /* This function for Chip bug on EVT0 */ pm_cpu_sleep(); } /* restore the cpu state */ cpu_init(); /* MTC IO OFF | MTC IO SD-MMC OFF | USB Phy Enable */ tmp = __raw_readl(S5P_OTHERS); tmp |= (1<<31); __raw_writel(tmp, S5P_OTHERS); tmp = __raw_readl(S5P_OTHERS); tmp |= ((1<<22)|(1<<16)); __raw_writel(tmp, S5P_OTHERS); tmp = __raw_readl(S5PC1XX_UHOST); tmp &= ~(1<<0); __raw_writel(tmp, S5PC1XX_UHOST); s5pc1xx_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s5pc1xx_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); s5pc1xx_pm_do_restore(core_save, ARRAY_SIZE(core_save)); s5pc1xx_pm_do_restore(sromc_save, ARRAY_SIZE(sromc_save)); s5pc1xx_pm_do_restore(nand_save, ARRAY_SIZE(nand_save)); s5pc1xx_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s5pc1xx_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); tmp = readl(weint_base + S5P_APM_WEINT1_PEND); writel(tmp , weint_base + S5P_APM_WEINT1_PEND); DBG("post sleep, preparing to return\n"); s5pc1xx_pm_check_restore(); #ifdef CONFIG_S5P_DEEP_IDLE_TEST tmp = __raw_readl(S5P_OTHERS); tmp |= (1<<30); __raw_writel(tmp, S5P_OTHERS); #endif /* ok, let's return from sleep */ DBG("S3C6410 PM Resume (post-restore)\n"); return 0; }