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