1
2
3
4
5
6
7#include <linux/of.h>
8#include <linux/of_address.h>
9#include <linux/io.h>
10#include <linux/slab.h>
11#include <linux/clkdev.h>
12#include <linux/delay.h>
13
14#include "clk-mtk.h"
15
16#define REG_CON0 0
17#define REG_CON1 4
18
19#define CON0_BASE_EN BIT(0)
20#define CON0_PWR_ON BIT(0)
21#define CON0_ISO_EN BIT(1)
22#define PCW_CHG_MASK BIT(31)
23
24#define AUDPLL_TUNER_EN BIT(31)
25
26#define POSTDIV_MASK 0x7
27
28
29#define INTEGER_BITS 7
30
31
32
33
34
35
36
37
38struct mtk_clk_pll {
39 struct clk_hw hw;
40 void __iomem *base_addr;
41 void __iomem *pd_addr;
42 void __iomem *pwr_addr;
43 void __iomem *tuner_addr;
44 void __iomem *tuner_en_addr;
45 void __iomem *pcw_addr;
46 void __iomem *pcw_chg_addr;
47 void __iomem *en_addr;
48 const struct mtk_pll_data *data;
49};
50
51static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
52{
53 return container_of(hw, struct mtk_clk_pll, hw);
54}
55
56static int mtk_pll_is_prepared(struct clk_hw *hw)
57{
58 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
59
60 return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0;
61}
62
63static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
64 u32 pcw, int postdiv)
65{
66 int pcwbits = pll->data->pcwbits;
67 int pcwfbits = 0;
68 int ibits;
69 u64 vco;
70 u8 c = 0;
71
72
73 ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
74 if (pcwbits > ibits)
75 pcwfbits = pcwbits - ibits;
76
77 vco = (u64)fin * pcw;
78
79 if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
80 c = 1;
81
82 vco >>= pcwfbits;
83
84 if (c)
85 vco++;
86
87 return ((unsigned long)vco + postdiv - 1) / postdiv;
88}
89
90static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll)
91{
92 u32 r;
93
94 if (pll->tuner_en_addr) {
95 r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
96 writel(r, pll->tuner_en_addr);
97 } else if (pll->tuner_addr) {
98 r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
99 writel(r, pll->tuner_addr);
100 }
101}
102
103static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll)
104{
105 u32 r;
106
107 if (pll->tuner_en_addr) {
108 r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
109 writel(r, pll->tuner_en_addr);
110 } else if (pll->tuner_addr) {
111 r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
112 writel(r, pll->tuner_addr);
113 }
114}
115
116static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
117 int postdiv)
118{
119 u32 chg, val;
120
121
122 __mtk_pll_tuner_disable(pll);
123
124
125 val = readl(pll->pd_addr);
126 val &= ~(POSTDIV_MASK << pll->data->pd_shift);
127 val |= (ffs(postdiv) - 1) << pll->data->pd_shift;
128
129
130 if (pll->pd_addr != pll->pcw_addr) {
131 writel(val, pll->pd_addr);
132 val = readl(pll->pcw_addr);
133 }
134
135
136 val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
137 pll->data->pcw_shift);
138 val |= pcw << pll->data->pcw_shift;
139 writel(val, pll->pcw_addr);
140 chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
141 writel(chg, pll->pcw_chg_addr);
142 if (pll->tuner_addr)
143 writel(val + 1, pll->tuner_addr);
144
145
146 __mtk_pll_tuner_enable(pll);
147
148 udelay(20);
149}
150
151
152
153
154
155
156
157
158
159
160static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
161 u32 freq, u32 fin)
162{
163 unsigned long fmin = pll->data->fmin ? pll->data->fmin : (1000 * MHZ);
164 const struct mtk_pll_div_table *div_table = pll->data->div_table;
165 u64 _pcw;
166 int ibits;
167 u32 val;
168
169 if (freq > pll->data->fmax)
170 freq = pll->data->fmax;
171
172 if (div_table) {
173 if (freq > div_table[0].freq)
174 freq = div_table[0].freq;
175
176 for (val = 0; div_table[val + 1].freq != 0; val++) {
177 if (freq > div_table[val + 1].freq)
178 break;
179 }
180 *postdiv = 1 << val;
181 } else {
182 for (val = 0; val < 5; val++) {
183 *postdiv = 1 << val;
184 if ((u64)freq * *postdiv >= fmin)
185 break;
186 }
187 }
188
189
190 ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
191 _pcw = ((u64)freq << val) << (pll->data->pcwbits - ibits);
192 do_div(_pcw, fin);
193
194 *pcw = (u32)_pcw;
195}
196
197static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
198 unsigned long parent_rate)
199{
200 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
201 u32 pcw = 0;
202 u32 postdiv;
203
204 mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
205 mtk_pll_set_rate_regs(pll, pcw, postdiv);
206
207 return 0;
208}
209
210static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
211 unsigned long parent_rate)
212{
213 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
214 u32 postdiv;
215 u32 pcw;
216
217 postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
218 postdiv = 1 << postdiv;
219
220 pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
221 pcw &= GENMASK(pll->data->pcwbits - 1, 0);
222
223 return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
224}
225
226static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
227 unsigned long *prate)
228{
229 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
230 u32 pcw = 0;
231 int postdiv;
232
233 mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
234
235 return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
236}
237
238static int mtk_pll_prepare(struct clk_hw *hw)
239{
240 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
241 u32 r;
242 u32 div_en_mask;
243
244 r = readl(pll->pwr_addr) | CON0_PWR_ON;
245 writel(r, pll->pwr_addr);
246 udelay(1);
247
248 r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
249 writel(r, pll->pwr_addr);
250 udelay(1);
251
252 r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit);
253 writel(r, pll->en_addr);
254
255 div_en_mask = pll->data->en_mask & ~CON0_BASE_EN;
256 if (div_en_mask) {
257 r = readl(pll->base_addr + REG_CON0) | div_en_mask;
258 writel(r, pll->base_addr + REG_CON0);
259 }
260
261 __mtk_pll_tuner_enable(pll);
262
263 udelay(20);
264
265 if (pll->data->flags & HAVE_RST_BAR) {
266 r = readl(pll->base_addr + REG_CON0);
267 r |= pll->data->rst_bar_mask;
268 writel(r, pll->base_addr + REG_CON0);
269 }
270
271 return 0;
272}
273
274static void mtk_pll_unprepare(struct clk_hw *hw)
275{
276 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
277 u32 r;
278 u32 div_en_mask;
279
280 if (pll->data->flags & HAVE_RST_BAR) {
281 r = readl(pll->base_addr + REG_CON0);
282 r &= ~pll->data->rst_bar_mask;
283 writel(r, pll->base_addr + REG_CON0);
284 }
285
286 __mtk_pll_tuner_disable(pll);
287
288 div_en_mask = pll->data->en_mask & ~CON0_BASE_EN;
289 if (div_en_mask) {
290 r = readl(pll->base_addr + REG_CON0) & ~div_en_mask;
291 writel(r, pll->base_addr + REG_CON0);
292 }
293
294 r = readl(pll->en_addr) & ~BIT(pll->data->pll_en_bit);
295 writel(r, pll->en_addr);
296
297 r = readl(pll->pwr_addr) | CON0_ISO_EN;
298 writel(r, pll->pwr_addr);
299
300 r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
301 writel(r, pll->pwr_addr);
302}
303
304static const struct clk_ops mtk_pll_ops = {
305 .is_prepared = mtk_pll_is_prepared,
306 .prepare = mtk_pll_prepare,
307 .unprepare = mtk_pll_unprepare,
308 .recalc_rate = mtk_pll_recalc_rate,
309 .round_rate = mtk_pll_round_rate,
310 .set_rate = mtk_pll_set_rate,
311};
312
313static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
314 void __iomem *base)
315{
316 struct mtk_clk_pll *pll;
317 struct clk_init_data init = {};
318 struct clk *clk;
319 const char *parent_name = "clk26m";
320
321 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
322 if (!pll)
323 return ERR_PTR(-ENOMEM);
324
325 pll->base_addr = base + data->reg;
326 pll->pwr_addr = base + data->pwr_reg;
327 pll->pd_addr = base + data->pd_reg;
328 pll->pcw_addr = base + data->pcw_reg;
329 if (data->pcw_chg_reg)
330 pll->pcw_chg_addr = base + data->pcw_chg_reg;
331 else
332 pll->pcw_chg_addr = pll->base_addr + REG_CON1;
333 if (data->tuner_reg)
334 pll->tuner_addr = base + data->tuner_reg;
335 if (data->tuner_en_reg)
336 pll->tuner_en_addr = base + data->tuner_en_reg;
337 if (data->en_reg)
338 pll->en_addr = base + data->en_reg;
339 else
340 pll->en_addr = pll->base_addr + REG_CON0;
341 pll->hw.init = &init;
342 pll->data = data;
343
344 init.name = data->name;
345 init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
346 init.ops = &mtk_pll_ops;
347 if (data->parent_name)
348 init.parent_names = &data->parent_name;
349 else
350 init.parent_names = &parent_name;
351 init.num_parents = 1;
352
353 clk = clk_register(NULL, &pll->hw);
354
355 if (IS_ERR(clk))
356 kfree(pll);
357
358 return clk;
359}
360
361void mtk_clk_register_plls(struct device_node *node,
362 const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
363{
364 void __iomem *base;
365 int i;
366 struct clk *clk;
367
368 base = of_iomap(node, 0);
369 if (!base) {
370 pr_err("%s(): ioremap failed\n", __func__);
371 return;
372 }
373
374 for (i = 0; i < num_plls; i++) {
375 const struct mtk_pll_data *pll = &plls[i];
376
377 clk = mtk_clk_register_pll(pll, base);
378
379 if (IS_ERR(clk)) {
380 pr_err("Failed to register clk %s: %ld\n",
381 pll->name, PTR_ERR(clk));
382 continue;
383 }
384
385 clk_data->clks[pll->id] = clk;
386 }
387}
388