1/* linux arch/arm/mach-exynos4/hotplug.c 2 * 3 * Cloned from linux/arch/arm/mach-realview/hotplug.c 4 * 5 * Copyright (C) 2002 ARM Ltd. 6 * All Rights Reserved 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11*/ 12 13#include <linux/kernel.h> 14#include <linux/errno.h> 15#include <linux/smp.h> 16#include <linux/io.h> 17 18#include <asm/cacheflush.h> 19#include <asm/cp15.h> 20#include <asm/smp_plat.h> 21 22#include <mach/regs-pmu.h> 23 24extern volatile int pen_release; 25 26static inline void cpu_enter_lowpower(void) 27{ 28 unsigned int v; 29 30 flush_cache_all(); 31 asm volatile( 32 " mcr p15, 0, %1, c7, c5, 0\n" 33 " mcr p15, 0, %1, c7, c10, 4\n" 34 /* 35 * Turn off coherency 36 */ 37 " mrc p15, 0, %0, c1, c0, 1\n" 38 " bic %0, %0, %3\n" 39 " mcr p15, 0, %0, c1, c0, 1\n" 40 " mrc p15, 0, %0, c1, c0, 0\n" 41 " bic %0, %0, %2\n" 42 " mcr p15, 0, %0, c1, c0, 0\n" 43 : "=&r" (v) 44 : "r" (0), "Ir" (CR_C), "Ir" (0x40) 45 : "cc"); 46} 47 48static inline void cpu_leave_lowpower(void) 49{ 50 unsigned int v; 51 52 asm volatile( 53 "mrc p15, 0, %0, c1, c0, 0\n" 54 " orr %0, %0, %1\n" 55 " mcr p15, 0, %0, c1, c0, 0\n" 56 " mrc p15, 0, %0, c1, c0, 1\n" 57 " orr %0, %0, %2\n" 58 " mcr p15, 0, %0, c1, c0, 1\n" 59 : "=&r" (v) 60 : "Ir" (CR_C), "Ir" (0x40) 61 : "cc"); 62} 63 64static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 65{ 66 for (;;) { 67 68 /* make cpu1 to be turned off at next WFI command */ 69 if (cpu == 1) 70 __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION); 71 72 /* 73 * here's the WFI 74 */ 75 asm(".word 0xe320f003\n" 76 : 77 : 78 : "memory", "cc"); 79 80 if (pen_release == cpu_logical_map(cpu)) { 81 /* 82 * OK, proper wakeup, we're done 83 */ 84 break; 85 } 86 87 /* 88 * Getting here, means that we have come out of WFI without 89 * having been woken up - this shouldn't happen 90 * 91 * Just note it happening - when we're woken, we can report 92 * its occurrence. 93 */ 94 (*spurious)++; 95 } 96} 97 98int platform_cpu_kill(unsigned int cpu) 99{ 100 return 1; 101} 102 103/* 104 * platform-specific code to shutdown a CPU 105 * 106 * Called with IRQs disabled 107 */ 108void platform_cpu_die(unsigned int cpu) 109{ 110 int spurious = 0; 111 112 /* 113 * we're ready for shutdown now, so do it 114 */ 115 cpu_enter_lowpower(); 116 platform_do_lowpower(cpu, &spurious); 117 118 /* 119 * bring this CPU back into the world of cache 120 * coherency, and then restore interrupts 121 */ 122 cpu_leave_lowpower(); 123 124 if (spurious) 125 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 126} 127 128int platform_cpu_disable(unsigned int cpu) 129{ 130 /* 131 * we don't allow CPU 0 to be shutdown (it is still too special 132 * e.g. clock tick interrupts) 133 */ 134 return cpu == 0 ? -EPERM : 0; 135} 136