.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * arch/arm/mach-sti/platsmp.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * |
---|
9 | 10 | * Copyright (C) 2002 ARM Ltd. |
---|
10 | 11 | * All Rights Reserved |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License version 2 as |
---|
14 | | - * published by the Free Software Foundation. |
---|
15 | 12 | */ |
---|
16 | 13 | #include <linux/init.h> |
---|
17 | 14 | #include <linux/errno.h> |
---|
.. | .. |
---|
28 | 25 | |
---|
29 | 26 | #include "smp.h" |
---|
30 | 27 | |
---|
31 | | -static void write_pen_release(int val) |
---|
32 | | -{ |
---|
33 | | - pen_release = val; |
---|
34 | | - smp_wmb(); |
---|
35 | | - sync_cache_w(&pen_release); |
---|
36 | | -} |
---|
37 | | - |
---|
38 | | -static DEFINE_SPINLOCK(boot_lock); |
---|
39 | | - |
---|
40 | | -static void sti_secondary_init(unsigned int cpu) |
---|
41 | | -{ |
---|
42 | | - /* |
---|
43 | | - * let the primary processor know we're out of the |
---|
44 | | - * pen, then head off into the C entry point |
---|
45 | | - */ |
---|
46 | | - write_pen_release(-1); |
---|
47 | | - |
---|
48 | | - /* |
---|
49 | | - * Synchronise with the boot thread. |
---|
50 | | - */ |
---|
51 | | - spin_lock(&boot_lock); |
---|
52 | | - spin_unlock(&boot_lock); |
---|
53 | | -} |
---|
| 28 | +static u32 __iomem *cpu_strt_ptr; |
---|
54 | 29 | |
---|
55 | 30 | static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) |
---|
56 | 31 | { |
---|
57 | | - unsigned long timeout; |
---|
| 32 | + unsigned long entry_pa = __pa_symbol(secondary_startup); |
---|
58 | 33 | |
---|
59 | 34 | /* |
---|
60 | | - * set synchronisation state between this boot processor |
---|
61 | | - * and the secondary one |
---|
| 35 | + * Secondary CPU is initialised and started by a U-BOOTROM firmware. |
---|
| 36 | + * Secondary CPU is spinning and waiting for a write at cpu_strt_ptr. |
---|
| 37 | + * Writing secondary_startup address at cpu_strt_ptr makes it to |
---|
| 38 | + * jump directly to secondary_startup(). |
---|
62 | 39 | */ |
---|
63 | | - spin_lock(&boot_lock); |
---|
| 40 | + __raw_writel(entry_pa, cpu_strt_ptr); |
---|
64 | 41 | |
---|
65 | | - /* |
---|
66 | | - * The secondary processor is waiting to be released from |
---|
67 | | - * the holding pen - release it, then wait for it to flag |
---|
68 | | - * that it has been released by resetting pen_release. |
---|
69 | | - * |
---|
70 | | - * Note that "pen_release" is the hardware CPU ID, whereas |
---|
71 | | - * "cpu" is Linux's internal ID. |
---|
72 | | - */ |
---|
73 | | - write_pen_release(cpu_logical_map(cpu)); |
---|
| 42 | + /* wmb so that data is actually written before cache flush is done */ |
---|
| 43 | + smp_wmb(); |
---|
| 44 | + sync_cache_w(cpu_strt_ptr); |
---|
74 | 45 | |
---|
75 | | - /* |
---|
76 | | - * Send the secondary CPU a soft interrupt, thereby causing |
---|
77 | | - * it to jump to the secondary entrypoint. |
---|
78 | | - */ |
---|
79 | | - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
---|
80 | | - |
---|
81 | | - timeout = jiffies + (1 * HZ); |
---|
82 | | - while (time_before(jiffies, timeout)) { |
---|
83 | | - smp_rmb(); |
---|
84 | | - if (pen_release == -1) |
---|
85 | | - break; |
---|
86 | | - |
---|
87 | | - udelay(10); |
---|
88 | | - } |
---|
89 | | - |
---|
90 | | - /* |
---|
91 | | - * now the secondary core is starting up let it run its |
---|
92 | | - * calibrations, then wait for it to finish |
---|
93 | | - */ |
---|
94 | | - spin_unlock(&boot_lock); |
---|
95 | | - |
---|
96 | | - return pen_release != -1 ? -ENOSYS : 0; |
---|
| 46 | + return 0; |
---|
97 | 47 | } |
---|
98 | 48 | |
---|
99 | 49 | static void __init sti_smp_prepare_cpus(unsigned int max_cpus) |
---|
100 | 50 | { |
---|
101 | 51 | struct device_node *np; |
---|
102 | 52 | void __iomem *scu_base; |
---|
103 | | - u32 __iomem *cpu_strt_ptr; |
---|
104 | 53 | u32 release_phys; |
---|
105 | 54 | int cpu; |
---|
106 | | - unsigned long entry_pa = __pa_symbol(sti_secondary_startup); |
---|
107 | 55 | |
---|
108 | 56 | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); |
---|
109 | 57 | |
---|
.. | .. |
---|
131 | 79 | } |
---|
132 | 80 | |
---|
133 | 81 | /* |
---|
134 | | - * holding pen is usually configured in SBC DMEM but can also be |
---|
135 | | - * in RAM. |
---|
| 82 | + * cpu-release-addr is usually configured in SBC DMEM but can |
---|
| 83 | + * also be in RAM. |
---|
136 | 84 | */ |
---|
137 | 85 | |
---|
138 | 86 | if (!memblock_is_memory(release_phys)) |
---|
.. | .. |
---|
142 | 90 | cpu_strt_ptr = |
---|
143 | 91 | (u32 __iomem *)phys_to_virt(release_phys); |
---|
144 | 92 | |
---|
145 | | - __raw_writel(entry_pa, cpu_strt_ptr); |
---|
146 | | - |
---|
147 | | - /* |
---|
148 | | - * wmb so that data is actually written |
---|
149 | | - * before cache flush is done |
---|
150 | | - */ |
---|
151 | | - smp_wmb(); |
---|
152 | | - sync_cache_w(cpu_strt_ptr); |
---|
153 | | - |
---|
154 | | - if (!memblock_is_memory(release_phys)) |
---|
155 | | - iounmap(cpu_strt_ptr); |
---|
| 93 | + set_cpu_possible(cpu, true); |
---|
156 | 94 | } |
---|
157 | 95 | } |
---|
158 | 96 | |
---|
159 | 97 | const struct smp_operations sti_smp_ops __initconst = { |
---|
160 | 98 | .smp_prepare_cpus = sti_smp_prepare_cpus, |
---|
161 | | - .smp_secondary_init = sti_secondary_init, |
---|
162 | 99 | .smp_boot_secondary = sti_boot_secondary, |
---|
163 | 100 | }; |
---|