#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <asm/smp_plat.h>
#include <asm/cp15.h>
#include "platsmp.h"
static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
{
unsigned int v;
asm volatile(
"mcr p15, 0, %1, c7, c5, 0\n"
" mcr p15, 0, %1, c7, c10, 4\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" bic %0, %0, %3\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), "Ir" (actrl_mask)
: "cc");
}
static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
{
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, %2\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (CR_C), "Ir" (actrl_mask)
: "cc");
}
static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
{
for (;;) {
wfi();
if (versatile_cpu_release == cpu_logical_map(cpu)) {
break;
}
(*spurious)++;
}
}
void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
{
int spurious = 0;
versatile_immitation_enter_lowpower(actrl_mask);
versatile_immitation_do_lowpower(cpu, &spurious);
versatile_immitation_leave_lowpower(actrl_mask);
if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}