Branch data Line data Source code
1 : : /*
2 : : * linux/arch/arm/mach-realview/hotplug.c
3 : : *
4 : : * Copyright (C) 2002 ARM Ltd.
5 : : * All Rights Reserved
6 : : *
7 : : * This program is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU General Public License version 2 as
9 : : * published by the Free Software Foundation.
10 : : */
11 : : #include <linux/kernel.h>
12 : : #include <linux/errno.h>
13 : : #include <linux/smp.h>
14 : :
15 : : #include <asm/smp_plat.h>
16 : : #include <asm/cp15.h>
17 : :
18 : : static inline void cpu_enter_lowpower(void)
19 : : {
20 : : unsigned int v;
21 : :
22 : 0 : asm volatile(
23 : : "mcr p15, 0, %1, c7, c5, 0\n"
24 : : " mcr p15, 0, %1, c7, c10, 4\n"
25 : : /*
26 : : * Turn off coherency
27 : : */
28 : : " mrc p15, 0, %0, c1, c0, 1\n"
29 : : " bic %0, %0, %3\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), "Ir" (0x40)
36 : : : "cc");
37 : : }
38 : :
39 : : static inline void cpu_leave_lowpower(void)
40 : : {
41 : : unsigned int v;
42 : :
43 : 0 : 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, %2\n"
49 : : " mcr p15, 0, %0, c1, c0, 1\n"
50 : : : "=&r" (v)
51 : : : "Ir" (CR_C), "Ir" (0x40)
52 : : : "cc");
53 : : }
54 : :
55 : : static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
56 : : {
57 : : /*
58 : : * there is no power-control hardware on this platform, so all
59 : : * we can do is put the core into WFI; this is safe as the calling
60 : : * code will have already disabled interrupts
61 : : */
62 : : for (;;) {
63 : 0 : wfi();
64 : :
65 [ # # ]: 0 : if (pen_release == cpu_logical_map(cpu)) {
66 : : /*
67 : : * OK, proper wakeup, we're done
68 : : */
69 : : break;
70 : : }
71 : :
72 : : /*
73 : : * Getting here, means that we have come out of WFI without
74 : : * having been woken up - this shouldn't happen
75 : : *
76 : : * Just note it happening - when we're woken, we can report
77 : : * its occurrence.
78 : : */
79 : 0 : (*spurious)++;
80 : : }
81 : : }
82 : :
83 : : /*
84 : : * platform-specific code to shutdown a CPU
85 : : *
86 : : * Called with IRQs disabled
87 : : */
88 : 0 : void __ref vexpress_cpu_die(unsigned int cpu)
89 : : {
90 : : int spurious = 0;
91 : :
92 : : /*
93 : : * we're ready for shutdown now, so do it
94 : : */
95 : : cpu_enter_lowpower();
96 : : platform_do_lowpower(cpu, &spurious);
97 : :
98 : : /*
99 : : * bring this CPU back into the world of cache
100 : : * coherency, and then restore interrupts
101 : : */
102 : : cpu_leave_lowpower();
103 : :
104 [ # # ]: 0 : if (spurious)
105 : 0 : pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
106 : 0 : }
|