1
2
3
4
5
6
7
8
9#include <linux/init.h>
10#include <linux/smp.h>
11#include <linux/delay.h>
12#include <linux/of.h>
13#include <linux/of_address.h>
14#include <asm/page.h>
15#include <asm/mach/map.h>
16#include <asm/smp_plat.h>
17#include <asm/smp_scu.h>
18#include <asm/cacheflush.h>
19#include <asm/cputype.h>
20
21#include "common.h"
22
23static void __iomem *clk_base;
24
25static DEFINE_SPINLOCK(boot_lock);
26
27
28volatile int prima2_pen_release = -1;
29
30static void sirfsoc_secondary_init(unsigned int cpu)
31{
32
33
34
35
36 prima2_pen_release = -1;
37 smp_wmb();
38
39
40
41
42 spin_lock(&boot_lock);
43 spin_unlock(&boot_lock);
44}
45
46static const struct of_device_id clk_ids[] = {
47 { .compatible = "sirf,atlas7-clkc" },
48 {},
49};
50
51static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
52{
53 unsigned long timeout;
54 struct device_node *np;
55
56 np = of_find_matching_node(NULL, clk_ids);
57 if (!np)
58 return -ENODEV;
59
60 clk_base = of_iomap(np, 0);
61 if (!clk_base)
62 return -ENOMEM;
63
64
65
66
67
68
69
70#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2bc
71 __raw_writel(__pa_symbol(sirfsoc_secondary_startup),
72 clk_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
73
74#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x2b8
75 __raw_writel(0x3CAF5D62,
76 clk_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
77
78
79 mb();
80
81 spin_lock(&boot_lock);
82
83
84
85
86
87
88
89
90
91 prima2_pen_release = cpu_logical_map(cpu);
92 sync_cache_w(&prima2_pen_release);
93
94
95
96
97
98 dsb_sev();
99
100 timeout = jiffies + (1 * HZ);
101 while (time_before(jiffies, timeout)) {
102 smp_rmb();
103 if (prima2_pen_release == -1)
104 break;
105
106 udelay(10);
107 }
108
109
110
111
112
113 spin_unlock(&boot_lock);
114
115 return prima2_pen_release != -1 ? -ENOSYS : 0;
116}
117
118const struct smp_operations sirfsoc_smp_ops __initconst = {
119 .smp_secondary_init = sirfsoc_secondary_init,
120 .smp_boot_secondary = sirfsoc_boot_secondary,
121#ifdef CONFIG_HOTPLUG_CPU
122 .cpu_die = sirfsoc_cpu_die,
123#endif
124};
125