linux/arch/arm/plat-versatile/hotplug.c
<<
>>
Prefs
   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 <plat/platsmp.h>
  19
  20static 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
  41static 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
  57static 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 */
  92void 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