GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / clk / bcm / clk-sr.c
1 /*
2  * Copyright 2017 Broadcom
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, version 2, as
6  * published by the Free Software Foundation (the "GPL").
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License version 2 (GPLv2) for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * version 2 (GPLv2) along with this source code.
15  */
16
17 #include <linux/err.h>
18 #include <linux/clk-provider.h>
19 #include <linux/of_device.h>
20 #include <linux/platform_device.h>
21
22 #include <dt-bindings/clock/bcm-sr.h>
23 #include "clk-iproc.h"
24
25 #define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
26
27 #define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
28         .pwr_shift = ps, .iso_shift = is }
29
30 #define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
31
32 #define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
33         .p_reset_shift = prs }
34
35 #define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
36         .ki_shift = kis, .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, \
37         .ka_shift = kas, .ka_width = kaw }
38
39 #define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
40
41 #define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
42         .hold_shift = hs, .bypass_shift = bs }
43
44
45 static const struct iproc_pll_ctrl sr_genpll0 = {
46         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
47                 IPROC_CLK_PLL_NEEDS_SW_CFG,
48         .aon = AON_VAL(0x0, 5, 1, 0),
49         .reset = RESET_VAL(0x0, 12, 11),
50         .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
51         .sw_ctrl = SW_CTRL_VAL(0x10, 31),
52         .ndiv_int = REG_VAL(0x10, 20, 10),
53         .ndiv_frac = REG_VAL(0x10, 0, 20),
54         .pdiv = REG_VAL(0x14, 0, 4),
55         .status = REG_VAL(0x30, 12, 1),
56 };
57
58 static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
59         [BCM_SR_GENPLL0_SATA_CLK] = {
60                 .channel = BCM_SR_GENPLL0_SATA_CLK,
61                 .flags = IPROC_CLK_AON,
62                 .enable = ENABLE_VAL(0x4, 6, 0, 12),
63                 .mdiv = REG_VAL(0x18, 0, 9),
64         },
65         [BCM_SR_GENPLL0_SCR_CLK] = {
66                 .channel = BCM_SR_GENPLL0_SCR_CLK,
67                 .flags = IPROC_CLK_AON,
68                 .enable = ENABLE_VAL(0x4, 7, 1, 13),
69                 .mdiv = REG_VAL(0x18, 10, 9),
70         },
71         [BCM_SR_GENPLL0_250M_CLK] = {
72                 .channel = BCM_SR_GENPLL0_250M_CLK,
73                 .flags = IPROC_CLK_AON,
74                 .enable = ENABLE_VAL(0x4, 8, 2, 14),
75                 .mdiv = REG_VAL(0x18, 20, 9),
76         },
77         [BCM_SR_GENPLL0_PCIE_AXI_CLK] = {
78                 .channel = BCM_SR_GENPLL0_PCIE_AXI_CLK,
79                 .flags = IPROC_CLK_AON,
80                 .enable = ENABLE_VAL(0x4, 9, 3, 15),
81                 .mdiv = REG_VAL(0x1c, 0, 9),
82         },
83         [BCM_SR_GENPLL0_PAXC_AXI_X2_CLK] = {
84                 .channel = BCM_SR_GENPLL0_PAXC_AXI_X2_CLK,
85                 .flags = IPROC_CLK_AON,
86                 .enable = ENABLE_VAL(0x4, 10, 4, 16),
87                 .mdiv = REG_VAL(0x1c, 10, 9),
88         },
89         [BCM_SR_GENPLL0_PAXC_AXI_CLK] = {
90                 .channel = BCM_SR_GENPLL0_PAXC_AXI_CLK,
91                 .flags = IPROC_CLK_AON,
92                 .enable = ENABLE_VAL(0x4, 11, 5, 17),
93                 .mdiv = REG_VAL(0x1c, 20, 9),
94         },
95 };
96
97 static int sr_genpll0_clk_init(struct platform_device *pdev)
98 {
99         iproc_pll_clk_setup(pdev->dev.of_node,
100                             &sr_genpll0, NULL, 0, sr_genpll0_clk,
101                             ARRAY_SIZE(sr_genpll0_clk));
102         return 0;
103 }
104
105 static const struct iproc_pll_ctrl sr_genpll3 = {
106         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
107                 IPROC_CLK_PLL_NEEDS_SW_CFG,
108         .aon = AON_VAL(0x0, 1, 19, 18),
109         .reset = RESET_VAL(0x0, 12, 11),
110         .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
111         .sw_ctrl = SW_CTRL_VAL(0x10, 31),
112         .ndiv_int = REG_VAL(0x10, 20, 10),
113         .ndiv_frac = REG_VAL(0x10, 0, 20),
114         .pdiv = REG_VAL(0x14, 0, 4),
115         .status = REG_VAL(0x30, 12, 1),
116 };
117
118 static const struct iproc_clk_ctrl sr_genpll3_clk[] = {
119         [BCM_SR_GENPLL3_HSLS_CLK] = {
120                 .channel = BCM_SR_GENPLL3_HSLS_CLK,
121                 .flags = IPROC_CLK_AON,
122                 .enable = ENABLE_VAL(0x4, 6, 0, 12),
123                 .mdiv = REG_VAL(0x18, 0, 9),
124         },
125         [BCM_SR_GENPLL3_SDIO_CLK] = {
126                 .channel = BCM_SR_GENPLL3_SDIO_CLK,
127                 .flags = IPROC_CLK_AON,
128                 .enable = ENABLE_VAL(0x4, 7, 1, 13),
129                 .mdiv = REG_VAL(0x18, 10, 9),
130         },
131 };
132
133 static void sr_genpll3_clk_init(struct device_node *node)
134 {
135         iproc_pll_clk_setup(node, &sr_genpll3, NULL, 0, sr_genpll3_clk,
136                             ARRAY_SIZE(sr_genpll3_clk));
137 }
138 CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);
139
140 static const struct iproc_pll_ctrl sr_genpll4 = {
141         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
142                 IPROC_CLK_PLL_NEEDS_SW_CFG,
143         .aon = AON_VAL(0x0, 1, 25, 24),
144         .reset = RESET_VAL(0x0, 12, 11),
145         .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
146         .sw_ctrl = SW_CTRL_VAL(0x10, 31),
147         .ndiv_int = REG_VAL(0x10, 20, 10),
148         .ndiv_frac = REG_VAL(0x10, 0, 20),
149         .pdiv = REG_VAL(0x14, 0, 4),
150         .status = REG_VAL(0x30, 12, 1),
151 };
152
153 static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
154         [BCM_SR_GENPLL4_CCN_CLK] = {
155                 .channel = BCM_SR_GENPLL4_CCN_CLK,
156                 .flags = IPROC_CLK_AON,
157                 .enable = ENABLE_VAL(0x4, 6, 0, 12),
158                 .mdiv = REG_VAL(0x18, 0, 9),
159         },
160 };
161
162 static int sr_genpll4_clk_init(struct platform_device *pdev)
163 {
164         iproc_pll_clk_setup(pdev->dev.of_node,
165                             &sr_genpll4, NULL, 0, sr_genpll4_clk,
166                             ARRAY_SIZE(sr_genpll4_clk));
167         return 0;
168 }
169
170 static const struct iproc_pll_ctrl sr_genpll5 = {
171         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
172                 IPROC_CLK_PLL_NEEDS_SW_CFG,
173         .aon = AON_VAL(0x0, 1, 1, 0),
174         .reset = RESET_VAL(0x0, 12, 11),
175         .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
176         .sw_ctrl = SW_CTRL_VAL(0x10, 31),
177         .ndiv_int = REG_VAL(0x10, 20, 10),
178         .ndiv_frac = REG_VAL(0x10, 0, 20),
179         .pdiv = REG_VAL(0x14, 0, 4),
180         .status = REG_VAL(0x30, 12, 1),
181 };
182
183 static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
184         [BCM_SR_GENPLL5_FS_CLK] = {
185                 .channel = BCM_SR_GENPLL5_FS_CLK,
186                 .flags = IPROC_CLK_AON,
187                 .enable = ENABLE_VAL(0x4, 6, 0, 12),
188                 .mdiv = REG_VAL(0x18, 0, 9),
189         },
190         [BCM_SR_GENPLL5_SPU_CLK] = {
191                 .channel = BCM_SR_GENPLL5_SPU_CLK,
192                 .flags = IPROC_CLK_AON,
193                 .enable = ENABLE_VAL(0x4, 6, 0, 12),
194                 .mdiv = REG_VAL(0x18, 10, 9),
195         },
196 };
197
198 static int sr_genpll5_clk_init(struct platform_device *pdev)
199 {
200         iproc_pll_clk_setup(pdev->dev.of_node,
201                             &sr_genpll5, NULL, 0, sr_genpll5_clk,
202                             ARRAY_SIZE(sr_genpll5_clk));
203         return 0;
204 }
205
206 static const struct iproc_pll_ctrl sr_lcpll0 = {
207         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
208         .aon = AON_VAL(0x0, 2, 19, 18),
209         .reset = RESET_VAL(0x0, 31, 30),
210         .sw_ctrl = SW_CTRL_VAL(0x4, 31),
211         .ndiv_int = REG_VAL(0x4, 16, 10),
212         .pdiv = REG_VAL(0x4, 26, 4),
213         .status = REG_VAL(0x38, 12, 1),
214 };
215
216 static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
217         [BCM_SR_LCPLL0_SATA_REF_CLK] = {
218                 .channel = BCM_SR_LCPLL0_SATA_REF_CLK,
219                 .flags = IPROC_CLK_AON,
220                 .enable = ENABLE_VAL(0x0, 7, 1, 13),
221                 .mdiv = REG_VAL(0x14, 0, 9),
222         },
223         [BCM_SR_LCPLL0_USB_REF_CLK] = {
224                 .channel = BCM_SR_LCPLL0_USB_REF_CLK,
225                 .flags = IPROC_CLK_AON,
226                 .enable = ENABLE_VAL(0x0, 8, 2, 14),
227                 .mdiv = REG_VAL(0x14, 10, 9),
228         },
229         [BCM_SR_LCPLL0_SATA_REFPN_CLK] = {
230                 .channel = BCM_SR_LCPLL0_SATA_REFPN_CLK,
231                 .flags = IPROC_CLK_AON,
232                 .enable = ENABLE_VAL(0x0, 9, 3, 15),
233                 .mdiv = REG_VAL(0x14, 20, 9),
234         },
235 };
236
237 static int sr_lcpll0_clk_init(struct platform_device *pdev)
238 {
239         iproc_pll_clk_setup(pdev->dev.of_node,
240                             &sr_lcpll0, NULL, 0, sr_lcpll0_clk,
241                             ARRAY_SIZE(sr_lcpll0_clk));
242         return 0;
243 }
244
245 static const struct iproc_pll_ctrl sr_lcpll1 = {
246         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
247         .aon = AON_VAL(0x0, 2, 22, 21),
248         .reset = RESET_VAL(0x0, 31, 30),
249         .sw_ctrl = SW_CTRL_VAL(0x4, 31),
250         .ndiv_int = REG_VAL(0x4, 16, 10),
251         .pdiv = REG_VAL(0x4, 26, 4),
252         .status = REG_VAL(0x38, 12, 1),
253 };
254
255 static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
256         [BCM_SR_LCPLL1_WAN_CLK] = {
257                 .channel = BCM_SR_LCPLL1_WAN_CLK,
258                 .flags = IPROC_CLK_AON,
259                 .enable = ENABLE_VAL(0x0, 7, 1, 13),
260                 .mdiv = REG_VAL(0x14, 0, 9),
261         },
262 };
263
264 static int sr_lcpll1_clk_init(struct platform_device *pdev)
265 {
266         iproc_pll_clk_setup(pdev->dev.of_node,
267                             &sr_lcpll1, NULL, 0, sr_lcpll1_clk,
268                             ARRAY_SIZE(sr_lcpll1_clk));
269         return 0;
270 }
271
272 static const struct iproc_pll_ctrl sr_lcpll_pcie = {
273         .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
274         .aon = AON_VAL(0x0, 2, 25, 24),
275         .reset = RESET_VAL(0x0, 31, 30),
276         .sw_ctrl = SW_CTRL_VAL(0x4, 31),
277         .ndiv_int = REG_VAL(0x4, 16, 10),
278         .pdiv = REG_VAL(0x4, 26, 4),
279         .status = REG_VAL(0x38, 12, 1),
280 };
281
282 static const struct iproc_clk_ctrl sr_lcpll_pcie_clk[] = {
283         [BCM_SR_LCPLL_PCIE_PHY_REF_CLK] = {
284                 .channel = BCM_SR_LCPLL_PCIE_PHY_REF_CLK,
285                 .flags = IPROC_CLK_AON,
286                 .enable = ENABLE_VAL(0x0, 7, 1, 13),
287                 .mdiv = REG_VAL(0x14, 0, 9),
288         },
289 };
290
291 static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
292 {
293         iproc_pll_clk_setup(pdev->dev.of_node,
294                             &sr_lcpll_pcie, NULL, 0, sr_lcpll_pcie_clk,
295                             ARRAY_SIZE(sr_lcpll_pcie_clk));
296         return 0;
297 }
298
299 static const struct of_device_id sr_clk_dt_ids[] = {
300         { .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
301         { .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
302         { .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
303         { .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
304         { .compatible = "brcm,sr-lcpll1", .data = sr_lcpll1_clk_init },
305         { .compatible = "brcm,sr-lcpll-pcie", .data = sr_lcpll_pcie_clk_init },
306         { /* sentinel */ }
307 };
308
309 static int sr_clk_probe(struct platform_device *pdev)
310 {
311         int (*probe_func)(struct platform_device *);
312
313         probe_func = of_device_get_match_data(&pdev->dev);
314         if (!probe_func)
315                 return -ENODEV;
316
317         return probe_func(pdev);
318 }
319
320 static struct platform_driver sr_clk_driver = {
321         .driver = {
322                 .name = "sr-clk",
323                 .of_match_table = sr_clk_dt_ids,
324         },
325         .probe = sr_clk_probe,
326 };
327 builtin_platform_driver(sr_clk_driver);