diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 299 | ||||
-rw-r--r-- | arch/mips/kernel/perf_event_mipsxx.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/prom.c | 29 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 76 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 1 |
6 files changed, 233 insertions, 181 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f4630e1082a..1b51046191e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -190,6 +190,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: case CPU_JZRISC: + case CPU_LOONGSON1: case CPU_XLR: case CPU_XLP: cpu_wait = r4k_wait; @@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) #endif } +static char unknown_isa[] __cpuinitdata = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + +static inline unsigned int decode_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + int isa; + + config0 = read_c0_config(); + + if (((config0 & MIPS_CONF_MT) >> 7) == 1) + c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; + switch (isa) { + case 0: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } + break; + case 2: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } + break; + default: + goto unknown; + } + + return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); +} + +static inline unsigned int decode_config1(struct cpuinfo_mips *c) +{ + unsigned int config1; + + config1 = read_c0_config1(); + + if (config1 & MIPS_CONF1_MD) + c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_WR) + c->options |= MIPS_CPU_WATCH; + if (config1 & MIPS_CONF1_CA) + c->ases |= MIPS_ASE_MIPS16; + if (config1 & MIPS_CONF1_EP) + c->options |= MIPS_CPU_EJTAG; + if (config1 & MIPS_CONF1_FP) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + if (cpu_has_tlb) + c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; + + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + config2 = read_c0_config2(); + + if (config2 & MIPS_CONF2_SL) + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_config3(struct cpuinfo_mips *c) +{ + unsigned int config3; + + config3 = read_c0_config3(); + + if (config3 & MIPS_CONF3_SM) + c->ases |= MIPS_ASE_SMARTMIPS; + if (config3 & MIPS_CONF3_DSP) + c->ases |= MIPS_ASE_DSP; + if (config3 & MIPS_CONF3_VINT) + c->options |= MIPS_CPU_VINT; + if (config3 & MIPS_CONF3_VEIC) + c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_MT) + c->ases |= MIPS_ASE_MIPSMT; + if (config3 & MIPS_CONF3_ULRI) + c->options |= MIPS_CPU_ULRI; + + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + config4 = read_c0_config4(); + + if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT + && cpu_has_tlb) + c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + + c->kscratch_mask = (config4 >> 16) & 0xff; + + return config4 & MIPS_CONF_M; +} + +static void __cpuinit decode_configs(struct cpuinfo_mips *c) +{ + int ok; + + /* MIPS32 or MIPS64 compliant CPU. */ + c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + ok = decode_config0(c); /* Read Config registers. */ + BUG_ON(!ok); /* Arch spec violation! */ + if (ok) + ok = decode_config1(c); + if (ok) + ok = decode_config2(c); + if (ok) + ok = decode_config3(c); + if (ok) + ok = decode_config4(c); + + mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) MIPS_CPU_32FPR; c->tlbsize = 64; break; - } -} - -static char unknown_isa[] __cpuinitdata = KERN_ERR \ - "Unsupported ISA type, c0.config0: %d."; + case PRID_IMP_LOONGSON1: + decode_configs(c); -static inline unsigned int decode_config0(struct cpuinfo_mips *c) -{ - unsigned int config0; - int isa; + c->cputype = CPU_LOONGSON1; - config0 = read_c0_config(); - - if (((config0 & MIPS_CONF_MT) >> 7) == 1) - c->options |= MIPS_CPU_TLB; - isa = (config0 & MIPS_CONF_AT) >> 13; - switch (isa) { - case 0: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M32R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M32R2; + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON1B: + __cpu_name[cpu] = "Loongson 1B"; break; - default: - goto unknown; } - break; - case 2: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M64R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M64R2; - break; - default: - goto unknown; - } - break; - default: - goto unknown; - } - - return config0 & MIPS_CONF_M; - -unknown: - panic(unknown_isa, config0); -} -static inline unsigned int decode_config1(struct cpuinfo_mips *c) -{ - unsigned int config1; - - config1 = read_c0_config1(); - - if (config1 & MIPS_CONF1_MD) - c->ases |= MIPS_ASE_MDMX; - if (config1 & MIPS_CONF1_WR) - c->options |= MIPS_CPU_WATCH; - if (config1 & MIPS_CONF1_CA) - c->ases |= MIPS_ASE_MIPS16; - if (config1 & MIPS_CONF1_EP) - c->options |= MIPS_CPU_EJTAG; - if (config1 & MIPS_CONF1_FP) { - c->options |= MIPS_CPU_FPU; - c->options |= MIPS_CPU_32FPR; + break; } - if (cpu_has_tlb) - c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; - - return config1 & MIPS_CONF_M; -} - -static inline unsigned int decode_config2(struct cpuinfo_mips *c) -{ - unsigned int config2; - - config2 = read_c0_config2(); - - if (config2 & MIPS_CONF2_SL) - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; - - return config2 & MIPS_CONF_M; -} - -static inline unsigned int decode_config3(struct cpuinfo_mips *c) -{ - unsigned int config3; - - config3 = read_c0_config3(); - - if (config3 & MIPS_CONF3_SM) - c->ases |= MIPS_ASE_SMARTMIPS; - if (config3 & MIPS_CONF3_DSP) - c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_VINT) - c->options |= MIPS_CPU_VINT; - if (config3 & MIPS_CONF3_VEIC) - c->options |= MIPS_CPU_VEIC; - if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; - if (config3 & MIPS_CONF3_ULRI) - c->options |= MIPS_CPU_ULRI; - - return config3 & MIPS_CONF_M; -} - -static inline unsigned int decode_config4(struct cpuinfo_mips *c) -{ - unsigned int config4; - - config4 = read_c0_config4(); - - if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT - && cpu_has_tlb) - c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; - - c->kscratch_mask = (config4 >> 16) & 0xff; - - return config4 & MIPS_CONF_M; -} - -static void __cpuinit decode_configs(struct cpuinfo_mips *c) -{ - int ok; - - /* MIPS32 or MIPS64 compliant CPU. */ - c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; - - c->scache.flags = MIPS_CACHE_NOT_PRESENT; - - ok = decode_config0(c); /* Read Config registers. */ - BUG_ON(!ok); /* Arch spec violation! */ - if (ok) - ok = decode_config1(c); - if (ok) - ok = decode_config2(c); - if (ok) - ok = decode_config3(c); - if (ok) - ok = decode_config4(c); - - mips_probe_watch_registers(c); - - if (cpu_has_mips_r2) - c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index eb5e394a465..2f28d3b5568 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1559,6 +1559,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.cache_event_map = &mipsxxcore_cache_map; break; + case CPU_LOONGSON1: + mipspmu.name = "mips/loongson1"; + mipspmu.general_event_map = &mipsxxcore_event_map; + mipspmu.cache_event_map = &mipsxxcore_cache_map; + break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index f11b2bbb826..028f6f837ef 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -35,16 +35,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) return add_memory_region(base, size, BOOT_MEM_RAM); } -int __init reserve_mem_mach(unsigned long addr, unsigned long size) -{ - return reserve_bootmem(addr, size, BOOTMEM_DEFAULT); -} - -void __init free_mem_mach(unsigned long addr, unsigned long size) -{ - return free_bootmem(addr, size); -} - void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); @@ -77,25 +67,6 @@ void __init early_init_devtree(void *params) of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); } -void __init device_tree_init(void) -{ - unsigned long base, size; - - if (!initial_boot_params) - return; - - base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); - - /* Before we do anything, lets reserve the dt blob */ - reserve_mem_mach(base, size); - - unflatten_device_tree(); - - /* free the space reserved for the dt blob */ - free_mem_mach(base, size); -} - void __init __dt_setup_arch(struct boot_param_header *bph) { if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1268392f1d2..31637d8c873 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void) #ifdef CONFIG_MIPS_MT_SMTC /* Only do cpu_probe for first TC of CPU */ - if ((read_c0_tcbind() & TCBIND_CURTC) == 0) + if ((read_c0_tcbind() & TCBIND_CURTC) != 0) + __cpu_name[smp_processor_id()] = __cpu_name[0]; + else #endif /* CONFIG_MIPS_MT_SMTC */ cpu_probe(); cpu_report(); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 15b5f3cfd20..1d47843d3cc 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS]; static struct smtc_ipi_q freeIPIq; +/* + * Number of FPU contexts for each VPE + */ + +static int smtc_nconf1[MAX_SMTC_VPES]; + + /* Forward declarations */ void ipi_decode(struct smtc_ipi *); @@ -174,9 +181,9 @@ static int __init tintq(char *str) __setup("tintq=", tintq); -static int imstuckcount[2][8]; +static int imstuckcount[MAX_SMTC_VPES][8]; /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ -static int vpemask[2][8] = { +static int vpemask[MAX_SMTC_VPES][8] = { {0, 0, 1, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 1} }; @@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot) static void smtc_tc_setup(int vpe, int tc, int cpu) { + static int cp1contexts[MAX_SMTC_VPES]; + + /* + * Make a local copy of the available FPU contexts in order + * to keep track of TCs that can have one. + */ + if (tc == 1) + { + /* + * FIXME: Multi-core SMTC hasn't been tested and the + * maximum number of VPEs may change. + */ + cp1contexts[0] = smtc_nconf1[0] - 1; + cp1contexts[1] = smtc_nconf1[1]; + } + settc(tc); write_tc_c0_tchalt(TCHALT_H); mips_ihb(); @@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) * an active IPI queue. */ write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); - /* Bind tc to vpe */ + + /* Bind TC to VPE. */ write_tc_c0_tcbind(vpe); + /* In general, all TCs should have the same cpu_data indications. */ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); - /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */ - if (cpu_data[0].cputype == CPU_34K || - cpu_data[0].cputype == CPU_1004K) + + /* Check to see if there is a FPU context available for this TC. */ + if (!cp1contexts[vpe]) cpu_data[cpu].options &= ~MIPS_CPU_FPU; + else + cp1contexts[vpe]--; + + /* Store the TC and VPE into the cpu_data structure. */ cpu_data[cpu].vpe_id = vpe; cpu_data[cpu].tc_id = tc; - /* Multi-core SMTC hasn't been tested, but be prepared */ + + /* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */ cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; } /* - * Tweak to get Count registes in as close a sync as possible. The + * Tweak to get Count registers synced as closely as possible. The * value seems good for 34K-class cores. */ @@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus) smtc_configure_tlb(); for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { + /* Get number of CP1 contexts for each VPE. */ + if (tc == 0) + { + /* + * Do not call settc() for TC0 or the FPU context + * value will be incorrect. Besides, we know that + * we are TC0 anyway. + */ + smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + if (nvpe == 2) + { + settc(1); + smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + settc(0); + } + } if (tcpervpe[vpe] == 0) continue; if (vpe != 0) @@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus) */ if (tc != 0) { smtc_tc_setup(vpe, tc, cpu); + if (vpe != 0) { + /* + * Set MVP bit (possibly again). Do it + * here to catch CPUs that have no TCs + * bound to the VPE at reset. In that + * case, a TC must be bound to the VPE + * before we can set VPEControl[MVP] + */ + write_vpe_c0_vpeconf0( + read_vpe_c0_vpeconf0() | + VPECONF0_MVP); + } cpu++; } printk(" %d", tc); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c3c29354370..9be3df1fa8a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void) case CPU_5KC: case CPU_5KE: + case CPU_LOONGSON1: write_c0_ecc(0x80000000); back_to_back_c0_hazard(); /* Set the PE bit (bit 31) in the c0_errctl register. */ |