spi: zynqmp_gqspi: fix set_speed bug on multiple runs
[platform/kernel/u-boot.git] / drivers / clk / altera / clk-arria10.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 Marek Vasut <marex@denx.de>
4  */
5
6 #include <common.h>
7 #include <malloc.h>
8 #include <asm/io.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <dm/device_compat.h>
12 #include <dm/devres.h>
13 #include <dm/lists.h>
14 #include <dm/util.h>
15 #include <linux/bitops.h>
16
17 #include <asm/arch/clock_manager.h>
18
19 enum socfpga_a10_clk_type {
20         SOCFPGA_A10_CLK_MAIN_PLL,
21         SOCFPGA_A10_CLK_PER_PLL,
22         SOCFPGA_A10_CLK_PERIP_CLK,
23         SOCFPGA_A10_CLK_GATE_CLK,
24         SOCFPGA_A10_CLK_UNKNOWN_CLK,
25 };
26
27 struct socfpga_a10_clk_plat {
28         enum socfpga_a10_clk_type type;
29         struct clk_bulk clks;
30         u32             regs;
31         /* Fixed divider */
32         u16             fix_div;
33         /* Control register */
34         u16             ctl_reg;
35         /* Divider register */
36         u16             div_reg;
37         u8              div_len;
38         u8              div_off;
39         /* Clock gating register */
40         u16             gate_reg;
41         u8              gate_bit;
42 };
43
44 static int socfpga_a10_clk_get_upstream(struct clk *clk, struct clk **upclk)
45 {
46         struct socfpga_a10_clk_plat *plat = dev_get_plat(clk->dev);
47         u32 reg, maxval;
48
49         if (plat->clks.count == 0)
50                 return 0;
51
52         if (plat->clks.count == 1) {
53                 *upclk = &plat->clks.clks[0];
54                 return 0;
55         }
56
57         if (!plat->ctl_reg) {
58                 dev_err(clk->dev, "Invalid control register\n");
59                 return -EINVAL;
60         }
61
62         reg = readl(plat->regs + plat->ctl_reg);
63
64         /* Assume PLLs are ON for now */
65         if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) {
66                 reg = (reg >> 8) & 0x3;
67                 maxval = 2;
68         } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) {
69                 reg = (reg >> 8) & 0x3;
70                 maxval = 3;
71         } else {
72                 reg = (reg >> 16) & 0x7;
73                 maxval = 4;
74         }
75
76         if (reg > maxval) {
77                 dev_err(clk->dev, "Invalid clock source\n");
78                 return -EINVAL;
79         }
80
81         *upclk = &plat->clks.clks[reg];
82         return 0;
83 }
84
85 static int socfpga_a10_clk_endisable(struct clk *clk, bool enable)
86 {
87         struct socfpga_a10_clk_plat *plat = dev_get_plat(clk->dev);
88         struct clk *upclk = NULL;
89         int ret;
90
91         if (!enable && plat->gate_reg)
92                 clrbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit));
93
94         ret = socfpga_a10_clk_get_upstream(clk, &upclk);
95         if (ret)
96                 return ret;
97
98         if (upclk) {
99                 if (enable)
100                         clk_enable(upclk);
101                 else
102                         clk_disable(upclk);
103         }
104
105         if (enable && plat->gate_reg)
106                 setbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit));
107
108         return 0;
109 }
110
111 static int socfpga_a10_clk_enable(struct clk *clk)
112 {
113         return socfpga_a10_clk_endisable(clk, true);
114 }
115
116 static int socfpga_a10_clk_disable(struct clk *clk)
117 {
118         return socfpga_a10_clk_endisable(clk, false);
119 }
120
121 static ulong socfpga_a10_clk_get_rate(struct clk *clk)
122 {
123         struct socfpga_a10_clk_plat *plat = dev_get_plat(clk->dev);
124         struct clk *upclk = NULL;
125         ulong rate = 0, reg, numer, denom;
126         int ret;
127
128         ret = socfpga_a10_clk_get_upstream(clk, &upclk);
129         if (ret || !upclk)
130                 return 0;
131
132         rate = clk_get_rate(upclk);
133
134         if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) {
135                 reg = readl(plat->regs + plat->ctl_reg + 4);    /* VCO1 */
136                 numer = reg & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
137                 denom = (reg >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) &
138                         CLKMGR_MAINPLL_VCO1_DENOM_MSK;
139
140                 rate /= denom + 1;
141                 rate *= numer + 1;
142         } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) {
143                 reg = readl(plat->regs + plat->ctl_reg + 4);    /* VCO1 */
144                 numer = reg & CLKMGR_PERPLL_VCO1_NUMER_MSK;
145                 denom = (reg >> CLKMGR_PERPLL_VCO1_DENOM_LSB) &
146                         CLKMGR_PERPLL_VCO1_DENOM_MSK;
147
148                 rate /= denom + 1;
149                 rate *= numer + 1;
150         } else {
151                 rate /= plat->fix_div;
152
153                 if (plat->fix_div == 1 && plat->ctl_reg) {
154                         reg = readl(plat->regs + plat->ctl_reg);
155                         reg &= 0x7ff;
156                         rate /= reg + 1;
157                 }
158
159                 if (plat->div_reg) {
160                         reg = readl(plat->regs + plat->div_reg);
161                         reg >>= plat->div_off;
162                         reg &= (1 << plat->div_len) - 1;
163                         if (plat->type == SOCFPGA_A10_CLK_PERIP_CLK)
164                                 rate /= reg + 1;
165                         if (plat->type == SOCFPGA_A10_CLK_GATE_CLK)
166                                 rate /= 1 << reg;
167                 }
168         }
169
170         return rate;
171 }
172
173 static struct clk_ops socfpga_a10_clk_ops = {
174         .enable         = socfpga_a10_clk_enable,
175         .disable        = socfpga_a10_clk_disable,
176         .get_rate       = socfpga_a10_clk_get_rate,
177 };
178
179 /*
180  * This workaround tries to fix the massively broken generated "handoff" DT,
181  * which contains duplicate clock nodes without any connection to the clock
182  * manager DT node. Yet, those "handoff" DT nodes contain configuration of
183  * the fixed input clock of the Arria10 which are missing from the base DT
184  * for Arria10.
185  *
186  * This workaround sets up upstream clock for the fixed input clocks of the
187  * A10 described in the base DT such that they map to the fixed clock from
188  * the "handoff" DT. This does not fully match how the clock look on the
189  * A10, but it is the least intrusive way to fix this mess.
190  */
191 static void socfpga_a10_handoff_workaround(struct udevice *dev)
192 {
193         struct socfpga_a10_clk_plat *plat = dev_get_plat(dev);
194         const void *fdt = gd->fdt_blob;
195         struct clk_bulk *bulk = &plat->clks;
196         int i, ret, offset = dev_of_offset(dev);
197         static const char * const socfpga_a10_fixedclk_map[] = {
198                 "osc1", "altera_arria10_hps_eosc1",
199                 "cb_intosc_ls_clk", "altera_arria10_hps_cb_intosc_ls",
200                 "f2s_free_clk", "altera_arria10_hps_f2h_free",
201         };
202
203         if (fdt_node_check_compatible(fdt, offset, "fixed-clock"))
204                 return;
205
206         for (i = 0; i < ARRAY_SIZE(socfpga_a10_fixedclk_map); i += 2)
207                 if (!strcmp(dev->name, socfpga_a10_fixedclk_map[i]))
208                         break;
209
210         if (i == ARRAY_SIZE(socfpga_a10_fixedclk_map))
211                 return;
212
213         ret = uclass_get_device_by_name(UCLASS_CLK,
214                                         socfpga_a10_fixedclk_map[i + 1], &dev);
215         if (ret)
216                 return;
217
218         bulk->count = 1;
219         bulk->clks = devm_kcalloc(dev, bulk->count,
220                                   sizeof(struct clk), GFP_KERNEL);
221         if (!bulk->clks)
222                 return;
223
224         ret = clk_request(dev, &bulk->clks[0]);
225         if (ret)
226                 free(bulk->clks);
227 }
228
229 static int socfpga_a10_clk_bind(struct udevice *dev)
230 {
231         const void *fdt = gd->fdt_blob;
232         int offset = dev_of_offset(dev);
233         bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
234         const char *name;
235         int ret;
236
237         for (offset = fdt_first_subnode(fdt, offset);
238              offset > 0;
239              offset = fdt_next_subnode(fdt, offset)) {
240                 name = fdt_get_name(fdt, offset, NULL);
241                 if (!name)
242                         return -EINVAL;
243
244                 if (!strcmp(name, "clocks")) {
245                         offset = fdt_first_subnode(fdt, offset);
246                         name = fdt_get_name(fdt, offset, NULL);
247                         if (!name)
248                                 return -EINVAL;
249                 }
250
251                 /* Filter out supported sub-clock */
252                 if (fdt_node_check_compatible(fdt, offset,
253                                               "altr,socfpga-a10-pll-clock") &&
254                     fdt_node_check_compatible(fdt, offset,
255                                               "altr,socfpga-a10-perip-clk") &&
256                     fdt_node_check_compatible(fdt, offset,
257                                               "altr,socfpga-a10-gate-clk") &&
258                     fdt_node_check_compatible(fdt, offset, "fixed-clock"))
259                         continue;
260
261                 if (pre_reloc_only &&
262                     !ofnode_pre_reloc(offset_to_ofnode(offset)))
263                         continue;
264
265                 ret = device_bind_driver_to_node(dev, "clk-a10", name,
266                                                  offset_to_ofnode(offset),
267                                                  NULL);
268                 if (ret)
269                         return ret;
270         }
271
272         return 0;
273 }
274
275 static int socfpga_a10_clk_probe(struct udevice *dev)
276 {
277         struct socfpga_a10_clk_plat *plat = dev_get_plat(dev);
278         struct socfpga_a10_clk_plat *pplat;
279         struct udevice *pdev;
280         const void *fdt = gd->fdt_blob;
281         int offset = dev_of_offset(dev);
282
283         clk_get_bulk(dev, &plat->clks);
284
285         socfpga_a10_handoff_workaround(dev);
286
287         if (!fdt_node_check_compatible(fdt, offset, "altr,clk-mgr")) {
288                 plat->regs = dev_read_addr(dev);
289         } else {
290                 pdev = dev_get_parent(dev);
291                 if (!pdev)
292                         return -ENODEV;
293
294                 pplat = dev_get_plat(pdev);
295                 if (!pplat)
296                         return -EINVAL;
297
298                 plat->ctl_reg = dev_read_u32_default(dev, "reg", 0x0);
299                 plat->regs = pplat->regs;
300         }
301
302         if (!fdt_node_check_compatible(fdt, offset,
303                                        "altr,socfpga-a10-pll-clock")) {
304                 /* Main PLL has 3 upstream clock */
305                 if (plat->clks.count == 3)
306                         plat->type = SOCFPGA_A10_CLK_MAIN_PLL;
307                 else
308                         plat->type = SOCFPGA_A10_CLK_PER_PLL;
309         } else if (!fdt_node_check_compatible(fdt, offset,
310                                               "altr,socfpga-a10-perip-clk")) {
311                 plat->type = SOCFPGA_A10_CLK_PERIP_CLK;
312         } else if (!fdt_node_check_compatible(fdt, offset,
313                                               "altr,socfpga-a10-gate-clk")) {
314                 plat->type = SOCFPGA_A10_CLK_GATE_CLK;
315         } else {
316                 plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK;
317         }
318
319         return 0;
320 }
321
322 static int socfpga_a10_of_to_plat(struct udevice *dev)
323 {
324         struct socfpga_a10_clk_plat *plat = dev_get_plat(dev);
325         unsigned int divreg[3], gatereg[2];
326         int ret;
327
328         plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK;
329
330         plat->fix_div = dev_read_u32_default(dev, "fixed-divider", 1);
331
332         ret = dev_read_u32_array(dev, "div-reg", divreg, ARRAY_SIZE(divreg));
333         if (!ret) {
334                 plat->div_reg = divreg[0];
335                 plat->div_len = divreg[2];
336                 plat->div_off = divreg[1];
337         }
338
339         ret = dev_read_u32_array(dev, "clk-gate", gatereg, ARRAY_SIZE(gatereg));
340         if (!ret) {
341                 plat->gate_reg = gatereg[0];
342                 plat->gate_bit = gatereg[1];
343         }
344
345         return 0;
346 }
347
348 static const struct udevice_id socfpga_a10_clk_match[] = {
349         { .compatible = "altr,clk-mgr" },
350         {}
351 };
352
353 U_BOOT_DRIVER(socfpga_a10_clk) = {
354         .name           = "clk-a10",
355         .id             = UCLASS_CLK,
356         .of_match       = socfpga_a10_clk_match,
357         .ops            = &socfpga_a10_clk_ops,
358         .bind           = socfpga_a10_clk_bind,
359         .probe          = socfpga_a10_clk_probe,
360         .of_to_plat = socfpga_a10_of_to_plat,
361
362         .plat_auto      = sizeof(struct socfpga_a10_clk_plat),
363 };