1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2002 ARM Ltd. 4 * All Rights Reserved 5 * 6 * This hotplug implementation is _specific_ to the situation found on 7 * ARM development platforms where there is _no_ possibility of actually 8 * taking a CPU offline, resetting it, or otherwise. Real platforms must 9 * NOT copy this code. 10 */ 11 #include <linux/kernel.h> 12 #include <linux/errno.h> 13 #include <linux/smp.h> 14 15 #include <asm/smp_plat.h> 16 #include <asm/cp15.h> 17 18 #include "platsmp.h" 19 20 static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask) 21 { 22 unsigned int v; 23 24 asm volatile( 25 "mcr p15, 0, %1, c7, c5, 0\n" 26 " mcr p15, 0, %1, c7, c10, 4\n" 27 /* 28 * Turn off coherency 29 */ 30 " mrc p15, 0, %0, c1, c0, 1\n" 31 " bic %0, %0, %3\n" 32 " mcr p15, 0, %0, c1, c0, 1\n" 33 " mrc p15, 0, %0, c1, c0, 0\n" 34 " bic %0, %0, %2\n" 35 " mcr p15, 0, %0, c1, c0, 0\n" 36 : "=&r" (v) 37 : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask) 38 : "cc"); 39 } 40 41 static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask) 42 { 43 unsigned int v; 44 45 asm volatile( 46 "mrc p15, 0, %0, c1, c0, 0\n" 47 " orr %0, %0, %1\n" 48 " mcr p15, 0, %0, c1, c0, 0\n" 49 " mrc p15, 0, %0, c1, c0, 1\n" 50 " orr %0, %0, %2\n" 51 " mcr p15, 0, %0, c1, c0, 1\n" 52 : "=&r" (v) 53 : "Ir" (CR_C), "Ir" (actrl_mask) 54 : "cc"); 55 } 56 57 static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious) 58 { 59 /* 60 * there is no power-control hardware on this platform, so all 61 * we can do is put the core into WFI; this is safe as the calling 62 * code will have already disabled interrupts. 63 * 64 * This code should not be used outside Versatile platforms. 65 */ 66 for (;;) { 67 wfi(); 68 69 if (versatile_cpu_release == cpu_logical_map(cpu)) { 70 /* 71 * OK, proper wakeup, we're done 72 */ 73 break; 74 } 75 76 /* 77 * Getting here, means that we have come out of WFI without 78 * having been woken up - this shouldn't happen 79 * 80 * Just note it happening - when we're woken, we can report 81 * its occurrence. 82 */ 83 (*spurious)++; 84 } 85 } 86 87 /* 88 * platform-specific code to shutdown a CPU. 89 * This code supports immitation-style CPU hotplug for Versatile/Realview/ 90 * Versatile Express platforms that are unable to do real CPU hotplug. 91 */ 92 void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask) 93 { 94 int spurious = 0; 95 96 versatile_immitation_enter_lowpower(actrl_mask); 97 versatile_immitation_do_lowpower(cpu, &spurious); 98 versatile_immitation_leave_lowpower(actrl_mask); 99 100 if (spurious) 101 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 102 } 103