static inline int dpidle_handler(int cpu) { int ret = 0; if (idle_switch[IDLE_TYPE_DP]) { #ifdef SPM_DEEPIDLE_PROFILE_TIME gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[0]); #endif if (dpidle_can_enter()) { dpidle_pre_handler(); spm_go_to_dpidle(slp_spm_deepidle_flags, 0); dpidle_post_handler(); ret = 1; #ifdef CONFIG_SMP idle_ver("DP:timer_left=%d, timer_left2=%d, delta=%d\n", dpidle_timer_left, dpidle_timer_left2, dpidle_timer_left-dpidle_timer_left2); #else idle_ver("DP:timer_left=%d, timer_left2=%d, delta=%d, timeout val=%d\n", dpidle_timer_left, dpidle_timer_left2, dpidle_timer_left2-dpidle_timer_left,dpidle_timer_cmp-dpidle_timer_left); #endif #ifdef SPM_DEEPIDLE_PROFILE_TIME gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[3]); idle_ver("1:%u, 2:%u, 3:%u, 4:%u\n", dpidle_profile[0], dpidle_profile[1], dpidle_profile[2],dpidle_profile[3]); #endif } } return ret; }
void soidle_before_wfi(void) { #ifdef CONFIG_SMP int err = 0; soidle_timer_left2 = localtimer_get_counter(); free_gpt(GPT4); err = request_gpt(GPT4, GPT_ONE_SHOT, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, 0, NULL, GPT_NOAUTOEN); if (err) { idle_info("[%s]fail to request GPT4\n", __func__); } soidle_timer_left2 = localtimer_get_counter(); if( soidle_timer_left2 <=0 ) gpt_set_cmp(GPT4, 1);//Trigger GPT4 Timerout imediately else gpt_set_cmp(GPT4, soidle_timer_left2); start_gpt(GPT4); #else gpt_get_cnt(GPT1, &soidle_timer_left2); #endif }
void spm_dpidle_after_wfi(void) { #if 0 idle_info("[%s]timer_left=%u, timer_left2=%u, delta=%u\n", dpidle_timer_left, dpidle_timer_left2, dpidle_timer_left-dpidle_timer_left2); #endif //if (gpt_check_irq(GPT4)) { if (gpt_check_and_ack_irq(GPT4)) { /* waked up by WAKEUP_GPT */ localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(GPT4, &cnt); gpt_get_cmp(GPT4, &cmp); if (unlikely(cmp < cnt)) { idle_err("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, GPT4 + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(GPT4); //GPT_ClearCount(WAKEUP_GPT); } faudintbus_sq2pll(); bus_dcm_disable(); dpidle_cnt[0]++; }
void spm_dpidle_after_wfi(void) { #ifdef CONFIG_SMP //if (gpt_check_irq(GPT4)) { if (gpt_check_and_ack_irq(GPT4)) { /* waked up by WAKEUP_GPT */ localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(GPT4, &cnt); gpt_get_cmp(GPT4, &cmp); if (unlikely(cmp < cnt)) { idle_err("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, GPT4 + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(GPT4); //GPT_ClearCount(WAKEUP_GPT); free_gpt(GPT4); } #endif disable_clock(MT_CG_PMIC_SW_CG_AP, "DEEP_IDLE"); clkmux_sel(MT_CLKMUX_AUD_INTBUS_SEL,g_clk_aud_intbus_sel,"Deep_Idle"); dpidle_cnt[0]++; }
void spm_mcdi_after_wfi(int cpu) { unsigned int id = mcidle_gpt_percpu[cpu]; if (cpu != 0) { if (gpt_check_and_ack_irq(id)) { localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(id, &cnt); gpt_get_cmp(id, &cmp); if (unlikely(cmp < cnt)) { printk("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, id + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(id); #ifdef SPM_SUSPEND_GPT_EN free_gpt(id); #endif } } }
void spm_dpidle_before_wfi(void) { int err = 0; g_clk_aud_intbus_sel = clkmux_get(MT_CLKMUX_AUD_INTBUS_SEL,"Deep_Idle"); clkmux_sel(MT_CLKMUX_AUD_INTBUS_SEL, MT_CG_SYS_26M,"Deep_Idle"); enable_clock(MT_CG_PMIC_SW_CG_AP, "DEEP_IDLE");//PMIC CG bit for AP. SPM need PMIC wrapper clock to change Vcore voltage #ifdef CONFIG_SMP free_gpt(GPT4); err = request_gpt(GPT4, GPT_ONE_SHOT, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, 0, NULL, GPT_NOAUTOEN); if (err) { idle_info("[%s]fail to request GPT4\n", __func__); } dpidle_timer_left2 = localtimer_get_counter(); if( dpidle_timer_left2 <=0 ) gpt_set_cmp(GPT4, 1);//Trigger GPT4 Timerout imediately else gpt_set_cmp(GPT4, dpidle_timer_left2); start_gpt(GPT4); #else gpt_get_cnt(GPT1, &dpidle_timer_left2); #endif }
void spm_dpidle_after_wfi(void) { #ifdef CONFIG_SMP //if (gpt_check_irq(GPT4)) { if (gpt_check_and_ack_irq(idle_gpt)) { /* waked up by WAKEUP_GPT */ localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(idle_gpt, &cnt); gpt_get_cmp(idle_gpt, &cmp); if (unlikely(cmp < cnt)) { idle_err("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, idle_gpt + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(idle_gpt); //GPT_ClearCount(WAKEUP_GPT); } #endif //clkmux_sel(MT_MUX_AUDINTBUS, 1, "Deepidle"); //mainpll clkmgr_faudintbus_sq2pll(); bus_dcm_disable(); dpidle_cnt[0]++; }
void mcidle_after_wfi(int cpu) { #ifdef CONFIG_SMP unsigned int id = mcidle_gpt_percpu[cpu]; //if (cpu != 0) { if (gpt_check_and_ack_irq(id)) { localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(id, &cnt); gpt_get_cmp(id, &cmp); if (unlikely(cmp < cnt)) { idle_err("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, id + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(id); free_gpt(id); } //} #endif mcidle_cnt[cpu]++; }
void spm_dpidle_before_wfi(void) { if (TRUE == mt_dpidle_chk_golden) { //FIXME: #if 0 mt_power_gs_dump_dpidle(); #endif } bus_dcm_enable(); clkmgr_faudintbus_pll2sq(); //clkmux_sel(MT_MUX_AUDINTBUS, 0, "Deepidle"); //select 26M #ifdef CONFIG_SMP dpidle_timer_left2 = localtimer_get_counter(); if( (int)dpidle_timer_left2 <=0 ) gpt_set_cmp(idle_gpt, 1);//Trigger GPT4 Timerout imediately else gpt_set_cmp(idle_gpt, dpidle_timer_left2); start_gpt(idle_gpt); #else gpt_get_cnt(idle_gpt, &dpidle_timer_left2); #endif }
static inline int soidle_handler(int cpu) { if (idle_switch[IDLE_TYPE_SO]) { #ifdef SPM_SODI_PROFILE_TIME gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[0]); #endif if (soidle_can_enter(cpu)) { soidle_pre_handler(); #ifdef DEFAULT_MMP_ENABLE MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagStart, 0, 0); #endif //DEFAULT_MMP_ENABLE spm_go_to_sodi(slp_spm_SODI_flags, 0); #ifdef DEFAULT_MMP_ENABLE MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagEnd, 0, spm_read(SPM_PCM_PASR_DPD_3)); #endif //DEFAULT_MMP_ENABLE soidle_post_handler(); #if 0 //removed unused log #ifdef CONFIG_SMP idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d\n", soidle_timer_left, soidle_timer_left2, soidle_timer_left-soidle_timer_left2); #else idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d,timeout val=%d\n", soidle_timer_left, soidle_timer_left2, soidle_timer_left2-soidle_timer_left,soidle_timer_cmp-soidle_timer_left); #endif #endif #if 0 //for DVT test only idle_switch[IDLE_TYPE_SO] = 0; #endif #ifdef SPM_SODI_PROFILE_TIME gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[3]); idle_ver("SODI: cpu_freq:%u, 1=>2:%u, 2=>3:%u, 3=>4:%u\n", mt_cpufreq_get_cur_freq(0), soidle_profile[1]-soidle_profile[0], soidle_profile[2]-soidle_profile[1], soidle_profile[3]-soidle_profile[2]); #endif return 1; } } return 0; }
bool soidle_can_enter(int cpu) { int reason = NR_REASONS; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(num_online_cpus() != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } //FIXED ME. this checking is needed in 6735? // decide when to enable SODI by display driver if(spm_get_sodi_en()==0){ reason = BY_OTH; goto out; } memset(soidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(soidle_condition_mask, soidle_block_mask)) { reason = BY_CLK; goto out; } #ifdef CONFIG_SMP soidle_timer_left = localtimer_get_counter(); if ((int)soidle_timer_left < soidle_time_critera || ((int)soidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &soidle_timer_left); gpt_get_cmp(GPT1, &soidle_timer_cmp); if((soidle_timer_cmp-soidle_timer_left)<soidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { soidle_block_cnt[cpu][reason]++; return false; } else { return true; } }
bool soidle_can_enter(int cpu) { int reason = NR_REASONS; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(atomic_read(&hotplug_cpu_count) != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } if(spm_get_sodi_en()==0){ reason = BY_OTH; goto out; } memset(soidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(soidle_condition_mask, soidle_block_mask)) { reason = BY_CLK; goto out; } #ifdef CONFIG_SMP soidle_timer_left = localtimer_get_counter(); if ((int)soidle_timer_left < soidle_time_critera || ((int)soidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &soidle_timer_left); gpt_get_cmp(GPT1, &soidle_timer_cmp); if((soidle_timer_cmp-soidle_timer_left)<soidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { soidle_block_cnt[cpu][reason]++; return false; } else { return true; } }
bool mcidle_can_enter(int cpu) { int reason = NR_REASONS; #ifndef CONFIG_SMP unsigned int cmp; #endif /* MCDI Only */ if (cpu == 0) { reason = BY_OTH; goto mcidle_out; } #ifdef CONFIG_SMP if (atomic_read(&hotplug_cpu_count) == 1) { reason = BY_CPU; goto mcidle_out; } #endif if (atomic_read(&is_in_hotplug) == 1) { reason = BY_CPU; goto mcidle_out; } #ifdef CONFIG_SMP mcidle_timer_left[cpu] = localtimer_get_counter(); if (mcidle_timer_left[cpu] < mcidle_time_critera || ((int)mcidle_timer_left[cpu]) < 0) { reason = BY_TMR; goto mcidle_out; } #else gpt_get_cnt(GPT1, &mcidle_timer_left[cpu]); gpt_get_cmp(GPT1, &cmp); if((cmp-mcidle_timer_left[cpu])<mcidle_time_critera) { reason = BY_TMR; goto mcidle_out; } #endif mcidle_out: if (reason < NR_REASONS) { mcidle_block_cnt[cpu][reason]++; return false; } else { return true; } }
void soidle_before_wfi(int cpu) { #ifdef CONFIG_SMP soidle_timer_left2 = localtimer_get_counter(); if( (int)soidle_timer_left2 <=0 ) { gpt_set_cmp(idle_gpt, 1);//Trigger idle_gpt Timerout imediately } else gpt_set_cmp(idle_gpt, soidle_timer_left2); start_gpt(idle_gpt); #else gpt_get_cnt(GPT1, &soidle_timer_left2); #endif }
unsigned char soidle_can_enter(int cpu) { int reason = NR_REASONS; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(atomic_read(&hotplug_cpu_count) != 1)) { reason = BY_CPU; goto soidle_out; } #endif memset(soidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(soidle_condition_mask, soidle_block_mask)) { reason = BY_CLK; goto soidle_out; } #ifdef CONFIG_SMP soidle_timer_left = localtimer_get_counter(); if (soidle_timer_left < soidle_time_critera || ((int)soidle_timer_left) < 0) { reason = BY_TMR; goto soidle_out; } #else gpt_get_cnt(GPT1, &soidle_timer_left); gpt_get_cmp(GPT1, &soidle_timer_cmp); if((soidle_timer_cmp-soidle_timer_left)<soidle_time_critera) { reason = BY_TMR; goto soidle_out; } #endif soidle_out: if (reason < NR_REASONS) soidle_block_cnt[cpu][reason]++; return reason; }
void mcidle_before_wfi(int cpu) { #ifdef CONFIG_SMP int err = 0; unsigned int id = mcidle_gpt_percpu[cpu]; mcidle_timer_left2[cpu] = localtimer_get_counter(); free_gpt(id); err = request_gpt(id, GPT_ONE_SHOT, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, 0, NULL, GPT_NOAUTOEN); if (err) { idle_info("[%s]fail to request GPT4\n", __func__); } mcidle_timer_left2[cpu] = localtimer_get_counter(); if(cpu!=0)//core1~n, avoid gpt clear by core0 { if( mcidle_timer_left2[cpu] <=2600 ) //200us(todo) { if(mcidle_timer_left2[cpu]<=0) gpt_set_cmp(id, 1);//Trigger GPT4 Timerout imediately else gpt_set_cmp(id, mcidle_timer_left2[cpu]); spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT,spm_read(SPM_SLEEP_CPU_WAKEUP_EVENT)|0x1);//spm wake up directly } else gpt_set_cmp(id, mcidle_timer_left2[cpu]); start_gpt(id); } #else gpt_get_cnt(GPT1, &mcidle_timer_left2); #endif }
void soidle_after_wfi(bool sodi_en) { #ifdef CONFIG_SMP if (gpt_check_and_ack_irq(GPT4)) { localtimer_set_next_event(1); } else { /* waked up by other wakeup source */ unsigned int cnt, cmp; gpt_get_cnt(GPT4, &cnt); gpt_get_cmp(GPT4, &cmp); if (unlikely(cmp < cnt)) { idle_err("[%s]GPT%d: counter = %10u, compare = %10u\n", __func__, GPT4 + 1, cnt, cmp); BUG(); } localtimer_set_next_event(cmp-cnt); stop_gpt(GPT4); free_gpt(GPT4); } #endif if(sodi_en) soidle_cnt[0]++; }
void soidle_before_wfi(int cpu) { #ifdef CONFIG_SMP #if !defined(SODI_APxGPT_TimerCount) || (SODI_APxGPT_TimerCount == 0) soidle_timer_left2 = localtimer_get_counter(); #else soidle_timer_left2 = 13000000*SODI_APxGPT_TimerCount; #endif if( (int)soidle_timer_left2 <=0 ) { gpt_set_cmp(idle_gpt, 1);//Trigger idle_gpt Timerout imediately } else { gpt_set_cmp(idle_gpt, soidle_timer_left2); } start_gpt(idle_gpt); #else gpt_get_cnt(GPT1, &soidle_timer_left2); #endif }
wake_reason_t spm_go_to_dpidle(u32 spm_flags, u32 spm_data) { struct wake_status wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; struct pcm_desc *pcmdesc = __spm_dpidle.pcmdesc; struct pwr_ctrl *pwrctrl = __spm_dpidle.pwrctrl; #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(1<<SPM_DEEPIDLE_ENTER); #endif set_pwrctrl_pcm_flags(pwrctrl, spm_flags); //pwrctrl->timer_val = 1 * 32768; spm_dpidle_before_wfi(); lockdep_off(); 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(); #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_UART_SLEEP)); #endif if (request_uart_to_sleep()) { 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_dpidle_pre_process(); __spm_kick_pcm_to_run(pwrctrl); #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_WFI)); #endif #ifdef SPM_DEEPIDLE_PROFILE_TIME gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[1]); #endif spm_trigger_wfi_for_dpidle(pwrctrl); #ifdef SPM_DEEPIDLE_PROFILE_TIME gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[2]); #endif #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_LEAVE_WFI)); #endif spm_dpidle_post_process(); __spm_get_wakeup_status(&wakesta); __spm_clean_after_wakeup(); #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_UART_AWAKE)); #endif request_uart_to_wakeup(); wr = __spm_output_wake_reason(&wakesta, pcmdesc, false); RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&__spm_lock, flags); lockdep_on(); spm_dpidle_after_wfi(); #if SPM_AEE_RR_REC aee_rr_rec_deepidle_val(0); #endif return wr; }
static bool dpidle_can_enter(void) { int reason = NR_REASONS; int i; unsigned long long dpidle_block_curr_time = 0; #ifdef SPM_MCDI_FUNC if (En_SPM_MCDI != 0) { reason = BY_OTH; goto out; } #endif #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(atomic_read(&hotplug_cpu_count) != 1)) { reason = BY_CPU; goto out; } #endif memset(dpidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(dpidle_condition_mask, dpidle_block_mask)) { reason = BY_CLK; goto out; } #ifdef CONFIG_SMP dpidle_timer_left = localtimer_get_counter(); if (dpidle_timer_left < dpidle_time_critera || ((int)dpidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &dpidle_timer_left); gpt_get_cmp(GPT1, &dpidle_timer_cmp); if((dpidle_timer_cmp-dpidle_timer_left)<dpidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { if( dpidle_block_prev_time == 0 ) dpidle_block_prev_time = idle_get_current_time_ms(); dpidle_block_curr_time = idle_get_current_time_ms(); if((dpidle_block_curr_time - dpidle_block_prev_time) > dpidle_block_time_critera) { if ((smp_processor_id() == 0)) { for (i = 0; i < nr_cpu_ids; i++) { idle_ver("dpidle_cnt[%d]=%lu, rgidle_cnt[%d]=%lu\n", i, dpidle_cnt[i], i, rgidle_cnt[i]); } for (i = 0; i < NR_REASONS; i++) { idle_ver("[%d]dpidle_block_cnt[%s]=%lu\n", i, reason_name[i], dpidle_block_cnt[i]); } for (i = 0; i < NR_GRPS; i++) { idle_ver("[%02d]dpidle_condition_mask[%-8s]=0x%08x\t\t" "dpidle_block_mask[%-8s]=0x%08x\n", i, grp_get_name(i), dpidle_condition_mask[i], grp_get_name(i), dpidle_block_mask[i]); } //printk("dpidle_block_prev_time =%lu, dpidle_block_curr_time = %lu\n",dpidle_block_prev_time,dpidle_block_curr_time); memset(dpidle_block_cnt, 0, sizeof(dpidle_block_cnt)); dpidle_block_prev_time = idle_get_current_time_ms(); } } dpidle_block_cnt[reason]++; return false; } else { dpidle_block_prev_time = idle_get_current_time_ms(); return true; } }
void spm_go_to_sodi(u32 spm_flags, u32 spm_data) { struct wake_status wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; struct pcm_desc *pcmdesc = __spm_sodi.pcmdesc; struct pwr_ctrl *pwrctrl = __spm_sodi.pwrctrl; int vcore_status = 0; //0:disable, 1:HPM, 2:LPM #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(1<<SPM_SODI_ENTER); #endif #if defined (CONFIG_ARM_PSCI)||defined(CONFIG_MTK_PSCI) spm_flags &= ~SPM_DISABLE_ATF_ABORT; #else spm_flags |= SPM_DISABLE_ATF_ABORT; #endif if(gSpm_SODI_mempll_pwr_mode == 1) { spm_flags |= SPM_MEMPLL_CG_EN; //MEMPLL CG mode } else { spm_flags &= ~SPM_MEMPLL_CG_EN; //DDRPHY power down mode } set_pwrctrl_pcm_flags(pwrctrl, spm_flags); //If Vcore DVFS is disable, force to disable SODI internal Vcore DVS if (pwrctrl->pcm_flags_cust == 0) { if ((pwrctrl->pcm_flags & SPM_VCORE_DVFS_EN) == 0) { pwrctrl->pcm_flags |= SPM_VCORE_DVS_EVENT_DIS; } } //SODI will not decrease Vcore voltage in HPM mode. if ((pwrctrl->pcm_flags & SPM_VCORE_DVS_EVENT_DIS) == 0) { if (get_ddr_khz() != FDDR_S1_KHZ) { #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_VCORE_HPM)); #endif /* //modify by mtk //if DRAM freq is high,SPM will not enter event_vector to enter EMI self-refresh if(pwrctrl->pcm_flags_cust == 0) { pwrctrl->pcm_flags|=0x80; } */ vcore_status = 1; //printk("SODI: get_ddr_khz() = %d\n", get_ddr_khz()); } else { #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_VCORE_LPM)); #endif vcore_status = 2; } } //enable APxGPT timer soidle_before_wfi(0); lockdep_off(); 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(); #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_UART_SLEEP)); #endif if (request_uart_to_sleep()) { wr = WR_UART_BUSY; goto RESTORE_IRQ; } #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_SPM_FLOW)); #endif __spm_reset_and_init_pcm(pcmdesc); /* * When commond-queue is in shut-down mode, SPM will hang if it tries to access commond-queue status. * Follwoing patch is to let SODI driver to notify SPM that commond-queue is in shut-down mode or not to avoid above SPM hang issue. * But, now display can automatically notify SPM that command-queue is shut-down or not, so following code is not needed anymore. */ #if 0 //check GCE if(clock_is_on(MT_CG_INFRA_GCE)) { pwrctrl->pcm_flags &= ~SPM_DDR_HIGH_SPEED; } else { pwrctrl->pcm_flags |= SPM_DDR_HIGH_SPEED; } #endif __spm_kick_im_to_fetch(pcmdesc); __spm_init_pcm_register(); __spm_init_event_vector(pcmdesc); #if 0 //In D2, can not set apsrc_req bit in SODI. It is used by Vcore DVS for GPU 550M in HPM mode //Display set SPM_PCM_SRC_REQ[0]=1'b1 to force DRAM not enter self-refresh mode if((spm_read(SPM_PCM_SRC_REQ)&0x00000001)) { pwrctrl->pcm_apsrc_req = 1; } else { pwrctrl->pcm_apsrc_req = 0; } #endif __spm_set_power_control(pwrctrl); __spm_set_wakeup_event(pwrctrl); #if SODI_DVT_PCM_TIMER_DISABLE //PCM_Timer is enable in above '__spm_set_wakeup_event(pwrctrl);', disable PCM Timer here spm_write(SPM_PCM_CON1 ,spm_read(SPM_PCM_CON1)&(~CON1_PCM_TIMER_EN)); #endif spm_sodi_pre_process(); __spm_kick_pcm_to_run(pwrctrl); #if SPM_SODI_DUMP_REGS printk("============SODI Before============\n"); spm_sodi_dump_regs(); //dump debug info #endif #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_WFI)); #endif #ifdef SPM_SODI_PROFILE_TIME gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[1]); #endif spm_trigger_wfi_for_sodi(pwrctrl); #ifdef SPM_SODI_PROFILE_TIME gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[2]); #endif #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_WFI)); #endif #if SPM_SODI_DUMP_REGS printk("============SODI After=============\n"); spm_sodi_dump_regs();//dump debug info #endif spm_sodi_post_process(); __spm_get_wakeup_status(&wakesta); sodi_debug("emi-selfrefrsh cnt = %d, pcm_flag = 0x%x, SPM_PCM_RESERVE2 = 0x%x, vcore_status = %d, %s\n", spm_read(SPM_PCM_PASR_DPD_3), spm_read(SPM_PCM_FLAGS), spm_read(SPM_PCM_RESERVE2), vcore_status, pcmdesc->version); __spm_clean_after_wakeup(); #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_UART_AWAKE)); #endif request_uart_to_wakeup(); wr = __spm_output_wake_reason(&wakesta, pcmdesc, false); if (wr == WR_PCM_ASSERT) { sodi_err("PCM ASSERT AT %u (%s), r13 = 0x%x, debug_flag = 0x%x\n", wakesta.assert_pc, pcmdesc->version, wakesta.r13, wakesta.debug_flag); } #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_SPM_FLOW)); #endif RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&__spm_lock, flags); lockdep_on(); //stop APxGPT timer and enable caore0 local timer soidle_after_wfi(0); #if SODI_DVT_SPM_MEM_RW_TEST { static u32 magic_init = 0; int i =0; if(magic_init == 0){ magic_init++; printk("magicNumArray:0x%p",magicArray); } for(i=0;i<16;i++) { if(magicArray[i]!=SODI_DVT_MAGIC_NUM) { printk("Error: sodi magic number no match!!!"); ASSERT(0); } } if (i>=16) printk("SODI_DVT_SPM_MEM_RW_TEST pass (count = %d)\n", magic_init); } #endif #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(0); #endif }
bool soidle_can_enter(int cpu) { int reason = NR_REASONS; unsigned long long soidle_block_curr_time = 0; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(num_online_cpus() != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } #if !defined(SODI_DISPLAY_DRV_CHK_DIS) || (SODI_DISPLAY_DRV_CHK_DIS == 0) // decide when to enable SODI by display driver if(spm_get_sodi_en()==0){ reason = BY_OTH; goto out; } #endif if (soidle_by_pass_cg == 0) { memset(soidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(soidle_condition_mask, soidle_block_mask)) { #if !defined(SODI_CG_CHK_DIS) || (SODI_CG_CHK_DIS == 0) reason = BY_CLK; goto out; #endif } } #ifdef CONFIG_SMP soidle_timer_left = localtimer_get_counter(); if ((int)soidle_timer_left < soidle_time_critera || ((int)soidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &soidle_timer_left); gpt_get_cmp(GPT1, &soidle_timer_cmp); if((soidle_timer_cmp-soidle_timer_left)<soidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { if( soidle_block_prev_time == 0 ) soidle_block_prev_time = idle_get_current_time_ms(); soidle_block_curr_time = idle_get_current_time_ms(); if((soidle_block_curr_time - soidle_block_prev_time) > soidle_block_time_critera) { if ((smp_processor_id() == 0)) { int i = 0; for (i = 0; i < nr_cpu_ids; i++) { idle_ver("soidle_cnt[%d]=%lu, rgidle_cnt[%d]=%lu\n", i, soidle_cnt[i], i, rgidle_cnt[i]); } for (i = 0; i < NR_REASONS; i++) { idle_ver("[%d]soidle_block_cnt[0][%s]=%lu\n", i, reason_name[i], soidle_block_cnt[0][i]); } for (i = 0; i < NR_GRPS; i++) { idle_ver("[%02d]soidle_condition_mask[%-8s]=0x%08x\t\t" "soidle_block_mask[%-8s]=0x%08x\n", i, grp_get_name(i), soidle_condition_mask[i], grp_get_name(i), soidle_block_mask[i]); } memset(soidle_block_cnt, 0, sizeof(soidle_block_cnt)); soidle_block_prev_time = idle_get_current_time_ms(); } } soidle_block_cnt[cpu][reason]++; return false; } else { soidle_block_prev_time = idle_get_current_time_ms(); return true; } }
static bool dpidle_can_enter(void) { int reason = NR_REASONS; int i = 0; unsigned long long dpidle_block_curr_time = 0; if(dpidle_by_pass_cg==0){ if (!mt_cpufreq_earlysuspend_status_get()){ reason = BY_VTG; goto out; } } #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) >= 1)||(num_online_cpus() != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } if(dpidle_by_pass_cg==0){ memset(dpidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(dpidle_condition_mask, dpidle_block_mask)) { reason = BY_CLK; goto out; } } #ifdef CONFIG_SMP dpidle_timer_left = localtimer_get_counter(); if ((int)dpidle_timer_left < dpidle_time_critera || ((int)dpidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &dpidle_timer_left); gpt_get_cmp(GPT1, &dpidle_timer_cmp); if((dpidle_timer_cmp-dpidle_timer_left)<dpidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { if( dpidle_block_prev_time == 0 ) dpidle_block_prev_time = idle_get_current_time_ms(); dpidle_block_curr_time = idle_get_current_time_ms(); if((dpidle_block_curr_time - dpidle_block_prev_time) > dpidle_block_time_critera) { if ((smp_processor_id() == 0)) { for (i = 0; i < nr_cpu_ids; i++) { idle_ver("dpidle_cnt[%d]=%lu, rgidle_cnt[%d]=%lu\n", i, dpidle_cnt[i], i, rgidle_cnt[i]); } for (i = 0; i < NR_REASONS; i++) { idle_ver("[%d]dpidle_block_cnt[%s]=%lu\n", i, reason_name[i], dpidle_block_cnt[i]); } for (i = 0; i < NR_GRPS; i++) { idle_ver("[%02d]dpidle_condition_mask[%-8s]=0x%08x\t\t" "dpidle_block_mask[%-8s]=0x%08x\n", i, grp_get_name(i), dpidle_condition_mask[i], grp_get_name(i), dpidle_block_mask[i]); } memset(dpidle_block_cnt, 0, sizeof(dpidle_block_cnt)); dpidle_block_prev_time = idle_get_current_time_ms(); } } dpidle_block_cnt[reason]++; return false; } else { dpidle_block_prev_time = idle_get_current_time_ms(); return true; } }