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;
}
void read_pcm_data(int *sram_data, int length)

{
	int data_addr;
	if (length <= last_pc_size)	{
		for (data_addr =0 ; data_addr < length; data_addr++)
			sram_data[data_addr] = pcm_im_read_data(last_pcm_sram_addr -data_addr);
	}		
	else	{	
		spm_crit2("over size: %d\n", last_pc_size);
	}
}
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;
}
static void spm_set_sysclk_settle(void)
{
    u32 md_settle, settle;

    /* get MD SYSCLK settle */
    spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) | CC_SYSSETTLE_SEL);
    spm_write(SPM_CLK_SETTLE, 0);
    md_settle = spm_read(SPM_CLK_SETTLE);

    /* SYSCLK settle = MD SYSCLK settle but set it again for MD PDN */
    spm_write(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE - md_settle);
    settle = spm_read(SPM_CLK_SETTLE);

    spm_crit2("md_settle = %u, settle = %u\n", md_settle, settle);
}
Example #5
0
static void spm_set_sysclk_settle(void)
{
    u32 md_settle, settle;
    
    /* MD SYSCLK settle is from MD1 */
    spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) | CC_SYSSETTLE_SEL);
    
    /* get MD SYSCLK settle */
    spm_write(SPM_CLK_SETTLE, 0);           
    md_settle = spm_read(SPM_CLK_SETTLE);
    
    /* SYSCLK settle = MD SYSCLK settle but change it if needed */
    #if SPM_AP_ONLY_SLEEP
        spm_write(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE - md_settle);
    #endif
        settle = spm_read(SPM_CLK_SETTLE);
    
   spm_crit2("md_settle = %u, settle = %u\n", md_settle, settle);
}
static u32 spm_get_wake_period(int pwake_time, wake_reason_t last_wr)
{
    int period = SPM_WAKE_PERIOD;

    if (pwake_time < 0) {
        /* use FG to get the period of 1% battery decrease */
        period = get_dynamic_period(last_wr != WR_PCM_TIMER ? 1 : 0, SPM_WAKE_PERIOD, 1);
        if (period <= 0) {
            spm_warn("CANNOT GET PERIOD FROM FUEL GAUGE\n");
            period = SPM_WAKE_PERIOD;
        }
    } else {
        period = pwake_time;
        spm_crit2("pwake = %d\n", pwake_time);
    }

    if (period > 36 * 3600)     /* max period is 36.4 hours */
        period = 36 * 3600;

    return period;
}
/*
 * if in talking, modify @spm_flags based on @lpscen and return __spm_talking,
 * otherwise, do nothing and return @lpscen
 */
struct spm_lp_scen *spm_check_talking_get_lpscen(struct spm_lp_scen *lpscen,
						 u32 *spm_flags)
{
	if (can_enter_talking_dpidle()) {
		if (lpscen == &__spm_suspend) {
			*spm_flags &= ~SPM_CPU_DORMANT;
			spm_crit2("in talking\n");
		} else {
			*spm_flags |= SPM_CPU_DORMANT;
			spm_debug("in talking\n");
		}

		set_flags_for_mainpll(spm_flags);	/* ANC needs MAINPLL on */

		__spm_talking.pwrctrl->wake_src = lpscen->pwrctrl->wake_src;
		__spm_talking.pwrctrl->wake_src_md32 = lpscen->pwrctrl->wake_src_md32;

		lpscen = &__spm_talking;
	}

	return lpscen;
}
/*
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
}
static void spm_suspend_post_process(struct pwr_ctrl *pwrctrl)
{
#if 0
    u32 rdata1 = 0, rdata2 = 0;
          
    pwrap_read(0x2c2, &rdata1);
    pwrap_write(0x2c2, 0x3210);
    pwrap_read(0x2c2, &rdata2);
    if(rdata2 != 0x3210)
    {
        spm_crit2("resume pmic wrapper 0x2c2, rdata1 = 0x%x, rdata2 = 0x%x\n", rdata1, rdata2);
        BUG();
    }
#endif

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

    /* set PMIC WRAP table for normal power control */
    mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_NORMAL);

    spm_i2c_control(I2C_CHANNEL, 0);
}
/*
 * 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;  
}
static bool pcm_sysfs_write(const char *buf,unsigned long count)
{
    char field[30];
    int value;
    
    if(buf[0]=='0' && buf[1]=='x')
        sscanf(buf,"%x%s",&value,field);
    else
        sscanf(buf,"%d%s",&value,field);
    
    if(strcmp(field,"monitor_signal_0")==0)
    {
        if(value >= 0 && value < twam_signal_num)
         {
                pcm_fs_curr->monitor_signal[0]=value;                
         }
    
    }
    else if(strcmp(field,"monitor_signal_1")==0)
    {
        if(value >= 0 && value < twam_signal_num)
         {
                pcm_fs_curr->monitor_signal[1]=value;
         }
    
    }    
    else if(strcmp(field,"twam_log_en")==0)
        pcm_fs_curr->twam_log_en=value;
    else if(strcmp(field,"cpu_pdn")==0)
    {
        if(pcm_fs_curr->scenario == SPM_PCM_KERNEL_SUSPEND)
        pcm_fs_curr->cpu_pdn=value;
        else if(pcm_fs_curr->scenario == SPM_PCM_DEEP_IDLE)
        {
            if( value == 0 )
                idle_state_en( IDLE_TYPE_DP , value );//dpidle disable
            else
            {
                pcm_fs_curr->cpu_pdn=(value-1);
                idle_state_en( IDLE_TYPE_DP , 1 );//dpidle enable
            }
        }
            
    }
    else if(strcmp(field,"infra_pdn")==0)
        pcm_fs_curr->infra_pdn=value;
    else if(strcmp(field,"timer_val_ms")==0)
        pcm_fs_curr->timer_val_ms=value;
    else if(strcmp(field,"wfi_sel0")==0)
        pcm_fs_curr->wfi_sel[0]=value;
    else if(strcmp(field,"wfi_sel1")==0)
        pcm_fs_curr->wfi_sel[1]=value;
    else if(strcmp(field,"wake_src")==0)
     {
        if(value == 0)
            {
                BUG_ON(pcm_wakesrc_backup[pcm_fs_curr->scenario]!=0);//you need to restore previous mask first
                pcm_wakesrc_backup[pcm_fs_curr->scenario] = spm_wakesrc_mask_all(pcm_fs_curr->scenario);
            }
        else if(value >= 0 && value < 32)
            spm_wakesrc_set(pcm_fs_curr->scenario,value);
        else if(value < 0 && value > -32)
            spm_wakesrc_clear(pcm_fs_curr->scenario,value* -1);
        else if(pcm_wakesrc_backup[pcm_fs_curr->scenario]!=0)
            {
                spm_wakesrc_restore(pcm_fs_curr->scenario,pcm_wakesrc_backup[pcm_fs_curr->scenario]);
                pcm_wakesrc_backup[pcm_fs_curr->scenario]=0;
            }
        
     }
     else if(strcmp(field,"md_mask")==0)
     	{
     		if(value >= 0 && value<=3)
     			pcm_fs_curr->md_mask=value;
     	}
     else if(strcmp(field,"mm_mask")==0)
     	{
     		if(value >= 0 && value<=3)
     			pcm_fs_curr->mm_mask=value;
     	}     
     else if(strcmp(field,"reserved")==0)
        pcm_fs_curr->reserved=value;
     else if(strcmp(field,"pcm_reserved")==0)
        pcm_fs_curr->pcm_reserved=value;     
     else
     {
        spm_crit2("spm_fs write FAIL: field = %s, value=%d\n",field,value);
        return false;//Can't not find field       
     }
     
  spm_crit2("spm_fs write success: field = %s, value=%d\n",field,value);
  
  return true; 
}
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);
}
Example #13
0
static wake_reason_t spm_output_wake_reason(const wake_status_t *wakesta, bool dpidle)
{
    char str[200] = { 0 };
    wake_reason_t wr = WR_NONE;

    if (wakesta->debug_reg != 0) {
        spm_error2("PCM ASSERT AND PC = %u (0x%x)(0x%x)\n",
                   wakesta->debug_reg, wakesta->r13, wakesta->event_reg);
        return WR_PCM_ASSERT;
    }

    if (dpidle) {   /* bypass wakeup event check */
        spm_info("[DP] r12 = 0x%x, r13 = 0x%x, r7 = 0x%x (0x%x)\n",
                 wakesta->r12, wakesta->r13, spm_read(SPM_PCM_REG7_DATA), spm_read(SPM_POWER_ON_VAL1));
        return WR_WAKE_SRC;
    }

    if (wakesta->r12 & (1U << 0)) {
        if (!(wakesta->isr & ISR_TWAM) && !wakesta->cpu_wake) {
            strcat(str, "PCM_TIMER ");
            wr = WR_PCM_TIMER;
        } else {
            if (wakesta->isr & ISR_TWAM) {
                strcat(str, "TWAM ");
                wr = WR_WAKE_SRC;
            }
            if (wakesta->cpu_wake) {
                strcat(str, "CPU ");
                wr = WR_WAKE_SRC;
            }
        }
    }
    if (wakesta->r12 & WAKE_SRC_TS) {
        strcat(str, "TS ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_KP) {
        strcat(str, "KP ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_WDT) {
        strcat(str, "WDT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_GPT) {
        strcat(str, "GPT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_EINT) {
        strcat(str, "EINT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CONN_WDT) {
        strcat(str, "CONN_WDT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CCIF_MD) {
        strcat(str, "CCIF_MD ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_LOW_BAT) {
        strcat(str, "LOW_BAT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CONN) {
        strcat(str, "CONN ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & (1U << 13)) {
        strcat(str, "PCM_WDT ");
        wr = WR_PCM_WDT;
    }
    if (wakesta->r12 & WAKE_SRC_USB_CD) {
        strcat(str, "USB_CD ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_USB_PDN) {
        strcat(str, "USB_PDN ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_DBGSYS) {
        strcat(str, "DBGSYS ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_UART0) {
        strcat(str, "UART0 ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_AFE) {
        strcat(str, "AFE ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_THERM) {
        strcat(str, "THERM ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CIRQ) {
        strcat(str, "CIRQ ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_SYSPWREQ) {
        strcat(str, "SYSPWREQ ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_MD_WDT) {
        strcat(str, "MD_WDT ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CPU0_IRQ) {
        strcat(str, "CPU0_IRQ ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CPU1_IRQ) {
        strcat(str, "CPU1_IRQ ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CPU2_IRQ) {
        strcat(str, "CPU2_IRQ ");
        wr = WR_WAKE_SRC;
    }
    if (wakesta->r12 & WAKE_SRC_CPU3_IRQ) {
        strcat(str, "CPU3_IRQ ");
        wr = WR_WAKE_SRC;
    }
    if (wr == WR_NONE) {
        strcat(str, "UNKNOWN ");
        wr = WR_UNKNOWN;
    }

    spm_crit2("wake up by %s(0x%x)(0x%x)(%u)\n",
              str, wakesta->r12, wakesta->raw_sta, wakesta->timer_out);
    spm_crit2("event_reg = 0x%x, isr = 0x%x, r13 = 0x%x\n",
              wakesta->event_reg, wakesta->isr, wakesta->r13);

    if (wakesta->r12 & WAKE_SRC_EINT)
        mt_eint_print_status();
    if (wakesta->r12 & WAKE_SRC_CCIF_MD)
        exec_ccci_kern_func_by_md_id(0, ID_GET_MD_WAKEUP_SRC, NULL, 0);

    return wr;
}
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;
}
Example #15
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;
}
Example #16
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;
    
}
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;
}