*/ static int s3c_pm_enter(suspend_state_t state) { int tmp; static unsigned long regs_save[16]; /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); S3C_PMDBG("%s(%d)\n", __func__, state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); return -EINVAL; } //Apollo + s5p_pad_pdn_control(); s3c_irqwake_intmask = 0xFFDF; // key //Apollo - /* 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) */ //printk("s3c_irqwake_intmask = 0x%08x, s3c_irqwake_intallow = 0x%08x+++++++\n", s3c_irqwake_intmask, s3c_irqwake_intallow); //printk("s3c_irqwake_eintmask = 0x%08x, s3c_irqwake_eintallow = 0x%08x+++++++\n", s3c_irqwake_eintmask, s3c_irqwake_eintallow); if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR "%s: No wake-up sources!\n", __func__); printk(KERN_ERR "%s: Aborting sleep\n", __func__); return -EINVAL; } /* store the physical address of the register recovery block */ s3c_sleep_save_phys = virt_to_phys(regs_save); //Apollo + /* set flag for sleep mode idle2 flag is also reserved */ #define SLEEP_MODE 0 #define IDLE2_MODE 1 __raw_writel(SLEEP_MODE, S5P_INFORM1); //Apollo - S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); //Apollo + s3c_config_sleep_gpio(); //ÅäÖÃÐÝÃßʱ¸÷io״̬ //Apollo - /* set the irq configuration for wake */ s3c_pm_configure_extint(); //printk(KERN_INFO"sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); s3c_irqwake_intmask = 0xFFDF; s3c_pm_arch_prepare_irqs(); /* call cpu specific preparation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c_pm_check_store(); /* clear wakeup_stat register for next wakeup reason */ __raw_writel(__raw_readl(S5P_WAKEUP_STAT), S5P_WAKEUP_STAT); /* send the cpu to sleep... */ s3c_pm_arch_stop_clocks(); /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ pmstats->sleep_count++; pmstats->sleep_freq = __raw_readl(S5P_CLK_DIV0); s3c_cpu_save(regs_save); pmstats->wake_count++; pmstats->wake_freq = __raw_readl(S5P_CLK_DIV0); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); tmp = readl(S5P_WAKEUP_STAT); fiq_glue_resume(); local_fiq_enable(); s3c_pm_restore_core(); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); s5pv210_restore_eint_group(); s3c_pm_debug_init(); /* restore the system state */ if (pm_cpu_restore) pm_cpu_restore(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ // s3c_pm_debug_smdkled(1 << 1, 0); s3c_pm_check_restore(); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n");
/* s3c_pm_enter * * central control for sleep/resume process */ static int s3c_pm_enter(suspend_state_t state) { #ifndef USE_DMA_ALLOC static unsigned long regs_save[16]; #endif /* !USE_DMA_ALLOC */ unsigned int tmp, audiodomain_On; unsigned int gpio; /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); S3C_PMDBG("%s(%d)\n", __func__, state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); return -EINVAL; } // printk("[PM-1] EINT0(0x%02x), EINT1(0x%02x), EINT2(0x%02x), EINT3(0x%02x)\n", // __raw_readl(S5PV210_EINT0PEND), __raw_readl(S5PV210_EINT1PEND), // __raw_readl(S5PV210_EINT2PEND), __raw_readl(S5PV210_EINT3PEND)); s5p_pad_pdn_control(); /* 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) */ s3c_irqwake_intmask = 0xFFDD; // key || rtc_alarm if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR "%s: No wake-up sources!\n", __func__); printk(KERN_ERR "%s: Aborting sleep\n", __func__); return -EINVAL; } // If pmic INT occured while entering sleep mode, then return. if( __raw_readl(S5PV210_EINT0PEND) & 0x80 ) { printk(KERN_ERR "%s: Aborting sleep because pmic INT\n", __func__); return -EINVAL; } /* store the physical address of the register recovery block */ #ifndef USE_DMA_ALLOC s3c_sleep_save_phys = virt_to_phys(regs_save); #else __raw_writel(phy_regs_save, S5P_INFORM2); #endif /* !USE_DMA_ALLOC */ /* set flag for sleep mode idle2 flag is also reserved */ __raw_writel(SLEEP_MODE, S5P_INFORM1); if(HWREV >=11) { // 20110113 - dukho.kim : control power of moviNAND at PM and add 400ms delay for stabilization of moviNAND. gpio = readl(S5PV210_GPJ2DAT); writel(gpio & (~0x80), S5PV210_GPJ2DAT); mdelay(400); } S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); s3c_config_sleep_gpio(); /* set the irq configuration for wake */ s3c_pm_configure_extint(); S3C_PMDBG("sleep: irq wakeup masks: 0x%08lx, 0x%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); /* Set wake up sources */ s3c_pm_set_eint(7, 0x2); // PMIC INT s3c_pm_set_eint(8, 0x4); // DET_3.5 s3c_pm_set_eint(9, 0x3); // TA_nCHG, Rising edge s3c_pm_set_eint(11, 0x2); // OneDRAM INT #if defined (CONFIG_TARGET_LOCALE_EUR) || defined(CONFIG_TARGET_LOCALE_HKTW) || defined (CONFIG_TARGET_LOCALE_HKTW_FET) || defined(CONFIG_TARGET_LOCALE_VZW) || defined(CONFIG_TARGET_LOCALE_USAGSM) s3c_pm_set_eint(12, 0x4); // SEND_END #endif s3c_pm_set_eint(14, 0x4); // FUEL_ALRT s3c_pm_set_eint(15, 0x2); // PHONE_ACTIVE s3c_pm_set_eint(20, 0x4); // WLAN s3c_pm_set_eint(21, 0x4); // BT s3c_pm_set_eint(22, 0x2); // Power Key s3c_pm_set_eint(23, 0x2); // Jack_nINT s3c_pm_set_eint(24, 0x4); // VOL_UP s3c_pm_set_eint(25, 0x4); // VOL_DN #ifndef CONFIG_TARGET_LOCALE_VZW s3c_pm_set_eint(27, 0x4); // SIM #endif s3c_pm_set_eint(28, 0x4); // T_FLASH #if defined (CONFIG_TARGET_LOCALE_EUR) || defined(CONFIG_TARGET_LOCALE_HKTW) || defined (CONFIG_TARGET_LOCALE_HKTW_FET) || defined(CONFIG_TARGET_LOCALE_VZW) || defined(CONFIG_TARGET_LOCALE_USAGSM) if(HWREV <= 0x4) s3c_pm_set_eint(29, 0x2); // HOME Key #endif #ifdef CONFIG_TARGET_LOCALE_KOR s3c_pm_set_eint(30, 0x4); // SEND_END #endif s3c_pm_set_eint(5, 0x4); //dock s3c_pm_set_eint(29, 0x4); //accessory //s3c_pm_arch_prepare_irqs(); /* call cpu specific preparation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c_pm_check_store(); __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK); //0xFFDD:key, RTC_ALARM /*clear for next wakeup*/ tmp = __raw_readl(S5P_WAKEUP_STAT); __raw_writel(tmp, S5P_WAKEUP_STAT); //s3c_config_sleep_gpio(); // Enable PS_HOLD pin to avoid reset failure */ __raw_writel((0x5 << 12 | 0x1<<9 | 0x1<<8 | 0x1<<0),S5P_PSHOLD_CONTROL); /* send the cpu to sleep... */ s3c_pm_arch_stop_clocks(); /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ s3c_cpu_save(regs_save); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); /* restore the system state */ s3c_pm_restore_core(); /*Reset the uart registers*/ __raw_writel(0x0, S3C24XX_VA_UART3+S3C2410_UCON); __raw_writel(0xf, S3C24XX_VA_UART3+S5P_UINTM); __raw_writel(0xf, S3C24XX_VA_UART3+S5P_UINTSP); __raw_writel(0xf, S3C24XX_VA_UART3+S5P_UINTP); __raw_writel(0x0, S3C24XX_VA_UART2+S3C2410_UCON); __raw_writel(0xf, S3C24XX_VA_UART2+S5P_UINTM); __raw_writel(0xf, S3C24XX_VA_UART2+S5P_UINTSP); __raw_writel(0xf, S3C24XX_VA_UART2+S5P_UINTP); __raw_writel(0x0, S3C24XX_VA_UART1+S3C2410_UCON); __raw_writel(0xf, S3C24XX_VA_UART1+S5P_UINTM); __raw_writel(0xf, S3C24XX_VA_UART1+S5P_UINTSP); __raw_writel(0xf, S3C24XX_VA_UART1+S5P_UINTP); __raw_writel(0x0, S3C24XX_VA_UART0+S3C2410_UCON); __raw_writel(0xf, S3C24XX_VA_UART0+S5P_UINTM); __raw_writel(0xf, S3C24XX_VA_UART0+S5P_UINTSP); __raw_writel(0xf, S3C24XX_VA_UART0+S5P_UINTP); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); tmp = readl(S5P_NORMAL_CFG); if(!(tmp & S5PC110_POWER_DOMAIN_AUDIO)) { tmp = tmp | S5PC110_POWER_DOMAIN_AUDIO; writel(tmp , S5P_NORMAL_CFG); audiodomain_On = 1; } else { audiodomain_On = 0; } /* enable gpio, uart, mmc */ tmp = __raw_readl(S5P_OTHERS); tmp |= (1<<31) | (1<<30) | (1<<28) | (1<<29); __raw_writel(tmp, S5P_OTHERS); tmp = readl(S5P_NORMAL_CFG); if (audiodomain_On) { tmp = tmp & ~S5PC110_POWER_DOMAIN_AUDIO; writel(tmp , S5P_NORMAL_CFG); } s3c_pm_debug_init(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); /*clear for next wakeup*/ tmp = __raw_readl(S5P_WAKEUP_STAT); printk("\n[PM] S5P_WAKEUP_STAT = 0x%08x\n", tmp); __raw_writel(tmp, S5P_WAKEUP_STAT); #if defined(CONFIG_MACH_S5PC110_P1) // Set wakeup stat s3c_pm_set_wakeup_stat(); #endif // CONFIG_MACH_S5PC110_P1 //s3c_pm_clear_eint(21); //s3c_pm_clear_eint(22); //S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); //printk("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ //s3c_pm_debug_smdkled(1 << 1, 0); s3c_pm_check_restore(); printk("[PM-2] EINT0(0x%02x), EINT1(0x%02x), EINT2(0x%02x), EINT3(0x%02x)\n", __raw_readl(S5PV210_EINT0PEND), __raw_readl(S5PV210_EINT1PEND), __raw_readl(S5PV210_EINT2PEND), __raw_readl(S5PV210_EINT3PEND)); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n"); return 0; }