1 // SPDX-License-Identifier: GPL-2.0
3 * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
5 * Copyright (C) 2010 Magnus Damm
6 * Copyright (C) 2010 Takashi Yoshii
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/smp.h>
12 #include <linux/delay.h>
14 #include <asm/smp_plat.h>
19 #define CPG_BASE2 0xe6151000
20 #define WUPCR 0x10 /* System-CPU Wake Up Control Register */
21 #define SRESCR 0x18 /* System-CPU Software Reset Control Register */
22 #define PSTR 0x40 /* System-CPU Power Status Register */
24 #define SYSC_BASE 0xe6180000
25 #define SBAR 0x20 /* SYS Boot Address Register */
27 #define AP_BASE 0xe6f10000
28 #define APARMBAREA 0x20 /* Address Translation Area Register */
30 #define SH73A0_SCU_BASE 0xf0000000
32 static int sh73a0_boot_secondary(unsigned int cpu
, struct task_struct
*idle
)
34 unsigned int lcpu
= cpu_logical_map(cpu
);
35 void __iomem
*cpg2
= ioremap(CPG_BASE2
, PAGE_SIZE
);
37 if (((readl(cpg2
+ PSTR
) >> (4 * lcpu
)) & 3) == 3)
38 writel(1 << lcpu
, cpg2
+ WUPCR
); /* wake up */
40 writel(1 << lcpu
, cpg2
+ SRESCR
); /* reset */
45 static void __init
sh73a0_smp_prepare_cpus(unsigned int max_cpus
)
47 void __iomem
*ap
= ioremap(AP_BASE
, PAGE_SIZE
);
48 void __iomem
*sysc
= ioremap(SYSC_BASE
, PAGE_SIZE
);
50 /* Map the reset vector (in headsmp.S) */
51 writel(0, ap
+ APARMBAREA
); /* 4k */
52 writel(__pa(shmobile_boot_vector
), sysc
+ SBAR
);
56 /* setup sh73a0 specific SCU bits */
57 shmobile_smp_scu_prepare_cpus(SH73A0_SCU_BASE
, max_cpus
);
60 const struct smp_operations sh73a0_smp_ops __initconst
= {
61 .smp_prepare_cpus
= sh73a0_smp_prepare_cpus
,
62 .smp_boot_secondary
= sh73a0_boot_secondary
,
63 #ifdef CONFIG_HOTPLUG_CPU
64 .cpu_can_disable
= shmobile_smp_cpu_can_disable
,
65 .cpu_die
= shmobile_smp_scu_cpu_die
,
66 .cpu_kill
= shmobile_smp_scu_cpu_kill
,