X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cpu%2Fmpc85xx%2Fmp.c;h=7626eb8e728459d14a19f02415303455be08aa75;hb=4b142febff71eabdb7ddbb125c7b583b24ddc434;hp=4e09c9c258bb5214f0a9399d02c420db869d889c;hpb=ce0eb70333331da6942167c41e6841c8c7994a33;p=platform%2Fkernel%2Fu-boot.git diff --git a/cpu/mpc85xx/mp.c b/cpu/mpc85xx/mp.c index 4e09c9c..7626eb8 100644 --- a/cpu/mpc85xx/mp.c +++ b/cpu/mpc85xx/mp.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Freescale Semiconductor. + * Copyright 2008-2009 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "mp.h" DECLARE_GLOBAL_DATA_PTR; @@ -36,8 +38,9 @@ u32 get_my_id() int cpu_reset(int nr) { - volatile ccsr_pic_t *pic = (void *)(CFG_MPC85xx_PIC_ADDR); + volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_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); out_be32(&pic->pir, 0x0); @@ -49,10 +52,10 @@ int cpu_status(int nr) u32 *table, id = get_my_id(); if (nr == id) { - table = (u32 *)get_spin_addr(); + table = (u32 *)get_spin_virt_addr(); printf("table base @ 0x%p\n", table); } else { - table = (u32 *)get_spin_addr() + nr * NUM_BOOT_ENTRY; + table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY; printf("Running on cpu %d\n", id); printf("\n"); printf("table @ 0x%p\n", table); @@ -74,7 +77,7 @@ static u8 boot_entry_map[4] = { int cpu_release(int nr, int argc, char *argv[]) { - u32 i, val, *table = (u32 *)get_spin_addr() + nr * NUM_BOOT_ENTRY; + u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY; u64 boot_addr; if (nr == get_my_id()) { @@ -87,11 +90,7 @@ int cpu_release(int nr, int argc, char *argv[]) return 1; } -#ifdef CFG_64BIT_STRTOUL boot_addr = simple_strtoull(argv[0], NULL, 16); -#else - boot_addr = simple_strtoul(argv[0], NULL, 16); -#endif /* handle pir, r3, r6 */ for (i = 1; i < 4; i++) { @@ -112,26 +111,112 @@ int cpu_release(int nr, int argc, char *argv[]) return 0; } -ulong get_spin_addr(void) +u32 determine_mp_bootpg(void) +{ + /* if we have 4G or more of memory, put the boot page at 4Gb-4k */ + if ((u64)gd->ram_size > 0xfffff000) + return (0xfffff000); + + return (gd->ram_size - 4096); +} + +ulong get_spin_phys_addr(void) { extern ulong __secondary_start_page; extern ulong __spin_table; - ulong addr = - (ulong)&__spin_table - (ulong)&__secondary_start_page; - addr += 0xfffff000; + return (determine_mp_bootpg() + + (ulong)&__spin_table - (ulong)&__secondary_start_page); +} - return addr; +ulong get_spin_virt_addr(void) +{ + extern ulong __secondary_start_page; + extern ulong __spin_table; + + return (CONFIG_BPTR_VIRT_ADDR + + (ulong)&__spin_table - (ulong)&__secondary_start_page); } -static void pq3_mp_up(unsigned long bootpg) +#ifdef CONFIG_FSL_CORENET +static void plat_mp_up(unsigned long bootpg) +{ + u32 up, 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; + 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; + + whoami = in_be32(&pic->whoami); + cpu_up_mask = 1 << whoami; + out_be32(&ccm->bstrl, bootpg); + + e = find_law(bootpg); + out_be32(&ccm->bstrar, LAW_EN | e.trgt_id << 20 | LAW_SIZE_4K); + + /* 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); + + /* 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); + }; + + if ((cpu_up_mask & up) == up) + break; + + udelay(100); + timeout--; + } + + if (timeout == 0) + printf("CPU up timeout. CPU up mask is %x should be %x\n", + cpu_up_mask, up); + + /* enable time base at the platform */ + out_be32(&rcpm->ctbenrl, 0); + mtspr(SPRN_TBWU, 0); + mtspr(SPRN_TBWL, 0); + out_be32(&rcpm->ctbenrl, (1 << nr_cpus) - 1); + +#ifdef CONFIG_MPC8xxx_DISABLE_BPTR + /* + * Disabling Boot Page Translation allows the memory region 0xfffff000 + * to 0xffffffff to be used normally. Leaving Boot Page Translation + * enabled remaps 0xfffff000 to SDRAM which makes that memory region + * 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); +#endif +} +#else +static void plat_mp_up(unsigned long bootpg) { u32 up, cpu_up_mask, whoami; - u32 *table = (u32 *)get_spin_addr(); + u32 *table = (u32 *)get_spin_virt_addr(); volatile u32 bpcr; - volatile ccsr_local_ecm_t *ecm = (void *)(CFG_MPC85xx_ECM_ADDR); - volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR); - volatile ccsr_pic_t *pic = (void *)(CFG_MPC85xx_PIC_ADDR); + 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); u32 devdisr; int timeout = 10; @@ -147,7 +232,7 @@ static void pq3_mp_up(unsigned long bootpg) out_be32(&gur->devdisr, devdisr); /* release the hounds */ - up = ((1 << CONFIG_NUM_CPUS) - 1); + up = ((1 << cpu_numcores()) - 1); bpcr = in_be32(&ecm->eebpcr); bpcr |= (up << 24); out_be32(&ecm->eebpcr, bpcr); @@ -157,7 +242,7 @@ static void pq3_mp_up(unsigned long bootpg) /* wait for everyone */ while (timeout) { int i; - for (i = 0; i < CONFIG_NUM_CPUS; i++) { + for (i = 0; i < cpu_numcores(); i++) { if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER]) cpu_up_mask |= (1 << i); }; @@ -184,17 +269,23 @@ static void pq3_mp_up(unsigned long bootpg) devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1); out_be32(&gur->devdisr, devdisr); + +#ifdef CONFIG_MPC8xxx_DISABLE_BPTR + /* + * Disabling Boot Page Translation allows the memory region 0xfffff000 + * to 0xffffffff to be used normally. Leaving Boot Page Translation + * enabled remaps 0xfffff000 to SDRAM which makes that memory region + * 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); +#endif } +#endif void cpu_mp_lmb_reserve(struct lmb *lmb) { - u32 bootpg; - - /* if we have 4G or more of memory, put the boot page at 4Gb-4k */ - if ((u64)gd->ram_size > 0xfffff000) - bootpg = 0xfffff000; - else - bootpg = gd->ram_size - 4096; + u32 bootpg = determine_mp_bootpg(); lmb_reserve(lmb, bootpg, 4096); } @@ -202,17 +293,30 @@ void cpu_mp_lmb_reserve(struct lmb *lmb) void setup_mp(void) { extern ulong __secondary_start_page; + extern ulong __bootpg_addr; ulong fixup = (ulong)&__secondary_start_page; - u32 bootpg; + u32 bootpg = determine_mp_bootpg(); - /* if we have 4G or more of memory, put the boot page at 4Gb-4k */ - if ((u64)gd->ram_size > 0xfffff000) - bootpg = 0xfffff000; - else - bootpg = gd->ram_size - 4096; + /* Store the bootpg's SDRAM address for use by secondary CPU cores */ + __bootpg_addr = bootpg; + + /* look for the tlb covering the reset page, there better be one */ + int i = find_tlb_idx((void *)CONFIG_BPTR_VIRT_ADDR, 1); - memcpy((void *)bootpg, (void *)fixup, 4096); - flush_cache(bootpg, 4096); + /* we found a match */ + if (i != -1) { + /* map reset page to bootpg so we can copy code there */ + disable_tlb(i); - pq3_mp_up(bootpg); + set_tlb(1, CONFIG_BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */ + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I, /* perms, wimge */ + 0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */ + + memcpy((void *)CONFIG_BPTR_VIRT_ADDR, (void *)fixup, 4096); + + plat_mp_up(bootpg); + } else { + puts("WARNING: No reset page TLB. " + "Skipping secondary core setup\n"); + } }