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