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

}
Beispiel #2
0
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;

}