blob: e934ba638fef62e99ff6ce635c8f9cef4611f59e [file] [log] [blame]
Eran Liberty9095d4a2005-07-28 10:08:46 -05001/*
Dave Liuf5035922006-10-25 14:41:21 -05002 * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
Eran Liberty9095d4a2005-07-28 10:08:46 -05003 *
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
Eran Liberty9095d4a2005-07-28 10:08:46 -050021 */
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>
Gerald Van Barend6abef42007-03-31 12:23:51 -040034#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
Eran Liberty9095d4a2005-07-28 10:08:46 -050041
Wolfgang Denk6405a152006-03-31 18:32:53 +020042DECLARE_GLOBAL_DATA_PTR;
43
Eran Liberty9095d4a2005-07-28 10:08:46 -050044
45int checkcpu(void)
46{
Dave Liua46daea2006-11-03 19:33:44 -060047 volatile immap_t *immr;
Eran Liberty9095d4a2005-07-28 10:08:46 -050048 ulong clock = gd->cpu_clk;
49 u32 pvr = get_pvr();
Dave Liua46daea2006-11-03 19:33:44 -060050 u32 spridr;
Eran Liberty9095d4a2005-07-28 10:08:46 -050051 char buf[32];
52
Timur Tabi386a2802006-11-03 12:00:28 -060053 immr = (immap_t *)CFG_IMMR;
Dave Liua46daea2006-11-03 19:33:44 -060054
Eran Liberty9095d4a2005-07-28 10:08:46 -050055 if ((pvr & 0xFFFF0000) != PVR_83xx) {
56 puts("Not MPC83xx Family!!!\n");
57 return -1;
58 }
59
Dave Liua46daea2006-11-03 19:33:44 -060060 spridr = immr->sysconf.spridr;
61 puts("CPU: ");
62 switch(spridr) {
63 case SPR_8349E_REV10:
64 case SPR_8349E_REV11:
Xie Xiaobo800b7532007-02-14 18:26:44 +080065 case SPR_8349E_REV31:
Dave Liua46daea2006-11-03 19:33:44 -060066 puts("MPC8349E, ");
67 break;
68 case SPR_8349_REV10:
69 case SPR_8349_REV11:
Xie Xiaobo800b7532007-02-14 18:26:44 +080070 case SPR_8349_REV31:
Dave Liua46daea2006-11-03 19:33:44 -060071 puts("MPC8349, ");
72 break;
73 case SPR_8347E_REV10_TBGA:
74 case SPR_8347E_REV11_TBGA:
Xie Xiaobo800b7532007-02-14 18:26:44 +080075 case SPR_8347E_REV31_TBGA:
Dave Liua46daea2006-11-03 19:33:44 -060076 case SPR_8347E_REV10_PBGA:
77 case SPR_8347E_REV11_PBGA:
Xie Xiaobo800b7532007-02-14 18:26:44 +080078 case SPR_8347E_REV31_PBGA:
Dave Liua46daea2006-11-03 19:33:44 -060079 puts("MPC8347E, ");
80 break;
81 case SPR_8347_REV10_TBGA:
82 case SPR_8347_REV11_TBGA:
Xie Xiaobo800b7532007-02-14 18:26:44 +080083 case SPR_8347_REV31_TBGA:
Dave Liua46daea2006-11-03 19:33:44 -060084 case SPR_8347_REV10_PBGA:
85 case SPR_8347_REV11_PBGA:
Xie Xiaobo800b7532007-02-14 18:26:44 +080086 case SPR_8347_REV31_PBGA:
Dave Liua46daea2006-11-03 19:33:44 -060087 puts("MPC8347, ");
Eran Liberty9095d4a2005-07-28 10:08:46 -050088 break;
Dave Liua46daea2006-11-03 19:33:44 -060089 case SPR_8343E_REV10:
90 case SPR_8343E_REV11:
Xie Xiaobo800b7532007-02-14 18:26:44 +080091 case SPR_8343E_REV31:
Dave Liua46daea2006-11-03 19:33:44 -060092 puts("MPC8343E, ");
93 break;
94 case SPR_8343_REV10:
95 case SPR_8343_REV11:
Xie Xiaobo800b7532007-02-14 18:26:44 +080096 case SPR_8343_REV31:
Dave Liua46daea2006-11-03 19:33:44 -060097 puts("MPC8343, ");
98 break;
99 case SPR_8360E_REV10:
100 case SPR_8360E_REV11:
101 case SPR_8360E_REV12:
Xie Xiaoboa9be42a2007-02-14 18:27:06 +0800102 case SPR_8360E_REV20:
Dave Liua46daea2006-11-03 19:33:44 -0600103 puts("MPC8360E, ");
104 break;
105 case SPR_8360_REV10:
106 case SPR_8360_REV11:
107 case SPR_8360_REV12:
Xie Xiaoboa9be42a2007-02-14 18:27:06 +0800108 case SPR_8360_REV20:
Dave Liua46daea2006-11-03 19:33:44 -0600109 puts("MPC8360, ");
Eran Liberty9095d4a2005-07-28 10:08:46 -0500110 break;
Dave Liue740c462006-12-07 21:13:15 +0800111 case SPR_8323E_REV10:
112 case SPR_8323E_REV11:
113 puts("MPC8323E, ");
114 break;
115 case SPR_8323_REV10:
116 case SPR_8323_REV11:
117 puts("MPC8323, ");
118 break;
119 case SPR_8321E_REV10:
120 case SPR_8321E_REV11:
121 puts("MPC8321E, ");
122 break;
123 case SPR_8321_REV10:
124 case SPR_8321_REV11:
125 puts("MPC8321, ");
126 break;
Eran Liberty9095d4a2005-07-28 10:08:46 -0500127 default:
Xie Xiaobo800b7532007-02-14 18:26:44 +0800128 puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n");
129 return 0;
Eran Liberty9095d4a2005-07-28 10:08:46 -0500130 }
Rafal Jaworowski384da5e2005-10-17 02:39:53 +0200131
Kumar Galab7870e72007-01-30 14:08:30 -0600132#if defined(CONFIG_MPC834X)
Xie Xiaobo800b7532007-02-14 18:26:44 +0800133 /* Multiple revisons of 834x processors may have the same SPRIDR value.
134 * So use PVR to identify the revision number.
135 */
136 printf("Rev: %02x at %s MHz\n", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock));
Dave Liua46daea2006-11-03 19:33:44 -0600137#else
138 printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock));
139#endif
Eran Liberty9095d4a2005-07-28 10:08:46 -0500140 return 0;
141}
142
143
Timur Tabiab347542006-11-03 19:15:00 -0600144/*
Timur Tabi054838e2006-10-31 18:44:42 -0600145 * Program a UPM with the code supplied in the table.
146 *
147 * The 'dummy' variable is used to increment the MAD. 'dummy' is
148 * supposed to be a pointer to the memory of the device being
149 * programmed by the UPM. The data in the MDR is written into
150 * memory and the MAD is incremented every time there's a read
151 * from 'dummy'. Unfortunately, the current prototype for this
152 * function doesn't allow for passing the address of this
153 * device, and changing the prototype will break a number lots
154 * of other code, so we need to use a round-about way of finding
155 * the value for 'dummy'.
156 *
157 * The value can be extracted from the base address bits of the
158 * Base Register (BR) associated with the specific UPM. To find
159 * that BR, we need to scan all 8 BRs until we find the one that
160 * has its MSEL bits matching the UPM we want. Once we know the
161 * right BR, we can extract the base address bits from it.
162 *
163 * The MxMR and the BR and OR of the chosen bank should all be
164 * configured before calling this function.
165 *
166 * Parameters:
167 * upm: 0=UPMA, 1=UPMB, 2=UPMC
168 * table: Pointer to an array of values to program
169 * size: Number of elements in the array. Must be 64 or less.
Timur Tabiab347542006-11-03 19:15:00 -0600170 */
Eran Liberty9095d4a2005-07-28 10:08:46 -0500171void upmconfig (uint upm, uint *table, uint size)
172{
Timur Tabi054838e2006-10-31 18:44:42 -0600173#if defined(CONFIG_MPC834X)
Timur Tabi386a2802006-11-03 12:00:28 -0600174 volatile immap_t *immap = (immap_t *) CFG_IMMR;
Timur Tabi054838e2006-10-31 18:44:42 -0600175 volatile lbus83xx_t *lbus = &immap->lbus;
176 volatile uchar *dummy = NULL;
177 const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */
178 volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */
179 uint i;
180
181 /* Scan all the banks to determine the base address of the device */
182 for (i = 0; i < 8; i++) {
183 if ((lbus->bank[i].br & BR_MSEL) == msel) {
184 dummy = (uchar *) (lbus->bank[i].br & BR_BA);
185 break;
186 }
187 }
188
189 if (!dummy) {
190 printf("Error: %s() could not find matching BR\n", __FUNCTION__);
191 hang();
192 }
193
194 /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */
195 *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000;
196
197 for (i = 0; i < size; i++) {
198 lbus->mdr = table[i];
199 __asm__ __volatile__ ("sync");
200 *dummy; /* Write the value to memory and increment MAD */
201 __asm__ __volatile__ ("sync");
202 }
203
204 /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */
205 *mxmr &= 0xCFFFFFC0;
206#else
207 printf("Error: %s() not defined for this configuration.\n", __FUNCTION__);
208 hang();
209#endif
Eran Liberty9095d4a2005-07-28 10:08:46 -0500210}
211
212
213int
214do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
215{
Wolfgang Denk301d0962005-08-05 19:49:35 +0200216 ulong msr;
217#ifndef MPC83xx_RESET
218 ulong addr;
219#endif
Eran Liberty9095d4a2005-07-28 10:08:46 -0500220
Timur Tabi386a2802006-11-03 12:00:28 -0600221 volatile immap_t *immap = (immap_t *) CFG_IMMR;
Eran Liberty9095d4a2005-07-28 10:08:46 -0500222
223#ifdef MPC83xx_RESET
224 /* Interrupts and MMU off */
225 __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
226
227 msr &= ~( MSR_EE | MSR_IR | MSR_DR);
228 __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
229
230 /* enable Reset Control Reg */
231 immap->reset.rpr = 0x52535445;
Marian Balakowicz919b1872006-03-14 16:12:48 +0100232 __asm__ __volatile__ ("sync");
233 __asm__ __volatile__ ("isync");
Eran Liberty9095d4a2005-07-28 10:08:46 -0500234
235 /* confirm Reset Control Reg is enabled */
236 while(!((immap->reset.rcer) & RCER_CRE));
237
238 printf("Resetting the board.");
239 printf("\n");
240
241 udelay(200);
242
243 /* perform reset, only one bit */
Wolfgang Denk301d0962005-08-05 19:49:35 +0200244 immap->reset.rcr = RCR_SWHR;
245
246#else /* ! MPC83xx_RESET */
Eran Liberty9095d4a2005-07-28 10:08:46 -0500247
Wolfgang Denk301d0962005-08-05 19:49:35 +0200248 immap->reset.rmr = RMR_CSRE; /* Checkstop Reset enable */
249
250 /* Interrupts and MMU off */
251 __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
Eran Liberty9095d4a2005-07-28 10:08:46 -0500252
253 msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
254 __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
255
256 /*
257 * Trying to execute the next instruction at a non-existing address
258 * should cause a machine check, resulting in reset
259 */
260 addr = CFG_RESET_ADDRESS;
261
262 printf("resetting the board.");
263 printf("\n");
264 ((void (*)(void)) addr) ();
Wolfgang Denk301d0962005-08-05 19:49:35 +0200265#endif /* MPC83xx_RESET */
266
Eran Liberty9095d4a2005-07-28 10:08:46 -0500267 return 1;
268}
269
270
271/*
272 * Get timebase clock frequency (like cpu_clk in Hz)
273 */
274
275unsigned long get_tbclk(void)
276{
Eran Liberty9095d4a2005-07-28 10:08:46 -0500277 ulong tbclk;
278
279 tbclk = (gd->bus_clk + 3L) / 4L;
280
281 return tbclk;
282}
283
284
285#if defined(CONFIG_WATCHDOG)
286void watchdog_reset (void)
287{
Timur Tabi054838e2006-10-31 18:44:42 -0600288 int re_enable = disable_interrupts();
289
290 /* Reset the 83xx watchdog */
Timur Tabi386a2802006-11-03 12:00:28 -0600291 volatile immap_t *immr = (immap_t *) CFG_IMMR;
Timur Tabi054838e2006-10-31 18:44:42 -0600292 immr->wdt.swsrr = 0x556c;
293 immr->wdt.swsrr = 0xaa39;
294
295 if (re_enable)
296 enable_interrupts ();
Eran Liberty9095d4a2005-07-28 10:08:46 -0500297}
Timur Tabi054838e2006-10-31 18:44:42 -0600298#endif
Kumar Gala5bbb0452006-01-11 16:48:10 -0600299
Gerald Van Barend6abef42007-03-31 12:23:51 -0400300#if defined(CONFIG_OF_LIBFDT)
301
302/*
Gerald Van Baren2f734162007-04-15 13:54:26 -0400303 * "Setter" functions used to add/modify FDT entries.
304 */
305static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd)
306{
307 /*
308 * Fix it up if it exists, don't create it if it doesn't exist.
309 */
310 if (fdt_get_property(fdt, nodeoffset, name, 0)) {
311 return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
312 }
313 return -FDT_ERR_NOTFOUND;
314}
315#ifdef CONFIG_HAS_ETH1
316/* second onboard ethernet port */
317static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd)
318{
319 /*
320 * Fix it up if it exists, don't create it if it doesn't exist.
321 */
322 if (fdt_get_property(fdt, nodeoffset, name, 0)) {
323 return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6);
324 }
325 return -FDT_ERR_NOTFOUND;
326}
327#endif
328#ifdef CONFIG_HAS_ETH2
329/* third onboard ethernet port */
330static int fdt_set_eth2(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_enet2addr, 6);
337 }
338 return -FDT_ERR_NOTFOUND;
339}
340#endif
341#ifdef CONFIG_HAS_ETH3
342/* fourth onboard ethernet port */
343static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd)
344{
345 /*
346 * Fix it up if it exists, don't create it if it doesn't exist.
347 */
348 if (fdt_get_property(fdt, nodeoffset, name, 0)) {
349 return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6);
350 }
351 return -FDT_ERR_NOTFOUND;
352}
353#endif
354
355static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
356{
357 u32 tmp;
358 /*
359 * Create or update the property.
360 */
361 tmp = cpu_to_be32(bd->bi_busfreq);
362 return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
363}
364
365/*
Gerald Van Barend6abef42007-03-31 12:23:51 -0400366 * Fixups to the fdt. If "create" is TRUE, the node is created
367 * unconditionally. If "create" is FALSE, the node is updated
368 * only if it already exists.
369 */
Gerald Van Barend6abef42007-03-31 12:23:51 -0400370static const struct {
Gerald Van Barend6abef42007-03-31 12:23:51 -0400371 char *node;
372 char *prop;
Gerald Van Baren2f734162007-04-15 13:54:26 -0400373 int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
Gerald Van Barend6abef42007-03-31 12:23:51 -0400374} fixup_props[] = {
Gerald Van Baren2f734162007-04-15 13:54:26 -0400375 { "/cpus/" OF_CPU,
Gerald Van Barend6abef42007-03-31 12:23:51 -0400376 "bus-frequency",
Gerald Van Baren2f734162007-04-15 13:54:26 -0400377 fdt_set_busfreq
Gerald Van Barend6abef42007-03-31 12:23:51 -0400378 },
Gerald Van Baren2f734162007-04-15 13:54:26 -0400379 { "/cpus/" OF_SOC,
380 "bus-frequency",
381 fdt_set_busfreq
Gerald Van Barend6abef42007-03-31 12:23:51 -0400382 },
Gerald Van Baren2f734162007-04-15 13:54:26 -0400383 { "/" OF_SOC "/serial@4500/",
384 "clock-frequency",
385 fdt_set_busfreq
Gerald Van Barend6abef42007-03-31 12:23:51 -0400386 },
Gerald Van Baren2f734162007-04-15 13:54:26 -0400387 { "/" OF_SOC "/serial@4600/",
388 "clock-frequency",
389 fdt_set_busfreq
Gerald Van Barend6abef42007-03-31 12:23:51 -0400390 },
391#ifdef CONFIG_MPC83XX_TSEC1
Gerald Van Baren2f734162007-04-15 13:54:26 -0400392 { "/" OF_SOC "/ethernet@24000,
Gerald Van Barend6abef42007-03-31 12:23:51 -0400393 "mac-address",
Gerald Van Baren2f734162007-04-15 13:54:26 -0400394 fdt_set_eth0
Gerald Van Barend6abef42007-03-31 12:23:51 -0400395 },
Gerald Van Baren2f734162007-04-15 13:54:26 -0400396 { "/" OF_SOC "/ethernet@24000,
Gerald Van Barend6abef42007-03-31 12:23:51 -0400397 "local-mac-address",
Gerald Van Baren2f734162007-04-15 13:54:26 -0400398 fdt_set_eth0
Gerald Van Barend6abef42007-03-31 12:23:51 -0400399 },
400#endif
401#ifdef CONFIG_MPC83XX_TSEC2
Gerald Van Baren2f734162007-04-15 13:54:26 -0400402 { "/" OF_SOC "/ethernet@25000,
403 "mac-address",
404 fdt_set_eth1
405 },
406 { "/" OF_SOC "/ethernet@25000,
407 "local-mac-address",
408 fdt_set_eth1
409 },
410#endif
411#ifdef CONFIG_UEC_ETH1
412#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
413 { "/" OF_QE "/ucc@2000/mac-address",
Gerald Van Barend6abef42007-03-31 12:23:51 -0400414 "mac-address",
Gerald Van Baren2f734162007-04-15 13:54:26 -0400415 fdt_set_eth0
Gerald Van Barend6abef42007-03-31 12:23:51 -0400416 },
Gerald Van Baren2f734162007-04-15 13:54:26 -0400417 { "/" OF_QE "/ucc@2000/mac-address",
Gerald Van Barend6abef42007-03-31 12:23:51 -0400418 "local-mac-address",
Gerald Van Baren2f734162007-04-15 13:54:26 -0400419 fdt_set_eth0
420 },
421#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
422 { "/" OF_QE "/ucc@2200/mac-address",
423 "mac-address",
424 fdt_set_eth0
425 },
426 { "/" OF_QE "/ucc@2200/mac-address",
427 "local-mac-address",
428 fdt_set_eth0
429 },
430#endif
431#endif
432#ifdef CONFIG_UEC_ETH2
433#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
434 { "/" OF_QE "/ucc@3000/mac-address",
435 "mac-address",
436 fdt_set_eth1
437 },
438 { "/" OF_QE "/ucc@3000/mac-address",
439 "local-mac-address",
440 fdt_set_eth1
441 },
442#elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */
443 { "/" OF_QE "/ucc@3200/mac-address",
444 "mac-address",
445 fdt_set_eth1
446 },
447 { "/" OF_QE "/ucc@3200/mac-address",
448 "local-mac-address",
449 fdt_set_eth1
Gerald Van Barend6abef42007-03-31 12:23:51 -0400450 },
451#endif
Gerald Van Baren2f734162007-04-15 13:54:26 -0400452#endif
Gerald Van Barend6abef42007-03-31 12:23:51 -0400453};
454
455void
456ft_cpu_setup(void *blob, bd_t *bd)
457{
Gerald Van Baren2f734162007-04-15 13:54:26 -0400458 int nodeoffset;
459 int err;
460 int j;
Gerald Van Barend6abef42007-03-31 12:23:51 -0400461
462 for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
Gerald Van Baren2f734162007-04-15 13:54:26 -0400463 nodeoffset = fdt_path_offset(fdt, fixup_props[j].node);
Gerald Van Barend6abef42007-03-31 12:23:51 -0400464 if (nodeoffset >= 0) {
Gerald Van Baren2f734162007-04-15 13:54:26 -0400465 err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd);
466 if (err < 0)
467 printf("set_fn/libfdt: %s %s returned %s\n",
468 fixup_props[j].node,
469 fixup_props[j].prop,
470 fdt_strerror(err));
Gerald Van Barend6abef42007-03-31 12:23:51 -0400471 }
472 }
473}
474#endif
475
Kumar Gala5bbb0452006-01-11 16:48:10 -0600476#if defined(CONFIG_OF_FLAT_TREE)
477void
478ft_cpu_setup(void *blob, bd_t *bd)
479{
480 u32 *p;
481 int len;
482 ulong clock;
483
484 clock = bd->bi_busfreq;
485 p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
486 if (p != NULL)
487 *p = cpu_to_be32(clock);
488
489 p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
490 if (p != NULL)
491 *p = cpu_to_be32(clock);
492
493 p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
494 if (p != NULL)
495 *p = cpu_to_be32(clock);
496
497 p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
498 if (p != NULL)
499 *p = cpu_to_be32(clock);
500
501#ifdef CONFIG_MPC83XX_TSEC1
Timur Tabief648382007-02-13 10:41:42 -0600502 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
503 if (p != NULL)
504 memcpy(p, bd->bi_enetaddr, 6);
505
Kim Phillipsd99bd8b2006-11-01 00:07:25 -0600506 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len);
Kim Phillips24f63e92007-01-30 16:15:21 -0600507 if (p != NULL)
Kumar Gala5bbb0452006-01-11 16:48:10 -0600508 memcpy(p, bd->bi_enetaddr, 6);
509#endif
510
511#ifdef CONFIG_MPC83XX_TSEC2
Timur Tabief648382007-02-13 10:41:42 -0600512 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
513 if (p != NULL)
514 memcpy(p, bd->bi_enet1addr, 6);
515
Kim Phillipsd99bd8b2006-11-01 00:07:25 -0600516 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len);
Kim Phillips24f63e92007-01-30 16:15:21 -0600517 if (p != NULL)
Kumar Gala5bbb0452006-01-11 16:48:10 -0600518 memcpy(p, bd->bi_enet1addr, 6);
519#endif
Kim Phillips526addb2007-02-22 20:06:57 -0600520
521#ifdef CONFIG_UEC_ETH1
522#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
523 p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len);
524 if (p != NULL)
525 memcpy(p, bd->bi_enetaddr, 6);
526
527 p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len);
528 if (p != NULL)
529 memcpy(p, bd->bi_enetaddr, 6);
530#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
531 p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len);
532 if (p != NULL)
533 memcpy(p, bd->bi_enetaddr, 6);
534
535 p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len);
536 if (p != NULL)
537 memcpy(p, bd->bi_enetaddr, 6);
538#endif
539#endif
540
541#ifdef CONFIG_UEC_ETH2
542#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
543 p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len);
544 if (p != NULL)
545 memcpy(p, bd->bi_enet1addr, 6);
546
547 p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len);
548 if (p != NULL)
549 memcpy(p, bd->bi_enet1addr, 6);
550#elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */
551 p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len);
552 if (p != NULL)
553 memcpy(p, bd->bi_enet1addr, 6);
554
555 p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len);
556 if (p != NULL)
557 memcpy(p, bd->bi_enet1addr, 6);
558#endif
559#endif
Kumar Gala5bbb0452006-01-11 16:48:10 -0600560}
561#endif
Marian Balakowicz7ec9ebc2006-03-14 16:14:48 +0100562
563#if defined(CONFIG_DDR_ECC)
564void dma_init(void)
565{
Timur Tabi386a2802006-11-03 12:00:28 -0600566 volatile immap_t *immap = (immap_t *)CFG_IMMR;
Dave Liuf5035922006-10-25 14:41:21 -0500567 volatile dma83xx_t *dma = &immap->dma;
Marian Balakowicz7ec9ebc2006-03-14 16:14:48 +0100568 volatile u32 status = swab32(dma->dmasr0);
569 volatile u32 dmamr0 = swab32(dma->dmamr0);
570
571 debug("DMA-init\n");
572
573 /* initialize DMASARn, DMADAR and DMAABCRn */
574 dma->dmadar0 = (u32)0;
575 dma->dmasar0 = (u32)0;
576 dma->dmabcr0 = 0;
577
578 __asm__ __volatile__ ("sync");
579 __asm__ __volatile__ ("isync");
580
581 /* clear CS bit */
582 dmamr0 &= ~DMA_CHANNEL_START;
583 dma->dmamr0 = swab32(dmamr0);
584 __asm__ __volatile__ ("sync");
585 __asm__ __volatile__ ("isync");
586
587 /* while the channel is busy, spin */
588 while(status & DMA_CHANNEL_BUSY) {
589 status = swab32(dma->dmasr0);
590 }
591
592 debug("DMA-init end\n");
593}
594
595uint dma_check(void)
596{
Timur Tabi386a2802006-11-03 12:00:28 -0600597 volatile immap_t *immap = (immap_t *)CFG_IMMR;
Dave Liuf5035922006-10-25 14:41:21 -0500598 volatile dma83xx_t *dma = &immap->dma;
Marian Balakowicz7ec9ebc2006-03-14 16:14:48 +0100599 volatile u32 status = swab32(dma->dmasr0);
600 volatile u32 byte_count = swab32(dma->dmabcr0);
601
602 /* while the channel is busy, spin */
603 while (status & DMA_CHANNEL_BUSY) {
604 status = swab32(dma->dmasr0);
605 }
606
607 if (status & DMA_CHANNEL_TRANSFER_ERROR) {
608 printf ("DMA Error: status = %x @ %d\n", status, byte_count);
609 }
610
611 return status;
612}
613
614int dma_xfer(void *dest, u32 count, void *src)
615{
Timur Tabi386a2802006-11-03 12:00:28 -0600616 volatile immap_t *immap = (immap_t *)CFG_IMMR;
Dave Liuf5035922006-10-25 14:41:21 -0500617 volatile dma83xx_t *dma = &immap->dma;
Marian Balakowicz7ec9ebc2006-03-14 16:14:48 +0100618 volatile u32 dmamr0;
619
620 /* initialize DMASARn, DMADAR and DMAABCRn */
621 dma->dmadar0 = swab32((u32)dest);
622 dma->dmasar0 = swab32((u32)src);
623 dma->dmabcr0 = swab32(count);
624
625 __asm__ __volatile__ ("sync");
626 __asm__ __volatile__ ("isync");
627
628 /* init direct transfer, clear CS bit */
629 dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT |
630 DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B |
631 DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN);
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200632
Marian Balakowicz7ec9ebc2006-03-14 16:14:48 +0100633 dma->dmamr0 = swab32(dmamr0);
634
635 __asm__ __volatile__ ("sync");
636 __asm__ __volatile__ ("isync");
637
638 /* set CS to start DMA transfer */
639 dmamr0 |= DMA_CHANNEL_START;
640 dma->dmamr0 = swab32(dmamr0);
641 __asm__ __volatile__ ("sync");
642 __asm__ __volatile__ ("isync");
643
644 return ((int)dma_check());
645}
646#endif /*CONFIG_DDR_ECC*/