aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath79/clock.c
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/ath79/clock.c
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/ath79/clock.c')
-rw-r--r--arch/mips/ath79/clock.c109
1 files changed, 81 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)