diff options
Diffstat (limited to 'arch/mips/pmc-sierra/msp71xx/msp_smtc.c')
-rw-r--r-- | arch/mips/pmc-sierra/msp71xx/msp_smtc.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_smtc.c b/arch/mips/pmc-sierra/msp71xx/msp_smtc.c new file mode 100644 index 00000000000..c8dcc1c01e1 --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/msp_smtc.c @@ -0,0 +1,105 @@ +/* + * MSP71xx Platform-specific hooks for SMP operation + */ +#include <linux/irq.h> +#include <linux/init.h> + +#include <asm/mipsmtregs.h> +#include <asm/mipsregs.h> +#include <asm/smtc.h> +#include <asm/smtc_ipi.h> + +/* VPE/SMP Prototype implements platform interfaces directly */ + +/* + * Cause the specified action to be performed on a targeted "CPU" + */ + +static void msp_smtc_send_ipi_single(int cpu, unsigned int action) +{ + /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ + smtc_send_ipi(cpu, LINUX_SMP_IPI, action); +} + +static void msp_smtc_send_ipi_mask(const struct cpumask *mask, + unsigned int action) +{ + unsigned int i; + + for_each_cpu(i, mask) + msp_smtc_send_ipi_single(i, action); +} + +/* + * Post-config but pre-boot cleanup entry point + */ +static void __cpuinit msp_smtc_init_secondary(void) +{ + int myvpe; + + /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ + myvpe = read_c0_tcbind() & TCBIND_CURVPE; + if (myvpe > 0) + change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 | + STATUSF_IP6 | STATUSF_IP7); + smtc_init_secondary(); +} + +/* + * Platform "CPU" startup hook + */ +static void __cpuinit msp_smtc_boot_secondary(int cpu, + struct task_struct *idle) +{ + smtc_boot_secondary(cpu, idle); +} + +/* + * SMP initialization finalization entry point + */ +static void __cpuinit msp_smtc_smp_finish(void) +{ + smtc_smp_finish(); +} + +/* + * Hook for after all CPUs are online + */ + +static void msp_smtc_cpus_done(void) +{ +} + +/* + * Platform SMP pre-initialization + * + * As noted above, we can assume a single CPU for now + * but it may be multithreaded. + */ + +static void __init msp_smtc_smp_setup(void) +{ + /* + * we won't get the definitive value until + * we've run smtc_prepare_cpus later, but + */ + + if (read_c0_config3() & (1 << 2)) + smp_num_siblings = smtc_build_cpu_map(0); +} + +static void __init msp_smtc_prepare_cpus(unsigned int max_cpus) +{ + smtc_prepare_cpus(max_cpus); +} + +struct plat_smp_ops msp_smtc_smp_ops = { + .send_ipi_single = msp_smtc_send_ipi_single, + .send_ipi_mask = msp_smtc_send_ipi_mask, + .init_secondary = msp_smtc_init_secondary, + .smp_finish = msp_smtc_smp_finish, + .cpus_done = msp_smtc_cpus_done, + .boot_secondary = msp_smtc_boot_secondary, + .smp_setup = msp_smtc_smp_setup, + .prepare_cpus = msp_smtc_prepare_cpus, +}; |