void spm_module_init(void) { int r; unsigned long flags; struct wd_api *wd_api; spin_lock_irqsave(&spm_lock, flags); /* enable register control */ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0)); /* init power control register (select PCM clock to 26M) */ spm_write(SPM_POWER_ON_VAL0, 0); spm_write(SPM_POWER_ON_VAL1, 0x00015820); spm_write(SPM_PCM_PWR_IO_EN, 0); /* reset PCM */ spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); spm_write(SPM_PCM_CON0, CON0_CFG_KEY); /* init PCM control register */ spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS); spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | CON1_IM_NONRP_EN | CON1_MIF_APBEN); spm_write(SPM_PCM_IM_PTR, 0); spm_write(SPM_PCM_IM_LEN, 0); /* SRCLKENA: POWER_ON_VAL1 (PWR_IO_EN[7]=0) or POWER_ON_VAL1|r7 (PWR_IO_EN[7]=1) */ /* CLKSQ: POWER_ON_VAL0 (PWR_IO_EN[0]=0) or r0 (PWR_IO_EN[0]=1) */ /* SRCLKENAI will trigger 26M-wake/sleep event */ spm_write(SPM_CLK_CON, CC_CXO32K_RM_EN_MD); spm_write(SPM_PCM_SRC_REQ, (1U << 1)); /* clean wakeup event raw status */ spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, 0xffffffff); /* clean ISR status */ spm_write(SPM_SLEEP_ISR_MASK, ISRM_ALL); spm_write(SPM_SLEEP_ISR_STATUS, ISRC_ALL); spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT_ALL); spin_unlock_irqrestore(&spm_lock, flags); r = request_irq(MT_SPM_IRQ_ID, spm_irq_handler, IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, "mt-spm", NULL); if (r) { spm_error("FAILED TO REQUEST SPM IRQ (%d)\n", r); WARN_ON(1); } get_wd_api(&wd_api); if (wd_api->wd_spmwdt_mode_config && wd_api->wd_thermal_mode_config) { wd_api->wd_spmwdt_mode_config(WD_REQ_EN, WD_REQ_RST_MODE); wd_api->wd_thermal_mode_config(WD_REQ_EN, WD_REQ_RST_MODE); } else { spm_error("FAILED TO GET WD API\n"); WARN_ON(1); } spm_go_to_normal(); /* let PCM help to do thermal protection */ }
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; } }
/* status RESERVED[0] : mcusys dormant RESERVED[1] : APSRCSLEEP - (pass CHECK_APSRCWAKE) RESERVED[2] : EMI self-refresh & mem ck off Options RESERVED[16] : skip arm pll cg/pd RESERVED[17] : skip arm pll pd RESERVED[18] : skip AXI 26 SWITCH RESERVED[19] : skip EMI self-refresh & mem ck off RESERVED[20] : skip mem ck off RESERVED[24] : stop after cpu power down / cpu pll off RESERVED[25] : stop after emi down / mem ck off */ wake_reason_t spm_go_to_sodi(bool sodi_en,int cpu) { wake_status_t *wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; u32 con0; spin_lock_irqsave(&spm_lock, flags); spm_stop_normal(); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM0_IRQ_ID); mt_cirq_clone_gic(); mt_cirq_enable(); spm_direct_enable_sodi(); spm_write(SPM_PCM_RESERVE,pcm_config_sodi.pcm_reserved); #ifdef SPM_SODI_SECONDARY_KICK_IMPROVE if( spm_last_senario != pcm_config_sodi.scenario)//MCDI SPM Initialize #endif { //spm_direct_enable_sodi(); if (spm_init_pcm(&pcm_config_sodi)==false) goto RESTORE_IRQ; spm_write(SPM_SLEEP_CPU_IRQ_MASK,0x1); spm_write(SPM_PCM_CON1,(spm_read(SPM_PCM_CON1)| CON1_CFG_KEY )&0xffffffdf);//temporary disable pcm timer spm_wfi_sel(pcm_config_sodi.wfi_sel, SPM_CORE0_WFI_SEL_SW_MASK ); spm_wfi_sel(pcm_config_sodi.wfi_sel, SPM_CORE1_WFI_SEL_SW_MASK ); spm_kick_pcm(&pcm_config_sodi); spm_change_fw = 1; } #ifdef SPM_SODI_SECONDARY_KICK_IMPROVE else { spm_write(SPM_SLEEP_CPU_IRQ_MASK,0x1); spm_wfi_sel(pcm_config_sodi.wfi_sel, SPM_CORE0_WFI_SEL_SW_MASK ); spm_wfi_sel(pcm_config_sodi.wfi_sel, SPM_CORE1_WFI_SEL_SW_MASK ); if( spm_secondary_kick(&pcm_config_sodi)==false) goto RESTORE_IRQ; spm_change_fw = 0; } #endif //gpiodbg_infra_dbg_out();//measure bus clock to LPD15 soidle_before_wfi(); spm_trigger_wfi_for_dpidle(1);//SODI with cpu dormant soidle_after_wfi(sodi_en); wakesta = spm_get_wakeup_status(&pcm_config_sodi); wr = wakesta->wake_reason; spm_clean_after_wakeup(); spm_write(SPM_PCM_CON1,(spm_read(SPM_PCM_CON1)| CON1_CFG_KEY )|(CON1_PCM_TIMER_EN)); RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spm_go_to_normal(); spin_unlock_irqrestore(&spm_lock, flags); return wr; }
wake_reason_t spm_go_to_dpidle(bool cpu_pdn, u8 pwrlevel) { wake_status_t *wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; u32 con0; u32 top_ckgen_val = 0; spin_lock_irqsave(&spm_lock, flags); spm_stop_normal(); mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM0_IRQ_ID); mt_cirq_clone_gic(); mt_cirq_enable(); #ifdef SPM_DPIDLE_SECONDARY_KICK_IMPROVE if( spm_last_senario != pcm_config_dpidle.scenario)//dpidle SPM Initialize #endif { if(pwrlevel>2) { spm_crit2("Hey!! wrong PWR Level: %x",pwrlevel);//ASSERT Wrong Para!! goto RESTORE_IRQ; } pcm_config_dpidle.pcm_pwrlevel = 1 << pwrlevel ; pcm_config_dpidle.spm_request_uart_sleep = (pwrlevel == 0 ? true : false); pcm_config_dpidle.cpu_pdn = cpu_pdn; if (spm_init_pcm(&pcm_config_dpidle)==false) goto RESTORE_IRQ; #ifdef SPM_CLOCK_INIT enable_clock(MT_CG_MEMSLP_DLYER_SW_CG, "SPM_DPIDLE"); enable_clock(MT_CG_SPM_SW_CG, "SPM_DPIDLE"); #endif #ifdef SPM_DPIDLE_CLK_DBG_OUT //gpiodbg_monitor(); gpiodbg_emi_dbg_out(); gpiodbg_armcore_dbg_out(); #endif spm_kick_pcm(&pcm_config_dpidle); //spm_change_fw = 1; } #ifdef SPM_DPIDLE_SECONDARY_KICK_IMPROVE else { if( spm_secondary_kick(&pcm_config_dpidle)==false) goto RESTORE_IRQ; //spm_change_fw = 0; } #endif spm_dpidle_before_wfi(); //hopping 33M-->fixed 26M, 20130902 HG.Wei top_ckgen_val = spm_read(TOPCKGEN_BASE); spm_write(TOPCKGEN_BASE,top_ckgen_val&(~(1<<26))); snapshot_golden_setting(__FUNCTION__, __LINE__); spm_trigger_wfi(&pcm_config_dpidle); //hopping fixed 26M-->hopping 33M, 20130902 HG.Wei spm_write(TOPCKGEN_BASE,top_ckgen_val); spm_dpidle_after_wfi(); wakesta = spm_get_wakeup_status(&pcm_config_dpidle); wr = wakesta->wake_reason; spm_clean_after_wakeup(); #ifdef SPM_CLOCK_INIT disable_clock(MT_CG_SPM_SW_CG, "SPM_DPIDLE"); disable_clock(MT_CG_MEMSLP_DLYER_SW_CG, "SPM_DPIDLE"); #endif RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spm_go_to_normal(); spin_unlock_irqrestore(&spm_lock, flags); return wr; }