diff options
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r-- | arch/mips/ath79/clock.c | 109 |
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 | ||
171 | static 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 | |||
169 | static void __init ar934x_clocks_init(void) | 191 | static 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 | ||
245 | void __init ath79_clocks_init(void) | 298 | void __init ath79_clocks_init(void) |