uboot/arch/arm/cpu/armv8/fwcall.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/**
   3 * (C) Copyright 2014, Cavium Inc.
   4 * (C) Copyright 2017, Xilinx Inc.
   5 *
   6**/
   7
   8#include <asm-offsets.h>
   9#include <config.h>
  10#include <asm/cache.h>
  11#include <asm/macro.h>
  12#include <asm/psci.h>
  13#include <asm/ptrace.h>
  14#include <asm/system.h>
  15
  16/*
  17 * Issue the hypervisor call
  18 *
  19 * x0~x7: input arguments
  20 * x0~x3: output arguments
  21 */
  22static void hvc_call(struct pt_regs *args)
  23{
  24        asm volatile(
  25                "ldr x0, %0\n"
  26                "ldr x1, %1\n"
  27                "ldr x2, %2\n"
  28                "ldr x3, %3\n"
  29                "ldr x4, %4\n"
  30                "ldr x5, %5\n"
  31                "ldr x6, %6\n"
  32                "hvc    #0\n"
  33                "str x0, %0\n"
  34                "str x1, %1\n"
  35                "str x2, %2\n"
  36                "str x3, %3\n"
  37                : "+m" (args->regs[0]), "+m" (args->regs[1]),
  38                  "+m" (args->regs[2]), "+m" (args->regs[3])
  39                : "m" (args->regs[4]), "m" (args->regs[5]),
  40                  "m" (args->regs[6])
  41                : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
  42                  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
  43                  "x16", "x17");
  44}
  45
  46/*
  47 * void smc_call(arg0, arg1...arg7)
  48 *
  49 * issue the secure monitor call
  50 *
  51 * x0~x7: input arguments
  52 * x0~x3: output arguments
  53 */
  54
  55void smc_call(struct pt_regs *args)
  56{
  57        asm volatile(
  58                "ldr x0, %0\n"
  59                "ldr x1, %1\n"
  60                "ldr x2, %2\n"
  61                "ldr x3, %3\n"
  62                "ldr x4, %4\n"
  63                "ldr x5, %5\n"
  64                "ldr x6, %6\n"
  65                "smc    #0\n"
  66                "str x0, %0\n"
  67                "str x1, %1\n"
  68                "str x2, %2\n"
  69                "str x3, %3\n"
  70                : "+m" (args->regs[0]), "+m" (args->regs[1]),
  71                  "+m" (args->regs[2]), "+m" (args->regs[3])
  72                : "m" (args->regs[4]), "m" (args->regs[5]),
  73                  "m" (args->regs[6])
  74                : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
  75                  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
  76                  "x16", "x17");
  77}
  78
  79/*
  80 * For now, all systems we support run at least in EL2 and thus
  81 * trigger PSCI calls to EL3 using SMC. If anyone ever wants to
  82 * use PSCI on U-Boot running below a hypervisor, please detect
  83 * this and set the flag accordingly.
  84 */
  85static const bool use_smc_for_psci = true;
  86
  87void __noreturn psci_system_reset(void)
  88{
  89        struct pt_regs regs;
  90
  91        regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET;
  92
  93        if (use_smc_for_psci)
  94                smc_call(&regs);
  95        else
  96                hvc_call(&regs);
  97
  98        while (1)
  99                ;
 100}
 101
 102void __noreturn psci_system_reset2(u32 reset_level, u32 cookie)
 103{
 104        struct pt_regs regs;
 105
 106        regs.regs[0] = ARM_PSCI_1_1_FN64_SYSTEM_RESET2;
 107        regs.regs[1] = PSCI_RESET2_TYPE_VENDOR | reset_level;
 108        regs.regs[2] = cookie;
 109        if (use_smc_for_psci)
 110                smc_call(&regs);
 111        else
 112                hvc_call(&regs);
 113
 114        while (1)
 115                ;
 116}
 117
 118void __noreturn psci_system_off(void)
 119{
 120        struct pt_regs regs;
 121
 122        regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF;
 123
 124        if (use_smc_for_psci)
 125                smc_call(&regs);
 126        else
 127                hvc_call(&regs);
 128
 129        while (1)
 130                ;
 131}
 132