]>
Commit | Line | Data |
---|---|---|
f046ccd1 | 1 | /* |
f6eda7f8 | 2 | * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. |
f046ccd1 EL |
3 | * |
4 | * See file CREDITS for list of people who contributed to this | |
5 | * project. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
20 | * MA 02111-1307 USA | |
f046ccd1 EL |
21 | */ |
22 | ||
23 | /* | |
24 | * CPU specific code for the MPC83xx family. | |
25 | * | |
26 | * Derived from the MPC8260 and MPC85xx. | |
27 | */ | |
28 | ||
29 | #include <common.h> | |
30 | #include <watchdog.h> | |
31 | #include <command.h> | |
32 | #include <mpc83xx.h> | |
33 | #include <asm/processor.h> | |
213bf8c8 GVB |
34 | #if defined(CONFIG_OF_FLAT_TREE) |
35 | #include <ft_build.h> | |
36 | #endif | |
37 | #if defined(CONFIG_OF_LIBFDT) | |
38 | #include <libfdt.h> | |
39 | #include <libfdt_env.h> | |
40 | #endif | |
f046ccd1 | 41 | |
d87080b7 WD |
42 | DECLARE_GLOBAL_DATA_PTR; |
43 | ||
f046ccd1 EL |
44 | |
45 | int checkcpu(void) | |
46 | { | |
5f820439 | 47 | volatile immap_t *immr; |
f046ccd1 EL |
48 | ulong clock = gd->cpu_clk; |
49 | u32 pvr = get_pvr(); | |
5f820439 | 50 | u32 spridr; |
f046ccd1 EL |
51 | char buf[32]; |
52 | ||
d239d74b | 53 | immr = (immap_t *)CFG_IMMR; |
5f820439 | 54 | |
95e7ef89 SW |
55 | puts("CPU: "); |
56 | ||
57 | switch (pvr & 0xffff0000) { | |
58 | case PVR_E300C1: | |
59 | printf("e300c1, "); | |
60 | break; | |
61 | ||
62 | case PVR_E300C2: | |
63 | printf("e300c2, "); | |
64 | break; | |
65 | ||
66 | case PVR_E300C3: | |
67 | printf("e300c3, "); | |
68 | break; | |
69 | ||
70 | default: | |
71 | printf("Unknown core, "); | |
f046ccd1 EL |
72 | } |
73 | ||
5f820439 | 74 | spridr = immr->sysconf.spridr; |
5f820439 DL |
75 | switch(spridr) { |
76 | case SPR_8349E_REV10: | |
77 | case SPR_8349E_REV11: | |
8d172c0f | 78 | case SPR_8349E_REV31: |
5f820439 DL |
79 | puts("MPC8349E, "); |
80 | break; | |
81 | case SPR_8349_REV10: | |
82 | case SPR_8349_REV11: | |
8d172c0f | 83 | case SPR_8349_REV31: |
5f820439 DL |
84 | puts("MPC8349, "); |
85 | break; | |
86 | case SPR_8347E_REV10_TBGA: | |
87 | case SPR_8347E_REV11_TBGA: | |
8d172c0f | 88 | case SPR_8347E_REV31_TBGA: |
5f820439 DL |
89 | case SPR_8347E_REV10_PBGA: |
90 | case SPR_8347E_REV11_PBGA: | |
8d172c0f | 91 | case SPR_8347E_REV31_PBGA: |
5f820439 DL |
92 | puts("MPC8347E, "); |
93 | break; | |
94 | case SPR_8347_REV10_TBGA: | |
95 | case SPR_8347_REV11_TBGA: | |
8d172c0f | 96 | case SPR_8347_REV31_TBGA: |
5f820439 DL |
97 | case SPR_8347_REV10_PBGA: |
98 | case SPR_8347_REV11_PBGA: | |
8d172c0f | 99 | case SPR_8347_REV31_PBGA: |
5f820439 DL |
100 | puts("MPC8347, "); |
101 | break; | |
102 | case SPR_8343E_REV10: | |
103 | case SPR_8343E_REV11: | |
8d172c0f | 104 | case SPR_8343E_REV31: |
5f820439 DL |
105 | puts("MPC8343E, "); |
106 | break; | |
107 | case SPR_8343_REV10: | |
108 | case SPR_8343_REV11: | |
8d172c0f | 109 | case SPR_8343_REV31: |
5f820439 DL |
110 | puts("MPC8343, "); |
111 | break; | |
112 | case SPR_8360E_REV10: | |
113 | case SPR_8360E_REV11: | |
114 | case SPR_8360E_REV12: | |
b110f40b | 115 | case SPR_8360E_REV20: |
5f820439 | 116 | puts("MPC8360E, "); |
f046ccd1 | 117 | break; |
5f820439 DL |
118 | case SPR_8360_REV10: |
119 | case SPR_8360_REV11: | |
120 | case SPR_8360_REV12: | |
b110f40b | 121 | case SPR_8360_REV20: |
5f820439 | 122 | puts("MPC8360, "); |
f046ccd1 | 123 | break; |
24c3aca3 DL |
124 | case SPR_8323E_REV10: |
125 | case SPR_8323E_REV11: | |
126 | puts("MPC8323E, "); | |
127 | break; | |
128 | case SPR_8323_REV10: | |
129 | case SPR_8323_REV11: | |
130 | puts("MPC8323, "); | |
131 | break; | |
132 | case SPR_8321E_REV10: | |
133 | case SPR_8321E_REV11: | |
134 | puts("MPC8321E, "); | |
135 | break; | |
136 | case SPR_8321_REV10: | |
137 | case SPR_8321_REV11: | |
138 | puts("MPC8321, "); | |
139 | break; | |
a35b0c49 SW |
140 | case SPR_8311_REV10: |
141 | puts("MPC8311, "); | |
142 | break; | |
143 | case SPR_8311E_REV10: | |
144 | puts("MPC8311E, "); | |
145 | break; | |
146 | case SPR_8313_REV10: | |
147 | puts("MPC8313, "); | |
148 | break; | |
149 | case SPR_8313E_REV10: | |
150 | puts("MPC8313E, "); | |
151 | break; | |
f046ccd1 | 152 | default: |
8d172c0f XX |
153 | puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n"); |
154 | return 0; | |
f046ccd1 | 155 | } |
6902df56 | 156 | |
3e78a31c | 157 | #if defined(CONFIG_MPC834X) |
8d172c0f XX |
158 | /* Multiple revisons of 834x processors may have the same SPRIDR value. |
159 | * So use PVR to identify the revision number. | |
160 | */ | |
161 | printf("Rev: %02x at %s MHz\n", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock)); | |
5f820439 DL |
162 | #else |
163 | printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock)); | |
164 | #endif | |
f046ccd1 EL |
165 | return 0; |
166 | } | |
167 | ||
168 | ||
be5e6181 | 169 | /* |
2ad6b513 TT |
170 | * Program a UPM with the code supplied in the table. |
171 | * | |
172 | * The 'dummy' variable is used to increment the MAD. 'dummy' is | |
173 | * supposed to be a pointer to the memory of the device being | |
174 | * programmed by the UPM. The data in the MDR is written into | |
175 | * memory and the MAD is incremented every time there's a read | |
176 | * from 'dummy'. Unfortunately, the current prototype for this | |
177 | * function doesn't allow for passing the address of this | |
178 | * device, and changing the prototype will break a number lots | |
179 | * of other code, so we need to use a round-about way of finding | |
180 | * the value for 'dummy'. | |
181 | * | |
182 | * The value can be extracted from the base address bits of the | |
183 | * Base Register (BR) associated with the specific UPM. To find | |
184 | * that BR, we need to scan all 8 BRs until we find the one that | |
185 | * has its MSEL bits matching the UPM we want. Once we know the | |
186 | * right BR, we can extract the base address bits from it. | |
187 | * | |
188 | * The MxMR and the BR and OR of the chosen bank should all be | |
189 | * configured before calling this function. | |
190 | * | |
191 | * Parameters: | |
192 | * upm: 0=UPMA, 1=UPMB, 2=UPMC | |
193 | * table: Pointer to an array of values to program | |
194 | * size: Number of elements in the array. Must be 64 or less. | |
be5e6181 | 195 | */ |
f046ccd1 EL |
196 | void upmconfig (uint upm, uint *table, uint size) |
197 | { | |
2ad6b513 | 198 | #if defined(CONFIG_MPC834X) |
d239d74b | 199 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
2ad6b513 TT |
200 | volatile lbus83xx_t *lbus = &immap->lbus; |
201 | volatile uchar *dummy = NULL; | |
202 | const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */ | |
203 | volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */ | |
204 | uint i; | |
205 | ||
206 | /* Scan all the banks to determine the base address of the device */ | |
207 | for (i = 0; i < 8; i++) { | |
208 | if ((lbus->bank[i].br & BR_MSEL) == msel) { | |
209 | dummy = (uchar *) (lbus->bank[i].br & BR_BA); | |
210 | break; | |
211 | } | |
212 | } | |
213 | ||
214 | if (!dummy) { | |
215 | printf("Error: %s() could not find matching BR\n", __FUNCTION__); | |
216 | hang(); | |
217 | } | |
218 | ||
219 | /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */ | |
220 | *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000; | |
221 | ||
222 | for (i = 0; i < size; i++) { | |
223 | lbus->mdr = table[i]; | |
224 | __asm__ __volatile__ ("sync"); | |
225 | *dummy; /* Write the value to memory and increment MAD */ | |
226 | __asm__ __volatile__ ("sync"); | |
227 | } | |
228 | ||
229 | /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */ | |
230 | *mxmr &= 0xCFFFFFC0; | |
231 | #else | |
232 | printf("Error: %s() not defined for this configuration.\n", __FUNCTION__); | |
233 | hang(); | |
234 | #endif | |
f046ccd1 EL |
235 | } |
236 | ||
237 | ||
238 | int | |
239 | do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) | |
240 | { | |
07a2505f WD |
241 | ulong msr; |
242 | #ifndef MPC83xx_RESET | |
243 | ulong addr; | |
244 | #endif | |
f046ccd1 | 245 | |
d239d74b | 246 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
f046ccd1 EL |
247 | |
248 | #ifdef MPC83xx_RESET | |
249 | /* Interrupts and MMU off */ | |
250 | __asm__ __volatile__ ("mfmsr %0":"=r" (msr):); | |
251 | ||
252 | msr &= ~( MSR_EE | MSR_IR | MSR_DR); | |
253 | __asm__ __volatile__ ("mtmsr %0"::"r" (msr)); | |
254 | ||
255 | /* enable Reset Control Reg */ | |
256 | immap->reset.rpr = 0x52535445; | |
6d8ae5ab MB |
257 | __asm__ __volatile__ ("sync"); |
258 | __asm__ __volatile__ ("isync"); | |
f046ccd1 EL |
259 | |
260 | /* confirm Reset Control Reg is enabled */ | |
261 | while(!((immap->reset.rcer) & RCER_CRE)); | |
262 | ||
263 | printf("Resetting the board."); | |
264 | printf("\n"); | |
265 | ||
266 | udelay(200); | |
267 | ||
268 | /* perform reset, only one bit */ | |
07a2505f WD |
269 | immap->reset.rcr = RCR_SWHR; |
270 | ||
271 | #else /* ! MPC83xx_RESET */ | |
f046ccd1 | 272 | |
07a2505f WD |
273 | immap->reset.rmr = RMR_CSRE; /* Checkstop Reset enable */ |
274 | ||
275 | /* Interrupts and MMU off */ | |
276 | __asm__ __volatile__ ("mfmsr %0":"=r" (msr):); | |
f046ccd1 EL |
277 | |
278 | msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR); | |
279 | __asm__ __volatile__ ("mtmsr %0"::"r" (msr)); | |
280 | ||
281 | /* | |
282 | * Trying to execute the next instruction at a non-existing address | |
283 | * should cause a machine check, resulting in reset | |
284 | */ | |
285 | addr = CFG_RESET_ADDRESS; | |
286 | ||
287 | printf("resetting the board."); | |
288 | printf("\n"); | |
289 | ((void (*)(void)) addr) (); | |
07a2505f WD |
290 | #endif /* MPC83xx_RESET */ |
291 | ||
f046ccd1 EL |
292 | return 1; |
293 | } | |
294 | ||
295 | ||
296 | /* | |
297 | * Get timebase clock frequency (like cpu_clk in Hz) | |
298 | */ | |
299 | ||
300 | unsigned long get_tbclk(void) | |
301 | { | |
f046ccd1 EL |
302 | ulong tbclk; |
303 | ||
304 | tbclk = (gd->bus_clk + 3L) / 4L; | |
305 | ||
306 | return tbclk; | |
307 | } | |
308 | ||
309 | ||
310 | #if defined(CONFIG_WATCHDOG) | |
311 | void watchdog_reset (void) | |
312 | { | |
2ad6b513 TT |
313 | int re_enable = disable_interrupts(); |
314 | ||
315 | /* Reset the 83xx watchdog */ | |
d239d74b | 316 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
2ad6b513 TT |
317 | immr->wdt.swsrr = 0x556c; |
318 | immr->wdt.swsrr = 0xaa39; | |
319 | ||
320 | if (re_enable) | |
321 | enable_interrupts (); | |
f046ccd1 | 322 | } |
2ad6b513 | 323 | #endif |
62ec6418 | 324 | |
213bf8c8 GVB |
325 | #if defined(CONFIG_OF_LIBFDT) |
326 | ||
f35a53fc GVB |
327 | /* |
328 | * "Setter" functions used to add/modify FDT entries. | |
329 | */ | |
330 | static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd) | |
331 | { | |
332 | /* | |
333 | * Fix it up if it exists, don't create it if it doesn't exist. | |
334 | */ | |
335 | if (fdt_get_property(fdt, nodeoffset, name, 0)) { | |
336 | return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6); | |
337 | } | |
338 | return -FDT_ERR_NOTFOUND; | |
339 | } | |
340 | #ifdef CONFIG_HAS_ETH1 | |
341 | /* second onboard ethernet port */ | |
342 | static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd) | |
343 | { | |
344 | /* | |
345 | * Fix it up if it exists, don't create it if it doesn't exist. | |
346 | */ | |
347 | if (fdt_get_property(fdt, nodeoffset, name, 0)) { | |
348 | return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6); | |
349 | } | |
350 | return -FDT_ERR_NOTFOUND; | |
351 | } | |
352 | #endif | |
353 | #ifdef CONFIG_HAS_ETH2 | |
354 | /* third onboard ethernet port */ | |
355 | static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd) | |
356 | { | |
357 | /* | |
358 | * Fix it up if it exists, don't create it if it doesn't exist. | |
359 | */ | |
360 | if (fdt_get_property(fdt, nodeoffset, name, 0)) { | |
361 | return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6); | |
362 | } | |
363 | return -FDT_ERR_NOTFOUND; | |
364 | } | |
365 | #endif | |
366 | #ifdef CONFIG_HAS_ETH3 | |
367 | /* fourth onboard ethernet port */ | |
368 | static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd) | |
369 | { | |
370 | /* | |
371 | * Fix it up if it exists, don't create it if it doesn't exist. | |
372 | */ | |
373 | if (fdt_get_property(fdt, nodeoffset, name, 0)) { | |
374 | return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6); | |
375 | } | |
376 | return -FDT_ERR_NOTFOUND; | |
377 | } | |
378 | #endif | |
379 | ||
380 | static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd) | |
381 | { | |
382 | u32 tmp; | |
383 | /* | |
384 | * Create or update the property. | |
385 | */ | |
386 | tmp = cpu_to_be32(bd->bi_busfreq); | |
387 | return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); | |
388 | } | |
389 | ||
213bf8c8 GVB |
390 | /* |
391 | * Fixups to the fdt. If "create" is TRUE, the node is created | |
392 | * unconditionally. If "create" is FALSE, the node is updated | |
393 | * only if it already exists. | |
394 | */ | |
213bf8c8 | 395 | static const struct { |
213bf8c8 GVB |
396 | char *node; |
397 | char *prop; | |
f35a53fc | 398 | int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd); |
213bf8c8 | 399 | } fixup_props[] = { |
f35a53fc | 400 | { "/cpus/" OF_CPU, |
213bf8c8 | 401 | "bus-frequency", |
f35a53fc | 402 | fdt_set_busfreq |
213bf8c8 | 403 | }, |
f35a53fc GVB |
404 | { "/cpus/" OF_SOC, |
405 | "bus-frequency", | |
406 | fdt_set_busfreq | |
213bf8c8 | 407 | }, |
f35a53fc GVB |
408 | { "/" OF_SOC "/serial@4500/", |
409 | "clock-frequency", | |
410 | fdt_set_busfreq | |
213bf8c8 | 411 | }, |
f35a53fc GVB |
412 | { "/" OF_SOC "/serial@4600/", |
413 | "clock-frequency", | |
414 | fdt_set_busfreq | |
213bf8c8 GVB |
415 | }, |
416 | #ifdef CONFIG_MPC83XX_TSEC1 | |
f35a53fc | 417 | { "/" OF_SOC "/ethernet@24000, |
213bf8c8 | 418 | "mac-address", |
f35a53fc | 419 | fdt_set_eth0 |
213bf8c8 | 420 | }, |
f35a53fc | 421 | { "/" OF_SOC "/ethernet@24000, |
213bf8c8 | 422 | "local-mac-address", |
f35a53fc | 423 | fdt_set_eth0 |
213bf8c8 GVB |
424 | }, |
425 | #endif | |
426 | #ifdef CONFIG_MPC83XX_TSEC2 | |
f35a53fc | 427 | { "/" OF_SOC "/ethernet@25000, |
213bf8c8 | 428 | "mac-address", |
f35a53fc | 429 | fdt_set_eth1 |
213bf8c8 | 430 | }, |
f35a53fc | 431 | { "/" OF_SOC "/ethernet@25000, |
213bf8c8 | 432 | "local-mac-address", |
f35a53fc | 433 | fdt_set_eth1 |
213bf8c8 GVB |
434 | }, |
435 | #endif | |
f35a53fc GVB |
436 | #ifdef CONFIG_UEC_ETH1 |
437 | #if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ | |
438 | { "/" OF_QE "/ucc@2000/mac-address", | |
439 | "mac-address", | |
440 | fdt_set_eth0 | |
441 | }, | |
442 | { "/" OF_QE "/ucc@2000/mac-address", | |
443 | "local-mac-address", | |
444 | fdt_set_eth0 | |
445 | }, | |
446 | #elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ | |
447 | { "/" OF_QE "/ucc@2200/mac-address", | |
448 | "mac-address", | |
449 | fdt_set_eth0 | |
450 | }, | |
451 | { "/" OF_QE "/ucc@2200/mac-address", | |
452 | "local-mac-address", | |
453 | fdt_set_eth0 | |
454 | }, | |
455 | #endif | |
456 | #endif | |
457 | #ifdef CONFIG_UEC_ETH2 | |
458 | #if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ | |
459 | { "/" OF_QE "/ucc@3000/mac-address", | |
460 | "mac-address", | |
461 | fdt_set_eth1 | |
462 | }, | |
463 | { "/" OF_QE "/ucc@3000/mac-address", | |
464 | "local-mac-address", | |
465 | fdt_set_eth1 | |
466 | }, | |
467 | #elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */ | |
468 | { "/" OF_QE "/ucc@3200/mac-address", | |
469 | "mac-address", | |
470 | fdt_set_eth1 | |
471 | }, | |
472 | { "/" OF_QE "/ucc@3200/mac-address", | |
473 | "local-mac-address", | |
474 | fdt_set_eth1 | |
475 | }, | |
476 | #endif | |
477 | #endif | |
213bf8c8 GVB |
478 | }; |
479 | ||
480 | void | |
481 | ft_cpu_setup(void *blob, bd_t *bd) | |
482 | { | |
f35a53fc GVB |
483 | int nodeoffset; |
484 | int err; | |
485 | int j; | |
213bf8c8 GVB |
486 | |
487 | for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { | |
f35a53fc | 488 | nodeoffset = fdt_path_offset(fdt, fixup_props[j].node); |
213bf8c8 | 489 | if (nodeoffset >= 0) { |
f35a53fc GVB |
490 | err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd); |
491 | if (err < 0) | |
492 | printf("set_fn/libfdt: %s %s returned %s\n", | |
493 | fixup_props[j].node, | |
494 | fixup_props[j].prop, | |
495 | fdt_strerror(err)); | |
213bf8c8 GVB |
496 | } |
497 | } | |
498 | } | |
499 | #endif | |
500 | ||
62ec6418 KG |
501 | #if defined(CONFIG_OF_FLAT_TREE) |
502 | void | |
503 | ft_cpu_setup(void *blob, bd_t *bd) | |
504 | { | |
505 | u32 *p; | |
506 | int len; | |
507 | ulong clock; | |
508 | ||
509 | clock = bd->bi_busfreq; | |
510 | p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len); | |
511 | if (p != NULL) | |
512 | *p = cpu_to_be32(clock); | |
513 | ||
514 | p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len); | |
515 | if (p != NULL) | |
516 | *p = cpu_to_be32(clock); | |
517 | ||
518 | p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len); | |
519 | if (p != NULL) | |
520 | *p = cpu_to_be32(clock); | |
521 | ||
522 | p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len); | |
523 | if (p != NULL) | |
524 | *p = cpu_to_be32(clock); | |
525 | ||
526 | #ifdef CONFIG_MPC83XX_TSEC1 | |
61f4f912 TT |
527 | p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len); |
528 | if (p != NULL) | |
529 | memcpy(p, bd->bi_enetaddr, 6); | |
530 | ||
48041365 | 531 | p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len); |
b7004747 | 532 | if (p != NULL) |
62ec6418 KG |
533 | memcpy(p, bd->bi_enetaddr, 6); |
534 | #endif | |
535 | ||
536 | #ifdef CONFIG_MPC83XX_TSEC2 | |
61f4f912 TT |
537 | p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len); |
538 | if (p != NULL) | |
539 | memcpy(p, bd->bi_enet1addr, 6); | |
540 | ||
48041365 | 541 | p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len); |
b7004747 | 542 | if (p != NULL) |
62ec6418 KG |
543 | memcpy(p, bd->bi_enet1addr, 6); |
544 | #endif | |
d51b3cf3 KP |
545 | |
546 | #ifdef CONFIG_UEC_ETH1 | |
547 | #if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ | |
548 | p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len); | |
549 | if (p != NULL) | |
550 | memcpy(p, bd->bi_enetaddr, 6); | |
551 | ||
552 | p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len); | |
553 | if (p != NULL) | |
554 | memcpy(p, bd->bi_enetaddr, 6); | |
555 | #elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ | |
556 | p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len); | |
557 | if (p != NULL) | |
558 | memcpy(p, bd->bi_enetaddr, 6); | |
559 | ||
560 | p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len); | |
561 | if (p != NULL) | |
562 | memcpy(p, bd->bi_enetaddr, 6); | |
563 | #endif | |
564 | #endif | |
565 | ||
566 | #ifdef CONFIG_UEC_ETH2 | |
567 | #if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ | |
568 | p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len); | |
569 | if (p != NULL) | |
570 | memcpy(p, bd->bi_enet1addr, 6); | |
571 | ||
572 | p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len); | |
573 | if (p != NULL) | |
574 | memcpy(p, bd->bi_enet1addr, 6); | |
575 | #elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */ | |
576 | p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len); | |
577 | if (p != NULL) | |
578 | memcpy(p, bd->bi_enet1addr, 6); | |
579 | ||
580 | p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len); | |
581 | if (p != NULL) | |
582 | memcpy(p, bd->bi_enet1addr, 6); | |
583 | #endif | |
584 | #endif | |
62ec6418 KG |
585 | } |
586 | #endif | |
61f25155 MB |
587 | |
588 | #if defined(CONFIG_DDR_ECC) | |
589 | void dma_init(void) | |
590 | { | |
d239d74b | 591 | volatile immap_t *immap = (immap_t *)CFG_IMMR; |
f6eda7f8 | 592 | volatile dma83xx_t *dma = &immap->dma; |
61f25155 MB |
593 | volatile u32 status = swab32(dma->dmasr0); |
594 | volatile u32 dmamr0 = swab32(dma->dmamr0); | |
595 | ||
596 | debug("DMA-init\n"); | |
597 | ||
598 | /* initialize DMASARn, DMADAR and DMAABCRn */ | |
599 | dma->dmadar0 = (u32)0; | |
600 | dma->dmasar0 = (u32)0; | |
601 | dma->dmabcr0 = 0; | |
602 | ||
603 | __asm__ __volatile__ ("sync"); | |
604 | __asm__ __volatile__ ("isync"); | |
605 | ||
606 | /* clear CS bit */ | |
607 | dmamr0 &= ~DMA_CHANNEL_START; | |
608 | dma->dmamr0 = swab32(dmamr0); | |
609 | __asm__ __volatile__ ("sync"); | |
610 | __asm__ __volatile__ ("isync"); | |
611 | ||
612 | /* while the channel is busy, spin */ | |
613 | while(status & DMA_CHANNEL_BUSY) { | |
614 | status = swab32(dma->dmasr0); | |
615 | } | |
616 | ||
617 | debug("DMA-init end\n"); | |
618 | } | |
619 | ||
620 | uint dma_check(void) | |
621 | { | |
d239d74b | 622 | volatile immap_t *immap = (immap_t *)CFG_IMMR; |
f6eda7f8 | 623 | volatile dma83xx_t *dma = &immap->dma; |
61f25155 MB |
624 | volatile u32 status = swab32(dma->dmasr0); |
625 | volatile u32 byte_count = swab32(dma->dmabcr0); | |
626 | ||
627 | /* while the channel is busy, spin */ | |
628 | while (status & DMA_CHANNEL_BUSY) { | |
629 | status = swab32(dma->dmasr0); | |
630 | } | |
631 | ||
632 | if (status & DMA_CHANNEL_TRANSFER_ERROR) { | |
633 | printf ("DMA Error: status = %x @ %d\n", status, byte_count); | |
634 | } | |
635 | ||
636 | return status; | |
637 | } | |
638 | ||
639 | int dma_xfer(void *dest, u32 count, void *src) | |
640 | { | |
d239d74b | 641 | volatile immap_t *immap = (immap_t *)CFG_IMMR; |
f6eda7f8 | 642 | volatile dma83xx_t *dma = &immap->dma; |
61f25155 MB |
643 | volatile u32 dmamr0; |
644 | ||
645 | /* initialize DMASARn, DMADAR and DMAABCRn */ | |
646 | dma->dmadar0 = swab32((u32)dest); | |
647 | dma->dmasar0 = swab32((u32)src); | |
648 | dma->dmabcr0 = swab32(count); | |
649 | ||
650 | __asm__ __volatile__ ("sync"); | |
651 | __asm__ __volatile__ ("isync"); | |
652 | ||
653 | /* init direct transfer, clear CS bit */ | |
654 | dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT | | |
655 | DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B | | |
656 | DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN); | |
cf48eb9a | 657 | |
61f25155 MB |
658 | dma->dmamr0 = swab32(dmamr0); |
659 | ||
660 | __asm__ __volatile__ ("sync"); | |
661 | __asm__ __volatile__ ("isync"); | |
662 | ||
663 | /* set CS to start DMA transfer */ | |
664 | dmamr0 |= DMA_CHANNEL_START; | |
665 | dma->dmamr0 = swab32(dmamr0); | |
666 | __asm__ __volatile__ ("sync"); | |
667 | __asm__ __volatile__ ("isync"); | |
668 | ||
669 | return ((int)dma_check()); | |
670 | } | |
671 | #endif /*CONFIG_DDR_ECC*/ |