aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-shmobile/smp-sh73a0.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile/smp-sh73a0.c')
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c90
1 files changed, 35 insertions, 55 deletions
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index a156d2108df..13ba36a6831 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -20,78 +20,58 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp.h>
-#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/delay.h>
#include <mach/common.h>
-#include <asm/smp_scu.h>
+#include <mach/sh73a0.h>
+#include <asm/smp_plat.h>
#include <asm/smp_twd.h>
-#include <asm/hardware/gic.h>
-#define WUPCR 0xe6151010
-#define SRESCR 0xe6151018
-#define PSTR 0xe6151040
-#define SBAR 0xe6180020
-#define APARMBAREA 0xe6f10020
+#define WUPCR IOMEM(0xe6151010)
+#define SRESCR IOMEM(0xe6151018)
+#define PSTR IOMEM(0xe6151040)
+#define SBAR IOMEM(0xe6180020)
+#define APARMBAREA IOMEM(0xe6f10020)
-static void __iomem *scu_base_addr(void)
-{
- return (void __iomem *)0xf0000000;
-}
-
-static DEFINE_SPINLOCK(scu_lock);
-static unsigned long tmp;
-
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
- void __iomem *scu_base = scu_base_addr();
-
- spin_lock(&scu_lock);
- tmp = __raw_readl(scu_base + 8);
- tmp &= ~clr;
- tmp |= set;
- spin_unlock(&scu_lock);
-
- /* disable cache coherency after releasing the lock */
- __raw_writel(tmp, scu_base + 8);
-}
-
-unsigned int __init sh73a0_get_core_count(void)
-{
- void __iomem *scu_base = scu_base_addr();
+#define SH73A0_SCU_BASE 0xf0000000
- return scu_get_core_count(scu_base);
-}
-
-void __cpuinit sh73a0_secondary_init(unsigned int cpu)
+#ifdef CONFIG_HAVE_ARM_TWD
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
+void __init sh73a0_register_twd(void)
{
- gic_secondary_init(0);
+ twd_local_timer_register(&twd_local_timer);
}
+#endif
-int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
+static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- /* enable cache coherency */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
+ unsigned int lcpu = cpu_logical_map(cpu);
- if (((__raw_readw(__io(PSTR)) >> (4 * cpu)) & 3) == 3)
- __raw_writel(1 << cpu, __io(WUPCR)); /* wake up */
+ if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
+ __raw_writel(1 << lcpu, WUPCR); /* wake up */
else
- __raw_writel(1 << cpu, __io(SRESCR)); /* reset */
+ __raw_writel(1 << lcpu, SRESCR); /* reset */
return 0;
}
-void __init sh73a0_smp_prepare_cpus(void)
+static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
{
-#ifdef CONFIG_HAVE_ARM_TWD
- twd_base = (void __iomem *)0xf0000600;
-#endif
-
- scu_enable(scu_base_addr());
-
/* Map the reset vector (in headsmp.S) */
- __raw_writel(0, __io(APARMBAREA)); /* 4k */
- __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
+ __raw_writel(0, APARMBAREA); /* 4k */
+ __raw_writel(__pa(shmobile_boot_vector), SBAR);
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (0 * 8));
+ /* setup sh73a0 specific SCU bits */
+ shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
+ shmobile_smp_scu_prepare_cpus(max_cpus);
}
+
+struct smp_operations sh73a0_smp_ops __initdata = {
+ .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
+ .smp_boot_secondary = sh73a0_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = shmobile_smp_cpu_disable,
+ .cpu_die = shmobile_smp_scu_cpu_die,
+ .cpu_kill = shmobile_smp_scu_cpu_kill,
+#endif
+};