/* linux arch/arm/mach-exynos4/hotplug.c1*2* Cloned from linux/arch/arm/mach-realview/hotplug.c3*4* Copyright (C) 2002 ARM Ltd.5* All Rights Reserved6*7* This program is free software; you can redistribute it and/or modify8* it under the terms of the GNU General Public License version 2 as9* published by the Free Software Foundation.10*/1112#include <linux/kernel.h>13#include <linux/errno.h>14#include <linux/smp.h>1516#include <asm/cacheflush.h>1718extern volatile int pen_release;1920static inline void cpu_enter_lowpower(void)21{22unsigned int v;2324flush_cache_all();25asm volatile(26" mcr p15, 0, %1, c7, c5, 0\n"27" mcr p15, 0, %1, c7, c10, 4\n"28/*29* Turn off coherency30*/31" mrc p15, 0, %0, c1, c0, 1\n"32" bic %0, %0, %3\n"33" mcr p15, 0, %0, c1, c0, 1\n"34" mrc p15, 0, %0, c1, c0, 0\n"35" bic %0, %0, %2\n"36" mcr p15, 0, %0, c1, c0, 0\n"37: "=&r" (v)38: "r" (0), "Ir" (CR_C), "Ir" (0x40)39: "cc");40}4142static inline void cpu_leave_lowpower(void)43{44unsigned int v;4546asm volatile(47"mrc p15, 0, %0, c1, c0, 0\n"48" orr %0, %0, %1\n"49" mcr p15, 0, %0, c1, c0, 0\n"50" mrc p15, 0, %0, c1, c0, 1\n"51" orr %0, %0, %2\n"52" mcr p15, 0, %0, c1, c0, 1\n"53: "=&r" (v)54: "Ir" (CR_C), "Ir" (0x40)55: "cc");56}5758static inline void platform_do_lowpower(unsigned int cpu, int *spurious)59{60/*61* there is no power-control hardware on this platform, so all62* we can do is put the core into WFI; this is safe as the calling63* code will have already disabled interrupts64*/65for (;;) {66/*67* here's the WFI68*/69asm(".word 0xe320f003\n"70:71:72: "memory", "cc");7374if (pen_release == cpu) {75/*76* OK, proper wakeup, we're done77*/78break;79}8081/*82* Getting here, means that we have come out of WFI without83* having been woken up - this shouldn't happen84*85* Just note it happening - when we're woken, we can report86* its occurrence.87*/88(*spurious)++;89}90}9192int platform_cpu_kill(unsigned int cpu)93{94return 1;95}9697/*98* platform-specific code to shutdown a CPU99*100* Called with IRQs disabled101*/102void platform_cpu_die(unsigned int cpu)103{104int spurious = 0;105106/*107* we're ready for shutdown now, so do it108*/109cpu_enter_lowpower();110platform_do_lowpower(cpu, &spurious);111112/*113* bring this CPU back into the world of cache114* coherency, and then restore interrupts115*/116cpu_leave_lowpower();117118if (spurious)119pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);120}121122int platform_cpu_disable(unsigned int cpu)123{124/*125* we don't allow CPU 0 to be shutdown (it is still too special126* e.g. clock tick interrupts)127*/128return cpu == 0 ? -EPERM : 0;129}130131132