Example #1
0
/*
 * 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;
}
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;
}
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;
}
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;
}