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