Merge tag 'jfs-5.2' of git://github.com/kleikamp/linux-shaggy
[linux-2.6-microblaze.git] / arch / arm / plat-versatile / hotplug.c
1 /*
2  *  Copyright (C) 2002 ARM Ltd.
3  *  All Rights Reserved
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This hotplug implementation is _specific_ to the situation found on
10  * ARM development platforms where there is _no_ possibility of actually
11  * taking a CPU offline, resetting it, or otherwise.  Real platforms must
12  * NOT copy this code.
13  */
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/smp.h>
17
18 #include <asm/smp_plat.h>
19 #include <asm/cp15.h>
20
21 #include <plat/platsmp.h>
22
23 static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
24 {
25         unsigned int v;
26
27         asm volatile(
28                 "mcr    p15, 0, %1, c7, c5, 0\n"
29         "       mcr     p15, 0, %1, c7, c10, 4\n"
30         /*
31          * Turn off coherency
32          */
33         "       mrc     p15, 0, %0, c1, c0, 1\n"
34         "       bic     %0, %0, %3\n"
35         "       mcr     p15, 0, %0, c1, c0, 1\n"
36         "       mrc     p15, 0, %0, c1, c0, 0\n"
37         "       bic     %0, %0, %2\n"
38         "       mcr     p15, 0, %0, c1, c0, 0\n"
39           : "=&r" (v)
40           : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
41           : "cc");
42 }
43
44 static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
45 {
46         unsigned int v;
47
48         asm volatile(
49                 "mrc    p15, 0, %0, c1, c0, 0\n"
50         "       orr     %0, %0, %1\n"
51         "       mcr     p15, 0, %0, c1, c0, 0\n"
52         "       mrc     p15, 0, %0, c1, c0, 1\n"
53         "       orr     %0, %0, %2\n"
54         "       mcr     p15, 0, %0, c1, c0, 1\n"
55           : "=&r" (v)
56           : "Ir" (CR_C), "Ir" (actrl_mask)
57           : "cc");
58 }
59
60 static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
61 {
62         /*
63          * there is no power-control hardware on this platform, so all
64          * we can do is put the core into WFI; this is safe as the calling
65          * code will have already disabled interrupts.
66          *
67          * This code should not be used outside Versatile platforms.
68          */
69         for (;;) {
70                 wfi();
71
72                 if (versatile_cpu_release == cpu_logical_map(cpu)) {
73                         /*
74                          * OK, proper wakeup, we're done
75                          */
76                         break;
77                 }
78
79                 /*
80                  * Getting here, means that we have come out of WFI without
81                  * having been woken up - this shouldn't happen
82                  *
83                  * Just note it happening - when we're woken, we can report
84                  * its occurrence.
85                  */
86                 (*spurious)++;
87         }
88 }
89
90 /*
91  * platform-specific code to shutdown a CPU.
92  * This code supports immitation-style CPU hotplug for Versatile/Realview/
93  * Versatile Express platforms that are unable to do real CPU hotplug.
94  */
95 void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
96 {
97         int spurious = 0;
98
99         versatile_immitation_enter_lowpower(actrl_mask);
100         versatile_immitation_do_lowpower(cpu, &spurious);
101         versatile_immitation_leave_lowpower(actrl_mask);
102
103         if (spurious)
104                 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
105 }