Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Gabor Juhos and committed by
Ralf Baechle
ded1e9d7 2b9dbb15

+206 -32
+32 -8
arch/mips/include/asm/mach-ralink/mt7620.h
··· 20 20 #define SYSC_REG_CHIP_REV 0x0c 21 21 #define SYSC_REG_SYSTEM_CONFIG0 0x10 22 22 #define SYSC_REG_SYSTEM_CONFIG1 0x14 23 + #define SYSC_REG_CLKCFG0 0x2c 24 + #define SYSC_REG_CPU_SYS_CLKCFG 0x3c 23 25 #define SYSC_REG_CPLL_CONFIG0 0x54 24 26 #define SYSC_REG_CPLL_CONFIG1 0x58 25 27 ··· 31 29 #define MT7620A_CHIP_NAME0 0x3637544d 32 30 #define MT7620A_CHIP_NAME1 0x20203032 33 31 32 + #define SYSCFG0_XTAL_FREQ_SEL BIT(6) 33 + 34 34 #define CHIP_REV_PKG_MASK 0x1 35 35 #define CHIP_REV_PKG_SHIFT 16 36 36 #define CHIP_REV_VER_MASK 0xf 37 37 #define CHIP_REV_VER_SHIFT 8 38 38 #define CHIP_REV_ECO_MASK 0xf 39 39 40 - #define CPLL_SW_CONFIG_SHIFT 31 41 - #define CPLL_SW_CONFIG_MASK 0x1 42 - #define CPLL_CPU_CLK_SHIFT 24 43 - #define CPLL_CPU_CLK_MASK 0x1 44 - #define CPLL_MULT_RATIO_SHIFT 16 45 - #define CPLL_MULT_RATIO 0x7 46 - #define CPLL_DIV_RATIO_SHIFT 10 47 - #define CPLL_DIV_RATIO 0x3 40 + #define CLKCFG0_PERI_CLK_SEL BIT(4) 41 + 42 + #define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 43 + #define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf 44 + #define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ 45 + #define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ 46 + #define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ 47 + #define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ 48 + #define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ 49 + #define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ 50 + #define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ 51 + #define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ 52 + #define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ 53 + #define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 54 + #define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f 55 + #define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 56 + #define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f 57 + 58 + #define CPLL_CFG0_SW_CFG BIT(31) 59 + #define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 60 + #define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 61 + #define CPLL_CFG0_LC_CURFCK BIT(15) 62 + #define CPLL_CFG0_BYPASS_REF_CLK BIT(14) 63 + #define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 64 + #define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 65 + 66 + #define CPLL_CFG1_CPU_AUX1 BIT(25) 67 + #define CPLL_CFG1_CPU_AUX0 BIT(24) 48 68 49 69 #define SYSCFG0_DRAM_TYPE_MASK 0x3 50 70 #define SYSCFG0_DRAM_TYPE_SHIFT 4
+174 -24
arch/mips/ralink/mt7620.c
··· 23 23 /* does the board have sdram or ddram */ 24 24 static int dram_type; 25 25 26 - /* the pll dividers */ 27 - static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 }; 28 - 29 26 static struct ralink_pinmux_grp mode_mux[] = { 30 27 { 31 28 .name = "i2c", ··· 137 140 .uart_mask = MT7620_GPIO_MODE_UART0_MASK, 138 141 }; 139 142 143 + static __init u32 144 + mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) 145 + { 146 + u64 t; 147 + 148 + t = ref_rate; 149 + t *= mul; 150 + do_div(t, div); 151 + 152 + return t; 153 + } 154 + 155 + #define MHZ(x) ((x) * 1000 * 1000) 156 + 157 + static __init unsigned long 158 + mt7620_get_xtal_rate(void) 159 + { 160 + u32 reg; 161 + 162 + reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); 163 + if (reg & SYSCFG0_XTAL_FREQ_SEL) 164 + return MHZ(40); 165 + 166 + return MHZ(20); 167 + } 168 + 169 + static __init unsigned long 170 + mt7620_get_periph_rate(unsigned long xtal_rate) 171 + { 172 + u32 reg; 173 + 174 + reg = rt_sysc_r32(SYSC_REG_CLKCFG0); 175 + if (reg & CLKCFG0_PERI_CLK_SEL) 176 + return xtal_rate; 177 + 178 + return MHZ(40); 179 + } 180 + 181 + static const u32 mt7620_clk_divider[] __initconst = { 2, 3, 4, 8 }; 182 + 183 + static __init unsigned long 184 + mt7620_get_cpu_pll_rate(unsigned long xtal_rate) 185 + { 186 + u32 reg; 187 + u32 mul; 188 + u32 div; 189 + 190 + reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); 191 + if (reg & CPLL_CFG0_BYPASS_REF_CLK) 192 + return xtal_rate; 193 + 194 + if ((reg & CPLL_CFG0_SW_CFG) == 0) 195 + return MHZ(600); 196 + 197 + mul = (reg >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & 198 + CPLL_CFG0_PLL_MULT_RATIO_MASK; 199 + mul += 24; 200 + if (reg & CPLL_CFG0_LC_CURFCK) 201 + mul *= 2; 202 + 203 + div = (reg >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & 204 + CPLL_CFG0_PLL_DIV_RATIO_MASK; 205 + 206 + WARN_ON(div >= ARRAY_SIZE(mt7620_clk_divider)); 207 + 208 + return mt7620_calc_rate(xtal_rate, mul, mt7620_clk_divider[div]); 209 + } 210 + 211 + static __init unsigned long 212 + mt7620_get_pll_rate(unsigned long xtal_rate, unsigned long cpu_pll_rate) 213 + { 214 + u32 reg; 215 + 216 + reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); 217 + if (reg & CPLL_CFG1_CPU_AUX1) 218 + return xtal_rate; 219 + 220 + if (reg & CPLL_CFG1_CPU_AUX0) 221 + return MHZ(480); 222 + 223 + return cpu_pll_rate; 224 + } 225 + 226 + static __init unsigned long 227 + mt7620_get_cpu_rate(unsigned long pll_rate) 228 + { 229 + u32 reg; 230 + u32 mul; 231 + u32 div; 232 + 233 + reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); 234 + 235 + mul = reg & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; 236 + div = (reg >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & 237 + CPU_SYS_CLKCFG_CPU_FDIV_MASK; 238 + 239 + return mt7620_calc_rate(pll_rate, mul, div); 240 + } 241 + 242 + static const u32 mt7620_ocp_dividers[16] __initconst = { 243 + [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, 244 + [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, 245 + [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, 246 + [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, 247 + [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, 248 + }; 249 + 250 + static __init unsigned long 251 + mt7620_get_dram_rate(unsigned long pll_rate) 252 + { 253 + if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) 254 + return pll_rate / 4; 255 + 256 + return pll_rate / 3; 257 + } 258 + 259 + static __init unsigned long 260 + mt7620_get_sys_rate(unsigned long cpu_rate) 261 + { 262 + u32 reg; 263 + u32 ocp_ratio; 264 + u32 div; 265 + 266 + reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); 267 + 268 + ocp_ratio = (reg >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & 269 + CPU_SYS_CLKCFG_OCP_RATIO_MASK; 270 + 271 + if (WARN_ON(ocp_ratio >= ARRAY_SIZE(mt7620_ocp_dividers))) 272 + return cpu_rate; 273 + 274 + div = mt7620_ocp_dividers[ocp_ratio]; 275 + if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) 276 + return cpu_rate; 277 + 278 + return cpu_rate / div; 279 + } 280 + 140 281 void __init ralink_clk_init(void) 141 282 { 142 - unsigned long cpu_rate, sys_rate; 143 - u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); 144 - u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); 145 - u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK; 146 - u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK; 283 + unsigned long xtal_rate; 284 + unsigned long cpu_pll_rate; 285 + unsigned long pll_rate; 286 + unsigned long cpu_rate; 287 + unsigned long sys_rate; 288 + unsigned long dram_rate; 289 + unsigned long periph_rate; 147 290 148 - if (cpu_clk) { 149 - cpu_rate = 480000000; 150 - } else if (!swconfig) { 151 - cpu_rate = 600000000; 152 - } else { 153 - u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO; 154 - u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO; 291 + xtal_rate = mt7620_get_xtal_rate(); 155 292 156 - cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; 157 - } 293 + cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); 294 + pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); 158 295 159 - if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) 160 - sys_rate = cpu_rate / 4; 161 - else 162 - sys_rate = cpu_rate / 3; 296 + cpu_rate = mt7620_get_cpu_rate(pll_rate); 297 + dram_rate = mt7620_get_dram_rate(pll_rate); 298 + sys_rate = mt7620_get_sys_rate(cpu_rate); 299 + periph_rate = mt7620_get_periph_rate(xtal_rate); 300 + 301 + #define RFMT(label) label ":%lu.%03luMHz " 302 + #define RINT(x) ((x) / 1000000) 303 + #define RFRAC(x) (((x) / 1000) % 1000) 304 + 305 + pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), 306 + RINT(xtal_rate), RFRAC(xtal_rate), 307 + RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), 308 + RINT(pll_rate), RFRAC(pll_rate)); 309 + 310 + pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), 311 + RINT(cpu_rate), RFRAC(cpu_rate), 312 + RINT(dram_rate), RFRAC(dram_rate), 313 + RINT(sys_rate), RFRAC(sys_rate), 314 + RINT(periph_rate), RFRAC(periph_rate)); 315 + 316 + #undef RFRAC 317 + #undef RINT 318 + #undef RFMT 163 319 164 320 ralink_clk_add("cpu", cpu_rate); 165 - ralink_clk_add("10000100.timer", 40000000); 166 - ralink_clk_add("10000500.uart", 40000000); 167 - ralink_clk_add("10000c00.uartlite", 40000000); 321 + ralink_clk_add("10000100.timer", periph_rate); 322 + ralink_clk_add("10000500.uart", periph_rate); 323 + ralink_clk_add("10000c00.uartlite", periph_rate); 168 324 } 169 325 170 326 void __init ralink_of_remap(void)