mpc83xx: Add the cpu and board specific code for MPC8349E rev3.1 MDS
[oweals/u-boot.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                 puts("MPC8360E, ");
97                 break;
98         case SPR_8360_REV10:
99         case SPR_8360_REV11:
100         case SPR_8360_REV12:
101                 puts("MPC8360, ");
102                 break;
103         case SPR_8323E_REV10:
104         case SPR_8323E_REV11:
105                 puts("MPC8323E, ");
106                 break;
107         case SPR_8323_REV10:
108         case SPR_8323_REV11:
109                 puts("MPC8323, ");
110                 break;
111         case SPR_8321E_REV10:
112         case SPR_8321E_REV11:
113                 puts("MPC8321E, ");
114                 break;
115         case SPR_8321_REV10:
116         case SPR_8321_REV11:
117                 puts("MPC8321, ");
118                 break;
119         default:
120                 puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n");
121                 return 0;
122         }
123
124 #if defined(CONFIG_MPC834X)
125         /* Multiple revisons of 834x processors may have the same SPRIDR value.
126          * So use PVR to identify the revision number.
127          */
128         printf("Rev: %02x at %s MHz\n", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock));
129 #else
130         printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock));
131 #endif
132         return 0;
133 }
134
135
136 /*
137  * Program a UPM with the code supplied in the table.
138  *
139  * The 'dummy' variable is used to increment the MAD. 'dummy' is
140  * supposed to be a pointer to the memory of the device being
141  * programmed by the UPM.  The data in the MDR is written into
142  * memory and the MAD is incremented every time there's a read
143  * from 'dummy'. Unfortunately, the current prototype for this
144  * function doesn't allow for passing the address of this
145  * device, and changing the prototype will break a number lots
146  * of other code, so we need to use a round-about way of finding
147  * the value for 'dummy'.
148  *
149  * The value can be extracted from the base address bits of the
150  * Base Register (BR) associated with the specific UPM.  To find
151  * that BR, we need to scan all 8 BRs until we find the one that
152  * has its MSEL bits matching the UPM we want.  Once we know the
153  * right BR, we can extract the base address bits from it.
154  *
155  * The MxMR and the BR and OR of the chosen bank should all be
156  * configured before calling this function.
157  *
158  * Parameters:
159  * upm: 0=UPMA, 1=UPMB, 2=UPMC
160  * table: Pointer to an array of values to program
161  * size: Number of elements in the array.  Must be 64 or less.
162  */
163 void upmconfig (uint upm, uint *table, uint size)
164 {
165 #if defined(CONFIG_MPC834X)
166         volatile immap_t *immap = (immap_t *) CFG_IMMR;
167         volatile lbus83xx_t *lbus = &immap->lbus;
168         volatile uchar *dummy = NULL;
169         const u32 msel = (upm + 4) << BR_MSEL_SHIFT;    /* What the MSEL field in BRn should be */
170         volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */
171         uint i;
172
173         /* Scan all the banks to determine the base address of the device */
174         for (i = 0; i < 8; i++) {
175                 if ((lbus->bank[i].br & BR_MSEL) == msel) {
176                         dummy = (uchar *) (lbus->bank[i].br & BR_BA);
177                         break;
178                 }
179         }
180
181         if (!dummy) {
182                 printf("Error: %s() could not find matching BR\n", __FUNCTION__);
183                 hang();
184         }
185
186         /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */
187         *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000;
188
189         for (i = 0; i < size; i++) {
190                 lbus->mdr = table[i];
191                 __asm__ __volatile__ ("sync");
192                 *dummy; /* Write the value to memory and increment MAD */
193                 __asm__ __volatile__ ("sync");
194         }
195
196         /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */
197         *mxmr &= 0xCFFFFFC0;
198 #else
199         printf("Error: %s() not defined for this configuration.\n", __FUNCTION__);
200         hang();
201 #endif
202 }
203
204
205 int
206 do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
207 {
208         ulong msr;
209 #ifndef MPC83xx_RESET
210         ulong addr;
211 #endif
212
213         volatile immap_t *immap = (immap_t *) CFG_IMMR;
214
215 #ifdef MPC83xx_RESET
216         /* Interrupts and MMU off */
217         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
218
219         msr &= ~( MSR_EE | MSR_IR | MSR_DR);
220         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
221
222         /* enable Reset Control Reg */
223         immap->reset.rpr = 0x52535445;
224         __asm__ __volatile__ ("sync");
225         __asm__ __volatile__ ("isync");
226
227         /* confirm Reset Control Reg is enabled */
228         while(!((immap->reset.rcer) & RCER_CRE));
229
230         printf("Resetting the board.");
231         printf("\n");
232
233         udelay(200);
234
235         /* perform reset, only one bit */
236         immap->reset.rcr = RCR_SWHR;
237
238 #else   /* ! MPC83xx_RESET */
239
240         immap->reset.rmr = RMR_CSRE;    /* Checkstop Reset enable */
241
242         /* Interrupts and MMU off */
243         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
244
245         msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
246         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
247
248         /*
249          * Trying to execute the next instruction at a non-existing address
250          * should cause a machine check, resulting in reset
251          */
252         addr = CFG_RESET_ADDRESS;
253
254         printf("resetting the board.");
255         printf("\n");
256         ((void (*)(void)) addr) ();
257 #endif  /* MPC83xx_RESET */
258
259         return 1;
260 }
261
262
263 /*
264  * Get timebase clock frequency (like cpu_clk in Hz)
265  */
266
267 unsigned long get_tbclk(void)
268 {
269         ulong tbclk;
270
271         tbclk = (gd->bus_clk + 3L) / 4L;
272
273         return tbclk;
274 }
275
276
277 #if defined(CONFIG_WATCHDOG)
278 void watchdog_reset (void)
279 {
280         int re_enable = disable_interrupts();
281
282         /* Reset the 83xx watchdog */
283         volatile immap_t *immr = (immap_t *) CFG_IMMR;
284         immr->wdt.swsrr = 0x556c;
285         immr->wdt.swsrr = 0xaa39;
286
287         if (re_enable)
288                 enable_interrupts ();
289 }
290 #endif
291
292 #if defined(CONFIG_OF_FLAT_TREE)
293 void
294 ft_cpu_setup(void *blob, bd_t *bd)
295 {
296         u32 *p;
297         int len;
298         ulong clock;
299
300         clock = bd->bi_busfreq;
301         p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
302         if (p != NULL)
303                 *p = cpu_to_be32(clock);
304
305         p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
306         if (p != NULL)
307                 *p = cpu_to_be32(clock);
308
309         p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
310         if (p != NULL)
311                 *p = cpu_to_be32(clock);
312
313         p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
314         if (p != NULL)
315                 *p = cpu_to_be32(clock);
316
317 #ifdef CONFIG_MPC83XX_TSEC1
318         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len);
319         if (p != NULL)
320                 memcpy(p, bd->bi_enetaddr, 6);
321 #endif
322
323 #ifdef CONFIG_MPC83XX_TSEC2
324         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len);
325         if (p != NULL)
326                 memcpy(p, bd->bi_enet1addr, 6);
327 #endif
328 }
329 #endif
330
331 #if defined(CONFIG_DDR_ECC)
332 void dma_init(void)
333 {
334         volatile immap_t *immap = (immap_t *)CFG_IMMR;
335         volatile dma83xx_t *dma = &immap->dma;
336         volatile u32 status = swab32(dma->dmasr0);
337         volatile u32 dmamr0 = swab32(dma->dmamr0);
338
339         debug("DMA-init\n");
340
341         /* initialize DMASARn, DMADAR and DMAABCRn */
342         dma->dmadar0 = (u32)0;
343         dma->dmasar0 = (u32)0;
344         dma->dmabcr0 = 0;
345
346         __asm__ __volatile__ ("sync");
347         __asm__ __volatile__ ("isync");
348
349         /* clear CS bit */
350         dmamr0 &= ~DMA_CHANNEL_START;
351         dma->dmamr0 = swab32(dmamr0);
352         __asm__ __volatile__ ("sync");
353         __asm__ __volatile__ ("isync");
354
355         /* while the channel is busy, spin */
356         while(status & DMA_CHANNEL_BUSY) {
357                 status = swab32(dma->dmasr0);
358         }
359
360         debug("DMA-init end\n");
361 }
362
363 uint dma_check(void)
364 {
365         volatile immap_t *immap = (immap_t *)CFG_IMMR;
366         volatile dma83xx_t *dma = &immap->dma;
367         volatile u32 status = swab32(dma->dmasr0);
368         volatile u32 byte_count = swab32(dma->dmabcr0);
369
370         /* while the channel is busy, spin */
371         while (status & DMA_CHANNEL_BUSY) {
372                 status = swab32(dma->dmasr0);
373         }
374
375         if (status & DMA_CHANNEL_TRANSFER_ERROR) {
376                 printf ("DMA Error: status = %x @ %d\n", status, byte_count);
377         }
378
379         return status;
380 }
381
382 int dma_xfer(void *dest, u32 count, void *src)
383 {
384         volatile immap_t *immap = (immap_t *)CFG_IMMR;
385         volatile dma83xx_t *dma = &immap->dma;
386         volatile u32 dmamr0;
387
388         /* initialize DMASARn, DMADAR and DMAABCRn */
389         dma->dmadar0 = swab32((u32)dest);
390         dma->dmasar0 = swab32((u32)src);
391         dma->dmabcr0 = swab32(count);
392
393         __asm__ __volatile__ ("sync");
394         __asm__ __volatile__ ("isync");
395
396         /* init direct transfer, clear CS bit */
397         dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT |
398                         DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B |
399                         DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN);
400
401         dma->dmamr0 = swab32(dmamr0);
402
403         __asm__ __volatile__ ("sync");
404         __asm__ __volatile__ ("isync");
405
406         /* set CS to start DMA transfer */
407         dmamr0 |= DMA_CHANNEL_START;
408         dma->dmamr0 = swab32(dmamr0);
409         __asm__ __volatile__ ("sync");
410         __asm__ __volatile__ ("isync");
411
412         return ((int)dma_check());
413 }
414 #endif /*CONFIG_DDR_ECC*/