common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / clk / mediatek / clk-mtk.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * MediaTek common clock driver
4  *
5  * Copyright (C) 2018 MediaTek Inc.
6  * Author: Ryder Lee <ryder.lee@mediatek.com>
7  */
8
9 #include <common.h>
10 #include <clk-uclass.h>
11 #include <div64.h>
12 #include <dm.h>
13 #include <asm/io.h>
14 #include <linux/delay.h>
15
16 #include "clk-mtk.h"
17
18 #define REG_CON0                        0
19 #define REG_CON1                        4
20
21 #define CON0_BASE_EN                    BIT(0)
22 #define CON0_PWR_ON                     BIT(0)
23 #define CON0_ISO_EN                     BIT(1)
24 #define CON1_PCW_CHG                    BIT(31)
25
26 #define POSTDIV_MASK                    0x7
27 #define INTEGER_BITS                    7
28
29 /* scpsys clock off control */
30 #define CLK_SCP_CFG0                    0x200
31 #define CLK_SCP_CFG1                    0x204
32 #define SCP_ARMCK_OFF_EN                GENMASK(9, 0)
33 #define SCP_AXICK_DCM_DIS_EN            BIT(0)
34 #define SCP_AXICK_26M_SEL_EN            BIT(4)
35
36 /* shared functions */
37
38 /*
39  * In case the rate change propagation to parent clocks is undesirable,
40  * this function is recursively called to find the parent to calculate
41  * the accurate frequency.
42  */
43 static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
44                                       const struct driver *drv)
45 {
46         struct clk parent = { .id = id, };
47
48         if (drv) {
49                 struct udevice *dev;
50
51                 if (uclass_get_device_by_driver(UCLASS_CLK, drv, &dev))
52                         return -ENODEV;
53
54                 parent.dev = dev;
55         } else {
56                 parent.dev = clk->dev;
57         }
58
59         return clk_get_rate(&parent);
60 }
61
62 static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
63                                   const struct mtk_composite *mux)
64 {
65         u32 val, index = 0;
66
67         while (mux->parent[index] != parent)
68                 if (++index == mux->num_parents)
69                         return -EINVAL;
70
71         if (mux->flags & CLK_MUX_SETCLR_UPD) {
72                 val = (mux->mux_mask << mux->mux_shift);
73                 writel(val, base + mux->mux_clr_reg);
74
75                 val = (index << mux->mux_shift);
76                 writel(val, base + mux->mux_set_reg);
77
78                 if (mux->upd_shift >= 0)
79                         writel(BIT(mux->upd_shift), base + mux->upd_reg);
80         } else {
81                 /* switch mux to a select parent */
82                 val = readl(base + mux->mux_reg);
83                 val &= ~(mux->mux_mask << mux->mux_shift);
84
85                 val |= index << mux->mux_shift;
86                 writel(val, base + mux->mux_reg);
87         }
88
89         return 0;
90 }
91
92 /* apmixedsys functions */
93
94 static unsigned long __mtk_pll_recalc_rate(const struct mtk_pll_data *pll,
95                                            u32 fin, u32 pcw, int postdiv)
96 {
97         int pcwbits = pll->pcwbits;
98         int pcwfbits;
99         int ibits;
100         u64 vco;
101         u8 c = 0;
102
103         /* The fractional part of the PLL divider. */
104         ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS;
105         pcwfbits = pcwbits > ibits ? pcwbits - ibits : 0;
106
107         vco = (u64)fin * pcw;
108
109         if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
110                 c = 1;
111
112         vco >>= pcwfbits;
113
114         if (c)
115                 vco++;
116
117         return ((unsigned long)vco + postdiv - 1) / postdiv;
118 }
119
120 /**
121  * MediaTek PLLs are configured through their pcw value. The pcw value
122  * describes a divider in the PLL feedback loop which consists of 7 bits
123  * for the integer part and the remaining bits (if present) for the
124  * fractional part. Also they have a 3 bit power-of-two post divider.
125  */
126 static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
127 {
128         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
129         const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
130         u32 val, chg;
131
132         /* set postdiv */
133         val = readl(priv->base + pll->pd_reg);
134         val &= ~(POSTDIV_MASK << pll->pd_shift);
135         val |= (ffs(postdiv) - 1) << pll->pd_shift;
136
137         /* postdiv and pcw need to set at the same time if on same register */
138         if (pll->pd_reg != pll->pcw_reg) {
139                 writel(val, priv->base + pll->pd_reg);
140                 val = readl(priv->base + pll->pcw_reg);
141         }
142
143         /* set pcw */
144         val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift);
145         val |= pcw << pll->pcw_shift;
146
147         if (pll->pcw_chg_reg) {
148                 chg = readl(priv->base + pll->pcw_chg_reg);
149                 chg |= CON1_PCW_CHG;
150                 writel(val, priv->base + pll->pcw_reg);
151                 writel(chg, priv->base + pll->pcw_chg_reg);
152         } else {
153                 val |= CON1_PCW_CHG;
154                 writel(val, priv->base + pll->pcw_reg);
155         }
156
157         udelay(20);
158 }
159
160 /**
161  * mtk_pll_calc_values - calculate good values for a given input frequency.
162  * @clk:        The clk
163  * @pcw:        The pcw value (output)
164  * @postdiv:    The post divider (output)
165  * @freq:       The desired target frequency
166  */
167 static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
168                                 u32 freq)
169 {
170         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
171         const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
172         unsigned long fmin = pll->fmin ? pll->fmin : 1000 * MHZ;
173         u64 _pcw;
174         int ibits;
175         u32 val;
176
177         if (freq > pll->fmax)
178                 freq = pll->fmax;
179
180         for (val = 0; val < 5; val++) {
181                 *postdiv = 1 << val;
182                 if ((u64)freq * *postdiv >= fmin)
183                         break;
184         }
185
186         /* _pcw = freq * postdiv / xtal_rate * 2^pcwfbits */
187         ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS;
188         _pcw = ((u64)freq << val) << (pll->pcwbits - ibits);
189         do_div(_pcw, priv->tree->xtal2_rate);
190
191         *pcw = (u32)_pcw;
192 }
193
194 static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate)
195 {
196         u32 pcw = 0;
197         u32 postdiv;
198
199         mtk_pll_calc_values(clk, &pcw, &postdiv, rate);
200         mtk_pll_set_rate_regs(clk, pcw, postdiv);
201
202         return 0;
203 }
204
205 static ulong mtk_apmixedsys_get_rate(struct clk *clk)
206 {
207         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
208         const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
209         u32 postdiv;
210         u32 pcw;
211
212         postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) &
213                    POSTDIV_MASK;
214         postdiv = 1 << postdiv;
215
216         pcw = readl(priv->base + pll->pcw_reg) >> pll->pcw_shift;
217         pcw &= GENMASK(pll->pcwbits - 1, 0);
218
219         return __mtk_pll_recalc_rate(pll, priv->tree->xtal2_rate,
220                                      pcw, postdiv);
221 }
222
223 static int mtk_apmixedsys_enable(struct clk *clk)
224 {
225         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
226         const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
227         u32 r;
228
229         r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON;
230         writel(r, priv->base + pll->pwr_reg);
231         udelay(1);
232
233         r = readl(priv->base + pll->pwr_reg) & ~CON0_ISO_EN;
234         writel(r, priv->base + pll->pwr_reg);
235         udelay(1);
236
237         r = readl(priv->base + pll->reg + REG_CON0);
238         r |= pll->en_mask;
239         writel(r, priv->base + pll->reg + REG_CON0);
240
241         udelay(20);
242
243         if (pll->flags & HAVE_RST_BAR) {
244                 r = readl(priv->base + pll->reg + REG_CON0);
245                 r |= pll->rst_bar_mask;
246                 writel(r, priv->base + pll->reg + REG_CON0);
247         }
248
249         return 0;
250 }
251
252 static int mtk_apmixedsys_disable(struct clk *clk)
253 {
254         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
255         const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
256         u32 r;
257
258         if (pll->flags & HAVE_RST_BAR) {
259                 r = readl(priv->base + pll->reg + REG_CON0);
260                 r &= ~pll->rst_bar_mask;
261                 writel(r, priv->base + pll->reg + REG_CON0);
262         }
263
264         r = readl(priv->base + pll->reg + REG_CON0);
265         r &= ~CON0_BASE_EN;
266         writel(r, priv->base + pll->reg + REG_CON0);
267
268         r = readl(priv->base + pll->pwr_reg) | CON0_ISO_EN;
269         writel(r, priv->base + pll->pwr_reg);
270
271         r = readl(priv->base + pll->pwr_reg) & ~CON0_PWR_ON;
272         writel(r, priv->base + pll->pwr_reg);
273
274         return 0;
275 }
276
277 /* topckgen functions */
278
279 static ulong mtk_factor_recalc_rate(const struct mtk_fixed_factor *fdiv,
280                                     ulong parent_rate)
281 {
282         u64 rate = parent_rate * fdiv->mult;
283
284         do_div(rate, fdiv->div);
285
286         return rate;
287 }
288
289 static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
290 {
291         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
292         const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
293         ulong rate;
294
295         switch (fdiv->flags & CLK_PARENT_MASK) {
296         case CLK_PARENT_APMIXED:
297                 rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
298                                 DM_GET_DRIVER(mtk_clk_apmixedsys));
299                 break;
300         case CLK_PARENT_TOPCKGEN:
301                 rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
302                 break;
303
304         default:
305                 rate = priv->tree->xtal_rate;
306         }
307
308         return mtk_factor_recalc_rate(fdiv, rate);
309 }
310
311 static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
312 {
313         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
314         const struct mtk_composite *mux = &priv->tree->muxes[off];
315         u32 index;
316
317         index = readl(priv->base + mux->mux_reg);
318         index &= mux->mux_mask << mux->mux_shift;
319         index = index >> mux->mux_shift;
320
321         if (mux->parent[index])
322                 return mtk_clk_find_parent_rate(clk, mux->parent[index],
323                                                 NULL);
324
325         return priv->tree->xtal_rate;
326 }
327
328 static ulong mtk_topckgen_get_rate(struct clk *clk)
329 {
330         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
331
332         if (clk->id < priv->tree->fdivs_offs)
333                 return priv->tree->fclks[clk->id].rate;
334         else if (clk->id < priv->tree->muxes_offs)
335                 return mtk_topckgen_get_factor_rate(clk, clk->id -
336                                                     priv->tree->fdivs_offs);
337         else
338                 return mtk_topckgen_get_mux_rate(clk, clk->id -
339                                                  priv->tree->muxes_offs);
340 }
341
342 static int mtk_topckgen_enable(struct clk *clk)
343 {
344         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
345         const struct mtk_composite *mux;
346         u32 val;
347
348         if (clk->id < priv->tree->muxes_offs)
349                 return 0;
350
351         mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
352         if (mux->gate_shift < 0)
353                 return 0;
354
355         /* enable clock gate */
356         if (mux->flags & CLK_MUX_SETCLR_UPD) {
357                 val = BIT(mux->gate_shift);
358                 writel(val, priv->base + mux->mux_clr_reg);
359         } else {
360                 val = readl(priv->base + mux->gate_reg);
361                 val &= ~BIT(mux->gate_shift);
362                 writel(val, priv->base + mux->gate_reg);
363         }
364
365         if (mux->flags & CLK_DOMAIN_SCPSYS) {
366                 /* enable scpsys clock off control */
367                 writel(SCP_ARMCK_OFF_EN, priv->base + CLK_SCP_CFG0);
368                 writel(SCP_AXICK_DCM_DIS_EN | SCP_AXICK_26M_SEL_EN,
369                        priv->base + CLK_SCP_CFG1);
370         }
371
372         return 0;
373 }
374
375 static int mtk_topckgen_disable(struct clk *clk)
376 {
377         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
378         const struct mtk_composite *mux;
379         u32 val;
380
381         if (clk->id < priv->tree->muxes_offs)
382                 return 0;
383
384         mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
385         if (mux->gate_shift < 0)
386                 return 0;
387
388         /* disable clock gate */
389         if (mux->flags & CLK_MUX_SETCLR_UPD) {
390                 val = BIT(mux->gate_shift);
391                 writel(val, priv->base + mux->mux_set_reg);
392         } else {
393                 val = readl(priv->base + mux->gate_reg);
394                 val |= BIT(mux->gate_shift);
395                 writel(val, priv->base + mux->gate_reg);
396         }
397
398         return 0;
399 }
400
401 static int mtk_topckgen_set_parent(struct clk *clk, struct clk *parent)
402 {
403         struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
404
405         if (clk->id < priv->tree->muxes_offs)
406                 return 0;
407
408         return mtk_clk_mux_set_parent(priv->base, parent->id,
409                         &priv->tree->muxes[clk->id - priv->tree->muxes_offs]);
410 }
411
412 /* CG functions */
413
414 static int mtk_clk_gate_enable(struct clk *clk)
415 {
416         struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
417         const struct mtk_gate *gate = &priv->gates[clk->id];
418         u32 bit = BIT(gate->shift);
419
420         switch (gate->flags & CLK_GATE_MASK) {
421         case CLK_GATE_SETCLR:
422                 writel(bit, priv->base + gate->regs->clr_ofs);
423                 break;
424         case CLK_GATE_SETCLR_INV:
425                 writel(bit, priv->base + gate->regs->set_ofs);
426                 break;
427         case CLK_GATE_NO_SETCLR:
428                 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
429                 break;
430         case CLK_GATE_NO_SETCLR_INV:
431                 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
432                 break;
433
434         default:
435                 return -EINVAL;
436         }
437
438         return 0;
439 }
440
441 static int mtk_clk_gate_disable(struct clk *clk)
442 {
443         struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
444         const struct mtk_gate *gate = &priv->gates[clk->id];
445         u32 bit = BIT(gate->shift);
446
447         switch (gate->flags & CLK_GATE_MASK) {
448         case CLK_GATE_SETCLR:
449                 writel(bit, priv->base + gate->regs->set_ofs);
450                 break;
451         case CLK_GATE_SETCLR_INV:
452                 writel(bit, priv->base + gate->regs->clr_ofs);
453                 break;
454         case CLK_GATE_NO_SETCLR:
455                 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
456                 break;
457         case CLK_GATE_NO_SETCLR_INV:
458                 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
459                 break;
460
461         default:
462                 return -EINVAL;
463         }
464
465         return 0;
466 }
467
468 static ulong mtk_clk_gate_get_rate(struct clk *clk)
469 {
470         struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
471         const struct mtk_gate *gate = &priv->gates[clk->id];
472
473         switch (gate->flags & CLK_PARENT_MASK) {
474         case CLK_PARENT_APMIXED:
475                 return mtk_clk_find_parent_rate(clk, gate->parent,
476                                 DM_GET_DRIVER(mtk_clk_apmixedsys));
477                 break;
478         case CLK_PARENT_TOPCKGEN:
479                 return mtk_clk_find_parent_rate(clk, gate->parent,
480                                 DM_GET_DRIVER(mtk_clk_topckgen));
481                 break;
482
483         default:
484                 return priv->tree->xtal_rate;
485         }
486 }
487
488 const struct clk_ops mtk_clk_apmixedsys_ops = {
489         .enable = mtk_apmixedsys_enable,
490         .disable = mtk_apmixedsys_disable,
491         .set_rate = mtk_apmixedsys_set_rate,
492         .get_rate = mtk_apmixedsys_get_rate,
493 };
494
495 const struct clk_ops mtk_clk_topckgen_ops = {
496         .enable = mtk_topckgen_enable,
497         .disable = mtk_topckgen_disable,
498         .get_rate = mtk_topckgen_get_rate,
499         .set_parent = mtk_topckgen_set_parent,
500 };
501
502 const struct clk_ops mtk_clk_gate_ops = {
503         .enable = mtk_clk_gate_enable,
504         .disable = mtk_clk_gate_disable,
505         .get_rate = mtk_clk_gate_get_rate,
506 };
507
508 int mtk_common_clk_init(struct udevice *dev,
509                         const struct mtk_clk_tree *tree)
510 {
511         struct mtk_clk_priv *priv = dev_get_priv(dev);
512
513         priv->base = dev_read_addr_ptr(dev);
514         if (!priv->base)
515                 return -ENOENT;
516
517         priv->tree = tree;
518
519         return 0;
520 }
521
522 int mtk_common_clk_gate_init(struct udevice *dev,
523                              const struct mtk_clk_tree *tree,
524                              const struct mtk_gate *gates)
525 {
526         struct mtk_cg_priv *priv = dev_get_priv(dev);
527
528         priv->base = dev_read_addr_ptr(dev);
529         if (!priv->base)
530                 return -ENOENT;
531
532         priv->tree = tree;
533         priv->gates = gates;
534
535         return 0;
536 }