// Copyright 2017 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <inttypes.h>
#include <string.h>
#include <trace.h>
#include <zircon/boot/driver-config.h>

#include <arch/arm64/smccc.h>
#include <dev/psci.h>
#include <pdev/driver.h>

#define LOCAL_TRACE 0

static uint64_t shutdown_args[3] = {0, 0, 0};
static uint64_t reboot_args[3] = {0, 0, 0};
static uint64_t reboot_bootloader_args[3] = {0, 0, 0};
static uint64_t reboot_recovery_args[3] = {0, 0, 0};
static uint32_t reset_command = PSCI64_SYSTEM_RESET;

static uint64_t psci_smc_call(uint32_t function, uint64_t arg0, uint64_t arg1, uint64_t arg2) {
  return arm_smccc_smc(function, arg0, arg1, arg2, 0, 0, 0, 0).x0;
}

static uint64_t psci_hvc_call(uint32_t function, uint64_t arg0, uint64_t arg1, uint64_t arg2) {
  return arm_smccc_hvc(function, arg0, arg1, arg2, 0, 0, 0, 0).x0;
}

typedef uint64_t (*psci_call_proc)(uint32_t function, uint64_t arg0, uint64_t arg1, uint64_t arg2);

static psci_call_proc do_psci_call = psci_smc_call;

void psci_system_off() {
  do_psci_call(PSCI64_SYSTEM_OFF, shutdown_args[0], shutdown_args[1], shutdown_args[2]);
}

uint32_t psci_get_version() { return (uint32_t)do_psci_call(PSCI64_PSCI_VERSION, 0, 0, 0); }

/* powers down the calling cpu - only returns if call fails */
uint32_t psci_cpu_off() { return (uint32_t)do_psci_call(PSCI64_CPU_OFF, 0, 0, 0); }

uint32_t psci_cpu_on(uint64_t mpid, paddr_t entry) {
  LTRACEF("CPU_ON mpid %#" PRIx64 ", entry %#" PRIx64 "\n", mpid, entry);
  return (uint32_t)do_psci_call(PSCI64_CPU_ON, mpid, entry, 0);
}

uint32_t psci_get_affinity_info(uint64_t cluster, uint64_t cpuid) {
  return (uint32_t)do_psci_call(PSCI64_AFFINITY_INFO, ARM64_MPID(cluster, cpuid), 0, 0);
}

uint32_t psci_get_feature(uint32_t psci_call) {
  return (uint32_t)do_psci_call(PSCI64_PSCI_FEATURES, psci_call, 0, 0);
}

void psci_system_reset(enum reboot_flags flags) {
  uint64_t* args = reboot_args;

  if (flags == REBOOT_BOOTLOADER) {
    args = reboot_bootloader_args;
  } else if (flags == REBOOT_RECOVERY) {
    args = reboot_recovery_args;
  }

  dprintf(INFO, "PSCI reboot: %#" PRIx32 " %#" PRIx64 " %#" PRIx64 " %#" PRIx64 "\n",
    reset_command, args[0], args[1], args[2]);
  do_psci_call(reset_command, args[0], args[1], args[2]);
}

static void arm_psci_init(const void* driver_data, uint32_t length) {
#if 0
    // TODO: restore this after everyone is updated to new bootloaders
    ASSERT(length >= sizeof(dcfg_arm_psci_driver_t));
#else
  ASSERT(length >= sizeof(dcfg_arm_psci_driver_t) - sizeof(reboot_recovery_args));
#endif

  auto driver = static_cast<const dcfg_arm_psci_driver_t*>(driver_data);

  do_psci_call = driver->use_hvc ? psci_hvc_call : psci_smc_call;
  memcpy(shutdown_args, driver->shutdown_args, sizeof(shutdown_args));
  memcpy(reboot_args, driver->reboot_args, sizeof(reboot_args));
  memcpy(reboot_bootloader_args, driver->reboot_bootloader_args, sizeof(reboot_bootloader_args));

  // TODO: remove this check after everyone is updated to new bootloaders
  if (length >= sizeof(dcfg_arm_psci_driver_t)) {
    memcpy(reboot_recovery_args, driver->reboot_recovery_args, sizeof(reboot_recovery_args));
  }

  // read information about the psci implementation
  uint32_t result = psci_get_version();
  uint32_t major = (result >> 16) & 0xffff;
  uint32_t minor = result & 0xffff;
  dprintf(INFO, "PSCI version %u.%u\n", major, minor);

  if (major >= 1 && major != 0xffff) {
    // query features
    dprintf(INFO, "PSCI supported features:\n");
    result = psci_get_feature(PSCI64_SYSTEM_OFF);
    dprintf(INFO, "\tPSCI64_SYSTEM_OFF %#x\n", result);
    result = psci_get_feature(PSCI64_SYSTEM_RESET);
    dprintf(INFO, "\tPSCI64_SYSTEM_RESET %#x\n", result);
    result = psci_get_feature(PSCI64_SYSTEM_RESET2);
    dprintf(INFO, "\tPSCI64_SYSTEM_RESET2 %#x\n", result);
    if (result == 0) {
      // Prefer RESET2 if present. It explicitly supports arguments, but some vendors have
      // extended RESET to behave the same way.
      reset_command = PSCI64_SYSTEM_RESET2;
    }
    result = psci_get_feature(PSCI64_CPU_ON);
    dprintf(INFO, "\tPSCI64_CPU_ON %#x\n", result);
    result = psci_get_feature(PSCI64_CPU_OFF);
    dprintf(INFO, "\tPSCI64_CPU_OFF %#x\n", result);
  }
}

LK_PDEV_INIT(arm_psci_init, KDRV_ARM_PSCI, arm_psci_init, LK_INIT_LEVEL_PLATFORM_EARLY)

#include <lib/console.h>

static int cmd_psci(int argc, const cmd_args* argv, uint32_t flags) {
  if (argc < 2) {
notenoughargs:
    printf("not enough arguments\n");
    printf("%s system_reset\n", argv[0].str);
    printf("%s system_off\n", argv[0].str);
    printf("%s cpu_on <mpidr>\n", argv[0].str);
    printf("%s affinity_info <cluster> <cpu>\n", argv[0].str);
    printf("%s <function_id> [arg0] [arg1] [arg2]\n", argv[0].str);
    return -1;
  }

  if (!strcmp(argv[1].str, "system_reset")) {
    psci_system_reset(REBOOT_NORMAL);
  } else if (!strcmp(argv[1].str, "system_off")) {
    psci_system_off();
  } else if (!strcmp(argv[1].str, "cpu_on")) {
    // Defined in start.S.
    extern paddr_t kernel_entry_paddr;
    if (argc < 3) {
      goto notenoughargs;
    }
    uint32_t ret = psci_cpu_on(argv[2].u, kernel_entry_paddr);
    printf("psci_cpu_on returns %u\n", ret);
  } else if (!strcmp(argv[1].str, "affinity_info")) {
    if (argc < 4) {
      goto notenoughargs;
    }
    uint32_t ret = psci_get_affinity_info(argv[2].u, argv[3].u);
    printf("affinity info returns %u\n", ret);
  } else {
    uint32_t function = static_cast<uint32_t>(argv[1].u);
    uint64_t arg0 = (argc >= 3) ? argv[2].u : 0;
    uint64_t arg1 = (argc >= 4) ? argv[3].u : 0;
    uint64_t arg2 = (argc >= 5) ? argv[4].u : 0;

    uint64_t ret = do_psci_call(function, arg0, arg1, arg2);
    printf("do_psci_call returned %" PRIu64 "\n", ret);
  }
  return 0;
}

STATIC_COMMAND_START
STATIC_COMMAND_MASKED("psci", "execute PSCI command", &cmd_psci, CMD_AVAIL_ALWAYS)
STATIC_COMMAND_END(psci)
