int enable_clock(enum mt65xx_clock_id id, char *mod_name) { unsigned long flags; int ret = 0; int category = id / CLK_REG_WIDTH; int offset = id % CLK_REG_WIDTH;
if (CATEGORY_AP1(category)) { … } … if (CATEGORY_MM(category)) { … } if (CATEGORY_AUD(category)) { … } ret = enable_clock_internal(category, mask);
/********************************** * cpufreq target callback function ***********************************/ /************************************************* * [note] * 1. handle frequency change request * 2. call mtk_cpufreq_set to set target frequency **************************************************/ static int mtk_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { … /****************************** * look up the target frequency *******************************/ if (cpufreq_frequency_table_target(policy, mtk_cpu_freqs_table, target_freq, relation, &idx)) return -EINVAL; //idx是目标调频点索引值
if (get_chip_ver() >= CHIP_6577_E1) {… } else if (get_chip_ver() >= CHIP_6575_E2) { next = &mt6575_freqs_e2[idx]; } … // next指向目标调频点 // freqs.old是当前频点,freqs.new是目标频点 freqs.old = policy->cur; freqs.new = next->cpufreq_mhz; freqs.cpu = policy->cpu;
if (freqs.new > g_limited_freq) { dprintk("CPU frequency has been limited to %d Mhz, request %d Mhz will be limited\n", g_limited_freq / 1000, freqs.new / 1000); freqs.new = g_limited_freq; }
if (freqs.new { dprintk("cannot switch CPU frequency to %d Mhz due to voltage limitation\n", g_limited_min_freq / 1000); freqs.new = g_limited_min_freq; } #endif
/************************************************ * target frequency == existing frequency, skip it *************************************************/ if (freqs.old == freqs.new) { dprintk("CPU frequency from %d MHz to %d MHz (skipped) due to same frequency\n", freqs.old / 1000, freqs.new / 1000); return 0; }
/********************************************* * update current frequency due to last change **********************************************/ freqs.old = g_cur_freq;
/****************************** * set to the target freeuency *******************************/ //真正的调频操作 mtk_cpufreq_set(freqs.old, freqs.new); spin_unlock_irqrestore(&mtk_cpufreq_lock, flags);
/***************************************** * frequency ramp up and ramp down handler ******************************************/ /*********************************************************** * [note] * 1. frequency ramp up need to wait voltage settle * 2. frequency ramp down do not need to wait voltage settle ************************************************************/ static void mtk_cpufreq_set(unsigned int freq_old, unsigned int freq_new) { if (freq_new == DVFS_F1 || freq_new == DVFS_F1_TM) /* set ARMPLL divider to 1/1 */ { … } else if (freq_new == DVFS_F2 || freq_new == DVFS_F2_TM) /* set ARMPLL divider to 5/6 */ { if (freq_new > freq_old) { //升频,先调压再调频 //调压 #ifdef MTK_BUCK_ADJUST DRV_WriteReg32(SC_AP_DVFS_CON, ((DRV_Reg32(SC_AP_DVFS_CON) & 0xFFFFFFFC) | 0x03));
mb(); udelay(PMIC_SETTLE_TIME); #endif g_cur_freq = freq_new; //调频 DRV_WriteReg32(TOP_CKDIV1, 0x19); } else { //降频,先调频再调压 //调频 g_cur_freq = freq_new; DRV_WriteReg32(TOP_CKDIV1, 0x19); mb(); //调压 #ifdef MTK_BUCK_ADJUST DRV_WriteReg32(SC_AP_DVFS_CON, ((DRV_Reg32(SC_AP_DVFS_CON) & 0xFFFFFFFC) | 0x03)); #endif } } else if (freq_new == DVFS_F3 || freq_new == DVFS_F3_TM) /* set ARMPLL divider to 3/4 */ { } else if (freq_new == DVFS_F4 || freq_new == DVFS_F4_TM) /* set ARMPLL divider to 2/3 */ { } else if (freq_new == DVFS_F5 || freq_new == DVFS_F5_TM) /* set ARMPLL divider to 1/2 */ { } else if (freq_new == DVFS_F6 || freq_new == DVFS_F6_TM) /* set ARMPLL divider to 1/4 */ { } else if (freq_new == DVFS_F7 || freq_new == DVFS_F7_TM) /* set ARMPLL divider to 1/6 */ { } }