1 2#undef DEBUG 3 4#include <linux/kernel.h> 5#include <linux/errno.h> 6#include <linux/clk.h> 7#include <linux/io.h> 8#include <linux/cpufreq.h> 9#include <linux/slab.h> 10 11#include <plat/clock.h> 12#include <plat/sram.h> 13#include <plat/sdrc.h> 14 15#include "clock.h" 16#include "clock2xxx.h" 17#include "opp2xxx.h" 18#include "cm.h" 19#include "cm-regbits-24xx.h" 20 21const struct prcm_config *curr_prcm_set; 22const struct prcm_config *rate_table; 23 24/** 25 * omap2_table_mpu_recalc - just return the MPU speed 26 * @clk: virt_prcm_set struct clk 27 * 28 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set. 29 */ 30unsigned long omap2_table_mpu_recalc(struct clk *clk) 31{ 32 return curr_prcm_set->mpu_speed; 33} 34 35/* 36 * Look for a rate equal or less than the target rate given a configuration set. 37 * 38 * What's not entirely clear is "which" field represents the key field. 39 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and 40 * just uses the ARM rates. 41 */ 42long omap2_round_to_table_rate(struct clk *clk, unsigned long rate) 43{ 44 const struct prcm_config *ptr; 45 long highest_rate; 46 47 highest_rate = -EINVAL; 48 49 for (ptr = rate_table; ptr->mpu_speed; ptr++) { 50 if (!(ptr->flags & cpu_mask)) 51 continue; 52 if (ptr->xtal_speed != sclk->rate) 53 continue; 54 55 highest_rate = ptr->mpu_speed; 56 57 /* Can check only after xtal frequency check */ 58 if (ptr->mpu_speed <= rate) 59 break; 60 } 61 return highest_rate; 62} 63 64/* Sets basic clocks based on the specified rate */ 65int omap2_select_table_rate(struct clk *clk, unsigned long rate) 66{ 67 u32 cur_rate, done_rate, bypass = 0, tmp; 68 const struct prcm_config *prcm; 69 unsigned long found_speed = 0; 70 unsigned long flags; 71 72 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 73 if (!(prcm->flags & cpu_mask)) 74 continue; 75 76 if (prcm->xtal_speed != sclk->rate) 77 continue; 78 79 if (prcm->mpu_speed <= rate) { 80 found_speed = prcm->mpu_speed; 81 break; 82 } 83 } 84 85 if (!found_speed) { 86 printk(KERN_INFO "Could not set MPU rate to %luMHz\n", 87 rate / 1000000); 88 return -EINVAL; 89 } 90 91 curr_prcm_set = prcm; 92 cur_rate = omap2xxx_clk_get_core_rate(dclk); 93 94 if (prcm->dpll_speed == cur_rate / 2) { 95 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); 96 } else if (prcm->dpll_speed == cur_rate * 2) { 97 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); 98 } else if (prcm->dpll_speed != cur_rate) { 99 local_irq_save(flags); 100 101 if (prcm->dpll_speed == prcm->xtal_speed) 102 bypass = 1; 103 104 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) == 105 CORE_CLK_SRC_DPLL_X2) 106 done_rate = CORE_CLK_SRC_DPLL_X2; 107 else 108 done_rate = CORE_CLK_SRC_DPLL; 109 110 /* MPU divider */ 111 cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL); 112 113 /* dsp + iva1 div(2420), iva2.1(2430) */ 114 cm_write_mod_reg(prcm->cm_clksel_dsp, 115 OMAP24XX_DSP_MOD, CM_CLKSEL); 116 117 cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL); 118 119 /* Major subsystem dividers */ 120 tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; 121 cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, 122 CM_CLKSEL1); 123 124 if (cpu_is_omap2430()) 125 cm_write_mod_reg(prcm->cm_clksel_mdm, 126 OMAP2430_MDM_MOD, CM_CLKSEL); 127 128 /* x2 to enter omap2xxx_sdrc_init_params() */ 129 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); 130 131 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, 132 bypass); 133 134 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); 135 omap2xxx_sdrc_reprogram(done_rate, 0); 136 137 local_irq_restore(flags); 138 } 139 140 return 0; 141} 142 143#ifdef CONFIG_CPU_FREQ 144static struct cpufreq_frequency_table *freq_table; 145 146void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table) 147{ 148 const struct prcm_config *prcm; 149 int i = 0; 150 int tbl_sz = 0; 151 152 if (!cpu_is_omap24xx()) 153 return; 154 155 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 156 if (!(prcm->flags & cpu_mask)) 157 continue; 158 if (prcm->xtal_speed != sclk->rate) 159 continue; 160 161 /* don't put bypass rates in table */ 162 if (prcm->dpll_speed == prcm->xtal_speed) 163 continue; 164 165 tbl_sz++; 166 } 167 168 if (tbl_sz == 0) { 169 pr_warning("%s: no matching entries in rate_table\n", 170 __func__); 171 return; 172 } 173 174 /* Include the CPUFREQ_TABLE_END terminator entry */ 175 tbl_sz++; 176 177 freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz, 178 GFP_ATOMIC); 179 if (!freq_table) { 180 pr_err("%s: could not kzalloc frequency table\n", __func__); 181 return; 182 } 183 184 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 185 if (!(prcm->flags & cpu_mask)) 186 continue; 187 if (prcm->xtal_speed != sclk->rate) 188 continue; 189 190 /* don't put bypass rates in table */ 191 if (prcm->dpll_speed == prcm->xtal_speed) 192 continue; 193 194 freq_table[i].index = i; 195 freq_table[i].frequency = prcm->mpu_speed / 1000; 196 i++; 197 } 198 199 freq_table[i].index = i; 200 freq_table[i].frequency = CPUFREQ_TABLE_END; 201 202 *table = &freq_table[0]; 203} 204 205void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) 206{ 207 if (!cpu_is_omap24xx()) 208 return; 209 210 kfree(freq_table); 211} 212 213#endif 214