Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2002 ARM Ltd.
0004  *  All Rights Reserved
0005  *
0006  * This hotplug implementation is _specific_ to the situation found on
0007  * ARM development platforms where there is _no_ possibility of actually
0008  * taking a CPU offline, resetting it, or otherwise.  Real platforms must
0009  * NOT copy this code.
0010  */
0011 #include <linux/kernel.h>
0012 #include <linux/errno.h>
0013 #include <linux/smp.h>
0014 
0015 #include <asm/smp_plat.h>
0016 #include <asm/cp15.h>
0017 
0018 #include "platsmp.h"
0019 
0020 static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
0021 {
0022     unsigned int v;
0023 
0024     asm volatile(
0025         "mcr    p15, 0, %1, c7, c5, 0\n"
0026     "   mcr p15, 0, %1, c7, c10, 4\n"
0027     /*
0028      * Turn off coherency
0029      */
0030     "   mrc p15, 0, %0, c1, c0, 1\n"
0031     "   bic %0, %0, %3\n"
0032     "   mcr p15, 0, %0, c1, c0, 1\n"
0033     "   mrc p15, 0, %0, c1, c0, 0\n"
0034     "   bic %0, %0, %2\n"
0035     "   mcr p15, 0, %0, c1, c0, 0\n"
0036       : "=&r" (v)
0037       : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
0038       : "cc");
0039 }
0040 
0041 static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
0042 {
0043     unsigned int v;
0044 
0045     asm volatile(
0046         "mrc    p15, 0, %0, c1, c0, 0\n"
0047     "   orr %0, %0, %1\n"
0048     "   mcr p15, 0, %0, c1, c0, 0\n"
0049     "   mrc p15, 0, %0, c1, c0, 1\n"
0050     "   orr %0, %0, %2\n"
0051     "   mcr p15, 0, %0, c1, c0, 1\n"
0052       : "=&r" (v)
0053       : "Ir" (CR_C), "Ir" (actrl_mask)
0054       : "cc");
0055 }
0056 
0057 static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
0058 {
0059     /*
0060      * there is no power-control hardware on this platform, so all
0061      * we can do is put the core into WFI; this is safe as the calling
0062      * code will have already disabled interrupts.
0063      *
0064      * This code should not be used outside Versatile platforms.
0065      */
0066     for (;;) {
0067         wfi();
0068 
0069         if (versatile_cpu_release == cpu_logical_map(cpu)) {
0070             /*
0071              * OK, proper wakeup, we're done
0072              */
0073             break;
0074         }
0075 
0076         /*
0077          * Getting here, means that we have come out of WFI without
0078          * having been woken up - this shouldn't happen
0079          *
0080          * Just note it happening - when we're woken, we can report
0081          * its occurrence.
0082          */
0083         (*spurious)++;
0084     }
0085 }
0086 
0087 /*
0088  * platform-specific code to shutdown a CPU.
0089  * This code supports immitation-style CPU hotplug for Versatile/Realview/
0090  * Versatile Express platforms that are unable to do real CPU hotplug.
0091  */
0092 void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
0093 {
0094     int spurious = 0;
0095 
0096     versatile_immitation_enter_lowpower(actrl_mask);
0097     versatile_immitation_do_lowpower(cpu, &spurious);
0098     versatile_immitation_leave_lowpower(actrl_mask);
0099 
0100     if (spurious)
0101         pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
0102 }