1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright 2017 Broadcom
4 */
5
6 #include <linux/err.h>
7 #include <linux/clk-provider.h>
8 #include <linux/of.h>
9 #include <linux/platform_device.h>
10
11 #include <dt-bindings/clock/bcm-sr.h>
12 #include "clk-iproc.h"
13
14 #define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
15
16 #define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
17 .pwr_shift = ps, .iso_shift = is }
18
19 #define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
20
21 #define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
22 .p_reset_shift = prs }
23
24 #define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
25 .ki_shift = kis, .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, \
26 .ka_shift = kas, .ka_width = kaw }
27
28 #define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
29
30 #define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
31 .hold_shift = hs, .bypass_shift = bs }
32
33
34 static const struct iproc_pll_ctrl sr_genpll0 = {
35 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
36 IPROC_CLK_PLL_NEEDS_SW_CFG,
37 .aon = AON_VAL(0x0, 5, 1, 0),
38 .reset = RESET_VAL(0x0, 12, 11),
39 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
40 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
41 .ndiv_int = REG_VAL(0x10, 20, 10),
42 .ndiv_frac = REG_VAL(0x10, 0, 20),
43 .pdiv = REG_VAL(0x14, 0, 4),
44 .status = REG_VAL(0x30, 12, 1),
45 };
46
47 static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
48 [BCM_SR_GENPLL0_125M_CLK] = {
49 .channel = BCM_SR_GENPLL0_125M_CLK,
50 .flags = IPROC_CLK_AON,
51 .enable = ENABLE_VAL(0x4, 6, 0, 12),
52 .mdiv = REG_VAL(0x18, 0, 9),
53 },
54 [BCM_SR_GENPLL0_SCR_CLK] = {
55 .channel = BCM_SR_GENPLL0_SCR_CLK,
56 .flags = IPROC_CLK_AON,
57 .enable = ENABLE_VAL(0x4, 7, 1, 13),
58 .mdiv = REG_VAL(0x18, 10, 9),
59 },
60 [BCM_SR_GENPLL0_250M_CLK] = {
61 .channel = BCM_SR_GENPLL0_250M_CLK,
62 .flags = IPROC_CLK_AON,
63 .enable = ENABLE_VAL(0x4, 8, 2, 14),
64 .mdiv = REG_VAL(0x18, 20, 9),
65 },
66 [BCM_SR_GENPLL0_PCIE_AXI_CLK] = {
67 .channel = BCM_SR_GENPLL0_PCIE_AXI_CLK,
68 .flags = IPROC_CLK_AON,
69 .enable = ENABLE_VAL(0x4, 9, 3, 15),
70 .mdiv = REG_VAL(0x1c, 0, 9),
71 },
72 [BCM_SR_GENPLL0_PAXC_AXI_X2_CLK] = {
73 .channel = BCM_SR_GENPLL0_PAXC_AXI_X2_CLK,
74 .flags = IPROC_CLK_AON,
75 .enable = ENABLE_VAL(0x4, 10, 4, 16),
76 .mdiv = REG_VAL(0x1c, 10, 9),
77 },
78 [BCM_SR_GENPLL0_PAXC_AXI_CLK] = {
79 .channel = BCM_SR_GENPLL0_PAXC_AXI_CLK,
80 .flags = IPROC_CLK_AON,
81 .enable = ENABLE_VAL(0x4, 11, 5, 17),
82 .mdiv = REG_VAL(0x1c, 20, 9),
83 },
84 };
85
sr_genpll0_clk_init(struct platform_device * pdev)86 static int sr_genpll0_clk_init(struct platform_device *pdev)
87 {
88 iproc_pll_clk_setup(pdev->dev.of_node,
89 &sr_genpll0, NULL, 0, sr_genpll0_clk,
90 ARRAY_SIZE(sr_genpll0_clk));
91 return 0;
92 }
93
94 static const struct iproc_pll_ctrl sr_genpll2 = {
95 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
96 IPROC_CLK_PLL_NEEDS_SW_CFG,
97 .aon = AON_VAL(0x0, 1, 13, 12),
98 .reset = RESET_VAL(0x0, 12, 11),
99 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
100 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
101 .ndiv_int = REG_VAL(0x10, 20, 10),
102 .ndiv_frac = REG_VAL(0x10, 0, 20),
103 .pdiv = REG_VAL(0x14, 0, 4),
104 .status = REG_VAL(0x30, 12, 1),
105 };
106
107 static const struct iproc_clk_ctrl sr_genpll2_clk[] = {
108 [BCM_SR_GENPLL2_NIC_CLK] = {
109 .channel = BCM_SR_GENPLL2_NIC_CLK,
110 .flags = IPROC_CLK_AON,
111 .enable = ENABLE_VAL(0x4, 6, 0, 12),
112 .mdiv = REG_VAL(0x18, 0, 9),
113 },
114 [BCM_SR_GENPLL2_TS_500_CLK] = {
115 .channel = BCM_SR_GENPLL2_TS_500_CLK,
116 .flags = IPROC_CLK_AON,
117 .enable = ENABLE_VAL(0x4, 7, 1, 13),
118 .mdiv = REG_VAL(0x18, 10, 9),
119 },
120 [BCM_SR_GENPLL2_125_NITRO_CLK] = {
121 .channel = BCM_SR_GENPLL2_125_NITRO_CLK,
122 .flags = IPROC_CLK_AON,
123 .enable = ENABLE_VAL(0x4, 8, 2, 14),
124 .mdiv = REG_VAL(0x18, 20, 9),
125 },
126 [BCM_SR_GENPLL2_CHIMP_CLK] = {
127 .channel = BCM_SR_GENPLL2_CHIMP_CLK,
128 .flags = IPROC_CLK_AON,
129 .enable = ENABLE_VAL(0x4, 9, 3, 15),
130 .mdiv = REG_VAL(0x1c, 0, 9),
131 },
132 [BCM_SR_GENPLL2_NIC_FLASH_CLK] = {
133 .channel = BCM_SR_GENPLL2_NIC_FLASH_CLK,
134 .flags = IPROC_CLK_AON,
135 .enable = ENABLE_VAL(0x4, 10, 4, 16),
136 .mdiv = REG_VAL(0x1c, 10, 9),
137 },
138 [BCM_SR_GENPLL2_FS4_CLK] = {
139 .channel = BCM_SR_GENPLL2_FS4_CLK,
140 .enable = ENABLE_VAL(0x4, 11, 5, 17),
141 .mdiv = REG_VAL(0x1c, 20, 9),
142 },
143 };
144
sr_genpll2_clk_init(struct platform_device * pdev)145 static int sr_genpll2_clk_init(struct platform_device *pdev)
146 {
147 iproc_pll_clk_setup(pdev->dev.of_node,
148 &sr_genpll2, NULL, 0, sr_genpll2_clk,
149 ARRAY_SIZE(sr_genpll2_clk));
150 return 0;
151 }
152
153 static const struct iproc_pll_ctrl sr_genpll3 = {
154 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
155 IPROC_CLK_PLL_NEEDS_SW_CFG,
156 .aon = AON_VAL(0x0, 1, 19, 18),
157 .reset = RESET_VAL(0x0, 12, 11),
158 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
159 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
160 .ndiv_int = REG_VAL(0x10, 20, 10),
161 .ndiv_frac = REG_VAL(0x10, 0, 20),
162 .pdiv = REG_VAL(0x14, 0, 4),
163 .status = REG_VAL(0x30, 12, 1),
164 };
165
166 static const struct iproc_clk_ctrl sr_genpll3_clk[] = {
167 [BCM_SR_GENPLL3_HSLS_CLK] = {
168 .channel = BCM_SR_GENPLL3_HSLS_CLK,
169 .flags = IPROC_CLK_AON,
170 .enable = ENABLE_VAL(0x4, 6, 0, 12),
171 .mdiv = REG_VAL(0x18, 0, 9),
172 },
173 [BCM_SR_GENPLL3_SDIO_CLK] = {
174 .channel = BCM_SR_GENPLL3_SDIO_CLK,
175 .flags = IPROC_CLK_AON,
176 .enable = ENABLE_VAL(0x4, 7, 1, 13),
177 .mdiv = REG_VAL(0x18, 10, 9),
178 },
179 };
180
sr_genpll3_clk_init(struct device_node * node)181 static void sr_genpll3_clk_init(struct device_node *node)
182 {
183 iproc_pll_clk_setup(node, &sr_genpll3, NULL, 0, sr_genpll3_clk,
184 ARRAY_SIZE(sr_genpll3_clk));
185 }
186 CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);
187
188 static const struct iproc_pll_ctrl sr_genpll4 = {
189 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
190 IPROC_CLK_PLL_NEEDS_SW_CFG,
191 .aon = AON_VAL(0x0, 1, 25, 24),
192 .reset = RESET_VAL(0x0, 12, 11),
193 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
194 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
195 .ndiv_int = REG_VAL(0x10, 20, 10),
196 .ndiv_frac = REG_VAL(0x10, 0, 20),
197 .pdiv = REG_VAL(0x14, 0, 4),
198 .status = REG_VAL(0x30, 12, 1),
199 };
200
201 static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
202 [BCM_SR_GENPLL4_CCN_CLK] = {
203 .channel = BCM_SR_GENPLL4_CCN_CLK,
204 .flags = IPROC_CLK_AON,
205 .enable = ENABLE_VAL(0x4, 6, 0, 12),
206 .mdiv = REG_VAL(0x18, 0, 9),
207 },
208 [BCM_SR_GENPLL4_TPIU_PLL_CLK] = {
209 .channel = BCM_SR_GENPLL4_TPIU_PLL_CLK,
210 .flags = IPROC_CLK_AON,
211 .enable = ENABLE_VAL(0x4, 7, 1, 13),
212 .mdiv = REG_VAL(0x18, 10, 9),
213 },
214 [BCM_SR_GENPLL4_NOC_CLK] = {
215 .channel = BCM_SR_GENPLL4_NOC_CLK,
216 .flags = IPROC_CLK_AON,
217 .enable = ENABLE_VAL(0x4, 8, 2, 14),
218 .mdiv = REG_VAL(0x18, 20, 9),
219 },
220 [BCM_SR_GENPLL4_CHCLK_FS4_CLK] = {
221 .channel = BCM_SR_GENPLL4_CHCLK_FS4_CLK,
222 .flags = IPROC_CLK_AON,
223 .enable = ENABLE_VAL(0x4, 9, 3, 15),
224 .mdiv = REG_VAL(0x1c, 0, 9),
225 },
226 [BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK] = {
227 .channel = BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK,
228 .flags = IPROC_CLK_AON,
229 .enable = ENABLE_VAL(0x4, 10, 4, 16),
230 .mdiv = REG_VAL(0x1c, 10, 9),
231 },
232 };
233
sr_genpll4_clk_init(struct platform_device * pdev)234 static int sr_genpll4_clk_init(struct platform_device *pdev)
235 {
236 iproc_pll_clk_setup(pdev->dev.of_node,
237 &sr_genpll4, NULL, 0, sr_genpll4_clk,
238 ARRAY_SIZE(sr_genpll4_clk));
239 return 0;
240 }
241
242 static const struct iproc_pll_ctrl sr_genpll5 = {
243 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
244 IPROC_CLK_PLL_NEEDS_SW_CFG,
245 .aon = AON_VAL(0x0, 1, 1, 0),
246 .reset = RESET_VAL(0x0, 12, 11),
247 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
248 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
249 .ndiv_int = REG_VAL(0x10, 20, 10),
250 .ndiv_frac = REG_VAL(0x10, 0, 20),
251 .pdiv = REG_VAL(0x14, 0, 4),
252 .status = REG_VAL(0x30, 12, 1),
253 };
254
255 static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
256 [BCM_SR_GENPLL5_FS4_HF_CLK] = {
257 .channel = BCM_SR_GENPLL5_FS4_HF_CLK,
258 .enable = ENABLE_VAL(0x4, 6, 0, 12),
259 .mdiv = REG_VAL(0x18, 0, 9),
260 },
261 [BCM_SR_GENPLL5_CRYPTO_AE_CLK] = {
262 .channel = BCM_SR_GENPLL5_CRYPTO_AE_CLK,
263 .enable = ENABLE_VAL(0x4, 7, 1, 12),
264 .mdiv = REG_VAL(0x18, 10, 9),
265 },
266 [BCM_SR_GENPLL5_RAID_AE_CLK] = {
267 .channel = BCM_SR_GENPLL5_RAID_AE_CLK,
268 .enable = ENABLE_VAL(0x4, 8, 2, 14),
269 .mdiv = REG_VAL(0x18, 20, 9),
270 },
271 };
272
sr_genpll5_clk_init(struct platform_device * pdev)273 static int sr_genpll5_clk_init(struct platform_device *pdev)
274 {
275 iproc_pll_clk_setup(pdev->dev.of_node,
276 &sr_genpll5, NULL, 0, sr_genpll5_clk,
277 ARRAY_SIZE(sr_genpll5_clk));
278 return 0;
279 }
280
281 static const struct iproc_pll_ctrl sr_lcpll0 = {
282 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
283 .aon = AON_VAL(0x0, 2, 19, 18),
284 .reset = RESET_VAL(0x0, 31, 30),
285 .sw_ctrl = SW_CTRL_VAL(0x4, 31),
286 .ndiv_int = REG_VAL(0x4, 16, 10),
287 .pdiv = REG_VAL(0x4, 26, 4),
288 .status = REG_VAL(0x38, 12, 1),
289 };
290
291 static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
292 [BCM_SR_LCPLL0_SATA_REFP_CLK] = {
293 .channel = BCM_SR_LCPLL0_SATA_REFP_CLK,
294 .flags = IPROC_CLK_AON,
295 .enable = ENABLE_VAL(0x0, 7, 1, 13),
296 .mdiv = REG_VAL(0x14, 0, 9),
297 },
298 [BCM_SR_LCPLL0_SATA_REFN_CLK] = {
299 .channel = BCM_SR_LCPLL0_SATA_REFN_CLK,
300 .flags = IPROC_CLK_AON,
301 .enable = ENABLE_VAL(0x0, 8, 2, 14),
302 .mdiv = REG_VAL(0x14, 10, 9),
303 },
304 [BCM_SR_LCPLL0_SATA_350_CLK] = {
305 .channel = BCM_SR_LCPLL0_SATA_350_CLK,
306 .flags = IPROC_CLK_AON,
307 .enable = ENABLE_VAL(0x0, 9, 3, 15),
308 .mdiv = REG_VAL(0x14, 20, 9),
309 },
310 [BCM_SR_LCPLL0_SATA_500_CLK] = {
311 .channel = BCM_SR_LCPLL0_SATA_500_CLK,
312 .flags = IPROC_CLK_AON,
313 .enable = ENABLE_VAL(0x0, 10, 4, 16),
314 .mdiv = REG_VAL(0x18, 0, 9),
315 },
316 };
317
sr_lcpll0_clk_init(struct platform_device * pdev)318 static int sr_lcpll0_clk_init(struct platform_device *pdev)
319 {
320 iproc_pll_clk_setup(pdev->dev.of_node,
321 &sr_lcpll0, NULL, 0, sr_lcpll0_clk,
322 ARRAY_SIZE(sr_lcpll0_clk));
323 return 0;
324 }
325
326 static const struct iproc_pll_ctrl sr_lcpll1 = {
327 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
328 .aon = AON_VAL(0x0, 2, 22, 21),
329 .reset = RESET_VAL(0x0, 31, 30),
330 .sw_ctrl = SW_CTRL_VAL(0x4, 31),
331 .ndiv_int = REG_VAL(0x4, 16, 10),
332 .pdiv = REG_VAL(0x4, 26, 4),
333 .status = REG_VAL(0x38, 12, 1),
334 };
335
336 static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
337 [BCM_SR_LCPLL1_WAN_CLK] = {
338 .channel = BCM_SR_LCPLL1_WAN_CLK,
339 .flags = IPROC_CLK_AON,
340 .enable = ENABLE_VAL(0x0, 7, 1, 13),
341 .mdiv = REG_VAL(0x14, 0, 9),
342 },
343 [BCM_SR_LCPLL1_USB_REF_CLK] = {
344 .channel = BCM_SR_LCPLL1_USB_REF_CLK,
345 .flags = IPROC_CLK_AON,
346 .enable = ENABLE_VAL(0x0, 8, 2, 14),
347 .mdiv = REG_VAL(0x14, 10, 9),
348 },
349 [BCM_SR_LCPLL1_CRMU_TS_CLK] = {
350 .channel = BCM_SR_LCPLL1_CRMU_TS_CLK,
351 .flags = IPROC_CLK_AON,
352 .enable = ENABLE_VAL(0x0, 9, 3, 15),
353 .mdiv = REG_VAL(0x14, 20, 9),
354 },
355 };
356
sr_lcpll1_clk_init(struct platform_device * pdev)357 static int sr_lcpll1_clk_init(struct platform_device *pdev)
358 {
359 iproc_pll_clk_setup(pdev->dev.of_node,
360 &sr_lcpll1, NULL, 0, sr_lcpll1_clk,
361 ARRAY_SIZE(sr_lcpll1_clk));
362 return 0;
363 }
364
365 static const struct iproc_pll_ctrl sr_lcpll_pcie = {
366 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
367 .aon = AON_VAL(0x0, 2, 25, 24),
368 .reset = RESET_VAL(0x0, 31, 30),
369 .sw_ctrl = SW_CTRL_VAL(0x4, 31),
370 .ndiv_int = REG_VAL(0x4, 16, 10),
371 .pdiv = REG_VAL(0x4, 26, 4),
372 .status = REG_VAL(0x38, 12, 1),
373 };
374
375 static const struct iproc_clk_ctrl sr_lcpll_pcie_clk[] = {
376 [BCM_SR_LCPLL_PCIE_PHY_REF_CLK] = {
377 .channel = BCM_SR_LCPLL_PCIE_PHY_REF_CLK,
378 .flags = IPROC_CLK_AON,
379 .enable = ENABLE_VAL(0x0, 7, 1, 13),
380 .mdiv = REG_VAL(0x14, 0, 9),
381 },
382 };
383
sr_lcpll_pcie_clk_init(struct platform_device * pdev)384 static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
385 {
386 iproc_pll_clk_setup(pdev->dev.of_node,
387 &sr_lcpll_pcie, NULL, 0, sr_lcpll_pcie_clk,
388 ARRAY_SIZE(sr_lcpll_pcie_clk));
389 return 0;
390 }
391
392 static const struct of_device_id sr_clk_dt_ids[] = {
393 { .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
394 { .compatible = "brcm,sr-genpll2", .data = sr_genpll2_clk_init },
395 { .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
396 { .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
397 { .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
398 { .compatible = "brcm,sr-lcpll1", .data = sr_lcpll1_clk_init },
399 { .compatible = "brcm,sr-lcpll-pcie", .data = sr_lcpll_pcie_clk_init },
400 { /* sentinel */ }
401 };
402
sr_clk_probe(struct platform_device * pdev)403 static int sr_clk_probe(struct platform_device *pdev)
404 {
405 int (*probe_func)(struct platform_device *);
406
407 probe_func = of_device_get_match_data(&pdev->dev);
408 if (!probe_func)
409 return -ENODEV;
410
411 return probe_func(pdev);
412 }
413
414 static struct platform_driver sr_clk_driver = {
415 .driver = {
416 .name = "sr-clk",
417 .of_match_table = sr_clk_dt_ids,
418 },
419 .probe = sr_clk_probe,
420 };
421 builtin_platform_driver(sr_clk_driver);
422