1 /* 2 * Atheros AR71XX/AR724X/AR913X common routines 3 * 4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 5 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 6 * 7 * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License version 2 as published 11 * by the Free Software Foundation. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/init.h> 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" 25 26 #define AR71XX_BASE_FREQ 40000000 27 #define AR724X_BASE_FREQ 5000000 28 #define AR913X_BASE_FREQ 5000000 29 30 struct clk { 31 unsigned long rate; 32 }; 33 34 static struct clk ath79_ref_clk; 35 static struct clk ath79_cpu_clk; 36 static struct clk ath79_ddr_clk; 37 static struct clk ath79_ahb_clk; 38 static struct clk ath79_wdt_clk; 39 static struct clk ath79_uart_clk; 40 41 static void __init ar71xx_clocks_init(void) 42 { 43 u32 pll; 44 u32 freq; 45 u32 div; 46 47 ath79_ref_clk.rate = AR71XX_BASE_FREQ; 48 49 pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); 50 51 div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; 52 freq = div * ath79_ref_clk.rate; 53 54 div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 55 ath79_cpu_clk.rate = freq / div; 56 57 div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 58 ath79_ddr_clk.rate = freq / div; 59 60 div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 61 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 62 63 ath79_wdt_clk.rate = ath79_ahb_clk.rate; 64 ath79_uart_clk.rate = ath79_ahb_clk.rate; 65 } 66 67 static void __init ar724x_clocks_init(void) 68 { 69 u32 pll; 70 u32 freq; 71 u32 div; 72 73 ath79_ref_clk.rate = AR724X_BASE_FREQ; 74 pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); 75 76 div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); 77 freq = div * ath79_ref_clk.rate; 78 79 div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); 80 freq *= div; 81 82 ath79_cpu_clk.rate = freq; 83 84 div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 85 ath79_ddr_clk.rate = freq / div; 86 87 div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 88 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 89 90 ath79_wdt_clk.rate = ath79_ahb_clk.rate; 91 ath79_uart_clk.rate = ath79_ahb_clk.rate; 92 } 93 94 static void __init ar913x_clocks_init(void) 95 { 96 u32 pll; 97 u32 freq; 98 u32 div; 99 100 ath79_ref_clk.rate = AR913X_BASE_FREQ; 101 pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); 102 103 div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK); 104 freq = div * ath79_ref_clk.rate; 105 106 ath79_cpu_clk.rate = freq; 107 108 div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1; 109 ath79_ddr_clk.rate = freq / div; 110 111 div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2; 112 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 113 114 ath79_wdt_clk.rate = ath79_ahb_clk.rate; 115 ath79_uart_clk.rate = ath79_ahb_clk.rate; 116 } 117 118 static void __init ar933x_clocks_init(void) 119 { 120 u32 clock_ctrl; 121 u32 cpu_config; 122 u32 freq; 123 u32 t; 124 125 t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 126 if (t & AR933X_BOOTSTRAP_REF_CLK_40) 127 ath79_ref_clk.rate = (40 * 1000 * 1000); 128 else 129 ath79_ref_clk.rate = (25 * 1000 * 1000); 130 131 clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); 132 if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 133 ath79_cpu_clk.rate = ath79_ref_clk.rate; 134 ath79_ahb_clk.rate = ath79_ref_clk.rate; 135 ath79_ddr_clk.rate = ath79_ref_clk.rate; 136 } else { 137 cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); 138 139 t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 140 AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 141 freq = ath79_ref_clk.rate / t; 142 143 t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 144 AR933X_PLL_CPU_CONFIG_NINT_MASK; 145 freq *= t; 146 147 t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 148 AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 149 if (t == 0) 150 t = 1; 151 152 freq >>= t; 153 154 t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 155 AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 156 ath79_cpu_clk.rate = freq / t; 157 158 t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 159 AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 160 ath79_ddr_clk.rate = freq / t; 161 162 t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 163 AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 164 ath79_ahb_clk.rate = freq / t; 165 } 166 167 ath79_wdt_clk.rate = ath79_ref_clk.rate; 168 ath79_uart_clk.rate = ath79_ref_clk.rate; 169 } 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 191 static void __init ar934x_clocks_init(void) 192 { 193 u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 194 u32 cpu_pll, ddr_pll; 195 u32 bootstrap; 196 void __iomem *dpll_base; 197 198 dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 199 200 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 201 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 202 ath79_ref_clk.rate = 40 * 1000 * 1000; 203 else 204 ath79_ref_clk.rate = 25 * 1000 * 1000; 205 206 pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 207 if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 208 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 209 AR934X_SRIF_DPLL2_OUTDIV_MASK; 210 pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 211 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 212 AR934X_SRIF_DPLL1_NINT_MASK; 213 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 214 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 215 AR934X_SRIF_DPLL1_REFDIV_MASK; 216 frac = 1 << 18; 217 } else { 218 pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 219 out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 220 AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 221 ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 222 AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 223 nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 224 AR934X_PLL_CPU_CONFIG_NINT_MASK; 225 nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 226 AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 227 frac = 1 << 6; 228 } 229 230 cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, 231 nfrac, frac, 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); 259 260 clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 261 262 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 263 AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 264 265 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 266 ath79_cpu_clk.rate = ath79_ref_clk.rate; 267 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 268 ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); 269 else 270 ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); 271 272 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 273 AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 274 275 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 276 ath79_ddr_clk.rate = ath79_ref_clk.rate; 277 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 278 ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); 279 else 280 ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); 281 282 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 283 AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 284 285 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 286 ath79_ahb_clk.rate = ath79_ref_clk.rate; 287 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 288 ath79_ahb_clk.rate = ddr_pll / (postdiv + 1); 289 else 290 ath79_ahb_clk.rate = cpu_pll / (postdiv + 1); 291 292 ath79_wdt_clk.rate = ath79_ref_clk.rate; 293 ath79_uart_clk.rate = ath79_ref_clk.rate; 294 295 iounmap(dpll_base); 296 } 297 298 void __init ath79_clocks_init(void) 299 { 300 if (soc_is_ar71xx()) 301 ar71xx_clocks_init(); 302 else if (soc_is_ar724x()) 303 ar724x_clocks_init(); 304 else if (soc_is_ar913x()) 305 ar913x_clocks_init(); 306 else if (soc_is_ar933x()) 307 ar933x_clocks_init(); 308 else if (soc_is_ar934x()) 309 ar934x_clocks_init(); 310 else 311 BUG(); 312 313 pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, " 314 "Ref:%lu.%03luMHz", 315 ath79_cpu_clk.rate / 1000000, 316 (ath79_cpu_clk.rate / 1000) % 1000, 317 ath79_ddr_clk.rate / 1000000, 318 (ath79_ddr_clk.rate / 1000) % 1000, 319 ath79_ahb_clk.rate / 1000000, 320 (ath79_ahb_clk.rate / 1000) % 1000, 321 ath79_ref_clk.rate / 1000000, 322 (ath79_ref_clk.rate / 1000) % 1000); 323 } 324 325 /* 326 * Linux clock API 327 */ 328 struct clk *clk_get(struct device *dev, const char *id) 329 { 330 if (!strcmp(id, "ref")) 331 return &ath79_ref_clk; 332 333 if (!strcmp(id, "cpu")) 334 return &ath79_cpu_clk; 335 336 if (!strcmp(id, "ddr")) 337 return &ath79_ddr_clk; 338 339 if (!strcmp(id, "ahb")) 340 return &ath79_ahb_clk; 341 342 if (!strcmp(id, "wdt")) 343 return &ath79_wdt_clk; 344 345 if (!strcmp(id, "uart")) 346 return &ath79_uart_clk; 347 348 return ERR_PTR(-ENOENT); 349 } 350 EXPORT_SYMBOL(clk_get); 351 352 int clk_enable(struct clk *clk) 353 { 354 return 0; 355 } 356 EXPORT_SYMBOL(clk_enable); 357 358 void clk_disable(struct clk *clk) 359 { 360 } 361 EXPORT_SYMBOL(clk_disable); 362 363 unsigned long clk_get_rate(struct clk *clk) 364 { 365 return clk->rate; 366 } 367 EXPORT_SYMBOL(clk_get_rate); 368 369 void clk_put(struct clk *clk) 370 { 371 } 372 EXPORT_SYMBOL(clk_put); 373