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