Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/arch/arm/mach-spear13xx/hotplug.c
0004  *
0005  * Copyright (C) 2012 ST Microelectronics Ltd.
0006  * Deepak Sikri <deepak.sikri@st.com>
0007  *
0008  * based upon linux/arch/arm/mach-realview/hotplug.c
0009  */
0010 #include <linux/kernel.h>
0011 #include <linux/errno.h>
0012 #include <linux/smp.h>
0013 #include <asm/cp15.h>
0014 #include <asm/smp_plat.h>
0015 
0016 #include "generic.h"
0017 
0018 static inline void cpu_enter_lowpower(void)
0019 {
0020     unsigned int v;
0021 
0022     asm volatile(
0023     "   mcr p15, 0, %1, c7, c5, 0\n"
0024     "   dsb\n"
0025     /*
0026      * Turn off coherency
0027      */
0028     "   mrc p15, 0, %0, c1, c0, 1\n"
0029     "   bic %0, %0, #0x20\n"
0030     "   mcr p15, 0, %0, c1, c0, 1\n"
0031     "   mrc p15, 0, %0, c1, c0, 0\n"
0032     "   bic %0, %0, %2\n"
0033     "   mcr p15, 0, %0, c1, c0, 0\n"
0034     : "=&r" (v)
0035     : "r" (0), "Ir" (CR_C)
0036     : "cc", "memory");
0037 }
0038 
0039 static inline void cpu_leave_lowpower(void)
0040 {
0041     unsigned int v;
0042 
0043     asm volatile("mrc   p15, 0, %0, c1, c0, 0\n"
0044     "   orr %0, %0, %1\n"
0045     "   mcr p15, 0, %0, c1, c0, 0\n"
0046     "   mrc p15, 0, %0, c1, c0, 1\n"
0047     "   orr %0, %0, #0x20\n"
0048     "   mcr p15, 0, %0, c1, c0, 1\n"
0049     : "=&r" (v)
0050     : "Ir" (CR_C)
0051     : "cc");
0052 }
0053 
0054 static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
0055 {
0056     for (;;) {
0057         wfi();
0058 
0059         if (spear_pen_release == cpu) {
0060             /*
0061              * OK, proper wakeup, we're done
0062              */
0063             break;
0064         }
0065 
0066         /*
0067          * Getting here, means that we have come out of WFI without
0068          * having been woken up - this shouldn't happen
0069          *
0070          * Just note it happening - when we're woken, we can report
0071          * its occurrence.
0072          */
0073         (*spurious)++;
0074     }
0075 }
0076 
0077 /*
0078  * platform-specific code to shutdown a CPU
0079  *
0080  * Called with IRQs disabled
0081  */
0082 void spear13xx_cpu_die(unsigned int cpu)
0083 {
0084     int spurious = 0;
0085 
0086     /*
0087      * we're ready for shutdown now, so do it
0088      */
0089     cpu_enter_lowpower();
0090     spear13xx_do_lowpower(cpu, &spurious);
0091 
0092     /*
0093      * bring this CPU back into the world of cache
0094      * coherency, and then restore interrupts
0095      */
0096     cpu_leave_lowpower();
0097 
0098     if (spurious)
0099         pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
0100 }