Skip to content

Commit 238cc63

Browse files
ziyao233pdp7
authored andcommitted
clk: thead: th1520-ap: Support setting PLL rates
TH1520 ships several PLLs that could operate in either integer or fractional mode. However, the TRM only lists a few configuration whose stability is considered guaranteed. Add a table-lookup rate determination logic to support PLL rate setting, and fill up frequency-configuration tables for AP-subsystem PLLs. Reviewed-by: Drew Fustini <fustini@kernel.org> Signed-off-by: Yao Zi <ziyao@disroot.org> Signed-off-by: Drew Fustini <fustini@kernel.org>
1 parent b436f8a commit 238cc63

1 file changed

Lines changed: 142 additions & 0 deletions

File tree

drivers/clk/thead/clk-th1520-ap.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define TH1520_PLL_REFDIV GENMASK(5, 0)
2323
#define TH1520_PLL_BYPASS BIT(30)
2424
#define TH1520_PLL_VCO_RST BIT(29)
25+
#define TH1520_PLL_DACPD BIT(25)
2526
#define TH1520_PLL_DSMPD BIT(24)
2627
#define TH1520_PLL_FRAC GENMASK(23, 0)
2728
#define TH1520_PLL_FRAC_BITS 24
@@ -72,9 +73,19 @@ struct ccu_div {
7273
struct ccu_common common;
7374
};
7475

76+
struct ccu_pll_cfg {
77+
unsigned long freq;
78+
u32 fbdiv;
79+
u32 frac;
80+
u32 postdiv1;
81+
u32 postdiv2;
82+
};
83+
7584
struct ccu_pll {
7685
struct ccu_common common;
7786
u32 lock_sts_mask;
87+
int cfgnum;
88+
const struct ccu_pll_cfg *cfgs;
7889
};
7990

8091
#define TH_CCU_ARG(_shift, _width) \
@@ -391,17 +402,102 @@ static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
391402
return rate;
392403
}
393404

405+
static const struct ccu_pll_cfg *ccu_pll_lookup_best_cfg(struct ccu_pll *pll,
406+
unsigned long rate)
407+
{
408+
unsigned long best_delta = ULONG_MAX;
409+
const struct ccu_pll_cfg *best_cfg;
410+
int i;
411+
412+
for (i = 0; i < pll->cfgnum; i++) {
413+
const struct ccu_pll_cfg *cfg = &pll->cfgs[i];
414+
unsigned long delta;
415+
416+
delta = abs_diff(cfg->freq, rate);
417+
if (delta < best_delta) {
418+
best_delta = delta;
419+
best_cfg = cfg;
420+
}
421+
}
422+
423+
return best_cfg;
424+
}
425+
426+
static int ccu_pll_determine_rate(struct clk_hw *hw,
427+
struct clk_rate_request *req)
428+
{
429+
struct ccu_pll *pll = hw_to_ccu_pll(hw);
430+
431+
req->rate = ccu_pll_lookup_best_cfg(pll, req->rate)->freq;
432+
433+
return 0;
434+
}
435+
436+
static int ccu_pll_set_rate(struct clk_hw *hw, unsigned long rate,
437+
unsigned long parent_rate)
438+
{
439+
struct ccu_pll *pll = hw_to_ccu_pll(hw);
440+
const struct ccu_pll_cfg *cfg;
441+
442+
cfg = ccu_pll_lookup_best_cfg(pll, rate);
443+
444+
ccu_pll_disable(hw);
445+
446+
regmap_write(pll->common.map, pll->common.cfg0,
447+
FIELD_PREP(TH1520_PLL_REFDIV, 1) |
448+
FIELD_PREP(TH1520_PLL_FBDIV, cfg->fbdiv) |
449+
FIELD_PREP(TH1520_PLL_POSTDIV1, cfg->postdiv1) |
450+
FIELD_PREP(TH1520_PLL_POSTDIV2, cfg->postdiv2));
451+
452+
regmap_update_bits(pll->common.map, pll->common.cfg1,
453+
TH1520_PLL_DACPD | TH1520_PLL_DSMPD |
454+
TH1520_PLL_FRAC,
455+
cfg->frac ? cfg->frac :
456+
TH1520_PLL_DACPD | TH1520_PLL_DSMPD);
457+
458+
return ccu_pll_enable(hw);
459+
}
460+
394461
static const struct clk_ops clk_pll_ops = {
395462
.disable = ccu_pll_disable,
396463
.enable = ccu_pll_enable,
397464
.is_enabled = ccu_pll_is_enabled,
398465
.recalc_rate = ccu_pll_recalc_rate,
466+
.determine_rate = ccu_pll_determine_rate,
467+
.set_rate = ccu_pll_set_rate,
399468
};
400469

401470
static const struct clk_parent_data osc_24m_clk[] = {
402471
{ .index = 0 }
403472
};
404473

474+
static const struct ccu_pll_cfg cpu_pll_cfgs[] = {
475+
{ 125000000, 125, 0, 6, 4 },
476+
{ 200000000, 125, 0, 5, 3 },
477+
{ 300000000, 125, 0, 5, 2 },
478+
{ 400000000, 100, 0, 3, 2 },
479+
{ 500000000, 125, 0, 6, 1 },
480+
{ 600000000, 125, 0, 5, 1 },
481+
{ 702000000, 117, 0, 4, 1 },
482+
{ 800000000, 100, 0, 3, 1 },
483+
{ 900000000, 75, 0, 2, 1 },
484+
{ 1000000000, 125, 0, 3, 1 },
485+
{ 1104000000, 92, 0, 2, 1 },
486+
{ 1200000000, 100, 0, 2, 1 },
487+
{ 1296000000, 108, 0, 2, 1 },
488+
{ 1404000000, 117, 0, 2, 1 },
489+
{ 1500000000, 125, 0, 2, 1 },
490+
{ 1608000000, 67, 0, 1, 1 },
491+
{ 1704000000, 71, 0, 1, 1 },
492+
{ 1800000000, 75, 0, 1, 1 },
493+
{ 1896000000, 79, 0, 1, 1 },
494+
{ 1992000000, 83, 0, 1, 1 },
495+
{ 2112000000, 88, 0, 1, 1 },
496+
{ 2208000000, 92, 0, 1, 1 },
497+
{ 2304000000, 96, 0, 1, 1 },
498+
{ 2400000000, 100, 0, 1, 1 },
499+
};
500+
405501
static struct ccu_pll cpu_pll0_clk = {
406502
.common = {
407503
.clkid = CLK_CPU_PLL0,
@@ -413,6 +509,8 @@ static struct ccu_pll cpu_pll0_clk = {
413509
CLK_IS_CRITICAL),
414510
},
415511
.lock_sts_mask = BIT(1),
512+
.cfgnum = ARRAY_SIZE(cpu_pll_cfgs),
513+
.cfgs = cpu_pll_cfgs,
416514
};
417515

418516
static struct ccu_pll cpu_pll1_clk = {
@@ -426,6 +524,16 @@ static struct ccu_pll cpu_pll1_clk = {
426524
CLK_IS_CRITICAL),
427525
},
428526
.lock_sts_mask = BIT(4),
527+
.cfgnum = ARRAY_SIZE(cpu_pll_cfgs),
528+
.cfgs = cpu_pll_cfgs,
529+
};
530+
531+
static const struct ccu_pll_cfg gmac_pll_cfg = {
532+
.freq = 1000000000,
533+
.fbdiv = 125,
534+
.frac = 0,
535+
.postdiv1 = 3,
536+
.postdiv2 = 1,
429537
};
430538

431539
static struct ccu_pll gmac_pll_clk = {
@@ -439,6 +547,8 @@ static struct ccu_pll gmac_pll_clk = {
439547
CLK_IS_CRITICAL),
440548
},
441549
.lock_sts_mask = BIT(3),
550+
.cfgnum = 1,
551+
.cfgs = &gmac_pll_cfg,
442552
};
443553

444554
static const struct clk_hw *gmac_pll_clk_parent[] = {
@@ -449,6 +559,14 @@ static const struct clk_parent_data gmac_pll_clk_pd[] = {
449559
{ .hw = &gmac_pll_clk.common.hw }
450560
};
451561

562+
static const struct ccu_pll_cfg video_pll_cfg = {
563+
.freq = 792000000,
564+
.fbdiv = 99,
565+
.frac = 0,
566+
.postdiv1 = 3,
567+
.postdiv2 = 1,
568+
};
569+
452570
static struct ccu_pll video_pll_clk = {
453571
.common = {
454572
.clkid = CLK_VIDEO_PLL,
@@ -460,6 +578,8 @@ static struct ccu_pll video_pll_clk = {
460578
CLK_IS_CRITICAL),
461579
},
462580
.lock_sts_mask = BIT(7),
581+
.cfgnum = 1,
582+
.cfgs = &video_pll_cfg,
463583
};
464584

465585
static const struct clk_hw *video_pll_clk_parent[] = {
@@ -470,6 +590,14 @@ static const struct clk_parent_data video_pll_clk_pd[] = {
470590
{ .hw = &video_pll_clk.common.hw }
471591
};
472592

593+
static const struct ccu_pll_cfg dpu_pll_cfg = {
594+
.freq = 1188000000,
595+
.fbdiv = 99,
596+
.frac = 0,
597+
.postdiv1 = 2,
598+
.postdiv2 = 1,
599+
};
600+
473601
static struct ccu_pll dpu0_pll_clk = {
474602
.common = {
475603
.clkid = CLK_DPU0_PLL,
@@ -481,6 +609,8 @@ static struct ccu_pll dpu0_pll_clk = {
481609
0),
482610
},
483611
.lock_sts_mask = BIT(8),
612+
.cfgnum = 1,
613+
.cfgs = &dpu_pll_cfg,
484614
};
485615

486616
static const struct clk_hw *dpu0_pll_clk_parent[] = {
@@ -498,12 +628,22 @@ static struct ccu_pll dpu1_pll_clk = {
498628
0),
499629
},
500630
.lock_sts_mask = BIT(9),
631+
.cfgnum = 1,
632+
.cfgs = &dpu_pll_cfg,
501633
};
502634

503635
static const struct clk_hw *dpu1_pll_clk_parent[] = {
504636
&dpu1_pll_clk.common.hw
505637
};
506638

639+
static const struct ccu_pll_cfg tee_pll_cfg = {
640+
.freq = 792000000,
641+
.fbdiv = 99,
642+
.frac = 0,
643+
.postdiv1 = 3,
644+
.postdiv2 = 1,
645+
};
646+
507647
static struct ccu_pll tee_pll_clk = {
508648
.common = {
509649
.clkid = CLK_TEE_PLL,
@@ -515,6 +655,8 @@ static struct ccu_pll tee_pll_clk = {
515655
CLK_IS_CRITICAL),
516656
},
517657
.lock_sts_mask = BIT(10),
658+
.cfgnum = 1,
659+
.cfgs = &tee_pll_cfg,
518660
};
519661

520662
static const struct clk_parent_data c910_i0_parents[] = {

0 commit comments

Comments
 (0)