1*52e6676eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*52e6676eSThomas Gleixner // Copyright (C) 2015 Broadcom Corporation
3f7225a83SJon Mason
4f7225a83SJon Mason #include <linux/kernel.h>
5f7225a83SJon Mason #include <linux/err.h>
6f7225a83SJon Mason #include <linux/clk-provider.h>
7f7225a83SJon Mason #include <linux/io.h>
8f7225a83SJon Mason #include <linux/of.h>
9f7225a83SJon Mason #include <linux/of_address.h>
10f7225a83SJon Mason
11f7225a83SJon Mason #include <dt-bindings/clock/bcm-ns2.h>
12f7225a83SJon Mason #include "clk-iproc.h"
13f7225a83SJon Mason
14f7225a83SJon Mason #define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
15f7225a83SJon Mason
16f7225a83SJon Mason #define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
17f7225a83SJon Mason .pwr_shift = ps, .iso_shift = is }
18f7225a83SJon Mason
19f7225a83SJon Mason #define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
20f7225a83SJon Mason .p_reset_shift = prs }
21f7225a83SJon Mason
22f7225a83SJon Mason #define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
23f7225a83SJon Mason .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
24f7225a83SJon Mason .ka_width = kaw }
25f7225a83SJon Mason
26f7225a83SJon Mason #define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
27f7225a83SJon Mason
28f7225a83SJon Mason #define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
29f7225a83SJon Mason .hold_shift = hs, .bypass_shift = bs }
30f7225a83SJon Mason
31f7225a83SJon Mason static const struct iproc_pll_ctrl genpll_scr = {
32f7225a83SJon Mason .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
33f7225a83SJon Mason .aon = AON_VAL(0x0, 1, 15, 12),
34f7225a83SJon Mason .reset = RESET_VAL(0x4, 2, 1),
35f7225a83SJon Mason .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
36f7225a83SJon Mason .ndiv_int = REG_VAL(0x8, 4, 10),
37f7225a83SJon Mason .pdiv = REG_VAL(0x8, 0, 4),
38f7225a83SJon Mason .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
39f7225a83SJon Mason .status = REG_VAL(0x0, 27, 1),
40f7225a83SJon Mason };
41f7225a83SJon Mason
42f7225a83SJon Mason
43f7225a83SJon Mason static const struct iproc_clk_ctrl genpll_scr_clk[] = {
44f7225a83SJon Mason /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
45f7225a83SJon Mason * in NS2. However, it doesn't appear to be used anywhere, so setting
46f7225a83SJon Mason * it to 0.
47f7225a83SJon Mason */
48f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_SCR_CLK] = {
49f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_SCR_CLK,
50f7225a83SJon Mason .flags = IPROC_CLK_AON,
51f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 18, 12, 0),
52f7225a83SJon Mason .mdiv = REG_VAL(0x18, 0, 8),
53f7225a83SJon Mason },
54f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_FS_CLK] = {
55f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_FS_CLK,
56f7225a83SJon Mason .flags = IPROC_CLK_AON,
57f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 19, 13, 0),
58f7225a83SJon Mason .mdiv = REG_VAL(0x18, 8, 8),
59f7225a83SJon Mason },
60f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {
61f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,
62f7225a83SJon Mason .flags = IPROC_CLK_AON,
63f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 20, 14, 0),
64f7225a83SJon Mason .mdiv = REG_VAL(0x14, 0, 8),
65f7225a83SJon Mason },
66f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {
67f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,
68f7225a83SJon Mason .flags = IPROC_CLK_AON,
69f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 21, 15, 0),
70f7225a83SJon Mason .mdiv = REG_VAL(0x14, 8, 8),
71f7225a83SJon Mason },
72f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {
73f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,
74f7225a83SJon Mason .flags = IPROC_CLK_AON,
75f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 22, 16, 0),
76f7225a83SJon Mason .mdiv = REG_VAL(0x14, 16, 8),
77f7225a83SJon Mason },
78f7225a83SJon Mason [BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {
79f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,
80f7225a83SJon Mason .flags = IPROC_CLK_AON,
81f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 23, 17, 0),
82f7225a83SJon Mason .mdiv = REG_VAL(0x14, 24, 8),
83f7225a83SJon Mason },
84f7225a83SJon Mason };
85f7225a83SJon Mason
ns2_genpll_scr_clk_init(struct device_node * node)86f7225a83SJon Mason static void __init ns2_genpll_scr_clk_init(struct device_node *node)
87f7225a83SJon Mason {
88f7225a83SJon Mason iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,
89f7225a83SJon Mason ARRAY_SIZE(genpll_scr_clk));
90f7225a83SJon Mason }
91f7225a83SJon Mason CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
92f7225a83SJon Mason ns2_genpll_scr_clk_init);
93f7225a83SJon Mason
94f7225a83SJon Mason static const struct iproc_pll_ctrl genpll_sw = {
95f7225a83SJon Mason .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
968973aa4aSBharat Kumar Reddy Gooty .aon = AON_VAL(0x0, 1, 11, 10),
97f7225a83SJon Mason .reset = RESET_VAL(0x4, 2, 1),
98f7225a83SJon Mason .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
99f7225a83SJon Mason .ndiv_int = REG_VAL(0x8, 4, 10),
100f7225a83SJon Mason .pdiv = REG_VAL(0x8, 0, 4),
101f7225a83SJon Mason .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
102f7225a83SJon Mason .status = REG_VAL(0x0, 13, 1),
103f7225a83SJon Mason };
104f7225a83SJon Mason
105f7225a83SJon Mason static const struct iproc_clk_ctrl genpll_sw_clk[] = {
106f7225a83SJon Mason /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
107f7225a83SJon Mason * in NS2. However, it doesn't appear to be used anywhere, so setting
108f7225a83SJon Mason * it to 0.
109f7225a83SJon Mason */
110f7225a83SJon Mason [BCM_NS2_GENPLL_SW_RPE_CLK] = {
111f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_RPE_CLK,
112f7225a83SJon Mason .flags = IPROC_CLK_AON,
113f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 18, 12, 0),
114f7225a83SJon Mason .mdiv = REG_VAL(0x18, 0, 8),
115f7225a83SJon Mason },
116f7225a83SJon Mason [BCM_NS2_GENPLL_SW_250_CLK] = {
117f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_250_CLK,
118f7225a83SJon Mason .flags = IPROC_CLK_AON,
119f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 19, 13, 0),
120f7225a83SJon Mason .mdiv = REG_VAL(0x18, 8, 8),
121f7225a83SJon Mason },
122f7225a83SJon Mason [BCM_NS2_GENPLL_SW_NIC_CLK] = {
123f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_NIC_CLK,
124f7225a83SJon Mason .flags = IPROC_CLK_AON,
125f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 20, 14, 0),
126f7225a83SJon Mason .mdiv = REG_VAL(0x14, 0, 8),
127f7225a83SJon Mason },
128f7225a83SJon Mason [BCM_NS2_GENPLL_SW_CHIMP_CLK] = {
129f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,
130f7225a83SJon Mason .flags = IPROC_CLK_AON,
131f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 21, 15, 0),
132f7225a83SJon Mason .mdiv = REG_VAL(0x14, 8, 8),
133f7225a83SJon Mason },
134f7225a83SJon Mason [BCM_NS2_GENPLL_SW_PORT_CLK] = {
135f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_PORT_CLK,
136f7225a83SJon Mason .flags = IPROC_CLK_AON,
137f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 22, 16, 0),
138f7225a83SJon Mason .mdiv = REG_VAL(0x14, 16, 8),
139f7225a83SJon Mason },
140f7225a83SJon Mason [BCM_NS2_GENPLL_SW_SDIO_CLK] = {
141f7225a83SJon Mason .channel = BCM_NS2_GENPLL_SW_SDIO_CLK,
142f7225a83SJon Mason .flags = IPROC_CLK_AON,
143f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 23, 17, 0),
144f7225a83SJon Mason .mdiv = REG_VAL(0x14, 24, 8),
145f7225a83SJon Mason },
146f7225a83SJon Mason };
147f7225a83SJon Mason
ns2_genpll_sw_clk_init(struct device_node * node)148f7225a83SJon Mason static void __init ns2_genpll_sw_clk_init(struct device_node *node)
149f7225a83SJon Mason {
150f7225a83SJon Mason iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,
151f7225a83SJon Mason ARRAY_SIZE(genpll_sw_clk));
152f7225a83SJon Mason }
153f7225a83SJon Mason CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",
154f7225a83SJon Mason ns2_genpll_sw_clk_init);
155f7225a83SJon Mason
156f7225a83SJon Mason static const struct iproc_pll_ctrl lcpll_ddr = {
157f7225a83SJon Mason .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
158f7225a83SJon Mason .aon = AON_VAL(0x0, 2, 1, 0),
159f7225a83SJon Mason .reset = RESET_VAL(0x4, 2, 1),
160f7225a83SJon Mason .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
161f7225a83SJon Mason .ndiv_int = REG_VAL(0x8, 4, 10),
162f7225a83SJon Mason .pdiv = REG_VAL(0x8, 0, 4),
163f7225a83SJon Mason .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
164f7225a83SJon Mason .status = REG_VAL(0x0, 0, 1),
165f7225a83SJon Mason };
166f7225a83SJon Mason
167f7225a83SJon Mason static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {
168f7225a83SJon Mason /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
169f7225a83SJon Mason * in NS2. However, it doesn't appear to be used anywhere, so setting
170f7225a83SJon Mason * it to 0.
171f7225a83SJon Mason */
172f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {
173f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,
174f7225a83SJon Mason .flags = IPROC_CLK_AON,
175f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 18, 12, 0),
176f7225a83SJon Mason .mdiv = REG_VAL(0x14, 0, 8),
177f7225a83SJon Mason },
178f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_DDR_CLK] = {
179f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_DDR_CLK,
180f7225a83SJon Mason .flags = IPROC_CLK_AON,
181f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 19, 13, 0),
182f7225a83SJon Mason .mdiv = REG_VAL(0x14, 8, 8),
183f7225a83SJon Mason },
184f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {
185f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,
186f7225a83SJon Mason .flags = IPROC_CLK_AON,
187f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 20, 14, 0),
188f7225a83SJon Mason .mdiv = REG_VAL(0x10, 0, 8),
189f7225a83SJon Mason },
190f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {
191f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,
192f7225a83SJon Mason .flags = IPROC_CLK_AON,
193f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 21, 15, 0),
194f7225a83SJon Mason .mdiv = REG_VAL(0x10, 8, 8),
195f7225a83SJon Mason },
196f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {
197f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,
198f7225a83SJon Mason .flags = IPROC_CLK_AON,
199f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 22, 16, 0),
200f7225a83SJon Mason .mdiv = REG_VAL(0x10, 16, 8),
201f7225a83SJon Mason },
202f7225a83SJon Mason [BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {
203f7225a83SJon Mason .channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,
204f7225a83SJon Mason .flags = IPROC_CLK_AON,
205f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 23, 17, 0),
206f7225a83SJon Mason .mdiv = REG_VAL(0x10, 24, 8),
207f7225a83SJon Mason },
208f7225a83SJon Mason };
209f7225a83SJon Mason
ns2_lcpll_ddr_clk_init(struct device_node * node)210f7225a83SJon Mason static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)
211f7225a83SJon Mason {
212f7225a83SJon Mason iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,
213f7225a83SJon Mason ARRAY_SIZE(lcpll_ddr_clk));
214f7225a83SJon Mason }
215f7225a83SJon Mason CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",
216f7225a83SJon Mason ns2_lcpll_ddr_clk_init);
217f7225a83SJon Mason
218f7225a83SJon Mason static const struct iproc_pll_ctrl lcpll_ports = {
219f7225a83SJon Mason .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
220f7225a83SJon Mason .aon = AON_VAL(0x0, 2, 5, 4),
221f7225a83SJon Mason .reset = RESET_VAL(0x4, 2, 1),
222f7225a83SJon Mason .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
223f7225a83SJon Mason .ndiv_int = REG_VAL(0x8, 4, 10),
224f7225a83SJon Mason .pdiv = REG_VAL(0x8, 0, 4),
225f7225a83SJon Mason .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
226f7225a83SJon Mason .status = REG_VAL(0x0, 0, 1),
227f7225a83SJon Mason };
228f7225a83SJon Mason
229f7225a83SJon Mason static const struct iproc_clk_ctrl lcpll_ports_clk[] = {
230f7225a83SJon Mason /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
231f7225a83SJon Mason * in NS2. However, it doesn't appear to be used anywhere, so setting
232f7225a83SJon Mason * it to 0.
233f7225a83SJon Mason */
234f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_WAN_CLK] = {
235f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,
236f7225a83SJon Mason .flags = IPROC_CLK_AON,
237f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 18, 12, 0),
238f7225a83SJon Mason .mdiv = REG_VAL(0x14, 0, 8),
239f7225a83SJon Mason },
240f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {
241f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,
242f7225a83SJon Mason .flags = IPROC_CLK_AON,
243f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 19, 13, 0),
244f7225a83SJon Mason .mdiv = REG_VAL(0x14, 8, 8),
245f7225a83SJon Mason },
246f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {
247f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,
248f7225a83SJon Mason .flags = IPROC_CLK_AON,
249f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 20, 14, 0),
250f7225a83SJon Mason .mdiv = REG_VAL(0x10, 0, 8),
251f7225a83SJon Mason },
252f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {
253f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,
254f7225a83SJon Mason .flags = IPROC_CLK_AON,
255f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 21, 15, 0),
256f7225a83SJon Mason .mdiv = REG_VAL(0x10, 8, 8),
257f7225a83SJon Mason },
258f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {
259f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,
260f7225a83SJon Mason .flags = IPROC_CLK_AON,
261f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 22, 16, 0),
262f7225a83SJon Mason .mdiv = REG_VAL(0x10, 16, 8),
263f7225a83SJon Mason },
264f7225a83SJon Mason [BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {
265f7225a83SJon Mason .channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,
266f7225a83SJon Mason .flags = IPROC_CLK_AON,
267f7225a83SJon Mason .enable = ENABLE_VAL(0x0, 23, 17, 0),
268f7225a83SJon Mason .mdiv = REG_VAL(0x10, 24, 8),
269f7225a83SJon Mason },
270f7225a83SJon Mason };
271f7225a83SJon Mason
ns2_lcpll_ports_clk_init(struct device_node * node)272f7225a83SJon Mason static void __init ns2_lcpll_ports_clk_init(struct device_node *node)
273f7225a83SJon Mason {
274f7225a83SJon Mason iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,
275f7225a83SJon Mason ARRAY_SIZE(lcpll_ports_clk));
276f7225a83SJon Mason }
277f7225a83SJon Mason CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",
278f7225a83SJon Mason ns2_lcpll_ports_clk_init);
279