Remove dead debug code.
[platform/kernel/u-boot.git] / cpu / mpc86xx / cpu.c
1 /*
2  * Copyright 2004 Freescale Semiconductor
3  * Jeff Brown (jeffrey@freescale.com)
4  * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26 #include <watchdog.h>
27 #include <command.h>
28 #include <asm/cache.h>
29 #include <mpc86xx.h>
30
31 #if defined(CONFIG_OF_FLAT_TREE)
32 #include <ft_build.h>
33 #endif
34
35 #include "../board/mpc8641hpcn/pixis.h"
36
37
38 int checkcpu (void)
39 {
40         sys_info_t sysinfo;
41         uint pvr, svr;
42         uint ver;
43         uint major, minor;
44         uint lcrr;              /* local bus clock ratio register */
45         uint clkdiv;            /* clock divider portion of lcrr */
46
47         puts("Freescale PowerPC\n");
48
49         pvr = get_pvr();
50         ver = PVR_VER(pvr);
51         major = PVR_MAJ(pvr);
52         minor = PVR_MIN(pvr);
53
54         puts("CPU:\n");
55
56         printf("    Core: ");
57
58         switch (ver) {
59         case PVR_VER(PVR_86xx):
60             puts("E600");
61             break;
62         default:
63             puts("Unknown");
64             break;
65         }
66         printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
67
68         svr = get_svr();
69         ver = SVR_VER(svr);
70         major = SVR_MAJ(svr);
71         minor = SVR_MIN(svr);
72
73         puts("    System: ");
74         switch (ver) {
75         case SVR_8641:
76                 puts("8641");
77                 break;
78         case SVR_8641D:
79                 puts("8641D");
80                 break;
81         default:
82                 puts("Unknown");
83                 break;
84         }
85         printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
86
87         get_sys_info(&sysinfo);
88
89         puts("    Clocks: ");
90         printf("CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
91         printf("MPX:%4lu MHz, ", sysinfo.freqSystemBus / 1000000);
92         printf("DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
93
94 #if defined(CFG_LBC_LCRR)
95         lcrr = CFG_LBC_LCRR;
96 #else
97         {
98             volatile immap_t *immap = (immap_t *)CFG_IMMR;
99             volatile ccsr_lbc_t *lbc= &immap->im_lbc;
100
101             lcrr = lbc->lcrr;
102         }
103 #endif
104         clkdiv = lcrr & 0x0f;
105         if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
106                 printf("LBC:%4lu MHz\n",
107                        sysinfo.freqSystemBus / 1000000 / clkdiv);
108         } else {
109                 printf("    LBC: unknown (lcrr: 0x%08x)\n", lcrr);
110         }
111
112         printf("    L2: ");
113         if (get_l2cr() & 0x80000000)
114                 printf("Enabled\n");
115         else
116                 printf("Disabled\n");
117
118         return 0;
119 }
120
121
122 static inline void
123 soft_restart(unsigned long addr)
124 {
125
126 #ifndef CONFIG_MPC8641HPCN
127
128         /* SRR0 has system reset vector, SRR1 has default MSR value */
129         /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
130
131         __asm__ __volatile__ ("mtspr    26, %0"         :: "r" (addr));
132         __asm__ __volatile__ ("li       4, (1 << 6)"    ::: "r4");
133         __asm__ __volatile__ ("mtspr    27, 4");
134         __asm__ __volatile__ ("rfi");
135
136 #else /* CONFIG_MPC8641HPCN */
137         out8(PIXIS_BASE+PIXIS_RST,0);
138 #endif /* !CONFIG_MPC8641HPCN */
139         while(1);       /* not reached */
140 }
141
142
143 /*
144  * No generic way to do board reset. Simply call soft_reset.
145  */
146 void
147 do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
148 {
149         char cmd;
150         ulong addr, val;
151         ulong corepll;
152
153 #ifdef CFG_RESET_ADDRESS
154         addr = CFG_RESET_ADDRESS;
155 #else
156         /*
157          * note: when CFG_MONITOR_BASE points to a RAM address,
158          * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
159          * address. Better pick an address known to be invalid on your
160          * system and assign it to CFG_RESET_ADDRESS.
161          */
162         addr = CFG_MONITOR_BASE - sizeof (ulong);
163 #endif
164
165 #ifndef CONFIG_MPC8641HPCN
166
167         /* flush and disable I/D cache */
168         __asm__ __volatile__ ("mfspr    3, 1008"        ::: "r3");
169         __asm__ __volatile__ ("ori      5, 5, 0xcc00"   ::: "r5");
170         __asm__ __volatile__ ("ori      4, 3, 0xc00"    ::: "r4");
171         __asm__ __volatile__ ("andc     5, 3, 5"        ::: "r5");
172         __asm__ __volatile__ ("sync");
173         __asm__ __volatile__ ("mtspr    1008, 4");
174         __asm__ __volatile__ ("isync");
175         __asm__ __volatile__ ("sync");
176         __asm__ __volatile__ ("mtspr    1008, 5");
177         __asm__ __volatile__ ("isync");
178         __asm__ __volatile__ ("sync");
179
180         soft_restart(addr);
181
182 #else /* CONFIG_MPC8641HPCN */
183
184         if (argc > 1) {
185                 cmd = argv[1][1];
186                 switch(cmd) {
187                 case 'f':    /* reset with frequency changed */
188                         if (argc < 5)
189                                 goto my_usage;
190                         read_from_px_regs(0);
191
192                         val = set_px_sysclk(simple_strtoul(argv[2],NULL,10));
193
194                         corepll = strfractoint(argv[3]);
195                         val = val + set_px_corepll(corepll);
196                         val = val + set_px_mpxpll(simple_strtoul(argv[4],
197                                                                  NULL, 10));
198                         if (val == 3) {
199                                 printf("Setting registers VCFGEN0 and VCTL\n");
200                                 read_from_px_regs(1);
201                                 printf("Resetting board with values from VSPEED0, VSPEED1, VCLKH, and VCLKL ....\n");
202                                 set_px_go();
203                         } else
204                                 goto my_usage;
205
206                         while (1); /* Not reached */
207
208                 case 'l':
209                         if (argv[2][1] == 'f') {
210                                 read_from_px_regs(0);
211                                 read_from_px_regs_altbank(0);
212                                 /* reset with frequency changed */
213                                 val = set_px_sysclk(simple_strtoul(argv[3],NULL,10));
214
215                                 corepll = strfractoint(argv[4]);
216                                 val = val + set_px_corepll(corepll);
217                                 val = val + set_px_mpxpll(simple_strtoul(argv[5],NULL,10));
218                                 if (val == 3) {
219                                         printf("Setting registers VCFGEN0, VCFGEN1, VBOOT, and VCTL\n");
220                                         set_altbank();
221                                         read_from_px_regs(1);
222                                         read_from_px_regs_altbank(1);
223                                         printf("Enabling watchdog timer on the FPGA and resetting board with values from VSPEED0, VSPEED1, VCLKH, and VCLKL to boot from the other bank ....\n");
224                                         set_px_go_with_watchdog();
225                                 } else
226                                         goto my_usage;
227
228                                 while(1); /* Not reached */
229                         } else if(argv[2][1] == 'd'){
230                                 /* Reset from next bank without changing frequencies but with watchdog timer enabled */
231                                 read_from_px_regs(0);
232                                 read_from_px_regs_altbank(0);
233                                 printf("Setting registers VCFGEN1, VBOOT, and VCTL\n");
234                                 set_altbank();
235                                 read_from_px_regs_altbank(1);
236                                 printf("Enabling watchdog timer on the FPGA and resetting board to boot from the other bank....\n");
237                                 set_px_go_with_watchdog();
238                                 while(1); /* Not reached */
239                         } else {
240                                 /* Reset from next bank without changing frequency and without watchdog timer enabled */
241                                 read_from_px_regs(0);
242                                 read_from_px_regs_altbank(0);
243                                 if(argc > 2)
244                                         goto my_usage;
245                                 printf("Setting registers VCFGNE1, VBOOT, and VCTL\n");
246                                 set_altbank();
247                                 read_from_px_regs_altbank(1);
248                                 printf("Resetting board to boot from the other bank....\n");
249                                 set_px_go();
250                         }
251
252                 default:
253                         goto my_usage;
254                 }
255
256 my_usage:
257                 printf("\nUsage: reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n");
258                 printf("       reset altbank [cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>]\n");
259                 printf("For example:   reset cf 40 2.5 10\n");
260                 printf("See MPC8641HPCN Design Workbook for valid values of command line parameters.\n");
261                 return;
262         } else
263                 out8(PIXIS_BASE+PIXIS_RST,0);
264
265 #endif /* !CONFIG_MPC8641HPCN */
266
267         while(1);       /* not reached */
268 }
269
270
271 /*
272  * Get timebase clock frequency
273  */
274 unsigned long get_tbclk(void)
275 {
276         sys_info_t  sys_info;
277
278         get_sys_info(&sys_info);
279         return (sys_info.freqSystemBus + 3L) / 4L;
280 }
281
282
283 #if defined(CONFIG_WATCHDOG)
284 void
285 watchdog_reset(void)
286 {
287 }
288 #endif  /* CONFIG_WATCHDOG */
289
290
291 #if defined(CONFIG_DDR_ECC)
292 void dma_init(void)
293 {
294         volatile immap_t *immap = (immap_t *)CFG_IMMR;
295         volatile ccsr_dma_t *dma = &immap->im_dma;
296
297         dma->satr0 = 0x00040000;
298         dma->datr0 = 0x00040000;
299         asm("sync; isync");
300 }
301
302 uint dma_check(void)
303 {
304         volatile immap_t *immap = (immap_t *)CFG_IMMR;
305         volatile ccsr_dma_t *dma = &immap->im_dma;
306         volatile uint status = dma->sr0;
307
308         /* While the channel is busy, spin */
309         while((status & 4) == 4) {
310                 status = dma->sr0;
311         }
312
313         if (status != 0) {
314                 printf ("DMA Error: status = %x\n", status);
315         }
316         return status;
317 }
318
319 int dma_xfer(void *dest, uint count, void *src)
320 {
321         volatile immap_t *immap = (immap_t *)CFG_IMMR;
322         volatile ccsr_dma_t *dma = &immap->im_dma;
323
324         dma->dar0 = (uint) dest;
325         dma->sar0 = (uint) src;
326         dma->bcr0 = count;
327         dma->mr0 = 0xf000004;
328         asm("sync;isync");
329         dma->mr0 = 0xf000005;
330         asm("sync;isync");
331         return dma_check();
332 }
333
334 #endif  /* CONFIG_DDR_ECC */
335
336
337 #ifdef CONFIG_OF_FLAT_TREE
338 void ft_cpu_setup(void *blob, bd_t *bd)
339 {
340         u32 *p;
341         ulong clock;
342         int len;
343
344         clock = bd->bi_busfreq;
345         p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
346         if (p != NULL)
347                 *p = cpu_to_be32(clock);
348
349         p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
350         if (p != NULL)
351                 *p = cpu_to_be32(clock);
352
353         p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
354         if (p != NULL)
355                 *p = cpu_to_be32(clock);
356
357 #if defined(CONFIG_MPC86XX_TSEC1)
358         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/address", &len);
359         memcpy(p, bd->bi_enetaddr, 6);
360 #endif
361
362 #if defined(CONFIG_MPC86XX_TSEC2)
363         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/address", &len);
364         memcpy(p, bd->bi_enet1addr, 6);
365 #endif
366
367 #if defined(CONFIG_MPC86XX_TSEC3)
368         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/address", &len);
369         memcpy(p, bd->bi_enet2addr, 6);
370 #endif
371
372 #if defined(CONFIG_MPC86XX_TSEC4)
373         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/address", &len);
374          memcpy(p, bd->bi_enet3addr, 6);
375 #endif
376
377 }
378 #endif