Skip to content

Commit c00def7

Browse files
linuswolofj
authored andcommitted
ARM: ux500: simplify secondary CPU boot
This removes a lot of ancient cruft from the Ux500 SMP boot. Instead of the pen grab/release, just point the ROM to secondary_boot() and start the second CPU there, then send the IPI. Use our own SMP enable method. This enables us to remove the last static mapping and get both CPUs booting properly. Tested this and it just works. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Olof Johansson <olof@lixom.net>
1 parent 58e00a6 commit c00def7

File tree

5 files changed

+40
-133
lines changed

5 files changed

+40
-133
lines changed

arch/arm/mach-ux500/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
77
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
88
obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \
99
board-mop500-audio.o
10-
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
10+
obj-$(CONFIG_SMP) += platsmp.o
1111
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
1212
obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
1313

arch/arm/mach-ux500/cpu-db8500.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ static const char * stericsson_dt_platform_compat[] = {
154154
};
155155

156156
DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
157-
.smp = smp_ops(ux500_smp_ops),
158157
.map_io = u8500_map_io,
159158
.init_irq = ux500_init_irq,
160159
/* we re-use nomadik timer here */

arch/arm/mach-ux500/headsmp.S

Lines changed: 0 additions & 37 deletions
This file was deleted.

arch/arm/mach-ux500/platsmp.c

Lines changed: 39 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -28,135 +28,81 @@
2828
#include "db8500-regs.h"
2929
#include "id.h"
3030

31-
static void __iomem *scu_base;
32-
static void __iomem *backupram;
33-
34-
/* This is called from headsmp.S to wakeup the secondary core */
35-
extern void u8500_secondary_startup(void);
36-
37-
/*
38-
* Write pen_release in a way that is guaranteed to be visible to all
39-
* observers, irrespective of whether they're taking part in coherency
40-
* or not. This is necessary for the hotplug code to work reliably.
41-
*/
42-
static void write_pen_release(int val)
43-
{
44-
pen_release = val;
45-
smp_wmb();
46-
sync_cache_w(&pen_release);
47-
}
48-
49-
static DEFINE_SPINLOCK(boot_lock);
50-
51-
static void ux500_secondary_init(unsigned int cpu)
52-
{
53-
/*
54-
* let the primary processor know we're out of the
55-
* pen, then head off into the C entry point
56-
*/
57-
write_pen_release(-1);
58-
59-
/*
60-
* Synchronise with the boot thread.
61-
*/
62-
spin_lock(&boot_lock);
63-
spin_unlock(&boot_lock);
64-
}
31+
/* Magic triggers in backup RAM */
32+
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
33+
#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
6534

66-
static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
35+
static void wakeup_secondary(void)
6736
{
68-
unsigned long timeout;
69-
70-
/*
71-
* set synchronisation state between this boot processor
72-
* and the secondary one
73-
*/
74-
spin_lock(&boot_lock);
75-
76-
/*
77-
* The secondary processor is waiting to be released from
78-
* the holding pen - release it, then wait for it to flag
79-
* that it has been released by resetting pen_release.
80-
*/
81-
write_pen_release(cpu_logical_map(cpu));
82-
83-
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
37+
struct device_node *np;
38+
static void __iomem *backupram;
8439

85-
timeout = jiffies + (1 * HZ);
86-
while (time_before(jiffies, timeout)) {
87-
if (pen_release == -1)
88-
break;
40+
np = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
41+
if (!np) {
42+
pr_err("No backupram base address\n");
43+
return;
44+
}
45+
backupram = of_iomap(np, 0);
46+
of_node_put(np);
47+
if (!backupram) {
48+
pr_err("No backupram remap\n");
49+
return;
8950
}
9051

91-
/*
92-
* now the secondary core is starting up let it run its
93-
* calibrations, then wait for it to finish
94-
*/
95-
spin_unlock(&boot_lock);
96-
97-
return pen_release != -1 ? -ENOSYS : 0;
98-
}
99-
100-
static void __init wakeup_secondary(void)
101-
{
10252
/*
10353
* write the address of secondary startup into the backup ram register
10454
* at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
10555
* backup ram register at offset 0x1FF0, which is what boot rom code
106-
* is waiting for. This would wake up the secondary core from WFE
56+
* is waiting for. This will wake up the secondary core from WFE.
10757
*/
108-
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
109-
__raw_writel(virt_to_phys(u8500_secondary_startup),
110-
backupram + UX500_CPU1_JUMPADDR_OFFSET);
111-
112-
#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
113-
__raw_writel(0xA1FEED01,
114-
backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
58+
writel(virt_to_phys(secondary_startup),
59+
backupram + UX500_CPU1_JUMPADDR_OFFSET);
60+
writel(0xA1FEED01,
61+
backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
11562

11663
/* make sure write buffer is drained */
11764
mb();
65+
iounmap(backupram);
11866
}
11967

120-
/*
121-
* Initialise the CPU possible map early - this describes the CPUs
122-
* which may be present or become present in the system.
123-
*/
124-
static void __init ux500_smp_init_cpus(void)
68+
static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
12569
{
126-
unsigned int i, ncores;
12770
struct device_node *np;
71+
static void __iomem *scu_base;
72+
unsigned int ncores;
73+
int i;
12874

12975
np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
76+
if (!np) {
77+
pr_err("No SCU base address\n");
78+
return;
79+
}
13080
scu_base = of_iomap(np, 0);
13181
of_node_put(np);
132-
if (!scu_base)
82+
if (!scu_base) {
83+
pr_err("No SCU remap\n");
13384
return;
134-
backupram = ioremap(U8500_BACKUPRAM0_BASE, SZ_8K);
135-
ncores = scu_get_core_count(scu_base);
136-
137-
/* sanity check */
138-
if (ncores > nr_cpu_ids) {
139-
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
140-
ncores, nr_cpu_ids);
141-
ncores = nr_cpu_ids;
14285
}
14386

87+
scu_enable(scu_base);
88+
ncores = scu_get_core_count(scu_base);
14489
for (i = 0; i < ncores; i++)
14590
set_cpu_possible(i, true);
91+
iounmap(scu_base);
14692
}
14793

148-
static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
94+
static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
14995
{
150-
scu_enable(scu_base);
15196
wakeup_secondary();
97+
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
98+
return 0;
15299
}
153100

154101
struct smp_operations ux500_smp_ops __initdata = {
155-
.smp_init_cpus = ux500_smp_init_cpus,
156102
.smp_prepare_cpus = ux500_smp_prepare_cpus,
157-
.smp_secondary_init = ux500_secondary_init,
158103
.smp_boot_secondary = ux500_boot_secondary,
159104
#ifdef CONFIG_HOTPLUG_CPU
160105
.cpu_die = ux500_cpu_die,
161106
#endif
162107
};
108+
CPU_METHOD_OF_DECLARE(ux500_smp, "ste,dbx500-smp", &ux500_smp_ops);

arch/arm/mach-ux500/setup.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ extern struct device *ux500_soc_device_init(const char *soc_id);
2626

2727
extern void ux500_timer_init(void);
2828

29-
extern struct smp_operations ux500_smp_ops;
3029
extern void ux500_cpu_die(unsigned int cpu);
3130

3231
#endif /* __ASM_ARCH_SETUP_H */

0 commit comments

Comments
 (0)