예제 #1
0
static irqreturn_t spm_irq_aux_handler(u32 irq_id)
{
	u32 isr;
	unsigned long flags;

	spin_lock_irqsave(&__spm_lock, flags);
	isr = spm_read(SPM_SLEEP_ISR_STATUS);
	spm_write(SPM_PCM_SW_INT_CLEAR, (1U << irq_id));
	spin_unlock_irqrestore(&__spm_lock, flags);

	spm_err("IRQ%u HANDLER SHOULD NOT BE EXECUTED (0x%x)\n", irq_id, isr);

	return IRQ_HANDLED;
}
예제 #2
0
void spm_deepidle_init(void)
{
#if defined (CONFIG_OF)
    struct device_node *node;
    struct resource r;

    /* mcucfg */
    node = of_find_compatible_node(NULL, NULL, MCUCFG_NODE);
    if (!node) 
    {
        spm_err("error: cannot find node " MCUCFG_NODE); 
        BUG();
    }
    if (of_address_to_resource(node, 0, &r)) {
        spm_err("error: cannot get phys addr" MCUCFG_NODE);
        BUG();
    }
    mcucfg_phys_base = r.start;

    mcucfg_base = (unsigned long)of_iomap(node, 0);
    if(!mcucfg_base) {
        spm_err("error: cannot iomap " MCUCFG_NODE);
        BUG();
    }
    
    printk("mcucfg_base = 0x%u\n", (unsigned int)mcucfg_base); 
#endif

#if SPM_USE_TWAM_DEBUG
	unsigned long flags;
	struct twam_sig twamsig = {
		.sig0 = 26,	/* md1_srcclkena */
		.sig1 = 22,	/* md_apsrc_req_mux */
		.sig2 = 25,	/* md2_srcclkena */
		.sig3 = 21,	/* md2_apsrc_req_mux */		
		//.sig2 = 23,	/* conn_srcclkena */
		//.sig3 = 20,	/* conn_apsrc_req */
	};
#if 0
	spin_lock_irqsave(&__spm_lock, flags);
	spm_write(SPM_AP_STANBY_CON, spm_read(SPM_AP_STANBY_CON) | ASC_MD_DDR_EN_SEL);
	spin_unlock_irqrestore(&__spm_lock, flags);
#endif
	spm_twam_register_handler(twam_handler);
	spm_twam_enable_monitor(&twamsig, false,SPM_TWAM_MONITOR_TICK);
#endif
}


MODULE_DESCRIPTION("SPM-DPIdle Driver v0.1");
void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
{
	/* set other SYS request mask */
	spm_write(SPM_AP_STANBY_CON, (!pwrctrl->md_vrf18_req_mask_b << 29) |
                     (!pwrctrl->lte_mask << 26) |
                     (!pwrctrl->srclkenai_mask<<25 ) |
                     (!!pwrctrl->md2_apsrc_sel << 24) |
                     (!pwrctrl->conn_mask << 23) |
                     (!!pwrctrl->md_apsrc_sel << 22) |
				     (!pwrctrl->md32_req_mask << 21) |
				     (!pwrctrl->md2_req_mask << 20) |
				     (!pwrctrl->md1_req_mask << 19) |
				     (!pwrctrl->gce_req_mask << 18) |
				     (!pwrctrl->mfg_req_mask << 17) |
				     (!pwrctrl->disp_req_mask << 16) |
				     (!!pwrctrl->mcusys_idle_mask << 7) |
				     (!!pwrctrl->ca15top_idle_mask << 6) |
				     (!!pwrctrl->ca7top_idle_mask << 5) |
				     (!!pwrctrl->wfi_op << 4));
	spm_write(SPM_PCM_SRC_REQ, (!pwrctrl->ccifmd_md2_event_mask << 8) |
                               (!pwrctrl->ccifmd_md1_event_mask << 7) |
                               (!pwrctrl->ccif1_to_ap_mask << 5) |
                               (!pwrctrl->ccif1_to_md_mask << 4) |
                               (!pwrctrl->ccif0_to_ap_mask << 3) |
				               (!pwrctrl->ccif0_to_md_mask << 2) |
                               (!!pwrctrl->pcm_f26m_req << 1) |
                               (!!pwrctrl->pcm_apsrc_req << 0));
	spm_write(SPM_PCM_PASR_DPD_2, (!pwrctrl->isp1_ddr_en_mask << 4) |
				      (!pwrctrl->isp0_ddr_en_mask << 3) |
				      (!pwrctrl->dpi_ddr_en_mask << 2) |
				      (!pwrctrl->dsi1_ddr_en_mask << 1) |

				      (!pwrctrl->dsi0_ddr_en_mask << 0));

#if 0
	spm_write(SPM_CLK_CON, (spm_read(SPM_CLK_CON) & ~CC_SRCLKENA_MASK_0) |
			       (pwrctrl->srclkenai_mask ? CC_SRCLKENA_MASK_0 : 0));
#endif

	/* set CPU WFI mask */
	spm_write(SPM_SLEEP_CA15_WFI0_EN, !!pwrctrl->ca15_wfi0_en);
	spm_write(SPM_SLEEP_CA15_WFI1_EN, !!pwrctrl->ca15_wfi1_en);
	spm_write(SPM_SLEEP_CA15_WFI2_EN, !!pwrctrl->ca15_wfi2_en);
	spm_write(SPM_SLEEP_CA15_WFI3_EN, !!pwrctrl->ca15_wfi3_en);
	spm_write(SPM_SLEEP_CA7_WFI0_EN, !!pwrctrl->ca7_wfi0_en);
	spm_write(SPM_SLEEP_CA7_WFI1_EN, !!pwrctrl->ca7_wfi1_en);
	spm_write(SPM_SLEEP_CA7_WFI2_EN, !!pwrctrl->ca7_wfi2_en);
	spm_write(SPM_SLEEP_CA7_WFI3_EN, !!pwrctrl->ca7_wfi3_en);
}
bool spm_check_wakeup_src(void)
{
    u32 wakeup_src;

    /* check wanek event raw status */
    wakeup_src = spm_read(SPM_SLEEP_ISR_RAW_STA);
    
    if (wakeup_src)
    {
        spm_crit2("WARNING: spm_check_wakeup_src = 0x%x", wakeup_src);
        return 1;
    }
    else
        return 0;
}
예제 #5
0
/**************************************
 * golden_dump_xxx Function
 **************************************/
static ssize_t golden_dump_show(struct kobject *kobj, struct kobj_attribute *attr,
				char *buf)
{
	char *p = buf;

	p += sprintf(p, "[TOPCKGEN]\n");
	p += sprintf(p, "0x10000200 = 0x%x (0x7ff)\n", spm_read(0xf0000200));
	p += sprintf(p, "0x10000204 = 0x%x (0x15)\n" , spm_read(0xf0000204));

	p += sprintf(p, "[DDRPHY]\n");
	p += sprintf(p, "0x1000f5c8 = 0x%x ([0]=1,[4]=1)\n" , spm_read(0xf000f5c8));
	p += sprintf(p, "0x100125c8 = 0x%x ([0]=1,[4]=1)\n" , spm_read(0xf00125c8));
	p += sprintf(p, "0x1000f640 = 0x%x ([2]=1,[4]=1)\n" , spm_read(0xf000f640));
	p += sprintf(p, "0x10012640 = 0x%x ([4]=1)\n", spm_read(0xf0012640));
	p += sprintf(p, "0x1000f5cc = 0x%x ([8]=0,[12]=1)\n", spm_read(0xf000f5cc));
	p += sprintf(p, "0x100125cc = 0x%x ([8]=0,[12]=1)\n", spm_read(0xf00125cc));
	p += sprintf(p, "0x1000f690 = 0x%x ([2]=1)\n", spm_read(0xf000f690));

	p += sprintf(p, "[PERICFG]\n");
	p += sprintf(p, "0x10003208 = 0x%x ([15]=1:4GB)\n", spm_read(0xf0003208));

	BUG_ON(p - buf >= PAGE_SIZE);
	return p - buf;
}
예제 #6
0
static void spm_kick_pcm_to_run(bool cpu_pdn, bool infra_pdn, bool pcmwdt_en)
{
    u32 clk, con0;

    /* keep CPU or INFRA/DDRPHY power if needed and lock INFRA DCM */
    clk = spm_read(SPM_CLK_CON) & ~(CC_DISABLE_DORM_PWR | CC_DISABLE_INFRA_PWR);
    if (!cpu_pdn)
        clk |= CC_DISABLE_DORM_PWR;
    if (!infra_pdn)
        clk |= CC_DISABLE_INFRA_PWR;
    spm_write(SPM_CLK_CON, clk | CC_LOCK_INFRA_DCM);

    /* init pause request mask for PCM */
    spm_write(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff);

    /* enable r0 and r7 to control power */
    spm_write(SPM_PCM_PWR_IO_EN, PCM_PWRIO_EN_R0 | PCM_PWRIO_EN_R7);

    /* enable PCM WDT (normal mode) to start count if needed */
#if SPM_PCMWDT_EN
    if (pcmwdt_en) {
        u32 con1;
        con1 = spm_read(SPM_PCM_CON1) & ~(CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
        spm_write(SPM_PCM_CON1, CON1_CFG_KEY | con1);

        BUG_ON(spm_read(SPM_PCM_TIMER_VAL) > PCM_TIMER_MAX_FOR_WDT);
        spm_write(SPM_PCM_WDT_TIMER_VAL, spm_read(SPM_PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
        spm_write(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_PCM_WDT_EN);
    }
#endif

    /* kick PCM to run (only toggle PCM_KICK) */
    con0 = spm_read(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK);
    spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK);
    spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
}
예제 #7
0
void spm_kick_pcm(SPM_PCM_CONFIG* pcm_config)
{
    u32 clk,con0;
    
    BUG_ON(pcm_config!=pcm_config_curr);
    
    //spm_crit2("spm_kick_pcm():%s, cpu_pdn:%d, infra_pdn:%d \n",pcm_scenario[pcm_config->scenario],pcm_config_curr->cpu_pdn,pcm_config_curr->infra_pdn);

    /* keep CPU or INFRA/DDRPHY power if needed and lock INFRA DCM */
    clk = spm_read(SPM_CLK_CON) & ~(CC_DISABLE_DORM_PWR | CC_DISABLE_INFRA_PWR);
    if (!pcm_config->cpu_pdn)
        clk |= CC_DISABLE_DORM_PWR;
    if (!pcm_config->infra_pdn)
        clk |= CC_DISABLE_INFRA_PWR;
    
    if(pcm_config->lock_infra_dcm)    
        clk |= CC_LOCK_INFRA_DCM;
        
    spm_write(SPM_CLK_CON, clk);

    /* init pause request mask for PCM */
    spm_write(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff);

    /* enable r0 and r7 to control power */
    if(pcm_config->sync_r0r7)
    {
        spm_write(SPM_PCM_PWR_IO_EN, PCM_PWRIO_EN_R0 | PCM_PWRIO_EN_R7 | PCM_PWRIO_EN_R1 | PCM_PWRIO_EN_R2);
        
        /* In order to prevent glitch from SRCLKENA,we move the co-clock logic to SPM 26M-wake/sleep VSR in MT6572/82 */
        spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) |CC_SRCLKENA_MASK );
     }
     else
        spm_write(SPM_PCM_PWR_IO_EN, 0);

    /* for E2 enable LPM to do 32k-less feature*/
    spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) |CC_CXO32K_REMOVE_MD);


    
    if(pcm_config->coclock_en){
        spm_write(SPM_PCM_SRC_REQ, spm_read(SPM_PCM_SRC_REQ) |SR_SRCLKENI_MASK );}
    else{
        spm_write(SPM_PCM_SRC_REQ, 0 );} //In the case of no 6605

/**************Disable Switch Bus to 26M from TY******************/
#if 0
spm_write(0xf0000020,spm_read(0xf0000020) & (~0x040));
#endif

    /* kick PCM to run */
    con0 = spm_read(SPM_PCM_CON0);
    con0 &= ~(CON0_PCM_KICK | CON0_IM_KICK);
    spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK);
    spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
}
예제 #8
0
static void spm_reset_and_init_pcm(void)
{
    u32 con1;

    /* reset PCM */
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY);

    /* init PCM_CON0 (disable event vector) */
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);

    /* init PCM_CON1 (disable PCM timer but keep PCM WDT setting) */
    con1 = spm_read(SPM_PCM_CON1) & (CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
    spm_write(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_SPM_SRAM_ISO_B |
                            CON1_SPM_SRAM_SLP_B | CON1_IM_NONRP_EN | CON1_MIF_APBEN);
}
static inline int mcidle_handler(int cpu)
{

#if 1
    if (idle_switch[IDLE_TYPE_MC]) {
        if (mcidle_can_enter(cpu)) {
            go_to_mcidle(cpu);
            //go_to_soidle(0,cpu);
            return 1;
        }
    }
#else

    if (idle_switch[IDLE_TYPE_MC]) {
        mtk_wdt_suspend();
        for(;;)
        {
            if(cpu==1)
            {
                printk("MCDI start\n");
                spm_go_to_mcdi_ipi_test(cpu);
                printk("MCDI %s\n",spm_get_wake_up_result(SPM_PCM_SODI));
            }
            if(cpu==0)
            {


#if 1

                if(spm_read(SPM_FC1_PWR_CON)==0x32)
                {
                    //printk("IPI start\n");
                    spm_check_core_status_before(2);
                    //printk("1. SPM_PCM_EVENT_VECTOR2 = 0x%x, SPM_PCM_REG15_DATA = 0x%x \n", spm_read(SPM_PCM_EVENT_VECTOR2),spm_read(SPM_PCM_REG15_DATA));
                    //mdelay(1);
                    spm_check_core_status_after(2);
                    //printk("2. SPM_PCM_EVENT_VECTOR2 = 0x%x, SPM_PCM_REG15_DATA = 0x%x \n", spm_read(SPM_PCM_EVENT_VECTOR2),spm_read(SPM_PCM_REG15_DATA));
                }
#endif

            }
        }
    }

#endif
    return 0;
}
예제 #10
0
static inline int soidle_handler(int cpu)
{
    if (idle_switch[IDLE_TYPE_SO]) {
#ifdef SPM_SODI_PROFILE_TIME
        gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[0]);
#endif
        if (soidle_can_enter(cpu)) {
            
            soidle_pre_handler();
            
            #ifdef DEFAULT_MMP_ENABLE
			MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagStart, 0, 0);
			#endif //DEFAULT_MMP_ENABLE
			
            spm_go_to_sodi(slp_spm_SODI_flags, 0);
            
            #ifdef DEFAULT_MMP_ENABLE
            MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagEnd, 0, spm_read(SPM_PCM_PASR_DPD_3));
			#endif //DEFAULT_MMP_ENABLE

            soidle_post_handler();

            #if 0 //removed unused log
            #ifdef CONFIG_SMP
            idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d\n",
                soidle_timer_left, soidle_timer_left2, soidle_timer_left-soidle_timer_left2);
            #else
            idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d,timeout val=%d\n",
                soidle_timer_left, soidle_timer_left2, soidle_timer_left2-soidle_timer_left,soidle_timer_cmp-soidle_timer_left);
            #endif
            #endif
            
            #if 0 //for DVT test only
            idle_switch[IDLE_TYPE_SO] = 0;
            #endif

#ifdef SPM_SODI_PROFILE_TIME
            gpt_get_cnt(SPM_SODI_PROFILE_APXGPT,&soidle_profile[3]);
            idle_ver("SODI: cpu_freq:%u, 1=>2:%u, 2=>3:%u, 3=>4:%u\n", mt_cpufreq_get_cur_freq(0),
                 soidle_profile[1]-soidle_profile[0], soidle_profile[2]-soidle_profile[1], soidle_profile[3]-soidle_profile[2]);
#endif
            return 1;
        }
    }

    return 0;
}
예제 #11
0
void spm_clean_after_wakeup(void)
{
    unsigned tmp;
    
    /* PCM has cleared uart_clk_off_req and now clear it in POWER_ON_VAL1 */
    spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) & ~R7_UART_CLK_OFF_REQ);

    /* SRCLKENA_PERI: POWER_ON_VAL1|r7 (PWR_IO_EN[7]=1) */
    /* SRCLKENA_MD: POWER_ON_VAL1|r7 (PWR_IO_EN[2]=1) */
    //spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) &
    //                       ~(CC_SYSCLK0_EN_1 | CC_SYSCLK0_EN_0 | CC_SRCLKEN0_EN));

    spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) &
                           ~(CC_SYSCLK0_EN_1 | CC_SYSCLK0_EN_0 | CC_SRCLKEN0_EN | CC_SRCLKENA_MASK));

    /* re-enable POWER_ON_VAL0/1 to control power */
    spm_write(SPM_PCM_PWR_IO_EN, 0);

    /* unlock INFRA DCM */
    spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) & ~CC_LOCK_INFRA_DCM);

    /* clean PCM timer event */
    spm_write(SPM_PCM_CON1, CON1_CFG_KEY | (spm_read(SPM_PCM_CON1) & ~ (CON1_PCM_TIMER_EN|CON1_PCM_WDT_EN)));

    /* clean CPU wakeup event (pause abort) */
    spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT, 0);

    /* clean wakeup event raw status */
    spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, 0xffffffff);

   // spm_write(SPM_PCM_CON0, 0x0b160000);

    /* clean ISR status */
    spm_write(SPM_SLEEP_ISR_MASK, 0x0008);
    spm_write(SPM_SLEEP_ISR_STATUS, 0x0008);

    if(pcm_config_curr->scenario == SPM_PCM_DEEP_IDLE)
        spm_write(SPM_PCM_SW_INT_CLEAR,0xd);//avoid spm1 irq clear for RGU workaround
    else
    spm_write(SPM_PCM_SW_INT_CLEAR,0xf);
    
    /*[WHQA_00014241]Work Around for CCCI needs to sync register values to flipflop after suspend*/
    tmp = spm_read(0xF0200200);
    spm_write(0xF0200200, 0);
    spm_write(0xF0200200, tmp);
    
    tmp = spm_read(0xF0200204);
    spm_write(0xF0200204, 0);
    spm_write(0xF0200204, tmp);
    
}
예제 #12
0
static void spm_reset_and_init_pcm(void)
{
    /* reset PCM */
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY);
    
    /* init PCM control register (disable event vector and PCM timer) */
    spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);
    
    if(pcm_config_curr->scenario == SPM_PCM_WDT){
       // spm_write(SPM_PCM_CON1, CON1_CFG_KEY & ~(CON1_IM_NONRP_EN | CON1_MIF_APBEN));
        spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_MIF_APBEN);
    }
    else if(pcm_config_curr->scenario == SPM_PCM_DEEP_IDLE)
      spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_IM_NONRP_EN | CON1_MIF_APBEN | (spm_read(SPM_PCM_CON1)&(CON1_PCM_WDT_EN | CON1_PCM_WDT_WAKE_MODE)));
    else    
      spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_IM_NONRP_EN | CON1_MIF_APBEN);
        
}
예제 #13
0
파일: mt_spm.c 프로젝트: Scorpio92/mediatek
void spm_twam_enable_monitor(twam_sig_t *twamsig, bool speed_mode)
{
    u32 con = TWAM_CON_EN;
    unsigned long flags;

    if (speed_mode)
        con |= TWAM_CON_SPEED_EN;

    if (twamsig) {
        con |= (twamsig->sig0 & 0xf) << 16;
        con |= (twamsig->sig1 & 0xf) << 20;
        con |= (twamsig->sig2 & 0xf) << 24;
        con |= (twamsig->sig3 & 0xf) << 28;
    }

    spin_lock_irqsave(&spm_lock, flags);
    spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) & ~ISR_TWAM);
    spm_write(SPM_SLEEP_TWAM_CON, con);
    spin_unlock_irqrestore(&spm_lock, flags);
}
예제 #14
0
static void spm_get_wakeup_status(wake_status_t *wakesta)
{
    /* get PC value if PCM assert (pause abort) */
    wakesta->debug_reg = spm_read(SPM_PCM_REG_DATA_INI);

    /* get wakeup event */
    wakesta->r12 = spm_read(SPM_PCM_REG9_DATA);     /* r9 = r12 for pcm_normal */
    wakesta->raw_sta = spm_read(SPM_SLEEP_ISR_RAW_STA);
    wakesta->cpu_wake = spm_read(SPM_SLEEP_CPU_WAKEUP_EVENT);

    /* get sleep time */
    wakesta->timer_out = spm_read(SPM_PCM_TIMER_OUT);

    /* get special pattern (0xf0000 or 0x10000) if sleep abort */
    wakesta->event_reg = spm_read(SPM_PCM_EVENT_REG_STA);

    /* get ISR status */
    wakesta->isr = spm_read(SPM_SLEEP_ISR_STATUS);

    /* get MD/CONN and co-clock status */
    wakesta->r13 = spm_read(SPM_PCM_REG13_DATA);
}
void mcidle_before_wfi(int cpu)
{
#ifdef CONFIG_SMP
    int err = 0;

    unsigned int id = mcidle_gpt_percpu[cpu];

    mcidle_timer_left2[cpu] = localtimer_get_counter();

    free_gpt(id);
    err = request_gpt(id, GPT_ONE_SHOT, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1,
                      0, NULL, GPT_NOAUTOEN);
    if (err) {
        idle_info("[%s]fail to request GPT4\n", __func__);
    }

    mcidle_timer_left2[cpu] = localtimer_get_counter();


    if(cpu!=0)//core1~n, avoid gpt clear by core0
    {
        if( mcidle_timer_left2[cpu] <=2600 ) //200us(todo)
        {
            if(mcidle_timer_left2[cpu]<=0)
                gpt_set_cmp(id, 1);//Trigger GPT4 Timerout imediately
            else
                gpt_set_cmp(id, mcidle_timer_left2[cpu]);

            spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT,spm_read(SPM_SLEEP_CPU_WAKEUP_EVENT)|0x1);//spm wake up directly

        }
        else
            gpt_set_cmp(id, mcidle_timer_left2[cpu]);

        start_gpt(id);
    }
#else
    gpt_get_cnt(GPT1, &mcidle_timer_left2);
#endif
}
static inline int soidle_handler(int cpu)
{
    if (idle_switch[IDLE_TYPE_SO]) {
        if (soidle_can_enter(cpu)) {
            
            soidle_pre_handler();
            
            #ifdef DEFAULT_MMP_ENABLE
			MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagStart, 0, 0);
			#endif //DEFAULT_MMP_ENABLE
			
            spm_go_to_sodi(slp_spm_SODI_flags, 0);
            
            #ifdef DEFAULT_MMP_ENABLE
            MMProfileLogEx(sodi_mmp_get_events()->sodi_enable, MMProfileFlagEnd, 0, spm_read(SPM_PCM_PASR_DPD_3));
			#endif //DEFAULT_MMP_ENABLE

            soidle_post_handler();

            #if 0 //removed unused log
            #ifdef CONFIG_SMP
            idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d\n",
                soidle_timer_left, soidle_timer_left2, soidle_timer_left-soidle_timer_left2);
            #else
            idle_ver("SO:timer_left=%d, timer_left2=%d, delta=%d,timeout val=%d\n",
                soidle_timer_left, soidle_timer_left2, soidle_timer_left2-soidle_timer_left,soidle_timer_cmp-soidle_timer_left);
            #endif
            #endif
            
            #if 0 //for DVT test only
            idle_switch[IDLE_TYPE_SO] = 0;
            #endif

            return 1;
        }
    }

    return 0;
}
int spm_ctrl_e3tcm(int state)
{
    int err = 0;
    unsigned long flags;

    spm_mtcmos_noncpu_lock(flags);
	
	if (state == STA_POWER_DOWN) {
	    spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) | (1<<14));
	    spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) & ~(1<<15));
	    spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) | E3TCM_SRAM_PDN);
        while ((spm_read(SPM_PCM_PASR_DPD_2) & E3TCM_SRAM_ACK) !=E3TCM_SRAM_ACK) {
        }
	} else {    /* STA_POWER_ON */
        spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) & ~E3TCM_SRAM_PDN);
        while ((spm_read(SPM_PCM_PASR_DPD_2) & E3TCM_SRAM_ACK)) {
        }
        spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) | (1<<15));
        spm_write(SPM_PCM_PASR_DPD_2, spm_read(SPM_PCM_PASR_DPD_2) & ~(1<<14));
    }
    
    spm_mtcmos_noncpu_unlock(flags);
    return err;
}
예제 #18
0
/*
static bool spm_set_suspend_pcm_ver(u32 *suspend_flags)
{
    u32 flag;

    flag = *suspend_flags;

    if(mt_get_clk_mem_sel()==MEMPLL3PLL)
    {
        __spm_suspend.pcmdesc = &suspend_pcm_3pll;
        flag |= SPM_VCORE_DVS_DIS;
    }
    else if(mt_get_clk_mem_sel()==MEMPLL1PLL)

    {
        __spm_suspend.pcmdesc = &suspend_pcm_1pll;
        flag &= ~SPM_VCORE_DVS_DIS;
    }
    else
        return false;

    *suspend_flags = flag;
    return true;

}
*/
static void spm_suspend_pre_process(struct pwr_ctrl *pwrctrl)
{
#if 0
    u32 rdata1 = 0, rdata2 = 0;
#endif

    /* set PMIC WRAP table for suspend power control */
    mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_SUSPEND);
    
    spm_i2c_control(I2C_CHANNEL, 1);

#if 0
    /* for infra pdn (emi driving) */
    spm_write(0xF0004000, spm_read(0xF0004000) | (1 << 24));

    /* MEMPLL control for SPM */
    spm_write(0xF000F5C8, 0x3010F030);
    spm_write(0xF000F5CC, 0x50101010);
#endif
    //spm_write(0xF0001070 , spm_read(0xF0001070) | (1 << 21)); // 26:26 enable 
    //spm_write(0xF0000204 , spm_read(0xF0000204) | (1 << 0));  // BUS 26MHz enable 
    //spm_write(0xF0001108 , 0x0);

#ifdef CONFIG_MD32_SUPPORT
    //spm_write(MD32_BASE+0x2C, (spm_read(MD32_BASE+0x2C) & ~0xFFFF) | 0xcafe);
#endif

#if 0    
    pwrap_read(0x2c2, &rdata1);
    pwrap_write(0x2c2, 0x0123);
    pwrap_read(0x2c2, &rdata2);
    if(rdata2 != 0x0123)
    {
        spm_crit2("suspend pmic wrapper 0x2c2, rdata1 = 0x%x, rdata2 = 0x%x\n", rdata1, rdata2);
        BUG();
    }
#endif
}
예제 #19
0
void spm_deepidle_init(void)
{
#if SPM_USE_TWAM_DEBUG
	unsigned long flags;
	struct twam_sig twamsig = {
		.sig0 = 26,	/* md1_srcclkena */
		.sig1 = 22,	/* md_apsrc_req_mux */
		.sig2 = 25,	/* md2_srcclkena */
		.sig3 = 21,	/* md2_apsrc_req_mux */		
		//.sig2 = 23,	/* conn_srcclkena */
		//.sig3 = 20,	/* conn_apsrc_req */
	};
#if 0
	spin_lock_irqsave(&__spm_lock, flags);
	spm_write(SPM_AP_STANBY_CON, spm_read(SPM_AP_STANBY_CON) | ASC_MD_DDR_EN_SEL);
	spin_unlock_irqrestore(&__spm_lock, flags);
#endif
	spm_twam_register_handler(twam_handler);
	spm_twam_enable_monitor(&twamsig, false,SPM_TWAM_MONITOR_TICK);
#endif
}


MODULE_DESCRIPTION("SPM-DPIdle Driver v0.1");
static bool is_fw_not_existed(void)
{
	return spm_read(SPM_PCM_REG1_DATA) != 0x1 || spm_read(SPM_PCM_REG11_DATA) == 0x55AA55AA;
}
int spm_set_vcore_dvs_voltage(unsigned int opp)
{
	u8 f26m_req, apsrc_req;
	u32 target_sta, req;
	int timeout, r = 0;
	bool not_existed;
	#if 0 /* For ULTRA Mode */
	bool not_support;
	#endif
	unsigned long flags;

	switch (opp) {
		#if 0 /* For ULTRA Mode */
		case OPPI_PERF_ULTRA:
			f26m_req = 1;
			apsrc_req = 1;
			target_sta = VCORE_STA_UHPM;
			break;
		#endif
		case OPPI_PERF:
			f26m_req = 1;
			apsrc_req = 0;
			target_sta = VCORE_STA_HPM;
			break;
		case OPPI_LOW_PWR:
			f26m_req = 0;
			apsrc_req = 0;
			target_sta = VCORE_STA_LPM;
			break;
		default:
			return -EINVAL;
	}

	spin_lock_irqsave(&__spm_lock, flags);
	not_existed = is_fw_not_existed();

	#if 0 /* For ULTRA Mode */
	not_support = is_fw_not_support_uhpm();
	if (not_existed || (opp == OPPI_PERF_ULTRA && not_support)) {
		__go_to_vcore_dvfs(SPM_VCORE_DVFS_EN, f26m_req, apsrc_req);
	} else {
		req = spm_read(SPM_PCM_SRC_REQ) & ~(SR_PCM_F26M_REQ | SR_PCM_APSRC_REQ);
		spm_write(SPM_PCM_SRC_REQ, req | (f26m_req << 1) | apsrc_req);
	}
	#else
	if (not_existed) {
		__go_to_vcore_dvfs(SPM_VCORE_DVFS_EN, f26m_req, apsrc_req);
	} else {
		req = spm_read(SPM_PCM_SRC_REQ) & ~(SR_PCM_F26M_REQ);
		spm_write(SPM_PCM_SRC_REQ, req | (f26m_req << 1));
	}
	#endif

	if (opp < OPPI_LOW_PWR) {
		/* normal FW fetch time + 1.25->1.15->1.25V transition time */
		timeout = 2 * __spm_vcore_dvfs.pcmdesc->size + 2 * PER_OPP_DVS_US;

		r = wait_pcm_complete_dvs(get_vcore_sta() == target_sta, timeout);

		if (r >= 0) {	/* DVS pass */
			r = 0;
		} else {
			#if 0 /* For ULTRA Mode */
			spm_err("[VcoreFS] OPP: %u (%u)(%u)\n", opp, not_existed, not_support);
			#else
			spm_err("[VcoreFS] OPP: %u (%u)\n", opp, not_existed);
			#endif
			spm_dump_vcore_dvs_regs(NULL);
			BUG();
		}
	}
	spin_unlock_irqrestore(&__spm_lock, flags);

	return r;
}
u32 read_pwr_statu(void)
{
	return (spm_read(SPM_PWR_STATUS) & spm_read(SPM_PWR_STATUS_2ND)) ;
}
char *spm_dump_vcore_dvs_regs(char *p)
{
	if (p) {
		p += sprintf(p, "SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA));
		p += sprintf(p, "PCM_SRC_REQ   : 0x%x\n", spm_read(SPM_PCM_SRC_REQ));
		p += sprintf(p, "PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA));
		p += sprintf(p, "PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA));
		p += sprintf(p, "PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK));
		p += sprintf(p, "AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON));
		p += sprintf(p, "PCM_IM_PTR    : 0x%x (%u)\n", spm_read(SPM_PCM_IM_PTR), spm_read(SPM_PCM_IM_LEN));
		p += sprintf(p, "PCM_REG6_DATA : 0x%x\n", spm_read(SPM_PCM_REG6_DATA));
		p += sprintf(p, "PCM_REG11_DATA: 0x%x\n", spm_read(SPM_PCM_REG11_DATA));
	} else {
		spm_err("[VcoreFS] SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA));
		spm_err("[VcoreFS] PCM_SRC_REQ   : 0x%x\n", spm_read(SPM_PCM_SRC_REQ));
		spm_err("[VcoreFS] PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA));
		spm_err("[VcoreFS] PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA));
		spm_err("[VcoreFS] PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK));
		spm_err("[VcoreFS] AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON));
		spm_err("[VcoreFS] PCM_IM_PTR    : 0x%x (%u)\n", spm_read(SPM_PCM_IM_PTR), spm_read(SPM_PCM_IM_LEN));
		spm_err("[VcoreFS] PCM_REG6_DATA : 0x%x\n", spm_read(SPM_PCM_REG6_DATA));
		spm_err("[VcoreFS] PCM_REG11_DATA: 0x%x\n", spm_read(SPM_PCM_REG11_DATA));

		spm_err("[VcoreFS] PCM_REG0_DATA : 0x%x\n", spm_read(SPM_PCM_REG0_DATA));
		spm_err("[VcoreFS] PCM_REG1_DATA : 0x%x\n", spm_read(SPM_PCM_REG1_DATA));
		spm_err("[VcoreFS] PCM_REG2_DATA : 0x%x\n", spm_read(SPM_PCM_REG2_DATA));
		spm_err("[VcoreFS] PCM_REG3_DATA : 0x%x\n", spm_read(SPM_PCM_REG3_DATA));
		spm_err("[VcoreFS] PCM_REG4_DATA : 0x%x\n", spm_read(SPM_PCM_REG4_DATA));
		spm_err("[VcoreFS] PCM_REG5_DATA : 0x%x\n", spm_read(SPM_PCM_REG5_DATA));
		spm_err("[VcoreFS] PCM_REG7_DATA : 0x%x\n", spm_read(SPM_PCM_REG7_DATA));
		spm_err("[VcoreFS] PCM_REG8_DATA : 0x%x\n", spm_read(SPM_PCM_REG8_DATA));
		spm_err("[VcoreFS] PCM_REG9_DATA : 0x%x\n", spm_read(SPM_PCM_REG9_DATA));
		spm_err("[VcoreFS] PCM_REG10_DATA: 0x%x\n", spm_read(SPM_PCM_REG10_DATA));
		spm_err("[VcoreFS] PCM_REG14_DATA: 0x%x\n", spm_read(SPM_PCM_REG14_DATA));
		spm_err("[VcoreFS] PCM_REG15_DATA: %u\n"  , spm_read(SPM_PCM_REG15_DATA));
	}

	return p;
}
static void spm_sodi_dump_regs(void)
{
    /* SPM register */
    printk("SPM_CA7_CPU0_IRQ_MASK   0x%p = 0x%x\n", SPM_CA7_CPU0_IRQ_MASK, spm_read(SPM_CA7_CPU0_IRQ_MASK));
    printk("SPM_CA7_CPU1_IRQ_MASK   0x%p = 0x%x\n", SPM_CA7_CPU1_IRQ_MASK, spm_read(SPM_CA7_CPU1_IRQ_MASK));
    printk("SPM_CA7_CPU2_IRQ_MASK   0x%p = 0x%x\n", SPM_CA7_CPU2_IRQ_MASK, spm_read(SPM_CA7_CPU2_IRQ_MASK));
    printk("SPM_CA7_CPU3_IRQ_MASK   0x%p = 0x%x\n", SPM_CA7_CPU3_IRQ_MASK, spm_read(SPM_CA7_CPU3_IRQ_MASK));

#if 0
    printk("SPM_MP1_CPU0_IRQ_MASK   0x%p = 0x%x\n", SPM_MP1_CPU0_IRQ_MASK, spm_read(SPM_MP1_CPU0_IRQ_MASK));
    printk("SPM_MP1_CPU1_IRQ_MASK   0x%p = 0x%x\n", SPM_MP1_CPU1_IRQ_MASK, spm_read(SPM_MP1_CPU1_IRQ_MASK));
    printk("SPM_MP1_CPU2_IRQ_MASK   0x%p = 0x%x\n", SPM_MP1_CPU2_IRQ_MASK, spm_read(SPM_MP1_CPU2_IRQ_MASK));
    printk("SPM_MP1_CPU3_IRQ_MASK   0x%p = 0x%x\n", SPM_MP1_CPU3_IRQ_MASK, spm_read(SPM_MP1_CPU3_IRQ_MASK));

    printk("POWER_ON_VAL0           0x%p = 0x%x\n", SPM_POWER_ON_VAL0          , spm_read(SPM_POWER_ON_VAL0));
    printk("POWER_ON_VAL1           0x%p = 0x%x\n", SPM_POWER_ON_VAL1          , spm_read(SPM_POWER_ON_VAL1));
    printk("PCM_PWR_IO_EN           0x%p = 0x%x\n", SPM_PCM_PWR_IO_EN          , spm_read(SPM_PCM_PWR_IO_EN));
    printk("CLK_CON                 0x%p = 0x%x\n", SPM_CLK_CON                , spm_read(SPM_CLK_CON));
    printk("AP_DVFS_CON             0x%p = 0x%x\n", SPM_AP_DVFS_CON_SET        , spm_read(SPM_AP_DVFS_CON_SET));
    printk("PWR_STATUS              0x%p = 0x%x\n", SPM_PWR_STATUS             , spm_read(SPM_PWR_STATUS));
    printk("PWR_STATUS_S            0x%p = 0x%x\n", SPM_PWR_STATUS_S           , spm_read(SPM_PWR_STATUS_S));
    printk("SLEEP_TIMER_STA         0x%p = 0x%x\n", SPM_SLEEP_TIMER_STA        , spm_read(SPM_SLEEP_TIMER_STA));
    printk("WAKE_EVENT_MASK         0x%p = 0x%x\n", SPM_SLEEP_WAKEUP_EVENT_MASK, spm_read(SPM_SLEEP_WAKEUP_EVENT_MASK));
    printk("SPM_SLEEP_CPU_WAKEUP_EVENT 0x%p = 0x%x\n", SPM_SLEEP_CPU_WAKEUP_EVENT, spm_read(SPM_SLEEP_CPU_WAKEUP_EVENT));
    printk("SPM_PCM_RESERVE         0x%p = 0x%x\n", SPM_PCM_RESERVE          , spm_read(SPM_PCM_RESERVE));
    printk("SPM_AP_STANBY_CON       0x%p = 0x%x\n", SPM_AP_STANBY_CON          , spm_read(SPM_AP_STANBY_CON));
    printk("SPM_PCM_TIMER_OUT       0x%p = 0x%x\n", SPM_PCM_TIMER_OUT          , spm_read(SPM_PCM_TIMER_OUT));
    printk("SPM_PCM_CON1            0x%p = 0x%x\n", SPM_PCM_CON1          , spm_read(SPM_PCM_CON1));
#endif

    // PCM register
    printk("PCM_REG0_DATA       0x%p = 0x%x\n", SPM_PCM_REG0_DATA          , spm_read(SPM_PCM_REG0_DATA));
    printk("PCM_REG1_DATA       0x%p = 0x%x\n", SPM_PCM_REG1_DATA          , spm_read(SPM_PCM_REG1_DATA));
    printk("PCM_REG2_DATA       0x%p = 0x%x\n", SPM_PCM_REG2_DATA          , spm_read(SPM_PCM_REG2_DATA));
    printk("PCM_REG3_DATA       0x%p = 0x%x\n", SPM_PCM_REG3_DATA          , spm_read(SPM_PCM_REG3_DATA));
    printk("PCM_REG4_DATA       0x%p = 0x%x\n", SPM_PCM_REG4_DATA          , spm_read(SPM_PCM_REG4_DATA));
    printk("PCM_REG5_DATA       0x%p = 0x%x\n", SPM_PCM_REG5_DATA          , spm_read(SPM_PCM_REG5_DATA));
    printk("PCM_REG6_DATA       0x%p = 0x%x\n", SPM_PCM_REG6_DATA          , spm_read(SPM_PCM_REG6_DATA));
    printk("PCM_REG7_DATA       0x%p = 0x%x\n", SPM_PCM_REG7_DATA          , spm_read(SPM_PCM_REG7_DATA));
    printk("PCM_REG8_DATA       0x%p = 0x%x\n", SPM_PCM_REG8_DATA          , spm_read(SPM_PCM_REG8_DATA));
    printk("PCM_REG9_DATA       0x%p = 0x%x\n", SPM_PCM_REG9_DATA          , spm_read(SPM_PCM_REG9_DATA));
    printk("PCM_REG10_DATA      0x%p = 0x%x\n", SPM_PCM_REG10_DATA          , spm_read(SPM_PCM_REG10_DATA));
    printk("PCM_REG11_DATA      0x%p = 0x%x\n", SPM_PCM_REG11_DATA          , spm_read(SPM_PCM_REG11_DATA));
    printk("PCM_REG12_DATA      0x%p = 0x%x\n", SPM_PCM_REG12_DATA          , spm_read(SPM_PCM_REG12_DATA));
    printk("PCM_REG13_DATA      0x%p = 0x%x\n", SPM_PCM_REG13_DATA          , spm_read(SPM_PCM_REG13_DATA));
    printk("PCM_REG14_DATA      0x%p = 0x%x\n", SPM_PCM_REG14_DATA          , spm_read(SPM_PCM_REG14_DATA));
    printk("PCM_REG15_DATA      0x%p = 0x%x\n", SPM_PCM_REG15_DATA          , spm_read(SPM_PCM_REG15_DATA));

#if 0
    printk("SPM_MP0_FC0_PWR_CON 0x%p = 0x%x\n", SPM_MP0_FC0_PWR_CON, spm_read(SPM_MP0_FC0_PWR_CON));
    printk("SPM_MP0_FC1_PWR_CON 0x%p = 0x%x\n", SPM_MP0_FC1_PWR_CON, spm_read(SPM_MP0_FC1_PWR_CON));
    printk("SPM_MP0_FC2_PWR_CON 0x%p = 0x%x\n", SPM_MP0_FC2_PWR_CON, spm_read(SPM_MP0_FC2_PWR_CON));
    printk("SPM_MP0_FC3_PWR_CON 0x%p = 0x%x\n", SPM_MP0_FC3_PWR_CON, spm_read(SPM_MP0_FC3_PWR_CON));
    printk("SPM_MP1_FC0_PWR_CON 0x%p = 0x%x\n", SPM_MP1_FC0_PWR_CON, spm_read(SPM_MP1_FC0_PWR_CON));
    printk("SPM_MP1_FC1_PWR_CON 0x%p = 0x%x\n", SPM_MP1_FC1_PWR_CON, spm_read(SPM_MP1_FC1_PWR_CON));
    printk("SPM_MP1_FC2_PWR_CON 0x%p = 0x%x\n", SPM_MP1_FC2_PWR_CON, spm_read(SPM_MP1_FC2_PWR_CON));
    printk("SPM_MP1_FC3_PWR_CON 0x%p = 0x%x\n", SPM_MP1_FC3_PWR_CON, spm_read(SPM_MP1_FC3_PWR_CON));
#endif

    printk("CLK_CON                 0x%p = 0x%x\n", SPM_CLK_CON           , spm_read(SPM_CLK_CON));
    printk("SPM_PCM_CON0            0x%p = 0x%x\n", SPM_PCM_CON0          , spm_read(SPM_PCM_CON0));
    printk("SPM_PCM_CON1            0x%p = 0x%x\n", SPM_PCM_CON1          , spm_read(SPM_PCM_CON1));

    printk("SPM_PCM_EVENT_VECTOR2   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR2  , spm_read(SPM_PCM_EVENT_VECTOR2));
    printk("SPM_PCM_EVENT_VECTOR3   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR3  , spm_read(SPM_PCM_EVENT_VECTOR3));
    printk("SPM_PCM_EVENT_VECTOR4   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR4  , spm_read(SPM_PCM_EVENT_VECTOR4));
    printk("SPM_PCM_EVENT_VECTOR5   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR5  , spm_read(SPM_PCM_EVENT_VECTOR5));
    printk("SPM_PCM_EVENT_VECTOR6   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR6  , spm_read(SPM_PCM_EVENT_VECTOR6));
    printk("SPM_PCM_EVENT_VECTOR7   0x%p = 0x%x\n", SPM_PCM_EVENT_VECTOR7  , spm_read(SPM_PCM_EVENT_VECTOR7));

    printk("SPM_PCM_RESERVE         0x%p = 0x%x\n", SPM_PCM_RESERVE  , spm_read(SPM_PCM_RESERVE));
    printk("SPM_PCM_WDT_TIMER_VAL   0x%p = 0x%x\n", SPM_PCM_WDT_TIMER_VAL  , spm_read(SPM_PCM_WDT_TIMER_VAL));

    printk("SPM_SLEEP_CA7_WFI0_EN   0x%p = 0x%x\n", SPM_SLEEP_CA7_WFI0_EN  , spm_read(SPM_SLEEP_CA7_WFI0_EN));
    printk("SPM_SLEEP_CA7_WFI1_EN   0x%p = 0x%x\n", SPM_SLEEP_CA7_WFI1_EN  , spm_read(SPM_SLEEP_CA7_WFI1_EN));
    printk("SPM_SLEEP_CA7_WFI2_EN   0x%p = 0x%x\n", SPM_SLEEP_CA7_WFI2_EN  , spm_read(SPM_SLEEP_CA7_WFI2_EN));
    printk("SPM_SLEEP_CA7_WFI3_EN   0x%p = 0x%x\n", SPM_SLEEP_CA7_WFI3_EN  , spm_read(SPM_SLEEP_CA7_WFI3_EN));
    printk("SPM_MP1_CORE0_WFI_SEL   0x%p = 0x%x\n", SPM_SLEEP_CA15_WFI0_EN  , spm_read(SPM_SLEEP_CA15_WFI0_EN));
    printk("SPM_MP1_CORE1_WFI_SEL   0x%p = 0x%x\n", SPM_SLEEP_CA15_WFI1_EN  , spm_read(SPM_SLEEP_CA15_WFI1_EN));
    printk("SPM_MP1_CORE2_WFI_SEL   0x%p = 0x%x\n", SPM_SLEEP_CA15_WFI2_EN  , spm_read(SPM_SLEEP_CA15_WFI2_EN));
    printk("SPM_MP1_CORE3_WFI_SEL   0x%p = 0x%x\n", SPM_SLEEP_CA15_WFI3_EN  , spm_read(SPM_SLEEP_CA15_WFI3_EN));

    printk("SPM_SLEEP_TIMER_STA     0x%p = 0x%x\n", SPM_SLEEP_TIMER_STA  , spm_read(SPM_SLEEP_TIMER_STA));
    printk("SPM_PWR_STATUS          0x%p = 0x%x\n", SPM_PWR_STATUS  , spm_read(SPM_PWR_STATUS));

    printk("SPM_PCM_FLAGS           0x%p = 0x%x\n", SPM_PCM_FLAGS  , spm_read(SPM_PCM_FLAGS));
    printk("SPM_PCM_RESERVE         0x%p = 0x%x\n", SPM_PCM_RESERVE  , spm_read(SPM_PCM_RESERVE));
    printk("SPM_PCM_RESERVE4        0x%p = 0x%x\n", SPM_PCM_RESERVE4  , spm_read(SPM_PCM_RESERVE4));
    printk("SPM_AP_STANBY_CON       0x%p = 0x%x\n", SPM_AP_STANBY_CON  , spm_read(SPM_AP_STANBY_CON));
    printk("SPM_PCM_SRC_REQ         0x%p = 0x%x\n", SPM_PCM_SRC_REQ  , spm_read(SPM_PCM_SRC_REQ));
}
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;
    int vcore_status = 0; //0:disable, 1:HPM, 2:LPM

#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)
    {
        if ((pwrctrl->pcm_flags & SPM_VCORE_DVFS_EN) == 0) 
        {
            pwrctrl->pcm_flags |= SPM_VCORE_DVS_EVENT_DIS;
        }
    }

    //SODI will not decrease Vcore voltage in HPM mode.
    if ((pwrctrl->pcm_flags & SPM_VCORE_DVS_EVENT_DIS) == 0)
    {
        if (get_ddr_khz() != FDDR_S1_KHZ)
        {
		#if SPM_AEE_RR_REC
		aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_VCORE_HPM));
		#endif 
/*            	//modify by mtk
		//if DRAM freq is high,SPM will not enter event_vector to enter EMI self-refresh
		if(pwrctrl->pcm_flags_cust == 0)
		{
			pwrctrl->pcm_flags|=0x80;		
		}
*/
            	vcore_status = 1;
            	//printk("SODI: get_ddr_khz() = %d\n", get_ddr_khz());
        }
        else
        {
			#if SPM_AEE_RR_REC
            aee_rr_rec_sodi_val(aee_rr_curr_sodi_val()|(1<<SPM_SODI_VCORE_LPM));
			#endif            
            
            vcore_status = 2;
        }
    }

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

#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 //In D2, can not set apsrc_req bit in SODI. It is used by Vcore DVS for GPU 550M in HPM mode
    //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, vcore_status = %d, %s\n", 
                spm_read(SPM_PCM_PASR_DPD_3), spm_read(SPM_PCM_FLAGS), spm_read(SPM_PCM_RESERVE2), vcore_status, 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

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
}
예제 #26
0
/***********************Exposed API*************************/
void spm_wdt_restart(void) //used to kick wdt.
{
    spm_write(SPM_POWER_ON_VAL1,spm_read(SPM_POWER_ON_VAL1)| R7_wdt_kick_p);
    spm_write(SPM_POWER_ON_VAL1,spm_read(SPM_POWER_ON_VAL1)& ~R7_wdt_kick_p);
		spm_notice("spm_wdt_restart\n");
}
void spm_ap_mdsrc_req(u8 set)
{
    unsigned long flags;
    u32 i = 0;
    u32 md_sleep = 0;

    if (set)
    {   
        spin_lock_irqsave(&__spm_lock, flags);

        if (spm_ap_mdsrc_req_cnt < 0)
        {
            spm_crit2("warning: set = %d, spm_ap_mdsrc_req_cnt = %d\n", set, spm_ap_mdsrc_req_cnt); 
            //goto AP_MDSRC_REC_CNT_ERR;
            spin_unlock_irqrestore(&__spm_lock, flags);
        }
        else
        {
            spm_ap_mdsrc_req_cnt++;

            hw_spin_lock_for_ddrdfs();
            spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) | (1 << 17));
            hw_spin_unlock_for_ddrdfs();

            spin_unlock_irqrestore(&__spm_lock, flags);
    
            /* if md_apsrc_req = 1'b0, wait 26M settling time (3ms) */
            if (0 == (spm_read(SPM_PCM_REG13_DATA) & R13_MD1_APSRC_REQ))
            {
                md_sleep = 1;
                mdelay(3);
            }

            /* Check ap_mdsrc_ack = 1'b1 */
            while(0 == (spm_read(SPM_PCM_REG13_DATA) & R13_AP_MD1SRC_ACK))
            {
                if (10 > i++)
                {
                    mdelay(1);
                }
                else
                {
                    spm_crit2("WARNING: MD SLEEP = %d, spm_ap_mdsrc_req CAN NOT polling AP_MD1SRC_ACK\n", md_sleep);
                    //goto AP_MDSRC_REC_CNT_ERR;
                    break;
                }
            }
        }        
    }
    else
    {
        spin_lock_irqsave(&__spm_lock, flags);

        spm_ap_mdsrc_req_cnt--;

        if (spm_ap_mdsrc_req_cnt < 0)
        {
            spm_crit2("warning: set = %d, spm_ap_mdsrc_req_cnt = %d\n", set, spm_ap_mdsrc_req_cnt); 
            //goto AP_MDSRC_REC_CNT_ERR;
        }
        else
        {
            if (0 == spm_ap_mdsrc_req_cnt)
            {
                hw_spin_lock_for_ddrdfs();
                spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) & ~(1 << 17));
                hw_spin_unlock_for_ddrdfs();
            }
        }
        
        spin_unlock_irqrestore(&__spm_lock, flags);
    }

//AP_MDSRC_REC_CNT_ERR:
//    spin_unlock_irqrestore(&__spm_lock, flags);
}
static void spm_i2c_control(u32 channel, bool onoff)
{
    static int pdn = 0;
    static bool i2c_onoff = 0;
#ifdef CONFIG_OF
    void __iomem *base;
#else
    u32 base;
#endif
    u32 i2c_clk;

    switch(channel)
    {
        case 0:
#ifdef CONFIG_OF
            base = SPM_I2C0_BASE;
#else
            base = I2C0_BASE;
#endif
            i2c_clk = MT_CG_PERI_I2C0;
            break;
        case 1:
#ifdef CONFIG_OF
            base = SPM_I2C1_BASE;
#else
            base = I2C1_BASE;
#endif
            i2c_clk = MT_CG_PERI_I2C1;
            break;
        case 2:
#ifdef CONFIG_OF
            base = SPM_I2C2_BASE;
#else
            base = I2C2_BASE;
#endif
            i2c_clk = MT_CG_PERI_I2C2;
            break;
        case 3:
#ifdef CONFIG_OF
            base = SPM_I2C3_BASE;
#else
            base = I2C3_BASE;
#endif
            i2c_clk = MT_CG_PERI_I2C3;
	          break;
//FIXME: I2C4 is defined in 6595 dts but not in 6795 dts. 
#if 0 
        case 4:
            base = I2C4_BASE;
            i2c_clk = MT_CG_PERI_I2C4;
	          break;
#endif
        default:
            break;
    }

    if ((1 == onoff) && (0 == i2c_onoff))
    {
       i2c_onoff = 1;
#if 1
        pdn = spm_read(PERI_PDN0_STA) & (1U << i2c_clk);
        spm_write(PERI_PDN0_CLR, pdn);                /* power on I2C */
#else
        pdn = clock_is_on(i2c_clk);
        if (!pdn)
            enable_clock(i2c_clk, "spm_i2c");
#endif
        spm_write(base + OFFSET_CONTROL,     0x0);    /* init I2C_CONTROL */
        spm_write(base + OFFSET_TRANSAC_LEN, 0x1);    /* init I2C_TRANSAC_LEN */
        spm_write(base + OFFSET_EXT_CONF,    0x1800); /* init I2C_EXT_CONF */
        spm_write(base + OFFSET_IO_CONFIG,   0x3);    /* init I2C_IO_CONFIG */
        spm_write(base + OFFSET_HS,          0x102);  /* init I2C_HS */
    }
    else
    if ((0 == onoff) && (1 == i2c_onoff))
    {
        i2c_onoff = 0;
#if 1
        spm_write(PERI_PDN0_SET, pdn);                /* restore I2C power */
#else
        if (!pdn)
            disable_clock(i2c_clk, "spm_i2c");      
#endif
    }
    else
        ASSERT(1);
}
bool spm_is_md_sleep(void)
{
    return !( (spm_read(SPM_PCM_REG13_DATA) & R13_MD1_SRCLKENA) | (spm_read(SPM_PCM_REG13_DATA) & R13_MD2_SRCLKENA));
}
static wake_reason_t spm_output_wake_reason(struct wake_status *wakesta, struct pcm_desc *pcmdesc)
{
	wake_reason_t wr;

	wr = __spm_output_wake_reason(wakesta, pcmdesc, true);

#if 1
    memcpy(&suspend_info[log_wakesta_cnt], wakesta, sizeof(struct wake_status));
    suspend_info[log_wakesta_cnt].log_index = log_wakesta_index;

    log_wakesta_cnt++;
    log_wakesta_index++;

    if (10 <= log_wakesta_cnt)
    {
        log_wakesta_cnt = 0;
        spm_snapshot_golden_setting = 0;
    }
#if 0
    else
    {
        if (2 != spm_snapshot_golden_setting)
        {
            if ((0x90100000 == wakesta->event_reg) && (0x140001f == wakesta->debug_flag))
                spm_snapshot_golden_setting = 1;
        }
    }
#endif
    
    
    if (0xFFFFFFF0 <= log_wakesta_index)
        log_wakesta_index = 0;
#endif

    spm_crit2("big core = %d, suspend dormant state = %d, chip = %d\n", SPM_CTRL_BIG_CPU, spm_dormant_sta, mt_get_chip_sw_ver());
    if (0 != spm_ap_mdsrc_req_cnt)
        spm_crit2("warning: spm_ap_mdsrc_req_cnt = %d, r7[ap_mdsrc_req] = 0x%x\n", spm_ap_mdsrc_req_cnt, spm_read(SPM_POWER_ON_VAL1) & (1<<17));

    if (wakesta->r12 & WAKE_SRC_EINT)
        mt_eint_print_status();

    if (wakesta->r12 & WAKE_SRC_CLDMA_MD)
        exec_ccci_kern_func_by_md_id(0, ID_GET_MD_WAKEUP_SRC, NULL, 0);

	return wr;
}