]>
Commit | Line | Data |
---|---|---|
1ee89e22 GC |
1 | /* |
2 | * Symmetric Multi Processing (SMP) support for Marvell EBU Cortex-A9 | |
3 | * based SOCs (Armada 375/38x). | |
4 | * | |
5 | * Copyright (C) 2014 Marvell | |
6 | * | |
7 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | |
8 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | |
9 | * | |
10 | * This file is licensed under the terms of the GNU General Public | |
11 | * License version 2. This program is licensed "as is" without any | |
12 | * warranty of any kind, whether express or implied. | |
13 | */ | |
14 | ||
15 | #include <linux/init.h> | |
16 | #include <linux/io.h> | |
17 | #include <linux/of.h> | |
18 | #include <linux/smp.h> | |
87384cc0 | 19 | #include <linux/mbus.h> |
1ee89e22 GC |
20 | #include <asm/smp_scu.h> |
21 | #include <asm/smp_plat.h> | |
22 | #include "common.h" | |
23 | #include "pmsu.h" | |
24 | ||
25 | extern void mvebu_cortex_a9_secondary_startup(void); | |
26 | ||
27 | static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, | |
28 | struct task_struct *idle) | |
29 | { | |
30 | int ret, hw_cpu; | |
31 | ||
32 | pr_info("Booting CPU %d\n", cpu); | |
33 | ||
34 | /* | |
35 | * Write the address of secondary startup into the system-wide | |
36 | * flags register. The boot monitor waits until it receives a | |
37 | * soft interrupt, and then the secondary CPU branches to this | |
38 | * address. | |
39 | */ | |
40 | hw_cpu = cpu_logical_map(cpu); | |
305969fb | 41 | if (of_machine_is_compatible("marvell,armada375")) |
1ee89e22 | 42 | mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup); |
305969fb GC |
43 | else |
44 | mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup); | |
1ee89e22 | 45 | smp_wmb(); |
626d6864 GC |
46 | |
47 | /* | |
48 | * Doing this before deasserting the CPUs is needed to wake up CPUs | |
49 | * in the offline state after using CPU hotplug. | |
50 | */ | |
51 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | |
52 | ||
1ee89e22 GC |
53 | ret = mvebu_cpu_reset_deassert(hw_cpu); |
54 | if (ret) { | |
55 | pr_err("Could not start the secondary CPU: %d\n", ret); | |
56 | return ret; | |
57 | } | |
1ee89e22 GC |
58 | |
59 | return 0; | |
60 | } | |
626d6864 GC |
61 | /* |
62 | * When a CPU is brought back online, either through CPU hotplug, or | |
63 | * because of the boot of a kexec'ed kernel, the PMSU configuration | |
64 | * for this CPU might be in the deep idle state, preventing this CPU | |
65 | * from receiving interrupts. Here, we therefore take out the current | |
66 | * CPU from this state, which was entered by armada_38x_cpu_die() | |
67 | * below. | |
68 | */ | |
69 | static void armada_38x_secondary_init(unsigned int cpu) | |
70 | { | |
71 | mvebu_v7_pmsu_idle_exit(); | |
72 | } | |
73 | ||
74 | #ifdef CONFIG_HOTPLUG_CPU | |
75 | static void armada_38x_cpu_die(unsigned int cpu) | |
76 | { | |
77 | /* | |
78 | * CPU hotplug is implemented by putting offline CPUs into the | |
79 | * deep idle sleep state. | |
80 | */ | |
81 | armada_38x_do_cpu_suspend(true); | |
82 | } | |
83 | ||
84 | /* | |
85 | * We need a dummy function, so that platform_can_cpu_hotplug() knows | |
86 | * we support CPU hotplug. However, the function does not need to do | |
87 | * anything, because CPUs going offline can enter the deep idle state | |
88 | * by themselves, without any help from a still alive CPU. | |
89 | */ | |
90 | static int armada_38x_cpu_kill(unsigned int cpu) | |
91 | { | |
92 | return 1; | |
93 | } | |
94 | #endif | |
1ee89e22 GC |
95 | |
96 | static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { | |
97 | .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, | |
1ee89e22 GC |
98 | }; |
99 | ||
626d6864 GC |
100 | static struct smp_operations armada_38x_smp_ops __initdata = { |
101 | .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, | |
102 | .smp_secondary_init = armada_38x_secondary_init, | |
103 | #ifdef CONFIG_HOTPLUG_CPU | |
104 | .cpu_die = armada_38x_cpu_die, | |
105 | .cpu_kill = armada_38x_cpu_kill, | |
106 | #endif | |
107 | }; | |
108 | ||
1ee89e22 GC |
109 | CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp", |
110 | &mvebu_cortex_a9_smp_ops); | |
111 | CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp", | |
626d6864 | 112 | &armada_38x_smp_ops); |