| .. | .. |
|---|
| 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_RAW_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 | | - raw_spin_lock(&boot_lock); |
|---|
| 52 | | - raw_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 | | - raw_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 | | - raw_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 | }; |
|---|