--- zzzz-none-000/linux-4.4.271/arch/mips/ath79/clock.c 2021-06-03 06:22:09.000000000 +0000 +++ dakota-7530ac-750/linux-4.4.271/arch/mips/ath79/clock.c 2023-01-11 09:25:41.000000000 +0000 @@ -25,16 +25,33 @@ #include #include "common.h" +#if CONFIG_AVM_KERNEL +#include +#endif + #define AR71XX_BASE_FREQ 40000000 -#define AR724X_BASE_FREQ 5000000 +#define AR724X_BASE_FREQ 40000000 #define AR913X_BASE_FREQ 5000000 -static struct clk *clks[3]; +static struct clk *clks[4]; static struct clk_onecell_data clk_data = { .clks = clks, .clk_num = ARRAY_SIZE(clks), }; +enum _avm_clock_cache { + clock_cache_cpu, + clock_cache_peripheral, + clock_cache_ahb, + clock_cache_ddr, + clock_cache_ref, + clock_cache_wdt, + + clock_cache_num, +}; + +static unsigned long clock_cache[clock_cache_num]; + static struct clk *__init ath79_add_sys_clkdev( const char *id, unsigned long rate) { @@ -103,8 +120,8 @@ div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); freq = div * ref_rate; - div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); - freq *= div; + div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; + freq /= div; cpu_rate = freq; @@ -218,7 +235,7 @@ clk_add_alias("uart", NULL, "ref", NULL); } -static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, +static u32 __init ar9xxx_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, u32 frac, u32 out_div) { u64 t; @@ -281,7 +298,7 @@ frac = 1 << 6; } - cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, + cpu_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, nfrac, frac, out_div); pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); @@ -308,7 +325,7 @@ frac = 1 << 10; } - ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, + ddr_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, nfrac, frac, out_div); clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); @@ -354,13 +371,98 @@ iounmap(dpll_base); } +static void __init qca953x_clocks_init(void) +{ + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; + u32 cpu_pll, ddr_pll; + u32 bootstrap; + + bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); + if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40) + ref_rate = 40 * 1000 * 1000; + else + ref_rate = 25 * 1000 * 1000; + + pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG); + out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + QCA953X_PLL_CPU_CONFIG_REFDIV_MASK; + nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) & + QCA953X_PLL_CPU_CONFIG_NINT_MASK; + nfrac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + QCA953X_PLL_CPU_CONFIG_NFRAC_MASK; + frac = 1 << 6; + + cpu_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, + nfrac, frac, out_div); + + pll = ath79_pll_rr(QCA953X_PLL_DDR_CONFIG_REG); + out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + QCA953X_PLL_DDR_CONFIG_REFDIV_MASK; + nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) & + QCA953X_PLL_DDR_CONFIG_NINT_MASK; + nfrac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + QCA953X_PLL_DDR_CONFIG_NFRAC_MASK; + frac = 1 << 10; + + ddr_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, + nfrac, frac, out_div); + + clk_ctrl = ath79_pll_rr(QCA953X_PLL_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + cpu_rate = ref_rate; + else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) + cpu_rate = cpu_pll / (postdiv + 1); + else + cpu_rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ddr_rate = ref_rate; + else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) + ddr_rate = ddr_pll / (postdiv + 1); + else + ddr_rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + ahb_rate = ref_rate; + else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + ahb_rate = ddr_pll / (postdiv + 1); + else + ahb_rate = cpu_pll / (postdiv + 1); + + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[3] = ath79_add_sys_clkdev("ref", ref_rate); + + clk_add_alias("wdt", NULL, "ref", NULL); + clk_add_alias("uart", NULL, "ref", NULL); +} + static void __init qca955x_clocks_init(void) { unsigned long ref_rate; unsigned long cpu_rate; unsigned long ddr_rate; unsigned long ahb_rate; - u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; u32 cpu_pll, ddr_pll; u32 bootstrap; @@ -377,12 +479,12 @@ QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & QCA955X_PLL_CPU_CONFIG_NINT_MASK; - frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + nfrac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; + frac = 1 << 6; - cpu_pll = nint * ref_rate / ref_div; - cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); - cpu_pll /= (1 << out_div); + cpu_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, + nfrac, frac, out_div); pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & @@ -391,12 +493,12 @@ QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & QCA955X_PLL_DDR_CONFIG_NINT_MASK; - frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + nfrac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; + frac = 1 << 10; - ddr_pll = nint * ref_rate / ref_div; - ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); - ddr_pll /= (1 << out_div); + ddr_pll = ar9xxx_get_pll_freq(ref_rate, ref_div, nint, + nfrac, frac, out_div); clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); @@ -430,15 +532,202 @@ else ahb_rate = cpu_pll / (postdiv + 1); - ath79_add_sys_clkdev("ref", ref_rate); clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[3] = ath79_add_sys_clkdev("ref", ref_rate); clk_add_alias("wdt", NULL, "ref", NULL); clk_add_alias("uart", NULL, "ref", NULL); } +static void __init qca956x_clocks_init(void) +{ + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; + u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv; + u32 cpu_pll, ddr_pll; + u32 bootstrap; + + bootstrap = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP); + if (bootstrap & QCA956X_BOOTSTRAP_REF_CLK_40) + ref_rate = 40 * 1000 * 1000; + else + ref_rate = 25 * 1000 * 1000; + + pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG_REG); + out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + QCA956X_PLL_CPU_CONFIG_REFDIV_MASK; + + pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG1_REG); + nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NINT_MASK; + hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK; + + cpu_pll = nint * ref_rate / ref_div; + cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + cpu_pll += (hfrac >> 13) * ref_rate / ref_div; + cpu_pll /= (1 << out_div); + + pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG_REG); + out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + QCA956X_PLL_DDR_CONFIG_REFDIV_MASK; + pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG1_REG); + nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NINT_MASK; + hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK; + + ddr_pll = nint * ref_rate / ref_div; + ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + ddr_pll += (hfrac >> 13) * ref_rate / ref_div; + ddr_pll /= (1 << out_div); + + clk_ctrl = ath79_pll_rr(QCA956X_PLL_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + cpu_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL) + cpu_rate = ddr_pll / (postdiv + 1); + else + cpu_rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ddr_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL) + ddr_rate = cpu_pll / (postdiv + 1); + else + ddr_rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + ahb_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + ahb_rate = ddr_pll / (postdiv + 1); + else + ahb_rate = cpu_pll / (postdiv + 1); + + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[3] = ath79_add_sys_clkdev("ref", ref_rate); + + clk_add_alias("wdt", NULL, "ref", NULL); + clk_add_alias("uart", NULL, "ref", NULL); +} + +static void __init qcn550x_clocks_init(void) +{ + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; + u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv; + u32 cpu_pll, ddr_pll; + u32 bootstrap; + + bootstrap = ath79_reset_rr(QCN550X_RESET_REG_BOOTSTRAP); + if (bootstrap & QCN550X_BOOTSTRAP_REF_CLK_40) + ref_rate = 40 * 1000 * 1000; + else + ref_rate = 25 * 1000 * 1000; + + pll = ath79_pll_rr(QCN550X_PLL_CPU_CONFIG_REG); + out_div = (pll >> QCN550X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + QCN550X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCN550X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + QCN550X_PLL_CPU_CONFIG_REFDIV_MASK; + + pll = ath79_pll_rr(QCN550X_PLL_CPU_CONFIG1_REG); + nint = (pll >> QCN550X_PLL_CPU_CONFIG1_NINT_SHIFT) & + QCN550X_PLL_CPU_CONFIG1_NINT_MASK; + hfrac = (pll >> QCN550X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) & + QCN550X_PLL_CPU_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCN550X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) & + QCN550X_PLL_CPU_CONFIG1_NFRAC_L_MASK; + + cpu_pll = nint * ref_rate / ref_div; + cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + cpu_pll += (hfrac >> 13) * ref_rate / ref_div; + cpu_pll /= (1 << out_div); + + pll = ath79_pll_rr(QCN550X_PLL_DDR_CONFIG_REG); + out_div = (pll >> QCN550X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + QCN550X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCN550X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + QCN550X_PLL_DDR_CONFIG_REFDIV_MASK; + pll = ath79_pll_rr(QCN550X_PLL_DDR_CONFIG1_REG); + nint = (pll >> QCN550X_PLL_DDR_CONFIG1_NINT_SHIFT) & + QCN550X_PLL_DDR_CONFIG1_NINT_MASK; + hfrac = (pll >> QCN550X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) & + QCN550X_PLL_DDR_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCN550X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) & + QCN550X_PLL_DDR_CONFIG1_NFRAC_L_MASK; + + ddr_pll = nint * ref_rate / ref_div; + ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + ddr_pll += (hfrac >> 13) * ref_rate / ref_div; + ddr_pll /= (1 << out_div); + + clk_ctrl = ath79_pll_rr(QCN550X_PLL_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> QCN550X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + QCN550X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & QCN550X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + cpu_rate = ref_rate; + else if (clk_ctrl & QCN550X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL) + cpu_rate = ddr_pll / (postdiv + 1); + else + cpu_rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCN550X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + QCN550X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & QCN550X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ddr_rate = ref_rate; + else if (clk_ctrl & QCN550X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL) + ddr_rate = cpu_pll / (postdiv + 1); + else + ddr_rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCN550X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + QCN550X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & QCN550X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + ahb_rate = ref_rate; + else if (clk_ctrl & QCN550X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + ahb_rate = ddr_pll / (postdiv + 1); + else + ahb_rate = cpu_pll / (postdiv + 1); + + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); + clks[3] = ath79_add_sys_clkdev("ref", ref_rate); + + clk_add_alias("wdt", NULL, "ref", NULL); + clk_add_alias("uart", NULL, "ref", NULL); +} void __init ath79_clocks_init(void) { if (soc_is_ar71xx()) @@ -451,16 +740,28 @@ ar933x_clocks_init(); else if (soc_is_ar934x()) ar934x_clocks_init(); + else if (soc_is_qca953x()) + qca953x_clocks_init(); else if (soc_is_qca955x()) qca955x_clocks_init(); + else if (soc_is_qca956x() || soc_is_tp9343()) + qca956x_clocks_init(); + else if (soc_is_qcn550x()) + qcn550x_clocks_init(); else BUG(); of_clk_init(NULL); + + clock_cache[clock_cache_cpu] = ath79_get_sys_clk_rate("cpu"); + clock_cache[clock_cache_peripheral] = ath79_get_sys_clk_rate("uart"); + clock_cache[clock_cache_ahb] = ath79_get_sys_clk_rate("ahb"); + clock_cache[clock_cache_ddr] = ath79_get_sys_clk_rate("ddr"); + clock_cache[clock_cache_ref] = ath79_get_sys_clk_rate("ref"); + clock_cache[clock_cache_wdt] = ath79_get_sys_clk_rate("wdt"); } -unsigned long __init -ath79_get_sys_clk_rate(const char *id) +unsigned long ath79_get_sys_clk_rate(const char *id) { struct clk *clk; unsigned long rate; @@ -475,6 +776,30 @@ return rate; } +#ifdef CONFIG_AVM_KERNEL +/* === ath79_get_clocks not implemented in qsdk 5 but needed for some avm features === */ +unsigned int ath79_get_clock(enum _avm_clock_id id) { + switch (id) { + case avm_clock_id_cpu: + return clock_cache[clock_cache_cpu]; + case avm_clock_id_peripheral: + return clock_cache[clock_cache_peripheral]; + case avm_clock_id_ahb: + return clock_cache[clock_cache_ahb]; + case avm_clock_id_ddr: + return clock_cache[clock_cache_ddr]; + case avm_clock_id_ref: + return clock_cache[clock_cache_ref]; + case avm_clock_id_wdt: + return clock_cache[clock_cache_wdt]; + + default: + return 0; + } +} +EXPORT_SYMBOL(ath79_get_clock); +#endif + #ifdef CONFIG_OF static void __init ath79_clocks_init_dt(struct device_node *np) {