Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[pandora-kernel.git] / arch / mips / ar7 / clock.c
1 /*
2  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
3  * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/types.h>
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/gcd.h>
26 #include <linux/io.h>
27
28 #include <asm/addrspace.h>
29 #include <asm/mach-ar7/ar7.h>
30
31 #define BOOT_PLL_SOURCE_MASK    0x3
32 #define CPU_PLL_SOURCE_SHIFT    16
33 #define BUS_PLL_SOURCE_SHIFT    14
34 #define USB_PLL_SOURCE_SHIFT    18
35 #define DSP_PLL_SOURCE_SHIFT    22
36 #define BOOT_PLL_SOURCE_AFE     0
37 #define BOOT_PLL_SOURCE_BUS     0
38 #define BOOT_PLL_SOURCE_REF     1
39 #define BOOT_PLL_SOURCE_XTAL    2
40 #define BOOT_PLL_SOURCE_CPU     3
41 #define BOOT_PLL_BYPASS         0x00000020
42 #define BOOT_PLL_ASYNC_MODE     0x02000000
43 #define BOOT_PLL_2TO1_MODE      0x00008000
44
45 #define TNETD7200_CLOCK_ID_CPU  0
46 #define TNETD7200_CLOCK_ID_DSP  1
47 #define TNETD7200_CLOCK_ID_USB  2
48
49 #define TNETD7200_DEF_CPU_CLK   211000000
50 #define TNETD7200_DEF_DSP_CLK   125000000
51 #define TNETD7200_DEF_USB_CLK   48000000
52
53 struct tnetd7300_clock {
54         u32 ctrl;
55 #define PREDIV_MASK     0x001f0000
56 #define PREDIV_SHIFT    16
57 #define POSTDIV_MASK    0x0000001f
58         u32 unused1[3];
59         u32 pll;
60 #define MUL_MASK        0x0000f000
61 #define MUL_SHIFT       12
62 #define PLL_MODE_MASK   0x00000001
63 #define PLL_NDIV        0x00000800
64 #define PLL_DIV         0x00000002
65 #define PLL_STATUS      0x00000001
66         u32 unused2[3];
67 };
68
69 struct tnetd7300_clocks {
70         struct tnetd7300_clock bus;
71         struct tnetd7300_clock cpu;
72         struct tnetd7300_clock usb;
73         struct tnetd7300_clock dsp;
74 };
75
76 struct tnetd7200_clock {
77         u32 ctrl;
78         u32 unused1[3];
79 #define DIVISOR_ENABLE_MASK 0x00008000
80         u32 mul;
81         u32 prediv;
82         u32 postdiv;
83         u32 postdiv2;
84         u32 unused2[6];
85         u32 cmd;
86         u32 status;
87         u32 cmden;
88         u32 padding[15];
89 };
90
91 struct tnetd7200_clocks {
92         struct tnetd7200_clock cpu;
93         struct tnetd7200_clock dsp;
94         struct tnetd7200_clock usb;
95 };
96
97 int ar7_cpu_clock = 150000000;
98 EXPORT_SYMBOL(ar7_cpu_clock);
99 int ar7_bus_clock = 125000000;
100 EXPORT_SYMBOL(ar7_bus_clock);
101 int ar7_dsp_clock;
102 EXPORT_SYMBOL(ar7_dsp_clock);
103
104 static void approximate(int base, int target, int *prediv,
105                         int *postdiv, int *mul)
106 {
107         int i, j, k, freq, res = target;
108         for (i = 1; i <= 16; i++)
109                 for (j = 1; j <= 32; j++)
110                         for (k = 1; k <= 32; k++) {
111                                 freq = abs(base / j * i / k - target);
112                                 if (freq < res) {
113                                         res = freq;
114                                         *mul = i;
115                                         *prediv = j;
116                                         *postdiv = k;
117                                 }
118                         }
119 }
120
121 static void calculate(int base, int target, int *prediv, int *postdiv,
122         int *mul)
123 {
124         int tmp_gcd, tmp_base, tmp_freq;
125
126         for (*prediv = 1; *prediv <= 32; (*prediv)++) {
127                 tmp_base = base / *prediv;
128                 tmp_gcd = gcd(target, tmp_base);
129                 *mul = target / tmp_gcd;
130                 *postdiv = tmp_base / tmp_gcd;
131                 if ((*mul < 1) || (*mul >= 16))
132                         continue;
133                 if ((*postdiv > 0) & (*postdiv <= 32))
134                         break;
135         }
136
137         if (base / *prediv * *mul / *postdiv != target) {
138                 approximate(base, target, prediv, postdiv, mul);
139                 tmp_freq = base / *prediv * *mul / *postdiv;
140                 printk(KERN_WARNING
141                        "Adjusted requested frequency %d to %d\n",
142                        target, tmp_freq);
143         }
144
145         printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
146                *prediv, *postdiv, *mul);
147 }
148
149 static int tnetd7300_dsp_clock(void)
150 {
151         u32 didr1, didr2;
152         u8 rev = ar7_chip_rev();
153         didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
154         didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
155         if (didr2 & (1 << 23))
156                 return 0;
157         if ((rev >= 0x23) && (rev != 0x57))
158                 return 250000000;
159         if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
160             > 4208000)
161                 return 250000000;
162         return 0;
163 }
164
165 static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
166         u32 *bootcr, u32 bus_clock)
167 {
168         int product;
169         int base_clock = AR7_REF_CLOCK;
170         u32 ctrl = readl(&clock->ctrl);
171         u32 pll = readl(&clock->pll);
172         int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
173         int postdiv = (ctrl & POSTDIV_MASK) + 1;
174         int divisor = prediv * postdiv;
175         int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
176
177         switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
178         case BOOT_PLL_SOURCE_BUS:
179                 base_clock = bus_clock;
180                 break;
181         case BOOT_PLL_SOURCE_REF:
182                 base_clock = AR7_REF_CLOCK;
183                 break;
184         case BOOT_PLL_SOURCE_XTAL:
185                 base_clock = AR7_XTAL_CLOCK;
186                 break;
187         case BOOT_PLL_SOURCE_CPU:
188                 base_clock = ar7_cpu_clock;
189                 break;
190         }
191
192         if (*bootcr & BOOT_PLL_BYPASS)
193                 return base_clock / divisor;
194
195         if ((pll & PLL_MODE_MASK) == 0)
196                 return (base_clock >> (mul / 16 + 1)) / divisor;
197
198         if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
199                 product = (mul & 1) ?
200                         (base_clock * mul) >> 1 :
201                         (base_clock * (mul - 1)) >> 2;
202                 return product / divisor;
203         }
204
205         if (mul == 16)
206                 return base_clock / divisor;
207
208         return base_clock * mul / divisor;
209 }
210
211 static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
212         u32 *bootcr, u32 frequency)
213 {
214         int prediv, postdiv, mul;
215         int base_clock = ar7_bus_clock;
216
217         switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
218         case BOOT_PLL_SOURCE_BUS:
219                 base_clock = ar7_bus_clock;
220                 break;
221         case BOOT_PLL_SOURCE_REF:
222                 base_clock = AR7_REF_CLOCK;
223                 break;
224         case BOOT_PLL_SOURCE_XTAL:
225                 base_clock = AR7_XTAL_CLOCK;
226                 break;
227         case BOOT_PLL_SOURCE_CPU:
228                 base_clock = ar7_cpu_clock;
229                 break;
230         }
231
232         calculate(base_clock, frequency, &prediv, &postdiv, &mul);
233
234         writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
235         msleep(1);
236         writel(4, &clock->pll);
237         while (readl(&clock->pll) & PLL_STATUS)
238                 ;
239         writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
240         msleep(75);
241 }
242
243 static void __init tnetd7300_init_clocks(void)
244 {
245         u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
246         struct tnetd7300_clocks *clocks =
247                                         ioremap_nocache(UR8_REGS_CLOCKS,
248                                         sizeof(struct tnetd7300_clocks));
249
250         ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
251                 &clocks->bus, bootcr, AR7_AFE_CLOCK);
252
253         if (*bootcr & BOOT_PLL_ASYNC_MODE)
254                 ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
255                         &clocks->cpu, bootcr, AR7_AFE_CLOCK);
256         else
257                 ar7_cpu_clock = ar7_bus_clock;
258
259         if (ar7_dsp_clock == 250000000)
260                 tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
261                         bootcr, ar7_dsp_clock);
262
263         iounmap(clocks);
264         iounmap(bootcr);
265 }
266
267 static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
268         int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
269 {
270         printk(KERN_INFO
271                 "Clocks: base = %d, frequency = %u, prediv = %d, "
272                 "postdiv = %d, postdiv2 = %d, mul = %d\n",
273                 base, frequency, prediv, postdiv, postdiv2, mul);
274
275         writel(0, &clock->ctrl);
276         writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
277         writel((mul - 1) & 0xF, &clock->mul);
278
279         while (readl(&clock->status) & 0x1)
280                 ; /* nop */
281
282         writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
283
284         writel(readl(&clock->cmden) | 1, &clock->cmden);
285         writel(readl(&clock->cmd) | 1, &clock->cmd);
286
287         while (readl(&clock->status) & 0x1)
288                 ; /* nop */
289
290         writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
291
292         writel(readl(&clock->cmden) | 1, &clock->cmden);
293         writel(readl(&clock->cmd) | 1, &clock->cmd);
294
295         while (readl(&clock->status) & 0x1)
296                 ; /* nop */
297
298         writel(readl(&clock->ctrl) | 1, &clock->ctrl);
299 }
300
301 static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
302 {
303         if (*bootcr & BOOT_PLL_ASYNC_MODE)
304                 /* Async */
305                 switch (clock_id) {
306                 case TNETD7200_CLOCK_ID_DSP:
307                         return AR7_REF_CLOCK;
308                 default:
309                         return AR7_AFE_CLOCK;
310                 }
311         else
312                 /* Sync */
313                 if (*bootcr & BOOT_PLL_2TO1_MODE)
314                         /* 2:1 */
315                         switch (clock_id) {
316                         case TNETD7200_CLOCK_ID_DSP:
317                                 return AR7_REF_CLOCK;
318                         default:
319                                 return AR7_AFE_CLOCK;
320                         }
321                 else
322                         /* 1:1 */
323                         return AR7_REF_CLOCK;
324 }
325
326
327 static void __init tnetd7200_init_clocks(void)
328 {
329         u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
330         struct tnetd7200_clocks *clocks =
331                                         ioremap_nocache(AR7_REGS_CLOCKS,
332                                         sizeof(struct tnetd7200_clocks));
333         int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
334         int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
335         int usb_base, usb_mul, usb_prediv, usb_postdiv;
336
337         cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
338         dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
339
340         if (*bootcr & BOOT_PLL_ASYNC_MODE) {
341                 printk(KERN_INFO "Clocks: Async mode\n");
342
343                 printk(KERN_INFO "Clocks: Setting DSP clock\n");
344                 calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
345                         &dsp_prediv, &dsp_postdiv, &dsp_mul);
346                 ar7_bus_clock =
347                         ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
348                 tnetd7200_set_clock(dsp_base, &clocks->dsp,
349                         dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
350                         ar7_bus_clock);
351
352                 printk(KERN_INFO "Clocks: Setting CPU clock\n");
353                 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
354                         &cpu_postdiv, &cpu_mul);
355                 ar7_cpu_clock =
356                         ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
357                 tnetd7200_set_clock(cpu_base, &clocks->cpu,
358                         cpu_prediv, cpu_postdiv, -1, cpu_mul,
359                         ar7_cpu_clock);
360
361         } else
362                 if (*bootcr & BOOT_PLL_2TO1_MODE) {
363                         printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
364
365                         printk(KERN_INFO "Clocks: Setting CPU clock\n");
366                         calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
367                                 &cpu_postdiv, &cpu_mul);
368                         ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
369                                                                 / cpu_postdiv;
370                         tnetd7200_set_clock(cpu_base, &clocks->cpu,
371                                 cpu_prediv, cpu_postdiv, -1, cpu_mul,
372                                 ar7_cpu_clock);
373
374                         printk(KERN_INFO "Clocks: Setting DSP clock\n");
375                         calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
376                                 &dsp_postdiv, &dsp_mul);
377                         ar7_bus_clock = ar7_cpu_clock / 2;
378                         tnetd7200_set_clock(dsp_base, &clocks->dsp,
379                                 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
380                                 dsp_mul * 2, ar7_bus_clock);
381                 } else {
382                         printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
383
384                         printk(KERN_INFO "Clocks: Setting DSP clock\n");
385                         calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
386                                 &dsp_postdiv, &dsp_mul);
387                         ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
388                                                                 / dsp_postdiv;
389                         tnetd7200_set_clock(dsp_base, &clocks->dsp,
390                                 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
391                                 dsp_mul * 2, ar7_bus_clock);
392
393                         ar7_cpu_clock = ar7_bus_clock;
394                 }
395
396         printk(KERN_INFO "Clocks: Setting USB clock\n");
397         usb_base = ar7_bus_clock;
398         calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
399                 &usb_postdiv, &usb_mul);
400         tnetd7200_set_clock(usb_base, &clocks->usb,
401                 usb_prediv, usb_postdiv, -1, usb_mul,
402                 TNETD7200_DEF_USB_CLK);
403
404         ar7_dsp_clock = ar7_cpu_clock;
405
406         iounmap(clocks);
407         iounmap(bootcr);
408 }
409
410 int __init ar7_init_clocks(void)
411 {
412         switch (ar7_chip_id()) {
413         case AR7_CHIP_7100:
414         case AR7_CHIP_7200:
415                 tnetd7200_init_clocks();
416                 break;
417         case AR7_CHIP_7300:
418                 ar7_dsp_clock = tnetd7300_dsp_clock();
419                 tnetd7300_init_clocks();
420                 break;
421         default:
422                 break;
423         }
424
425         return 0;
426 }
427 arch_initcall(ar7_init_clocks);