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; }
/* * cpu_pdn: * true = CPU dormant * false = CPU standby * pwrlevel: * 0 = AXI is off * 1 = AXI is 26M * pwake_time: * >= 0 = specific wakeup period */ wake_reason_t spm_go_to_sleep_dpidle(u32 spm_flags, u32 spm_data) { u32 sec = 0; u32 dpidle_timer_val = 0; u32 dpidle_wake_src = 0; int wd_ret; struct wake_status wakesta; unsigned long flags; struct mtk_irq_mask mask; struct wd_api *wd_api; static wake_reason_t last_wr = WR_NONE; struct pcm_desc *pcmdesc = __spm_dpidle.pcmdesc; struct pwr_ctrl *pwrctrl = __spm_dpidle.pwrctrl; /* backup original dpidle setting */ dpidle_timer_val = pwrctrl->timer_val; dpidle_wake_src = pwrctrl->wake_src; set_pwrctrl_pcm_flags(pwrctrl, spm_flags); #if SPM_PWAKE_EN sec = spm_get_wake_period(-1 /* FIXME */, last_wr); #endif pwrctrl->timer_val = sec * 32768; pwrctrl->wake_src = spm_get_sleep_wakesrc(); wd_ret = get_wd_api(&wd_api); if (!wd_ret) wd_api->wd_suspend_notify(); spin_lock_irqsave(&__spm_lock, flags); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(SPM_IRQ0_ID); mt_cirq_clone_gic(); mt_cirq_enable(); /* set PMIC WRAP table for deepidle power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_DEEPIDLE); spm_crit2("sleep_deepidle, sec = %u, wakesrc = 0x%x [%u]\n", sec, pwrctrl->wake_src, is_cpu_pdn(pwrctrl->pcm_flags)); __spm_reset_and_init_pcm(pcmdesc); __spm_kick_im_to_fetch(pcmdesc); if (request_uart_to_sleep()) { last_wr = WR_UART_BUSY; goto RESTORE_IRQ; } __spm_init_pcm_register(); __spm_init_event_vector(pcmdesc); __spm_set_power_control(pwrctrl); __spm_set_wakeup_event(pwrctrl); __spm_kick_pcm_to_run(pwrctrl); spm_dpidle_pre_process(); spm_trigger_wfi_for_dpidle(pwrctrl); spm_dpidle_post_process(); __spm_get_wakeup_status(&wakesta); __spm_clean_after_wakeup(); request_uart_to_wakeup(); last_wr = __spm_output_wake_reason(&wakesta, pcmdesc, true); RESTORE_IRQ: /* set PMIC WRAP table for normal power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_NORMAL); mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&__spm_lock, flags); if (!wd_ret) wd_api->wd_resume_notify(); /* restore original dpidle setting */ pwrctrl->timer_val = dpidle_timer_val; pwrctrl->wake_src = dpidle_wake_src; return last_wr; }
wake_reason_t spm_go_to_sleep(u32 spm_flags, u32 spm_data) { u32 sec = 0; int wd_ret; struct wake_status wakesta; unsigned long flags; struct mtk_irq_mask mask; struct wd_api *wd_api; static wake_reason_t last_wr = WR_NONE; struct pcm_desc *pcmdesc = __spm_suspend.pcmdesc; struct pwr_ctrl *pwrctrl = __spm_suspend.pwrctrl; struct spm_lp_scen *lpscen; lpscen = spm_check_talking_get_lpscen(&__spm_suspend, &spm_flags); pcmdesc = lpscen->pcmdesc; pwrctrl = lpscen->pwrctrl; set_pwrctrl_pcm_flags(pwrctrl, spm_flags); set_pwrctrl_pcm_data(pwrctrl, spm_data); #if SPM_PWAKE_EN sec = spm_get_wake_period(-1 /* FIXME */, last_wr); #endif pwrctrl->timer_val = sec * 32768; wd_ret = get_wd_api(&wd_api); if (!wd_ret) wd_api->wd_suspend_notify(); spm_suspend_pre_process(pwrctrl); spin_lock_irqsave(&__spm_lock, flags); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM_IRQ_ID); mt_cirq_clone_gic(); mt_cirq_enable(); spm_set_sysclk_settle(); spm_crit2("sec = %u, wakesrc = 0x%x (%u)(%u)\n", sec, pwrctrl->wake_src, is_cpu_pdn(pwrctrl->pcm_flags), is_infra_pdn(pwrctrl->pcm_flags)); if (request_uart_to_sleep()) { last_wr = WR_UART_BUSY; goto RESTORE_IRQ; } __spm_reset_and_init_pcm(pcmdesc); __spm_kick_im_to_fetch(pcmdesc); __spm_init_pcm_register(); __spm_init_event_vector(pcmdesc); __spm_set_power_control(pwrctrl); __spm_set_wakeup_event(pwrctrl); spm_kick_pcm_to_run(pwrctrl); #if 0 if (1 == spm_snapshot_golden_setting) { snapshot_golden_setting(__FUNCTION__, __LINE__); spm_snapshot_golden_setting = 2; } #endif spm_trigger_wfi_for_sleep(pwrctrl); __spm_get_wakeup_status(&wakesta); spm_clean_after_wakeup(); request_uart_to_wakeup(); last_wr = spm_output_wake_reason(&wakesta, pcmdesc); RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&__spm_lock, flags); spm_suspend_post_process(pwrctrl); if (!wd_ret) wd_api->wd_resume_notify(); return last_wr; }
/* * cpu_pdn: * true = CPU shutdown * false = CPU standby * infra_pdn: * true = INFRA/DDRPHY power down * false = keep INFRA/DDRPHY power * pwake_time: * >= 0 = specific wakeup period */ wake_reason_t spm_go_to_sleep(bool cpu_pdn, bool infra_pdn, int pwake_time) { u32 sec = 0; int wd_ret; wake_status_t wakesta; unsigned long flags; struct mtk_irq_mask mask; struct wd_api *wd_api; static wake_reason_t last_wr = WR_NONE; const pcm_desc_t *pcmdesc = &pcm_suspend; const bool pcmwdt_en = true; #if SPM_PWAKE_EN sec = spm_get_wake_period(pwake_time, last_wr); #endif wd_ret = get_wd_api(&wd_api); if (!wd_ret) wd_api->wd_suspend_notify(); spin_lock_irqsave(&spm_lock, flags); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM_IRQ_ID); mt_cirq_clone_gic(); mt_cirq_enable(); spm_set_sysclk_settle(); spm_crit2("sec = %u, wakesrc = 0x%x (%u)(%u)\n", sec, spm_sleep_wakesrc, cpu_pdn, infra_pdn); spm_reset_and_init_pcm(); spm_kick_im_to_fetch(pcmdesc); if (spm_request_uart_to_sleep()) { last_wr = WR_UART_BUSY; goto RESTORE_IRQ; } spm_init_pcm_register(); spm_init_event_vector(pcmdesc); spm_set_pwrctl_for_sleep(); spm_set_wakeup_event(sec * 32768, spm_sleep_wakesrc); spm_kick_pcm_to_run(cpu_pdn, infra_pdn, pcmwdt_en); spm_trigger_wfi_for_sleep(cpu_pdn, infra_pdn); spm_get_wakeup_status(&wakesta); spm_clean_after_wakeup(pcmwdt_en); last_wr = spm_output_wake_reason(&wakesta, false); RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&spm_lock, flags); //spm_go_to_normal(); /* included in pcm_suspend */ if (!wd_ret) wd_api->wd_resume_notify(); return last_wr; }