2 * Qualcomm/Atheros WiSoCs system clocks related functions
4 * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
7 * Linux/arch/mips/ath79/clock.c
9 * SPDX-License-Identifier: GPL-2.0
15 #include <asm/addrspace.h>
16 #include <soc/qca_soc_common.h>
19 * Calculates and returns PLL value
20 * TODO: check for overflow!
22 static u32 qca_get_pll(u32 ref_clk,
38 pll_mul = pll_mul * ((nint * nfracdiv) + nfrac);
39 pll_div = pll_div * nfracdiv;
41 pll_mul = pll_mul * nint;
44 pll_div = pll_div << outdiv;
46 return (u32)(pll_mul / pll_div);
50 * Get CPU, RAM, AHB and SPI clocks
51 * TODO: confirm nfracdiv values
53 void qca_sys_clocks(u32 *cpu_clk,
59 u32 qca_ahb_clk, qca_cpu_clk, qca_ddr_clk, qca_ref_clk, qca_spi_clk;
60 u32 nint, outdiv, refdiv;
64 #if (SOC_TYPE & QCA_AR933X_SOC)
70 if (qca_xtal_is_40mhz() == 1) {
71 qca_ref_clk = VAL_40MHz;
73 qca_ref_clk = VAL_25MHz;
76 #if (SOC_TYPE & QCA_AR933X_SOC)
78 * Main AR933x CPU PLL clock calculation:
80 * 1. If CPU PLL DITHER is disabled:
81 * VCO_OUT = (REF_CLK / REF_DIV) * (NINT + (NFRAC_MIN / 1024))
82 * CPU_PLL_OUT = VCO_OUT / (2^OUT_DIV)
84 * 2. If CPU PLL DITHER is enabled:
85 * VCO_OUT = (REF_CLK / REF_DIV) * (NINT + (NFRAC / 1024))
86 * CPU_PLL_OUT = VCO_OUT / (2^OUT_DIV)
88 * TODO: NFRAC does not exist in AR9331 datasheet,
89 * but exist in many other QC/A WiSOC datasheets,
90 * we should somehow (scope?) check and confirm it
93 /* Read CPU CLock Control Register (CLOCK_CONTROL) value */
94 reg_val = qca_soc_reg_read(QCA_PLL_CPU_CLK_CTRL_REG);
96 if (reg_val & QCA_PLL_CPU_CLK_CTRL_BYPASS_MASK) {
97 /* PLL is bypassed, so all clocks are == reference clock */
98 qca_cpu_clk = qca_ref_clk;
99 qca_ddr_clk = qca_ref_clk;
100 qca_ahb_clk = qca_ref_clk;
102 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_DITHER_REG);
104 if (reg_val & QCA_PLL_CPU_PLL_DITHER_DITHER_EN_MASK) {
105 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
106 nfrac = (reg_val & QCA_PLL_CPU_PLL_CFG_NFRAC_MASK)
107 >> QCA_PLL_CPU_PLL_CFG_NFRAC_SHIFT;
109 /* NFRAC = NFRAC_MIN if DITHER_EN is 0 */
110 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_DITHER_FRAC_REG);
111 nfrac = (reg_val & QCA_PLL_CPU_PLL_DITHER_FRAC_NFRAC_MIN_MASK)
112 >> QCA_PLL_CPU_PLL_DITHER_FRAC_NFRAC_MIN_SHIFT;
117 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
119 nint = (reg_val & QCA_PLL_CPU_PLL_CFG_NINT_MASK)
120 >> QCA_PLL_CPU_PLL_CFG_NINT_SHIFT;
122 refdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_REFDIV_MASK)
123 >> QCA_PLL_CPU_PLL_CFG_REFDIV_SHIFT;
125 outdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_OUTDIV_MASK)
126 >> QCA_PLL_CPU_PLL_CFG_OUTDIV_SHIFT;
128 /* TODO: need confirmation that OUTDIV == 0 is not supported for AR933x */
132 /* Final CPU PLL value */
133 cpu_pll = qca_get_pll(qca_ref_clk, refdiv,
134 nfrac, nfracdiv, nint, outdiv);
136 /* CPU, DDR and AHB clock dividers */
137 reg_val = qca_soc_reg_read(QCA_PLL_CPU_CLK_CTRL_REG);
139 temp = ((reg_val & QCA_PLL_CPU_CLK_CTRL_CPU_POST_DIV_MASK)
140 >> QCA_PLL_CPU_CLK_CTRL_CPU_POST_DIV_SHIFT) + 1;
141 qca_cpu_clk = cpu_pll / temp;
143 temp = ((reg_val & QCA_PLL_CPU_CLK_CTRL_DDR_POST_DIV_MASK)
144 >> QCA_PLL_CPU_CLK_CTRL_DDR_POST_DIV_SHIFT) + 1;
145 qca_ddr_clk = cpu_pll / temp;
147 temp = ((reg_val & QCA_PLL_CPU_CLK_CTRL_AHB_POST_DIV_MASK)
148 >> QCA_PLL_CPU_CLK_CTRL_AHB_POST_DIV_SHIFT) + 1;
149 qca_ahb_clk = cpu_pll / temp;
153 * Main AR934x/QCA95xx CPU/DDR PLL clock calculation
157 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_CPU_DPLL2_REG);
159 /* CPU PLL settings from SRIF CPU DPLL2? */
160 if (reg_val & QCA_PLL_SRIF_DPLL2_LOCAL_PLL_MASK) {
161 outdiv = (reg_val & QCA_PLL_SRIF_DPLL2_OUTDIV_MASK)
162 >> QCA_PLL_SRIF_DPLL2_OUTDIV_SHIFT;
164 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_CPU_DPLL1_REG);
166 nfrac = (reg_val & QCA_PLL_SRIF_DPLL1_NFRAC_MASK)
167 >> QCA_PLL_SRIF_DPLL1_NFRAC_SHIFT;
171 nint = (reg_val & QCA_PLL_SRIF_DPLL1_NINT_MASK)
172 >> QCA_PLL_SRIF_DPLL1_NINT_SHIFT;
174 refdiv = (reg_val & QCA_PLL_SRIF_DPLL1_REFDIV_MASK)
175 >> QCA_PLL_SRIF_DPLL1_REFDIV_SHIFT;
177 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_DITHER_REG);
179 if (reg_val & QCA_PLL_CPU_PLL_DITHER_DITHER_EN_MASK) {
180 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
181 nfrac = (reg_val & QCA_PLL_CPU_PLL_CFG_NFRAC_MASK)
182 >> QCA_PLL_CPU_PLL_CFG_NFRAC_SHIFT;
184 /* NFRAC = NFRAC_MIN if DITHER_EN is 0 */
185 nfrac = (reg_val & QCA_PLL_CPU_PLL_DITHER_NFRAC_MIN_MASK)
186 >> QCA_PLL_CPU_PLL_DITHER_NFRAC_MIN_SHIFT;
191 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
193 nint = (reg_val & QCA_PLL_CPU_PLL_CFG_NINT_MASK)
194 >> QCA_PLL_CPU_PLL_CFG_NINT_SHIFT;
196 refdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_REFDIV_MASK)
197 >> QCA_PLL_CPU_PLL_CFG_REFDIV_SHIFT;
199 outdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_OUTDIV_MASK)
200 >> QCA_PLL_CPU_PLL_CFG_OUTDIV_SHIFT;
203 /* Final CPU PLL value */
204 cpu_pll = qca_get_pll(qca_ref_clk, refdiv,
205 nfrac, nfracdiv, nint, outdiv);
208 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_DDR_DPLL2_REG);
210 /* DDR PLL settings from SRIF DDR DPLL2? */
211 if (reg_val & QCA_PLL_SRIF_DPLL2_LOCAL_PLL_MASK) {
212 outdiv = (reg_val & QCA_PLL_SRIF_DPLL2_OUTDIV_MASK)
213 >> QCA_PLL_SRIF_DPLL2_OUTDIV_SHIFT;
215 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_DDR_DPLL1_REG);
217 nfrac = (reg_val & QCA_PLL_SRIF_DPLL1_NFRAC_MASK)
218 >> QCA_PLL_SRIF_DPLL1_NFRAC_SHIFT;
222 nint = (reg_val & QCA_PLL_SRIF_DPLL1_NINT_MASK)
223 >> QCA_PLL_SRIF_DPLL1_NINT_SHIFT;
225 refdiv = (reg_val & QCA_PLL_SRIF_DPLL1_REFDIV_MASK)
226 >> QCA_PLL_SRIF_DPLL1_REFDIV_SHIFT;
228 reg_val = qca_soc_reg_read(QCA_PLL_DDR_PLL_DITHER_REG);
230 if (reg_val & QCA_PLL_DDR_PLL_DITHER_DITHER_EN_MASK) {
231 reg_val = qca_soc_reg_read(QCA_PLL_DDR_PLL_CFG_REG);
232 nfrac = (reg_val & QCA_PLL_DDR_PLL_CFG_NFRAC_MASK)
233 >> QCA_PLL_DDR_PLL_CFG_NFRAC_SHIFT;
235 /* NFRAC = NFRAC_MIN if DITHER_EN is 0 */
236 nfrac = (reg_val & QCA_PLL_DDR_PLL_DITHER_NFRAC_MIN_MASK)
237 >> QCA_PLL_DDR_PLL_DITHER_NFRAC_MIN_SHIFT;
242 reg_val = qca_soc_reg_read(QCA_PLL_DDR_PLL_CFG_REG);
244 nint = (reg_val & QCA_PLL_DDR_PLL_CFG_NINT_MASK)
245 >> QCA_PLL_DDR_PLL_CFG_NINT_SHIFT;
247 refdiv = (reg_val & QCA_PLL_DDR_PLL_CFG_REFDIV_MASK)
248 >> QCA_PLL_DDR_PLL_CFG_REFDIV_SHIFT;
250 outdiv = (reg_val & QCA_PLL_DDR_PLL_CFG_OUTDIV_MASK)
251 >> QCA_PLL_DDR_PLL_CFG_OUTDIV_SHIFT;
254 /* Final DDR PLL value */
255 ddr_pll = qca_get_pll(qca_ref_clk, refdiv,
256 nfrac, nfracdiv, nint, outdiv);
258 /* CPU clock divider */
259 reg_val = qca_soc_reg_read(QCA_PLL_CPU_DDR_CLK_CTRL_REG);
261 temp = ((reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK)
262 >> QCA_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) + 1;
264 if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS_MASK) {
265 qca_cpu_clk = qca_ref_clk;
266 } else if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL_MASK) {
267 qca_cpu_clk = cpu_pll / temp;
269 qca_cpu_clk = ddr_pll / temp;
272 /* DDR clock divider */
273 temp = ((reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK)
274 >> QCA_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) + 1;
276 if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS_MASK) {
277 qca_ddr_clk = qca_ref_clk;
278 } else if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL_MASK) {
279 qca_ddr_clk = ddr_pll / temp;
281 qca_ddr_clk = cpu_pll / temp;
284 /* AHB clock divider */
285 temp = ((reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK)
286 >> QCA_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) + 1;
288 if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS_MASK) {
289 qca_ahb_clk = qca_ref_clk;
290 } else if (reg_val & QCA_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL_MASK) {
291 qca_ahb_clk = ddr_pll / temp;
293 qca_ahb_clk = cpu_pll / temp;
296 /* Calculate SPI FLASH clock - first disable SPI */
297 qca_soc_reg_read_set(QCA_SPI_FUNC_SEL_REG,
298 QCA_SPI_FUNC_SEL_FUNC_SEL_MASK);
300 /* SPI clock = AHB clock / ((SPI clock divider + 1) * 2) */
301 reg_val = (qca_soc_reg_read(QCA_SPI_CTRL_REG) & QCA_SPI_CTRL_CLK_DIV_MASK)
302 >> QCA_SPI_CTRL_CLK_DIV_SHIFT;
304 qca_spi_clk = qca_ahb_clk / ((reg_val + 1) * 2);
307 qca_soc_reg_read_clear(QCA_SPI_FUNC_SEL_REG,
308 QCA_SPI_FUNC_SEL_FUNC_SEL_MASK);
312 *cpu_clk = qca_cpu_clk;
315 *ddr_clk = qca_ddr_clk;
318 *ahb_clk = qca_ahb_clk;
321 *spi_clk = qca_spi_clk;
324 *ref_clk = qca_ref_clk;