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+
7584struct 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+
394461static 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
401470static 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+
405501static 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
418516static 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
431539static 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
444554static 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+
452570static 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
465585static 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+
473601static 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
486616static 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
503635static 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+
507647static 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
520662static const struct clk_parent_data c910_i0_parents [] = {
0 commit comments