xref: /OK3568_Linux_fs/kernel/arch/arm/mach-sti/platsmp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  arch/arm/mach-sti/platsmp.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
6*4882a593Smuzhiyun  *		http://www.st.com
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *  Copyright (C) 2002 ARM Ltd.
11*4882a593Smuzhiyun  *  All Rights Reserved
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/errno.h>
15*4882a593Smuzhiyun #include <linux/delay.h>
16*4882a593Smuzhiyun #include <linux/smp.h>
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include <linux/of.h>
19*4882a593Smuzhiyun #include <linux/of_address.h>
20*4882a593Smuzhiyun #include <linux/memblock.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include <asm/cacheflush.h>
23*4882a593Smuzhiyun #include <asm/smp_plat.h>
24*4882a593Smuzhiyun #include <asm/smp_scu.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include "smp.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static u32 __iomem *cpu_strt_ptr;
29*4882a593Smuzhiyun 
sti_boot_secondary(unsigned int cpu,struct task_struct * idle)30*4882a593Smuzhiyun static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	unsigned long entry_pa = __pa_symbol(secondary_startup);
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	/*
35*4882a593Smuzhiyun 	 * Secondary CPU is initialised and started by a U-BOOTROM firmware.
36*4882a593Smuzhiyun 	 * Secondary CPU is spinning and waiting for a write at cpu_strt_ptr.
37*4882a593Smuzhiyun 	 * Writing secondary_startup address at cpu_strt_ptr makes it to
38*4882a593Smuzhiyun 	 * jump directly to secondary_startup().
39*4882a593Smuzhiyun 	 */
40*4882a593Smuzhiyun 	__raw_writel(entry_pa, cpu_strt_ptr);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	/* wmb so that data is actually written before cache flush is done */
43*4882a593Smuzhiyun 	smp_wmb();
44*4882a593Smuzhiyun 	sync_cache_w(cpu_strt_ptr);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	return 0;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
sti_smp_prepare_cpus(unsigned int max_cpus)49*4882a593Smuzhiyun static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct device_node *np;
52*4882a593Smuzhiyun 	void __iomem *scu_base;
53*4882a593Smuzhiyun 	u32 release_phys;
54*4882a593Smuzhiyun 	int cpu;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	if (np) {
59*4882a593Smuzhiyun 		scu_base = of_iomap(np, 0);
60*4882a593Smuzhiyun 		scu_enable(scu_base);
61*4882a593Smuzhiyun 		of_node_put(np);
62*4882a593Smuzhiyun 	}
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	if (max_cpus <= 1)
65*4882a593Smuzhiyun 		return;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	for_each_possible_cpu(cpu) {
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 		np = of_get_cpu_node(cpu, NULL);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		if (!np)
72*4882a593Smuzhiyun 			continue;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 		if (of_property_read_u32(np, "cpu-release-addr",
75*4882a593Smuzhiyun 						&release_phys)) {
76*4882a593Smuzhiyun 			pr_err("CPU %d: missing or invalid cpu-release-addr "
77*4882a593Smuzhiyun 				"property\n", cpu);
78*4882a593Smuzhiyun 			continue;
79*4882a593Smuzhiyun 		}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 		/*
82*4882a593Smuzhiyun 		 * cpu-release-addr is usually configured in SBC DMEM but can
83*4882a593Smuzhiyun 		 * also be in RAM.
84*4882a593Smuzhiyun 		 */
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 		if (!memblock_is_memory(release_phys))
87*4882a593Smuzhiyun 			cpu_strt_ptr =
88*4882a593Smuzhiyun 				ioremap(release_phys, sizeof(release_phys));
89*4882a593Smuzhiyun 		else
90*4882a593Smuzhiyun 			cpu_strt_ptr =
91*4882a593Smuzhiyun 				(u32 __iomem *)phys_to_virt(release_phys);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		set_cpu_possible(cpu, true);
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun const struct smp_operations sti_smp_ops __initconst = {
98*4882a593Smuzhiyun 	.smp_prepare_cpus	= sti_smp_prepare_cpus,
99*4882a593Smuzhiyun 	.smp_boot_secondary	= sti_boot_secondary,
100*4882a593Smuzhiyun };
101