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