static int mt_fh_hal_dfs_mpll(unsigned int target_dds) { unsigned long flags = 0; const unsigned int pll_id = FH_M_PLLID; const unsigned int reg_cfg = g_reg_cfg[pll_id]; FH_MSG("%s, current dds(MPLL_CON1): 0x%x, target dds %d", __func__,(fh_read32(g_reg_pll_con1[pll_id])&MASK21b), target_dds); spin_lock_irqsave(&g_fh_lock, flags); if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ unsigned int pll_dds = 0; unsigned int fh_dds = 0; 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 pll_dds = (DRV_Reg32(g_reg_dds[pll_id])) & MASK21b; fh_dds = (DRV_Reg32(g_reg_mon[pll_id])) & MASK21b; FH_MSG(">p:f< %x:%x",pll_dds,fh_dds); wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); } mt_fh_hal_dvfs(pll_id, target_dds); if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ const struct freqhopping_ssc* p_setting = &ssc_mpll_setting[2]; 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(pll_id); FH_MSG("Enable mpll SSC mode"); FH_MSG("DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); fh_set_field(reg_cfg,MASK_FRDDSX_DYS,p_setting->df); fh_set_field(reg_cfg,MASK_FRDDSX_DTS,p_setting->dt); fh_write32(g_reg_updnlmt[pll_id], (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd) << 16)); FH_MSG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); fh_switch2fhctl(pll_id, 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)); } spin_unlock_irqrestore(&g_fh_lock, flags); return 0; }
static void mt_fh_hal_popod_save(void) { const unsigned int pll_id = FH_MAIN_PLLID; FH_MSG_DEBUG("EN: %s",__func__); //disable maipll SSC mode if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ unsigned int fh_dds = 0; unsigned int pll_dds = 0; const unsigned int reg_cfg = g_reg_cfg[pll_id]; //only when SSC is enable, turn off MAINPLL hopping 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 pll_dds = (DRV_Reg32(g_reg_dds[pll_id])) & MASK21b; fh_dds = (DRV_Reg32(g_reg_mon[pll_id])) & MASK21b; FH_MSG("Org pll_dds:%x fh_dds:%x",pll_dds,fh_dds); wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); //write back to ncpo fh_write32(g_reg_pll_con1[pll_id], (fh_read32(g_reg_dds[pll_id])&MASK21b)|(fh_read32(MAINPLL_CON1)&0xFFE00000)|(BIT32)); FH_MSG("MAINPLL_CON1: 0x%08x",(fh_read32(g_reg_pll_con1[pll_id])&MASK21b)); // switch to register control fh_switch2fhctl(pll_id,0); mb(); } }
//armpll dfs mdoe static int mt_fh_hal_dfs_armpll(unsigned int pll, unsigned int dds) { unsigned long flags = 0; unsigned int reg_cfg = 0; FH_MSG("%s for pll %d dds %d", __func__, pll, dds); switch(pll){ case FH_ARMCA7_PLLID: case FH_ARMCA15_PLLID: reg_cfg = g_reg_cfg[pll]; FH_MSG("(PLL_CON1): 0x%x",(fh_read32(g_reg_pll_con1[pll])&MASK21b)); break; default: BUG_ON(1); return 1; }; //TODO: provelock issue spin_lock(&g_fh_lock); spin_lock_irqsave(&g_fh_lock, flags); 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 mt_fh_hal_dvfs(pll, dds); 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 spin_unlock_irqrestore(&g_fh_lock, flags); return 0; }
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 mt_fh_hal_popod_restore(void) { const unsigned int pll_id = FH_MAIN_PLLID; FH_MSG_DEBUG("EN: %s",__func__); //enable maipll SSC mode if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ const struct freqhopping_ssc* p_setting = &ssc_mainpll_setting[2]; const unsigned int reg_cfg = g_reg_cfg[pll_id]; 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(pll_id); FH_MSG("Enable mainpll SSC mode"); FH_MSG("sync ncpo to DDS of FHCTL"); FH_MSG("FHCTL1_DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p_setting->df); fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p_setting->dt); fh_write32(g_reg_updnlmt[pll_id], (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd) << 16)); FH_MSG("REG_FHCTL2_UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); fh_switch2fhctl(pll_id,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("REG_FHCTL2_CFG: 0x%08x", fh_read32(reg_cfg)); } }
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 void __enable_ssc(unsigned int pll_id,const struct freqhopping_ssc* setting) { unsigned long flags = 0; const unsigned int reg_cfg = g_reg_cfg[pll_id]; const unsigned int reg_updnlmt = g_reg_updnlmt[pll_id]; const unsigned int reg_dds = g_reg_dds[pll_id]; FH_MSG_DEBUG("%s: %x~%x df:%d dt:%d dds:%x", __func__ , setting->lowbnd, setting->upbnd ,setting->df ,setting->dt ,setting->dds); mb(); g_fh_pll[pll_id].fh_status = FH_FH_ENABLE_SSC; local_irq_save(flags); //Set the relative parameter registers (dt/df/upbnd/downbnd) fh_set_field(reg_cfg, MASK_FRDDSX_DYS, setting->df); fh_set_field(reg_cfg, MASK_FRDDSX_DTS, setting->dt); fh_sync_ncpo_to_fhctl_dds(pll_id); //TODO: Not setting upper due to they are all 0? fh_write32(reg_updnlmt, (PERCENT_TO_DDSLMT((fh_read32(reg_dds)&MASK21b), setting->lowbnd) << 16)); //Switch to FHCTL fh_switch2fhctl(pll_id, 1); mb(); //Enable SSC fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); //Enable Hopping control fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); local_irq_restore(flags); return; }
static int mt_fh_hal_dfs_mmpll(unsigned int target_freq) //mmpll dfs mode { unsigned long flags = 0; unsigned int target_dds = 0; const unsigned int pll_id = FH_MM_PLLID; const unsigned int reg_cfg = g_reg_cfg[pll_id]; FH_MSG("%s, current dds(MMPLL_CON1): 0x%x, target freq %d", __func__,(fh_read32(g_reg_pll_con1[pll_id])&MASK21b), target_freq); spin_lock_irqsave(&g_fh_lock, flags); if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ unsigned int pll_dds = 0; unsigned int fh_dds = 0; //only when SSC is enable, turn off MEMPLL hopping 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 pll_dds = (DRV_Reg32(g_reg_dds[pll_id])) & MASK21b; fh_dds = (DRV_Reg32(g_reg_mon[pll_id])) & MASK21b; FH_MSG(">p:f< %x:%x",pll_dds,fh_dds); wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); } #if 1 //target_dds = (target_freq/26000) * pow(2, 14); //target_dds = (unsigned int)(((double)(target_freq)/26000.0) * 16384.0); //target_dds = target_freq * 16384 / 26000; //target_dds = (target_freq / 1000) * 16384 / 26; target_dds = (target_freq / 1000) * 8192 / 13; #else switch(target_freq){ case MMPLL_TARGET1_VCO: target_dds = MMPLL_TARGET1_DDS; break; case MMPLL_TARGET2_VCO: target_dds = MMPLL_TARGET2_DDS; break; case MMPLL_TARGET3_VCO: target_dds = MMPLL_TARGET3_DDS; break; case MMPLL_TARGET4_VCO: target_dds = MMPLL_TARGET4_DDS; break; case MMPLL_TARGET5_VCO: target_dds = MMPLL_TARGET5_DDS; break; case MMPLL_TARGET6_VCO: target_dds = MMPLL_TARGET6_DDS; break; default: FH_BUG_ON("incorrect target_freq"); break; }; #endif FH_MSG("target dds: 0x%x",target_dds); mt_fh_hal_dvfs(pll_id, target_dds); if(g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC){ const struct freqhopping_ssc* p_setting = &ssc_mmpll_setting[2]; 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(pll_id); FH_MSG("Enable mmpll SSC mode"); FH_MSG("DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); fh_set_field(reg_cfg,MASK_FRDDSX_DYS,p_setting->df); fh_set_field(reg_cfg,MASK_FRDDSX_DTS,p_setting->dt); fh_write32(g_reg_updnlmt[pll_id], (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd) << 16)); FH_MSG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); fh_switch2fhctl(pll_id, 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)); } spin_unlock_irqrestore(&g_fh_lock, flags); return 0; }
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 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; }