aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ralink/mt7620.c
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2013-08-23 02:31:30 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-09-04 10:57:05 -0400
commitded1e9d727f0e7cb1cf7f243dac2a87974ae048f (patch)
tree1b642fd72fda9849b8b48d03108eaf6019c4d0ab /arch/mips/ralink/mt7620.c
parent2b9dbb15a9d4c7b8f87f98aa770f68fb60a7b170 (diff)
MIPS: ralink: mt7620: Improve clock frequency detection
The current code assumes that the peripheral clock always runs at 40MHz which is not true in all configuration. The peripheral clock can also use the reference clock instead of the fixed 40MHz rate. If the reference clock runs at a different rate, various peripheries are behaving incorrectly. Additionally, the currectly calculated system clock is also wrong. The actual value what the code computes is the rate of the DRAM which can be different from the system clock. Add new helper functions to get the rate of the different clocks and use the correct values for the registered clock devices. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5755/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/ralink/mt7620.c')
-rw-r--r--arch/mips/ralink/mt7620.c200
1 files changed, 175 insertions, 25 deletions
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index ccdec5a68c18..61dcee8248de 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -23,9 +23,6 @@
23/* does the board have sdram or ddram */ 23/* does the board have sdram or ddram */
24static int dram_type; 24static int dram_type;
25 25
26/* the pll dividers */
27static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 };
28
29static struct ralink_pinmux_grp mode_mux[] = { 26static struct ralink_pinmux_grp mode_mux[] = {
30 { 27 {
31 .name = "i2c", 28 .name = "i2c",
@@ -140,34 +137,187 @@ struct ralink_pinmux rt_gpio_pinmux = {
140 .uart_mask = MT7620_GPIO_MODE_UART0_MASK, 137 .uart_mask = MT7620_GPIO_MODE_UART0_MASK,
141}; 138};
142 139
143void __init ralink_clk_init(void) 140static __init u32
141mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
144{ 142{
145 unsigned long cpu_rate, sys_rate; 143 u64 t;
146 u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0);
147 u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1);
148 u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK;
149 u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK;
150
151 if (cpu_clk) {
152 cpu_rate = 480000000;
153 } else if (!swconfig) {
154 cpu_rate = 600000000;
155 } else {
156 u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO;
157 u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO;
158 144
159 cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; 145 t = ref_rate;
160 } 146 t *= mul;
147 do_div(t, div);
148
149 return t;
150}
151
152#define MHZ(x) ((x) * 1000 * 1000)
153
154static __init unsigned long
155mt7620_get_xtal_rate(void)
156{
157 u32 reg;
158
159 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
160 if (reg & SYSCFG0_XTAL_FREQ_SEL)
161 return MHZ(40);
162
163 return MHZ(20);
164}
165
166static __init unsigned long
167mt7620_get_periph_rate(unsigned long xtal_rate)
168{
169 u32 reg;
170
171 reg = rt_sysc_r32(SYSC_REG_CLKCFG0);
172 if (reg & CLKCFG0_PERI_CLK_SEL)
173 return xtal_rate;
174
175 return MHZ(40);
176}
177
178static const u32 mt7620_clk_divider[] __initconst = { 2, 3, 4, 8 };
179
180static __init unsigned long
181mt7620_get_cpu_pll_rate(unsigned long xtal_rate)
182{
183 u32 reg;
184 u32 mul;
185 u32 div;
186
187 reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0);
188 if (reg & CPLL_CFG0_BYPASS_REF_CLK)
189 return xtal_rate;
190
191 if ((reg & CPLL_CFG0_SW_CFG) == 0)
192 return MHZ(600);
193
194 mul = (reg >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) &
195 CPLL_CFG0_PLL_MULT_RATIO_MASK;
196 mul += 24;
197 if (reg & CPLL_CFG0_LC_CURFCK)
198 mul *= 2;
199
200 div = (reg >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) &
201 CPLL_CFG0_PLL_DIV_RATIO_MASK;
202
203 WARN_ON(div >= ARRAY_SIZE(mt7620_clk_divider));
204
205 return mt7620_calc_rate(xtal_rate, mul, mt7620_clk_divider[div]);
206}
207
208static __init unsigned long
209mt7620_get_pll_rate(unsigned long xtal_rate, unsigned long cpu_pll_rate)
210{
211 u32 reg;
212
213 reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1);
214 if (reg & CPLL_CFG1_CPU_AUX1)
215 return xtal_rate;
216
217 if (reg & CPLL_CFG1_CPU_AUX0)
218 return MHZ(480);
161 219
220 return cpu_pll_rate;
221}
222
223static __init unsigned long
224mt7620_get_cpu_rate(unsigned long pll_rate)
225{
226 u32 reg;
227 u32 mul;
228 u32 div;
229
230 reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
231
232 mul = reg & CPU_SYS_CLKCFG_CPU_FFRAC_MASK;
233 div = (reg >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) &
234 CPU_SYS_CLKCFG_CPU_FDIV_MASK;
235
236 return mt7620_calc_rate(pll_rate, mul, div);
237}
238
239static const u32 mt7620_ocp_dividers[16] __initconst = {
240 [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2,
241 [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3,
242 [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4,
243 [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5,
244 [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10,
245};
246
247static __init unsigned long
248mt7620_get_dram_rate(unsigned long pll_rate)
249{
162 if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) 250 if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM)
163 sys_rate = cpu_rate / 4; 251 return pll_rate / 4;
164 else 252
165 sys_rate = cpu_rate / 3; 253 return pll_rate / 3;
254}
255
256static __init unsigned long
257mt7620_get_sys_rate(unsigned long cpu_rate)
258{
259 u32 reg;
260 u32 ocp_ratio;
261 u32 div;
262
263 reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
264
265 ocp_ratio = (reg >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) &
266 CPU_SYS_CLKCFG_OCP_RATIO_MASK;
267
268 if (WARN_ON(ocp_ratio >= ARRAY_SIZE(mt7620_ocp_dividers)))
269 return cpu_rate;
270
271 div = mt7620_ocp_dividers[ocp_ratio];
272 if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio))
273 return cpu_rate;
274
275 return cpu_rate / div;
276}
277
278void __init ralink_clk_init(void)
279{
280 unsigned long xtal_rate;
281 unsigned long cpu_pll_rate;
282 unsigned long pll_rate;
283 unsigned long cpu_rate;
284 unsigned long sys_rate;
285 unsigned long dram_rate;
286 unsigned long periph_rate;
287
288 xtal_rate = mt7620_get_xtal_rate();
289
290 cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate);
291 pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate);
292
293 cpu_rate = mt7620_get_cpu_rate(pll_rate);
294 dram_rate = mt7620_get_dram_rate(pll_rate);
295 sys_rate = mt7620_get_sys_rate(cpu_rate);
296 periph_rate = mt7620_get_periph_rate(xtal_rate);
297
298#define RFMT(label) label ":%lu.%03luMHz "
299#define RINT(x) ((x) / 1000000)
300#define RFRAC(x) (((x) / 1000) % 1000)
301
302 pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"),
303 RINT(xtal_rate), RFRAC(xtal_rate),
304 RINT(cpu_pll_rate), RFRAC(cpu_pll_rate),
305 RINT(pll_rate), RFRAC(pll_rate));
306
307 pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"),
308 RINT(cpu_rate), RFRAC(cpu_rate),
309 RINT(dram_rate), RFRAC(dram_rate),
310 RINT(sys_rate), RFRAC(sys_rate),
311 RINT(periph_rate), RFRAC(periph_rate));
312
313#undef RFRAC
314#undef RINT
315#undef RFMT
166 316
167 ralink_clk_add("cpu", cpu_rate); 317 ralink_clk_add("cpu", cpu_rate);
168 ralink_clk_add("10000100.timer", 40000000); 318 ralink_clk_add("10000100.timer", periph_rate);
169 ralink_clk_add("10000500.uart", 40000000); 319 ralink_clk_add("10000500.uart", periph_rate);
170 ralink_clk_add("10000c00.uartlite", 40000000); 320 ralink_clk_add("10000c00.uartlite", periph_rate);
171} 321}
172 322
173void __init ralink_of_remap(void) 323void __init ralink_of_remap(void)