]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
4 | * Marius Groeger <mgroeger@sysgo.de> | |
5 | * | |
6 | * Board specific routines for the MBX | |
7 | * | |
8 | * - initialisation | |
9 | * - interface to VPD data (mac address, clock speeds) | |
10 | * - memory controller | |
11 | * - serial io initialisation | |
12 | * - ethernet io initialisation | |
13 | * | |
14 | * ----------------------------------------------------------------- | |
15 | * See file CREDITS for list of people who contributed to this | |
16 | * project. | |
17 | * | |
18 | * This program is free software; you can redistribute it and/or | |
19 | * modify it under the terms of the GNU General Public License as | |
20 | * published by the Free Software Foundation; either version 2 of | |
21 | * the License, or (at your option) any later version. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, | |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | * GNU General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program; if not, write to the Free Software | |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
31 | * MA 02111-1307 USA | |
32 | */ | |
33 | ||
34 | #include <common.h> | |
35 | #include <commproc.h> | |
36 | #include <mpc8xx.h> | |
37 | #include "dimm.h" | |
38 | #include "vpd.h" | |
39 | #include "csr.h" | |
40 | ||
41 | /* ------------------------------------------------------------------------- */ | |
42 | ||
43 | static const uint sdram_table_40[] = { | |
44 | /* DRAM - single read. (offset 0 in upm RAM) | |
45 | */ | |
46 | 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x30AF0C00, | |
47 | 0xF1BF4805, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
48 | ||
49 | /* DRAM - burst read. (offset 8 in upm RAM) | |
50 | */ | |
51 | 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x03AF0C08, | |
52 | 0x0CAF0C04, 0x03AF0C08, 0x0CAF0C04, 0x03AF0C08, | |
53 | 0x0CAF0C04, 0x30AF0C00, 0xF3BF4805, 0xFFFFC005, | |
54 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
55 | ||
56 | /* DRAM - single write. (offset 18 in upm RAM) | |
57 | */ | |
58 | 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x33FF4804, | |
59 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
60 | ||
61 | /* DRAM - burst write. (offset 20 in upm RAM) | |
62 | */ | |
63 | 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C, | |
64 | 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C, | |
65 | 0x0CFF0C00, 0x33FF4804, 0xFFFFC005, 0xFFFFC005, | |
66 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
67 | ||
68 | /* refresh (offset 30 in upm RAM) | |
69 | */ | |
70 | 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004, | |
71 | 0x3FFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
72 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
73 | ||
74 | /* exception. (offset 3c in upm RAM) | |
75 | */ | |
76 | 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, | |
77 | }; | |
78 | ||
79 | static const uint sdram_table_50[] = { | |
80 | /* DRAM - single read. (offset 0 in upm RAM) | |
81 | */ | |
82 | 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x10AF0C04, | |
83 | 0xF0AF0C00, 0xF3BF4805, 0xFFFFC005, 0xFFFFC005, | |
84 | ||
85 | /* DRAM - burst read. (offset 8 in upm RAM) | |
86 | */ | |
87 | 0xCFAFC004, 0X0FAFC404, 0X0CAF8C04, 0X00AF0C04, | |
88 | /* 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C04, */ | |
89 | 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, | |
90 | 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, 0X0CAF0C04, | |
91 | /* 0X10AF0C04, 0XF0AFC000, 0XF3FF4805, 0XFFFFC005, */ | |
92 | 0X10AF0C04, 0XF0AFC000, 0XF3BF4805, 0XFFFFC005, | |
93 | ||
94 | /* DRAM - single write. (offset 18 in upm RAM) | |
95 | */ | |
96 | 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x13FF4804, | |
97 | 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
98 | ||
99 | /* DRAM - burst write. (offset 20 in upm RAM) | |
100 | */ | |
101 | 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C, | |
102 | 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C, | |
103 | 0x0CFF0C00, 0x13FF4804, 0xFFFFC004, 0xFFFFC005, | |
104 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
105 | ||
106 | /* refresh (offset 30 in upm RAM) | |
107 | */ | |
108 | 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004, | |
109 | 0x1FFFC004, 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, | |
110 | 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, | |
111 | ||
112 | /* exception. (offset 3c in upm RAM) | |
113 | */ | |
114 | 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, | |
115 | }; | |
116 | ||
117 | /* ------------------------------------------------------------------------- */ | |
118 | ||
119 | static unsigned int get_reffreq(void); | |
120 | static unsigned int board_get_cpufreq(void); | |
121 | ||
122 | void mbx_init (void) | |
123 | { | |
6d0f6bcf | 124 | volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; |
c609719b WD |
125 | volatile memctl8xx_t *memctl = &immr->im_memctl; |
126 | ulong speed, refclock, plprcr, sccr; | |
127 | ulong br0_32 = memctl->memc_br0 & 0x400; | |
128 | ||
129 | /* real-time clock status and control register */ | |
130 | immr->im_sitk.sitk_rtcsck = KAPWR_KEY; | |
131 | immr->im_sit.sit_rtcsc = 0x00C3; | |
132 | ||
133 | /* SIEL and SIMASK Registers (see MBX PRG 2-3) */ | |
134 | immr->im_siu_conf.sc_simask = 0x00000000; | |
135 | immr->im_siu_conf.sc_siel = 0xAAAA0000; | |
136 | immr->im_siu_conf.sc_tesr = 0xFFFFFFFF; | |
137 | ||
138 | /* | |
139 | * Prepare access to i2c bus. The MBX offers 3 devices on the i2c bus: | |
140 | * 1. Vital Product Data (contains clock speeds, MAC address etc, see vpd.h) | |
141 | * 2. RAM Specs (see dimm.h) | |
142 | * 2. DIMM Specs (see dimm.h) | |
143 | */ | |
144 | vpd_init (); | |
145 | ||
146 | /* system clock and reset control register */ | |
147 | immr->im_clkrstk.cark_sccrk = KAPWR_KEY; | |
148 | sccr = immr->im_clkrst.car_sccr; | |
149 | sccr &= SCCR_MASK; | |
6d0f6bcf | 150 | sccr |= CONFIG_SYS_SCCR; |
c609719b WD |
151 | immr->im_clkrst.car_sccr = sccr; |
152 | ||
153 | speed = board_get_cpufreq (); | |
154 | refclock = get_reffreq (); | |
155 | ||
6d0f6bcf JCPV |
156 | #if ((CONFIG_SYS_PLPRCR & PLPRCR_MF_MSK) != 0) |
157 | plprcr = CONFIG_SYS_PLPRCR; | |
c609719b WD |
158 | #else |
159 | plprcr = immr->im_clkrst.car_plprcr; | |
160 | plprcr &= PLPRCR_MF_MSK; /* isolate MF field */ | |
6d0f6bcf | 161 | plprcr |= CONFIG_SYS_PLPRCR; /* reset control bits */ |
c609719b WD |
162 | #endif |
163 | ||
6d0f6bcf | 164 | #ifdef CONFIG_SYS_USE_OSCCLK /* See doc/README.MBX ! */ |
c609719b WD |
165 | plprcr |= ((speed + refclock / 2) / refclock - 1) << 20; |
166 | #endif | |
167 | ||
168 | immr->im_clkrstk.cark_plprcrk = KAPWR_KEY; | |
169 | immr->im_clkrst.car_plprcr = plprcr; | |
170 | ||
171 | /* | |
172 | * preliminary setup of memory controller: | |
173 | * - map Flash, otherwise configuration/status | |
174 | * registers won't be accessible when read | |
175 | * by board_init_f. | |
176 | * - map NVRAM and configuation/status registers. | |
177 | * - map pci registers. | |
178 | * - DON'T map ram yet, this is done in initdram(). | |
179 | */ | |
180 | switch (speed / 1000000) { | |
181 | case 40: | |
182 | memctl->memc_br0 = 0xFE000000 | br0_32 | 1; | |
183 | memctl->memc_or0 = 0xFF800930; | |
6d0f6bcf JCPV |
184 | memctl->memc_or4 = CONFIG_SYS_NVRAM_OR | 0x920; |
185 | memctl->memc_br4 = CONFIG_SYS_NVRAM_BASE | 0x401; | |
c609719b WD |
186 | break; |
187 | case 50: | |
188 | memctl->memc_br0 = 0xFE000000 | br0_32 | 1; | |
189 | memctl->memc_or0 = 0xFF800940; | |
6d0f6bcf JCPV |
190 | memctl->memc_or4 = CONFIG_SYS_NVRAM_OR | 0x930; |
191 | memctl->memc_br4 = CONFIG_SYS_NVRAM_BASE | 0x401; | |
c609719b WD |
192 | break; |
193 | default: | |
194 | hang (); | |
195 | break; | |
196 | } | |
197 | #ifdef CONFIG_USE_PCI | |
6d0f6bcf JCPV |
198 | memctl->memc_or5 = CONFIG_SYS_PCIMEM_OR; |
199 | memctl->memc_br5 = CONFIG_SYS_PCIMEM_BASE | 0x001; | |
200 | memctl->memc_or6 = CONFIG_SYS_PCIBRIDGE_OR; | |
201 | memctl->memc_br6 = CONFIG_SYS_PCIBRIDGE_BASE | 0x001; | |
c609719b WD |
202 | #endif |
203 | /* | |
204 | * FIXME: I do not understand why I have to call this to | |
205 | * initialise the control register here before booting from | |
206 | * the PCMCIA card but if I do not the Linux kernel falls | |
207 | * over in a big heap. If you can answer this question I | |
208 | * would like to know about it. | |
209 | */ | |
210 | board_ether_init(); | |
211 | } | |
212 | ||
213 | void board_serial_init (void) | |
214 | { | |
215 | MBX_CSR1 &= ~(CSR1_COM1EN | CSR1_XCVRDIS); | |
216 | } | |
217 | ||
218 | void board_ether_init (void) | |
219 | { | |
220 | MBX_CSR1 &= ~(CSR1_EAEN | CSR1_ELEN); | |
221 | MBX_CSR1 |= CSR1_ETEN | CSR1_TPEN | CSR1_FDDIS; | |
222 | } | |
223 | ||
224 | static unsigned int board_get_cpufreq (void) | |
225 | { | |
226 | #ifndef CONFIG_8xx_GCLK_FREQ | |
227 | vpd_packet_t *packet; | |
228 | ||
229 | packet = vpd_find_packet (VPD_PID_ICS); | |
230 | return *((ulong *) packet->data); | |
231 | #else | |
232 | return((unsigned int)CONFIG_8xx_GCLK_FREQ ); | |
233 | #endif /* CONFIG_8xx_GCLK_FREQ */ | |
234 | } | |
235 | ||
236 | static unsigned int get_reffreq (void) | |
237 | { | |
238 | vpd_packet_t *packet; | |
239 | ||
240 | packet = vpd_find_packet (VPD_PID_RCS); | |
241 | return *((ulong *) packet->data); | |
242 | } | |
243 | ||
244 | void board_get_enetaddr (uchar * addr) | |
245 | { | |
246 | int i; | |
247 | vpd_packet_t *packet; | |
248 | ||
249 | packet = vpd_find_packet (VPD_PID_EA); | |
250 | for (i = 0; i < 6; i++) | |
251 | addr[i] = packet->data[i]; | |
252 | } | |
253 | ||
254 | /* | |
255 | * Check Board Identity: | |
256 | */ | |
257 | ||
258 | int checkboard (void) | |
259 | { | |
260 | vpd_packet_t *packet; | |
261 | int i; | |
262 | const char *const fmt = | |
263 | "\n *** Warning: Low Battery Status - %s Battery ***"; | |
264 | ||
265 | puts ("Board: "); | |
266 | ||
267 | packet = vpd_find_packet (VPD_PID_PID); | |
268 | for (i = 0; i < packet->size; i++) { | |
269 | serial_putc (packet->data[i]); | |
270 | } | |
271 | packet = vpd_find_packet (VPD_PID_MT); | |
272 | for (i = 0; i < packet->size; i++) { | |
273 | serial_putc (packet->data[i]); | |
274 | } | |
275 | serial_putc ('('); | |
276 | packet = vpd_find_packet (VPD_PID_FAN); | |
277 | for (i = 0; i < packet->size; i++) { | |
278 | serial_putc (packet->data[i]); | |
279 | } | |
280 | serial_putc (')'); | |
281 | ||
282 | if (!(MBX_CSR2 & SR2_BATGD)) | |
283 | printf (fmt, "On-Board"); | |
284 | if (!(MBX_CSR2 & SR2_NVBATGD)) | |
285 | printf (fmt, "NVRAM"); | |
286 | ||
287 | serial_putc ('\n'); | |
288 | ||
289 | return (0); | |
290 | } | |
291 | ||
292 | /* ------------------------------------------------------------------------- */ | |
293 | ||
294 | static ulong get_ramsize (dimm_t * dimm) | |
295 | { | |
296 | ulong size = 0; | |
297 | ||
298 | if (dimm->fmt == 1 || dimm->fmt == 2 || dimm->fmt == 3 | |
299 | || dimm->fmt == 4) { | |
300 | size = (1 << (dimm->n_row + dimm->n_col)) * dimm->n_banks * | |
301 | ((dimm->data_w_hi << 8 | dimm->data_w_lo) / 8); | |
302 | } | |
303 | ||
304 | return size; | |
305 | } | |
306 | ||
9973e3c6 | 307 | phys_size_t initdram (int board_type) |
c609719b | 308 | { |
6d0f6bcf | 309 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
c609719b WD |
310 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
311 | unsigned long ram_sz = 0; | |
312 | unsigned long dimm_sz = 0; | |
313 | dimm_t vpd_dimm, vpd_dram; | |
314 | unsigned int speed = board_get_cpufreq () / 1000000; | |
315 | ||
316 | if (vpd_read (0xa2, (uchar *) & vpd_dimm, sizeof (vpd_dimm), 0) > 0) { | |
317 | dimm_sz = get_ramsize (&vpd_dimm); | |
318 | } | |
319 | if (vpd_read (0xa6, (uchar *) & vpd_dram, sizeof (vpd_dram), 0) > 0) { | |
320 | ram_sz = get_ramsize (&vpd_dram); | |
321 | } | |
322 | ||
323 | /* | |
324 | * Only initialize memory controller when running from FLASH. | |
325 | * When running from RAM, don't touch it. | |
326 | */ | |
327 | if ((ulong) initdram & 0xff000000) { | |
328 | ulong dimm_bank; | |
329 | ulong br0_32 = memctl->memc_br0 & 0x400; | |
330 | ||
331 | switch (speed) { | |
332 | case 40: | |
333 | upmconfig (UPMA, (uint *) sdram_table_40, | |
334 | sizeof (sdram_table_40) / sizeof (uint)); | |
335 | memctl->memc_mptpr = 0x0200; | |
336 | memctl->memc_mamr = dimm_sz ? 0x06801000 : 0x13801000; | |
337 | memctl->memc_or7 = 0xff800930; | |
338 | memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1; | |
339 | break; | |
340 | case 50: | |
341 | upmconfig (UPMA, (uint *) sdram_table_50, | |
342 | sizeof (sdram_table_50) / sizeof (uint)); | |
343 | memctl->memc_mptpr = 0x0200; | |
344 | memctl->memc_mamr = dimm_sz ? 0x08801000 : 0x1880100; | |
345 | memctl->memc_or7 = 0xff800940; | |
346 | memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1; | |
347 | break; | |
348 | default: | |
349 | hang (); | |
350 | break; | |
351 | } | |
352 | ||
353 | /* now map ram and dimm, largest one first */ | |
354 | dimm_bank = dimm_sz / 2; | |
355 | if (!dimm_sz) { | |
356 | memctl->memc_or1 = ~(ram_sz - 1) | 0x400; | |
6d0f6bcf | 357 | memctl->memc_br1 = CONFIG_SYS_SDRAM_BASE | 0x81; |
c609719b WD |
358 | memctl->memc_br2 = 0; |
359 | memctl->memc_br3 = 0; | |
360 | } else if (ram_sz > dimm_bank) { | |
361 | memctl->memc_or1 = ~(ram_sz - 1) | 0x400; | |
6d0f6bcf | 362 | memctl->memc_br1 = CONFIG_SYS_SDRAM_BASE | 0x81; |
c609719b | 363 | memctl->memc_or2 = ~(dimm_bank - 1) | 0x400; |
6d0f6bcf | 364 | memctl->memc_br2 = (CONFIG_SYS_SDRAM_BASE + ram_sz) | 0x81; |
c609719b | 365 | memctl->memc_or3 = ~(dimm_bank - 1) | 0x400; |
6d0f6bcf | 366 | memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE + ram_sz + dimm_bank) \ |
c609719b WD |
367 | | 0x81; |
368 | } else { | |
369 | memctl->memc_or2 = ~(dimm_bank - 1) | 0x400; | |
6d0f6bcf | 370 | memctl->memc_br2 = CONFIG_SYS_SDRAM_BASE | 0x81; |
c609719b | 371 | memctl->memc_or3 = ~(dimm_bank - 1) | 0x400; |
6d0f6bcf | 372 | memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE + dimm_bank) | 0x81; |
c609719b | 373 | memctl->memc_or1 = ~(ram_sz - 1) | 0x400; |
6d0f6bcf | 374 | memctl->memc_br1 = (CONFIG_SYS_SDRAM_BASE + dimm_sz) | 0x81; |
c609719b WD |
375 | } |
376 | } | |
377 | ||
378 | return ram_sz + dimm_sz; | |
379 | } |