1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010 Magnus Damm
6*4882a593Smuzhiyun * Copyright (C) 2010 Takashi Yoshii
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/smp.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <asm/smp_plat.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "common.h"
17*4882a593Smuzhiyun #include "sh73a0.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define WUPCR IOMEM(0xe6151010)
20*4882a593Smuzhiyun #define SRESCR IOMEM(0xe6151018)
21*4882a593Smuzhiyun #define PSTR IOMEM(0xe6151040)
22*4882a593Smuzhiyun #define SBAR IOMEM(0xe6180020)
23*4882a593Smuzhiyun #define APARMBAREA IOMEM(0xe6f10020)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define SH73A0_SCU_BASE 0xf0000000
26*4882a593Smuzhiyun
sh73a0_boot_secondary(unsigned int cpu,struct task_struct * idle)27*4882a593Smuzhiyun static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun unsigned int lcpu = cpu_logical_map(cpu);
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
32*4882a593Smuzhiyun __raw_writel(1 << lcpu, WUPCR); /* wake up */
33*4882a593Smuzhiyun else
34*4882a593Smuzhiyun __raw_writel(1 << lcpu, SRESCR); /* reset */
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
sh73a0_smp_prepare_cpus(unsigned int max_cpus)39*4882a593Smuzhiyun static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun /* Map the reset vector (in headsmp.S) */
42*4882a593Smuzhiyun __raw_writel(0, APARMBAREA); /* 4k */
43*4882a593Smuzhiyun __raw_writel(__pa(shmobile_boot_vector), SBAR);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* setup sh73a0 specific SCU bits */
46*4882a593Smuzhiyun shmobile_smp_scu_prepare_cpus(SH73A0_SCU_BASE, max_cpus);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun const struct smp_operations sh73a0_smp_ops __initconst = {
50*4882a593Smuzhiyun .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
51*4882a593Smuzhiyun .smp_boot_secondary = sh73a0_boot_secondary,
52*4882a593Smuzhiyun #ifdef CONFIG_HOTPLUG_CPU
53*4882a593Smuzhiyun .cpu_can_disable = shmobile_smp_cpu_can_disable,
54*4882a593Smuzhiyun .cpu_die = shmobile_smp_scu_cpu_die,
55*4882a593Smuzhiyun .cpu_kill = shmobile_smp_scu_cpu_kill,
56*4882a593Smuzhiyun #endif
57*4882a593Smuzhiyun };
58