static void spm_trigger_wfi_for_sodi(struct pwr_ctrl *pwrctrl)
{
    if (is_cpu_pdn(pwrctrl->pcm_flags)) {    
        //sodi_debug("enter mt_cpu_dormant(CPU_SODI_MODE)\n");
        mt_cpu_dormant(CPU_SODI_MODE);
        //sodi_debug("exit mt_cpu_dormant(CPU_SODI_MODE)\n");
    } else {
        u32 val = 0;
        
        //backup MP0_AXI_CONFIG
    	val = reg_read(MP0_AXI_CONFIG);
    	
    	//disable snoop function 
        MCUSYS_SMC_WRITE(MP0_AXI_CONFIG, val | ACINACTM);
        
        sodi_debug("enter legacy WIFI, MP0_AXI_CONFIG=0x%x\n", reg_read(MP0_AXI_CONFIG));
        
        //enter WFI
        wfi_with_sync();
        
        //restore MP0_AXI_CONFIG
        MCUSYS_SMC_WRITE(MP0_AXI_CONFIG, val);
        
        sodi_debug("exit legacy WIFI, MP0_AXI_CONFIG=0x%x\n", reg_read(MP0_AXI_CONFIG));
    }
}
static void spm_trigger_wfi_for_sleep(struct pwr_ctrl *pwrctrl)
{
//    sync_hw_gating_value();     /* for Vcore DVFS */

    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        spm_dormant_sta = mt_cpu_dormant(CPU_SHUTDOWN_MODE/* | DORMANT_SKIP_WFI*/);
        switch (spm_dormant_sta)
        {
            case MT_CPU_DORMANT_RESET:
                break;
            case MT_CPU_DORMANT_ABORT:
                break;
            case MT_CPU_DORMANT_BREAK:
                break;
            case MT_CPU_DORMANT_BYPASS:
                break;
        }
    } else {
        spm_dormant_sta = -1;
        spm_write(CA7_BUS_CONFIG, spm_read(CA7_BUS_CONFIG) | 0x10);
        wfi_with_sync();
        spm_write(CA7_BUS_CONFIG, spm_read(CA7_BUS_CONFIG) & ~0x10);
    }

    if (is_infra_pdn(pwrctrl->pcm_flags))
        mtk_uart_restore();
}
static void spm_trigger_wfi_for_sleep(struct pwr_ctrl *pwrctrl)
{
//FIXME: for K2 fpga early porting
#if 0
    sync_hw_gating_value();     /* for Vcore DVFS */
#endif

    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        spm_dormant_sta = mt_cpu_dormant(CPU_SHUTDOWN_MODE/* | DORMANT_SKIP_WFI*/);
        switch (spm_dormant_sta)
        {
            case MT_CPU_DORMANT_RESET:
                break;
            case MT_CPU_DORMANT_ABORT:
                break;
            case MT_CPU_DORMANT_BREAK:
                break;
            case MT_CPU_DORMANT_BYPASS:
                break;
        }
    } else {
        spm_dormant_sta = -1;
		//spm_write(MP0_AXI_CONFIG, spm_read(MP0_AXI_CONFIG) | ACINACTM);
        wfi_with_sync();
      //  spm_write(MP0_AXI_CONFIG, spm_read(MP0_AXI_CONFIG) & ~ACINACTM);
    }

    if (is_infra_pdn(pwrctrl->pcm_flags))
        mtk_uart_restore();
}
static void spm_trigger_wfi_for_dpidle(struct pwr_ctrl *pwrctrl)
{
    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        mt_cpu_dormant(CPU_DEEPIDLE_MODE);
    } else {
        wfi_with_sync();
    }
}
static void spm_trigger_wfi_for_dpidle(struct pwr_ctrl *pwrctrl)
{
    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        mt_cpu_dormant(CPU_DEEPIDLE_MODE);
    } else {
        //Mp0_axi_config[4] is one by default. No need to program it before entering suspend.
        wfi_with_sync();
    }
}
Exemple #6
0
static int slp_suspend_ops_begin(suspend_state_t state)
{
    /* legacy log */
    slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
    slp_notice("Chip_pm_begin(%u)(%u)\n", is_cpu_pdn(slp_spm_flags), is_infra_pdn(slp_spm_flags));
    slp_notice("@@@@@@@@@@@@@@@@@@@@\n");

    slp_wake_reason = WR_NONE;

    return 0;
}
static void spm_trigger_wfi_for_sodi(struct pwr_ctrl *pwrctrl)
{
    //sync_hw_gating_value();     /* for Vcore DVFS */

    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        mt_cpu_dormant(CPU_SODI_MODE);
    } else {
        
//        spm_write(CA7_BUS_CONFIG, spm_read(CA7_BUS_CONFIG) | 0x10);
        wfi_with_sync();
//        spm_write(CA7_BUS_CONFIG, spm_read(CA7_BUS_CONFIG) & ~0x10);

    }
}
static void spm_trigger_wfi_for_sodi(struct pwr_ctrl *pwrctrl)
{
    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        //sodi_debug("enter mt_cpu_dormant(CPU_SODI_MODE)\n");
        mt_cpu_dormant(CPU_SODI_MODE);
        //sodi_debug("exit mt_cpu_dormant(CPU_SODI_MODE)\n");
    } else {
        sodi_debug("enter legacy WIFI\n");

        //enter WFI
        wfi_with_sync();

        sodi_debug("exit legacy WIFI\n");
    }
}
static void spm_trigger_wfi_for_dpidle(struct pwr_ctrl *pwrctrl)
{
    //sync_hw_gating_value();     /* for Vcore DVFS */

#if 0	//deepidle no need, vproc(ext buck) can't set to 0v, because SRAM perpheral control from vproc
    spm_i2c_control(mt6333_BUSNUM, 1);
#endif

    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        mt_cpu_dormant(CPU_DEEPIDLE_MODE);
    } else {
        wfi_with_sync();
    }

#if 0	//deepidle no need, vproc(ext buck) can't set to 0v, because SRAM perpheral control from vproc
    spm_i2c_control(mt6333_BUSNUM, 0);     /* restore I2C1 power */
#endif
}
/*
 * go_to_sleep_before_wfi() - trigger SPM to enter suspend scenario
 */
static void go_to_sleep_before_wfi(const unsigned int spm_flags)
{
	struct pwr_ctrl *pwrctrl;

	pwrctrl = &spm_ctrl;

	set_pwrctrl_pcm_flags(pwrctrl, spm_flags);

	spm_set_sysclk_settle();

	INFO("sec = %u, wakesrc = 0x%x (%u)(%u)\n",
	     pwrctrl->timer_val, pwrctrl->wake_src,
	     is_cpu_pdn(pwrctrl->pcm_flags),
	     is_infra_pdn(pwrctrl->pcm_flags));

	spm_reset_and_init_pcm();
	spm_init_pcm_register();
	spm_set_power_control(pwrctrl);
	spm_set_wakeup_event(pwrctrl);
	spm_kick_pcm_to_run(pwrctrl);
	spm_init_event_vector(&suspend_pcm_ca7);
	spm_kick_im_to_fetch(&suspend_pcm_ca7);
}
Exemple #11
0
static void spm_trigger_wfi_for_dpidle(struct pwr_ctrl *pwrctrl)
{
    u32 v0, v1;

    if (is_cpu_pdn(pwrctrl->pcm_flags)) {
        mt_cpu_dormant(CPU_DEEPIDLE_MODE);
    } else {
        //Mp0_axi_config[4] is one by default. No need to program it before entering suspend.
        //backup MPx_AXI_CONFIG
        v0 = reg_read(MP0_AXI_CONFIG);
        v1 = reg_read(MP1_AXI_CONFIG);
        
        //disable snoop function 
        MCUSYS_SMC_WRITE(MP0_AXI_CONFIG, v0 | ACINACTM);
        MCUSYS_SMC_WRITE(MP1_AXI_CONFIG, v1 | ACINACTM);

        wfi_with_sync();

        //restore MP0_AXI_CONFIG
        MCUSYS_SMC_WRITE(MP0_AXI_CONFIG, v0);
        MCUSYS_SMC_WRITE(MP1_AXI_CONFIG, v1);
    }
}
/*
 * 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;  
}
Exemple #13
0
static int slp_suspend_ops_enter(suspend_state_t state)
{
    int ret = 0;

#ifdef CONFIG_MTK_TC1_FM_AT_SUSPEND
    int fm_radio_is_playing = 0;
    if ( ConditionEnterSuspend() == true )
    	fm_radio_is_playing = 0;
    else
    	fm_radio_is_playing = 1;
#endif /* CONFIG_MTK_TC1_FM_AT_SUSPEND */ 
#ifdef CONFIG_MTKPASR
    /* PASR SW operations */
    enter_pasrdpd();
#endif

    /* legacy log */
    slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
    slp_crit2("Chip_pm_enter\n");
    slp_notice("@@@@@@@@@@@@@@@@@@@@\n");

//FIXME: for K2 bring up
    if (slp_dump_gpio)
        gpio_dump_regs();
#if 0
    if (slp_dump_regs)
        slp_dump_pm_regs();
#endif

    if (slp_check_mtcmos_pll)
        slp_check_pm_mtcmos_pll();

    if (!spm_cpusys0_can_power_down()) {
        slp_error("CANNOT SLEEP DUE TO CPU1~x PON, SPM_PWR_STATUS = 0x%x, SPM_PWR_STATUS_2ND = 0x%x\n",
                  slp_read(SPM_PWR_STATUS), slp_read(SPM_PWR_STATUS_2ND));
        //return -EPERM;
        ret = -EPERM;
        goto LEAVE_SLEEP;
    }

    if (is_infra_pdn(slp_spm_flags) && !is_cpu_pdn(slp_spm_flags)) {
        slp_error("CANNOT SLEEP DUE TO INFRA PDN BUT CPU PON\n");
        //return -EPERM;
        ret = -EPERM;
        goto LEAVE_SLEEP;
    }

    
    /* only for test */
    #if 0
    slp_pasr_en(1, 0x0);
    slp_dpd_en(1);
    #endif

#if SLP_SLEEP_DPIDLE_EN
#ifdef CONFIG_MTK_TC1_FM_AT_SUSPEND
    if (slp_ck26m_on | fm_radio_is_playing)
#else
    if (slp_ck26m_on)
#endif
        slp_wake_reason = spm_go_to_sleep_dpidle(slp_spm_deepidle_flags, slp_spm_data);
    else
#endif
        slp_wake_reason = spm_go_to_sleep(slp_spm_flags, slp_spm_data);

LEAVE_SLEEP:
#ifdef CONFIG_MTKPASR
    /* PASR SW operations */
    leave_pasrdpd();
#endif

#ifdef CONFIG_MTK_SYSTRACKER
    systracker_enable();
#endif

    return ret;
}
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;
}