1
2
3
4
5
6
7
8
9
10
11#include <linux/kernel.h>
12#include <linux/errno.h>
13#include <linux/smp.h>
14
15#include <asm/cacheflush.h>
16
17static inline void cpu_enter_lowpower(void)
18{
19 unsigned int v;
20
21 flush_cache_all();
22 asm volatile(
23 " mcr p15, 0, %1, c7, c5, 0\n"
24 " mcr p15, 0, %1, c7, c10, 4\n"
25
26
27
28 " mrc p15, 0, %0, c1, c0, 1\n"
29 " bic %0, %0, #0x20\n"
30 " mcr p15, 0, %0, c1, c0, 1\n"
31 " mrc p15, 0, %0, c1, c0, 0\n"
32 " bic %0, %0, %2\n"
33 " mcr p15, 0, %0, c1, c0, 0\n"
34 : "=&r" (v)
35 : "r" (0), "Ir" (CR_C)
36 : "cc");
37}
38
39static inline void cpu_leave_lowpower(void)
40{
41 unsigned int v;
42
43 asm volatile(
44 "mrc p15, 0, %0, c1, c0, 0\n"
45 " orr %0, %0, %1\n"
46 " mcr p15, 0, %0, c1, c0, 0\n"
47 " mrc p15, 0, %0, c1, c0, 1\n"
48 " orr %0, %0, #0x20\n"
49 " mcr p15, 0, %0, c1, c0, 1\n"
50 : "=&r" (v)
51 : "Ir" (CR_C)
52 : "cc");
53}
54
55static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
56{
57
58
59
60
61
62 for (;;) {
63
64
65
66 asm(".word 0xe320f003\n"
67 :
68 :
69 : "memory", "cc");
70
71
72
73
74
75 break;
76
77
78
79
80
81
82
83
84
85 (*spurious)++;
86 }
87}
88
89int platform_cpu_kill(unsigned int cpu)
90{
91 return 1;
92}
93
94
95
96
97
98
99void platform_cpu_die(unsigned int cpu)
100{
101 int spurious = 0;
102
103
104
105
106 cpu_enter_lowpower();
107 platform_do_lowpower(cpu, &spurious);
108
109
110
111
112
113 cpu_leave_lowpower();
114
115 if (spurious)
116 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
117}
118
119int platform_cpu_disable(unsigned int cpu)
120{
121
122
123
124
125 return cpu == 0 ? -EPERM : 0;
126}
127