Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
[sfrench/cifs-2.6.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_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                 mtdcr(DCRN_SDRAM0_CFGADDR, sdram_bxcr[i]);
33                 bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
34
35                 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
36                         memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
37         }
38
39         dt_fixup_memory(0, memsize);
40 }
41
42 /* 4xx DDR1/2 Denali memory controller support */
43 /* DDR0 registers */
44 #define DDR0_02                 2
45 #define DDR0_08                 8
46 #define DDR0_10                 10
47 #define DDR0_14                 14
48 #define DDR0_42                 42
49 #define DDR0_43                 43
50
51 /* DDR0_02 */
52 #define DDR_START               0x1
53 #define DDR_START_SHIFT         0
54 #define DDR_MAX_CS_REG          0x3
55 #define DDR_MAX_CS_REG_SHIFT    24
56 #define DDR_MAX_COL_REG         0xf
57 #define DDR_MAX_COL_REG_SHIFT   16
58 #define DDR_MAX_ROW_REG         0xf
59 #define DDR_MAX_ROW_REG_SHIFT   8
60 /* DDR0_08 */
61 #define DDR_DDR2_MODE           0x1
62 #define DDR_DDR2_MODE_SHIFT     0
63 /* DDR0_10 */
64 #define DDR_CS_MAP              0x3
65 #define DDR_CS_MAP_SHIFT        8
66 /* DDR0_14 */
67 #define DDR_REDUC               0x1
68 #define DDR_REDUC_SHIFT         16
69 /* DDR0_42 */
70 #define DDR_APIN                0x7
71 #define DDR_APIN_SHIFT          24
72 /* DDR0_43 */
73 #define DDR_COL_SZ              0x7
74 #define DDR_COL_SZ_SHIFT        8
75 #define DDR_BANK8               0x1
76 #define DDR_BANK8_SHIFT         0
77
78 #define DDR_GET_VAL(val, mask, shift)   (((val) >> (shift)) & (mask))
79
80 static inline u32 mfdcr_sdram0(u32 reg)
81 {
82         mtdcr(DCRN_SDRAM0_CFGADDR, reg);
83         return mfdcr(DCRN_SDRAM0_CFGDATA);
84 }
85
86 void ibm4xx_denali_fixup_memsize(void)
87 {
88         u32 val, max_cs, max_col, max_row;
89         u32 cs, col, row, bank, dpath;
90         unsigned long memsize;
91
92         val = mfdcr_sdram0(DDR0_02);
93         if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
94                 fatal("DDR controller is not initialized\n");
95
96         /* get maximum cs col and row values */
97         max_cs  = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
98         max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
99         max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
100
101         /* get CS value */
102         val = mfdcr_sdram0(DDR0_10);
103
104         val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
105         cs = 0;
106         while (val) {
107                 if (val && 0x1)
108                         cs++;
109                 val = val >> 1;
110         }
111
112         if (!cs)
113                 fatal("No memory installed\n");
114         if (cs > max_cs)
115                 fatal("DDR wrong CS configuration\n");
116
117         /* get data path bytes */
118         val = mfdcr_sdram0(DDR0_14);
119
120         if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
121                 dpath = 8; /* 64 bits */
122         else
123                 dpath = 4; /* 32 bits */
124
125         /* get adress pins (rows) */
126         val = mfdcr_sdram0(DDR0_42);
127
128         row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
129         if (row > max_row)
130                 fatal("DDR wrong APIN configuration\n");
131         row = max_row - row;
132
133         /* get collomn size and banks */
134         val = mfdcr_sdram0(DDR0_43);
135
136         col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
137         if (col > max_col)
138                 fatal("DDR wrong COL configuration\n");
139         col = max_col - col;
140
141         if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
142                 bank = 8; /* 8 banks */
143         else
144                 bank = 4; /* 4 banks */
145
146         memsize = cs * (1 << (col+row)) * bank * dpath;
147         dt_fixup_memory(0, memsize);
148 }
149
150 #define SPRN_DBCR0_40X 0x3F2
151 #define SPRN_DBCR0_44X 0x134
152 #define DBCR0_RST_SYSTEM 0x30000000
153
154 void ibm44x_dbcr_reset(void)
155 {
156         unsigned long tmp;
157
158         asm volatile (
159                 "mfspr  %0,%1\n"
160                 "oris   %0,%0,%2@h\n"
161                 "mtspr  %1,%0"
162                 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
163                 );
164
165 }
166
167 void ibm40x_dbcr_reset(void)
168 {
169         unsigned long tmp;
170
171         asm volatile (
172                 "mfspr  %0,%1\n"
173                 "oris   %0,%0,%2@h\n"
174                 "mtspr  %1,%0"
175                 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
176                 );
177 }
178
179 #define EMAC_RESET 0x20000000
180 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
181 {
182         /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't do this for us */
183         if (emac0)
184                 *emac0 = EMAC_RESET;
185         if (emac1)
186                 *emac1 = EMAC_RESET;
187
188         mtdcr(DCRN_MAL0_CFG, MAL_RESET);
189 }
190
191 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
192  * banks into the OPB address space */
193 void ibm4xx_fixup_ebc_ranges(const char *ebc)
194 {
195         void *devp;
196         u32 bxcr;
197         u32 ranges[EBC_NUM_BANKS*4];
198         u32 *p = ranges;
199         int i;
200
201         for (i = 0; i < EBC_NUM_BANKS; i++) {
202                 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
203                 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
204
205                 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
206                         *p++ = i;
207                         *p++ = 0;
208                         *p++ = bxcr & EBC_BXCR_BAS;
209                         *p++ = EBC_BXCR_BANK_SIZE(bxcr);
210                 }
211         }
212
213         devp = finddevice(ebc);
214         if (! devp)
215                 fatal("Couldn't locate EBC node %s\n\r", ebc);
216
217         setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
218 }
219
220 #define SPRN_CCR1 0x378
221 void ibm440ep_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
222 {
223         u32 cpu, plb, opb, ebc, tb, uart0, m, vco;
224         u32 reg;
225         u32 fwdva, fwdvb, fbdv, lfbdv, opbdv0, perdv0, spcid0, prbdv0, tmp;
226
227         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLD0);
228         reg = mfdcr(DCRN_CPR0_DATA);
229         tmp = (reg & 0x000F0000) >> 16;
230         fwdva = tmp ? tmp : 16;
231         tmp = (reg & 0x00000700) >> 8;
232         fwdvb = tmp ? tmp : 8;
233         tmp = (reg & 0x1F000000) >> 24;
234         fbdv = tmp ? tmp : 32;
235         lfbdv = (reg & 0x0000007F);
236
237         mtdcr(DCRN_CPR0_ADDR, CPR0_OPBD0);
238         reg = mfdcr(DCRN_CPR0_DATA);
239         tmp = (reg & 0x03000000) >> 24;
240         opbdv0 = tmp ? tmp : 4;
241
242         mtdcr(DCRN_CPR0_ADDR, CPR0_PERD0);
243         reg = mfdcr(DCRN_CPR0_DATA);
244         tmp = (reg & 0x07000000) >> 24;
245         perdv0 = tmp ? tmp : 8;
246
247         mtdcr(DCRN_CPR0_ADDR, CPR0_PRIMBD0);
248         reg = mfdcr(DCRN_CPR0_DATA);
249         tmp = (reg & 0x07000000) >> 24;
250         prbdv0 = tmp ? tmp : 8;
251
252         mtdcr(DCRN_CPR0_ADDR, CPR0_SCPID);
253         reg = mfdcr(DCRN_CPR0_DATA);
254         tmp = (reg & 0x03000000) >> 24;
255         spcid0 = tmp ? tmp : 4;
256
257         /* Calculate M */
258         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLC0);
259         reg = mfdcr(DCRN_CPR0_DATA);
260         tmp = (reg & 0x03000000) >> 24;
261         if (tmp == 0) { /* PLL output */
262                 tmp = (reg & 0x20000000) >> 29;
263                 if (!tmp) /* PLLOUTA */
264                         m = fbdv * lfbdv * fwdva;
265                 else
266                         m = fbdv * lfbdv * fwdvb;
267         }
268         else if (tmp == 1) /* CPU output */
269                 m = fbdv * fwdva;
270         else
271                 m = perdv0 * opbdv0 * fwdvb;
272
273         vco = (m * sysclk) + (m >> 1);
274         cpu = vco / fwdva;
275         plb = vco / fwdvb / prbdv0;
276         opb = plb / opbdv0;
277         ebc = plb / perdv0;
278
279         /* FIXME */
280         uart0 = ser_clk;
281
282         /* Figure out timebase.  Either CPU or default TmrClk */
283         asm volatile (
284                         "mfspr  %0,%1\n"
285                         :
286                         "=&r"(reg) : "i"(SPRN_CCR1));
287         if (reg & 0x0080)
288                 tb = 25000000; /* TmrClk is 25MHz */
289         else
290                 tb = cpu;
291
292         dt_fixup_cpu_clocks(cpu, tb, 0);
293         dt_fixup_clock("/plb", plb);
294         dt_fixup_clock("/plb/opb", opb);
295         dt_fixup_clock("/plb/opb/ebc", ebc);
296         dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
297         dt_fixup_clock("/plb/opb/serial@ef600400", uart0);
298         dt_fixup_clock("/plb/opb/serial@ef600500", uart0);
299         dt_fixup_clock("/plb/opb/serial@ef600600", uart0);
300 }