clk: mediatek: add support to configure clock driver parent
[platform/kernel/u-boot.git] / drivers / clk / mpc83xx_clk.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2017
4  * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5  */
6
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <clock_legacy.h>
10 #include <command.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <vsprintf.h>
14 #include <asm/global_data.h>
15 #include <dm/lists.h>
16 #include <dt-bindings/clk/mpc83xx-clk.h>
17 #include <asm/arch/soc.h>
18 #include <linux/bitops.h>
19
20 #include "mpc83xx_clk.h"
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 /**
25  * struct mpc83xx_clk_priv - Private data structure for the MPC83xx clock
26  *                           driver
27  * @speed: Array containing the speed values of all system clocks (initialized
28  *         once, then only read back)
29  */
30 struct mpc83xx_clk_priv {
31         u32 speed[MPC83XX_CLK_COUNT];
32 };
33
34 /**
35  * is_clk_valid() - Check if clock ID is valid for given clock device
36  * @clk: The clock device for which to check a clock ID
37  * @id:  The clock ID to check
38  *
39  * Return: true if clock ID is valid for clock device, false if not
40  */
41 static inline bool is_clk_valid(struct udevice *clk, int id)
42 {
43         ulong type = dev_get_driver_data(clk);
44
45         switch (id) {
46         case MPC83XX_CLK_MEM:
47                 return true;
48         case MPC83XX_CLK_MEM_SEC:
49                 return type == SOC_MPC8360;
50         case MPC83XX_CLK_ENC:
51                 return (type == SOC_MPC8308) || (type == SOC_MPC8309);
52         case MPC83XX_CLK_I2C1:
53                 return true;
54         case MPC83XX_CLK_TDM:
55                 return type == SOC_MPC8315;
56         case MPC83XX_CLK_SDHC:
57                 return mpc83xx_has_sdhc(type);
58         case MPC83XX_CLK_TSEC1:
59         case MPC83XX_CLK_TSEC2:
60                 return mpc83xx_has_tsec(type);
61         case MPC83XX_CLK_USBDR:
62                 return type == SOC_MPC8360;
63         case MPC83XX_CLK_USBMPH:
64                 return type == SOC_MPC8349;
65         case MPC83XX_CLK_PCIEXP1:
66                 return mpc83xx_has_pcie1(type);
67         case MPC83XX_CLK_PCIEXP2:
68                 return mpc83xx_has_pcie2(type);
69         case MPC83XX_CLK_SATA:
70                 return mpc83xx_has_sata(type);
71         case MPC83XX_CLK_DMAC:
72                 return (type == SOC_MPC8308) || (type == SOC_MPC8309);
73         case MPC83XX_CLK_PCI:
74                 /*
75                  * FIXME: implement proper support for this.
76                  */
77                 return 0 && mpc83xx_has_pci(type);
78         case MPC83XX_CLK_CSB:
79                 return true;
80         case MPC83XX_CLK_I2C2:
81                 return mpc83xx_has_second_i2c(type);
82         case MPC83XX_CLK_QE:
83         case MPC83XX_CLK_BRG:
84                 return mpc83xx_has_quicc_engine(type) && (type != SOC_MPC8309);
85         case MPC83XX_CLK_LCLK:
86         case MPC83XX_CLK_LBIU:
87         case MPC83XX_CLK_CORE:
88                 return true;
89         }
90
91         return false;
92 }
93
94 /**
95  * init_single_clk() - Initialize a clock with a given ID
96  * @dev: The clock device for which to initialize the clock
97  * @clk: The clock ID
98  *
99  * The clock speed is read from the hardware's registers, and stored in the
100  * private data structure of the driver. From there it is only retrieved, and
101  * not set.
102  *
103  * Return: 0 if OK, -ve on error
104  */
105 static int init_single_clk(struct udevice *dev, int clk)
106 {
107         struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
108         immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
109         ulong type = dev_get_driver_data(dev);
110         struct clk_mode mode;
111         ulong mask;
112         u32 csb_clk = get_csb_clk(im);
113         int ret;
114
115         ret = retrieve_mode(clk, type, &mode);
116         if (ret) {
117                 debug("%s: Could not retrieve mode for clk %d (ret = %d)\n",
118                       dev->name, clk, ret);
119                 return ret;
120         }
121
122         if (mode.type == TYPE_INVALID) {
123                 debug("%s: clock %d invalid\n", dev->name, clk);
124                 return -EINVAL;
125         }
126
127         if (mode.type == TYPE_SCCR_STANDARD) {
128                 mask = GENMASK(31 - mode.low, 31 - mode.high);
129
130                 switch (sccr_field(im, mask)) {
131                 case 0:
132                         priv->speed[clk] = 0;
133                         break;
134                 case 1:
135                         priv->speed[clk] = csb_clk;
136                         break;
137                 case 2:
138                         priv->speed[clk] = csb_clk / 2;
139                         break;
140                 case 3:
141                         priv->speed[clk] = csb_clk / 3;
142                         break;
143                 default:
144                         priv->speed[clk] = 0;
145                 }
146
147                 return 0;
148         }
149
150         if (mode.type == TYPE_SPMR_DIRECT_MULTIPLY) {
151                 mask = GENMASK(31 - mode.low, 31 - mode.high);
152
153                 priv->speed[clk] = csb_clk * (1 + sccr_field(im, mask));
154                 return 0;
155         }
156
157         if (clk == MPC83XX_CLK_CSB || clk == MPC83XX_CLK_I2C2) {
158                 priv->speed[clk] = csb_clk; /* i2c-2 clk is equal to csb clk */
159                 return 0;
160         }
161
162         if (clk == MPC83XX_CLK_QE || clk == MPC83XX_CLK_BRG) {
163                 u32 pci_sync_in = get_pci_sync_in(im);
164                 u32 qepmf = spmr_field(im, SPMR_CEPMF);
165                 u32 qepdf = spmr_field(im, SPMR_CEPDF);
166                 u32 qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
167
168                 if (clk == MPC83XX_CLK_QE)
169                         priv->speed[clk] = qe_clk;
170                 else
171                         priv->speed[clk] = qe_clk / 2;
172
173                 return 0;
174         }
175
176         if (clk == MPC83XX_CLK_LCLK || clk == MPC83XX_CLK_LBIU) {
177                 u32 lbiu_clk = csb_clk *
178                         (1 + spmr_field(im, SPMR_LBIUCM));
179                 u32 clkdiv = lcrr_field(im, LCRR_CLKDIV);
180
181                 if (clk == MPC83XX_CLK_LBIU)
182                         priv->speed[clk] = lbiu_clk;
183
184                 switch (clkdiv) {
185                 case 2:
186                 case 4:
187                 case 8:
188                         priv->speed[clk] = lbiu_clk / clkdiv;
189                         break;
190                 default:
191                         /* unknown lcrr */
192                         priv->speed[clk] = 0;
193                 }
194
195                 return 0;
196         }
197
198         if (clk == MPC83XX_CLK_CORE) {
199                 u8 corepll = spmr_field(im, SPMR_COREPLL);
200                 u32 corecnf_tab_index = ((corepll & 0x1F) << 2) |
201                                         ((corepll & 0x60) >> 5);
202
203                 if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
204                         debug("%s: Core configuration index %02x too high; possible wrong value",
205                               dev->name, corecnf_tab_index);
206                         return -EINVAL;
207                 }
208
209                 switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
210                 case RAT_BYP:
211                 case RAT_1_TO_1:
212                         priv->speed[clk] = csb_clk;
213                         break;
214                 case RAT_1_5_TO_1:
215                         priv->speed[clk] = (3 * csb_clk) / 2;
216                         break;
217                 case RAT_2_TO_1:
218                         priv->speed[clk] = 2 * csb_clk;
219                         break;
220                 case RAT_2_5_TO_1:
221                         priv->speed[clk] = (5 * csb_clk) / 2;
222                         break;
223                 case RAT_3_TO_1:
224                         priv->speed[clk] = 3 * csb_clk;
225                         break;
226                 default:
227                         /* unknown core to csb ratio */
228                         priv->speed[clk] = 0;
229                 }
230
231                 return 0;
232         }
233
234         /* Unknown clk value -> error */
235         debug("%s: clock %d invalid\n", dev->name, clk);
236         return -EINVAL;
237 }
238
239 /**
240  * init_all_clks() - Initialize all clocks of a clock device
241  * @dev: The clock device whose clocks should be initialized
242  *
243  * Return: 0 if OK, -ve on error
244  */
245 static inline int init_all_clks(struct udevice *dev)
246 {
247         int i;
248
249         for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
250                 int ret;
251
252                 if (!is_clk_valid(dev, i))
253                         continue;
254
255                 ret = init_single_clk(dev, i);
256                 if (ret) {
257                         debug("%s: Failed to initialize %s clock\n",
258                               dev->name, names[i]);
259                         return ret;
260                 }
261         }
262
263         return 0;
264 }
265
266 static int mpc83xx_clk_request(struct clk *clock)
267 {
268         /* Reject requests of clocks that are not available */
269         if (is_clk_valid(clock->dev, clock->id))
270                 return 0;
271         else
272                 return -ENODEV;
273 }
274
275 static ulong mpc83xx_clk_get_rate(struct clk *clk)
276 {
277         struct mpc83xx_clk_priv *priv = dev_get_priv(clk->dev);
278
279         if (clk->id >= MPC83XX_CLK_COUNT) {
280                 debug("%s: clock index %lu invalid\n", __func__, clk->id);
281                 return 0;
282         }
283
284         return priv->speed[clk->id];
285 }
286
287 static int mpc83xx_clk_enable(struct clk *clk)
288 {
289         /* MPC83xx clocks are always enabled */
290         return 0;
291 }
292
293 int get_clocks(void)
294 {
295         /* Empty implementation to keep the prototype in common.h happy */
296         return 0;
297 }
298
299 int get_serial_clock(void)
300 {
301         struct mpc83xx_clk_priv *priv;
302         struct udevice *clk;
303         int ret;
304
305         ret = uclass_first_device_err(UCLASS_CLK, &clk);
306         if (ret) {
307                 debug("%s: Could not get clock device\n", __func__);
308                 return ret;
309         }
310
311         priv = dev_get_priv(clk);
312
313         return priv->speed[MPC83XX_CLK_CSB];
314 }
315
316 const struct clk_ops mpc83xx_clk_ops = {
317         .request = mpc83xx_clk_request,
318         .get_rate = mpc83xx_clk_get_rate,
319         .enable = mpc83xx_clk_enable,
320 };
321
322 static const struct udevice_id mpc83xx_clk_match[] = {
323         { .compatible = "fsl,mpc8308-clk", .data = SOC_MPC8308 },
324         { .compatible = "fsl,mpc8309-clk", .data = SOC_MPC8309 },
325         { .compatible = "fsl,mpc8313-clk", .data = SOC_MPC8313 },
326         { .compatible = "fsl,mpc8315-clk", .data = SOC_MPC8315 },
327         { .compatible = "fsl,mpc832x-clk", .data = SOC_MPC832X },
328         { .compatible = "fsl,mpc8349-clk", .data = SOC_MPC8349 },
329         { .compatible = "fsl,mpc8360-clk", .data = SOC_MPC8360 },
330         { .compatible = "fsl,mpc8379-clk", .data = SOC_MPC8379 },
331         { /* sentinel */ }
332 };
333
334 static int mpc83xx_clk_probe(struct udevice *dev)
335 {
336         struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
337         ulong type;
338         int ret;
339
340         ret = init_all_clks(dev);
341         if (ret) {
342                 debug("%s: Could not initialize all clocks (ret = %d)\n",
343                       dev->name, ret);
344                 return ret;
345         }
346
347         type = dev_get_driver_data(dev);
348
349         if (mpc83xx_has_sdhc(type))
350                 gd->arch.sdhc_clk = priv->speed[MPC83XX_CLK_SDHC];
351
352         gd->arch.core_clk = priv->speed[MPC83XX_CLK_CORE];
353         gd->arch.i2c1_clk = priv->speed[MPC83XX_CLK_I2C1];
354         if (mpc83xx_has_second_i2c(type))
355                 gd->arch.i2c2_clk = priv->speed[MPC83XX_CLK_I2C2];
356
357         gd->mem_clk = priv->speed[MPC83XX_CLK_MEM];
358
359         if (mpc83xx_has_pci(type))
360                 gd->pci_clk = priv->speed[MPC83XX_CLK_PCI];
361
362         gd->cpu_clk = priv->speed[MPC83XX_CLK_CORE];
363         gd->bus_clk = priv->speed[MPC83XX_CLK_CSB];
364
365         return 0;
366 }
367
368 static int mpc83xx_clk_bind(struct udevice *dev)
369 {
370         int ret;
371         struct udevice *sys_child;
372
373         /*
374          * Since there is no corresponding device tree entry, and since the
375          * clock driver has to be present in either case, bind the sysreset
376          * driver here.
377          */
378         ret = device_bind_driver(dev, "mpc83xx_sysreset", "sysreset",
379                                  &sys_child);
380         if (ret)
381                 debug("%s: No sysreset driver: ret=%d\n",
382                       dev->name, ret);
383
384         return 0;
385 }
386
387 U_BOOT_DRIVER(mpc83xx_clk) = {
388         .name = "mpc83xx_clk",
389         .id = UCLASS_CLK,
390         .of_match = mpc83xx_clk_match,
391         .ops = &mpc83xx_clk_ops,
392         .probe = mpc83xx_clk_probe,
393         .priv_auto      = sizeof(struct mpc83xx_clk_priv),
394         .bind = mpc83xx_clk_bind,
395 };
396
397 static int do_clocks(struct cmd_tbl *cmdtp, int flag, int argc,
398                      char *const argv[])
399 {
400         int i;
401         char buf[32];
402         struct udevice *clk;
403         int ret;
404         struct mpc83xx_clk_priv *priv;
405
406         ret = uclass_first_device_err(UCLASS_CLK, &clk);
407         if (ret) {
408                 debug("%s: Could not get clock device\n", __func__);
409                 return ret;
410         }
411
412         for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
413                 if (!is_clk_valid(clk, i))
414                         continue;
415
416                 priv = dev_get_priv(clk);
417
418                 printf("%s = %s MHz\n", names[i], strmhz(buf, priv->speed[i]));
419         }
420
421         return 0;
422 }
423
424 U_BOOT_CMD(clocks,      1,      1,      do_clocks,
425            "display values of SoC's clocks",
426            ""
427 );