aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-09-08 08:02:21 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-10-01 05:37:15 -0400
commit97541ccfb9db2bb9cd1dde6344d5834438d14bda (patch)
treefbdcb943e76ee180c6025a2f7f5645c101014f00 /arch/mips
parent65fc7f9957c52ad4fdf4ee5dfe3a75aa0a633d39 (diff)
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>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/ath79/clock.c109
-rw-r--r--arch/mips/include/asm/mach-ath79/ar71xx_regs.h23
2 files changed, 104 insertions, 28 deletions
diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c
index d2728573e9fc..579f452c0b45 100644
--- a/arch/mips/ath79/clock.c
+++ b/arch/mips/ath79/clock.c
@@ -17,6 +17,8 @@
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19 19
20#include <asm/div64.h>
21
20#include <asm/mach-ath79/ath79.h> 22#include <asm/mach-ath79/ath79.h>
21#include <asm/mach-ath79/ar71xx_regs.h> 23#include <asm/mach-ath79/ar71xx_regs.h>
22#include "common.h" 24#include "common.h"
@@ -166,11 +168,34 @@ static void __init ar933x_clocks_init(void)
166 ath79_uart_clk.rate = ath79_ref_clk.rate; 168 ath79_uart_clk.rate = ath79_ref_clk.rate;
167} 169}
168 170
171static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
172 u32 frac, u32 out_div)
173{
174 u64 t;
175 u32 ret;
176
177 t = ath79_ref_clk.rate;
178 t *= nint;
179 do_div(t, ref_div);
180 ret = t;
181
182 t = ath79_ref_clk.rate;
183 t *= nfrac;
184 do_div(t, ref_div * frac);
185 ret += t;
186
187 ret /= (1 << out_div);
188 return ret;
189}
190
169static void __init ar934x_clocks_init(void) 191static void __init ar934x_clocks_init(void)
170{ 192{
171 u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 193 u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
172 u32 cpu_pll, ddr_pll; 194 u32 cpu_pll, ddr_pll;
173 u32 bootstrap; 195 u32 bootstrap;
196 void __iomem *dpll_base;
197
198 dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE);
174 199
175 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 200 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
176 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 201 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
@@ -178,33 +203,59 @@ static void __init ar934x_clocks_init(void)
178 else 203 else
179 ath79_ref_clk.rate = 25 * 1000 * 1000; 204 ath79_ref_clk.rate = 25 * 1000 * 1000;
180 205
181 pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 206 pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
182 out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 207 if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
183 AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 208 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
184 ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 209 AR934X_SRIF_DPLL2_OUTDIV_MASK;
185 AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 210 pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG);
186 nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 211 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
187 AR934X_PLL_CPU_CONFIG_NINT_MASK; 212 AR934X_SRIF_DPLL1_NINT_MASK;
188 frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 213 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
189 AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 214 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
190 215 AR934X_SRIF_DPLL1_REFDIV_MASK;
191 cpu_pll = nint * ath79_ref_clk.rate / ref_div; 216 frac = 1 << 18;
192 cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); 217 } else {
193 cpu_pll /= (1 << out_div); 218 pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
194 219 out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
195 pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 220 AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
196 out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 221 ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
197 AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 222 AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
198 ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 223 nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
199 AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 224 AR934X_PLL_CPU_CONFIG_NINT_MASK;
200 nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 225 nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
201 AR934X_PLL_DDR_CONFIG_NINT_MASK; 226 AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
202 frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 227 frac = 1 << 6;
203 AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 228 }
204 229
205 ddr_pll = nint * ath79_ref_clk.rate / ref_div; 230 cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
206 ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); 231 nfrac, frac, out_div);
207 ddr_pll /= (1 << out_div); 232
233 pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG);
234 if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
235 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
236 AR934X_SRIF_DPLL2_OUTDIV_MASK;
237 pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG);
238 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
239 AR934X_SRIF_DPLL1_NINT_MASK;
240 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
241 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
242 AR934X_SRIF_DPLL1_REFDIV_MASK;
243 frac = 1 << 18;
244 } else {
245 pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
246 out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
247 AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
248 ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
249 AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
250 nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
251 AR934X_PLL_DDR_CONFIG_NINT_MASK;
252 nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
253 AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
254 frac = 1 << 10;
255 }
256
257 ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
258 nfrac, frac, out_div);
208 259
209 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 260 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
210 261
@@ -240,6 +291,8 @@ static void __init ar934x_clocks_init(void)
240 291
241 ath79_wdt_clk.rate = ath79_ref_clk.rate; 292 ath79_wdt_clk.rate = ath79_ref_clk.rate;
242 ath79_uart_clk.rate = ath79_ref_clk.rate; 293 ath79_uart_clk.rate = ath79_ref_clk.rate;
294
295 iounmap(dpll_base);
243} 296}
244 297
245void __init ath79_clocks_init(void) 298void __init ath79_clocks_init(void)
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 3ccae12cc7b3..a5e0f17ea77c 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -65,6 +65,8 @@
65#define AR934X_WMAC_SIZE 0x20000 65#define AR934X_WMAC_SIZE 0x20000
66#define AR934X_EHCI_BASE 0x1b000000 66#define AR934X_EHCI_BASE 0x1b000000
67#define AR934X_EHCI_SIZE 0x200 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 * DDR_CTRL block 72 * DDR_CTRL block
@@ -406,4 +408,25 @@
406#define AR933X_GPIO_COUNT 30 408#define AR933X_GPIO_COUNT 30
407#define AR934X_GPIO_COUNT 23 409#define AR934X_GPIO_COUNT 23
408 410
411/*
412 * SRIF block
413 */
414#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0
415#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4
416#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8
417
418#define AR934X_SRIF_DDR_DPLL1_REG 0x240
419#define AR934X_SRIF_DDR_DPLL2_REG 0x244
420#define AR934X_SRIF_DDR_DPLL3_REG 0x248
421
422#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27
423#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f
424#define AR934X_SRIF_DPLL1_NINT_SHIFT 18
425#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff
426#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff
427
428#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30)
429#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13
430#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7
431
409#endif /* __ASM_MACH_AR71XX_REGS_H */ 432#endif /* __ASM_MACH_AR71XX_REGS_H */