e5b07c73867f0f18f64689ea9a1bd12511972b0e
[oweals/u-boot.git] / drivers / clk / aspeed / clk_ast2500.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2016 Google, Inc
4  */
5
6 #include <common.h>
7 #include <clk-uclass.h>
8 #include <dm.h>
9 #include <log.h>
10 #include <asm/io.h>
11 #include <asm/arch/scu_ast2500.h>
12 #include <dm/lists.h>
13 #include <dt-bindings/clock/ast2500-scu.h>
14 #include <linux/err.h>
15
16 /*
17  * MAC Clock Delay settings, taken from Aspeed SDK
18  */
19 #define RGMII_TXCLK_ODLY                8
20 #define RMII_RXCLK_IDLY         2
21
22 /*
23  * TGMII Clock Duty constants, taken from Aspeed SDK
24  */
25 #define RGMII2_TXCK_DUTY        0x66
26 #define RGMII1_TXCK_DUTY        0x64
27
28 #define D2PLL_DEFAULT_RATE      (250 * 1000 * 1000)
29
30 DECLARE_GLOBAL_DATA_PTR;
31
32 /*
33  * Clock divider/multiplier configuration struct.
34  * For H-PLL and M-PLL the formula is
35  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
36  * M - Numerator
37  * N - Denumerator
38  * P - Post Divider
39  * They have the same layout in their control register.
40  *
41  * D-PLL and D2-PLL have extra divider (OD + 1), which is not
42  * yet needed and ignored by clock configurations.
43  */
44 struct ast2500_div_config {
45         unsigned int num;
46         unsigned int denum;
47         unsigned int post_div;
48 };
49
50 /*
51  * Get the rate of the M-PLL clock from input clock frequency and
52  * the value of the M-PLL Parameter Register.
53  */
54 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
55 {
56         const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
57         const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
58                         >> SCU_MPLL_DENUM_SHIFT;
59         const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
60                         >> SCU_MPLL_POST_SHIFT;
61
62         return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
63 }
64
65 /*
66  * Get the rate of the H-PLL clock from input clock frequency and
67  * the value of the H-PLL Parameter Register.
68  */
69 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
70 {
71         const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
72         const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
73                         >> SCU_HPLL_DENUM_SHIFT;
74         const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
75                         >> SCU_HPLL_POST_SHIFT;
76
77         return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
78 }
79
80 static ulong ast2500_get_clkin(struct ast2500_scu *scu)
81 {
82         return readl(&scu->hwstrap) & SCU_HWSTRAP_CLKIN_25MHZ
83                         ? 25 * 1000 * 1000 : 24 * 1000 * 1000;
84 }
85
86 /**
87  * Get current rate or uart clock
88  *
89  * @scu SCU registers
90  * @uart_index UART index, 1-5
91  *
92  * @return current setting for uart clock rate
93  */
94 static ulong ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_index)
95 {
96         /*
97          * ast2500 datasheet is very confusing when it comes to UART clocks,
98          * especially when CLKIN = 25 MHz. The settings are in
99          * different registers and it is unclear how they interact.
100          *
101          * This has only been tested with default settings and CLKIN = 24 MHz.
102          */
103         ulong uart_clkin;
104
105         if (readl(&scu->misc_ctrl2) &
106             (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT)))
107                 uart_clkin = 192 * 1000 * 1000;
108         else
109                 uart_clkin = 24 * 1000 * 1000;
110
111         if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
112                 uart_clkin /= 13;
113
114         return uart_clkin;
115 }
116
117 static ulong ast2500_clk_get_rate(struct clk *clk)
118 {
119         struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
120         ulong clkin = ast2500_get_clkin(priv->scu);
121         ulong rate;
122
123         switch (clk->id) {
124         case PLL_HPLL:
125         case ARMCLK:
126                 /*
127                  * This ignores dynamic/static slowdown of ARMCLK and may
128                  * be inaccurate.
129                  */
130                 rate = ast2500_get_hpll_rate(clkin,
131                                              readl(&priv->scu->h_pll_param));
132                 break;
133         case MCLK_DDR:
134                 rate = ast2500_get_mpll_rate(clkin,
135                                              readl(&priv->scu->m_pll_param));
136                 break;
137         case BCLK_PCLK:
138                 {
139                         ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
140                                                   & SCU_PCLK_DIV_MASK)
141                                                  >> SCU_PCLK_DIV_SHIFT);
142                         rate = ast2500_get_hpll_rate(clkin,
143                                                      readl(&priv->
144                                                            scu->h_pll_param));
145                         rate = rate / apb_div;
146                 }
147                 break;
148         case BCLK_SDCLK:
149                 {
150                         ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
151                                                   & SCU_SDCLK_DIV_MASK)
152                                                  >> SCU_SDCLK_DIV_SHIFT);
153                         rate = ast2500_get_hpll_rate(clkin,
154                                                      readl(&priv->
155                                                            scu->h_pll_param));
156                         rate = rate / apb_div;
157                 }
158                 break;
159         case PCLK_UART1:
160                 rate = ast2500_get_uart_clk_rate(priv->scu, 1);
161                 break;
162         case PCLK_UART2:
163                 rate = ast2500_get_uart_clk_rate(priv->scu, 2);
164                 break;
165         case PCLK_UART3:
166                 rate = ast2500_get_uart_clk_rate(priv->scu, 3);
167                 break;
168         case PCLK_UART4:
169                 rate = ast2500_get_uart_clk_rate(priv->scu, 4);
170                 break;
171         case PCLK_UART5:
172                 rate = ast2500_get_uart_clk_rate(priv->scu, 5);
173                 break;
174         default:
175                 return -ENOENT;
176         }
177
178         return rate;
179 }
180
181 struct ast2500_clock_config {
182         ulong input_rate;
183         ulong rate;
184         struct ast2500_div_config cfg;
185 };
186
187 static const struct ast2500_clock_config ast2500_clock_config_defaults[] = {
188         { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
189 };
190
191 static bool ast2500_get_clock_config_default(ulong input_rate,
192                                              ulong requested_rate,
193                                              struct ast2500_div_config *cfg)
194 {
195         int i;
196
197         for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) {
198                 const struct ast2500_clock_config *default_cfg =
199                         &ast2500_clock_config_defaults[i];
200                 if (default_cfg->input_rate == input_rate &&
201                     default_cfg->rate == requested_rate) {
202                         *cfg = default_cfg->cfg;
203                         return true;
204                 }
205         }
206
207         return false;
208 }
209
210 /*
211  * @input_rate - the rate of input clock in Hz
212  * @requested_rate - desired output rate in Hz
213  * @div - this is an IN/OUT parameter, at input all fields of the config
214  * need to be set to their maximum allowed values.
215  * The result (the best config we could find), would also be returned
216  * in this structure.
217  *
218  * @return The clock rate, when the resulting div_config is used.
219  */
220 static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
221                                        struct ast2500_div_config *cfg)
222 {
223         /*
224          * The assumption is that kHz precision is good enough and
225          * also enough to avoid overflow when multiplying.
226          */
227         const ulong input_rate_khz = input_rate / 1000;
228         const ulong rate_khz = requested_rate / 1000;
229         const struct ast2500_div_config max_vals = *cfg;
230         struct ast2500_div_config it = { 0, 0, 0 };
231         ulong delta = rate_khz;
232         ulong new_rate_khz = 0;
233
234         /*
235          * Look for a well known frequency first.
236          */
237         if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg))
238                 return requested_rate;
239
240         for (; it.denum <= max_vals.denum; ++it.denum) {
241                 for (it.post_div = 0; it.post_div <= max_vals.post_div;
242                      ++it.post_div) {
243                         it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
244                             * (it.denum + 1);
245                         if (it.num > max_vals.num)
246                                 continue;
247
248                         new_rate_khz = (input_rate_khz
249                                         * ((it.num + 1) / (it.denum + 1)))
250                             / (it.post_div + 1);
251
252                         /* Keep the rate below requested one. */
253                         if (new_rate_khz > rate_khz)
254                                 continue;
255
256                         if (new_rate_khz - rate_khz < delta) {
257                                 delta = new_rate_khz - rate_khz;
258                                 *cfg = it;
259                                 if (delta == 0)
260                                         return new_rate_khz * 1000;
261                         }
262                 }
263         }
264
265         return new_rate_khz * 1000;
266 }
267
268 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
269 {
270         ulong clkin = ast2500_get_clkin(scu);
271         u32 mpll_reg;
272         struct ast2500_div_config div_cfg = {
273                 .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
274                 .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
275                 .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
276         };
277
278         ast2500_calc_clock_config(clkin, rate, &div_cfg);
279
280         mpll_reg = readl(&scu->m_pll_param);
281         mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
282                       | SCU_MPLL_DENUM_MASK);
283         mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
284             | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
285             | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
286
287         ast_scu_unlock(scu);
288         writel(mpll_reg, &scu->m_pll_param);
289         ast_scu_lock(scu);
290
291         return ast2500_get_mpll_rate(clkin, mpll_reg);
292 }
293
294 static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
295 {
296         ulong clkin = ast2500_get_clkin(scu);
297         ulong hpll_rate = ast2500_get_hpll_rate(clkin,
298                                                 readl(&scu->h_pll_param));
299         ulong required_rate;
300         u32 hwstrap;
301         u32 divisor;
302         u32 reset_bit;
303         u32 clkstop_bit;
304
305         /*
306          * According to data sheet, for 10/100 mode the MAC clock frequency
307          * should be at least 25MHz and for 1000 mode at least 100MHz
308          */
309         hwstrap = readl(&scu->hwstrap);
310         if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
311                 required_rate = 100 * 1000 * 1000;
312         else
313                 required_rate = 25 * 1000 * 1000;
314
315         divisor = hpll_rate / required_rate;
316
317         if (divisor < 4) {
318                 /* Clock can't run fast enough, but let's try anyway */
319                 debug("MAC clock too slow\n");
320                 divisor = 4;
321         } else if (divisor > 16) {
322                 /* Can't slow down the clock enough, but let's try anyway */
323                 debug("MAC clock too fast\n");
324                 divisor = 16;
325         }
326
327         switch (index) {
328         case 1:
329                 reset_bit = SCU_SYSRESET_MAC1;
330                 clkstop_bit = SCU_CLKSTOP_MAC1;
331                 break;
332         case 2:
333                 reset_bit = SCU_SYSRESET_MAC2;
334                 clkstop_bit = SCU_CLKSTOP_MAC2;
335                 break;
336         default:
337                 return -EINVAL;
338         }
339
340         ast_scu_unlock(scu);
341         clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
342                         ((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
343
344         /*
345          * Disable MAC, start its clock and re-enable it.
346          * The procedure and the delays (100us & 10ms) are
347          * specified in the datasheet.
348          */
349         setbits_le32(&scu->sysreset_ctrl1, reset_bit);
350         udelay(100);
351         clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
352         mdelay(10);
353         clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
354
355         writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
356                | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
357                &scu->clk_duty_sel);
358
359         ast_scu_lock(scu);
360
361         return required_rate;
362 }
363
364 static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
365 {
366         /*
367          * The values and the meaning of the next three
368          * parameters are undocumented. Taken from Aspeed SDK.
369          *
370          * TODO(clg@kaod.org): the SIP and SIC values depend on the
371          * Numerator value
372          */
373         const u32 d2_pll_ext_param = 0x2c;
374         const u32 d2_pll_sip = 0x11;
375         const u32 d2_pll_sic = 0x18;
376         u32 clk_delay_settings =
377             (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
378             | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
379             | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
380             | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
381         struct ast2500_div_config div_cfg = {
382                 .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
383                 .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
384                 .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
385         };
386         ulong clkin = ast2500_get_clkin(scu);
387         ulong new_rate;
388
389         ast_scu_unlock(scu);
390         writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
391                | SCU_D2PLL_EXT1_OFF
392                | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
393
394         /*
395          * Select USB2.0 port1 PHY clock as a clock source for GCRT.
396          * This would disconnect it from D2-PLL.
397          */
398         clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
399                         SCU_MISC_GCRT_USB20CLK);
400
401         new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
402         writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
403                | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
404                | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
405                | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
406                | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
407                &scu->d2_pll_param);
408
409         clrbits_le32(&scu->d2_pll_ext_param[0],
410                      SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
411
412         clrsetbits_le32(&scu->misc_ctrl2,
413                         SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
414                         | SCU_MISC2_RGMII_CLKDIV_MASK |
415                         SCU_MISC2_RMII_CLKDIV_MASK,
416                         (4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
417
418         writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
419         writel(clk_delay_settings, &scu->mac_clk_delay_100M);
420         writel(clk_delay_settings, &scu->mac_clk_delay_10M);
421
422         ast_scu_lock(scu);
423
424         return new_rate;
425 }
426
427 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
428 {
429         struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
430
431         ulong new_rate;
432         switch (clk->id) {
433         case PLL_MPLL:
434         case MCLK_DDR:
435                 new_rate = ast2500_configure_ddr(priv->scu, rate);
436                 break;
437         case PLL_D2PLL:
438                 new_rate = ast2500_configure_d2pll(priv->scu, rate);
439                 break;
440         default:
441                 return -ENOENT;
442         }
443
444         return new_rate;
445 }
446
447 static int ast2500_clk_enable(struct clk *clk)
448 {
449         struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
450
451         switch (clk->id) {
452         case BCLK_SDCLK:
453                 if (readl(&priv->scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) {
454                         ast_scu_unlock(priv->scu);
455
456                         setbits_le32(&priv->scu->sysreset_ctrl1,
457                                      SCU_SYSRESET_SDIO);
458                         udelay(100);
459                         clrbits_le32(&priv->scu->clk_stop_ctrl1,
460                                      SCU_CLKSTOP_SDCLK);
461                         mdelay(10);
462                         clrbits_le32(&priv->scu->sysreset_ctrl1,
463                                      SCU_SYSRESET_SDIO);
464
465                         ast_scu_lock(priv->scu);
466                 }
467                 break;
468         /*
469          * For MAC clocks the clock rate is
470          * configured based on whether RGMII or RMII mode has been selected
471          * through hardware strapping.
472          */
473         case PCLK_MAC1:
474                 ast2500_configure_mac(priv->scu, 1);
475                 break;
476         case PCLK_MAC2:
477                 ast2500_configure_mac(priv->scu, 2);
478                 break;
479         case PLL_D2PLL:
480                 ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
481                 break;
482         default:
483                 return -ENOENT;
484         }
485
486         return 0;
487 }
488
489 struct clk_ops ast2500_clk_ops = {
490         .get_rate = ast2500_clk_get_rate,
491         .set_rate = ast2500_clk_set_rate,
492         .enable = ast2500_clk_enable,
493 };
494
495 static int ast2500_clk_ofdata_to_platdata(struct udevice *dev)
496 {
497         struct ast2500_clk_priv *priv = dev_get_priv(dev);
498
499         priv->scu = devfdt_get_addr_ptr(dev);
500         if (IS_ERR(priv->scu))
501                 return PTR_ERR(priv->scu);
502
503         return 0;
504 }
505
506 static int ast2500_clk_bind(struct udevice *dev)
507 {
508         int ret;
509
510         /* The reset driver does not have a device node, so bind it here */
511         ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
512         if (ret)
513                 debug("Warning: No reset driver: ret=%d\n", ret);
514
515         return 0;
516 }
517
518 static const struct udevice_id ast2500_clk_ids[] = {
519         { .compatible = "aspeed,ast2500-scu" },
520         { }
521 };
522
523 U_BOOT_DRIVER(aspeed_ast2500_scu) = {
524         .name           = "aspeed_ast2500_scu",
525         .id             = UCLASS_CLK,
526         .of_match       = ast2500_clk_ids,
527         .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
528         .ops            = &ast2500_clk_ops,
529         .bind           = ast2500_clk_bind,
530         .ofdata_to_platdata             = ast2500_clk_ofdata_to_platdata,
531 };