diff options
Diffstat (limited to 'arch/mips/ath79/clock.c')
-rw-r--r-- | arch/mips/ath79/clock.c | 96 |
1 files changed, 71 insertions, 25 deletions
diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index c3a94ead06ab..79fb8b44ba09 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -18,6 +18,8 @@ #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <dt-bindings/clock/ath79-clk.h> #include <asm/div64.h> @@ -25,6 +27,7 @@ #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/ar71xx_regs.h> #include "common.h" +#include "machtypes.h" #define AR71XX_BASE_FREQ 40000000 #define AR724X_BASE_FREQ 40000000 @@ -87,37 +90,48 @@ static void __init ar71xx_clocks_init(void) clk_add_alias("uart", NULL, "ahb", NULL); } -static void __init ar724x_clocks_init(void) +static struct clk * __init ath79_reg_ffclk(const char *name, + const char *parent_name, unsigned int mult, unsigned int div) { - unsigned long ref_rate; - unsigned long cpu_rate; - unsigned long ddr_rate; - unsigned long ahb_rate; - u32 pll; - u32 freq; - u32 div; + struct clk *clk; - ref_rate = AR724X_BASE_FREQ; - pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); + clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); + if (!clk) + panic("failed to allocate %s clock structure", name); - div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); - freq = div * ref_rate; + return clk; +} + +static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base) +{ + u32 pll; + u32 mult, div, ddr_div, ahb_div; + pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG); + + mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; - freq /= div; - cpu_rate = freq; + ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; + ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; - div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; - ddr_rate = freq / div; + clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div); + clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div); + clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div); +} - div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; - ahb_rate = cpu_rate / div; +static void __init ar724x_clocks_init(void) +{ + struct clk *ref_clk; - ath79_add_sys_clkdev("ref", ref_rate); - clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); - clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); - clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); + ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ); + + ar724x_clk_init(ref_clk, ath79_pll_base); + + /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ + clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); + clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); + clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -420,8 +434,6 @@ void __init ath79_clocks_init(void) qca955x_clocks_init(); else BUG(); - - of_clk_init(NULL); } unsigned long __init @@ -448,8 +460,42 @@ static void __init ath79_clocks_init_dt(struct device_node *np) CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); -CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); + +static void __init ath79_clocks_init_dt_ng(struct device_node *np) +{ + struct clk *ref_clk; + void __iomem *pll_base; + const char *dnfn = of_node_full_name(np); + + ref_clk = of_clk_get(np, 0); + if (IS_ERR(ref_clk)) { + pr_err("%s: of_clk_get failed\n", dnfn); + goto err; + } + + pll_base = of_iomap(np, 0); + if (!pll_base) { + pr_err("%s: can't map pll registers\n", dnfn); + goto err_clk; + } + + ar724x_clk_init(ref_clk, pll_base); + + if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { + pr_err("%s: could not register clk provider\n", dnfn); + goto err_clk; + } + + return; + +err_clk: + clk_put(ref_clk); + +err: + return; +} +CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng); #endif |