]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc83xx/cpu.c
mpc83xx: update [local-]mac-address properties on UEC based devices
[karo-tx-uboot.git] / cpu / mpc83xx / cpu.c
1 /*
2  * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
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
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 <ft_build.h>
34 #include <asm/processor.h>
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38
39 int checkcpu(void)
40 {
41         volatile immap_t *immr;
42         ulong clock = gd->cpu_clk;
43         u32 pvr = get_pvr();
44         u32 spridr;
45         char buf[32];
46
47         immr = (immap_t *)CFG_IMMR;
48
49         if ((pvr & 0xFFFF0000) != PVR_83xx) {
50                 puts("Not MPC83xx Family!!!\n");
51                 return -1;
52         }
53
54         spridr = immr->sysconf.spridr;
55         puts("CPU: ");
56         switch(spridr) {
57         case SPR_8349E_REV10:
58         case SPR_8349E_REV11:
59         case SPR_8349E_REV31:
60                 puts("MPC8349E, ");
61                 break;
62         case SPR_8349_REV10:
63         case SPR_8349_REV11:
64         case SPR_8349_REV31:
65                 puts("MPC8349, ");
66                 break;
67         case SPR_8347E_REV10_TBGA:
68         case SPR_8347E_REV11_TBGA:
69         case SPR_8347E_REV31_TBGA:
70         case SPR_8347E_REV10_PBGA:
71         case SPR_8347E_REV11_PBGA:
72         case SPR_8347E_REV31_PBGA:
73                 puts("MPC8347E, ");
74                 break;
75         case SPR_8347_REV10_TBGA:
76         case SPR_8347_REV11_TBGA:
77         case SPR_8347_REV31_TBGA:
78         case SPR_8347_REV10_PBGA:
79         case SPR_8347_REV11_PBGA:
80         case SPR_8347_REV31_PBGA:
81                 puts("MPC8347, ");
82                 break;
83         case SPR_8343E_REV10:
84         case SPR_8343E_REV11:
85         case SPR_8343E_REV31:
86                 puts("MPC8343E, ");
87                 break;
88         case SPR_8343_REV10:
89         case SPR_8343_REV11:
90         case SPR_8343_REV31:
91                 puts("MPC8343, ");
92                 break;
93         case SPR_8360E_REV10:
94         case SPR_8360E_REV11:
95         case SPR_8360E_REV12:
96         case SPR_8360E_REV20:
97                 puts("MPC8360E, ");
98                 break;
99         case SPR_8360_REV10:
100         case SPR_8360_REV11:
101         case SPR_8360_REV12:
102         case SPR_8360_REV20:
103                 puts("MPC8360, ");
104                 break;
105         case SPR_8323E_REV10:
106         case SPR_8323E_REV11:
107                 puts("MPC8323E, ");
108                 break;
109         case SPR_8323_REV10:
110         case SPR_8323_REV11:
111                 puts("MPC8323, ");
112                 break;
113         case SPR_8321E_REV10:
114         case SPR_8321E_REV11:
115                 puts("MPC8321E, ");
116                 break;
117         case SPR_8321_REV10:
118         case SPR_8321_REV11:
119                 puts("MPC8321, ");
120                 break;
121         default:
122                 puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n");
123                 return 0;
124         }
125
126 #if defined(CONFIG_MPC834X)
127         /* Multiple revisons of 834x processors may have the same SPRIDR value.
128          * So use PVR to identify the revision number.
129          */
130         printf("Rev: %02x at %s MHz\n", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock));
131 #else
132         printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock));
133 #endif
134         return 0;
135 }
136
137
138 /*
139  * Program a UPM with the code supplied in the table.
140  *
141  * The 'dummy' variable is used to increment the MAD. 'dummy' is
142  * supposed to be a pointer to the memory of the device being
143  * programmed by the UPM.  The data in the MDR is written into
144  * memory and the MAD is incremented every time there's a read
145  * from 'dummy'. Unfortunately, the current prototype for this
146  * function doesn't allow for passing the address of this
147  * device, and changing the prototype will break a number lots
148  * of other code, so we need to use a round-about way of finding
149  * the value for 'dummy'.
150  *
151  * The value can be extracted from the base address bits of the
152  * Base Register (BR) associated with the specific UPM.  To find
153  * that BR, we need to scan all 8 BRs until we find the one that
154  * has its MSEL bits matching the UPM we want.  Once we know the
155  * right BR, we can extract the base address bits from it.
156  *
157  * The MxMR and the BR and OR of the chosen bank should all be
158  * configured before calling this function.
159  *
160  * Parameters:
161  * upm: 0=UPMA, 1=UPMB, 2=UPMC
162  * table: Pointer to an array of values to program
163  * size: Number of elements in the array.  Must be 64 or less.
164  */
165 void upmconfig (uint upm, uint *table, uint size)
166 {
167 #if defined(CONFIG_MPC834X)
168         volatile immap_t *immap = (immap_t *) CFG_IMMR;
169         volatile lbus83xx_t *lbus = &immap->lbus;
170         volatile uchar *dummy = NULL;
171         const u32 msel = (upm + 4) << BR_MSEL_SHIFT;    /* What the MSEL field in BRn should be */
172         volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */
173         uint i;
174
175         /* Scan all the banks to determine the base address of the device */
176         for (i = 0; i < 8; i++) {
177                 if ((lbus->bank[i].br & BR_MSEL) == msel) {
178                         dummy = (uchar *) (lbus->bank[i].br & BR_BA);
179                         break;
180                 }
181         }
182
183         if (!dummy) {
184                 printf("Error: %s() could not find matching BR\n", __FUNCTION__);
185                 hang();
186         }
187
188         /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */
189         *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000;
190
191         for (i = 0; i < size; i++) {
192                 lbus->mdr = table[i];
193                 __asm__ __volatile__ ("sync");
194                 *dummy; /* Write the value to memory and increment MAD */
195                 __asm__ __volatile__ ("sync");
196         }
197
198         /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */
199         *mxmr &= 0xCFFFFFC0;
200 #else
201         printf("Error: %s() not defined for this configuration.\n", __FUNCTION__);
202         hang();
203 #endif
204 }
205
206
207 int
208 do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
209 {
210         ulong msr;
211 #ifndef MPC83xx_RESET
212         ulong addr;
213 #endif
214
215         volatile immap_t *immap = (immap_t *) CFG_IMMR;
216
217 #ifdef MPC83xx_RESET
218         /* Interrupts and MMU off */
219         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
220
221         msr &= ~( MSR_EE | MSR_IR | MSR_DR);
222         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
223
224         /* enable Reset Control Reg */
225         immap->reset.rpr = 0x52535445;
226         __asm__ __volatile__ ("sync");
227         __asm__ __volatile__ ("isync");
228
229         /* confirm Reset Control Reg is enabled */
230         while(!((immap->reset.rcer) & RCER_CRE));
231
232         printf("Resetting the board.");
233         printf("\n");
234
235         udelay(200);
236
237         /* perform reset, only one bit */
238         immap->reset.rcr = RCR_SWHR;
239
240 #else   /* ! MPC83xx_RESET */
241
242         immap->reset.rmr = RMR_CSRE;    /* Checkstop Reset enable */
243
244         /* Interrupts and MMU off */
245         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
246
247         msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
248         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
249
250         /*
251          * Trying to execute the next instruction at a non-existing address
252          * should cause a machine check, resulting in reset
253          */
254         addr = CFG_RESET_ADDRESS;
255
256         printf("resetting the board.");
257         printf("\n");
258         ((void (*)(void)) addr) ();
259 #endif  /* MPC83xx_RESET */
260
261         return 1;
262 }
263
264
265 /*
266  * Get timebase clock frequency (like cpu_clk in Hz)
267  */
268
269 unsigned long get_tbclk(void)
270 {
271         ulong tbclk;
272
273         tbclk = (gd->bus_clk + 3L) / 4L;
274
275         return tbclk;
276 }
277
278
279 #if defined(CONFIG_WATCHDOG)
280 void watchdog_reset (void)
281 {
282         int re_enable = disable_interrupts();
283
284         /* Reset the 83xx watchdog */
285         volatile immap_t *immr = (immap_t *) CFG_IMMR;
286         immr->wdt.swsrr = 0x556c;
287         immr->wdt.swsrr = 0xaa39;
288
289         if (re_enable)
290                 enable_interrupts ();
291 }
292 #endif
293
294 #if defined(CONFIG_OF_FLAT_TREE)
295 void
296 ft_cpu_setup(void *blob, bd_t *bd)
297 {
298         u32 *p;
299         int len;
300         ulong clock;
301
302         clock = bd->bi_busfreq;
303         p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
304         if (p != NULL)
305                 *p = cpu_to_be32(clock);
306
307         p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
308         if (p != NULL)
309                 *p = cpu_to_be32(clock);
310
311         p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
312         if (p != NULL)
313                 *p = cpu_to_be32(clock);
314
315         p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
316         if (p != NULL)
317                 *p = cpu_to_be32(clock);
318
319 #ifdef CONFIG_MPC83XX_TSEC1
320         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
321         if (p != NULL)
322                 memcpy(p, bd->bi_enetaddr, 6);
323
324         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len);
325         if (p != NULL)
326                 memcpy(p, bd->bi_enetaddr, 6);
327 #endif
328
329 #ifdef CONFIG_MPC83XX_TSEC2
330         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
331         if (p != NULL)
332                 memcpy(p, bd->bi_enet1addr, 6);
333
334         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len);
335         if (p != NULL)
336                 memcpy(p, bd->bi_enet1addr, 6);
337 #endif
338
339 #ifdef CONFIG_UEC_ETH1
340 #if CFG_UEC1_UCC_NUM == 0  /* UCC1 */
341         p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len);
342         if (p != NULL)
343                 memcpy(p, bd->bi_enetaddr, 6);
344
345         p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len);
346         if (p != NULL)
347                 memcpy(p, bd->bi_enetaddr, 6);
348 #elif CFG_UEC1_UCC_NUM == 2  /* UCC3 */
349         p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len);
350         if (p != NULL)
351                 memcpy(p, bd->bi_enetaddr, 6);
352
353         p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len);
354         if (p != NULL)
355                 memcpy(p, bd->bi_enetaddr, 6);
356 #endif
357 #endif
358
359 #ifdef CONFIG_UEC_ETH2
360 #if CFG_UEC2_UCC_NUM == 1  /* UCC2 */
361         p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len);
362         if (p != NULL)
363                 memcpy(p, bd->bi_enet1addr, 6);
364
365         p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len);
366         if (p != NULL)
367                 memcpy(p, bd->bi_enet1addr, 6);
368 #elif CFG_UEC2_UCC_NUM == 3  /* UCC4 */
369         p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len);
370         if (p != NULL)
371                 memcpy(p, bd->bi_enet1addr, 6);
372
373         p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len);
374         if (p != NULL)
375                 memcpy(p, bd->bi_enet1addr, 6);
376 #endif
377 #endif
378 }
379 #endif
380
381 #if defined(CONFIG_DDR_ECC)
382 void dma_init(void)
383 {
384         volatile immap_t *immap = (immap_t *)CFG_IMMR;
385         volatile dma83xx_t *dma = &immap->dma;
386         volatile u32 status = swab32(dma->dmasr0);
387         volatile u32 dmamr0 = swab32(dma->dmamr0);
388
389         debug("DMA-init\n");
390
391         /* initialize DMASARn, DMADAR and DMAABCRn */
392         dma->dmadar0 = (u32)0;
393         dma->dmasar0 = (u32)0;
394         dma->dmabcr0 = 0;
395
396         __asm__ __volatile__ ("sync");
397         __asm__ __volatile__ ("isync");
398
399         /* clear CS bit */
400         dmamr0 &= ~DMA_CHANNEL_START;
401         dma->dmamr0 = swab32(dmamr0);
402         __asm__ __volatile__ ("sync");
403         __asm__ __volatile__ ("isync");
404
405         /* while the channel is busy, spin */
406         while(status & DMA_CHANNEL_BUSY) {
407                 status = swab32(dma->dmasr0);
408         }
409
410         debug("DMA-init end\n");
411 }
412
413 uint dma_check(void)
414 {
415         volatile immap_t *immap = (immap_t *)CFG_IMMR;
416         volatile dma83xx_t *dma = &immap->dma;
417         volatile u32 status = swab32(dma->dmasr0);
418         volatile u32 byte_count = swab32(dma->dmabcr0);
419
420         /* while the channel is busy, spin */
421         while (status & DMA_CHANNEL_BUSY) {
422                 status = swab32(dma->dmasr0);
423         }
424
425         if (status & DMA_CHANNEL_TRANSFER_ERROR) {
426                 printf ("DMA Error: status = %x @ %d\n", status, byte_count);
427         }
428
429         return status;
430 }
431
432 int dma_xfer(void *dest, u32 count, void *src)
433 {
434         volatile immap_t *immap = (immap_t *)CFG_IMMR;
435         volatile dma83xx_t *dma = &immap->dma;
436         volatile u32 dmamr0;
437
438         /* initialize DMASARn, DMADAR and DMAABCRn */
439         dma->dmadar0 = swab32((u32)dest);
440         dma->dmasar0 = swab32((u32)src);
441         dma->dmabcr0 = swab32(count);
442
443         __asm__ __volatile__ ("sync");
444         __asm__ __volatile__ ("isync");
445
446         /* init direct transfer, clear CS bit */
447         dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT |
448                         DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B |
449                         DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN);
450
451         dma->dmamr0 = swab32(dmamr0);
452
453         __asm__ __volatile__ ("sync");
454         __asm__ __volatile__ ("isync");
455
456         /* set CS to start DMA transfer */
457         dmamr0 |= DMA_CHANNEL_START;
458         dma->dmamr0 = swab32(dmamr0);
459         __asm__ __volatile__ ("sync");
460         __asm__ __volatile__ ("isync");
461
462         return ((int)dma_check());
463 }
464 #endif /*CONFIG_DDR_ECC*/