2 * Copyright 2004 Freescale Semiconductor
3 * Jeff Brown (jeffrey@freescale.com)
4 * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
6 * See file CREDITS for list of people who contributed to this
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.
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.
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,
28 #include <asm/cache.h>
31 #if defined(CONFIG_OF_FLAT_TREE)
36 // SS: For debug only, remove after use
38 static __inline__ unsigned long get_dbat3u (void)
41 asm volatile("mfspr %0, 542" : "=r" (dbat3u) :);
45 static __inline__ unsigned long get_dbat3l (void)
48 asm volatile("mfspr %0, 543" : "=r" (dbat3l) :);
52 static __inline__ unsigned long get_msr (void)
55 asm volatile("mfmsr %0" : "=r" (msr) :);
59 extern unsigned long get_board_sys_clk(ulong dummy);
67 uint lcrr; /* local bus clock ratio register */
68 uint clkdiv; /* clock divider portion of lcrr */
70 puts("Freescale PowerPC\n");
82 case PVR_VER(PVR_86xx):
89 printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
108 printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
110 get_sys_info(&sysinfo);
113 printf("CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
114 printf("MPX:%4lu MHz, ", sysinfo.freqSystemBus / 1000000);
115 printf("DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
117 #if defined(CFG_LBC_LCRR)
121 volatile immap_t *immap = (immap_t *)CFG_IMMR;
122 volatile ccsr_lbc_t *lbc= &immap->im_lbc;
127 clkdiv = lcrr & 0x0f;
128 if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
129 printf("LBC:%4lu MHz\n",
130 sysinfo.freqSystemBus / 1000000 / clkdiv);
132 printf(" LBC: unknown (lcrr: 0x%08x)\n", lcrr);
136 if (get_l2cr() & 0x80000000)
139 printf("Disabled\n");
145 /* -------------------------------------------------------------------- */
148 soft_restart(unsigned long addr)
151 #ifndef CONFIG_MPC8641HPCN
153 /* SRR0 has system reset vector, SRR1 has default MSR value */
154 /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
156 __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr));
157 __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4");
158 __asm__ __volatile__ ("mtspr 27, 4");
159 __asm__ __volatile__ ("rfi");
161 #else /* CONFIG_MPC8641HPCN */
162 out8(PIXIS_BASE+PIXIS_RST,0);
163 #endif /* !CONFIG_MPC8641HPCN */
164 while(1); /* not reached */
169 #ifdef CONFIG_MPC8641HPCN
171 int set_px_sysclk(ulong sysclk)
173 u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux,tmp;
175 /* Per table 27, page 58 of MPC8641HPCN spec*/
227 printf("Unsupported SYSCLK frequency.\n");
231 vclkh = (sysclk_s << 5) | sysclk_r ;
233 out8(PIXIS_BASE+PIXIS_VCLKH,vclkh);
234 out8(PIXIS_BASE+PIXIS_VCLKL,vclkl);
236 out8(PIXIS_BASE+PIXIS_AUX,sysclk_aux);
241 int set_px_mpxpll(ulong mpxpll)
258 printf("Unsupported MPXPLL ratio.\n");
262 tmp = in8(PIXIS_BASE+PIXIS_VSPEED1);
263 tmp = (tmp & 0xF0) | (val & 0x0F);
264 out8(PIXIS_BASE+PIXIS_VSPEED1,tmp);
269 int set_px_corepll(ulong corepll)
295 printf("Unsupported COREPLL ratio.\n");
299 tmp = in8(PIXIS_BASE+PIXIS_VSPEED0);
300 tmp = (tmp & 0xE0) | (val & 0x1F);
301 out8(PIXIS_BASE+PIXIS_VSPEED0,tmp);
306 void read_from_px_regs(int set)
309 tmp = in8(PIXIS_BASE+PIXIS_VCFGEN0);
314 out8(PIXIS_BASE+PIXIS_VCFGEN0,tmp);
317 void read_from_px_regs_altbank(int set)
320 tmp = in8(PIXIS_BASE+PIXIS_VCFGEN1);
325 out8(PIXIS_BASE+PIXIS_VCFGEN1,tmp);
328 void set_altbank(void)
331 tmp = in8(PIXIS_BASE+PIXIS_VBOOT);
333 out8(PIXIS_BASE+PIXIS_VBOOT,tmp);
340 tmp = in8(PIXIS_BASE+PIXIS_VCTL);
342 out8(PIXIS_BASE+PIXIS_VCTL,tmp);
343 tmp = in8(PIXIS_BASE+PIXIS_VCTL);
345 out8(PIXIS_BASE+PIXIS_VCTL,tmp);
348 void set_px_go_with_watchdog(void)
351 tmp = in8(PIXIS_BASE+PIXIS_VCTL);
353 out8(PIXIS_BASE+PIXIS_VCTL,tmp);
354 tmp = in8(PIXIS_BASE+PIXIS_VCTL);
356 out8(PIXIS_BASE+PIXIS_VCTL,tmp);
359 /* This function takes the non-integral cpu:mpx pll ratio
360 * and converts it to an integer that can be used to assign
361 * FPGA register values.
362 * input: strptr i.e. argv[2]
365 ulong strfractoint(uchar *strptr)
367 int i,j,retval,intarr_len=0, decarr_len=0, mulconst, no_dec=0;
368 ulong intval =0, decval=0;
369 uchar intarr[3], decarr[3];
371 /* Assign the integer part to intarr[]
372 * If there is no decimal point i.e.
373 * if the ratio is an integral value
374 * simply create the intarr.
377 while(strptr[i] != 46)
382 break; /* Break from loop once the end of string is reached */
385 intarr[i] = strptr[i];
389 intarr_len = i; /* Assign length of integer part to intarr_len*/
390 intarr[i] = '\0'; /* */
394 mulconst=10; /* Currently needed only for single digit corepll ratios */
400 i++; /* Skipping the decimal point */
401 while ((strptr[i] > 47) && (strptr[i] < 58))
403 decarr[j] = strptr[i];
412 for(i=0; i<decarr_len;i++)
413 mulconst = mulconst*10;
414 decval = simple_strtoul(decarr,NULL,10);
417 intval = simple_strtoul(intarr,NULL,10);
418 intval = intval*mulconst;
420 retval = intval+decval;
427 #endif //CONFIG_MPC8641HPCN
430 /* no generic way to do board reset. simply call soft_reset. */
432 do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
440 #ifdef CFG_RESET_ADDRESS
441 addr = CFG_RESET_ADDRESS;
444 * note: when CFG_MONITOR_BASE points to a RAM address,
445 * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
446 * address. Better pick an address known to be invalid on your
447 * system and assign it to CFG_RESET_ADDRESS.
449 addr = CFG_MONITOR_BASE - sizeof (ulong);
452 #ifndef CONFIG_MPC8641HPCN
454 /* flush and disable I/D cache */
455 __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3");
456 __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5");
457 __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4");
458 __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5");
459 __asm__ __volatile__ ("sync");
460 __asm__ __volatile__ ("mtspr 1008, 4");
461 __asm__ __volatile__ ("isync");
462 __asm__ __volatile__ ("sync");
463 __asm__ __volatile__ ("mtspr 1008, 5");
464 __asm__ __volatile__ ("isync");
465 __asm__ __volatile__ ("sync");
469 #else /* CONFIG_MPC8641HPCN */
476 case 'f': /* reset with frequency changed */
481 read_from_px_regs(0);
483 val = set_px_sysclk(simple_strtoul(argv[2],NULL,10));
485 corepll = strfractoint(argv[3]);
486 val = val + set_px_corepll(corepll);
487 val = val + set_px_mpxpll(simple_strtoul(argv[4],NULL,10));
490 printf("Setting registers VCFGEN0 and VCTL\n");
491 read_from_px_regs(1);
492 printf("Resetting board with values from VSPEED0, VSPEED1, VCLKH, and VCLKL ....\n");
498 while(1); /* Not reached */
501 if(argv[2][1] == 'f')
503 read_from_px_regs(0);
504 read_from_px_regs_altbank(0);
505 /* reset with frequency changed */
506 val = set_px_sysclk(simple_strtoul(argv[3],NULL,10));
508 corepll = strfractoint(argv[4]);
509 val = val + set_px_corepll(corepll);
510 val = val + set_px_mpxpll(simple_strtoul(argv[5],NULL,10));
513 printf("Setting registers VCFGEN0, VCFGEN1, VBOOT, and VCTL\n");
515 read_from_px_regs(1);
516 read_from_px_regs_altbank(1);
517 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");
518 set_px_go_with_watchdog();
524 while(1); /* Not reached */
526 else /* Reset from next bank without changing frequencies */
528 read_from_px_regs(0);
529 read_from_px_regs_altbank(0);
532 printf("Setting registers VCFGEN1, VBOOT, and VCTL\n");
534 read_from_px_regs_altbank(1);
535 printf("Enabling watchdog timer on the FPGA and resetting board to boot from the other bank....\n");
536 set_px_go_with_watchdog();
537 while(1); /* Not reached */
544 printf("\nUsage: reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n");
545 printf(" reset altbank [cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>]\n");
546 printf("For example: reset cf 40 2.5 10\n");
547 printf("See MPC8641HPCN Design Workbook for valid values of command line parameters.\n");
551 out8(PIXIS_BASE+PIXIS_RST,0);
553 #endif /* !CONFIG_MPC8641HPCN */
555 while(1); /* not reached */
559 /* ------------------------------------------------------------------------- */
562 * Get timebase clock frequency
564 unsigned long get_tbclk(void)
568 get_sys_info(&sys_info);
569 return ((sys_info.freqSystemBus + 3L) / 4L);
573 /* ------------------------------------------------------------------------- */
575 #if defined(CONFIG_WATCHDOG)
581 #endif /* CONFIG_WATCHDOG */
583 /* ------------------------------------------------------------------------- */
585 #if defined(CONFIG_DDR_ECC)
586 void dma_init(void) {
587 volatile immap_t *immap = (immap_t *)CFG_IMMR;
588 volatile ccsr_dma_t *dma = &immap->im_dma;
590 dma->satr0 = 0x00040000;
591 dma->datr0 = 0x00040000;
596 uint dma_check(void) {
597 volatile immap_t *immap = (immap_t *)CFG_IMMR;
598 volatile ccsr_dma_t *dma = &immap->im_dma;
599 volatile uint status = dma->sr0;
601 /* While the channel is busy, spin */
602 while((status & 4) == 4) {
607 printf ("DMA Error: status = %x\n", status);
612 int dma_xfer(void *dest, uint count, void *src) {
613 volatile immap_t *immap = (immap_t *)CFG_IMMR;
614 volatile ccsr_dma_t *dma = &immap->im_dma;
616 dma->dar0 = (uint) dest;
617 dma->sar0 = (uint) src;
619 dma->mr0 = 0xf000004;
621 dma->mr0 = 0xf000005;
625 #endif /* CONFIG_DDR_ECC */
628 #ifdef CONFIG_OF_FLAT_TREE
629 void ft_cpu_setup(void *blob, bd_t *bd)
635 clock = bd->bi_busfreq;
636 p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
638 *p = cpu_to_be32(clock);
640 p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
642 *p = cpu_to_be32(clock);
644 p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
646 *p = cpu_to_be32(clock);
648 #if defined(CONFIG_MPC86XX_TSEC1)
649 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/address", &len);
650 memcpy(p, bd->bi_enetaddr, 6);
653 #if defined(CONFIG_MPC86XX_TSEC2)
654 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/address", &len);
655 memcpy(p, bd->bi_enet1addr, 6);
658 #if defined(CONFIG_MPC86XX_TSEC3)
659 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/address", &len);
660 memcpy(p, bd->bi_enet2addr, 6);
663 #if defined(CONFIG_MPC86XX_TSEC4)
664 p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/address", &len);
665 memcpy(p, bd->bi_enet3addr, 6);