1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/delay.h>
19#include <linux/smp.h>
20#include <linux/io.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23
24#include <asm/cacheflush.h>
25#include <asm/smp_plat.h>
26#include <asm/smp_scu.h>
27
28#include "smp.h"
29
30static void write_pen_release(int val)
31{
32 pen_release = val;
33 smp_wmb();
34 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
35 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
36}
37
38static DEFINE_SPINLOCK(boot_lock);
39
40void sti_secondary_init(unsigned int cpu)
41{
42 trace_hardirqs_off();
43
44
45
46
47
48 write_pen_release(-1);
49
50
51
52
53 spin_lock(&boot_lock);
54 spin_unlock(&boot_lock);
55}
56
57int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
58{
59 unsigned long timeout;
60
61
62
63
64
65 spin_lock(&boot_lock);
66
67
68
69
70
71
72
73
74
75 write_pen_release(cpu_logical_map(cpu));
76
77
78
79
80
81 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
82
83 timeout = jiffies + (1 * HZ);
84 while (time_before(jiffies, timeout)) {
85 smp_rmb();
86 if (pen_release == -1)
87 break;
88
89 udelay(10);
90 }
91
92
93
94
95
96 spin_unlock(&boot_lock);
97
98 return pen_release != -1 ? -ENOSYS : 0;
99}
100
101void __init sti_smp_prepare_cpus(unsigned int max_cpus)
102{
103 void __iomem *scu_base = NULL;
104 struct device_node *np = of_find_compatible_node(
105 NULL, NULL, "arm,cortex-a9-scu");
106 if (np) {
107 scu_base = of_iomap(np, 0);
108 scu_enable(scu_base);
109 of_node_put(np);
110 }
111}
112
113struct smp_operations __initdata sti_smp_ops = {
114 .smp_prepare_cpus = sti_smp_prepare_cpus,
115 .smp_secondary_init = sti_secondary_init,
116 .smp_boot_secondary = sti_boot_secondary,
117};
118