Merge branch 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/pasemi
[pandora-kernel.git] / arch / powerpc / boot / 4xx.c
1 /*
2  * Copyright 2007 David Gibson, IBM Corporation.
3  *
4  * Based on earlier code:
5  *   Matt Porter <mporter@kernel.crashing.org>
6  *   Copyright 2002-2005 MontaVista Software Inc.
7  *
8  *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9  *   Copyright (c) 2003, 2004 Zultys Technologies
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version
14  * 2 of the License, or (at your option) any later version.
15  */
16 #include <stddef.h>
17 #include "types.h"
18 #include "string.h"
19 #include "stdio.h"
20 #include "ops.h"
21 #include "reg.h"
22 #include "dcr.h"
23
24 /* Read the 4xx SDRAM controller to get size of system memory. */
25 void ibm4xx_sdram_fixup_memsize(void)
26 {
27         int i;
28         unsigned long memsize, bank_config;
29
30         memsize = 0;
31         for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
32                 bank_config = SDRAM0_READ(sdram_bxcr[i]);
33                 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
34                         memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
35         }
36
37         dt_fixup_memory(0, memsize);
38 }
39
40 /* Read the 440SPe MQ controller to get size of system memory. */
41 #define DCRN_MQ0_B0BAS          0x40
42 #define DCRN_MQ0_B1BAS          0x41
43 #define DCRN_MQ0_B2BAS          0x42
44 #define DCRN_MQ0_B3BAS          0x43
45
46 static u64 ibm440spe_decode_bas(u32 bas)
47 {
48         u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
49
50         /* open coded because I'm paranoid about invalid values */
51         switch ((bas >> 4) & 0xFFF) {
52         case 0:
53                 return 0;
54         case 0xffc:
55                 return base + 0x000800000ull;
56         case 0xff8:
57                 return base + 0x001000000ull;
58         case 0xff0:
59                 return base + 0x002000000ull;
60         case 0xfe0:
61                 return base + 0x004000000ull;
62         case 0xfc0:
63                 return base + 0x008000000ull;
64         case 0xf80:
65                 return base + 0x010000000ull;
66         case 0xf00:
67                 return base + 0x020000000ull;
68         case 0xe00:
69                 return base + 0x040000000ull;
70         case 0xc00:
71                 return base + 0x080000000ull;
72         case 0x800:
73                 return base + 0x100000000ull;
74         }
75         printf("Memory BAS value 0x%08x unsupported !\n", bas);
76         return 0;
77 }
78
79 void ibm440spe_fixup_memsize(void)
80 {
81         u64 banktop, memsize = 0;
82
83         /* Ultimately, we should directly construct the memory node
84          * so we are able to handle holes in the memory address space
85          */
86         banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
87         if (banktop > memsize)
88                 memsize = banktop;
89         banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
90         if (banktop > memsize)
91                 memsize = banktop;
92         banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
93         if (banktop > memsize)
94                 memsize = banktop;
95         banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
96         if (banktop > memsize)
97                 memsize = banktop;
98
99         dt_fixup_memory(0, memsize);
100 }
101
102
103 /* 4xx DDR1/2 Denali memory controller support */
104 /* DDR0 registers */
105 #define DDR0_02                 2
106 #define DDR0_08                 8
107 #define DDR0_10                 10
108 #define DDR0_14                 14
109 #define DDR0_42                 42
110 #define DDR0_43                 43
111
112 /* DDR0_02 */
113 #define DDR_START               0x1
114 #define DDR_START_SHIFT         0
115 #define DDR_MAX_CS_REG          0x3
116 #define DDR_MAX_CS_REG_SHIFT    24
117 #define DDR_MAX_COL_REG         0xf
118 #define DDR_MAX_COL_REG_SHIFT   16
119 #define DDR_MAX_ROW_REG         0xf
120 #define DDR_MAX_ROW_REG_SHIFT   8
121 /* DDR0_08 */
122 #define DDR_DDR2_MODE           0x1
123 #define DDR_DDR2_MODE_SHIFT     0
124 /* DDR0_10 */
125 #define DDR_CS_MAP              0x3
126 #define DDR_CS_MAP_SHIFT        8
127 /* DDR0_14 */
128 #define DDR_REDUC               0x1
129 #define DDR_REDUC_SHIFT         16
130 /* DDR0_42 */
131 #define DDR_APIN                0x7
132 #define DDR_APIN_SHIFT          24
133 /* DDR0_43 */
134 #define DDR_COL_SZ              0x7
135 #define DDR_COL_SZ_SHIFT        8
136 #define DDR_BANK8               0x1
137 #define DDR_BANK8_SHIFT         0
138
139 #define DDR_GET_VAL(val, mask, shift)   (((val) >> (shift)) & (mask))
140
141 void ibm4xx_denali_fixup_memsize(void)
142 {
143         u32 val, max_cs, max_col, max_row;
144         u32 cs, col, row, bank, dpath;
145         unsigned long memsize;
146
147         val = SDRAM0_READ(DDR0_02);
148         if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
149                 fatal("DDR controller is not initialized\n");
150
151         /* get maximum cs col and row values */
152         max_cs  = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
153         max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
154         max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
155
156         /* get CS value */
157         val = SDRAM0_READ(DDR0_10);
158
159         val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
160         cs = 0;
161         while (val) {
162                 if (val && 0x1)
163                         cs++;
164                 val = val >> 1;
165         }
166
167         if (!cs)
168                 fatal("No memory installed\n");
169         if (cs > max_cs)
170                 fatal("DDR wrong CS configuration\n");
171
172         /* get data path bytes */
173         val = SDRAM0_READ(DDR0_14);
174
175         if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
176                 dpath = 8; /* 64 bits */
177         else
178                 dpath = 4; /* 32 bits */
179
180         /* get address pins (rows) */
181         val = SDRAM0_READ(DDR0_42);
182
183         row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
184         if (row > max_row)
185                 fatal("DDR wrong APIN configuration\n");
186         row = max_row - row;
187
188         /* get collomn size and banks */
189         val = SDRAM0_READ(DDR0_43);
190
191         col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
192         if (col > max_col)
193                 fatal("DDR wrong COL configuration\n");
194         col = max_col - col;
195
196         if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
197                 bank = 8; /* 8 banks */
198         else
199                 bank = 4; /* 4 banks */
200
201         memsize = cs * (1 << (col+row)) * bank * dpath;
202         dt_fixup_memory(0, memsize);
203 }
204
205 #define SPRN_DBCR0_40X 0x3F2
206 #define SPRN_DBCR0_44X 0x134
207 #define DBCR0_RST_SYSTEM 0x30000000
208
209 void ibm44x_dbcr_reset(void)
210 {
211         unsigned long tmp;
212
213         asm volatile (
214                 "mfspr  %0,%1\n"
215                 "oris   %0,%0,%2@h\n"
216                 "mtspr  %1,%0"
217                 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
218                 );
219
220 }
221
222 void ibm40x_dbcr_reset(void)
223 {
224         unsigned long tmp;
225
226         asm volatile (
227                 "mfspr  %0,%1\n"
228                 "oris   %0,%0,%2@h\n"
229                 "mtspr  %1,%0"
230                 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
231                 );
232 }
233
234 #define EMAC_RESET 0x20000000
235 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
236 {
237         /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
238          * do this for us
239          */
240         if (emac0)
241                 *emac0 = EMAC_RESET;
242         if (emac1)
243                 *emac1 = EMAC_RESET;
244
245         mtdcr(DCRN_MAL0_CFG, MAL_RESET);
246         while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
247                 ; /* loop until reset takes effect */
248 }
249
250 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
251  * banks into the OPB address space */
252 void ibm4xx_fixup_ebc_ranges(const char *ebc)
253 {
254         void *devp;
255         u32 bxcr;
256         u32 ranges[EBC_NUM_BANKS*4];
257         u32 *p = ranges;
258         int i;
259
260         for (i = 0; i < EBC_NUM_BANKS; i++) {
261                 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
262                 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
263
264                 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
265                         *p++ = i;
266                         *p++ = 0;
267                         *p++ = bxcr & EBC_BXCR_BAS;
268                         *p++ = EBC_BXCR_BANK_SIZE(bxcr);
269                 }
270         }
271
272         devp = finddevice(ebc);
273         if (! devp)
274                 fatal("Couldn't locate EBC node %s\n\r", ebc);
275
276         setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
277 }
278
279 /* Calculate 440GP clocks */
280 void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
281 {
282         u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
283         u32 cr0 = mfdcr(DCRN_CPC0_CR0);
284         u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
285         u32 opdv = CPC0_SYS0_OPDV(sys0);
286         u32 epdv = CPC0_SYS0_EPDV(sys0);
287
288         if (sys0 & CPC0_SYS0_BYPASS) {
289                 /* Bypass system PLL */
290                 cpu = plb = sys_clk;
291         } else {
292                 if (sys0 & CPC0_SYS0_EXTSL)
293                         /* PerClk */
294                         m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
295                 else
296                         /* CPU clock */
297                         m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
298                 cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
299                 plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
300         }
301
302         opb = plb / opdv;
303         ebc = opb / epdv;
304
305         /* FIXME: Check if this is for all 440GP, or just Ebony */
306         if ((mfpvr() & 0xf0000fff) == 0x40000440)
307                 /* Rev. B 440GP, use external system clock */
308                 tb = sys_clk;
309         else
310                 /* Rev. C 440GP, errata force us to use internal clock */
311                 tb = cpu;
312
313         if (cr0 & CPC0_CR0_U0EC)
314                 /* External UART clock */
315                 uart0 = ser_clk;
316         else
317                 /* Internal UART clock */
318                 uart0 = plb / CPC0_CR0_UDIV(cr0);
319
320         if (cr0 & CPC0_CR0_U1EC)
321                 /* External UART clock */
322                 uart1 = ser_clk;
323         else
324                 /* Internal UART clock */
325                 uart1 = plb / CPC0_CR0_UDIV(cr0);
326
327         printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
328                (sys_clk + 500000) / 1000000, sys_clk);
329
330         dt_fixup_cpu_clocks(cpu, tb, 0);
331
332         dt_fixup_clock("/plb", plb);
333         dt_fixup_clock("/plb/opb", opb);
334         dt_fixup_clock("/plb/opb/ebc", ebc);
335         dt_fixup_clock("/plb/opb/serial@40000200", uart0);
336         dt_fixup_clock("/plb/opb/serial@40000300", uart1);
337 }
338
339 #define SPRN_CCR1 0x378
340
341 static inline u32 __fix_zero(u32 v, u32 def)
342 {
343         return v ? v : def;
344 }
345
346 static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
347                                                 unsigned int tmr_clk,
348                                                 int per_clk_from_opb)
349 {
350         /* PLL config */
351         u32 pllc  = CPR0_READ(DCRN_CPR0_PLLC);
352         u32 plld  = CPR0_READ(DCRN_CPR0_PLLD);
353
354         /* Dividers */
355         u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
356         u32 fwdva  = __fix_zero((plld >> 16) & 0xf, 16);
357         u32 fwdvb  = __fix_zero((plld >> 8) & 7, 8);
358         u32 lfbdv  = __fix_zero(plld & 0x3f, 64);
359         u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
360         u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
361         u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
362         u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
363
364         /* Input clocks for primary dividers */
365         u32 clk_a, clk_b;
366
367         /* Resulting clocks */
368         u32 cpu, plb, opb, ebc, vco;
369
370         /* Timebase */
371         u32 ccr1, tb = tmr_clk;
372
373         if (pllc & 0x40000000) {
374                 u32 m;
375
376                 /* Feedback path */
377                 switch ((pllc >> 24) & 7) {
378                 case 0:
379                         /* PLLOUTx */
380                         m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
381                         break;
382                 case 1:
383                         /* CPU */
384                         m = fwdva * pradv0;
385                         break;
386                 case 5:
387                         /* PERClk */
388                         m = fwdvb * prbdv0 * opbdv0 * perdv0;
389                         break;
390                 default:
391                         printf("WARNING ! Invalid PLL feedback source !\n");
392                         goto bypass;
393                 }
394                 m *= fbdv;
395                 vco = sys_clk * m;
396                 clk_a = vco / fwdva;
397                 clk_b = vco / fwdvb;
398         } else {
399 bypass:
400                 /* Bypass system PLL */
401                 vco = 0;
402                 clk_a = clk_b = sys_clk;
403         }
404
405         cpu = clk_a / pradv0;
406         plb = clk_b / prbdv0;
407         opb = plb / opbdv0;
408         ebc = (per_clk_from_opb ? opb : plb) / perdv0;
409
410         /* Figure out timebase.  Either CPU or default TmrClk */
411         ccr1 = mfspr(SPRN_CCR1);
412
413         /* If passed a 0 tmr_clk, force CPU clock */
414         if (tb == 0) {
415                 ccr1 &= ~0x80u;
416                 mtspr(SPRN_CCR1, ccr1);
417         }
418         if ((ccr1 & 0x0080) == 0)
419                 tb = cpu;
420
421         dt_fixup_cpu_clocks(cpu, tb, 0);
422         dt_fixup_clock("/plb", plb);
423         dt_fixup_clock("/plb/opb", opb);
424         dt_fixup_clock("/plb/opb/ebc", ebc);
425
426         return plb;
427 }
428
429 static void eplike_fixup_uart_clk(int index, const char *path,
430                                   unsigned int ser_clk,
431                                   unsigned int plb_clk)
432 {
433         unsigned int sdr;
434         unsigned int clock;
435
436         switch (index) {
437         case 0:
438                 sdr = SDR0_READ(DCRN_SDR0_UART0);
439                 break;
440         case 1:
441                 sdr = SDR0_READ(DCRN_SDR0_UART1);
442                 break;
443         case 2:
444                 sdr = SDR0_READ(DCRN_SDR0_UART2);
445                 break;
446         case 3:
447                 sdr = SDR0_READ(DCRN_SDR0_UART3);
448                 break;
449         default:
450                 return;
451         }
452
453         if (sdr & 0x00800000u)
454                 clock = ser_clk;
455         else
456                 clock = plb_clk / __fix_zero(sdr & 0xff, 256);
457
458         dt_fixup_clock(path, clock);
459 }
460
461 void ibm440ep_fixup_clocks(unsigned int sys_clk,
462                            unsigned int ser_clk,
463                            unsigned int tmr_clk)
464 {
465         unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
466
467         /* serial clocks beed fixup based on int/ext */
468         eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
469         eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
470         eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
471         eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
472 }
473
474 void ibm440gx_fixup_clocks(unsigned int sys_clk,
475                            unsigned int ser_clk,
476                            unsigned int tmr_clk)
477 {
478         unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
479
480         /* serial clocks beed fixup based on int/ext */
481         eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
482         eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
483 }
484
485 void ibm440spe_fixup_clocks(unsigned int sys_clk,
486                             unsigned int ser_clk,
487                             unsigned int tmr_clk)
488 {
489         unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
490
491         /* serial clocks beed fixup based on int/ext */
492         eplike_fixup_uart_clk(0, "/plb/opb/serial@10000200", ser_clk, plb_clk);
493         eplike_fixup_uart_clk(1, "/plb/opb/serial@10000300", ser_clk, plb_clk);
494         eplike_fixup_uart_clk(2, "/plb/opb/serial@10000600", ser_clk, plb_clk);
495 }
496
497 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
498 {
499         u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
500         u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
501         u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
502         u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
503         u32 fwdv, fbdv, cbdv, opdv, epdv, udiv;
504
505         fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
506         fbdv = (pllmr & 0x1e000000) >> 25;
507         cbdv = ((pllmr & 0x00060000) >> 17) + 1;
508         opdv = ((pllmr & 0x00018000) >> 15) + 1;
509         epdv = ((pllmr & 0x00001800) >> 13) + 2;
510         udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
511
512         m = fwdv * fbdv * cbdv;
513
514         cpu = sys_clk * m / fwdv;
515         plb = cpu / cbdv;
516         opb = plb / opdv;
517         ebc = plb / epdv;
518
519         if (cpc0_cr0 & 0x80)
520                 /* uart0 uses the external clock */
521                 uart0 = ser_clk;
522         else
523                 uart0 = cpu / udiv;
524
525         if (cpc0_cr0 & 0x40)
526                 /* uart1 uses the external clock */
527                 uart1 = ser_clk;
528         else
529                 uart1 = cpu / udiv;
530
531         /* setup the timebase clock to tick at the cpu frequency */
532         cpc0_cr1 = cpc0_cr1 & ~0x00800000;
533         mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
534         tb = cpu;
535
536         dt_fixup_cpu_clocks(cpu, tb, 0);
537         dt_fixup_clock("/plb", plb);
538         dt_fixup_clock("/plb/opb", opb);
539         dt_fixup_clock("/plb/ebc", ebc);
540         dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
541         dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
542 }
543