Linux-libre 4.14.68-gnu
[librecmc/linux-libre.git] / drivers / clk / berlin / bg2q.c
1 /*
2  * Copyright (c) 2014 Marvell Technology Group Ltd.
3  *
4  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <linux/clk.h>
21 #include <linux/clk-provider.h>
22 #include <linux/kernel.h>
23 #include <linux/of.h>
24 #include <linux/of_address.h>
25 #include <linux/slab.h>
26
27 #include <dt-bindings/clock/berlin2q.h>
28
29 #include "berlin2-div.h"
30 #include "berlin2-pll.h"
31 #include "common.h"
32
33 #define REG_PINMUX0             0x0018
34 #define REG_PINMUX5             0x002c
35 #define REG_SYSPLLCTL0          0x0030
36 #define REG_SYSPLLCTL4          0x0040
37 #define REG_CLKENABLE           0x00e8
38 #define REG_CLKSELECT0          0x00ec
39 #define REG_CLKSELECT1          0x00f0
40 #define REG_CLKSELECT2          0x00f4
41 #define REG_CLKSWITCH0          0x00f8
42 #define REG_CLKSWITCH1          0x00fc
43 #define REG_SW_GENERIC0         0x0110
44 #define REG_SW_GENERIC3         0x011c
45 #define REG_SDIO0XIN_CLKCTL     0x0158
46 #define REG_SDIO1XIN_CLKCTL     0x015c
47
48 #define MAX_CLKS 28
49 static struct clk_hw_onecell_data *clk_data;
50 static DEFINE_SPINLOCK(lock);
51 static void __iomem *gbase;
52 static void __iomem *cpupll_base;
53
54 enum {
55         REFCLK,
56         SYSPLL, CPUPLL,
57         AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
58         AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
59 };
60
61 static const char *clk_names[] = {
62         [REFCLK]                = "refclk",
63         [SYSPLL]                = "syspll",
64         [CPUPLL]                = "cpupll",
65         [AVPLL_B1]              = "avpll_b1",
66         [AVPLL_B2]              = "avpll_b2",
67         [AVPLL_B3]              = "avpll_b3",
68         [AVPLL_B4]              = "avpll_b4",
69         [AVPLL_B5]              = "avpll_b5",
70         [AVPLL_B6]              = "avpll_b6",
71         [AVPLL_B7]              = "avpll_b7",
72         [AVPLL_B8]              = "avpll_b8",
73 };
74
75 static const struct berlin2_pll_map bg2q_pll_map __initconst = {
76         .vcodiv         = {1, 0, 2, 0, 3, 4, 0, 6, 8},
77         .mult           = 1,
78         .fbdiv_shift    = 7,
79         .rfdiv_shift    = 2,
80         .divsel_shift   = 9,
81 };
82
83 static const u8 default_parent_ids[] = {
84         SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
85 };
86
87 static const struct berlin2_div_data bg2q_divs[] __initconst = {
88         {
89                 .name = "sys",
90                 .parent_ids = default_parent_ids,
91                 .num_parents = ARRAY_SIZE(default_parent_ids),
92                 .map = {
93                         BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
94                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
95                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
96                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
97                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
98                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
99                 },
100                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
101                 .flags = CLK_IGNORE_UNUSED,
102         },
103         {
104                 .name = "drmfigo",
105                 .parent_ids = default_parent_ids,
106                 .num_parents = ARRAY_SIZE(default_parent_ids),
107                 .map = {
108                         BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
109                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
110                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
111                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
112                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
113                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
114                 },
115                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
116                 .flags = 0,
117         },
118         {
119                 .name = "cfg",
120                 .parent_ids = default_parent_ids,
121                 .num_parents = ARRAY_SIZE(default_parent_ids),
122                 .map = {
123                         BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
124                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
125                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
126                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
127                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
128                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
129                 },
130                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
131                 .flags = 0,
132         },
133         {
134                 .name = "gfx2d",
135                 .parent_ids = default_parent_ids,
136                 .num_parents = ARRAY_SIZE(default_parent_ids),
137                 .map = {
138                         BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
139                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
140                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
141                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
142                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
143                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
144                 },
145                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
146                 .flags = 0,
147         },
148         {
149                 .name = "zsp",
150                 .parent_ids = default_parent_ids,
151                 .num_parents = ARRAY_SIZE(default_parent_ids),
152                 .map = {
153                         BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
154                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
155                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
156                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
157                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
158                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
159                 },
160                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
161                 .flags = 0,
162         },
163         {
164                 .name = "perif",
165                 .parent_ids = default_parent_ids,
166                 .num_parents = ARRAY_SIZE(default_parent_ids),
167                 .map = {
168                         BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
169                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
170                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
171                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
172                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
173                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
174                 },
175                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
176                 .flags = CLK_IGNORE_UNUSED,
177         },
178         {
179                 .name = "pcube",
180                 .parent_ids = default_parent_ids,
181                 .num_parents = ARRAY_SIZE(default_parent_ids),
182                 .map = {
183                         BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
184                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
185                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
186                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
187                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
188                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
189                 },
190                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
191                 .flags = 0,
192         },
193         {
194                 .name = "vscope",
195                 .parent_ids = default_parent_ids,
196                 .num_parents = ARRAY_SIZE(default_parent_ids),
197                 .map = {
198                         BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
199                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
200                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
201                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
202                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
203                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
204                 },
205                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
206                 .flags = 0,
207         },
208         {
209                 .name = "nfc_ecc",
210                 .parent_ids = default_parent_ids,
211                 .num_parents = ARRAY_SIZE(default_parent_ids),
212                 .map = {
213                         BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
214                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
215                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
216                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
217                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
218                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
219                 },
220                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
221                 .flags = 0,
222         },
223         {
224                 .name = "vpp",
225                 .parent_ids = default_parent_ids,
226                 .num_parents = ARRAY_SIZE(default_parent_ids),
227                 .map = {
228                         BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
229                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
230                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
231                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
232                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
233                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
234                 },
235                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
236                 .flags = 0,
237         },
238         {
239                 .name = "app",
240                 .parent_ids = default_parent_ids,
241                 .num_parents = ARRAY_SIZE(default_parent_ids),
242                 .map = {
243                         BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
244                         BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
245                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
246                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
247                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
248                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
249                 },
250                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
251                 .flags = 0,
252         },
253         {
254                 .name = "sdio0xin",
255                 .parent_ids = default_parent_ids,
256                 .num_parents = ARRAY_SIZE(default_parent_ids),
257                 .map = {
258                         BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
259                 },
260                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
261                 .flags = 0,
262         },
263         {
264                 .name = "sdio1xin",
265                 .parent_ids = default_parent_ids,
266                 .num_parents = ARRAY_SIZE(default_parent_ids),
267                 .map = {
268                         BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
269                 },
270                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
271                 .flags = 0,
272         },
273 };
274
275 static const struct berlin2_gate_data bg2q_gates[] __initconst = {
276         { "gfx2daxi",   "perif",        5 },
277         { "geth0",      "perif",        8 },
278         { "sata",       "perif",        9 },
279         { "ahbapb",     "perif",        10, CLK_IGNORE_UNUSED },
280         { "usb0",       "perif",        11 },
281         { "usb1",       "perif",        12 },
282         { "usb2",       "perif",        13 },
283         { "usb3",       "perif",        14 },
284         { "pbridge",    "perif",        15, CLK_IGNORE_UNUSED },
285         { "sdio",       "perif",        16 },
286         { "nfc",        "perif",        18 },
287         { "pcie",       "perif",        22 },
288 };
289
290 static void __init berlin2q_clock_setup(struct device_node *np)
291 {
292         struct device_node *parent_np = of_get_parent(np);
293         const char *parent_names[9];
294         struct clk *clk;
295         struct clk_hw **hws;
296         int n, ret;
297
298         clk_data = kzalloc(sizeof(*clk_data) +
299                            sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL);
300         if (!clk_data)
301                 return;
302         clk_data->num = MAX_CLKS;
303         hws = clk_data->hws;
304
305         gbase = of_iomap(parent_np, 0);
306         if (!gbase) {
307                 pr_err("%pOF: Unable to map global base\n", np);
308                 return;
309         }
310
311         /* BG2Q CPU PLL is not part of global registers */
312         cpupll_base = of_iomap(parent_np, 1);
313         if (!cpupll_base) {
314                 pr_err("%pOF: Unable to map cpupll base\n", np);
315                 iounmap(gbase);
316                 return;
317         }
318
319         /* overwrite default clock names with DT provided ones */
320         clk = of_clk_get_by_name(np, clk_names[REFCLK]);
321         if (!IS_ERR(clk)) {
322                 clk_names[REFCLK] = __clk_get_name(clk);
323                 clk_put(clk);
324         }
325
326         /* simple register PLLs */
327         ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
328                                    clk_names[SYSPLL], clk_names[REFCLK], 0);
329         if (ret)
330                 goto bg2q_fail;
331
332         ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
333                                    clk_names[CPUPLL], clk_names[REFCLK], 0);
334         if (ret)
335                 goto bg2q_fail;
336
337         /* TODO: add BG2Q AVPLL */
338
339         /*
340          * TODO: add reference clock bypass switches:
341          * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
342          */
343
344         /* clock divider cells */
345         for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
346                 const struct berlin2_div_data *dd = &bg2q_divs[n];
347                 int k;
348
349                 for (k = 0; k < dd->num_parents; k++)
350                         parent_names[k] = clk_names[dd->parent_ids[k]];
351
352                 hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
353                                 dd->name, dd->div_flags, parent_names,
354                                 dd->num_parents, dd->flags, &lock);
355         }
356
357         /* clock gate cells */
358         for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
359                 const struct berlin2_gate_data *gd = &bg2q_gates[n];
360
361                 hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name,
362                             gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
363                             gd->bit_idx, 0, &lock);
364         }
365
366         /* cpuclk divider is fixed to 1 */
367         hws[CLKID_CPU] =
368                 clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
369                                           0, 1, 1);
370         /* twdclk is derived from cpu/3 */
371         hws[CLKID_TWD] =
372                 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
373
374         /* check for errors on leaf clocks */
375         for (n = 0; n < MAX_CLKS; n++) {
376                 if (!IS_ERR(hws[n]))
377                         continue;
378
379                 pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
380                 goto bg2q_fail;
381         }
382
383         /* register clk-provider */
384         of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
385
386         return;
387
388 bg2q_fail:
389         iounmap(cpupll_base);
390         iounmap(gbase);
391 }
392 CLK_OF_DECLARE(berlin2q_clk, "marvell,berlin2q-clk",
393                berlin2q_clock_setup);