#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h>
#include "generic.h"
static inline void cpu_enter_lowpower(void)
{
unsigned int v;
asm volatile(
" mcr p15, 0, %1, c7, c5, 0\n"
" dsb\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" bic %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, %2\n"
" mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v)
: "r" (0), "Ir" (CR_C)
: "cc", "memory");
}
static inline void cpu_leave_lowpower(void)
{
unsigned int v;
asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
" orr %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (CR_C)
: "cc");
}
static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
{
for (;;) {
wfi();
if (spear_pen_release == cpu) {
break;
}
(*spurious)++;
}
}
void spear13xx_cpu_die(unsigned int cpu)
{
int spurious = 0;
cpu_enter_lowpower();
spear13xx_do_lowpower(cpu, &spurious);
cpu_leave_lowpower();
if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}