static void fh_switch2fhctl(enum FH_PLL_ID pll_id, int i_control) { unsigned int mask = 0; VALIDATE_PLLID(pll_id); mask = 0x1U<<pll_id; //FIXME: clock should be turned on/off at entry functions // Turn on clock //if (i_control == 1) //fh_set_field(REG_FHCTL_CLK_CON, mask, i_control); // Release software reset //fh_set_field(REG_FHCTL_RST_CON, mask, 0); // Switch to FHCTL_CORE controller fh_set_field(REG_FHCTL_HP_EN, mask, i_control); //Turn off clock //if (i_control == 0) //fh_set_field(REG_FHCTL_CLK_CON, mask, i_control); return; }
static void fh_sync_ncpo_to_fhctl_dds(enum FH_PLL_ID pll_id) { unsigned int reg_src = 0; unsigned int reg_dst = 0; VALIDATE_PLLID(pll_id); reg_src = g_reg_pll_con1[pll_id]; reg_dst = g_reg_dds[pll_id]; fh_write32(reg_dst, (fh_read32(reg_src)&MASK21b)|BIT32); return; }
static void fh_sync_ncpo_to_fhctl_dds(enum FH_PLL_ID pll_id) { unsigned long reg_src = 0; unsigned long reg_dst = 0; VALIDATE_PLLID(pll_id); reg_src = g_reg_pll_con1[pll_id]; reg_dst = g_reg_dds[pll_id]; if (pll_id == FH_MEM_PLLID) { /* MEMPLL_CON1 field mapping. Integer: [31:25] => FHCTL_DDS[20:14] ; Fraction: [24:1] => FHCTL_DDS[13:0] */ fh_write32(reg_dst, (((fh_read32(reg_src) & 0xFFFFFFFE) >> 11) & MASK21b) | BIT32); } else {
static int mt_fh_hal_dvfs(enum FH_PLL_ID pll_id, unsigned int dds_value) { unsigned long flags = 0; FH_MSG("%s for pll %d:",__func__, pll_id); VALIDATE_PLLID(pll_id); local_irq_save(flags); //1. sync ncpo to DDS of FHCTL fh_sync_ncpo_to_fhctl_dds(pll_id); //FH_MSG("1. sync ncpo to DDS of FHCTL"); FH_MSG("FHCTL%d_DDS: 0x%08x", pll_id, (fh_read32(g_reg_dds[pll_id])&MASK21b)); //2. enable DVFS and Hopping control { unsigned int reg_cfg = g_reg_cfg[pll_id]; fh_set_field(reg_cfg, FH_SFSTRX_EN, 1); //enable dvfs mode fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); //enable hopping control } //for slope setting. //TODO: Does this need to be changed? fh_write32(REG_FHCTL_SLOPE0, 0x6003c97); //FH_MSG("2. enable DVFS and Hopping control"); //3. switch to hopping control fh_switch2fhctl(pll_id, 1); mb(); //FH_MSG("3. switch to hopping control"); //4. set DFS DDS { unsigned int dvfs_req = g_reg_dvfs[pll_id]; fh_write32(dvfs_req, (dds_value)|(BIT32)); //set dds //FH_MSG("4. set DFS DDS"); FH_MSG("FHCTL%d_DDS: 0x%08x", pll_id, (fh_read32(dvfs_req)&MASK21b)); FH_MSG("FHCTL%d_DVFS: 0x%08x", pll_id, (fh_read32(dvfs_req)&MASK21b)); } //4.1 ensure jump to target DDS wait_dds_stable(dds_value, g_reg_mon[pll_id], 100); //FH_MSG("4.1 ensure jump to target DDS"); //5. write back to ncpo //FH_MSG("5. write back to ncpo"); { unsigned int reg_dvfs = 0; unsigned int reg_pll_con1 = 0; reg_pll_con1 = g_reg_pll_con1[pll_id]; reg_dvfs = g_reg_dvfs[pll_id]; FH_MSG("PLL_CON1: 0x%08x",(fh_read32(reg_pll_con1)&MASK21b)); fh_write32(reg_pll_con1, (fh_read32(g_reg_mon[pll_id])&MASK21b) |(fh_read32(reg_pll_con1)&0xFFE00000)|(BIT32)); FH_MSG("PLL_CON1: 0x%08x",(fh_read32(reg_pll_con1)&MASK21b)); } //6. switch to register control fh_switch2fhctl(pll_id, 0); mb(); //FH_MSG("6. switch to register control"); local_irq_restore(flags); return 0; }
static int __freqhopping_ctrl(struct freqhopping_ioctl* fh_ctl,bool enable) { const struct freqhopping_ssc* pSSC_setting = NULL; unsigned int ssc_setting_id = 0; int retVal = 1; fh_pll_t* pfh_pll = NULL; FH_MSG("%s for pll %d", __func__, fh_ctl->pll_id); //Check the out of range of frequency hopping PLL ID VALIDATE_PLLID(fh_ctl->pll_id); pfh_pll = &g_fh_pll[fh_ctl->pll_id]; pfh_pll->curr_freq = g_default_freq[fh_ctl->pll_id]; if((enable == true) && (pfh_pll->fh_status == FH_FH_ENABLE_SSC)){ __disable_ssc(fh_ctl->pll_id,pSSC_setting); } else if((enable == false) && (pfh_pll->fh_status == FH_FH_DISABLE)){ retVal = 0; goto Exit; } //enable freq. hopping @ fh_ctl->pll_id if( enable == true) { if(pfh_pll->pll_status == FH_PLL_DISABLE) { pfh_pll->fh_status = FH_FH_ENABLE_SSC; retVal = 0; goto Exit; } else { if(pfh_pll->user_defined == true){ FH_MSG("Apply user defined setting"); pSSC_setting = &mt_ssc_fhpll_userdefined[fh_ctl->pll_id]; pfh_pll->setting_id = USER_DEFINE_SETTING_ID; } else { if( pfh_pll->curr_freq != 0 ){ ssc_setting_id = pfh_pll->setting_id = __freq_to_index(fh_ctl->pll_id, pfh_pll->curr_freq); } else{ ssc_setting_id = 0; } if(ssc_setting_id == 0){ FH_MSG("!!! No corresponding setting found !!!"); //just disable FH & exit __disable_ssc(fh_ctl->pll_id,pSSC_setting); goto Exit; } pSSC_setting = &g_ssc_setting[fh_ctl->pll_id][ssc_setting_id]; }//user defined if(pSSC_setting == NULL){ FH_MSG("SSC_setting is NULL!"); //disable FH & exit __disable_ssc(fh_ctl->pll_id, pSSC_setting); goto Exit; } __enable_ssc(fh_ctl->pll_id, pSSC_setting); retVal = 0; } } else{ //disable req. hopping @ fh_ctl->pll_id __disable_ssc(fh_ctl->pll_id, pSSC_setting); retVal = 0; } Exit: return retVal; }
static int fh_dvfs_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) { unsigned int p1,p2,p3,p4,p5; p1 = p2 = p3 = p4 = p5 = 0; FH_MSG("EN: %s",__func__); if (count == 0) return -1; FH_MSG("EN: p1=%d p2=%d p3=%d", p1, p2, p3); switch(p1){ case FH_ARMCA7_PLLID: mt_fh_hal_dfs_armpll(p2, p3); FH_MSG("ARMCA7PLL DVFS completed\n"); break; case FH_ARMCA15_PLLID: mt_fh_hal_dfs_armpll(p2, p3); FH_MSG("ARMCA15PLL DVFS completed\n"); break; case FH_MM_PLLID: mt_fh_hal_dfs_mmpll(p3); FH_MSG("MMPLL DVFS completed\n"); break; case FH_VENC_PLLID: mt_fh_hal_dfs_vencpll(p3); FH_MSG("VENCPLL DVFS completed\n"); break; case 4370: { unsigned int reg_cfg = 0; VALIDATE_PLLID(p2); reg_cfg = g_reg_cfg[p2]; //TODO: Find out who use this case FH_MSG("pllid=%d dt=%d df=%d lowbnd=%d", p2, p3, p4, p5); fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); //disable SSC mode fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); //disable dvfs mode fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); //disable hopping control fh_sync_ncpo_to_fhctl_dds(p2); FH_MSG("Enable FHCTL%d SSC mode", p2); FH_MSG("DDS: 0x%08x", (fh_read32(reg_cfg)&MASK21b)); fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p4); fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p3); fh_write32(g_reg_updnlmt[p2], (PERCENT_TO_DDSLMT((fh_read32(reg_cfg)&MASK21b),p5) << 16)); FH_MSG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[p2])); fh_switch2fhctl(p2, 1); fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); //enable SSC mode fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); //enable hopping control FH_MSG("CFG: 0x%08x", fh_read32(reg_cfg)); } break; case 2222: //TODO: and what this case for? if (p2==0) //disable mt_fh_hal_popod_save(); else if (p2==1) //enable mt_fh_hal_popod_restore(); break; default: mt_fh_hal_dvfs(p1, p2); break; }; return count; }