blob: c1158c132903d524929f4e1be203b75991aad683 [file] [log] [blame]
Tero Kristo81744b72021-06-11 11:45:13 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments K3 SoC PLL clock driver
4 *
Dave Gerlach6bc722e2021-09-07 17:16:57 -05005 * Copyright (C) 2020-2021 Texas Instruments Incorporated - http://www.ti.com/
Tero Kristo81744b72021-06-11 11:45:13 +03006 * Tero Kristo <t-kristo@ti.com>
7 */
8
9#include <common.h>
10#include <asm/io.h>
11#include <dm.h>
12#include <div64.h>
13#include <errno.h>
14#include <clk-uclass.h>
15#include <linux/clk-provider.h>
16#include "k3-clk.h"
17#include <linux/rational.h>
18
19/* 16FFT register offsets */
20#define PLL_16FFT_CFG 0x08
21#define PLL_KICK0 0x10
22#define PLL_KICK1 0x14
23#define PLL_16FFT_CTRL 0x20
24#define PLL_16FFT_STAT 0x24
25#define PLL_16FFT_FREQ_CTRL0 0x30
26#define PLL_16FFT_FREQ_CTRL1 0x34
27#define PLL_16FFT_DIV_CTRL 0x38
Vishal Mahaveera5135b82023-10-23 08:35:46 -050028#define PLL_16FFT_CAL_CTRL 0x60
29#define PLL_16FFT_CAL_STAT 0x64
30
31/* CAL STAT register bits */
32#define PLL_16FFT_CAL_STAT_CAL_LOCK BIT(31)
33
34/* CFG register bits */
35#define PLL_16FFT_CFG_PLL_TYPE_SHIFT (0)
36#define PLL_16FFT_CFG_PLL_TYPE_MASK (0x3 << 0)
37#define PLL_16FFT_CFG_PLL_TYPE_FRACF 1
38
39/* CAL CTRL register bits */
40#define PLL_16FFT_CAL_CTRL_CAL_EN BIT(31)
41#define PLL_16FFT_CAL_CTRL_FAST_CAL BIT(20)
42#define PLL_16FFT_CAL_CTRL_CAL_BYP BIT(15)
43#define PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT 16
44#define PLL_16FFT_CAL_CTRL_CAL_CNT_MASK (0x7 << 16)
Tero Kristo81744b72021-06-11 11:45:13 +030045
46/* CTRL register bits */
47#define PLL_16FFT_CTRL_BYPASS_EN BIT(31)
48#define PLL_16FFT_CTRL_PLL_EN BIT(15)
49#define PLL_16FFT_CTRL_DSM_EN BIT(1)
50
51/* STAT register bits */
52#define PLL_16FFT_STAT_LOCK BIT(0)
53
54/* FREQ_CTRL0 bits */
55#define PLL_16FFT_FREQ_CTRL0_FB_DIV_INT_MASK 0xfff
56
57/* DIV CTRL register bits */
58#define PLL_16FFT_DIV_CTRL_REF_DIV_MASK 0x3f
59
Vishal Mahaveera5135b82023-10-23 08:35:46 -050060/* HSDIV register bits*/
Tero Kristo81744b72021-06-11 11:45:13 +030061#define PLL_16FFT_HSDIV_CTRL_CLKOUT_EN BIT(15)
62
Vishal Mahaveera5135b82023-10-23 08:35:46 -050063/* FREQ_CTRL1 bits */
64#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24
65#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK 0xffffff
66#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT 0
67
Tero Kristo81744b72021-06-11 11:45:13 +030068/* KICK register magic values */
69#define PLL_KICK0_VALUE 0x68ef3490
70#define PLL_KICK1_VALUE 0xd172bc5a
71
72/**
73 * struct ti_pll_clk - TI PLL clock data info structure
74 * @clk: core clock structure
75 * @reg: memory address of the PLL controller
76 */
77struct ti_pll_clk {
78 struct clk clk;
79 void __iomem *reg;
80};
81
82#define to_clk_pll(_clk) container_of(_clk, struct ti_pll_clk, clk)
83
84static int ti_pll_wait_for_lock(struct clk *clk)
85{
86 struct ti_pll_clk *pll = to_clk_pll(clk);
87 u32 stat;
Vishal Mahaveera5135b82023-10-23 08:35:46 -050088 u32 cfg;
89 u32 cal;
90 u32 freq_ctrl1;
Tero Kristo81744b72021-06-11 11:45:13 +030091 int i;
Vishal Mahaveera5135b82023-10-23 08:35:46 -050092 u32 pllfm;
93 u32 pll_type;
94 int success;
Tero Kristo81744b72021-06-11 11:45:13 +030095
96 for (i = 0; i < 100000; i++) {
97 stat = readl(pll->reg + PLL_16FFT_STAT);
Vishal Mahaveera5135b82023-10-23 08:35:46 -050098 if (stat & PLL_16FFT_STAT_LOCK) {
99 success = 1;
100 break;
101 }
Tero Kristo81744b72021-06-11 11:45:13 +0300102 }
103
Vishal Mahaveera5135b82023-10-23 08:35:46 -0500104 /* Enable calibration if not in fractional mode of the FRACF PLL */
105 freq_ctrl1 = readl(pll->reg + PLL_16FFT_FREQ_CTRL1);
106 pllfm = freq_ctrl1 & PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK;
107 pllfm >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT;
108 cfg = readl(pll->reg + PLL_16FFT_CFG);
109 pll_type = (cfg & PLL_16FFT_CFG_PLL_TYPE_MASK) >> PLL_16FFT_CFG_PLL_TYPE_SHIFT;
Tero Kristo81744b72021-06-11 11:45:13 +0300110
Vishal Mahaveera5135b82023-10-23 08:35:46 -0500111 if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF && pllfm == 0) {
112 cal = readl(pll->reg + PLL_16FFT_CAL_CTRL);
113
114 /* Enable calibration for FRACF */
115 cal |= PLL_16FFT_CAL_CTRL_CAL_EN;
116
117 /* Enable fast cal mode */
118 cal |= PLL_16FFT_CAL_CTRL_FAST_CAL;
119
120 /* Disable calibration bypass */
121 cal &= ~PLL_16FFT_CAL_CTRL_CAL_BYP;
122
123 /* Set CALCNT to 2 */
124 cal &= ~PLL_16FFT_CAL_CTRL_CAL_CNT_MASK;
125 cal |= 2 << PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT;
126
127 /* Note this register does not readback the written value. */
128 writel(cal, pll->reg + PLL_16FFT_CAL_CTRL);
129
130 success = 0;
131 for (i = 0; i < 100000; i++) {
132 stat = readl(pll->reg + PLL_16FFT_CAL_STAT);
133 if (stat & PLL_16FFT_CAL_STAT_CAL_LOCK) {
134 success = 1;
135 break;
136 }
137 }
138 }
139
140 if (success == 0) {
141 printf("%s: pll (%s) failed to lock\n", __func__,
142 clk->dev->name);
143 return -EBUSY;
144 } else {
145 return 0;
146 }
Tero Kristo81744b72021-06-11 11:45:13 +0300147}
148
149static ulong ti_pll_clk_get_rate(struct clk *clk)
150{
151 struct ti_pll_clk *pll = to_clk_pll(clk);
152 u64 current_freq;
153 u64 parent_freq = clk_get_parent_rate(clk);
154 u32 pllm;
155 u32 plld;
156 u32 pllfm;
157 u32 ctrl;
158
159 /* Check if we are in bypass */
160 ctrl = readl(pll->reg + PLL_16FFT_CTRL);
161 if (ctrl & PLL_16FFT_CTRL_BYPASS_EN)
162 return parent_freq;
163
164 pllm = readl(pll->reg + PLL_16FFT_FREQ_CTRL0);
165 pllfm = readl(pll->reg + PLL_16FFT_FREQ_CTRL1);
166
167 plld = readl(pll->reg + PLL_16FFT_DIV_CTRL) &
168 PLL_16FFT_DIV_CTRL_REF_DIV_MASK;
169
170 current_freq = parent_freq * pllm / plld;
171
172 if (pllfm) {
173 u64 tmp;
174
175 tmp = parent_freq * pllfm;
176 do_div(tmp, plld);
177 tmp >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS;
178 current_freq += tmp;
179 }
180
181 return current_freq;
182}
183
184static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate)
185{
186 struct ti_pll_clk *pll = to_clk_pll(clk);
187 u64 current_freq;
188 u64 parent_freq = clk_get_parent_rate(clk);
189 int ret;
190 u32 ctrl;
191 unsigned long pllm;
192 u32 pllfm = 0;
193 unsigned long plld;
Dave Gerlach6bc722e2021-09-07 17:16:57 -0500194 u32 div_ctrl;
Tero Kristo81744b72021-06-11 11:45:13 +0300195 u32 rem;
196 int shift;
197
198 debug("%s(clk=%p, rate=%u)\n", __func__, clk, (u32)rate);
199
200 if (ti_pll_clk_get_rate(clk) == rate)
201 return rate;
202
203 if (rate != parent_freq)
204 /*
205 * Attempt with higher max multiplier value first to give
206 * some space for fractional divider to kick in.
207 */
208 for (shift = 8; shift >= 0; shift -= 8) {
209 rational_best_approximation(rate, parent_freq,
210 ((PLL_16FFT_FREQ_CTRL0_FB_DIV_INT_MASK + 1) << shift) - 1,
211 PLL_16FFT_DIV_CTRL_REF_DIV_MASK, &pllm, &plld);
212 if (pllm / plld <= PLL_16FFT_FREQ_CTRL0_FB_DIV_INT_MASK)
213 break;
214 }
215
216 /* Put PLL to bypass mode */
217 ctrl = readl(pll->reg + PLL_16FFT_CTRL);
218 ctrl |= PLL_16FFT_CTRL_BYPASS_EN;
219 writel(ctrl, pll->reg + PLL_16FFT_CTRL);
220
221 if (rate == parent_freq) {
222 debug("%s: put %s to bypass\n", __func__, clk->dev->name);
223 return rate;
224 }
225
226 debug("%s: pre-frac-calc: rate=%u, parent_freq=%u, plld=%u, pllm=%u\n",
227 __func__, (u32)rate, (u32)parent_freq, (u32)plld, (u32)pllm);
228
229 /* Check if we need fractional config */
230 if (plld > 1) {
231 pllfm = pllm % plld;
232 pllfm <<= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS;
233 rem = pllfm % plld;
234 pllfm /= plld;
235 if (rem)
236 pllfm++;
237 pllm /= plld;
238 plld = 1;
239 }
240
241 if (pllfm)
242 ctrl |= PLL_16FFT_CTRL_DSM_EN;
243 else
244 ctrl &= ~PLL_16FFT_CTRL_DSM_EN;
245
246 writel(pllm, pll->reg + PLL_16FFT_FREQ_CTRL0);
247 writel(pllfm, pll->reg + PLL_16FFT_FREQ_CTRL1);
Dave Gerlach6bc722e2021-09-07 17:16:57 -0500248
249 /*
250 * div_ctrl register contains other divider values, so rmw
251 * only plld and leave existing values alone
252 */
253 div_ctrl = readl(pll->reg + PLL_16FFT_DIV_CTRL);
254 div_ctrl &= ~PLL_16FFT_DIV_CTRL_REF_DIV_MASK;
255 div_ctrl |= plld;
256 writel(div_ctrl, pll->reg + PLL_16FFT_DIV_CTRL);
Tero Kristo81744b72021-06-11 11:45:13 +0300257
258 ctrl &= ~PLL_16FFT_CTRL_BYPASS_EN;
259 ctrl |= PLL_16FFT_CTRL_PLL_EN;
260 writel(ctrl, pll->reg + PLL_16FFT_CTRL);
261
262 ret = ti_pll_wait_for_lock(clk);
263 if (ret)
264 return ret;
265
266 debug("%s: pllm=%u, plld=%u, pllfm=%u, parent_freq=%u\n",
267 __func__, (u32)pllm, (u32)plld, (u32)pllfm, (u32)parent_freq);
268
269 current_freq = parent_freq * pllm / plld;
270
271 if (pllfm) {
272 u64 tmp;
273
274 tmp = parent_freq * pllfm;
275 do_div(tmp, plld);
276 tmp >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS;
277 current_freq += tmp;
278 }
279
280 return current_freq;
281}
282
283static int ti_pll_clk_enable(struct clk *clk)
284{
285 struct ti_pll_clk *pll = to_clk_pll(clk);
286 u32 ctrl;
287
288 ctrl = readl(pll->reg + PLL_16FFT_CTRL);
289 ctrl &= ~PLL_16FFT_CTRL_BYPASS_EN;
290 ctrl |= PLL_16FFT_CTRL_PLL_EN;
291 writel(ctrl, pll->reg + PLL_16FFT_CTRL);
292
293 return ti_pll_wait_for_lock(clk);
294}
295
296static int ti_pll_clk_disable(struct clk *clk)
297{
298 struct ti_pll_clk *pll = to_clk_pll(clk);
299 u32 ctrl;
300
301 ctrl = readl(pll->reg + PLL_16FFT_CTRL);
302 ctrl |= PLL_16FFT_CTRL_BYPASS_EN;
303 writel(ctrl, pll->reg + PLL_16FFT_CTRL);
304
305 return 0;
306}
307
308static const struct clk_ops ti_pll_clk_ops = {
309 .get_rate = ti_pll_clk_get_rate,
310 .set_rate = ti_pll_clk_set_rate,
311 .enable = ti_pll_clk_enable,
312 .disable = ti_pll_clk_disable,
313};
314
315struct clk *clk_register_ti_pll(const char *name, const char *parent_name,
316 void __iomem *reg)
317{
318 struct ti_pll_clk *pll;
319 int ret;
320 int i;
321 u32 cfg, ctrl, hsdiv_presence_bit, hsdiv_ctrl_offs;
322
323 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
324 if (!pll)
325 return ERR_PTR(-ENOMEM);
326
327 pll->reg = reg;
328
329 ret = clk_register(&pll->clk, "ti-pll-clk", name, parent_name);
330 if (ret) {
331 printf("%s: failed to register: %d\n", __func__, ret);
332 kfree(pll);
333 return ERR_PTR(ret);
334 }
335
336 /* Unlock the PLL registers */
337 writel(PLL_KICK0_VALUE, pll->reg + PLL_KICK0);
338 writel(PLL_KICK1_VALUE, pll->reg + PLL_KICK1);
339
340 /* Enable all HSDIV outputs */
341 cfg = readl(pll->reg + PLL_16FFT_CFG);
342 for (i = 0; i < 16; i++) {
343 hsdiv_presence_bit = BIT(16 + i);
344 hsdiv_ctrl_offs = 0x80 + (i * 4);
345 /* Enable HSDIV output if present */
346 if ((hsdiv_presence_bit & cfg) != 0UL) {
347 ctrl = readl(pll->reg + hsdiv_ctrl_offs);
348 ctrl |= PLL_16FFT_HSDIV_CTRL_CLKOUT_EN;
349 writel(ctrl, pll->reg + hsdiv_ctrl_offs);
350 }
351 }
352
353 return &pll->clk;
354}
355
356U_BOOT_DRIVER(ti_pll_clk) = {
357 .name = "ti-pll-clk",
358 .id = UCLASS_CLK,
359 .ops = &ti_pll_clk_ops,
360 .flags = DM_FLAG_PRE_RELOC,
361};