]>
Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
e3978dc7 VK |
2 | /* |
3 | * linux/arch/arm/mach-spear13xx/hotplug.c | |
4 | * | |
5 | * Copyright (C) 2012 ST Microelectronics Ltd. | |
6 | * Deepak Sikri <deepak.sikri@st.com> | |
7 | * | |
8 | * based upon linux/arch/arm/mach-realview/hotplug.c | |
e3978dc7 VK |
9 | */ |
10 | #include <linux/kernel.h> | |
11 | #include <linux/errno.h> | |
12 | #include <linux/smp.h> | |
e3978dc7 VK |
13 | #include <asm/cp15.h> |
14 | #include <asm/smp_plat.h> | |
15 | ||
6213f70e RK |
16 | #include "generic.h" |
17 | ||
e3978dc7 VK |
18 | static inline void cpu_enter_lowpower(void) |
19 | { | |
20 | unsigned int v; | |
21 | ||
e3978dc7 VK |
22 | asm volatile( |
23 | " mcr p15, 0, %1, c7, c5, 0\n" | |
24 | " dsb\n" | |
25 | /* | |
26 | * Turn off coherency | |
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", "memory"); | |
37 | } | |
38 | ||
39 | static inline void cpu_leave_lowpower(void) | |
40 | { | |
41 | unsigned int v; | |
42 | ||
43 | asm volatile("mrc p15, 0, %0, c1, c0, 0\n" | |
44 | " orr %0, %0, %1\n" | |
45 | " mcr p15, 0, %0, c1, c0, 0\n" | |
46 | " mrc p15, 0, %0, c1, c0, 1\n" | |
47 | " orr %0, %0, #0x20\n" | |
48 | " mcr p15, 0, %0, c1, c0, 1\n" | |
49 | : "=&r" (v) | |
50 | : "Ir" (CR_C) | |
51 | : "cc"); | |
52 | } | |
53 | ||
2d8b21d9 | 54 | static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious) |
e3978dc7 VK |
55 | { |
56 | for (;;) { | |
57 | wfi(); | |
58 | ||
6213f70e | 59 | if (spear_pen_release == cpu) { |
e3978dc7 VK |
60 | /* |
61 | * OK, proper wakeup, we're done | |
62 | */ | |
63 | break; | |
64 | } | |
65 | ||
66 | /* | |
67 | * Getting here, means that we have come out of WFI without | |
68 | * having been woken up - this shouldn't happen | |
69 | * | |
70 | * Just note it happening - when we're woken, we can report | |
71 | * its occurrence. | |
72 | */ | |
73 | (*spurious)++; | |
74 | } | |
75 | } | |
76 | ||
e3978dc7 VK |
77 | /* |
78 | * platform-specific code to shutdown a CPU | |
79 | * | |
80 | * Called with IRQs disabled | |
81 | */ | |
b96fc2f3 | 82 | void spear13xx_cpu_die(unsigned int cpu) |
e3978dc7 VK |
83 | { |
84 | int spurious = 0; | |
85 | ||
86 | /* | |
87 | * we're ready for shutdown now, so do it | |
88 | */ | |
89 | cpu_enter_lowpower(); | |
2d8b21d9 | 90 | spear13xx_do_lowpower(cpu, &spurious); |
e3978dc7 VK |
91 | |
92 | /* | |
93 | * bring this CPU back into the world of cache | |
94 | * coherency, and then restore interrupts | |
95 | */ | |
96 | cpu_leave_lowpower(); | |
97 | ||
98 | if (spurious) | |
99 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | |
100 | } |