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; }
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; }
/************************************** * 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; }
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); }
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); }
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; }
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; }
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); }
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); }
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); }
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; }
/* 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 }
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 }
/***********************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; }