aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-keystone/platsmp.c')
-rw-r--r--arch/arm/mach-keystone/platsmp.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
new file mode 100644
index 00000000000..beeb8d83b8d
--- /dev/null
+++ b/arch/arm/mach-keystone/platsmp.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright 2012 Texas Instruments, Inc.
3 *
4 * Based on platsmp.c, Copyright 2010-2011 Calxeda, Inc.
5 * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <linux/init.h>
20#include <linux/smp.h>
21#include <linux/io.h>
22#include <linux/of.h>
23
24#include <asm/smp.h>
25#include <asm/smp_plat.h>
26#include <asm/cacheflush.h>
27#include <asm/tlbflush.h>
28#include <asm/memory.h>
29#include <asm/psci.h>
30
31#include "keystone.h"
32asm(".arch_extension sec\n\t");
33
34static void __cpuinit keystone_smp_secondary_initmem(void)
35{
36#ifdef CONFIG_ARM_LPAE
37 pgd_t *pgd0 = pgd_offset_k(0);
38 cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
39 local_flush_tlb_all();
40#endif
41}
42
43static void __cpuinit keystone_smp_secondary_init(unsigned int cpu)
44{
45 keystone_smp_secondary_initmem();
46}
47
48static int __cpuinit
49keystone_smp_boot_secondary(unsigned int cpu, struct task_struct *idle)
50{
51 unsigned long start = virt_to_idmap(&secondary_startup);
52 int error;
53
54 pr_debug("keystone-smp: booting cpu %d, vector %08lx\n",
55 cpu, start);
56
57 asm volatile (
58 "mov r0, #0\n" /* power on cmd */
59 "mov r1, %1\n" /* cpu */
60 "mov r2, %2\n" /* start */
61 "smc #0\n" /* SMI */
62 "mov %0, r0\n"
63 : "=r" (error)
64 : "r"(cpu), "r"(start)
65 : "cc", "r0", "r1", "r2", "memory"
66 );
67
68 pr_debug("keystone-smp: monitor returned %d\n", error);
69
70 return error;
71}
72
73#ifdef CONFIG_HOTPLUG_CPU
74static void keystone_cpu_die(unsigned int cpu)
75{
76#ifdef CONFIG_ARM_PSCI
77 struct psci_power_state pwr_state = {0, 0, 0};
78
79 printk(KERN_INFO "keystone_cpu_die(%d) from %d using PSCI\n", cpu,
80 smp_processor_id());
81
82 if (psci_ops.cpu_off)
83 psci_ops.cpu_off(pwr_state);
84#else
85 /*
86 * We may want to add here a direct smc call to monitor
87 * if the kernel doesn't support PSCI API
88 */
89#endif
90
91 /*
92 * we shouldn't come here. But in case something went
93 * wrong the code below prevents kernel from crush
94 */
95 while (1)
96 cpu_do_idle();
97}
98#endif
99
100struct smp_operations keystone_smp_ops __initdata = {
101 .smp_secondary_init = keystone_smp_secondary_init,
102 .smp_boot_secondary = keystone_smp_boot_secondary,
103#ifdef CONFIG_HOTPLUG_CPU
104 .cpu_die = keystone_cpu_die,
105#endif
106};