/* * cpu_pdn: * true = CPU dormant * false = CPU standby * pwrlevel: * 0 = AXI is off * 1 = AXI is 26M */ wake_reason_t spm_go_to_dpidle(bool cpu_pdn, u16 pwrlevel) { wake_status_t wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; const pcm_desc_t *pcmdesc = &pcm_dpidle; const bool pcmwdt_en = false; 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_reset_and_init_pcm(); spm_kick_im_to_fetch(pcmdesc); if (spm_request_uart_to_sleep()) { wr = WR_UART_BUSY; goto RESTORE_IRQ; } spm_init_pcm_register(); spm_init_event_vector(pcmdesc); spm_set_pwrctl_for_dpidle(pwrlevel); spm_set_wakeup_event(0, WAKE_SRC_FOR_DPIDLE); spm_kick_pcm_to_run(cpu_pdn, false, pcmwdt_en); /* keep INFRA/DDRPHY power */ spm_dpidle_before_wfi(); spm_trigger_wfi_for_dpidle(cpu_pdn); spm_dpidle_after_wfi(); spm_get_wakeup_status(&wakesta); spm_clean_after_wakeup(pcmwdt_en); wr = spm_output_wake_reason(&wakesta, true); RESTORE_IRQ: mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&spm_lock, flags); return wr; }
static void rgidle_after_wfi(int cpu) { #ifdef CCI400_CLOCK_SWITCH struct mtk_irq_mask mask; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 0)&&(atomic_read(&hotplug_cpu_count) == 1)) #endif { mt_irq_mask_all(&mask); mt_cirq_clone_gic(); mt_cirq_enable(); cci400_clk_restore(); mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); } #endif rgidle_cnt[cpu]++; }
static void slidle_before_wfi(int cpu) { //struct mtk_irq_mask mask; bus_dcm_enable(); #ifdef CCI400_CLOCK_SWITCH #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 0)&&(atomic_read(&hotplug_cpu_count) == 1)) #endif { mt_irq_mask_all(&mask); mt_cirq_clone_gic(); mt_cirq_enable(); cci400_clk_26MHz(); mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); } #endif }
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; }
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 }
void APDMA_test_transfer(int testcase) { int i, channel; int start_dma; unsigned int cnt = 20; channel = mt_req_gdma(GDMA_ANY); printk("GDMA channel:%d\n",channel); if(channel < 0 ){ printk("ERROR Register DMA\n"); return; } mt_reset_gdma_conf(channel); dma_dst_array_v = dma_alloc_coherent(NULL, TEST_LEN, &dma_dst_array_p, GFP_KERNEL ); // 25 unsinged int dma_src_array_v = dma_alloc_coherent(NULL, TEST_LEN, &dma_src_array_p, GFP_KERNEL ); struct mt_gdma_conf dma_conf = { .count = TEST_LEN, .src = dma_src_array_p, .dst = dma_dst_array_p, .iten = (testcase == 2) ? DMA_FALSE : DMA_TRUE, .isr_cb = (testcase == 2) ? NULL : irq_dma_handler, .data = channel, .burst = DMA_CON_BURST_SINGLE, .dfix = DMA_FALSE, .sfix = DMA_FALSE, //.cohen = DMA_TRUE, //enable coherence bus .sec = DMA_FALSE, // non-security channel .domain = 0, .limiter = (testcase == 3 || testcase == 4) ? 0x3FF : 0, }; for(i = 0; i < LEN; i++) { dma_dst_array_v[i] = 0; dma_src_array_v[i] = i; } if ( mt_config_gdma(channel, &dma_conf, ALL) != 0) { printk("ERROR set DMA\n"); goto _exit; return; } /* unsigned int dma_src = readl(DMA_SRC(DMA_BASE_CH(channel))); unsigned int dma_dst = readl(DMA_DST); unsigned int len = readl(DMA_LEN1); printk("start dma channel %d src = 0x%x, dst = 0x%x, len = %d bytes\n", channel, dma_src, dma_dst, len); */ start_dma=mt_start_gdma(channel); #ifdef CONFIG_OF mt_irq_dump_status(cqdma_irq_num); #else mt_irq_dump_status(CQ_DMA_IRQ_BIT_ID); #endif printk("Start %d\n",start_dma); switch(testcase) { case 1: while(!DMA_INT_DONE); #ifdef CONFIG_OF mt_irq_dump_status(cqdma_irq_num); #else mt_irq_dump_status(CQ_DMA_IRQ_BIT_ID); #endif DMA_INT_DONE=0; break; case 2: if (mt_polling_gdma(channel, GDMA_WARM_RST_TIMEOUT) != 0) printk("Polling transfer failed\n"); else printk("Polling succeeded\n"); mt_free_gdma(channel); break; case 3: mt_warm_reset_gdma(channel); for(i = 0; i < LEN; i++) { if(dma_dst_array_v[i] != dma_src_array_v[i]) { printk("Warm reset succeeded\n"); break; } mt_free_gdma(channel); } if(i == LEN) printk("Warm reset failed\n"); break; case 4: mt_hard_reset_gdma(channel); for(i = 0; i < LEN; i++) { if(dma_dst_array_v[i] != dma_src_array_v[i]) { printk("Hard reset succeeded\n"); break; } mt_free_gdma(channel); } if(i == LEN) printk("Hard reset failed\n"); break; case 5: do { mdelay(50); printk("GIC mask test cnt = %d\n", cnt); if (cnt-- == 0) { mt_irq_unmask(irq_get_irq_data(cqdma_irq_num)); printk("GIC Mask PASS !!!\n"); break; } }while(!DMA_INT_DONE); #ifdef CONFIG_OF mt_irq_dump_status(cqdma_irq_num); #else mt_irq_dump_status(CQ_DMA_IRQ_BIT_ID); #endif DMA_INT_DONE=0; break; case 6: do { mdelay(50); printk("GIC ack test cnt = %d\n", cnt); if (cnt-- == 0) { mt_irq_mask_restore(&mask); printk("GIC Mask All PASS !!!\n"); break; } }while(!DMA_INT_DONE); #ifdef CONFIG_OF mt_irq_dump_status(cqdma_irq_num); #else mt_irq_dump_status(CQ_DMA_IRQ_BIT_ID); #endif DMA_INT_DONE=0; break; default: break; } _exit: if(dma_dst_array_v){ dma_free_coherent(NULL, TEST_LEN, dma_dst_array_v, dma_dst_array_p); dma_dst_array_v = dma_dst_array_p = NULL; } if(dma_src_array_v){ dma_free_coherent(NULL, TEST_LEN, dma_src_array_v, dma_src_array_p); dma_src_array_v = dma_src_array_p = NULL; } return; } static ssize_t cqdma_dvt_show(struct device_driver *driver, char *buf) { return snprintf(buf, PAGE_SIZE, "==CQDMA test==\n" "1.CQDMA transfer (interrupt mode)\n" "2.CQDMA transfer (polling mode)\n" "3.CQDMA warm reset\n" "4.CQDMA hard reset\n" "5.Mask CQDMA interrupt test\n" "6.Mask all CQDMA interrupt test\n" ); } static ssize_t cqdma_dvt_store(struct device_driver *driver, const char *buf, size_t count) { char *p = (char *)buf; unsigned int num; num = simple_strtoul(p, &p, 10); switch(num){ /* Test APDMA Normal Function */ case 1: APDMA_test_transfer(1); break; case 2: APDMA_test_transfer(2); break; case 3: APDMA_test_transfer(3); break; case 4: APDMA_test_transfer(4); break; case 5: mt_irq_mask(irq_get_irq_data(cqdma_irq_num)); APDMA_test_transfer(5); break; case 6: mt_irq_mask_all(&mask); APDMA_test_transfer(6); break; default: break; } return count; }
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; }
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; struct spm_lp_scen *lpscen; lpscen = spm_check_talking_get_lpscen(&__spm_dpidle, &spm_flags); pcmdesc = lpscen->pcmdesc; pwrctrl = lpscen->pwrctrl; set_pwrctrl_pcm_flags(pwrctrl, spm_flags); /* set PMIC WRAP table for deepidle power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_DEEPIDLE); 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(); 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_kick_pcm_to_run(pwrctrl); spm_dpidle_before_wfi(); spm_trigger_wfi_for_dpidle(pwrctrl); spm_dpidle_after_wfi(); __spm_get_wakeup_status(&wakesta); __spm_clean_after_wakeup(); 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); /* set PMIC WRAP table for normal power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_NORMAL); return wr; }
/* 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_mcdi_ipi_test(int cpu) { wake_status_t *wakesta; unsigned long flags; struct mtk_irq_mask mask; wake_reason_t wr = WR_NONE; u32 con0; bool sodi_en = 0; spin_lock_irqsave(&spm_lock, flags); //mt_irq_mask_all(&mask); //mt_irq_unmask_for_sleep(MT_SPM0_IRQ_ID); if(cpu==0)//except mcdi { mt_irq_mask_all(&mask); mt_irq_unmask_for_sleep(MT_SPM0_IRQ_ID); //spm_wdt_config(false); mt_cirq_clone_gic(); mt_cirq_enable(); } pcm_config_sodi.spm_request_uart_sleep = true; pcm_config_sodi.wake_src=WAKE_SRC_FOR_SODI; if((sodi_en==1)&&(cpu==0))//SODI { spm_direct_enable_sodi(); pcm_config_sodi.wfi_sel[0]=true; pcm_config_sodi.wfi_sel[1]=true; pcm_config_sodi.wfi_scu_mask=false; pcm_config_sodi.wfi_l2c_mask=false; spm_write(SPM_PCM_RESERVE,spm_read(SPM_PCM_RESERVE)&~0x1); } else if((sodi_en==0)&&(cpu==0))//CPU Dormant { pcm_config_sodi.wfi_sel[0]=true; pcm_config_sodi.wfi_sel[1]=true; pcm_config_sodi.wfi_scu_mask=false; pcm_config_sodi.wfi_l2c_mask=false; spm_direct_disable_sodi(); spm_write(SPM_PCM_RESERVE,spm_read(SPM_PCM_RESERVE)&~0x1); } else if((sodi_en==0)&&(cpu!=0))//MCDI { //pcm_config_sodi.wake_src=WAKE_SRC_FOR_MCDI; pcm_config_sodi.wake_src=0x0;//for test IPI only pcm_config_sodi.wfi_sel[0]=false; pcm_config_sodi.wfi_sel[1]=true; pcm_config_sodi.wfi_scu_mask=true; pcm_config_sodi.wfi_l2c_mask=true; pcm_config_sodi.spm_request_uart_sleep = false; spm_direct_disable_sodi(); spm_write(SPM_PCM_RESERVE,spm_read(SPM_PCM_RESERVE)|0x1); } else { printk("[SPM]Wrong para!!\n"); goto RESTORE_IRQ; } if( spm_last_senario != pcm_config_sodi.scenario)//MCDI SPM Initialize { //spm_direct_enable_sodi(); if (spm_init_pcm(&pcm_config_sodi)==false) goto RESTORE_IRQ; if(cpu==1)//except mcdi { spm_write(SPM_SLEEP_CPU_IRQ_MASK,0x2); spm_mcdi_init_core_mux(); } else 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_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_change_fw = 1; } else { if(cpu==1)//except mcdi { spm_write(SPM_SLEEP_CPU_IRQ_MASK,0x2); //spm_mcdi_init_core_mux(); } 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; } if(cpu==0) { soidle_before_wfi(); spm_trigger_wfi_for_dpidle(1);//SODI with cpu dormant soidle_after_wfi(sodi_en); } else { spm_pre_SPM_PCM_SW_INT_SET=spm_read(SPM_PCM_SW_INT_SET); spm_pre_SPM_SLEEP_ISR_STATUS=spm_read(SPM_SLEEP_ISR_STATUS); spm_write(SPM_PCM_SW_INT_CLEAR,0xf); //mcidle_before_wfi(cpu); if (!cpu_power_down(DORMANT_MODE)) { switch_to_amp(); /* do not add code here */ wfi_with_sync(); } switch_to_smp(); cpu_check_dormant_abort(); //mcidle_after_wfi(cpu); spm_post_SPM_PCM_SW_INT_SET=spm_read(SPM_PCM_SW_INT_SET); spm_post_SPM_SLEEP_ISR_STATUS=spm_read(SPM_SLEEP_ISR_STATUS); spm_post_SPM_PCM_RESERVE = spm_read(SPM_PCM_RESERVE ); } #if 1 wakesta = spm_get_wakeup_status(&pcm_config_sodi); wr = wakesta->wake_reason; #endif spm_clean_after_wakeup(); spm_write(SPM_PCM_CON1,(spm_read(SPM_PCM_CON1)| CON1_CFG_KEY )|(CON1_PCM_TIMER_EN)); RESTORE_IRQ: if(cpu==0)//except mcdi { mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); } //mt_irq_mask_restore(&mask); 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; }
/* * pwrlevel: * 0: CPU standby + AP sleep (SRCLKENA high) => legacy deep idle * 1: CPU dormant (L1/L2 sleep) + AP sleep (SRCLKENA high) * 2: CPU shutdown (L1/L2 power down) + AP sleep (SRCLKENA high) */ void sc_go_to_dpidle(unsigned int pwrlevel) { u32 wakesrc, dvfscon, clksettle; unsigned long flags; struct mtk_irq_mask mask; wakesrc = WAKE_SRC_KP | WAKE_SRC_MSDC1 | WAKE_SRC_EINT | WAKE_SRC_RTC | WAKE_SRC_CCIF_MD | WAKE_SRC_ACCDET | WAKE_SRC_GPT | WAKE_SRC_AFE; spin_lock_irqsave(&sc_lock, flags); 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); /* keep SRCLKENA high (26M on) when in sleep mode */ sc_write(SC_CLK_CON, sc_read(SC_CLK_CON) | SC_CLK_CON_SRCLKEN); /* set SYSCLK settle time to 1T 32K */ clksettle = sc_read(SC_CLK_SETTLE); sc_write(SC_CLK_SETTLE, SC_CLK_SETTLE_26MON); sc_write(SC_PAUSE, 0xffffffff); /* unmask wakeup sources */ sc_write(SC_WAKEUP_EVENT_MASK, ~wakesrc); /* unmask Pause Interrupt and Pause Abort */ sc_write(SC_ISR_MASK, 0x0001); sc_write(SC_TIMER_CON, SC_TIMER_CON_EN); sc_write(SC_TIMER_CMD, SC_TIMER_CMD_KEY | SC_TIMER_CMD_CONWR | SC_TIMER_CMD_CNTWR | SC_TIMER_CMD_WR); while (!(sc_read(SC_TIMER_STA) & SC_TIMER_STA_CMDCPL)); if (sc_dpidle_can_enter()) { sc_write(SC_TIMER_CMD, SC_TIMER_CMD_KEY | SC_TIMER_CMD_PAUSE); while (!(sc_read(SC_TIMER_STA) & SC_TIMER_STA_CMDCPL)); sc_dpidle_before_wfi(); sc_wait_for_interrupt(pwrlevel, true); sc_dpidle_after_wfi(); } /* delay to make sure ISR_STATUS can be cleared later */ udelay(100); /* for cleaning wakeup source status */ sc_write(SC_DBG_WAKEUP, 0); sc_write(SC_TIMER_CON, SC_TIMER_CON_DBG | SC_TIMER_CON_EN); sc_write(SC_TIMER_CMD, SC_TIMER_CMD_KEY | SC_TIMER_CMD_CONWR | SC_TIMER_CMD_WR); while (!(sc_read(SC_TIMER_STA) & SC_TIMER_STA_CMDCPL)); sc_write(SC_ISR_MASK, 0x0007); sc_write(SC_ISR_STATUS, 0x0007); /* write 1 clear */ /* restore SC_CLK_SETTLE and SC_CLK_CON */ sc_write(SC_CLK_SETTLE, clksettle); sc_write(SC_CLK_CON, sc_read(SC_CLK_CON) & ~SC_CLK_CON_SRCLKEN); sc_write_sync(); /* 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); }
/* * 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; }
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; }
/* * 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; }
/* * 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; }
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; #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(1<<SPM_SODI_ENTER); #endif set_pwrctrl_pcm_flags(pwrctrl, spm_flags); /* set PMIC WRAP table for deepidle power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_SODI); 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_SPM_IRQ_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_SPM_FLOW)); #endif __spm_reset_and_init_pcm(pcmdesc); #if 0 /* 0: mempll shutdown mode; 1: cg mode */ gSpm_SODI_mempll_pwr_mode ? (pwrctrl->pcm_flags |= SPM_MEMPLL_CPU) : (pwrctrl->pcm_flags &= ~SPM_MEMPLL_CPU); #endif __spm_kick_im_to_fetch(pcmdesc); __spm_init_pcm_register(); __spm_init_event_vector(pcmdesc); /* set pcm_apsrc_req to be 1 if 10006b0c[0] is 1 */ if ((spm_read(SPM_PCM_SRC_REQ) & 1) || pwrctrl->pcm_apsrc_req) pwrctrl->pcm_apsrc_req = 1; else pwrctrl->pcm_apsrc_req = 0; __spm_set_power_control(pwrctrl); __spm_set_wakeup_event(pwrctrl); /* set pcm_flags[18] to be 1 if 10006b08[7] is 1 */ if ((spm_read(SPM_PCM_FLAGS) & SPM_MEMPLL_RESET) || gSpm_SODI_mempll_pwr_mode || (pwrctrl->pcm_flags_cust & SPM_MEMPLL_CPU)) pwrctrl->pcm_flags |= SPM_MEMPLL_CPU; else pwrctrl->pcm_flags &= ~SPM_MEMPLL_CPU; __spm_kick_pcm_to_run(pwrctrl); #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_WFI)); #endif spm_trigger_wfi_for_sodi(pwrctrl); #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_WFI)); #endif __spm_get_wakeup_status(&wakesta); __spm_clean_after_wakeup(); wr = __spm_output_wake_reason(&wakesta, pcmdesc, false); /* for test */ /* wr = __spm_output_wake_reason(&wakesta, pcmdesc, true); */ #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_SPM_FLOW)); #endif mt_cirq_flush(); mt_cirq_disable(); mt_irq_mask_restore(&mask); spin_unlock_irqrestore(&__spm_lock, flags); lockdep_on(); soidle_after_wfi(0); /* set PMIC WRAP table for normal power control */ mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_NORMAL); #if SPM_AEE_RR_REC aee_rr_rec_sodi_val(0); #endif //return wr; }