diff options
author | Paul Burton <paul.burton@imgtec.com> | 2016-02-03 03:15:33 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2016-05-13 14:01:50 +0200 |
commit | 5a3e7c02d84fd31e6a2b1b242612363b6131a09e (patch) | |
tree | a78fe880eb1b5dd0c3936df0924d8ceb108e395b /arch/mips/kernel/smp-cps.c | |
parent | 87a70bcdb41008decfcf7c217e26b0bcd7f52642 (diff) | |
download | lwn-5a3e7c02d84fd31e6a2b1b242612363b6131a09e.tar.gz lwn-5a3e7c02d84fd31e6a2b1b242612363b6131a09e.zip |
MIPS: smp-cps: Support MIPSr6 Virtual Processors
Introduce support for bringing up Virtual Processors in MIPSr6 systems
as CPUs, much like their VPE parallel from the now-deprecated MT ASE.
The existing mips_cps_boot_vpes function fits the MIPSr6 architecture
pretty well - it can now simply write the mask of running VPs to the
VC_RUN register, rather than looping through each & starting or stopping
as appropriate as is done for VPEs from the MT ASE. Thus the VP support
is in general an extension & simplification of the existing MT ASE VPE
(aka SMVP) support.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Matt Redfearn <matt.redfearn@imgtec.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Niklas Cassel <niklas.cassel@axis.com>
Cc: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/12339/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/smp-cps.c')
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 1a289db642cf..06512171fd19 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -35,7 +35,8 @@ static unsigned core_vpe_count(unsigned core) { unsigned cfg; - if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp)) return 1; mips_cm_lock_other(core, 0); @@ -47,11 +48,12 @@ static unsigned core_vpe_count(unsigned core) static void __init cps_smp_setup(void) { unsigned int ncores, nvpes, core_vpes; + unsigned long core_entry; int c, v; /* Detect & record VPE topology */ ncores = mips_cm_numcores(); - pr_info("VPE topology "); + pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE"); for (c = nvpes = 0; c < ncores; c++) { core_vpes = core_vpe_count(c); pr_cont("%c%u", c ? ',' : '{', core_vpes); @@ -62,7 +64,7 @@ static void __init cps_smp_setup(void) for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) { cpu_data[nvpes + v].core = c; -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) cpu_data[nvpes + v].vpe_id = v; #endif } @@ -91,6 +93,11 @@ static void __init cps_smp_setup(void) /* Make core 0 coherent with everything */ write_gcr_cl_coherence(0xff); + if (mips_cm_revision() >= CM_REV_CM3) { + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_bev_base(core_entry); + } + #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ if (cpu_has_fpu) @@ -213,6 +220,18 @@ static void boot_core(unsigned core) if (mips_cpc_present()) { /* Reset the core */ mips_cpc_lock_other(core); + + if (mips_cm_revision() >= CM_REV_CM3) { + /* Run VP0 following the reset */ + write_cpc_co_vp_run(0x1); + + /* + * Ensure that the VP_RUN register is written before the + * core leaves reset. + */ + wmb(); + } + write_cpc_co_cmd(CPC_Cx_CMD_RESET); timeout = 100; @@ -262,6 +281,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id]; + unsigned long core_entry; unsigned int remote; int err; @@ -279,6 +299,13 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } + if (cpu_has_vp) { + mips_cm_lock_other(core, vpe_id); + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_co_reset_base(core_entry); + mips_cm_unlock_other(); + } + if (core != current_cpu_data.core) { /* Boot a VPE on another powered up core */ for (remote = 0; remote < NR_CPUS; remote++) { @@ -296,7 +323,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } - BUG_ON(!cpu_has_mipsmt); + BUG_ON(!cpu_has_mipsmt && !cpu_has_vp); /* Boot a VPE on this core */ mips_cps_boot_vpes(core_cfg, vpe_id); |