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
34static 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
47static 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
86static int sr_genpll0_clk_init(struct platform_device *pdev)
87{
88 iproc_pll_clk_setup(node: pdev->dev.of_node,
89 pll_ctrl: &sr_genpll0, NULL, num_vco_entries: 0, clk_ctrl: sr_genpll0_clk,
90 ARRAY_SIZE(sr_genpll0_clk));
91 return 0;
92}
93
94static 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
107static 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
145static int sr_genpll2_clk_init(struct platform_device *pdev)
146{
147 iproc_pll_clk_setup(node: pdev->dev.of_node,
148 pll_ctrl: &sr_genpll2, NULL, num_vco_entries: 0, clk_ctrl: sr_genpll2_clk,
149 ARRAY_SIZE(sr_genpll2_clk));
150 return 0;
151}
152
153static 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
166static 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
181static void sr_genpll3_clk_init(struct device_node *node)
182{
183 iproc_pll_clk_setup(node, pll_ctrl: &sr_genpll3, NULL, num_vco_entries: 0, clk_ctrl: sr_genpll3_clk,
184 ARRAY_SIZE(sr_genpll3_clk));
185}
186CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);
187
188static 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
201static 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
234static int sr_genpll4_clk_init(struct platform_device *pdev)
235{
236 iproc_pll_clk_setup(node: pdev->dev.of_node,
237 pll_ctrl: &sr_genpll4, NULL, num_vco_entries: 0, clk_ctrl: sr_genpll4_clk,
238 ARRAY_SIZE(sr_genpll4_clk));
239 return 0;
240}
241
242static 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
255static 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
273static int sr_genpll5_clk_init(struct platform_device *pdev)
274{
275 iproc_pll_clk_setup(node: pdev->dev.of_node,
276 pll_ctrl: &sr_genpll5, NULL, num_vco_entries: 0, clk_ctrl: sr_genpll5_clk,
277 ARRAY_SIZE(sr_genpll5_clk));
278 return 0;
279}
280
281static 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
291static 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
318static int sr_lcpll0_clk_init(struct platform_device *pdev)
319{
320 iproc_pll_clk_setup(node: pdev->dev.of_node,
321 pll_ctrl: &sr_lcpll0, NULL, num_vco_entries: 0, clk_ctrl: sr_lcpll0_clk,
322 ARRAY_SIZE(sr_lcpll0_clk));
323 return 0;
324}
325
326static 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
336static 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
357static int sr_lcpll1_clk_init(struct platform_device *pdev)
358{
359 iproc_pll_clk_setup(node: pdev->dev.of_node,
360 pll_ctrl: &sr_lcpll1, NULL, num_vco_entries: 0, clk_ctrl: sr_lcpll1_clk,
361 ARRAY_SIZE(sr_lcpll1_clk));
362 return 0;
363}
364
365static 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
375static 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
384static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
385{
386 iproc_pll_clk_setup(node: pdev->dev.of_node,
387 pll_ctrl: &sr_lcpll_pcie, NULL, num_vco_entries: 0, clk_ctrl: sr_lcpll_pcie_clk,
388 ARRAY_SIZE(sr_lcpll_pcie_clk));
389 return 0;
390}
391
392static 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
403static 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(dev: &pdev->dev);
408 if (!probe_func)
409 return -ENODEV;
410
411 return probe_func(pdev);
412}
413
414static 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};
421builtin_platform_driver(sr_clk_driver);
422

source code of linux/drivers/clk/bcm/clk-sr.c