wake_reason_t spm_go_to_sleep(void) { wake_status_t *wakesta; unsigned long flags,i; struct mtk_irq_mask mask; static wake_reason_t last_wr = WR_NONE; if(pcm_config_suspend.reserved & SPM_SUSPEND_GET_FGUAGE) pcm_config_suspend.timer_val_ms = spm_get_wake_period(last_wr)*1000; mtk_wdt_suspend(); spin_lock_irqsave(&spm_lock, flags); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM0_IRQ_ID); if (spm_init_pcm(&pcm_config_suspend)==false) goto RESTORE_IRQ; spm_kick_pcm(&pcm_config_suspend); snapshot_golden_setting(__FUNCTION__, __LINE__); spm_trigger_wfi(&pcm_config_suspend); wakesta = spm_get_wakeup_status(&pcm_config_suspend); last_wr = wakesta->wake_reason; spm_clean_after_wakeup(); RESTORE_IRQ: mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&spm_lock, flags); mtk_wdt_resume(); return last_wr; }
/* * pwrlevel: * 0: CPU standby + AP sleep => legacy sleep mode * 1: CPU dormant (L1/L2 sleep) + AP sleep * 2: CPU shutdown (L1/L2 power down) + AP sleep */ wake_reason_t sc_go_to_sleep(unsigned int pwrlevel) { u32 wakesrc, dvfscon, sec = 0; int i, r; unsigned long flags; struct mtk_irq_mask mask; static wake_reason_t last_wr = WR_NONE; sc_info2("pwrlevel = %u\n", pwrlevel); if (sc_pwake_en) sec = sc_get_wake_period(!!(last_wr != WR_SLP_TMR)); mtk_wdt_suspend(); spin_lock_irqsave(&sc_lock, flags); wakesrc = sc_wake_src; for (i = 0; i < NUM_WAKE_SRC; i++) { if (wakesrc & (1U << i)) { r = sc_enable_wake_irq(sc_wake_irq[i]); if (r) wakesrc &= ~(1U << i); } } mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SLEEP_IRQ_ID); /* to workaround DVFS issue due to CKDIV1 failure */ dvfscon = sc_read(SC_AP_DVFS_CON); //ckdiv1 = sc_read(TOP_CKDIV1); sc_write(SC_AP_DVFS_CON, dvfscon | 0x3); sc_write_sync(); sc_set_apmcu_pwrctl(pwrlevel); #ifdef CONFIG_MTK_SC_DEBUG /* bypass CSYSPWRUPREQ to avoid keeping SRCLKENA high */ sc_write(SC_CLK_CON, sc_read(SC_CLK_CON) | SC_CLK_CON_BYPASSDBG); sc_write_sync(); #endif last_wr = sc_enter_pause_mode(pwrlevel, sec, wakesrc); #ifdef CONFIG_MTK_SC_DEBUG /* restore SC_CLK_CON */ sc_write(SC_CLK_CON, sc_read(SC_CLK_CON) & ~SC_CLK_CON_BYPASSDBG); sc_write_sync(); #endif /* to workaround DVFS issue due to CKDIV1 failure */ //sc_write(TOP_CKDIV1, 0x00); //sc_write(TOP_CKDIV1, ckdiv1); sc_write(SC_AP_DVFS_CON, dvfscon); sc_write_sync(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&sc_lock, flags); mtk_wdt_resume(); return last_wr; }