From 123bd96d533190a207c9fcea84ae6328732a16cc Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:20:22 +0000 Subject: [PATCH] powerpc/mpc8xxx: use topology registers to calculate number of cores We have actual topology infomation to find out exactly which core is present. Calculate the number of cores if not specified. Signed-off-by: Kumar Gala Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/cpu.c | 65 ++++++++++++++++++++++++---- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/lib/board.c | 13 ++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c index 6cc5c4bcbb..78a8f926b3 100644 --- a/arch/powerpc/cpu/mpc8xxx/cpu.c +++ b/arch/powerpc/cpu/mpc8xxx/cpu.c @@ -82,7 +82,39 @@ struct cpu_type cpu_type_list [] = { #endif }; -struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 1); +#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 +u32 compute_ppc_cpumask(void) +{ + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, mask = 0; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i++].lower); + for (j = 0; j < 4; j++) { + u32 idx = (cluster >> (j*8)) & TP_CLUSTER_INIT_MASK; + u32 type = in_be32(&gur->tp_ityp[idx]); + + if (type & TP_ITYP_AV) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_PPC) + mask |= 1 << count; + } + count++; + } + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return mask; +} +#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ +/* + * Before chassis genenration 2, the cpumask should be hard-coded. + * In case of cpu type unknown or cpumask unset, use 1 as fail save. + */ +#define compute_ppc_cpumask() 1 +#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ + +struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 0); struct cpu_type *identify_cpu(u32 ver) { @@ -110,6 +142,9 @@ u32 cpu_mask() return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + if (cpu->num_cores == 0) + return compute_ppc_cpumask(); + return cpu->mask; } @@ -117,13 +152,14 @@ u32 cpu_mask() * Return the number of cores on this SOC. */ int cpu_numcores() { - ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR; struct cpu_type *cpu = gd->cpu; - /* better to query feature reporting register than just assume 1 */ - if (cpu == &cpu_type_unknown) - return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> - MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + /* + * Report # of cores in terms of the cpu_mask if we haven't + * figured out how many there are yet + */ + if (cpu->num_cores == 0) + return hweight32(cpu_mask()); return cpu->num_cores; } @@ -135,9 +171,7 @@ int cpu_numcores() { */ int is_core_valid(unsigned int core) { - struct cpu_type *cpu = gd->cpu; - - return !!((1 << core) & cpu->mask); + return !!((1 << core) & cpu_mask()); } int probecpu (void) @@ -153,6 +187,19 @@ int probecpu (void) return 0; } +/* Once in memory, compute mask & # cores once and save them off */ +int fixup_cpu(void) +{ + struct cpu_type *cpu = gd->cpu; + + if (cpu->num_cores == 0) { + cpu->mask = cpu_mask(); + cpu->num_cores = cpu_numcores(); + } + + return 0; +} + /* * Initializes on-chip ethernet controllers. * to override, implement board_eth_init() diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index a8ffedbc86..3247c805e5 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -1157,6 +1157,7 @@ struct cpu_type { }; struct cpu_type *identify_cpu(u32 ver); +int fixup_cpu(void); #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) #define CPU_TYPE_ENTRY(n, v, nc) \ diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c index 435ef10a2e..07feaf55fc 100644 --- a/arch/powerpc/lib/board.c +++ b/arch/powerpc/lib/board.c @@ -345,6 +345,13 @@ ulong get_effective_memsize(void) #endif } +int __fixup_cpu(void) +{ + return 0; +} + +int fixup_cpu(void) __attribute__((weak, alias("__fixup_cpu"))); + /* * This is the first part of the initialization sequence that is * implemented in C, but still running from ROM. @@ -646,6 +653,12 @@ void board_init_r(gd_t *id, ulong dest_addr) * We need to update it to point to the same CPU entry in RAM. */ gd->cpu += dest_addr - CONFIG_SYS_MONITOR_BASE; + + /* + * If we didn't know the cpu mask & # cores, we can save them of + * now rather than 'computing' them constantly + */ + fixup_cpu(); #endif #ifdef CONFIG_SYS_EXTRA_ENV_RELOC -- 2.34.1