]> git.sur5r.net Git - u-boot/blobdiff - arch/powerpc/cpu/mpc85xx/mp.c
mpc83xx: Cleanup usage of DDR constants
[u-boot] / arch / powerpc / cpu / mpc85xx / mp.c
index e05257cf04abd8bba157db911c950df2568e7a20..ffc2a9ad65d6efc7d8b72d7a2520cd885dfbbd5d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -36,9 +36,30 @@ u32 get_my_id()
        return mfspr(SPRN_PIR);
 }
 
+/*
+ * Determine if U-Boot should keep secondary cores in reset, or let them out
+ * of reset and hold them in a spinloop
+ */
+int hold_cores_in_reset(int verbose)
+{
+       const char *s = getenv("mp_holdoff");
+
+       /* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */
+       if (s && (*s == 'y' || *s == 'Y' || *s == '1')) {
+               if (verbose) {
+                       puts("Secondary cores are being held in reset.\n");
+                       puts("See 'mp_holdoff' environment variable\n");
+               }
+
+               return 1;
+       }
+
+       return 0;
+}
+
 int cpu_reset(int nr)
 {
-       volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+       volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
        out_be32(&pic->pir, 1 << nr);
        /* the dummy read works around an errata on early 85xx MP PICs */
        (void)in_be32(&pic->pir);
@@ -51,6 +72,9 @@ int cpu_status(int nr)
 {
        u32 *table, id = get_my_id();
 
+       if (hold_cores_in_reset(1))
+               return 0;
+
        if (nr == id) {
                table = (u32 *)get_spin_virt_addr();
                printf("table base @ 0x%p\n", table);
@@ -133,6 +157,9 @@ int cpu_release(int nr, int argc, char * const argv[])
        u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
        u64 boot_addr;
 
+       if (hold_cores_in_reset(1))
+               return 0;
+
        if (nr == get_my_id()) {
                printf("Invalid to release the boot core.\n\n");
                return 1;
@@ -194,22 +221,20 @@ ulong get_spin_virt_addr(void)
 #ifdef CONFIG_FSL_CORENET
 static void plat_mp_up(unsigned long bootpg)
 {
-       u32 up, cpu_up_mask, whoami;
+       u32 cpu_up_mask, whoami;
        u32 *table = (u32 *)get_spin_virt_addr();
        volatile ccsr_gur_t *gur;
        volatile ccsr_local_t *ccm;
        volatile ccsr_rcpm_t *rcpm;
        volatile ccsr_pic_t *pic;
        int timeout = 10;
-       u32 nr_cpus;
+       u32 mask = cpu_mask();
        struct law_entry e;
 
        gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
        ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
        rcpm = (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
-       pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
-
-       nr_cpus = ((in_be32(&pic->frr) >> 8) & 0xff) + 1;
+       pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
 
        whoami = in_be32(&pic->whoami);
        cpu_up_mask = 1 << whoami;
@@ -224,19 +249,18 @@ static void plat_mp_up(unsigned long bootpg)
        /* disable time base at the platform */
        out_be32(&rcpm->ctbenrl, cpu_up_mask);
 
-       /* release the hounds */
-       up = ((1 << nr_cpus) - 1);
-       out_be32(&gur->brrl, up);
+       out_be32(&gur->brrl, mask);
 
        /* wait for everyone */
        while (timeout) {
-               int i;
-               for (i = 0; i < nr_cpus; i++) {
-                       if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
-                               cpu_up_mask |= (1 << i);
-               };
+               unsigned int i, cpu, nr_cpus = cpu_numcores();
 
-               if ((cpu_up_mask & up) == up)
+               for_each_cpu(i, cpu, nr_cpus, mask) {
+                       if (table[cpu * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+                               cpu_up_mask |= (1 << cpu);
+               }
+
+               if ((cpu_up_mask & mask) == mask)
                        break;
 
                udelay(100);
@@ -245,13 +269,18 @@ static void plat_mp_up(unsigned long bootpg)
 
        if (timeout == 0)
                printf("CPU up timeout. CPU up mask is %x should be %x\n",
-                       cpu_up_mask, up);
+                       cpu_up_mask, mask);
 
        /* enable time base at the platform */
        out_be32(&rcpm->ctbenrl, 0);
+
+       /* readback to sync write */
+       in_be32(&rcpm->ctbenrl);
+
        mtspr(SPRN_TBWU, 0);
        mtspr(SPRN_TBWL, 0);
-       out_be32(&rcpm->ctbenrl, (1 << nr_cpus) - 1);
+
+       out_be32(&rcpm->ctbenrl, mask);
 
 #ifdef CONFIG_MPC8xxx_DISABLE_BPTR
        /*
@@ -261,7 +290,7 @@ static void plat_mp_up(unsigned long bootpg)
         * unusable for normal operation but it does allow OSes to easily
         * reset a processor core to put it back into U-Boot's spinloop.
         */
-       clrbits_be32(&ecm->bptr, 0x80000000);
+       clrbits_be32(&ccm->bstrar, LAW_EN);
 #endif
 }
 #else
@@ -272,7 +301,7 @@ static void plat_mp_up(unsigned long bootpg)
        volatile u32 bpcr;
        volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
        volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
-       volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+       volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
        u32 devdisr;
        int timeout = 10;
 
@@ -320,6 +349,10 @@ static void plat_mp_up(unsigned long bootpg)
        else
                devdisr |= MPC85xx_DEVDISR_TB0;
        out_be32(&gur->devdisr, devdisr);
+
+       /* readback to sync write */
+       in_be32(&gur->devdisr);
+
        mtspr(SPRN_TBWU, 0);
        mtspr(SPRN_TBWL, 0);
 
@@ -353,6 +386,10 @@ void setup_mp(void)
        ulong fixup = (ulong)&__secondary_start_page;
        u32 bootpg = determine_mp_bootpg();
 
+       /* Some OSes expect secondary cores to be held in reset */
+       if (hold_cores_in_reset(0))
+               return;
+
        /* Store the bootpg's SDRAM address for use by secondary CPU cores */
        __bootpg_addr = bootpg;