blob: d2c45be30decb552ce3bb435c6468919c3832b8b [file] [log] [blame]
developer2186c982018-11-15 10:07:54 +08001// 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
developer2186c982018-11-15 10:07:54 +08009#include <clk-uclass.h>
10#include <div64.h>
11#include <dm.h>
12#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060013#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
developer2186c982018-11-15 10:07:54 +080015
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 */
developer65da8e72020-01-10 16:30:30 +080043static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
developerfd47f762022-09-09 20:00:01 +080044 struct udevice *pdev)
developer2186c982018-11-15 10:07:54 +080045{
46 struct clk parent = { .id = id, };
47
developerfd47f762022-09-09 20:00:01 +080048 if (pdev)
49 parent.dev = pdev;
50 else
developer2186c982018-11-15 10:07:54 +080051 parent.dev = clk->dev;
developer2186c982018-11-15 10:07:54 +080052
53 return clk_get_rate(&parent);
54}
55
56static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
57 const struct mtk_composite *mux)
58{
59 u32 val, index = 0;
60
61 while (mux->parent[index] != parent)
62 if (++index == mux->num_parents)
63 return -EINVAL;
64
developerba560c72019-12-31 11:29:21 +080065 if (mux->flags & CLK_MUX_SETCLR_UPD) {
66 val = (mux->mux_mask << mux->mux_shift);
67 writel(val, base + mux->mux_clr_reg);
developer2186c982018-11-15 10:07:54 +080068
developerba560c72019-12-31 11:29:21 +080069 val = (index << mux->mux_shift);
70 writel(val, base + mux->mux_set_reg);
71
72 if (mux->upd_shift >= 0)
73 writel(BIT(mux->upd_shift), base + mux->upd_reg);
74 } else {
75 /* switch mux to a select parent */
76 val = readl(base + mux->mux_reg);
77 val &= ~(mux->mux_mask << mux->mux_shift);
78
79 val |= index << mux->mux_shift;
80 writel(val, base + mux->mux_reg);
81 }
developer2186c982018-11-15 10:07:54 +080082
83 return 0;
84}
85
86/* apmixedsys functions */
87
88static unsigned long __mtk_pll_recalc_rate(const struct mtk_pll_data *pll,
89 u32 fin, u32 pcw, int postdiv)
90{
91 int pcwbits = pll->pcwbits;
92 int pcwfbits;
developer0b5e5f12019-12-31 11:29:22 +080093 int ibits;
developer2186c982018-11-15 10:07:54 +080094 u64 vco;
95 u8 c = 0;
96
97 /* The fractional part of the PLL divider. */
developer0b5e5f12019-12-31 11:29:22 +080098 ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS;
99 pcwfbits = pcwbits > ibits ? pcwbits - ibits : 0;
developer2186c982018-11-15 10:07:54 +0800100
101 vco = (u64)fin * pcw;
102
103 if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
104 c = 1;
105
106 vco >>= pcwfbits;
107
108 if (c)
109 vco++;
110
111 return ((unsigned long)vco + postdiv - 1) / postdiv;
112}
113
114/**
115 * MediaTek PLLs are configured through their pcw value. The pcw value
116 * describes a divider in the PLL feedback loop which consists of 7 bits
117 * for the integer part and the remaining bits (if present) for the
118 * fractional part. Also they have a 3 bit power-of-two post divider.
119 */
120static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
121{
122 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
123 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
developer0b5e5f12019-12-31 11:29:22 +0800124 u32 val, chg;
developer2186c982018-11-15 10:07:54 +0800125
126 /* set postdiv */
127 val = readl(priv->base + pll->pd_reg);
128 val &= ~(POSTDIV_MASK << pll->pd_shift);
129 val |= (ffs(postdiv) - 1) << pll->pd_shift;
130
131 /* postdiv and pcw need to set at the same time if on same register */
132 if (pll->pd_reg != pll->pcw_reg) {
133 writel(val, priv->base + pll->pd_reg);
134 val = readl(priv->base + pll->pcw_reg);
135 }
136
137 /* set pcw */
138 val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift);
139 val |= pcw << pll->pcw_shift;
developer2186c982018-11-15 10:07:54 +0800140
developer0b5e5f12019-12-31 11:29:22 +0800141 if (pll->pcw_chg_reg) {
142 chg = readl(priv->base + pll->pcw_chg_reg);
143 chg |= CON1_PCW_CHG;
144 writel(val, priv->base + pll->pcw_reg);
145 writel(chg, priv->base + pll->pcw_chg_reg);
146 } else {
147 val |= CON1_PCW_CHG;
148 writel(val, priv->base + pll->pcw_reg);
149 }
developer2186c982018-11-15 10:07:54 +0800150
151 udelay(20);
152}
153
154/**
155 * mtk_pll_calc_values - calculate good values for a given input frequency.
156 * @clk: The clk
157 * @pcw: The pcw value (output)
158 * @postdiv: The post divider (output)
159 * @freq: The desired target frequency
160 */
161static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
162 u32 freq)
163{
164 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
165 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
developer0b5e5f12019-12-31 11:29:22 +0800166 unsigned long fmin = pll->fmin ? pll->fmin : 1000 * MHZ;
developer2186c982018-11-15 10:07:54 +0800167 u64 _pcw;
developer0b5e5f12019-12-31 11:29:22 +0800168 int ibits;
developer2186c982018-11-15 10:07:54 +0800169 u32 val;
170
171 if (freq > pll->fmax)
172 freq = pll->fmax;
173
174 for (val = 0; val < 5; val++) {
175 *postdiv = 1 << val;
176 if ((u64)freq * *postdiv >= fmin)
177 break;
178 }
179
180 /* _pcw = freq * postdiv / xtal_rate * 2^pcwfbits */
developer0b5e5f12019-12-31 11:29:22 +0800181 ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS;
182 _pcw = ((u64)freq << val) << (pll->pcwbits - ibits);
developer2186c982018-11-15 10:07:54 +0800183 do_div(_pcw, priv->tree->xtal2_rate);
184
185 *pcw = (u32)_pcw;
186}
187
188static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate)
189{
190 u32 pcw = 0;
191 u32 postdiv;
192
193 mtk_pll_calc_values(clk, &pcw, &postdiv, rate);
194 mtk_pll_set_rate_regs(clk, pcw, postdiv);
195
196 return 0;
197}
198
199static ulong mtk_apmixedsys_get_rate(struct clk *clk)
200{
201 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
202 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
203 u32 postdiv;
204 u32 pcw;
205
206 postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) &
207 POSTDIV_MASK;
208 postdiv = 1 << postdiv;
209
210 pcw = readl(priv->base + pll->pcw_reg) >> pll->pcw_shift;
211 pcw &= GENMASK(pll->pcwbits - 1, 0);
212
213 return __mtk_pll_recalc_rate(pll, priv->tree->xtal2_rate,
214 pcw, postdiv);
215}
216
217static int mtk_apmixedsys_enable(struct clk *clk)
218{
219 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
220 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
221 u32 r;
222
223 r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON;
224 writel(r, priv->base + pll->pwr_reg);
225 udelay(1);
226
227 r = readl(priv->base + pll->pwr_reg) & ~CON0_ISO_EN;
228 writel(r, priv->base + pll->pwr_reg);
229 udelay(1);
230
231 r = readl(priv->base + pll->reg + REG_CON0);
232 r |= pll->en_mask;
233 writel(r, priv->base + pll->reg + REG_CON0);
234
235 udelay(20);
236
237 if (pll->flags & HAVE_RST_BAR) {
238 r = readl(priv->base + pll->reg + REG_CON0);
239 r |= pll->rst_bar_mask;
240 writel(r, priv->base + pll->reg + REG_CON0);
241 }
242
243 return 0;
244}
245
246static int mtk_apmixedsys_disable(struct clk *clk)
247{
248 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
249 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
250 u32 r;
251
252 if (pll->flags & HAVE_RST_BAR) {
253 r = readl(priv->base + pll->reg + REG_CON0);
254 r &= ~pll->rst_bar_mask;
255 writel(r, priv->base + pll->reg + REG_CON0);
256 }
257
258 r = readl(priv->base + pll->reg + REG_CON0);
259 r &= ~CON0_BASE_EN;
260 writel(r, priv->base + pll->reg + REG_CON0);
261
262 r = readl(priv->base + pll->pwr_reg) | CON0_ISO_EN;
263 writel(r, priv->base + pll->pwr_reg);
264
265 r = readl(priv->base + pll->pwr_reg) & ~CON0_PWR_ON;
266 writel(r, priv->base + pll->pwr_reg);
267
268 return 0;
269}
270
271/* topckgen functions */
272
273static ulong mtk_factor_recalc_rate(const struct mtk_fixed_factor *fdiv,
274 ulong parent_rate)
275{
276 u64 rate = parent_rate * fdiv->mult;
277
278 do_div(rate, fdiv->div);
279
280 return rate;
281}
282
developer65da8e72020-01-10 16:30:30 +0800283static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
developer2186c982018-11-15 10:07:54 +0800284{
285 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
286 const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
287 ulong rate;
288
289 switch (fdiv->flags & CLK_PARENT_MASK) {
290 case CLK_PARENT_APMIXED:
291 rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
developerfd47f762022-09-09 20:00:01 +0800292 priv->parent);
developer2186c982018-11-15 10:07:54 +0800293 break;
294 case CLK_PARENT_TOPCKGEN:
295 rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
296 break;
297
developerf724f112022-09-09 20:00:07 +0800298 case CLK_PARENT_XTAL:
developer2186c982018-11-15 10:07:54 +0800299 default:
300 rate = priv->tree->xtal_rate;
301 }
302
303 return mtk_factor_recalc_rate(fdiv, rate);
304}
305
developerad5b0752022-09-09 20:00:04 +0800306static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
307{
308 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
309 const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
310 ulong rate;
311
312 switch (fdiv->flags & CLK_PARENT_MASK) {
313 case CLK_PARENT_TOPCKGEN:
314 rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
315 priv->parent);
316 break;
developerf724f112022-09-09 20:00:07 +0800317 case CLK_PARENT_XTAL:
318 rate = priv->tree->xtal_rate;
319 break;
developerad5b0752022-09-09 20:00:04 +0800320 default:
321 rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
322 }
323
324 return mtk_factor_recalc_rate(fdiv, rate);
325}
326
developer65da8e72020-01-10 16:30:30 +0800327static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
developer2186c982018-11-15 10:07:54 +0800328{
329 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
330 const struct mtk_composite *mux = &priv->tree->muxes[off];
331 u32 index;
332
333 index = readl(priv->base + mux->mux_reg);
334 index &= mux->mux_mask << mux->mux_shift;
335 index = index >> mux->mux_shift;
336
developer2dc4caa2022-09-09 19:59:59 +0800337 if (mux->parent[index] > 0 ||
338 (mux->parent[index] == CLK_XTAL &&
developerfd47f762022-09-09 20:00:01 +0800339 priv->tree->flags & CLK_BYPASS_XTAL)) {
340 switch (mux->flags & CLK_PARENT_MASK) {
341 case CLK_PARENT_APMIXED:
342 return mtk_clk_find_parent_rate(clk, mux->parent[index],
343 priv->parent);
344 break;
345 default:
346 return mtk_clk_find_parent_rate(clk, mux->parent[index],
347 NULL);
348 break;
349 }
350 }
developer2186c982018-11-15 10:07:54 +0800351
352 return priv->tree->xtal_rate;
353}
354
developerad5b0752022-09-09 20:00:04 +0800355static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
356{
357 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
358 const struct mtk_composite *mux = &priv->tree->muxes[off];
359 u32 index;
360
361 index = readl(priv->base + mux->mux_reg);
362 index &= mux->mux_mask << mux->mux_shift;
363 index = index >> mux->mux_shift;
364
365 if (mux->parent[index] > 0 ||
366 (mux->parent[index] == CLK_XTAL &&
367 priv->tree->flags & CLK_BYPASS_XTAL)) {
368 switch (mux->flags & CLK_PARENT_MASK) {
369 case CLK_PARENT_TOPCKGEN:
370 return mtk_clk_find_parent_rate(clk, mux->parent[index],
371 priv->parent);
372 break;
373 default:
374 return mtk_clk_find_parent_rate(clk, mux->parent[index],
375 NULL);
376 break;
377 }
378 }
379 return 0;
380}
381
developer2186c982018-11-15 10:07:54 +0800382static ulong mtk_topckgen_get_rate(struct clk *clk)
383{
384 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
385
386 if (clk->id < priv->tree->fdivs_offs)
387 return priv->tree->fclks[clk->id].rate;
388 else if (clk->id < priv->tree->muxes_offs)
389 return mtk_topckgen_get_factor_rate(clk, clk->id -
390 priv->tree->fdivs_offs);
391 else
392 return mtk_topckgen_get_mux_rate(clk, clk->id -
393 priv->tree->muxes_offs);
developerad5b0752022-09-09 20:00:04 +0800394}
395
396static ulong mtk_infrasys_get_rate(struct clk *clk)
397{
398 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
399
400 ulong rate;
401
402 if (clk->id < priv->tree->fdivs_offs) {
403 rate = priv->tree->fclks[clk->id].rate;
404 } else if (clk->id < priv->tree->muxes_offs) {
405 rate = mtk_infrasys_get_factor_rate(clk, clk->id -
406 priv->tree->fdivs_offs);
407 } else {
408 rate = mtk_infrasys_get_mux_rate(clk, clk->id -
409 priv->tree->muxes_offs);
410 }
411
412 return rate;
developer2186c982018-11-15 10:07:54 +0800413}
414
developerfd47f762022-09-09 20:00:01 +0800415static int mtk_clk_mux_enable(struct clk *clk)
developer2186c982018-11-15 10:07:54 +0800416{
417 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
418 const struct mtk_composite *mux;
419 u32 val;
420
421 if (clk->id < priv->tree->muxes_offs)
422 return 0;
423
424 mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
425 if (mux->gate_shift < 0)
426 return 0;
427
428 /* enable clock gate */
developerba560c72019-12-31 11:29:21 +0800429 if (mux->flags & CLK_MUX_SETCLR_UPD) {
430 val = BIT(mux->gate_shift);
431 writel(val, priv->base + mux->mux_clr_reg);
432 } else {
433 val = readl(priv->base + mux->gate_reg);
434 val &= ~BIT(mux->gate_shift);
435 writel(val, priv->base + mux->gate_reg);
436 }
developer2186c982018-11-15 10:07:54 +0800437
438 if (mux->flags & CLK_DOMAIN_SCPSYS) {
439 /* enable scpsys clock off control */
440 writel(SCP_ARMCK_OFF_EN, priv->base + CLK_SCP_CFG0);
441 writel(SCP_AXICK_DCM_DIS_EN | SCP_AXICK_26M_SEL_EN,
442 priv->base + CLK_SCP_CFG1);
443 }
444
445 return 0;
446}
447
developerfd47f762022-09-09 20:00:01 +0800448static int mtk_clk_mux_disable(struct clk *clk)
developer2186c982018-11-15 10:07:54 +0800449{
450 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
451 const struct mtk_composite *mux;
452 u32 val;
453
454 if (clk->id < priv->tree->muxes_offs)
455 return 0;
456
457 mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
458 if (mux->gate_shift < 0)
459 return 0;
460
461 /* disable clock gate */
developerba560c72019-12-31 11:29:21 +0800462 if (mux->flags & CLK_MUX_SETCLR_UPD) {
463 val = BIT(mux->gate_shift);
464 writel(val, priv->base + mux->mux_set_reg);
465 } else {
466 val = readl(priv->base + mux->gate_reg);
467 val |= BIT(mux->gate_shift);
468 writel(val, priv->base + mux->gate_reg);
469 }
developer2186c982018-11-15 10:07:54 +0800470
471 return 0;
472}
473
developerfd47f762022-09-09 20:00:01 +0800474static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
developer2186c982018-11-15 10:07:54 +0800475{
476 struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
477
478 if (clk->id < priv->tree->muxes_offs)
479 return 0;
480
481 return mtk_clk_mux_set_parent(priv->base, parent->id,
482 &priv->tree->muxes[clk->id - priv->tree->muxes_offs]);
483}
484
485/* CG functions */
486
487static int mtk_clk_gate_enable(struct clk *clk)
488{
489 struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
490 const struct mtk_gate *gate = &priv->gates[clk->id];
491 u32 bit = BIT(gate->shift);
492
493 switch (gate->flags & CLK_GATE_MASK) {
494 case CLK_GATE_SETCLR:
495 writel(bit, priv->base + gate->regs->clr_ofs);
496 break;
Fabien Parent69463e52019-03-24 16:46:35 +0100497 case CLK_GATE_SETCLR_INV:
498 writel(bit, priv->base + gate->regs->set_ofs);
499 break;
500 case CLK_GATE_NO_SETCLR:
501 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
502 break;
developer2186c982018-11-15 10:07:54 +0800503 case CLK_GATE_NO_SETCLR_INV:
504 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
505 break;
506
507 default:
508 return -EINVAL;
509 }
510
511 return 0;
512}
513
514static int mtk_clk_gate_disable(struct clk *clk)
515{
516 struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
517 const struct mtk_gate *gate = &priv->gates[clk->id];
518 u32 bit = BIT(gate->shift);
519
520 switch (gate->flags & CLK_GATE_MASK) {
521 case CLK_GATE_SETCLR:
522 writel(bit, priv->base + gate->regs->set_ofs);
523 break;
Fabien Parent69463e52019-03-24 16:46:35 +0100524 case CLK_GATE_SETCLR_INV:
525 writel(bit, priv->base + gate->regs->clr_ofs);
526 break;
527 case CLK_GATE_NO_SETCLR:
528 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
529 break;
developer2186c982018-11-15 10:07:54 +0800530 case CLK_GATE_NO_SETCLR_INV:
531 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
532 break;
533
534 default:
535 return -EINVAL;
536 }
537
538 return 0;
539}
540
541static ulong mtk_clk_gate_get_rate(struct clk *clk)
542{
543 struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
544 const struct mtk_gate *gate = &priv->gates[clk->id];
545
developerfd47f762022-09-09 20:00:01 +0800546 return mtk_clk_find_parent_rate(clk, gate->parent, priv->parent);
developer2186c982018-11-15 10:07:54 +0800547}
548
549const struct clk_ops mtk_clk_apmixedsys_ops = {
550 .enable = mtk_apmixedsys_enable,
551 .disable = mtk_apmixedsys_disable,
552 .set_rate = mtk_apmixedsys_set_rate,
553 .get_rate = mtk_apmixedsys_get_rate,
554};
555
556const struct clk_ops mtk_clk_topckgen_ops = {
developerfd47f762022-09-09 20:00:01 +0800557 .enable = mtk_clk_mux_enable,
558 .disable = mtk_clk_mux_disable,
developer2186c982018-11-15 10:07:54 +0800559 .get_rate = mtk_topckgen_get_rate,
developerfd47f762022-09-09 20:00:01 +0800560 .set_parent = mtk_common_clk_set_parent,
developer2186c982018-11-15 10:07:54 +0800561};
562
developerad5b0752022-09-09 20:00:04 +0800563const struct clk_ops mtk_clk_infrasys_ops = {
564 .enable = mtk_clk_mux_enable,
565 .disable = mtk_clk_mux_disable,
566 .get_rate = mtk_infrasys_get_rate,
567 .set_parent = mtk_common_clk_set_parent,
568};
569
developer2186c982018-11-15 10:07:54 +0800570const struct clk_ops mtk_clk_gate_ops = {
571 .enable = mtk_clk_gate_enable,
572 .disable = mtk_clk_gate_disable,
573 .get_rate = mtk_clk_gate_get_rate,
574};
575
576int mtk_common_clk_init(struct udevice *dev,
577 const struct mtk_clk_tree *tree)
578{
579 struct mtk_clk_priv *priv = dev_get_priv(dev);
developerfd47f762022-09-09 20:00:01 +0800580 struct udevice *parent;
581 int ret;
developer2186c982018-11-15 10:07:54 +0800582
583 priv->base = dev_read_addr_ptr(dev);
584 if (!priv->base)
585 return -ENOENT;
586
developerfd47f762022-09-09 20:00:01 +0800587 ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
588 if (ret || !parent) {
589 ret = uclass_get_device_by_driver(UCLASS_CLK,
590 DM_DRIVER_GET(mtk_clk_apmixedsys), &parent);
591 if (ret || !parent)
592 return -ENOENT;
593 }
594
595 priv->parent = parent;
developer2186c982018-11-15 10:07:54 +0800596 priv->tree = tree;
597
598 return 0;
599}
600
601int mtk_common_clk_gate_init(struct udevice *dev,
602 const struct mtk_clk_tree *tree,
603 const struct mtk_gate *gates)
604{
605 struct mtk_cg_priv *priv = dev_get_priv(dev);
developerfd47f762022-09-09 20:00:01 +0800606 struct udevice *parent;
607 int ret;
developer2186c982018-11-15 10:07:54 +0800608
609 priv->base = dev_read_addr_ptr(dev);
610 if (!priv->base)
611 return -ENOENT;
612
developerfd47f762022-09-09 20:00:01 +0800613 ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
614 if (ret || !parent) {
615 ret = uclass_get_device_by_driver(UCLASS_CLK,
616 DM_DRIVER_GET(mtk_clk_topckgen), &parent);
617 if (ret || !parent)
618 return -ENOENT;
619 }
620
621 priv->parent = parent;
developer2186c982018-11-15 10:07:54 +0800622 priv->tree = tree;
623 priv->gates = gates;
624
625 return 0;
626}