コード例 #1
0
void spm_go_to_sodi(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_sodi.pcmdesc;
    struct pwr_ctrl *pwrctrl = __spm_sodi.pwrctrl;

#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(1<<SPM_SODI_ENTER);
#endif 
    
#if defined (CONFIG_ARM_PSCI)||defined(CONFIG_MTK_PSCI)
    spm_flags &= ~SPM_DISABLE_ATF_ABORT;
#else
    spm_flags |= SPM_DISABLE_ATF_ABORT;
#endif

	if(gSpm_SODI_mempll_pwr_mode == 1)
	{
		spm_flags |= SPM_MEMPLL_CG_EN; //MEMPLL CG mode
	}
	else
	{
		spm_flags &= ~SPM_MEMPLL_CG_EN; //DDRPHY power down mode
	}

    set_pwrctrl_pcm_flags(pwrctrl, spm_flags);
    
    //If Vcore DVFS is disable, force to disable SODI internal Vcore DVS
    if (pwrctrl->pcm_flags_cust == 0)
    {
    	//force to bypass Vcore DVS in SODI. 
    	//In D3, low level of Vcore is 1.15V, and it is enough for MD/CONN. 
    	//So, SODI doesn't need to do Vcore DVS
        pwrctrl->pcm_flags |= SPM_VCORE_DVS_EVENT_DIS;
    }
    
    //If SODI internal Vcore DVS is enabled, DRAM must be in low frequency
    if ((pwrctrl->pcm_flags & SPM_VCORE_DVS_EVENT_DIS) == 0)
    {
        if (get_ddr_khz() != FDDR_S1_KHZ)
        {
            sodi_debug("warning: get_ddr_khz() = %d\n", get_ddr_khz());
        }
    }
    
    //enable APxGPT timer
	soidle_before_wfi(0);
	
	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();

	__spm_enable_i2c4_clk();

#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_UART_SLEEP));
#endif     

    if (request_uart_to_sleep()) {
        wr = WR_UART_BUSY;
        goto RESTORE_IRQ;
    }
    
#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_SPM_FLOW));
#endif

    __spm_reset_and_init_pcm(pcmdesc);

	/*
	 * When commond-queue is in shut-down mode, SPM will hang if it tries to access commond-queue status.  
     * Follwoing patch is to let SODI driver to notify SPM that commond-queue is in shut-down mode or not to avoid above SPM hang issue. 
     * But, now display can automatically notify SPM that command-queue is shut-down or not, so following code is not needed anymore.
	 */
	#if 0 
    //check GCE
	if(clock_is_on(MT_CG_INFRA_GCE))
	{
		pwrctrl->pcm_flags &= ~SPM_DDR_HIGH_SPEED; 
	}
	else
	{
		pwrctrl->pcm_flags |= SPM_DDR_HIGH_SPEED; 
	}
	#endif

    __spm_kick_im_to_fetch(pcmdesc);
    
    __spm_init_pcm_register();
    
    __spm_init_event_vector(pcmdesc);
    
#if 0
    //Display set SPM_PCM_SRC_REQ[0]=1'b1 to force DRAM not enter self-refresh mode
	if((spm_read(SPM_PCM_SRC_REQ)&0x00000001))
	{
		pwrctrl->pcm_apsrc_req = 1;
	}
	else
	{
		pwrctrl->pcm_apsrc_req = 0;
	}
#endif

    __spm_set_power_control(pwrctrl);
    
    __spm_set_wakeup_event(pwrctrl);
    
#if SODI_DVT_PCM_TIMER_DISABLE
	//PCM_Timer is enable in above '__spm_set_wakeup_event(pwrctrl);', disable PCM Timer here
	spm_write(SPM_PCM_CON1 ,spm_read(SPM_PCM_CON1)&(~CON1_PCM_TIMER_EN));
#endif

    spm_sodi_pre_process();
    
    __spm_kick_pcm_to_run(pwrctrl);

#if SPM_SODI_DUMP_REGS
    printk("============SODI Before============\n");
    spm_sodi_dump_regs(); //dump debug info
#endif
      
#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_WFI));
#endif

#ifdef SPM_SODI_PROFILE_TIME
    gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[1]);
#endif

    spm_trigger_wfi_for_sodi(pwrctrl);

#ifdef SPM_SODI_PROFILE_TIME
    gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[2]);
#endif

#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_WFI));
#endif

#if SPM_SODI_DUMP_REGS
    printk("============SODI After=============\n");
    spm_sodi_dump_regs();//dump debug info
#endif

    spm_sodi_post_process();
    
    __spm_get_wakeup_status(&wakesta);
    
    sodi_debug("emi-selfrefrsh cnt = %d, pcm_flag = 0x%x, SPM_PCM_RESERVE2 = 0x%x, %s\n", spm_read(SPM_PCM_PASR_DPD_3), spm_read(SPM_PCM_FLAGS), spm_read(SPM_PCM_RESERVE2), pcmdesc->version);
    
    __spm_clean_after_wakeup();

#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_ENTER_UART_AWAKE));
#endif

    request_uart_to_wakeup();

    wr = __spm_output_wake_reason(&wakesta, pcmdesc, false);
    if (wr == WR_PCM_ASSERT)
    {
        sodi_err("PCM ASSERT AT %u (%s), r13 = 0x%x, debug_flag = 0x%x\n", wakesta.assert_pc, pcmdesc->version, wakesta.r13, wakesta.debug_flag);   
    }
    
#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_LEAVE_SPM_FLOW));
#endif  

	__spm_disable_i2c4_clk();

RESTORE_IRQ:
    mt_cirq_flush();
    mt_cirq_disable();
    mt_irq_mask_restore(&mask);
	
    spin_unlock_irqrestore(&__spm_lock, flags);
    lockdep_on();

    //stop APxGPT timer and enable caore0 local timer
    soidle_after_wfi(0);  

#if SODI_DVT_SPM_MEM_RW_TEST
    {	
        static u32 magic_init = 0;
        int i =0;

        if(magic_init == 0){
		    magic_init++;
		    printk("magicNumArray:0x%p",magicArray);
	    }

    	for(i=0;i<16;i++)
    	{
    		if(magicArray[i]!=SODI_DVT_MAGIC_NUM)
    		{
    			printk("Error: sodi magic number no match!!!");
    			ASSERT(0);
    		}
    	}
    	
    	if (i>=16)
    	    printk("SODI_DVT_SPM_MEM_RW_TEST pass (count = %d)\n", magic_init);
    }
#endif

#if SPM_AEE_RR_REC
    aee_rr_rec_sodi_val(0);
#endif 
}
コード例 #2
0
ファイル: mt_spm_dpidle3.c プロジェクト: Klozz/P8000-Kernel
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 

	/* Workaround: do NOT lower VPROC for turbo mode */
	/* Workaround (2015.04.17): do NOT lower VPROC for FW v0.2.5 */
#if 0
	if (is_ext_buck_exist())
#endif
		spm_flags |= SPM_CPU_DVS_DIS;

    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();

	__spm_enable_i2c4_clk();

#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);

	__spm_disable_i2c4_clk();

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