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 17 #include <linux/err.h> 18 18 #include <linux/clk.h> 19 19 20 + #include <asm/div64.h> 21 + 20 22 #include <asm/mach-ath79/ath79.h> 21 23 #include <asm/mach-ath79/ar71xx_regs.h> 22 24 #include "common.h" ··· 168 166 ath79_uart_clk.rate = ath79_ref_clk.rate; 169 167 } 170 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 + 171 189 static void __init ar934x_clocks_init(void) 172 190 { 173 - u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 191 + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 174 192 u32 cpu_pll, ddr_pll; 175 193 u32 bootstrap; 194 + void __iomem *dpll_base; 195 + 196 + dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 176 197 177 198 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 178 199 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) ··· 203 178 else 204 179 ath79_ref_clk.rate = 25 * 1000 * 1000; 205 180 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; 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 + } 215 204 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); 205 + cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, 206 + nfrac, frac, out_div); 219 207 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; 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 + } 229 231 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); 232 + ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, 233 + nfrac, frac, out_div); 233 234 234 235 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 235 236 ··· 291 240 292 241 ath79_wdt_clk.rate = ath79_ref_clk.rate; 293 242 ath79_uart_clk.rate = ath79_ref_clk.rate; 243 + 244 + iounmap(dpll_base); 294 245 } 295 246 296 247 void __init ath79_clocks_init(void)
+23
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
··· 65 65 #define AR934X_WMAC_SIZE 0x20000 66 66 #define AR934X_EHCI_BASE 0x1b000000 67 67 #define AR934X_EHCI_SIZE 0x200 68 + #define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) 69 + #define AR934X_SRIF_SIZE 0x1000 68 70 69 71 /* 70 72 * DDR_CTRL block ··· 407 405 #define AR913X_GPIO_COUNT 22 408 406 #define AR933X_GPIO_COUNT 30 409 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 410 429 411 430 #endif /* __ASM_MACH_AR71XX_REGS_H */