89e7444f5763c71daa10850cf971ef9b8bf1d249
[oweals/u-boot_mod.git] / u-boot / cpu / mips / ar7240 / qca_clocks.c
1 /*
2  * Qualcomm/Atheros WiSoCs system clocks related functions
3  *
4  * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
5  *
6  * Partially based on:
7  * Linux/arch/mips/ath79/clock.c
8  *
9  * SPDX-License-Identifier: GPL-2.0
10  */
11
12 #include <config.h>
13 #include <common.h>
14 #include <asm/io.h>
15 #include <asm/addrspace.h>
16 #include <soc/qca_soc_common.h>
17
18 /*
19  * Calculates and returns PLL value
20  * TODO: check for overflow!
21  */
22 static u32 qca_get_pll(u32 ref_clk,
23                                            u32 refdiv,
24                                            u32 nfrac,
25                                            u32 nfracdiv,
26                                            u32 nint,
27                                            u32 outdiv)
28 {
29         u64 pll_mul, pll_div;
30
31         pll_mul = ref_clk;
32         pll_div = refdiv;
33
34         if (pll_div == 0)
35                 pll_div = 1;
36
37         if (nfrac > 0) {
38                 pll_mul = pll_mul * ((nint * nfracdiv) + nfrac);
39                 pll_div = pll_div * nfracdiv;
40         } else {
41                 pll_mul = pll_mul * nint;
42         }
43
44         pll_div = pll_div << outdiv;
45
46         return (u32)(pll_mul / pll_div);
47 }
48
49 /*
50  * Get CPU, RAM, AHB and SPI clocks
51  * TODO: confirm nfracdiv values
52  */
53 void qca_sys_clocks(u32 *cpu_clk,
54                                         u32 *ddr_clk,
55                                         u32 *ahb_clk,
56                                         u32 *spi_clk,
57                                         u32 *ref_clk)
58 {
59         u32 qca_ahb_clk, qca_cpu_clk, qca_ddr_clk, qca_ref_clk, qca_spi_clk;
60         u32 nint, outdiv, refdiv;
61         u32 nfrac, nfracdiv;
62         u32 reg_val, temp;
63
64 #if (SOC_TYPE & QCA_AR933X_SOC)
65         u32 cpu_pll;
66 #else
67         u32 cpu_pll, ddr_pll;
68 #endif
69
70         if (qca_xtal_is_40mhz() == 1) {
71                 qca_ref_clk = VAL_40MHz;
72         } else {
73                 qca_ref_clk = VAL_25MHz;
74         }
75
76 #if (SOC_TYPE & QCA_AR933X_SOC)
77         /*
78          * Main AR933x CPU PLL clock calculation:
79          *
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)
83          *
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)
87          *
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
91          */
92
93         /* Read CPU CLock Control Register (CLOCK_CONTROL) value */
94         reg_val = qca_soc_reg_read(QCA_PLL_CPU_CLK_CTRL_REG);
95
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;
101         } else {
102                 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_DITHER_REG);
103
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;
108                 } else {
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;
113                 }
114
115                 nfracdiv = 1 << 10;
116
117                 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
118
119                 nint = (reg_val & QCA_PLL_CPU_PLL_CFG_NINT_MASK)
120                            >> QCA_PLL_CPU_PLL_CFG_NINT_SHIFT;
121
122                 refdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_REFDIV_MASK)
123                                  >> QCA_PLL_CPU_PLL_CFG_REFDIV_SHIFT;
124
125                 outdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_OUTDIV_MASK)
126                                  >> QCA_PLL_CPU_PLL_CFG_OUTDIV_SHIFT;
127
128                 /* TODO: need confirmation that OUTDIV == 0 is not supported for AR933x */
129                 if (outdiv == 0)
130                         outdiv = 1;
131
132                 /* Final CPU PLL value */
133                 cpu_pll = qca_get_pll(qca_ref_clk, refdiv,
134                                                           nfrac, nfracdiv, nint, outdiv);
135
136                 /* CPU, DDR and AHB clock dividers */
137                 reg_val = qca_soc_reg_read(QCA_PLL_CPU_CLK_CTRL_REG);
138
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;
142
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;
146
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;
150         }
151 #else
152         /*
153          * Main AR934x/QCA95xx CPU/DDR PLL clock calculation
154          */
155
156         /* CPU PLL */
157         reg_val = qca_soc_reg_read(QCA_PLL_SRIF_CPU_DPLL2_REG);
158
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;
163
164                 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_CPU_DPLL1_REG);
165
166                 nfrac = (reg_val & QCA_PLL_SRIF_DPLL1_NFRAC_MASK)
167                                 >> QCA_PLL_SRIF_DPLL1_NFRAC_SHIFT;
168
169                 nfracdiv = 1 << 18;
170
171                 nint = (reg_val & QCA_PLL_SRIF_DPLL1_NINT_MASK)
172                            >> QCA_PLL_SRIF_DPLL1_NINT_SHIFT;
173
174                 refdiv = (reg_val & QCA_PLL_SRIF_DPLL1_REFDIV_MASK)
175                                  >> QCA_PLL_SRIF_DPLL1_REFDIV_SHIFT;
176         } else {
177                 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_DITHER_REG);
178
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;
183                 } else {
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;
187                 }
188
189                 nfracdiv = 1 << 6;
190
191                 reg_val = qca_soc_reg_read(QCA_PLL_CPU_PLL_CFG_REG);
192
193                 nint = (reg_val & QCA_PLL_CPU_PLL_CFG_NINT_MASK)
194                            >> QCA_PLL_CPU_PLL_CFG_NINT_SHIFT;
195
196                 refdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_REFDIV_MASK)
197                                  >> QCA_PLL_CPU_PLL_CFG_REFDIV_SHIFT;
198
199                 outdiv = (reg_val & QCA_PLL_CPU_PLL_CFG_OUTDIV_MASK)
200                                  >> QCA_PLL_CPU_PLL_CFG_OUTDIV_SHIFT;
201         }
202
203         /* Final CPU PLL value */
204         cpu_pll = qca_get_pll(qca_ref_clk, refdiv,
205                                                   nfrac, nfracdiv, nint, outdiv);
206
207         /* DDR PLL */
208         reg_val = qca_soc_reg_read(QCA_PLL_SRIF_DDR_DPLL2_REG);
209
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;
214
215                 reg_val = qca_soc_reg_read(QCA_PLL_SRIF_DDR_DPLL1_REG);
216
217                 nfrac = (reg_val & QCA_PLL_SRIF_DPLL1_NFRAC_MASK)
218                                 >> QCA_PLL_SRIF_DPLL1_NFRAC_SHIFT;
219
220                 nfracdiv = 1 << 18;
221
222                 nint = (reg_val & QCA_PLL_SRIF_DPLL1_NINT_MASK)
223                            >> QCA_PLL_SRIF_DPLL1_NINT_SHIFT;
224
225                 refdiv = (reg_val & QCA_PLL_SRIF_DPLL1_REFDIV_MASK)
226                                  >> QCA_PLL_SRIF_DPLL1_REFDIV_SHIFT;
227         } else {
228                 reg_val = qca_soc_reg_read(QCA_PLL_DDR_PLL_DITHER_REG);
229
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;
234                 } else {
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;
238                 }
239
240                 nfracdiv = 1 << 10;
241
242                 reg_val = qca_soc_reg_read(QCA_PLL_DDR_PLL_CFG_REG);
243
244                 nint = (reg_val & QCA_PLL_DDR_PLL_CFG_NINT_MASK)
245                            >> QCA_PLL_DDR_PLL_CFG_NINT_SHIFT;
246
247                 refdiv = (reg_val & QCA_PLL_DDR_PLL_CFG_REFDIV_MASK)
248                                  >> QCA_PLL_DDR_PLL_CFG_REFDIV_SHIFT;
249
250                 outdiv = (reg_val & QCA_PLL_DDR_PLL_CFG_OUTDIV_MASK)
251                                  >> QCA_PLL_DDR_PLL_CFG_OUTDIV_SHIFT;
252         }
253
254         /* Final DDR PLL value */
255         ddr_pll = qca_get_pll(qca_ref_clk, refdiv,
256                                                   nfrac, nfracdiv, nint, outdiv);
257
258         /* CPU clock divider */
259         reg_val = qca_soc_reg_read(QCA_PLL_CPU_DDR_CLK_CTRL_REG);
260
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;
263
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;
268         } else {
269                 qca_cpu_clk = ddr_pll / temp;
270         }
271
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;
275
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;
280         } else {
281                 qca_ddr_clk = cpu_pll / temp;
282         }
283
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;
287
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;
292         } else {
293                 qca_ahb_clk = cpu_pll / temp;
294         }
295 #endif
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);
299
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;
303
304         qca_spi_clk = qca_ahb_clk / ((reg_val + 1) * 2);
305
306         /* Re-enable SPI */
307         qca_soc_reg_read_clear(QCA_SPI_FUNC_SEL_REG,
308                                                    QCA_SPI_FUNC_SEL_FUNC_SEL_MASK);
309
310         /* Return values */
311         if (cpu_clk != NULL)
312                 *cpu_clk = qca_cpu_clk;
313
314         if (ddr_clk != NULL)
315                 *ddr_clk = qca_ddr_clk;
316
317         if (ahb_clk != NULL)
318                 *ahb_clk = qca_ahb_clk;
319
320         if (spi_clk != NULL)
321                 *spi_clk = qca_spi_clk;
322
323         if (ref_clk != NULL)
324                 *ref_clk = qca_ref_clk;
325 }