void arch_idle(void) { int cpu = smp_processor_id(); int i; #if defined(SPM_MCDI_FUNC) /*Only core0 onload & offload MCDI*/ if(cpu==0)//only core0 offload mcdi { if(SPM_MCDI_isKICK==1) { if((atomic_read(&hotplug_cpu_count) == 1)||(SPM_MCDI_Enable==0)) { printk("start leave mcdi\n"); spm_leave_MCDI(); spm_go_to_normal(); } } else if ((SPM_MCDI_isKICK==0)&&(SPM_MCDI_Enable)) { if((atomic_read(&hotplug_cpu_count)!=1)&&(atomic_read(&is_in_hotplug) < 1) ) { if(is_ext_buck_exist() == 0) mcidle_time_critera = 19500;//1.5ms for internal buck else mcidle_time_critera = 39000;//3ms for external buck spm_go_to_mcdi(1); } } } #endif for (i = 0; i < NR_TYPES; i++) { if (idle_handlers[i](cpu)) break; } }
static bool dpidle_can_enter(void) { int reason = NR_REASONS; int i = 0; unsigned long long dpidle_block_curr_time = 0; #if 0 /* Temporarily disable deepidle/SODI for Turbo-mode */ if (is_ext_buck_exist()) { reason = BY_OTH; goto out; } #endif #if 0 if(dpidle_by_pass_cg==0){ if (!mt_cpufreq_earlysuspend_status_get()){ reason = BY_VTG; goto out; } } #endif #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; } }
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 0 //workaround for ultra CPU mode if (is_ext_buck_exist()) { 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; } }
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 /* Workaround: do NOT lower VPROC for turbo mode */ /* Workaround (2015.04.17): do NOT lower VPROC for FW v0.2.5 */ #if 0 if (is_ext_buck_exist()) #endif spm_flags |= SPM_CPU_DVS_DIS; 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(); __spm_enable_i2c4_clk(); #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); __spm_disable_i2c4_clk(); 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; }