diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-04-26 19:11:51 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-04-26 19:11:51 +0900 |
commit | 54b41b97fd07842d8b64963d538003c5f756ca12 (patch) | |
tree | eb70c7c0dee9e237018c3fda0b5566d6d1338a3b /arch/sh/kernel/cpu | |
parent | e60692b9347d17774cdad00ae2b9afd3dc5444af (diff) | |
parent | e7dc951eecb708d4aef18db4dbf489ba282d16ff (diff) |
Merge branch 'sh/smp'
Diffstat (limited to 'arch/sh/kernel/cpu')
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/smp-shx3.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index c98b4574c44..de865cac02e 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -1,7 +1,7 @@ /* * SH-X3 SMP * - * Copyright (C) 2007 - 2008 Paul Mundt + * Copyright (C) 2007 - 2010 Paul Mundt * Copyright (C) 2007 Magnus Damm * * This file is subject to the terms and conditions of the GNU General Public @@ -9,16 +9,22 @@ * for more details. */ #include <linux/init.h> +#include <linux/kernel.h> #include <linux/cpumask.h> #include <linux/smp.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/cpu.h> +#include <asm/sections.h> #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) #define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) #define STBCR_MSTP 0x00000001 #define STBCR_RESET 0x00000002 +#define STBCR_SLEEP 0x00000004 #define STBCR_LTSLP 0x80000000 static irqreturn_t ipi_interrupt_handler(int irq, void *arg) @@ -37,7 +43,7 @@ static irqreturn_t ipi_interrupt_handler(int irq, void *arg) return IRQ_HANDLED; } -void __init plat_smp_setup(void) +static void shx3_smp_setup(void) { unsigned int cpu = 0; int i, num; @@ -63,7 +69,7 @@ void __init plat_smp_setup(void) printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); } -void __init plat_prepare_cpus(unsigned int max_cpus) +static void shx3_prepare_cpus(unsigned int max_cpus) { int i; @@ -74,9 +80,12 @@ void __init plat_prepare_cpus(unsigned int max_cpus) for (i = 0; i < SMP_MSG_NR; i++) request_irq(104 + i, ipi_interrupt_handler, IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); + + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); } -void plat_start_cpu(unsigned int cpu, unsigned long entry_point) +static void shx3_start_cpu(unsigned int cpu, unsigned long entry_point) { if (__in_29bit_mode()) __raw_writel(entry_point, RESET_REG(cpu)); @@ -93,12 +102,12 @@ void plat_start_cpu(unsigned int cpu, unsigned long entry_point) __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); } -int plat_smp_processor_id(void) +static unsigned int shx3_smp_processor_id(void) { return __raw_readl(0xff000048); /* CPIDR */ } -void plat_send_ipi(unsigned int cpu, unsigned int message) +static void shx3_send_ipi(unsigned int cpu, unsigned int message) { unsigned long addr = 0xfe410070 + (cpu * 4); @@ -106,3 +115,52 @@ void plat_send_ipi(unsigned int cpu, unsigned int message) __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ } + +static void shx3_update_boot_vector(unsigned int cpu) +{ + __raw_writel(STBCR_MSTP, STBCR_REG(cpu)); + while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) + cpu_relax(); + __raw_writel(STBCR_RESET, STBCR_REG(cpu)); +} + +static int __cpuinit +shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned int)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + shx3_update_boot_vector(cpu); + break; + case CPU_ONLINE: + pr_info("CPU %u is now online\n", cpu); + break; + case CPU_DEAD: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata shx3_cpu_notifier = { + .notifier_call = shx3_cpu_callback, +}; + +static int __cpuinit register_shx3_cpu_notifier(void) +{ + register_hotcpu_notifier(&shx3_cpu_notifier); + return 0; +} +late_initcall(register_shx3_cpu_notifier); + +struct plat_smp_ops shx3_smp_ops = { + .smp_setup = shx3_smp_setup, + .prepare_cpus = shx3_prepare_cpus, + .start_cpu = shx3_start_cpu, + .smp_processor_id = shx3_smp_processor_id, + .send_ipi = shx3_send_ipi, + .cpu_die = native_cpu_die, + .cpu_disable = native_cpu_disable, + .play_dead = native_play_dead, +}; |