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