aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/mips/include/asm/mach-ralink/mt7620.h40
-rw-r--r--arch/mips/ralink/mt7620.c200
2 files changed, 207 insertions, 33 deletions
diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h
index 9809972ea882..6f9b24f51157 100644
--- a/arch/mips/include/asm/mach-ralink/mt7620.h
+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -20,6 +20,8 @@
20#define SYSC_REG_CHIP_REV 0x0c 20#define SYSC_REG_CHIP_REV 0x0c
21#define SYSC_REG_SYSTEM_CONFIG0 0x10 21#define SYSC_REG_SYSTEM_CONFIG0 0x10
22#define SYSC_REG_SYSTEM_CONFIG1 0x14 22#define SYSC_REG_SYSTEM_CONFIG1 0x14
23#define SYSC_REG_CLKCFG0 0x2c
24#define SYSC_REG_CPU_SYS_CLKCFG 0x3c
23#define SYSC_REG_CPLL_CONFIG0 0x54 25#define SYSC_REG_CPLL_CONFIG0 0x54
24#define SYSC_REG_CPLL_CONFIG1 0x58 26#define SYSC_REG_CPLL_CONFIG1 0x58
25 27
@@ -29,20 +31,42 @@
29#define MT7620A_CHIP_NAME0 0x3637544d 31#define MT7620A_CHIP_NAME0 0x3637544d
30#define MT7620A_CHIP_NAME1 0x20203032 32#define MT7620A_CHIP_NAME1 0x20203032
31 33
34#define SYSCFG0_XTAL_FREQ_SEL BIT(6)
35
32#define CHIP_REV_PKG_MASK 0x1 36#define CHIP_REV_PKG_MASK 0x1
33#define CHIP_REV_PKG_SHIFT 16 37#define CHIP_REV_PKG_SHIFT 16
34#define CHIP_REV_VER_MASK 0xf 38#define CHIP_REV_VER_MASK 0xf
35#define CHIP_REV_VER_SHIFT 8 39#define CHIP_REV_VER_SHIFT 8
36#define CHIP_REV_ECO_MASK 0xf 40#define CHIP_REV_ECO_MASK 0xf
37 41
38#define CPLL_SW_CONFIG_SHIFT 31 42#define CLKCFG0_PERI_CLK_SEL BIT(4)
39#define CPLL_SW_CONFIG_MASK 0x1 43
40#define CPLL_CPU_CLK_SHIFT 24 44#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16
41#define CPLL_CPU_CLK_MASK 0x1 45#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf
42#define CPLL_MULT_RATIO_SHIFT 16 46#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */
43#define CPLL_MULT_RATIO 0x7 47#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */
44#define CPLL_DIV_RATIO_SHIFT 10 48#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */
45#define CPLL_DIV_RATIO 0x3 49#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */
50#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */
51#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */
52#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */
53#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */
54#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */
55#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8
56#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f
57#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0
58#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f
59
60#define CPLL_CFG0_SW_CFG BIT(31)
61#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16
62#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7
63#define CPLL_CFG0_LC_CURFCK BIT(15)
64#define CPLL_CFG0_BYPASS_REF_CLK BIT(14)
65#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10
66#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3
67
68#define CPLL_CFG1_CPU_AUX1 BIT(25)
69#define CPLL_CFG1_CPU_AUX0 BIT(24)
46 70
47#define SYSCFG0_DRAM_TYPE_MASK 0x3 71#define SYSCFG0_DRAM_TYPE_MASK 0x3
48#define SYSCFG0_DRAM_TYPE_SHIFT 4 72#define SYSCFG0_DRAM_TYPE_SHIFT 4
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)