aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/kernel/cpu/sh4a/smp-shx3.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
index dd245e68aa2e..de865cac02ee 100644
--- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
@@ -9,16 +9,22 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/kernel.h>
12#include <linux/cpumask.h> 13#include <linux/cpumask.h>
13#include <linux/smp.h> 14#include <linux/smp.h>
14#include <linux/interrupt.h> 15#include <linux/interrupt.h>
15#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/sched.h>
18#include <linux/delay.h>
19#include <linux/cpu.h>
20#include <asm/sections.h>
16 21
17#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) 22#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12))
18#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) 23#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12))
19 24
20#define STBCR_MSTP 0x00000001 25#define STBCR_MSTP 0x00000001
21#define STBCR_RESET 0x00000002 26#define STBCR_RESET 0x00000002
27#define STBCR_SLEEP 0x00000004
22#define STBCR_LTSLP 0x80000000 28#define STBCR_LTSLP 0x80000000
23 29
24static irqreturn_t ipi_interrupt_handler(int irq, void *arg) 30static irqreturn_t ipi_interrupt_handler(int irq, void *arg)
@@ -110,10 +116,51 @@ static void shx3_send_ipi(unsigned int cpu, unsigned int message)
110 __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ 116 __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */
111} 117}
112 118
119static void shx3_update_boot_vector(unsigned int cpu)
120{
121 __raw_writel(STBCR_MSTP, STBCR_REG(cpu));
122 while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP))
123 cpu_relax();
124 __raw_writel(STBCR_RESET, STBCR_REG(cpu));
125}
126
127static int __cpuinit
128shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
129{
130 unsigned int cpu = (unsigned int)hcpu;
131
132 switch (action) {
133 case CPU_UP_PREPARE:
134 shx3_update_boot_vector(cpu);
135 break;
136 case CPU_ONLINE:
137 pr_info("CPU %u is now online\n", cpu);
138 break;
139 case CPU_DEAD:
140 break;
141 }
142
143 return NOTIFY_OK;
144}
145
146static struct notifier_block __cpuinitdata shx3_cpu_notifier = {
147 .notifier_call = shx3_cpu_callback,
148};
149
150static int __cpuinit register_shx3_cpu_notifier(void)
151{
152 register_hotcpu_notifier(&shx3_cpu_notifier);
153 return 0;
154}
155late_initcall(register_shx3_cpu_notifier);
156
113struct plat_smp_ops shx3_smp_ops = { 157struct plat_smp_ops shx3_smp_ops = {
114 .smp_setup = shx3_smp_setup, 158 .smp_setup = shx3_smp_setup,
115 .prepare_cpus = shx3_prepare_cpus, 159 .prepare_cpus = shx3_prepare_cpus,
116 .start_cpu = shx3_start_cpu, 160 .start_cpu = shx3_start_cpu,
117 .smp_processor_id = shx3_smp_processor_id, 161 .smp_processor_id = shx3_smp_processor_id,
118 .send_ipi = shx3_send_ipi, 162 .send_ipi = shx3_send_ipi,
163 .cpu_die = native_cpu_die,
164 .cpu_disable = native_cpu_disable,
165 .play_dead = native_play_dead,
119}; 166};