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