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(pdev->dev.of_node,
89			    &sr_genpll0, NULL, 0, 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(pdev->dev.of_node,
148			    &sr_genpll2, NULL, 0, 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, &sr_genpll3, NULL, 0, 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(pdev->dev.of_node,
237			    &sr_genpll4, NULL, 0, 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(pdev->dev.of_node,
276			    &sr_genpll5, NULL, 0, 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(pdev->dev.of_node,
321			    &sr_lcpll0, NULL, 0, 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(pdev->dev.of_node,
360			    &sr_lcpll1, NULL, 0, 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(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
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(&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