blob: d15d1bb915ebfee50a89dbcc9151b81a39b6d426 [file] [log] [blame]
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -08001/*
Deepak Katragadda043f8542017-02-22 11:21:31 -08002 * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -08003 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/kernel.h>
15#include <linux/export.h>
16#include <linux/clk-provider.h>
17#include <linux/regmap.h>
18#include <linux/delay.h>
19
20#include "clk-alpha-pll.h"
21
22#define PLL_MODE 0x00
23# define PLL_OUTCTRL BIT(0)
24# define PLL_BYPASSNL BIT(1)
25# define PLL_RESET_N BIT(2)
26# define PLL_LOCK_COUNT_SHIFT 8
27# define PLL_LOCK_COUNT_MASK 0x3f
28# define PLL_BIAS_COUNT_SHIFT 14
29# define PLL_BIAS_COUNT_MASK 0x3f
30# define PLL_VOTE_FSM_ENA BIT(20)
31# define PLL_VOTE_FSM_RESET BIT(21)
32# define PLL_ACTIVE_FLAG BIT(30)
33# define PLL_LOCK_DET BIT(31)
34
35#define PLL_L_VAL 0x04
36#define PLL_ALPHA_VAL 0x08
37#define PLL_ALPHA_VAL_U 0x0c
38
39#define PLL_USER_CTL 0x10
40# define PLL_POST_DIV_SHIFT 8
41# define PLL_POST_DIV_MASK 0xf
42# define PLL_ALPHA_EN BIT(24)
43# define PLL_VCO_SHIFT 20
44# define PLL_VCO_MASK 0x3
45
46#define PLL_USER_CTL_U 0x14
47
48#define PLL_CONFIG_CTL 0x18
49#define PLL_TEST_CTL 0x1c
50#define PLL_TEST_CTL_U 0x20
51#define PLL_STATUS 0x24
52
53/*
54 * Even though 40 bits are present, use only 32 for ease of calculation.
55 */
56#define ALPHA_REG_BITWIDTH 40
57#define ALPHA_BITWIDTH 32
Deepak Katragadda2b803212016-06-29 16:35:22 -070058#define FABIA_BITWIDTH 16
59
60#define FABIA_USER_CTL_LO 0xc
61#define FABIA_USER_CTL_HI 0x10
62#define FABIA_CAL_L_VAL 0x8
63#define FABIA_FRAC_VAL 0x38
64#define FABIA_OPMODE 0x2c
65#define FABIA_PLL_STANDBY 0x0
66#define FABIA_PLL_RUN 0x1
67#define FABIA_PLL_OUT_MASK 0x7
68#define FABIA_PLL_RATE_MARGIN 500
69#define FABIA_PLL_ACK_LATCH BIT(29)
70#define FABIA_PLL_UPDATE BIT(22)
71#define FABIA_PLL_HW_UPDATE_LOGIC_BYPASS BIT(23)
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -080072
73#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
74 struct clk_alpha_pll, clkr)
75
76#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
77 struct clk_alpha_pll_postdiv, clkr)
78
Rajendra Nayake512fb22016-04-18 11:40:43 +053079static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
80 const char *action)
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -080081{
Rajendra Nayake512fb22016-04-18 11:40:43 +053082 u32 val, off;
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -080083 int count;
84 int ret;
85 const char *name = clk_hw_get_name(&pll->clkr.hw);
86
87 off = pll->offset;
88 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
89 if (ret)
90 return ret;
91
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -080092 for (count = 100; count > 0; count--) {
93 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
94 if (ret)
95 return ret;
Rajendra Nayake512fb22016-04-18 11:40:43 +053096 if (inverse && (val & mask))
97 return 0;
98 else if ((val & mask) == mask)
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -080099 return 0;
100
101 udelay(1);
102 }
103
Rajendra Nayake512fb22016-04-18 11:40:43 +0530104 WARN(1, "%s failed to %s!\n", name, action);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800105 return -ETIMEDOUT;
106}
107
Rajendra Nayake512fb22016-04-18 11:40:43 +0530108static int wait_for_pll_enable(struct clk_alpha_pll *pll, u32 mask)
109{
110 return wait_for_pll(pll, mask, 0, "enable");
111}
112
113static int wait_for_pll_disable(struct clk_alpha_pll *pll, u32 mask)
114{
115 return wait_for_pll(pll, mask, 1, "disable");
116}
117
118static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask)
119{
120 return wait_for_pll(pll, mask, 0, "offline");
121}
122
123
124/* alpha pll with hwfsm support */
125
126#define PLL_OFFLINE_REQ BIT(7)
127#define PLL_FSM_ENA BIT(20)
128#define PLL_OFFLINE_ACK BIT(28)
129#define PLL_ACTIVE_FLAG BIT(30)
130
131void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
132 const struct pll_config *config)
133{
134 u32 val, mask;
135
136 regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
137 config->config_ctl_val);
138
139 val = config->main_output_mask;
140 val |= config->aux_output_mask;
141 val |= config->aux2_output_mask;
142 val |= config->early_output_mask;
143 val |= config->post_div_val;
144
145 mask = config->main_output_mask;
146 mask |= config->aux_output_mask;
147 mask |= config->aux2_output_mask;
148 mask |= config->early_output_mask;
149 mask |= config->post_div_mask;
150
151 regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, mask, val);
152}
153
154static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
155{
156 int ret;
157 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
158 u32 val, off;
159
160 off = pll->offset;
161 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
162 if (ret)
163 return ret;
164 /* Enable HW FSM mode, clear OFFLINE request */
165 val |= PLL_FSM_ENA;
166 val &= ~PLL_OFFLINE_REQ;
167 ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
168 if (ret)
169 return ret;
170
171 /* Make sure enable request goes through before waiting for update */
172 mb();
173
174 ret = wait_for_pll_enable(pll, PLL_ACTIVE_FLAG);
175 if (ret)
176 return ret;
177
178 return 0;
179}
180
181static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
182{
183 int ret;
184 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
185 u32 val, off;
186
187 off = pll->offset;
188 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
189 if (ret)
190 return;
191 /* Request PLL_OFFLINE and wait for ack */
192 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
193 PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
194 if (ret)
195 return;
196 ret = wait_for_pll_offline(pll, PLL_OFFLINE_ACK);
197 if (ret)
198 return;
199
200 /* Disable hwfsm */
201 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
202 PLL_FSM_ENA, 0);
203 if (ret)
204 return;
205 wait_for_pll_disable(pll, PLL_ACTIVE_FLAG);
206}
207
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800208static int clk_alpha_pll_enable(struct clk_hw *hw)
209{
210 int ret;
211 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
212 u32 val, mask, off;
213
214 off = pll->offset;
215
216 mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
217 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
218 if (ret)
219 return ret;
220
221 /* If in FSM mode, just vote for it */
222 if (val & PLL_VOTE_FSM_ENA) {
223 ret = clk_enable_regmap(hw);
224 if (ret)
225 return ret;
Rajendra Nayake512fb22016-04-18 11:40:43 +0530226 return wait_for_pll_enable(pll, PLL_ACTIVE_FLAG);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800227 }
228
229 /* Skip if already enabled */
230 if ((val & mask) == mask)
231 return 0;
232
233 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
234 PLL_BYPASSNL, PLL_BYPASSNL);
235 if (ret)
236 return ret;
237
238 /*
239 * H/W requires a 5us delay between disabling the bypass and
240 * de-asserting the reset.
241 */
242 mb();
243 udelay(5);
244
245 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
246 PLL_RESET_N, PLL_RESET_N);
247 if (ret)
248 return ret;
249
Rajendra Nayake512fb22016-04-18 11:40:43 +0530250 ret = wait_for_pll_enable(pll, PLL_LOCK_DET);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800251 if (ret)
252 return ret;
253
254 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
255 PLL_OUTCTRL, PLL_OUTCTRL);
256
257 /* Ensure that the write above goes through before returning. */
258 mb();
259 return ret;
260}
261
262static void clk_alpha_pll_disable(struct clk_hw *hw)
263{
264 int ret;
265 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
266 u32 val, mask, off;
267
268 off = pll->offset;
269
270 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
271 if (ret)
272 return;
273
274 /* If in FSM mode, just unvote it */
275 if (val & PLL_VOTE_FSM_ENA) {
276 clk_disable_regmap(hw);
277 return;
278 }
279
280 mask = PLL_OUTCTRL;
281 regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
282
283 /* Delay of 2 output clock ticks required until output is disabled */
284 mb();
285 udelay(1);
286
287 mask = PLL_RESET_N | PLL_BYPASSNL;
288 regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
289}
290
Deepak Katragadda2b803212016-06-29 16:35:22 -0700291static unsigned long alpha_pll_calc_rate(const struct clk_alpha_pll *pll,
292 u64 prate, u32 l, u32 a)
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800293{
Deepak Katragadda2b803212016-06-29 16:35:22 -0700294 int alpha_bw = ALPHA_BITWIDTH;
295
296 if (pll->type == FABIA_PLL)
297 alpha_bw = FABIA_BITWIDTH;
298
299 return (prate * l) + ((prate * a) >> alpha_bw);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800300}
301
302static unsigned long
Deepak Katragadda2b803212016-06-29 16:35:22 -0700303alpha_pll_round_rate(const struct clk_alpha_pll *pll, unsigned long rate,
304 unsigned long prate, u32 *l, u64 *a)
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800305{
306 u64 remainder;
307 u64 quotient;
Deepak Katragadda2b803212016-06-29 16:35:22 -0700308 int alpha_bw = ALPHA_BITWIDTH;
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800309
Deepak Katragaddab0823d02017-04-21 15:17:19 -0700310 /*
311 * The PLLs parent rate is zero probably since the parent hasn't
312 * registered yet. Return early with the requested rate.
313 */
314 if (!prate) {
315 pr_debug("PLLs parent rate hasn't been initialized.\n");
316 return rate;
317 }
318
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800319 quotient = rate;
320 remainder = do_div(quotient, prate);
321 *l = quotient;
322
323 if (!remainder) {
324 *a = 0;
325 return rate;
326 }
327
Deepak Katragadda2b803212016-06-29 16:35:22 -0700328 /* Fabia PLLs only have 16 bits to program the fractional divider */
329 if (pll->type == FABIA_PLL)
330 alpha_bw = FABIA_BITWIDTH;
331
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800332 /* Upper ALPHA_BITWIDTH bits of Alpha */
Deepak Katragadda2b803212016-06-29 16:35:22 -0700333 quotient = remainder << alpha_bw;
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800334 remainder = do_div(quotient, prate);
335
336 if (remainder)
337 quotient++;
338
339 *a = quotient;
Deepak Katragadda2b803212016-06-29 16:35:22 -0700340 return alpha_pll_calc_rate(pll, prate, *l, *a);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800341}
342
343static const struct pll_vco *
344alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate)
345{
346 const struct pll_vco *v = pll->vco_table;
347 const struct pll_vco *end = v + pll->num_vco;
348
349 for (; v < end; v++)
350 if (rate >= v->min_freq && rate <= v->max_freq)
351 return v;
352
353 return NULL;
354}
355
356static unsigned long
357clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
358{
359 u32 l, low, high, ctl;
360 u64 a = 0, prate = parent_rate;
361 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
362 u32 off = pll->offset;
363
364 regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
365
366 regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
367 if (ctl & PLL_ALPHA_EN) {
368 regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
369 regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
370 a = (u64)high << 32 | low;
371 a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
372 }
373
Deepak Katragadda2b803212016-06-29 16:35:22 -0700374 return alpha_pll_calc_rate(pll, prate, l, a);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800375}
376
377static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
378 unsigned long prate)
379{
380 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
381 const struct pll_vco *vco;
382 u32 l, off = pll->offset;
383 u64 a;
384
Deepak Katragadda2b803212016-06-29 16:35:22 -0700385 rate = alpha_pll_round_rate(pll, rate, prate, &l, &a);
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800386 vco = alpha_pll_find_vco(pll, rate);
387 if (!vco) {
388 pr_err("alpha pll not in a valid vco range\n");
389 return -EINVAL;
390 }
391
392 a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
393
394 regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
395 regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
396 regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
397
398 regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
399 PLL_VCO_MASK << PLL_VCO_SHIFT,
400 vco->val << PLL_VCO_SHIFT);
401
402 regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
403 PLL_ALPHA_EN);
404
405 return 0;
406}
407
408static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
409 unsigned long *prate)
410{
411 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
412 u32 l;
413 u64 a;
414 unsigned long min_freq, max_freq;
415
Deepak Katragadda2b803212016-06-29 16:35:22 -0700416 rate = alpha_pll_round_rate(pll, rate, *prate, &l, &a);
417 if (pll->type == FABIA_PLL || alpha_pll_find_vco(pll, rate))
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800418 return rate;
419
420 min_freq = pll->vco_table[0].min_freq;
421 max_freq = pll->vco_table[pll->num_vco - 1].max_freq;
422
423 return clamp(rate, min_freq, max_freq);
424}
425
Taniya Das4b006ad2016-11-07 10:01:38 +0530426static void clk_alpha_pll_list_registers(struct seq_file *f, struct clk_hw *hw)
427{
428 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
429 int size, i, val;
430
431 static struct clk_register_data data[] = {
432 {"PLL_MODE", 0x0},
433 {"PLL_L_VAL", 0x4},
434 {"PLL_ALPHA_VAL", 0x8},
435 {"PLL_ALPHA_VAL_U", 0xC},
436 {"PLL_USER_CTL", 0x10},
437 {"PLL_CONFIG_CTL", 0x18},
438 };
439
440 static struct clk_register_data data1[] = {
441 {"APSS_PLL_VOTE", 0x0},
442 };
443
444 size = ARRAY_SIZE(data);
445
446 for (i = 0; i < size; i++) {
447 regmap_read(pll->clkr.regmap, pll->offset + data[i].offset,
448 &val);
449 seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
450 }
451
452 regmap_read(pll->clkr.regmap, pll->offset + data[0].offset, &val);
453
454 if (val & PLL_FSM_ENA) {
455 regmap_read(pll->clkr.regmap, pll->clkr.enable_reg +
456 data1[0].offset, &val);
457 seq_printf(f, "%20s: 0x%.8x\n", data1[0].name, val);
458 }
459}
460
Deepak Katragadda2b803212016-06-29 16:35:22 -0700461void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
462 const struct pll_config *config)
463{
464 u32 val, mask;
465
466 if (config->l) {
467 regmap_write(regmap, pll->offset + PLL_L_VAL,
468 config->l);
469 regmap_write(regmap, pll->offset + FABIA_CAL_L_VAL,
470 config->l);
471 }
472
473 if (config->frac)
474 regmap_write(regmap, pll->offset + FABIA_FRAC_VAL,
475 config->frac);
476 if (config->config_ctl_val)
477 regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
478 config->config_ctl_val);
479
480 if (config->post_div_mask) {
481 mask = config->post_div_mask;
482 val = config->post_div_val;
483 regmap_update_bits(regmap, pll->offset + FABIA_USER_CTL_LO,
484 mask, val);
485 }
486
487 regmap_update_bits(regmap, pll->offset + PLL_MODE,
488 FABIA_PLL_HW_UPDATE_LOGIC_BYPASS,
489 FABIA_PLL_HW_UPDATE_LOGIC_BYPASS);
490
491 regmap_update_bits(regmap, pll->offset + PLL_MODE,
492 PLL_RESET_N, PLL_RESET_N);
493
494 pll->inited = true;
495}
496
Deepak Katragadda2b803212016-06-29 16:35:22 -0700497static int clk_fabia_pll_enable(struct clk_hw *hw)
498{
499 int ret;
500 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
501 u32 val, off = pll->offset;
502
503 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
504 if (ret)
505 return ret;
506
507 /* If in FSM mode, just vote for it */
508 if (val & PLL_VOTE_FSM_ENA) {
509 ret = clk_enable_regmap(hw);
510 if (ret)
511 return ret;
512 return wait_for_pll_enable(pll, PLL_ACTIVE_FLAG);
513 }
514
515 if (unlikely(!pll->inited))
516 clk_fabia_pll_configure(pll, pll->clkr.regmap, pll->config);
517
518 /* Disable PLL output */
519 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
520 PLL_OUTCTRL, 0);
521 if (ret)
522 return ret;
523
524 /* Set operation mode to STANDBY */
525 regmap_write(pll->clkr.regmap, off + FABIA_OPMODE, FABIA_PLL_STANDBY);
526
527 /* PLL should be in STANDBY mode before continuing */
528 mb();
529
530 /* Bring PLL out of reset */
531 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
532 PLL_RESET_N, PLL_RESET_N);
533 if (ret)
534 return ret;
535
536 /* Set operation mode to RUN */
537 regmap_write(pll->clkr.regmap, off + FABIA_OPMODE, FABIA_PLL_RUN);
538
539 ret = wait_for_pll_enable(pll, PLL_LOCK_DET);
540 if (ret)
541 return ret;
542
543 /* Enable the main PLL output */
544 ret = regmap_update_bits(pll->clkr.regmap, off + FABIA_USER_CTL_LO,
545 FABIA_PLL_OUT_MASK, FABIA_PLL_OUT_MASK);
546 if (ret)
547 return ret;
548
549 /* Enable PLL outputs */
550 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
551 PLL_OUTCTRL, PLL_OUTCTRL);
552 if (ret)
553 return ret;
554
555 /* Ensure that the write above goes through before returning. */
556 mb();
557 return ret;
558}
559
560static void clk_fabia_pll_disable(struct clk_hw *hw)
561{
562 int ret;
563 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
564 u32 val, off = pll->offset;
565
566 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
567 if (ret)
568 return;
569
570 /* If in FSM mode, just unvote it */
571 if (val & PLL_VOTE_FSM_ENA) {
572 clk_disable_regmap(hw);
573 return;
574 }
575
576 /* Disable PLL outputs */
577 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
578 PLL_OUTCTRL, 0);
579 if (ret)
580 return;
581
582 /* Disable the main PLL output */
583 ret = regmap_update_bits(pll->clkr.regmap, off + FABIA_USER_CTL_LO,
584 FABIA_PLL_OUT_MASK, 0);
585 if (ret)
586 return;
587
588 /* Place the PLL mode in STANDBY */
589 regmap_write(pll->clkr.regmap, off + FABIA_OPMODE, FABIA_PLL_STANDBY);
590}
591
592static unsigned long
593clk_fabia_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
594{
595 u32 l, frac;
596 u64 prate = parent_rate;
597 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
598 u32 off = pll->offset;
599
600 regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
601 regmap_read(pll->clkr.regmap, off + FABIA_FRAC_VAL, &frac);
602
603 return alpha_pll_calc_rate(pll, prate, l, frac);
604}
605
606static int clk_fabia_pll_set_rate(struct clk_hw *hw, unsigned long rate,
607 unsigned long prate)
608{
609 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
610 unsigned long rrate;
611 u32 regval, l, off = pll->offset;
612 u64 a;
613 int ret;
614
615 ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &regval);
616 if (ret)
617 return ret;
618
619 rrate = alpha_pll_round_rate(pll, rate, prate, &l, &a);
620 /*
621 * Due to limited number of bits for fractional rate programming, the
622 * rounded up rate could be marginally higher than the requested rate.
623 */
624 if (rrate > (rate + FABIA_PLL_RATE_MARGIN) || rrate < rate) {
625 pr_err("Call set rate on the PLL with rounded rates!\n");
626 return -EINVAL;
627 }
628
629 regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
630 /*
631 * pll_cal_l_val is set to pll_l_val on MOST targets. Set it
632 * explicitly here for PLL out-of-reset calibration to work
633 * without a glitch on ALL of them.
634 */
635 regmap_write(pll->clkr.regmap, off + FABIA_CAL_L_VAL, l);
636 regmap_write(pll->clkr.regmap, off + FABIA_FRAC_VAL, a);
637
638 /* Latch the PLL input */
639 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
640 FABIA_PLL_UPDATE, FABIA_PLL_UPDATE);
641 if (ret)
642 return ret;
643
644 /* Wait for 2 reference cycles before checking the ACK bit. */
645 udelay(1);
646 regmap_read(pll->clkr.regmap, off + PLL_MODE, &regval);
647 if (!(regval & FABIA_PLL_ACK_LATCH)) {
648 WARN(1, "PLL latch failed. Output may be unstable!\n");
649 return -EINVAL;
650 }
651
652 /* Return the latch input to 0 */
653 ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
654 FABIA_PLL_UPDATE, 0);
655 if (ret)
656 return ret;
657
658 /* Wait for PLL output to stabilize */
659 udelay(100);
660 return 0;
661}
662
Taniya Das4b006ad2016-11-07 10:01:38 +0530663static void clk_fabia_pll_list_registers(struct seq_file *f, struct clk_hw *hw)
664{
665 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
666 int size, i, val;
667
668 static struct clk_register_data data[] = {
669 {"PLL_MODE", 0x0},
670 {"PLL_L_VAL", 0x4},
671 {"PLL_FRAC_VAL", 0x38},
672 {"PLL_USER_CTL", 0xc},
673 {"PLL_CONFIG_CTL", 0x14},
674 {"PLL_OPMODE", 0x2c},
675 };
676
677 static struct clk_register_data data1[] = {
678 {"APSS_PLL_VOTE", 0x0},
679 };
680
681 size = ARRAY_SIZE(data);
682
683 for (i = 0; i < size; i++) {
684 regmap_read(pll->clkr.regmap, pll->offset + data[i].offset,
685 &val);
686 seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
687 }
688
689 regmap_read(pll->clkr.regmap, pll->offset + data[0].offset, &val);
690
691 if (val & PLL_FSM_ENA) {
692 regmap_read(pll->clkr.regmap, pll->clkr.enable_reg +
693 data1[0].offset, &val);
694 seq_printf(f, "%20s: 0x%.8x\n", data1[0].name, val);
695 }
696}
697
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800698const struct clk_ops clk_alpha_pll_ops = {
699 .enable = clk_alpha_pll_enable,
700 .disable = clk_alpha_pll_disable,
701 .recalc_rate = clk_alpha_pll_recalc_rate,
702 .round_rate = clk_alpha_pll_round_rate,
703 .set_rate = clk_alpha_pll_set_rate,
Taniya Das4b006ad2016-11-07 10:01:38 +0530704 .list_registers = clk_alpha_pll_list_registers,
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800705};
706EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
707
Rajendra Nayake512fb22016-04-18 11:40:43 +0530708const struct clk_ops clk_alpha_pll_hwfsm_ops = {
709 .enable = clk_alpha_pll_hwfsm_enable,
710 .disable = clk_alpha_pll_hwfsm_disable,
711 .recalc_rate = clk_alpha_pll_recalc_rate,
712 .round_rate = clk_alpha_pll_round_rate,
713 .set_rate = clk_alpha_pll_set_rate,
Taniya Das4b006ad2016-11-07 10:01:38 +0530714 .list_registers = clk_alpha_pll_list_registers,
Rajendra Nayake512fb22016-04-18 11:40:43 +0530715};
716EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
717
Deepak Katragadda2b803212016-06-29 16:35:22 -0700718const struct clk_ops clk_fabia_pll_ops = {
719 .enable = clk_fabia_pll_enable,
720 .disable = clk_fabia_pll_disable,
721 .recalc_rate = clk_fabia_pll_recalc_rate,
722 .round_rate = clk_alpha_pll_round_rate,
723 .set_rate = clk_fabia_pll_set_rate,
Taniya Das4b006ad2016-11-07 10:01:38 +0530724 .list_registers = clk_fabia_pll_list_registers,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700725};
726EXPORT_SYMBOL_GPL(clk_fabia_pll_ops);
727
728const struct clk_ops clk_fabia_fixed_pll_ops = {
729 .enable = clk_fabia_pll_enable,
730 .disable = clk_fabia_pll_disable,
731 .recalc_rate = clk_fabia_pll_recalc_rate,
Deepak Katragadda24c04712016-11-28 14:27:05 -0800732 .round_rate = clk_alpha_pll_round_rate,
Taniya Das4b006ad2016-11-07 10:01:38 +0530733 .list_registers = clk_fabia_pll_list_registers,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700734};
735EXPORT_SYMBOL_GPL(clk_fabia_fixed_pll_ops);
736
Stephen Boyd8ff1f4c2015-11-30 17:31:39 -0800737static unsigned long
738clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
739{
740 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
741 u32 ctl;
742
743 regmap_read(pll->clkr.regmap, pll->offset + PLL_USER_CTL, &ctl);
744
745 ctl >>= PLL_POST_DIV_SHIFT;
746 ctl &= PLL_POST_DIV_MASK;
747
748 return parent_rate >> fls(ctl);
749}
750
751static const struct clk_div_table clk_alpha_div_table[] = {
752 { 0x0, 1 },
753 { 0x1, 2 },
754 { 0x3, 4 },
755 { 0x7, 8 },
756 { 0xf, 16 },
757 { }
758};
759
760static long
761clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
762 unsigned long *prate)
763{
764 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
765
766 return divider_round_rate(hw, rate, prate, clk_alpha_div_table,
767 pll->width, CLK_DIVIDER_POWER_OF_TWO);
768}
769
770static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
771 unsigned long parent_rate)
772{
773 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
774 int div;
775
776 /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
777 div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
778
779 return regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
780 PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
781 div << PLL_POST_DIV_SHIFT);
782}
783
784const struct clk_ops clk_alpha_pll_postdiv_ops = {
785 .recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
786 .round_rate = clk_alpha_pll_postdiv_round_rate,
787 .set_rate = clk_alpha_pll_postdiv_set_rate,
788};
789EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);
Deepak Katragadda2b803212016-06-29 16:35:22 -0700790
Deepak Katragadda582d6022016-11-09 16:17:45 -0800791static unsigned long clk_generic_pll_postdiv_recalc_rate(struct clk_hw *hw,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700792 unsigned long parent_rate)
793{
794 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
795 u32 i, div = 1, val;
796
Deepak Katragadda582d6022016-11-09 16:17:45 -0800797 if (!pll->post_div_table) {
798 pr_err("Missing the post_div_table for the PLL\n");
799 return -EINVAL;
800 }
801
Deepak Katragadda2b803212016-06-29 16:35:22 -0700802 regmap_read(pll->clkr.regmap, pll->offset + FABIA_USER_CTL_LO, &val);
803
Deepak Katragadda2b803212016-06-29 16:35:22 -0700804 val >>= pll->post_div_shift;
805 val &= PLL_POST_DIV_MASK;
806
Deepak Katragadda582d6022016-11-09 16:17:45 -0800807 for (i = 0; i < pll->num_post_div; i++) {
808 if (pll->post_div_table[i].val == val) {
809 div = pll->post_div_table[i].div;
Deepak Katragadda2b803212016-06-29 16:35:22 -0700810 break;
811 }
812 }
813
814 return (parent_rate / div);
815}
816
Deepak Katragadda582d6022016-11-09 16:17:45 -0800817static long clk_generic_pll_postdiv_round_rate(struct clk_hw *hw,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700818 unsigned long rate, unsigned long *prate)
819{
820 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
821
Deepak Katragadda582d6022016-11-09 16:17:45 -0800822 if (!pll->post_div_table)
823 return -EINVAL;
824
825 return divider_round_rate(hw, rate, prate, pll->post_div_table,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700826 pll->width, CLK_DIVIDER_ROUND_CLOSEST);
827}
828
Deepak Katragadda582d6022016-11-09 16:17:45 -0800829static int clk_generic_pll_postdiv_set_rate(struct clk_hw *hw,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700830 unsigned long rate, unsigned long parent_rate)
831{
832 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
Deepak Katragadda043f8542017-02-22 11:21:31 -0800833 int i, val = 0, div, ret;
834
835 /*
836 * If the PLL is in FSM mode, then treat the set_rate callback
837 * as a no-operation.
838 */
839 ret = regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &val);
840 if (ret)
841 return ret;
842
843 if (val & PLL_VOTE_FSM_ENA)
844 return 0;
Deepak Katragadda2b803212016-06-29 16:35:22 -0700845
Deepak Katragadda582d6022016-11-09 16:17:45 -0800846 if (!pll->post_div_table) {
847 pr_err("Missing the post_div_table for the PLL\n");
848 return -EINVAL;
849 }
850
Deepak Katragadda2b803212016-06-29 16:35:22 -0700851 div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
Deepak Katragadda582d6022016-11-09 16:17:45 -0800852 for (i = 0; i < pll->num_post_div; i++) {
853 if (pll->post_div_table[i].div == div) {
854 val = pll->post_div_table[i].val;
Deepak Katragadda2b803212016-06-29 16:35:22 -0700855 break;
856 }
857 }
858
859 return regmap_update_bits(pll->clkr.regmap,
860 pll->offset + FABIA_USER_CTL_LO,
861 PLL_POST_DIV_MASK << pll->post_div_shift,
862 val << pll->post_div_shift);
863}
864
Deepak Katragadda582d6022016-11-09 16:17:45 -0800865const struct clk_ops clk_generic_pll_postdiv_ops = {
866 .recalc_rate = clk_generic_pll_postdiv_recalc_rate,
867 .round_rate = clk_generic_pll_postdiv_round_rate,
868 .set_rate = clk_generic_pll_postdiv_set_rate,
Deepak Katragadda2b803212016-06-29 16:35:22 -0700869};
Deepak Katragadda582d6022016-11-09 16:17:45 -0800870EXPORT_SYMBOL_GPL(clk_generic_pll_postdiv_ops);