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