29
29
#define PDIV_MASK GENMASK(9, 4)
30
30
#define SDIV_MASK GENMASK(2, 0)
31
31
#define KDIV_MASK GENMASK(15, 0)
32
+ #define KDIV_MIN SHRT_MIN
33
+ #define KDIV_MAX SHRT_MAX
32
34
33
35
#define LOCK_TIMEOUT_US 10000
34
36
@@ -113,7 +115,106 @@ static long pll14xx_calc_rate(struct clk_pll14xx *pll, int mdiv, int pdiv,
113
115
return fvco ;
114
116
}
115
117
116
- static long clk_pll14xx_round_rate (struct clk_hw * hw , unsigned long rate ,
118
+ static long pll1443x_calc_kdiv (int mdiv , int pdiv , int sdiv ,
119
+ unsigned long rate , unsigned long prate )
120
+ {
121
+ long kdiv ;
122
+
123
+ /* calc kdiv = round(rate * pdiv * 65536 * 2^sdiv / prate) - (mdiv * 65536) */
124
+ kdiv = ((rate * ((pdiv * 65536 ) << sdiv ) + prate / 2 ) / prate ) - (mdiv * 65536 );
125
+
126
+ return clamp_t (short , kdiv , KDIV_MIN , KDIV_MAX );
127
+ }
128
+
129
+ static void imx_pll14xx_calc_settings (struct clk_pll14xx * pll , unsigned long rate ,
130
+ unsigned long prate , struct imx_pll14xx_rate_table * t )
131
+ {
132
+ u32 pll_div_ctl0 , pll_div_ctl1 ;
133
+ int mdiv , pdiv , sdiv , kdiv ;
134
+ long fvco , rate_min , rate_max , dist , best = LONG_MAX ;
135
+ const struct imx_pll14xx_rate_table * tt ;
136
+
137
+ /*
138
+ * Fractional PLL constrains:
139
+ *
140
+ * a) 6MHz <= prate <= 25MHz
141
+ * b) 1 <= p <= 63 (1 <= p <= 4 prate = 24MHz)
142
+ * c) 64 <= m <= 1023
143
+ * d) 0 <= s <= 6
144
+ * e) -32768 <= k <= 32767
145
+ *
146
+ * fvco = (m * 65536 + k) * prate / (p * 65536)
147
+ */
148
+
149
+ /* First try if we can get the desired rate from one of the static entries */
150
+ tt = imx_get_pll_settings (pll , rate );
151
+ if (tt ) {
152
+ pr_debug ("%s: in=%ld, want=%ld, Using PLL setting from table\n" ,
153
+ clk_hw_get_name (& pll -> hw ), prate , rate );
154
+ t -> rate = tt -> rate ;
155
+ t -> mdiv = tt -> mdiv ;
156
+ t -> pdiv = tt -> pdiv ;
157
+ t -> sdiv = tt -> sdiv ;
158
+ t -> kdiv = tt -> kdiv ;
159
+ return ;
160
+ }
161
+
162
+ pll_div_ctl0 = readl_relaxed (pll -> base + DIV_CTL0 );
163
+ mdiv = FIELD_GET (MDIV_MASK , pll_div_ctl0 );
164
+ pdiv = FIELD_GET (PDIV_MASK , pll_div_ctl0 );
165
+ sdiv = FIELD_GET (SDIV_MASK , pll_div_ctl0 );
166
+ pll_div_ctl1 = readl_relaxed (pll -> base + DIV_CTL1 );
167
+
168
+ /* Then see if we can get the desired rate by only adjusting kdiv (glitch free) */
169
+ rate_min = pll14xx_calc_rate (pll , mdiv , pdiv , sdiv , KDIV_MIN , prate );
170
+ rate_max = pll14xx_calc_rate (pll , mdiv , pdiv , sdiv , KDIV_MAX , prate );
171
+
172
+ if (rate >= rate_min && rate <= rate_max ) {
173
+ kdiv = pll1443x_calc_kdiv (mdiv , pdiv , sdiv , rate , prate );
174
+ pr_debug ("%s: in=%ld, want=%ld Only adjust kdiv %ld -> %d\n" ,
175
+ clk_hw_get_name (& pll -> hw ), prate , rate ,
176
+ FIELD_GET (KDIV_MASK , pll_div_ctl1 ), kdiv );
177
+ fvco = pll14xx_calc_rate (pll , mdiv , pdiv , sdiv , kdiv , prate );
178
+ t -> rate = (unsigned int )fvco ;
179
+ t -> mdiv = mdiv ;
180
+ t -> pdiv = pdiv ;
181
+ t -> sdiv = sdiv ;
182
+ t -> kdiv = kdiv ;
183
+ return ;
184
+ }
185
+
186
+ /* Finally calculate best values */
187
+ for (pdiv = 1 ; pdiv <= 7 ; pdiv ++ ) {
188
+ for (sdiv = 0 ; sdiv <= 6 ; sdiv ++ ) {
189
+ /* calc mdiv = round(rate * pdiv * 2^sdiv) / prate) */
190
+ mdiv = DIV_ROUND_CLOSEST (rate * (pdiv << sdiv ), prate );
191
+ mdiv = clamp (mdiv , 64 , 1023 );
192
+
193
+ kdiv = pll1443x_calc_kdiv (mdiv , pdiv , sdiv , rate , prate );
194
+ fvco = pll14xx_calc_rate (pll , mdiv , pdiv , sdiv , kdiv , prate );
195
+
196
+ /* best match */
197
+ dist = abs ((long )rate - (long )fvco );
198
+ if (dist < best ) {
199
+ best = dist ;
200
+ t -> rate = (unsigned int )fvco ;
201
+ t -> mdiv = mdiv ;
202
+ t -> pdiv = pdiv ;
203
+ t -> sdiv = sdiv ;
204
+ t -> kdiv = kdiv ;
205
+
206
+ if (!dist )
207
+ goto found ;
208
+ }
209
+ }
210
+ }
211
+ found :
212
+ pr_debug ("%s: in=%ld, want=%ld got=%d (pdiv=%d sdiv=%d mdiv=%d kdiv=%d)\n" ,
213
+ clk_hw_get_name (& pll -> hw ), prate , rate , t -> rate , t -> pdiv , t -> sdiv ,
214
+ t -> mdiv , t -> kdiv );
215
+ }
216
+
217
+ static long clk_pll1416x_round_rate (struct clk_hw * hw , unsigned long rate ,
117
218
unsigned long * prate )
118
219
{
119
220
struct clk_pll14xx * pll = to_clk_pll14xx (hw );
@@ -129,6 +230,17 @@ static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
129
230
return rate_table [pll -> rate_count - 1 ].rate ;
130
231
}
131
232
233
+ static long clk_pll1443x_round_rate (struct clk_hw * hw , unsigned long rate ,
234
+ unsigned long * prate )
235
+ {
236
+ struct clk_pll14xx * pll = to_clk_pll14xx (hw );
237
+ struct imx_pll14xx_rate_table t ;
238
+
239
+ imx_pll14xx_calc_settings (pll , rate , * prate , & t );
240
+
241
+ return t .rate ;
242
+ }
243
+
132
244
static unsigned long clk_pll14xx_recalc_rate (struct clk_hw * hw ,
133
245
unsigned long parent_rate )
134
246
{
@@ -239,25 +351,21 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
239
351
unsigned long prate )
240
352
{
241
353
struct clk_pll14xx * pll = to_clk_pll14xx (hw );
242
- const struct imx_pll14xx_rate_table * rate ;
354
+ struct imx_pll14xx_rate_table rate ;
243
355
u32 gnrl_ctl , div_ctl0 ;
244
356
int ret ;
245
357
246
- rate = imx_get_pll_settings (pll , drate );
247
- if (!rate ) {
248
- pr_err ("%s: Invalid rate : %lu for pll clk %s\n" , __func__ ,
249
- drate , clk_hw_get_name (hw ));
250
- return - EINVAL ;
251
- }
358
+ imx_pll14xx_calc_settings (pll , drate , prate , & rate );
252
359
253
360
div_ctl0 = readl_relaxed (pll -> base + DIV_CTL0 );
254
361
255
- if (!clk_pll14xx_mp_change (rate , div_ctl0 )) {
362
+ if (!clk_pll14xx_mp_change (& rate , div_ctl0 )) {
363
+ /* only sdiv and/or kdiv changed - no need to RESET PLL */
256
364
div_ctl0 &= ~SDIV_MASK ;
257
- div_ctl0 |= FIELD_PREP (SDIV_MASK , rate -> sdiv );
365
+ div_ctl0 |= FIELD_PREP (SDIV_MASK , rate . sdiv );
258
366
writel_relaxed (div_ctl0 , pll -> base + DIV_CTL0 );
259
367
260
- writel_relaxed (FIELD_PREP (KDIV_MASK , rate -> kdiv ),
368
+ writel_relaxed (FIELD_PREP (KDIV_MASK , rate . kdiv ),
261
369
pll -> base + DIV_CTL1 );
262
370
263
371
return 0 ;
@@ -272,11 +380,12 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
272
380
gnrl_ctl |= BYPASS_MASK ;
273
381
writel_relaxed (gnrl_ctl , pll -> base + GNRL_CTL );
274
382
275
- div_ctl0 = FIELD_PREP (MDIV_MASK , rate -> mdiv ) |
276
- FIELD_PREP (PDIV_MASK , rate -> pdiv ) |
277
- FIELD_PREP (SDIV_MASK , rate -> sdiv );
383
+ div_ctl0 = FIELD_PREP (MDIV_MASK , rate . mdiv ) |
384
+ FIELD_PREP (PDIV_MASK , rate . pdiv ) |
385
+ FIELD_PREP (SDIV_MASK , rate . sdiv );
278
386
writel_relaxed (div_ctl0 , pll -> base + DIV_CTL0 );
279
- writel_relaxed (FIELD_PREP (KDIV_MASK , rate -> kdiv ), pll -> base + DIV_CTL1 );
387
+
388
+ writel_relaxed (FIELD_PREP (KDIV_MASK , rate .kdiv ), pll -> base + DIV_CTL1 );
280
389
281
390
/*
282
391
* According to SPEC, t3 - t2 need to be greater than
@@ -359,7 +468,7 @@ static const struct clk_ops clk_pll1416x_ops = {
359
468
.unprepare = clk_pll14xx_unprepare ,
360
469
.is_prepared = clk_pll14xx_is_prepared ,
361
470
.recalc_rate = clk_pll14xx_recalc_rate ,
362
- .round_rate = clk_pll14xx_round_rate ,
471
+ .round_rate = clk_pll1416x_round_rate ,
363
472
.set_rate = clk_pll1416x_set_rate ,
364
473
};
365
474
@@ -372,7 +481,7 @@ static const struct clk_ops clk_pll1443x_ops = {
372
481
.unprepare = clk_pll14xx_unprepare ,
373
482
.is_prepared = clk_pll14xx_is_prepared ,
374
483
.recalc_rate = clk_pll14xx_recalc_rate ,
375
- .round_rate = clk_pll14xx_round_rate ,
484
+ .round_rate = clk_pll1443x_round_rate ,
376
485
.set_rate = clk_pll1443x_set_rate ,
377
486
};
378
487
0 commit comments