| 1 | From 3f735e202d5099a5b7c621443bea365b87b0e3bb Mon Sep 17 00:00:00 2001 |
| 2 | From: Gabor Juhos <juhosg@openwrt.org> |
| 3 | Date: Sat, 8 Sep 2012 12:12:50 +0200 |
| 4 | Subject: [PATCH] MIPS: ath79: fix CPU/DDR frequency calculation for SRIF PLLs |
| 5 | |
| 6 | Besides the CPU and DDR PLLs, the CPU and DDR frequencies |
| 7 | can be derived from other PLLs in the SRIF block on the |
| 8 | AR934x SoCs. The current code does not checks if the SRIF |
| 9 | PLLs are used and this can lead to incorrectly calculated |
| 10 | CPU/DDR frequencies. |
| 11 | |
| 12 | Fix it by calculating the frequencies from SRIF PLLs if |
| 13 | those are used on a given board. |
| 14 | |
| 15 | Cc: <stable@vger.kernel.org> |
| 16 | Signed-off-by: Gabor Juhos <juhosg@openwrt.org> |
| 17 | --- |
| 18 | This depends on the following patch: |
| 19 | 'MIPS: ath79: use correct fractional dividers for {CPU,DDR}_PLL on AR934x' |
| 20 | https://patchwork.linux-mips.org/patch/4305/ |
| 21 | |
| 22 | arch/mips/ath79/clock.c | 109 ++++++++++++++++++------ |
| 23 | arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 23 +++++ |
| 24 | 2 files changed, 104 insertions(+), 28 deletions(-) |
| 25 | |
| 26 | --- a/arch/mips/ath79/clock.c |
| 27 | +++ b/arch/mips/ath79/clock.c |
| 28 | @@ -17,6 +17,8 @@ |
| 29 | #include <linux/err.h> |
| 30 | #include <linux/clk.h> |
| 31 | |
| 32 | +#include <asm/div64.h> |
| 33 | + |
| 34 | #include <asm/mach-ath79/ath79.h> |
| 35 | #include <asm/mach-ath79/ar71xx_regs.h> |
| 36 | #include "common.h" |
| 37 | @@ -166,11 +168,34 @@ static void __init ar933x_clocks_init(vo |
| 38 | ath79_uart_clk.rate = ath79_ref_clk.rate; |
| 39 | } |
| 40 | |
| 41 | +static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, |
| 42 | + u32 frac, u32 out_div) |
| 43 | +{ |
| 44 | + u64 t; |
| 45 | + u32 ret; |
| 46 | + |
| 47 | + t = ath79_ref_clk.rate; |
| 48 | + t *= nint; |
| 49 | + do_div(t, ref_div); |
| 50 | + ret = t; |
| 51 | + |
| 52 | + t = ath79_ref_clk.rate; |
| 53 | + t *= nfrac; |
| 54 | + do_div(t, ref_div * frac); |
| 55 | + ret += t; |
| 56 | + |
| 57 | + ret /= (1 << out_div); |
| 58 | + return ret; |
| 59 | +} |
| 60 | + |
| 61 | static void __init ar934x_clocks_init(void) |
| 62 | { |
| 63 | - u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; |
| 64 | + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; |
| 65 | u32 cpu_pll, ddr_pll; |
| 66 | u32 bootstrap; |
| 67 | + void __iomem *dpll_base; |
| 68 | + |
| 69 | + dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); |
| 70 | |
| 71 | bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); |
| 72 | if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) |
| 73 | @@ -178,33 +203,59 @@ static void __init ar934x_clocks_init(vo |
| 74 | else |
| 75 | ath79_ref_clk.rate = 25 * 1000 * 1000; |
| 76 | |
| 77 | - pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); |
| 78 | - out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & |
| 79 | - AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; |
| 80 | - ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & |
| 81 | - AR934X_PLL_CPU_CONFIG_REFDIV_MASK; |
| 82 | - nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & |
| 83 | - AR934X_PLL_CPU_CONFIG_NINT_MASK; |
| 84 | - frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & |
| 85 | - AR934X_PLL_CPU_CONFIG_NFRAC_MASK; |
| 86 | - |
| 87 | - cpu_pll = nint * ath79_ref_clk.rate / ref_div; |
| 88 | - cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); |
| 89 | - cpu_pll /= (1 << out_div); |
| 90 | - |
| 91 | - pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); |
| 92 | - out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & |
| 93 | - AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; |
| 94 | - ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & |
| 95 | - AR934X_PLL_DDR_CONFIG_REFDIV_MASK; |
| 96 | - nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & |
| 97 | - AR934X_PLL_DDR_CONFIG_NINT_MASK; |
| 98 | - frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & |
| 99 | - AR934X_PLL_DDR_CONFIG_NFRAC_MASK; |
| 100 | - |
| 101 | - ddr_pll = nint * ath79_ref_clk.rate / ref_div; |
| 102 | - ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); |
| 103 | - ddr_pll /= (1 << out_div); |
| 104 | + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); |
| 105 | + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { |
| 106 | + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & |
| 107 | + AR934X_SRIF_DPLL2_OUTDIV_MASK; |
| 108 | + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); |
| 109 | + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & |
| 110 | + AR934X_SRIF_DPLL1_NINT_MASK; |
| 111 | + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; |
| 112 | + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & |
| 113 | + AR934X_SRIF_DPLL1_REFDIV_MASK; |
| 114 | + frac = 1 << 18; |
| 115 | + } else { |
| 116 | + pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); |
| 117 | + out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & |
| 118 | + AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; |
| 119 | + ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & |
| 120 | + AR934X_PLL_CPU_CONFIG_REFDIV_MASK; |
| 121 | + nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & |
| 122 | + AR934X_PLL_CPU_CONFIG_NINT_MASK; |
| 123 | + nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & |
| 124 | + AR934X_PLL_CPU_CONFIG_NFRAC_MASK; |
| 125 | + frac = 1 << 6; |
| 126 | + } |
| 127 | + |
| 128 | + cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, |
| 129 | + nfrac, frac, out_div); |
| 130 | + |
| 131 | + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); |
| 132 | + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { |
| 133 | + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & |
| 134 | + AR934X_SRIF_DPLL2_OUTDIV_MASK; |
| 135 | + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); |
| 136 | + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & |
| 137 | + AR934X_SRIF_DPLL1_NINT_MASK; |
| 138 | + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; |
| 139 | + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & |
| 140 | + AR934X_SRIF_DPLL1_REFDIV_MASK; |
| 141 | + frac = 1 << 18; |
| 142 | + } else { |
| 143 | + pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); |
| 144 | + out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & |
| 145 | + AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; |
| 146 | + ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & |
| 147 | + AR934X_PLL_DDR_CONFIG_REFDIV_MASK; |
| 148 | + nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & |
| 149 | + AR934X_PLL_DDR_CONFIG_NINT_MASK; |
| 150 | + nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & |
| 151 | + AR934X_PLL_DDR_CONFIG_NFRAC_MASK; |
| 152 | + frac = 1 << 10; |
| 153 | + } |
| 154 | + |
| 155 | + ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, |
| 156 | + nfrac, frac, out_div); |
| 157 | |
| 158 | clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); |
| 159 | |
| 160 | @@ -240,6 +291,8 @@ static void __init ar934x_clocks_init(vo |
| 161 | |
| 162 | ath79_wdt_clk.rate = ath79_ref_clk.rate; |
| 163 | ath79_uart_clk.rate = ath79_ref_clk.rate; |
| 164 | + |
| 165 | + iounmap(dpll_base); |
| 166 | } |
| 167 | |
| 168 | void __init ath79_clocks_init(void) |
| 169 | --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h |
| 170 | +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h |
| 171 | @@ -65,6 +65,8 @@ |
| 172 | #define AR934X_WMAC_SIZE 0x20000 |
| 173 | #define AR934X_EHCI_BASE 0x1b000000 |
| 174 | #define AR934X_EHCI_SIZE 0x200 |
| 175 | +#define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) |
| 176 | +#define AR934X_SRIF_SIZE 0x1000 |
| 177 | |
| 178 | /* |
| 179 | * DDR_CTRL block |
| 180 | @@ -405,4 +407,25 @@ |
| 181 | #define AR933X_GPIO_COUNT 30 |
| 182 | #define AR934X_GPIO_COUNT 23 |
| 183 | |
| 184 | +/* |
| 185 | + * SRIF block |
| 186 | + */ |
| 187 | +#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 |
| 188 | +#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 |
| 189 | +#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 |
| 190 | + |
| 191 | +#define AR934X_SRIF_DDR_DPLL1_REG 0x240 |
| 192 | +#define AR934X_SRIF_DDR_DPLL2_REG 0x244 |
| 193 | +#define AR934X_SRIF_DDR_DPLL3_REG 0x248 |
| 194 | + |
| 195 | +#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 |
| 196 | +#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f |
| 197 | +#define AR934X_SRIF_DPLL1_NINT_SHIFT 18 |
| 198 | +#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff |
| 199 | +#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff |
| 200 | + |
| 201 | +#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) |
| 202 | +#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 |
| 203 | +#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 |
| 204 | + |
| 205 | #endif /* __ASM_MACH_AR71XX_REGS_H */ |
| 206 | |