blob: 3708b6f59f492d6b1a86b1fcaf0048b88531c02f [file] [log] [blame]
Cyril Chemparathy692a7af2010-06-07 14:13:32 -04001/*
2 * TNETV107X: Clock management APIs
3 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Cyril Chemparathy692a7af2010-06-07 14:13:32 -04005 */
6
7#include <common.h>
8#include <asm-generic/errno.h>
9#include <asm/io.h>
10#include <asm/processor.h>
11#include <asm/arch/clock.h>
12
13#define CLOCK_BASE TNETV107X_CLOCK_CONTROL_BASE
14#define PSC_BASE TNETV107X_PSC_BASE
15
16#define BIT(x) (1 << (x))
17
18#define MAX_PREDIV 64
19#define MAX_POSTDIV 8
20#define MAX_MULT 512
21#define MAX_DIV (MAX_PREDIV * MAX_POSTDIV)
22
23/* LPSC registers */
24#define PSC_PTCMD 0x120
25#define PSC_PTSTAT 0x128
26#define PSC_MDSTAT(n) (0x800 + (n) * 4)
27#define PSC_MDCTL(n) (0xA00 + (n) * 4)
28
29#define PSC_MDCTL_LRSTZ BIT(8)
30
31#define psc_reg_read(reg) __raw_readl((u32 *)(PSC_BASE + (reg)))
32#define psc_reg_write(reg, val) __raw_writel(val, (u32 *)(PSC_BASE + (reg)))
33
34/* SSPLL registers */
35struct sspll_regs {
36 u32 modes;
37 u32 postdiv;
38 u32 prediv;
39 u32 mult_factor;
40 u32 divider_range;
41 u32 bw_divider;
42 u32 spr_amount;
43 u32 spr_rate_div;
44 u32 diag;
45};
46
47/* SSPLL base addresses */
48static struct sspll_regs *sspll_regs[] = {
49 (struct sspll_regs *)(CLOCK_BASE + 0x040),
50 (struct sspll_regs *)(CLOCK_BASE + 0x080),
51 (struct sspll_regs *)(CLOCK_BASE + 0x0c0),
52};
53
54#define sspll_reg(pll, reg) (&(sspll_regs[pll]->reg))
55#define sspll_reg_read(pll, reg) __raw_readl(sspll_reg(pll, reg))
56#define sspll_reg_write(pll, reg, val) __raw_writel(val, sspll_reg(pll, reg))
57
58
59/* PLL Control Registers */
60struct pllctl_regs {
61 u32 ctl; /* 00 */
62 u32 ocsel; /* 04 */
63 u32 secctl; /* 08 */
64 u32 __pad0;
65 u32 mult; /* 10 */
66 u32 prediv; /* 14 */
67 u32 div1; /* 18 */
68 u32 div2; /* 1c */
69 u32 div3; /* 20 */
70 u32 oscdiv1; /* 24 */
71 u32 postdiv; /* 28 */
72 u32 bpdiv; /* 2c */
73 u32 wakeup; /* 30 */
74 u32 __pad1;
75 u32 cmd; /* 38 */
76 u32 stat; /* 3c */
77 u32 alnctl; /* 40 */
78 u32 dchange; /* 44 */
79 u32 cken; /* 48 */
80 u32 ckstat; /* 4c */
81 u32 systat; /* 50 */
82 u32 ckctl; /* 54 */
83 u32 __pad2[2];
84 u32 div4; /* 60 */
85 u32 div5; /* 64 */
86 u32 div6; /* 68 */
87 u32 div7; /* 6c */
88 u32 div8; /* 70 */
89};
90
91struct lpsc_map {
92 int pll, div;
93};
94
95static struct pllctl_regs *pllctl_regs[] = {
96 (struct pllctl_regs *)(CLOCK_BASE + 0x700),
97 (struct pllctl_regs *)(CLOCK_BASE + 0x300),
98 (struct pllctl_regs *)(CLOCK_BASE + 0x500),
99};
100
101#define pllctl_reg(pll, reg) (&(pllctl_regs[pll]->reg))
102#define pllctl_reg_read(pll, reg) __raw_readl(pllctl_reg(pll, reg))
103#define pllctl_reg_write(pll, reg, val) __raw_writel(val, pllctl_reg(pll, reg))
104
105#define pllctl_reg_rmw(pll, reg, mask, val) \
106 pllctl_reg_write(pll, reg, \
107 (pllctl_reg_read(pll, reg) & ~(mask)) | val)
108
109#define pllctl_reg_setbits(pll, reg, mask) \
110 pllctl_reg_rmw(pll, reg, 0, mask)
111
112#define pllctl_reg_clrbits(pll, reg, mask) \
113 pllctl_reg_rmw(pll, reg, mask, 0)
114
115/* PLLCTL Bits */
116#define PLLCTL_CLKMODE BIT(8)
117#define PLLCTL_PLLSELB BIT(7)
118#define PLLCTL_PLLENSRC BIT(5)
119#define PLLCTL_PLLDIS BIT(4)
120#define PLLCTL_PLLRST BIT(3)
121#define PLLCTL_PLLPWRDN BIT(1)
122#define PLLCTL_PLLEN BIT(0)
123
124#define PLLDIV_ENABLE BIT(15)
125
126static int pll_div_offset[] = {
127#define div_offset(reg) offsetof(struct pllctl_regs, reg)
128 div_offset(div1), div_offset(div2), div_offset(div3),
129 div_offset(div4), div_offset(div5), div_offset(div6),
130 div_offset(div7), div_offset(div8),
131};
132
133static unsigned long pll_bypass_mask[] = { 1, 4, 2 };
134static unsigned long pll_div_mask[] = { 0x01ff, 0x00ff, 0x00ff };
135
136/* Mappings from PLL+DIV to subsystem clocks */
137#define sys_arm1176_clk {SYS_PLL, 0}
138#define sys_dsp_clk {SYS_PLL, 1}
139#define sys_ddr_clk {SYS_PLL, 2}
140#define sys_full_clk {SYS_PLL, 3}
141#define sys_lcd_clk {SYS_PLL, 4}
142#define sys_vlynq_ref_clk {SYS_PLL, 5}
143#define sys_tsc_clk {SYS_PLL, 6}
144#define sys_half_clk {SYS_PLL, 7}
145
146#define eth_clk_5 {ETH_PLL, 0}
147#define eth_clk_50 {ETH_PLL, 1}
148#define eth_clk_125 {ETH_PLL, 2}
149#define eth_clk_250 {ETH_PLL, 3}
150#define eth_clk_25 {ETH_PLL, 4}
151
152#define tdm_clk {TDM_PLL, 0}
153#define tdm_extra_clk {TDM_PLL, 1}
154#define tdm1_clk {TDM_PLL, 2}
155
Cyril Chemparathy692a7af2010-06-07 14:13:32 -0400156static const struct lpsc_map lpsc_clk_map[] = {
157 [TNETV107X_LPSC_ARM] = sys_arm1176_clk,
158 [TNETV107X_LPSC_GEM] = sys_dsp_clk,
159 [TNETV107X_LPSC_DDR2_PHY] = sys_ddr_clk,
160 [TNETV107X_LPSC_TPCC] = sys_full_clk,
161 [TNETV107X_LPSC_TPTC0] = sys_full_clk,
162 [TNETV107X_LPSC_TPTC1] = sys_full_clk,
163 [TNETV107X_LPSC_RAM] = sys_full_clk,
164 [TNETV107X_LPSC_MBX_LITE] = sys_arm1176_clk,
165 [TNETV107X_LPSC_LCD] = sys_lcd_clk,
166 [TNETV107X_LPSC_ETHSS] = eth_clk_125,
167 [TNETV107X_LPSC_AEMIF] = sys_full_clk,
168 [TNETV107X_LPSC_CHIP_CFG] = sys_half_clk,
169 [TNETV107X_LPSC_TSC] = sys_tsc_clk,
170 [TNETV107X_LPSC_ROM] = sys_half_clk,
171 [TNETV107X_LPSC_UART2] = sys_half_clk,
172 [TNETV107X_LPSC_PKTSEC] = sys_half_clk,
173 [TNETV107X_LPSC_SECCTL] = sys_half_clk,
174 [TNETV107X_LPSC_KEYMGR] = sys_half_clk,
175 [TNETV107X_LPSC_KEYPAD] = sys_half_clk,
176 [TNETV107X_LPSC_GPIO] = sys_half_clk,
177 [TNETV107X_LPSC_MDIO] = sys_half_clk,
178 [TNETV107X_LPSC_SDIO0] = sys_half_clk,
179 [TNETV107X_LPSC_UART0] = sys_half_clk,
180 [TNETV107X_LPSC_UART1] = sys_half_clk,
181 [TNETV107X_LPSC_TIMER0] = sys_half_clk,
182 [TNETV107X_LPSC_TIMER1] = sys_half_clk,
183 [TNETV107X_LPSC_WDT_ARM] = sys_half_clk,
184 [TNETV107X_LPSC_WDT_DSP] = sys_half_clk,
185 [TNETV107X_LPSC_SSP] = sys_half_clk,
186 [TNETV107X_LPSC_TDM0] = tdm_clk,
187 [TNETV107X_LPSC_VLYNQ] = sys_vlynq_ref_clk,
188 [TNETV107X_LPSC_MCDMA] = sys_half_clk,
189 [TNETV107X_LPSC_USB0] = sys_half_clk,
190 [TNETV107X_LPSC_TDM1] = tdm1_clk,
191 [TNETV107X_LPSC_DEBUGSS] = sys_half_clk,
192 [TNETV107X_LPSC_ETHSS_RGMII] = eth_clk_250,
193 [TNETV107X_LPSC_SYSTEM] = sys_half_clk,
194 [TNETV107X_LPSC_IMCOP] = sys_dsp_clk,
195 [TNETV107X_LPSC_SPARE] = sys_half_clk,
196 [TNETV107X_LPSC_SDIO1] = sys_half_clk,
197 [TNETV107X_LPSC_USB1] = sys_half_clk,
198 [TNETV107X_LPSC_USBSS] = sys_half_clk,
199 [TNETV107X_LPSC_DDR2_EMIF1_VRST] = sys_ddr_clk,
200 [TNETV107X_LPSC_DDR2_EMIF2_VCTL_RST] = sys_ddr_clk,
201};
202
203static const unsigned long pll_ext_freq[] = {
204 [SYS_PLL] = CONFIG_PLL_SYS_EXT_FREQ,
205 [ETH_PLL] = CONFIG_PLL_ETH_EXT_FREQ,
206 [TDM_PLL] = CONFIG_PLL_TDM_EXT_FREQ,
207};
208
209static unsigned long pll_freq_get(int pll)
210{
211 unsigned long mult = 1, prediv = 1, postdiv = 1;
212 unsigned long ref = CONFIG_SYS_INT_OSC_FREQ;
213 unsigned long ret;
214 u32 bypass;
215
216 bypass = __raw_readl((u32 *)(CLOCK_BASE));
217 if (!(bypass & pll_bypass_mask[pll])) {
218 mult = sspll_reg_read(pll, mult_factor);
219 prediv = sspll_reg_read(pll, prediv) + 1;
220 postdiv = sspll_reg_read(pll, postdiv) + 1;
221 }
222
223 if (pllctl_reg_read(pll, ctl) & PLLCTL_CLKMODE)
224 ref = pll_ext_freq[pll];
225
226 if (!(pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN))
227 return ref;
228
229 ret = (unsigned long)(ref + ((unsigned long long)ref * mult) / 256);
230 ret /= (prediv * postdiv);
231
232 return ret;
233}
234
235static unsigned long __pll_div_freq_get(int pll, unsigned int fpll,
236 int div)
237{
238 int divider = 1;
239 unsigned long divreg;
240
241 divreg = __raw_readl((void *)pllctl_regs[pll] + pll_div_offset[div]);
242
243 if (divreg & PLLDIV_ENABLE)
244 divider = (divreg & pll_div_mask[pll]) + 1;
245
246 return fpll / divider;
247}
248
249static unsigned long pll_div_freq_get(int pll, int div)
250{
251 unsigned int fpll = pll_freq_get(pll);
252
253 return __pll_div_freq_get(pll, fpll, div);
254}
255
256static void __pll_div_freq_set(int pll, unsigned int fpll, int div,
257 unsigned long hz)
258{
259 int divider = (fpll / hz - 1);
260
261 divider &= pll_div_mask[pll];
262 divider |= PLLDIV_ENABLE;
263
264 __raw_writel(divider, (void *)pllctl_regs[pll] + pll_div_offset[div]);
265 pllctl_reg_setbits(pll, alnctl, (1 << div));
266 pllctl_reg_setbits(pll, dchange, (1 << div));
267}
268
269static unsigned long pll_div_freq_set(int pll, int div, unsigned long hz)
270{
271 unsigned int fpll = pll_freq_get(pll);
272
273 __pll_div_freq_set(pll, fpll, div, hz);
274
275 pllctl_reg_write(pll, cmd, 1);
276
277 /* Wait until new divider takes effect */
278 while (pllctl_reg_read(pll, stat) & 0x01);
279
280 return __pll_div_freq_get(pll, fpll, div);
281}
282
283unsigned long clk_get_rate(unsigned int clk)
284{
285 return pll_div_freq_get(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div);
286}
287
288unsigned long clk_round_rate(unsigned int clk, unsigned long hz)
289{
290 unsigned long fpll, divider, pll;
291
292 pll = lpsc_clk_map[clk].pll;
293 fpll = pll_freq_get(pll);
294 divider = (fpll / hz - 1);
295 divider &= pll_div_mask[pll];
296
297 return fpll / (divider + 1);
298}
299
300int clk_set_rate(unsigned int clk, unsigned long _hz)
301{
302 unsigned long hz;
303
304 hz = clk_round_rate(clk, _hz);
305 if (hz != _hz)
306 return -EINVAL; /* Cannot set to target freq */
307
308 pll_div_freq_set(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div, hz);
309 return 0;
310}
311
312void lpsc_control(int mod, unsigned long state, int lrstz)
313{
314 u32 mdctl;
315
316 mdctl = psc_reg_read(PSC_MDCTL(mod));
317 mdctl &= ~0x1f;
318 mdctl |= state;
319
320 if (lrstz == 0)
321 mdctl &= ~PSC_MDCTL_LRSTZ;
322 else if (lrstz == 1)
323 mdctl |= PSC_MDCTL_LRSTZ;
324
325 psc_reg_write(PSC_MDCTL(mod), mdctl);
326
327 psc_reg_write(PSC_PTCMD, 1);
328
329 /* wait for power domain transition to end */
330 while (psc_reg_read(PSC_PTSTAT) & 1);
331
332 /* Wait for module state change */
333 while ((psc_reg_read(PSC_MDSTAT(mod)) & 0x1f) != state);
334}
335
336int lpsc_status(unsigned int id)
337{
338 return psc_reg_read(PSC_MDSTAT(id)) & 0x1f;
339}
340
341static void init_pll(const struct pll_init_data *data)
342{
343 unsigned long fpll;
344 unsigned long best_pre = 0, best_post = 0, best_mult = 0;
345 unsigned long div, prediv, postdiv, mult;
346 unsigned long delta, actual;
347 long best_delta = -1;
348 int i;
349 u32 tmp;
350
351 if (data->pll == SYS_PLL)
352 return; /* cannot reconfigure system pll on the fly */
353
354 tmp = pllctl_reg_read(data->pll, ctl);
355 if (data->internal_osc) {
356 tmp &= ~PLLCTL_CLKMODE;
357 fpll = CONFIG_SYS_INT_OSC_FREQ;
358 } else {
359 tmp |= PLLCTL_CLKMODE;
360 fpll = pll_ext_freq[data->pll];
361 }
362 pllctl_reg_write(data->pll, ctl, tmp);
363
364 mult = data->pll_freq / fpll;
365 for (mult = MAX(mult, 1); mult <= MAX_MULT; mult++) {
366 div = (fpll * mult) / data->pll_freq;
367 if (div < 1 || div > MAX_DIV)
368 continue;
369
370 for (postdiv = 1; postdiv <= min(div, MAX_POSTDIV); postdiv++) {
371 prediv = div / postdiv;
372 if (prediv < 1 || prediv > MAX_PREDIV)
373 continue;
374
375 actual = (fpll / prediv) * (mult / postdiv);
376 delta = (actual - data->pll_freq);
377 if (delta < 0)
378 delta = -delta;
379 if ((delta < best_delta) || (best_delta == -1)) {
380 best_delta = delta;
381 best_mult = mult;
382 best_pre = prediv;
383 best_post = postdiv;
384 if (delta == 0)
385 goto done;
386 }
387 }
388 }
389done:
390
391 if (best_delta == -1) {
392 printf("pll cannot derive %lu from %lu\n",
393 data->pll_freq, fpll);
394 return;
395 }
396
397 fpll = fpll * best_mult;
398 fpll /= best_pre * best_post;
399
400 pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLENSRC);
401 pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN);
402
403 pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST);
404
405 pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN);
406 pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLDIS);
407
408 sspll_reg_write(data->pll, mult_factor, (best_mult - 1) << 8);
409 sspll_reg_write(data->pll, prediv, best_pre - 1);
410 sspll_reg_write(data->pll, postdiv, best_post - 1);
411
412 for (i = 0; i < 10; i++)
413 if (data->div_freq[i])
414 __pll_div_freq_set(data->pll, fpll, i,
415 data->div_freq[i]);
416
417 pllctl_reg_write(data->pll, cmd, 1);
418
419 /* Wait until pll "go" operation completes */
420 while (pllctl_reg_read(data->pll, stat) & 0x01);
421
422 pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST);
423 pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN);
424}
425
426void init_plls(int num_pll, struct pll_init_data *config)
427{
428 int i;
429
430 for (i = 0; i < num_pll; i++)
431 init_pll(&config[i]);
432}