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