]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/powerpc/boot/4xx.c
[POWERPC] 4xx: Add mfspr/mtspr inline macros to 4xx bootwrapper
[linux-2.6-omap-h63xx.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 }
248
249 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
250  * banks into the OPB address space */
251 void ibm4xx_fixup_ebc_ranges(const char *ebc)
252 {
253         void *devp;
254         u32 bxcr;
255         u32 ranges[EBC_NUM_BANKS*4];
256         u32 *p = ranges;
257         int i;
258
259         for (i = 0; i < EBC_NUM_BANKS; i++) {
260                 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
261                 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
262
263                 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
264                         *p++ = i;
265                         *p++ = 0;
266                         *p++ = bxcr & EBC_BXCR_BAS;
267                         *p++ = EBC_BXCR_BANK_SIZE(bxcr);
268                 }
269         }
270
271         devp = finddevice(ebc);
272         if (! devp)
273                 fatal("Couldn't locate EBC node %s\n\r", ebc);
274
275         setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
276 }
277
278 #define SPRN_CCR1 0x378
279 void ibm440ep_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
280 {
281         u32 cpu, plb, opb, ebc, tb, uart0, m, vco;
282         u32 reg;
283         u32 fwdva, fwdvb, fbdv, lfbdv, opbdv0, perdv0, spcid0, prbdv0, tmp;
284
285         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLD0);
286         reg = mfdcr(DCRN_CPR0_DATA);
287         tmp = (reg & 0x000F0000) >> 16;
288         fwdva = tmp ? tmp : 16;
289         tmp = (reg & 0x00000700) >> 8;
290         fwdvb = tmp ? tmp : 8;
291         tmp = (reg & 0x1F000000) >> 24;
292         fbdv = tmp ? tmp : 32;
293         lfbdv = (reg & 0x0000007F);
294
295         mtdcr(DCRN_CPR0_ADDR, CPR0_OPBD0);
296         reg = mfdcr(DCRN_CPR0_DATA);
297         tmp = (reg & 0x03000000) >> 24;
298         opbdv0 = tmp ? tmp : 4;
299
300         mtdcr(DCRN_CPR0_ADDR, CPR0_PERD0);
301         reg = mfdcr(DCRN_CPR0_DATA);
302         tmp = (reg & 0x07000000) >> 24;
303         perdv0 = tmp ? tmp : 8;
304
305         mtdcr(DCRN_CPR0_ADDR, CPR0_PRIMBD0);
306         reg = mfdcr(DCRN_CPR0_DATA);
307         tmp = (reg & 0x07000000) >> 24;
308         prbdv0 = tmp ? tmp : 8;
309
310         mtdcr(DCRN_CPR0_ADDR, CPR0_SCPID);
311         reg = mfdcr(DCRN_CPR0_DATA);
312         tmp = (reg & 0x03000000) >> 24;
313         spcid0 = tmp ? tmp : 4;
314
315         /* Calculate M */
316         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLC0);
317         reg = mfdcr(DCRN_CPR0_DATA);
318         tmp = (reg & 0x03000000) >> 24;
319         if (tmp == 0) { /* PLL output */
320                 tmp = (reg & 0x20000000) >> 29;
321                 if (!tmp) /* PLLOUTA */
322                         m = fbdv * lfbdv * fwdva;
323                 else
324                         m = fbdv * lfbdv * fwdvb;
325         }
326         else if (tmp == 1) /* CPU output */
327                 m = fbdv * fwdva;
328         else
329                 m = perdv0 * opbdv0 * fwdvb;
330
331         vco = (m * sysclk) + (m >> 1);
332         cpu = vco / fwdva;
333         plb = vco / fwdvb / prbdv0;
334         opb = plb / opbdv0;
335         ebc = plb / perdv0;
336
337         /* FIXME */
338         uart0 = ser_clk;
339
340         /* Figure out timebase.  Either CPU or default TmrClk */
341         asm volatile (
342                         "mfspr  %0,%1\n"
343                         :
344                         "=&r"(reg) : "i"(SPRN_CCR1));
345         if (reg & 0x0080)
346                 tb = 25000000; /* TmrClk is 25MHz */
347         else
348                 tb = cpu;
349
350         dt_fixup_cpu_clocks(cpu, tb, 0);
351         dt_fixup_clock("/plb", plb);
352         dt_fixup_clock("/plb/opb", opb);
353         dt_fixup_clock("/plb/opb/ebc", ebc);
354         dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
355         dt_fixup_clock("/plb/opb/serial@ef600400", uart0);
356         dt_fixup_clock("/plb/opb/serial@ef600500", uart0);
357         dt_fixup_clock("/plb/opb/serial@ef600600", uart0);
358 }
359
360 void ibm405gp_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
361 {
362         u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
363         u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
364         u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
365         u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
366         u32 fwdv, fbdv, cbdv, opdv, epdv, udiv;
367
368         fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
369         fbdv = (pllmr & 0x1e000000) >> 25;
370         cbdv = ((pllmr & 0x00060000) >> 17) + 1;
371         opdv = ((pllmr & 0x00018000) >> 15) + 1;
372         epdv = ((pllmr & 0x00001800) >> 13) + 2;
373         udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
374
375         m = fwdv * fbdv * cbdv;
376
377         cpu = sysclk * m / fwdv;
378         plb = cpu / cbdv;
379         opb = plb / opdv;
380         ebc = plb / epdv;
381
382         if (cpc0_cr0 & 0x80) {
383                 /* uart0 uses the external clock */
384                 uart0 = ser_clk;
385         } else {
386                 uart0 = cpu / udiv;
387         }
388
389         if (cpc0_cr0 & 0x40) {
390                 /* uart1 uses the external clock */
391                 uart1 = ser_clk;
392         } else {
393                 uart1 = cpu / udiv;
394         }
395
396         /* setup the timebase clock to tick at the cpu frequency */
397         cpc0_cr1 = cpc0_cr1 & ~0x00800000;
398         mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
399         tb = cpu;
400
401         dt_fixup_cpu_clocks(cpu, tb, 0);
402         dt_fixup_clock("/plb", plb);
403         dt_fixup_clock("/plb/opb", opb);
404         dt_fixup_clock("/plb/ebc", ebc);
405         dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
406         dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
407 }
408