0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/errno.h>
0013 #include <linux/smp.h>
0014
0015 #include <asm/smp_plat.h>
0016 #include <asm/cp15.h>
0017
0018 #include "platsmp.h"
0019
0020 static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
0021 {
0022 unsigned int v;
0023
0024 asm volatile(
0025 "mcr p15, 0, %1, c7, c5, 0\n"
0026 " mcr p15, 0, %1, c7, c10, 4\n"
0027
0028
0029
0030 " mrc p15, 0, %0, c1, c0, 1\n"
0031 " bic %0, %0, %3\n"
0032 " mcr p15, 0, %0, c1, c0, 1\n"
0033 " mrc p15, 0, %0, c1, c0, 0\n"
0034 " bic %0, %0, %2\n"
0035 " mcr p15, 0, %0, c1, c0, 0\n"
0036 : "=&r" (v)
0037 : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
0038 : "cc");
0039 }
0040
0041 static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
0042 {
0043 unsigned int v;
0044
0045 asm volatile(
0046 "mrc p15, 0, %0, c1, c0, 0\n"
0047 " orr %0, %0, %1\n"
0048 " mcr p15, 0, %0, c1, c0, 0\n"
0049 " mrc p15, 0, %0, c1, c0, 1\n"
0050 " orr %0, %0, %2\n"
0051 " mcr p15, 0, %0, c1, c0, 1\n"
0052 : "=&r" (v)
0053 : "Ir" (CR_C), "Ir" (actrl_mask)
0054 : "cc");
0055 }
0056
0057 static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
0058 {
0059
0060
0061
0062
0063
0064
0065
0066 for (;;) {
0067 wfi();
0068
0069 if (versatile_cpu_release == cpu_logical_map(cpu)) {
0070
0071
0072
0073 break;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083 (*spurious)++;
0084 }
0085 }
0086
0087
0088
0089
0090
0091
0092 void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
0093 {
0094 int spurious = 0;
0095
0096 versatile_immitation_enter_lowpower(actrl_mask);
0097 versatile_immitation_do_lowpower(cpu, &spurious);
0098 versatile_immitation_leave_lowpower(actrl_mask);
0099
0100 if (spurious)
0101 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
0102 }