MIPS: ath79: Fix CPU/DDR frequency calculation for SRIF PLLs

Besides the CPU and DDR PLLs, the CPU and DDR frequencies
can be derived from other PLLs in the SRIF block on the
AR934x SoCs. The current code does not checks if the SRIF
PLLs are used and this can lead to incorrectly calculated
CPU/DDR frequencies.

Fix it by calculating the frequencies from SRIF PLLs if
those are used on a given board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: <stable@vger.kernel.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/4324/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Gabor Juhos and committed by
Ralf Baechle
97541ccf 65fc7f99

+101 -25
+78 -25
arch/mips/ath79/clock.c
··· 17 #include <linux/err.h> 18 #include <linux/clk.h> 19 20 #include <asm/mach-ath79/ath79.h> 21 #include <asm/mach-ath79/ar71xx_regs.h> 22 #include "common.h" ··· 168 ath79_uart_clk.rate = ath79_ref_clk.rate; 169 } 170 171 static void __init ar934x_clocks_init(void) 172 { 173 - u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 174 u32 cpu_pll, ddr_pll; 175 u32 bootstrap; 176 177 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 178 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) ··· 203 else 204 ath79_ref_clk.rate = 25 * 1000 * 1000; 205 206 - pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 207 - out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 208 - AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 209 - ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 210 - AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 211 - nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 212 - AR934X_PLL_CPU_CONFIG_NINT_MASK; 213 - frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 214 - AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 215 216 - cpu_pll = nint * ath79_ref_clk.rate / ref_div; 217 - cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); 218 - cpu_pll /= (1 << out_div); 219 220 - pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 221 - out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 222 - AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 223 - ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 224 - AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 225 - nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 226 - AR934X_PLL_DDR_CONFIG_NINT_MASK; 227 - frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 228 - AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 229 230 - ddr_pll = nint * ath79_ref_clk.rate / ref_div; 231 - ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); 232 - ddr_pll /= (1 << out_div); 233 234 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 235 ··· 291 292 ath79_wdt_clk.rate = ath79_ref_clk.rate; 293 ath79_uart_clk.rate = ath79_ref_clk.rate; 294 } 295 296 void __init ath79_clocks_init(void)
··· 17 #include <linux/err.h> 18 #include <linux/clk.h> 19 20 + #include <asm/div64.h> 21 + 22 #include <asm/mach-ath79/ath79.h> 23 #include <asm/mach-ath79/ar71xx_regs.h> 24 #include "common.h" ··· 166 ath79_uart_clk.rate = ath79_ref_clk.rate; 167 } 168 169 + static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 170 + u32 frac, u32 out_div) 171 + { 172 + u64 t; 173 + u32 ret; 174 + 175 + t = ath79_ref_clk.rate; 176 + t *= nint; 177 + do_div(t, ref_div); 178 + ret = t; 179 + 180 + t = ath79_ref_clk.rate; 181 + t *= nfrac; 182 + do_div(t, ref_div * frac); 183 + ret += t; 184 + 185 + ret /= (1 << out_div); 186 + return ret; 187 + } 188 + 189 static void __init ar934x_clocks_init(void) 190 { 191 + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 192 u32 cpu_pll, ddr_pll; 193 u32 bootstrap; 194 + void __iomem *dpll_base; 195 + 196 + dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 197 198 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 199 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) ··· 178 else 179 ath79_ref_clk.rate = 25 * 1000 * 1000; 180 181 + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 182 + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 183 + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 184 + AR934X_SRIF_DPLL2_OUTDIV_MASK; 185 + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 186 + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 187 + AR934X_SRIF_DPLL1_NINT_MASK; 188 + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 189 + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 190 + AR934X_SRIF_DPLL1_REFDIV_MASK; 191 + frac = 1 << 18; 192 + } else { 193 + pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 194 + out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 195 + AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 196 + ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 197 + AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 198 + nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 199 + AR934X_PLL_CPU_CONFIG_NINT_MASK; 200 + nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 201 + AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 202 + frac = 1 << 6; 203 + } 204 205 + cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, 206 + nfrac, frac, out_div); 207 208 + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 209 + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 210 + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 211 + AR934X_SRIF_DPLL2_OUTDIV_MASK; 212 + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 213 + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 214 + AR934X_SRIF_DPLL1_NINT_MASK; 215 + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 216 + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 217 + AR934X_SRIF_DPLL1_REFDIV_MASK; 218 + frac = 1 << 18; 219 + } else { 220 + pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 221 + out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 222 + AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 223 + ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 224 + AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 225 + nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 226 + AR934X_PLL_DDR_CONFIG_NINT_MASK; 227 + nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 228 + AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 229 + frac = 1 << 10; 230 + } 231 232 + ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, 233 + nfrac, frac, out_div); 234 235 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 236 ··· 240 241 ath79_wdt_clk.rate = ath79_ref_clk.rate; 242 ath79_uart_clk.rate = ath79_ref_clk.rate; 243 + 244 + iounmap(dpll_base); 245 } 246 247 void __init ath79_clocks_init(void)
+23
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
··· 65 #define AR934X_WMAC_SIZE 0x20000 66 #define AR934X_EHCI_BASE 0x1b000000 67 #define AR934X_EHCI_SIZE 0x200 68 69 /* 70 * DDR_CTRL block ··· 407 #define AR913X_GPIO_COUNT 22 408 #define AR933X_GPIO_COUNT 30 409 #define AR934X_GPIO_COUNT 23 410 411 #endif /* __ASM_MACH_AR71XX_REGS_H */
··· 65 #define AR934X_WMAC_SIZE 0x20000 66 #define AR934X_EHCI_BASE 0x1b000000 67 #define AR934X_EHCI_SIZE 0x200 68 + #define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) 69 + #define AR934X_SRIF_SIZE 0x1000 70 71 /* 72 * DDR_CTRL block ··· 405 #define AR913X_GPIO_COUNT 22 406 #define AR933X_GPIO_COUNT 30 407 #define AR934X_GPIO_COUNT 23 408 + 409 + /* 410 + * SRIF block 411 + */ 412 + #define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 413 + #define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 414 + #define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 415 + 416 + #define AR934X_SRIF_DDR_DPLL1_REG 0x240 417 + #define AR934X_SRIF_DDR_DPLL2_REG 0x244 418 + #define AR934X_SRIF_DDR_DPLL3_REG 0x248 419 + 420 + #define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 421 + #define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f 422 + #define AR934X_SRIF_DPLL1_NINT_SHIFT 18 423 + #define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff 424 + #define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff 425 + 426 + #define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) 427 + #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 428 + #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 429 430 #endif /* __ASM_MACH_AR71XX_REGS_H */