blob: e21b051266c92b32f59e8728eece0d426ca37906 [file] [log] [blame]
Jon Loeligerdebb7352006-04-26 17:58:56 -05001/*
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
Jon Loeliger126aa702006-05-30 17:47:00 -050035#include "../board/mpc8641hpcn/pixis.h"
Jon Loeligerdebb7352006-04-26 17:58:56 -050036
Jon Loeligerdebb7352006-04-26 17:58:56 -050037
38static __inline__ unsigned long get_dbat3u (void)
39{
Jon Loeliger5c9efb32006-04-27 10:15:16 -050040 unsigned long dbat3u;
41 asm volatile("mfspr %0, 542" : "=r" (dbat3u) :);
42 return dbat3u;
Jon Loeligerdebb7352006-04-26 17:58:56 -050043}
44
45static __inline__ unsigned long get_dbat3l (void)
46{
Jon Loeliger5c9efb32006-04-27 10:15:16 -050047 unsigned long dbat3l;
48 asm volatile("mfspr %0, 543" : "=r" (dbat3l) :);
49 return dbat3l;
Jon Loeligerdebb7352006-04-26 17:58:56 -050050}
51
52static __inline__ unsigned long get_msr (void)
53{
Jon Loeliger5c9efb32006-04-27 10:15:16 -050054 unsigned long msr;
55 asm volatile("mfmsr %0" : "=r" (msr) :);
56 return msr;
Jon Loeligerdebb7352006-04-26 17:58:56 -050057}
58
Jon Loeligerdebb7352006-04-26 17:58:56 -050059
60int 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 */
Jon Loeliger5c9efb32006-04-27 10:15:16 -050068
Jon Loeligerdebb7352006-04-26 17:58:56 -050069 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
Jon Loeliger5c9efb32006-04-27 10:15:16 -050076 puts("CPU:\n");
Jon Loeligerdebb7352006-04-26 17:58:56 -050077
78 printf(" Core: ");
Jon Loeliger5c9efb32006-04-27 10:15:16 -050079
Jon Loeligerdebb7352006-04-26 17:58:56 -050080 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: ");
Jon Loeliger5c9efb32006-04-27 10:15:16 -050096 switch (ver) {
Jon Loeligerdebb7352006-04-26 17:58:56 -050097 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);
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500115
Jon Loeligerdebb7352006-04-26 17:58:56 -0500116#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
Jon Loeliger126aa702006-05-30 17:47:00 -0500134 printf(" L2: ");
135 if (get_l2cr() & 0x80000000)
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500136 printf("Enabled\n");
Jon Loeliger126aa702006-05-30 17:47:00 -0500137 else
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500138 printf("Disabled\n");
139
140 return 0;
Jon Loeligerdebb7352006-04-26 17:58:56 -0500141}
142
143
144/* -------------------------------------------------------------------- */
145
146static inline void
147soft_restart(unsigned long addr)
148{
149
150#ifndef CONFIG_MPC8641HPCN
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500151
Jon Loeligerdebb7352006-04-26 17:58:56 -0500152 /* 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 */
Jon Loeliger126aa702006-05-30 17:47:00 -0500161 out8(PIXIS_BASE+PIXIS_RST,0);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500162#endif /* !CONFIG_MPC8641HPCN */
163 while(1); /* not reached */
164}
165
166
Jon Loeliger126aa702006-05-30 17:47:00 -0500167/*
168 * No generic way to do board reset. Simply call soft_reset.
169 */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500170void
Jon Loeliger126aa702006-05-30 17:47:00 -0500171do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
Jon Loeligerdebb7352006-04-26 17:58:56 -0500172{
Jon Loeliger126aa702006-05-30 17:47:00 -0500173 char cmd;
174 ulong addr, val;
175 ulong corepll;
Jon Loeligerdebb7352006-04-26 17:58:56 -0500176
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
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500191 /* flush and disable I/D cache */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500192 __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
Jon Loeliger126aa702006-05-30 17:47:00 -0500204 soft_restart(addr);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500205
206#else /* CONFIG_MPC8641HPCN */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500207
Jon Loeliger126aa702006-05-30 17:47:00 -0500208 if (argc > 1) {
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500209 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);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500215
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500216 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 */
Haiying Wang38cee122006-05-30 09:10:32 -0500253 } else if(argv[2][1] == 'd'){
254 /* Reset from next bank without changing frequencies but with watchdog timer enabled */
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500255 read_from_px_regs(0);
256 read_from_px_regs_altbank(0);
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500257 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 */
Haiying Wang38cee122006-05-30 09:10:32 -0500263 } 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();
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500274 }
275
276 default:
277 goto my_usage;
278 }
279
Jon Loeligerdebb7352006-04-26 17:58:56 -0500280my_usage:
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500281 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;
Jon Loeliger126aa702006-05-30 17:47:00 -0500286 } else
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500287 out8(PIXIS_BASE+PIXIS_RST,0);
288
Jon Loeligerdebb7352006-04-26 17:58:56 -0500289#endif /* !CONFIG_MPC8641HPCN */
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500290
Jon Loeligerdebb7352006-04-26 17:58:56 -0500291 while(1); /* not reached */
292}
293
294
Jon Loeligerdebb7352006-04-26 17:58:56 -0500295/*
296 * Get timebase clock frequency
297 */
298unsigned long get_tbclk(void)
299{
300 sys_info_t sys_info;
301
302 get_sys_info(&sys_info);
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500303 return (sys_info.freqSystemBus + 3L) / 4L;
Jon Loeligerdebb7352006-04-26 17:58:56 -0500304}
305
Jon Loeligerdebb7352006-04-26 17:58:56 -0500306
307#if defined(CONFIG_WATCHDOG)
308void
309watchdog_reset(void)
310{
Jon Loeligerdebb7352006-04-26 17:58:56 -0500311}
312#endif /* CONFIG_WATCHDOG */
313
Jon Loeligerdebb7352006-04-26 17:58:56 -0500314
315#if defined(CONFIG_DDR_ECC)
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500316void dma_init(void)
317{
Jon Loeligerdebb7352006-04-26 17:58:56 -0500318 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");
Jon Loeligerdebb7352006-04-26 17:58:56 -0500324}
325
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500326uint dma_check(void)
327{
Jon Loeligerdebb7352006-04-26 17:58:56 -0500328 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
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500343int dma_xfer(void *dest, uint count, void *src)
344{
Jon Loeligerdebb7352006-04-26 17:58:56 -0500345 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}
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500357
Jon Loeligerdebb7352006-04-26 17:58:56 -0500358#endif /* CONFIG_DDR_ECC */
359
360
361#ifdef CONFIG_OF_FLAT_TREE
362void ft_cpu_setup(void *blob, bd_t *bd)
363{
364 u32 *p;
365 ulong clock;
366 int len;
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500367
Jon Loeligerdebb7352006-04-26 17:58:56 -0500368 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
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500385
Jon Loeligerdebb7352006-04-26 17:58:56 -0500386#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