xref: /openbmc/linux/arch/arm/mach-imx/platsmp.c (revision 31b90347)
1 /*
2  * Copyright 2011 Freescale Semiconductor, Inc.
3  * Copyright 2011 Linaro Ltd.
4  *
5  * The code contained herein is licensed under the GNU General Public
6  * License. You may obtain a copy of the GNU General Public License
7  * Version 2 or later at the following locations:
8  *
9  * http://www.opensource.org/licenses/gpl-license.html
10  * http://www.gnu.org/copyleft/gpl.html
11  */
12 
13 #include <linux/init.h>
14 #include <linux/smp.h>
15 #include <asm/cacheflush.h>
16 #include <asm/page.h>
17 #include <asm/smp_scu.h>
18 #include <asm/mach/map.h>
19 
20 #include "common.h"
21 #include "hardware.h"
22 
23 #define SCU_STANDBY_ENABLE	(1 << 5)
24 
25 u32 g_diag_reg;
26 static void __iomem *scu_base;
27 
28 static struct map_desc scu_io_desc __initdata = {
29 	/* .virtual and .pfn are run-time assigned */
30 	.length		= SZ_4K,
31 	.type		= MT_DEVICE,
32 };
33 
34 void __init imx_scu_map_io(void)
35 {
36 	unsigned long base;
37 
38 	/* Get SCU base */
39 	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
40 
41 	scu_io_desc.virtual = IMX_IO_P2V(base);
42 	scu_io_desc.pfn = __phys_to_pfn(base);
43 	iotable_init(&scu_io_desc, 1);
44 
45 	scu_base = IMX_IO_ADDRESS(base);
46 }
47 
48 void imx_scu_standby_enable(void)
49 {
50 	u32 val = readl_relaxed(scu_base);
51 
52 	val |= SCU_STANDBY_ENABLE;
53 	writel_relaxed(val, scu_base);
54 }
55 
56 static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
57 {
58 	imx_set_cpu_jump(cpu, v7_secondary_startup);
59 	imx_enable_cpu(cpu, true);
60 	return 0;
61 }
62 
63 /*
64  * Initialise the CPU possible map early - this describes the CPUs
65  * which may be present or become present in the system.
66  */
67 static void __init imx_smp_init_cpus(void)
68 {
69 	int i, ncores;
70 
71 	ncores = scu_get_core_count(scu_base);
72 
73 	for (i = ncores; i < NR_CPUS; i++)
74 		set_cpu_possible(i, false);
75 }
76 
77 void imx_smp_prepare(void)
78 {
79 	scu_enable(scu_base);
80 }
81 
82 static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
83 {
84 	imx_smp_prepare();
85 
86 	/*
87 	 * The diagnostic register holds the errata bits.  Mostly bootloader
88 	 * does not bring up secondary cores, so that when errata bits are set
89 	 * in bootloader, they are set only for boot cpu.  But on a SMP
90 	 * configuration, it should be equally done on every single core.
91 	 * Read the register from boot cpu here, and will replicate it into
92 	 * secondary cores when booting them.
93 	 */
94 	asm("mrc p15, 0, %0, c15, c0, 1" : "=r" (g_diag_reg) : : "cc");
95 	__cpuc_flush_dcache_area(&g_diag_reg, sizeof(g_diag_reg));
96 	outer_clean_range(__pa(&g_diag_reg), __pa(&g_diag_reg + 1));
97 }
98 
99 struct smp_operations  imx_smp_ops __initdata = {
100 	.smp_init_cpus		= imx_smp_init_cpus,
101 	.smp_prepare_cpus	= imx_smp_prepare_cpus,
102 	.smp_boot_secondary	= imx_boot_secondary,
103 #ifdef CONFIG_HOTPLUG_CPU
104 	.cpu_die		= imx_cpu_die,
105 	.cpu_kill		= imx_cpu_kill,
106 #endif
107 };
108