1 /* 2 * Copyright 2011 Freescale Semiconductor, Inc. 3 * Copyright 2011 Linaro Ltd. 4 * 5 * The code contained herein is licensed under the GNU General Public 6 * License. You may obtain a copy of the GNU General Public License 7 * Version 2 or later at the following locations: 8 * 9 * http://www.opensource.org/licenses/gpl-license.html 10 * http://www.gnu.org/copyleft/gpl.html 11 */ 12 13 #include <linux/errno.h> 14 #include <asm/cp15.h> 15 16 #include "common.h" 17 18 static inline void cpu_enter_lowpower(void) 19 { 20 unsigned int v; 21 22 asm volatile( 23 "mcr p15, 0, %1, c7, c5, 0\n" 24 " mcr p15, 0, %1, c7, c10, 4\n" 25 /* 26 * Turn off coherency 27 */ 28 " mrc p15, 0, %0, c1, c0, 1\n" 29 " bic %0, %0, %3\n" 30 " mcr p15, 0, %0, c1, c0, 1\n" 31 " mrc p15, 0, %0, c1, c0, 0\n" 32 " bic %0, %0, %2\n" 33 " mcr p15, 0, %0, c1, c0, 0\n" 34 : "=&r" (v) 35 : "r" (0), "Ir" (CR_C), "Ir" (0x40) 36 : "cc"); 37 } 38 39 /* 40 * platform-specific code to shutdown a CPU 41 * 42 * Called with IRQs disabled 43 */ 44 void imx_cpu_die(unsigned int cpu) 45 { 46 cpu_enter_lowpower(); 47 /* 48 * We use the cpu jumping argument register to sync with 49 * imx_cpu_kill() which is running on cpu0 and waiting for 50 * the register being cleared to kill the cpu. 51 */ 52 imx_set_cpu_arg(cpu, ~0); 53 cpu_do_idle(); 54 } 55 56 int imx_cpu_kill(unsigned int cpu) 57 { 58 unsigned long timeout = jiffies + msecs_to_jiffies(50); 59 60 while (imx_get_cpu_arg(cpu) == 0) 61 if (time_after(jiffies, timeout)) 62 return 0; 63 imx_enable_cpu(cpu, false); 64 imx_set_cpu_arg(cpu, 0); 65 return 1; 66 } 67