@@ -54,6 +54,7 @@ static u32 cpg_mode __initdata;
5454
5555/* Fractional 8.25 PLL */
5656#define CPG_PLLxCR0_NI8 GENMASK(27, 20) /* Integer mult. factor */
57+ #define CPG_PLLxCR1_NF25 GENMASK(24, 0) /* Fractional mult. factor */
5758
5859#define CPG_PLLxCR_STC GENMASK(30, 24) /* R_Car V3U PLLxCR */
5960
@@ -67,6 +68,7 @@ static u32 cpg_mode __initdata;
6768struct cpg_pll_clk {
6869 struct clk_hw hw ;
6970 void __iomem * pllcr0_reg ;
71+ void __iomem * pllcr1_reg ;
7072 void __iomem * pllecr_reg ;
7173 u32 pllecr_pllst_mask ;
7274};
@@ -77,17 +79,26 @@ static unsigned long cpg_pll_8_25_clk_recalc_rate(struct clk_hw *hw,
7779 unsigned long parent_rate )
7880{
7981 struct cpg_pll_clk * pll_clk = to_pll_clk (hw );
80- unsigned int mult ;
81-
82- mult = FIELD_GET (CPG_PLLxCR0_NI8 , readl (pll_clk -> pllcr0_reg )) + 1 ;
82+ u32 cr0 = readl (pll_clk -> pllcr0_reg );
83+ unsigned int ni , nf ;
84+ unsigned long rate ;
85+
86+ ni = (FIELD_GET (CPG_PLLxCR0_NI8 , cr0 ) + 1 ) * 2 ;
87+ rate = parent_rate * ni ;
88+ if (cr0 & CPG_PLLxCR0_SSMODE_FM ) {
89+ nf = FIELD_GET (CPG_PLLxCR1_NF25 , readl (pll_clk -> pllcr1_reg ));
90+ rate += mul_u64_u32_shr (parent_rate , nf , 24 );
91+ }
8392
84- return parent_rate * mult * 2 ;
93+ return rate ;
8594}
8695
8796static int cpg_pll_8_25_clk_determine_rate (struct clk_hw * hw ,
8897 struct clk_rate_request * req )
8998{
90- unsigned int min_mult , max_mult , mult ;
99+ struct cpg_pll_clk * pll_clk = to_pll_clk (hw );
100+ unsigned int min_mult , max_mult , ni , nf ;
101+ u32 cr0 = readl (pll_clk -> pllcr0_reg );
91102 unsigned long prate ;
92103
93104 prate = req -> best_parent_rate * 2 ;
@@ -96,28 +107,58 @@ static int cpg_pll_8_25_clk_determine_rate(struct clk_hw *hw,
96107 if (max_mult < min_mult )
97108 return - EINVAL ;
98109
99- mult = DIV_ROUND_CLOSEST_ULL (req -> rate , prate );
100- mult = clamp (mult , min_mult , max_mult );
110+ if (cr0 & CPG_PLLxCR0_SSMODE_FM ) {
111+ ni = div64_ul (req -> rate , prate );
112+ if (ni < min_mult ) {
113+ ni = min_mult ;
114+ nf = 0 ;
115+ } else {
116+ ni = min (ni , max_mult );
117+ nf = div64_ul ((u64 )(req -> rate - prate * ni ) << 24 ,
118+ req -> best_parent_rate );
119+ }
120+ } else {
121+ ni = DIV_ROUND_CLOSEST_ULL (req -> rate , prate );
122+ ni = clamp (ni , min_mult , max_mult );
123+ nf = 0 ;
124+ }
125+ req -> rate = prate * ni + mul_u64_u32_shr (req -> best_parent_rate , nf , 24 );
101126
102- req -> rate = prate * mult ;
103127 return 0 ;
104128}
105129
106130static int cpg_pll_8_25_clk_set_rate (struct clk_hw * hw , unsigned long rate ,
107131 unsigned long parent_rate )
108132{
109133 struct cpg_pll_clk * pll_clk = to_pll_clk (hw );
110- unsigned int mult ;
134+ unsigned long prate = parent_rate * 2 ;
135+ u32 cr0 = readl (pll_clk -> pllcr0_reg );
136+ unsigned int ni , nf ;
111137 u32 val ;
112138
113- mult = DIV_ROUND_CLOSEST_ULL (rate , parent_rate * 2 );
114- mult = clamp (mult , 1U , 256U );
139+ if (cr0 & CPG_PLLxCR0_SSMODE_FM ) {
140+ ni = div64_ul (rate , prate );
141+ if (ni < 1 ) {
142+ ni = 1 ;
143+ nf = 0 ;
144+ } else {
145+ ni = min (ni , 256U );
146+ nf = div64_ul ((u64 )(rate - prate * ni ) << 24 ,
147+ parent_rate );
148+ }
149+ } else {
150+ ni = DIV_ROUND_CLOSEST_ULL (rate , prate );
151+ ni = clamp (ni , 1U , 256U );
152+ }
115153
116154 if (readl (pll_clk -> pllcr0_reg ) & CPG_PLLxCR0_KICK )
117155 return - EBUSY ;
118156
119157 cpg_reg_modify (pll_clk -> pllcr0_reg , CPG_PLLxCR0_NI8 ,
120- FIELD_PREP (CPG_PLLxCR0_NI8 , mult - 1 ));
158+ FIELD_PREP (CPG_PLLxCR0_NI8 , ni - 1 ));
159+ if (cr0 & CPG_PLLxCR0_SSMODE_FM )
160+ cpg_reg_modify (pll_clk -> pllcr1_reg , CPG_PLLxCR1_NF25 ,
161+ FIELD_PREP (CPG_PLLxCR1_NF25 , nf ));
121162
122163 /*
123164 * Set KICK bit in PLLxCR0 to update hardware setting and wait for
@@ -167,19 +208,17 @@ static struct clk * __init cpg_pll_clk_register(const char *name,
167208
168209 pll_clk -> hw .init = & init ;
169210 pll_clk -> pllcr0_reg = base + cr0_offset ;
211+ pll_clk -> pllcr1_reg = base + cr1_offset ;
170212 pll_clk -> pllecr_reg = base + CPG_PLLECR ;
171213 pll_clk -> pllecr_pllst_mask = CPG_PLLECR_PLLST (index );
172214
173- /* Disable Fractional Multiplication and Frequency Dithering */
174- writel (0 , base + cr1_offset );
175- cpg_reg_modify (pll_clk -> pllcr0_reg , CPG_PLLxCR0_SSMODE , 0 );
176-
177215 clk = clk_register (NULL , & pll_clk -> hw );
178216 if (IS_ERR (clk ))
179217 kfree (pll_clk );
180218
181219 return clk ;
182220}
221+
183222/*
184223 * Z0 Clock & Z1 Clock
185224 */
0 commit comments