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