xref: /OK3568_Linux_fs/kernel/arch/arm/mach-shmobile/smp-sh73a0.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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