Merge with git://www.denx.de/git/u-boot.git
[platform/kernel/u-boot.git] / cpu / mpc85xx / cpu.c
index 64f2782..08e0468 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2004,2007 Freescale Semiconductor, Inc.
  * (C) Copyright 2002, 2003 Motorola Inc.
  * Xianghua Xiao (X.Xiao@motorola.com)
  *
 #include <command.h>
 #include <asm/cache.h>
 
-/* ------------------------------------------------------------------------- */
+#if defined(CONFIG_OF_FLAT_TREE)
+#include <ft_build.h>
+#endif
+
 
 int checkcpu (void)
 {
-       uint pir = get_pir();
-       uint pvr = get_pvr();
+       sys_info_t sysinfo;
+       uint lcrr;              /* local bus clock ratio register */
+       uint clkdiv;            /* clock divider portion of lcrr */
+       uint pvr, svr;
+       uint fam;
+       uint ver;
+       uint major, minor;
 
-       printf("Motorola PowerPC ProcessorID=%08x Rev. ",pir);
-       switch(pvr) {
+       svr = get_svr();
+       ver = SVR_VER(svr);
+       major = SVR_MAJ(svr);
+       minor = SVR_MIN(svr);
+
+       puts("CPU:   ");
+       switch (ver) {
+       case SVR_8540:
+               puts("8540");
+               break;
+       case SVR_8541:
+               puts("8541");
+               break;
+       case SVR_8555:
+               puts("8555");
+               break;
+       case SVR_8560:
+               puts("8560");
+               break;
+       case SVR_8548:
+               puts("8548");
+               break;
+       case SVR_8548_E:
+               puts("8548_E");
+               break;
+       case SVR_8544:
+               puts("8544");
+               break;
+       case SVR_8544_E:
+               puts("8544_E");
+               break;
+       case SVR_8568_E:
+               puts("8568_E");
+               break;
        default:
-               printf("PVR=%08x", pvr);
+               puts("Unknown");
                break;
        }
+       printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+       pvr = get_pvr();
+       fam = PVR_FAM(pvr);
+       ver = PVR_VER(pvr);
+       major = PVR_MAJ(pvr);
+       minor = PVR_MIN(pvr);
+
+       printf("Core:  ");
+       switch (fam) {
+       case PVR_FAM(PVR_85xx):
+           puts("E500");
+           break;
+       default:
+           puts("Unknown");
+           break;
+       }
+       printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
 
-       printf("\n");
+       get_sys_info(&sysinfo);
+
+       puts("Clock Configuration:\n");
+       printf("       CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
+       printf("CCB:%4lu MHz,\n", sysinfo.freqSystemBus / 1000000);
+       printf("       DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
+
+#if defined(CFG_LBC_LCRR)
+       lcrr = CFG_LBC_LCRR;
+#else
+       {
+           volatile immap_t *immap = (immap_t *)CFG_IMMR;
+           volatile ccsr_lbc_t *lbc= &immap->im_lbc;
+
+           lcrr = lbc->lcrr;
+       }
+#endif
+       clkdiv = lcrr & 0x0f;
+       if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
+#if defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544)
+               /*
+                * Yes, the entire PQ38 family use the same
+                * bit-representation for twice the clock divider values.
+                */
+                clkdiv *= 2;
+#endif
+               printf("LBC:%4lu MHz\n",
+                      sysinfo.freqSystemBus / 1000000 / clkdiv);
+       } else {
+               printf("LBC: unknown (lcrr: 0x%08x)\n", lcrr);
+       }
+
+       if (ver == SVR_8560) {
+               printf("CPM:  %lu Mhz\n",
+                      sysinfo.freqSystemBus / 1000000);
+       }
+
+       puts("L1:    D-cache 32 kB enabled\n       I-cache 32 kB enabled\n");
 
        return 0;
 }
@@ -53,12 +149,25 @@ int checkcpu (void)
 
 int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 {
+       uint pvr;
+       uint ver;
+       pvr = get_pvr();
+       ver = PVR_VER(pvr);
+       if (ver & 1){
+       /* e500 v2 core has reset control register */
+               volatile unsigned int * rstcr;
+               rstcr = (volatile unsigned int *)(CFG_IMMR + 0xE00B0);
+               *rstcr = 0x2;           /* HRESET_REQ */
+       }else{
        /*
         * Initiate hard reset in debug control register DBCR0
         * Make sure MSR[DE] = 1
         */
-       __asm__ __volatile__("lis   3, 0x7000" ::: "r3");
-       mtspr(DBCR0,3);
+               unsigned long val;
+               val = mfspr(DBCR0);
+               val |= 0x70000000;
+               mtspr(DBCR0,val);
+       }
        return 1;
 }
 
@@ -72,7 +181,7 @@ unsigned long get_tbclk (void)
        sys_info_t  sys_info;
 
        get_sys_info(&sys_info);
-       return ((sys_info.freqSystemBus + 3L) / 4L);
+       return ((sys_info.freqSystemBus + 7L) / 8L);
 }
 
 
@@ -92,29 +201,20 @@ reset_85xx_watchdog(void)
         * Clear TSR(WIS) bit by writing 1
         */
        unsigned long val;
-       val = mfspr(tsr);
-       val |= 0x40000000;
-       mtspr(tsr, val);
+       val = mfspr(SPRN_TSR);
+       val |= TSR_WIS;
+       mtspr(SPRN_TSR, val);
 }
 #endif /* CONFIG_WATCHDOG */
 
 #if defined(CONFIG_DDR_ECC)
-__inline__ void dcbz(const void* addr)
-{
-       __asm__ __volatile__ ("dcbz 0,%0" :: "r" (addr));
-}
-
-__inline__ void dcbf(const void* addr)
-{
-       __asm__ __volatile__ ("dcbf 0,%0" :: "r" (addr));
-}
-
 void dma_init(void) {
        volatile immap_t *immap = (immap_t *)CFG_IMMR;
        volatile ccsr_dma_t *dma = &immap->im_dma;
 
        dma->satr0 = 0x02c40000;
        dma->datr0 = 0x02c40000;
+       dma->sr0 = 0xfffffff; /* clear any errors */
        asm("sync; isync; msync");
        return;
 }
@@ -129,6 +229,10 @@ uint dma_check(void) {
                status = dma->sr0;
        }
 
+       /* clear MR0[CS] channel start bit */
+       dma->mr0 &= 0x00000001;
+       asm("sync;isync;msync");
+
        if (status != 0) {
                printf ("DMA Error: status = %x\n", status);
        }
@@ -149,3 +253,94 @@ int dma_xfer(void *dest, uint count, void *src) {
        return dma_check();
 }
 #endif
+
+
+#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+       u32 *p;
+       ulong clock;
+       int len;
+
+       clock = bd->bi_busfreq;
+       p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
+       if (p != NULL)
+               *p = cpu_to_be32(clock);
+
+       p = ft_get_prop(blob, "/qe@e0080000/" OF_CPU "/bus-frequency", &len);
+       if (p != NULL)
+               *p = cpu_to_be32(clock);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
+       if (p != NULL)
+               *p = cpu_to_be32(clock);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
+       if (p != NULL)
+               *p = cpu_to_be32(clock);
+
+#if defined(CONFIG_HAS_ETH0)
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enetaddr, 6);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enetaddr, 6);
+#endif
+
+#if defined(CONFIG_HAS_ETH1)
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet1addr, 6);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet1addr, 6);
+#endif
+
+#if defined(CONFIG_HAS_ETH2)
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet2addr, 6);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet2addr, 6);
+
+#ifdef CONFIG_UEC_ETH
+       p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet2addr, 6);
+
+       p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet2addr, 6);
+
+#endif
+#endif
+
+#if defined(CONFIG_HAS_ETH3)
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet3addr, 6);
+
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet3addr, 6);
+
+#ifdef CONFIG_UEC_ETH
+       p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet3addr, 6);
+
+       p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len);
+       if (p)
+               memcpy(p, bd->bi_enet3addr, 6);
+
+#endif
+#endif
+
+}
+#endif