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