void spm_mcdi_poll_mask(u32 core_id,bool core_wfi_sel[]) { while((spm_read(SPM_SLEEP_CPU_IRQ_MASK) & (0x1 << core_id) )==0); #if 0 { if(core_id==0) spm_wfi_sel(core_wfi_sel, SPM_CORE1_WFI_SEL_SW_MASK );//check Core IRQ Mask else spm_wfi_sel(core_wfi_sel, SPM_CORE0_WFI_SEL_SW_MASK );;//check Core IRQ Mask } #endif }
static void spm_set_ap_standbywfi(u32 md_mask,u32 mm_mask,u32 wfi_scu_mask,u32 wfi_l2c_mask,u32 wfi_op,bool core_wfi_sel[]) { //spm_crit2("md_mask:0x%X,mm_mask:0x%X,wfi_scu_mask:0x%X,wfi_l2c_mask:0x%X,wfi_op:0x%X,wfi_sel:0x%X\n",md_mask,mm_mask,wfi_scu_mask,wfi_l2c_mask,wfi_op,wfi_sel); spm_write(SPM_AP_STANBY_CON, (md_mask << 19) | /* unmask MD1 and MD2 */ (mm_mask << 16) | /* unmask DISP and MFG */ (wfi_scu_mask << 6) | /* check SCU idle */ (wfi_l2c_mask << 5) | /* check L2C idle */ (wfi_op << 4)); /* Reduce AND */ spm_wfi_sel(core_wfi_sel, 0 ); }
//extern u32 cpu_pdn_cnt; void spm_mcdi_wfi(void) { volatile u32 core_id; //u32 clc_counter; unsigned long flags; //u32 temp_address; #if 0 core_id = (u32)smp_processor_id(); if(core_id == 0) { if(MCDI_Test_Mode == 1) { //clc_notice("SPM_FC1_PWR_CON %x, cpu_pdn_cnt %d.\n",spm_read(SPM_FC1_PWR_CON),cpu_pdn_cnt); clc_notice("core_%d set wfi_sel.\n", core_id); } spm_wfi_sel(pcm_config_mcdi.wfi_sel, SPM_CORE1_WFI_SEL_SW_MASK ); spm_mcdi_poll_mask(core_id,pcm_config_mcdi.wfi_sel); if(MCDI_Test_Mode == 1) { clc_notice("core_%d mask polling done.\n", core_id); } wfi_with_sync(); // enter wfi //spm_get_wakeup_status(&pcm_config_mcdi); if(MCDI_Test_Mode == 1) clc_notice("core_%d exit wfi.\n", core_id); //if(MCDI_Test_Mode == 1) //mdelay(10); // delay 10 ms } else // Core 1 Keep original IRQ #endif { if(MCDI_Test_Mode == 1) { clc_notice("core_%d set wfi_sel.\n", core_id); } spm_wfi_sel(pcm_config_mcdi.wfi_sel, SPM_CORE0_WFI_SEL_SW_MASK ); ////clc_notice("core_%d enter wfi.\n", core_id); spm_mcdi_poll_mask(core_id,pcm_config_mcdi.wfi_sel); if(MCDI_Test_Mode == 1) { clc_notice("core_%d mask polling done.\n", core_id); } mcidle_before_wfi(1); 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(1); spm_get_wakeup_status(&pcm_config_mcdi); if(MCDI_Test_Mode == 1) clc_notice("core_%d exit wfi.\n", core_id); } }
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; }
/* 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; }