Esempio n. 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;
}
/*
 * 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);
}
Esempio n. 3
0
bool spm_init_pcm(SPM_PCM_CONFIG* pcm_config)
{
  u32 timer_val,wdt_timer_val;
  bool wfi_sel[2] = {false,false};

  pcm_config_curr =   pcm_config;
    
    if(pcm_config->scenario == SPM_PCM_DEEP_IDLE)
        spm_crit2("%s with cpu_pdn=%d, pwr_level=%d, infra_pdn=%d\n",pcm_scenario[pcm_config->scenario],pcm_config->cpu_pdn,pcm_config->pcm_pwrlevel,pcm_config->infra_pdn);
    else
        spm_crit2("%s with cpu_pdn=%d, infra_pdn=%d\n",pcm_scenario[pcm_config->scenario],pcm_config->cpu_pdn,pcm_config->infra_pdn);
     //spm_crit2("spm_init_pcm():%s, timer_val: %d, wake_src:0x%X \n",pcm_scenario[pcm_config->scenario],pcm_config->timer_val_sec,pcm_config->wake_src);


  /*
  if(pcm_config->scenario == SPM_PCM_KERNEL_SUSPEND)
    pcm_config_curr->cpu_status = SHUTDOWN_MODE;
  else if(pcm_config->scenario == SPM_PCM_DEEP_IDLE)
    pcm_config_curr->cpu_status = DORMANT_MODE;*/
    
      
  pcm_config->wakesta[pcm_config->wakesta_idx].wake_reason = WR_NONE ;
  
  spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));

 
   //if pcm will turn on and off the 26Mhz, we need to setup the settle time
    if(pcm_config->spm_turn_off_26m)
        spm_set_sysclk_settle();

    spm_reset_and_init_pcm();
    
    /*init Instruction Memory*/
    spm_kick_im_to_fetch(pcm_config->pcm_firmware_addr,pcm_config->pcm_firmware_len);

    if (pcm_config->spm_request_uart_sleep)
        if(spm_request_uart_to_sleep()){
            return false;
    }
    
    /*init R0 ,R7*/
    if(pcm_config->sync_r0r7)
        spm_init_pcm_register();
    
	
	/*init VSRs*/
	spm_init_event_vector(pcm_config->pcm_vsr);

    /*Setup pwr level if necessary*/
    spm_set_ap_pwrctl(pcm_config->pcm_pwrlevel);

    if(pcm_config->scenario == SPM_PCM_MCDI)
    {
    	/* set standby wfi */
         spm_set_ap_standbywfi(pcm_config->md_mask,
    	                      pcm_config->mm_mask,
    	                      pcm_config->wfi_scu_mask,
    	                      pcm_config->wfi_l2c_mask,
    	                      pcm_config->wfi_op,
    	                      wfi_sel);

    }
    else
    {
        
    	/* set standby wfi */
         spm_set_ap_standbywfi(pcm_config->md_mask,
    	                      pcm_config->mm_mask,
    	                      pcm_config->wfi_scu_mask,
    	                      pcm_config->wfi_l2c_mask,
    	                      pcm_config->wfi_op,
    	                      pcm_config->wfi_sel);
    }
	
    timer_val= (unsigned int)((pcm_config->timer_val_ms * 32768)/1024);//In the unit of 32Khz
    wdt_timer_val = (unsigned int)((pcm_config->wdt_val_ms * 32768)/1024);//In the unit of 32Khz
	
    //spm_set_wakeup_event(pcm_config->timer_val_sec * 32768,pcm_config->wake_src);
//if(pcm_config->scenario != SPM_PCM_WDT) 
    spm_set_wakeup_event(timer_val,wdt_timer_val,pcm_config->wake_src);

    return true;
    
}
Esempio n. 4
0
/*
 * 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;
}