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