armv8: implementation of PSCI calls
authorReto Achermann <reto.achermann@inf.ethz.ch>
Wed, 1 Mar 2017 08:28:33 +0000 (09:28 +0100)
committerReto Achermann <reto.achermann@inf.ethz.ch>
Wed, 1 Mar 2017 08:28:33 +0000 (09:28 +0100)
Signed-off-by: Reto Achermann <reto.achermann@inf.ethz.ch>

errors/errno.fugu
kernel/Hakefile
kernel/arch/armv8/psci.c [new file with mode: 0644]
kernel/arch/armv8/smc.S [new file with mode: 0644]
kernel/include/arch/armv8/psci.h [new file with mode: 0644]

index 64f16b2..49f238a 100755 (executable)
@@ -1251,3 +1251,15 @@ errors sfn SFN_ERR_{
     failure QDRIVER              "Failure starting queue driver", 
 };
 
+errors psci PSCI_ERR_{
+    failure NOT_SUPPORTED    "Function not supported",
+    failure INVALID_PARAMETER "Invalid parameters supplied",
+    failure DENIED           "Access to the function denied",
+    failure ALREADY_ON       "Core is already on",
+    failure ON_PENDING       "There is a pending CPU_ON for this core",
+    failure INTERNAL_FAILURE "Internal failure",
+    failure NOT_PRESENT      "Resource not present",
+    failure DISABLED         "Core is disabled",
+    failure INVALID_ADDRESS  "Invald address provided",
+    failure UNKNOWN_ERROR    "Error number unknown",
+};
index 627cf60..b408c35 100644 (file)
@@ -577,7 +577,8 @@ let
      assemblyFiles = [
         "arch/armv8/efiboot.S",
         "arch/armv8/sysreg.S",
-        "arch/armv8/exceptions.S"
+        "arch/armv8/exceptions.S",
+        "arch/armv8/smc.S"
      ],
      cFiles = [
          "arch/arm/misc.c",
@@ -593,6 +594,7 @@ let
          "arch/armv8/dispatch.c",
          "arch/armv8/exec.c",
          "arch/armv8/exn.c",
+         "arch/armv8/psci.c",
          "arch/armv8/gic_v3.c",
          "arch/armv8/paging.c",
          "arch/armv8/startup_arch.c",
diff --git a/kernel/arch/armv8/psci.c b/kernel/arch/armv8/psci.c
new file mode 100644 (file)
index 0000000..df8972b
--- /dev/null
@@ -0,0 +1,454 @@
+/**
+ * \file psci.c
+ * \brief 
+ */
+
+
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <kernel.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include <psci.h>
+
+
+struct psci_retval
+{
+    uintptr_t a0;
+    uintptr_t a1;
+};
+
+
+
+extern void invoke_arm_smc64(uintptr_t fn, uintptr_t a1, uintptr_t a2,
+                             uintptr_t a3, uintptr_t a4, uintptr_t a5,
+                             uintptr_t a6, uintptr_t a7, struct psci_retval *res);
+
+
+
+static inline void psci_invoke(psci_fn_t fn, uintptr_t arg0, uintptr_t arg1,
+                               uintptr_t arg2, struct psci_retval *ret_val)
+{
+    invoke_arm_smc64(fn, arg0, arg1, arg2, 0, 0, 0, 0, ret_val);
+}
+
+
+static errval_t psci_error_to_barrelfish(struct psci_retval retval)
+{
+    int32_t err = (int32_t)(retval.a0 & 0xffffffff);
+
+    if (err >= 0) {
+        return SYS_ERR_OK;
+    }
+
+    if (err == PSCI_ERRNO_NOT_SUPPORTED) {
+        return PSCI_ERR_NOT_SUPPORTED;
+    } else if (err == PSCI_ERRNO_INVALID_PARAMETER) {
+        return PSCI_ERR_INVALID_PARAMETER;
+    } else if (err == PSCI_ERRNO_DENIED) {
+        return PSCI_ERR_DENIED;
+    } else if (err == PSCI_ERRNO_ALREADY_ON) {
+        return PSCI_ERR_ALREADY_ON;
+    } else if (err == PSCI_ERRNO_ON_PENDING) {
+        return PSCI_ERR_ON_PENDING;
+    } else if (err == PSCI_ERRNO_INTERNAL_FAILURE) {
+        return PSCI_ERR_INTERNAL_FAILURE;
+    } else if (err == PSCI_ERRNO_NOT_PRESENT) {
+        return PSCI_ERR_NOT_PRESENT;
+    } else if (err == PSCI_ERRNO_DISABLED) {
+        return PSCI_ERR_DISABLED;
+    } else if (err == PSCI_ERRNO_INVALID_ADDRESS) {
+        return PSCI_ERR_INVALID_ADDRESS;
+    }
+
+    return PSCI_ERR_UNKNOWN_ERROR;
+}
+
+/**
+ * @brief Return the version of PSCI implemented.
+ *
+ * @param major returns the major version
+ * @param minor returns the minor version
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_* on failure
+ */
+errval_t psci_version(uint16_t *major, uint16_t *minor)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_VERSION, 0, 0, 0, &retval);
+
+    uint32_t version = (uint32_t)retval.a0;
+    if (major) {
+        *major = (version  >> 16) & 0xffff;
+    }
+    if (minor) {
+        *minor = version & 0xffff;
+    }
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * @brief Suspend execution on a core or higher level topology node.
+ *
+ * @param power_state   the power state to
+ * @param entry_point   Physical address of the location to resume execution
+ * @param context_id    Value left in x0/r0 when resuming execution
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_INVALID_PARAMTER
+ *         PSCI_ERR_INVALID_ADDRESS
+ *         PSCI_ERR_DENIED
+ *
+ * This call is intended for use in idle subsystems where the core is expected
+ * to return to execution through a wakeup event. See section 5.4.
+ */
+errval_t psci_cpu_suspend(uint32_t power_state, lpaddr_t entry_point,
+                          uintptr_t context_id)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_CPU_SUSPEND, power_state, entry_point, context_id, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Power down the calling core.
+ *
+ * @return PSCI_ERR_DENIED on failure
+ *         The call does not return on success
+ *
+ * This call is intended for use in hotplug. A core that is powered down by
+ * CPU_OFF can only be powered up again in response to a CPU_ON.
+ */
+errval_t psci_cpu_off(void)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_CPU_OFF, 0, 0, 0, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Power up a core.
+ *
+ * @param target_cpu    MPIDR of the target processors
+ * @param entry_point   Address at which the core must commence execution
+ * @param context_id    Value left in x0/r0 when resuming execution
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_INVALID_PARAMETERS
+ *          PSCI_ERR_INVALID_ADDRESS
+ *          PSCI_ERR_ALREADY_ON
+ *          PSCI_ERR_ON_PENDING
+ *          PSCI_ERR_INTERNAL_FAILURE
+ *
+ * This call is used to power up cores that either:
+ * - Have not yet been booted into the calling supervisory software.
+ * - Have been previously powered down with a CPU_OFF call.
+ */
+errval_t psci_cpu_on(uintptr_t target_cpu, lpaddr_t entry_point,
+                     uintptr_t context_id)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_CPU_OFF, target_cpu, entry_point, context_id, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Places the core into an IMPLEMENTATION DEFINED low-power state
+ *
+ * @return on success, does not return
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_DENIED
+ */
+errval_t psci_cpu_freeze(void)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_CPU_FREEZE, 0, 0, 0, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Will place a core into an IMPLEMENTATION DEFINED low-power state
+ *
+ * @param entry_point_address   Address to be executed when waking up
+ * @param context_id            Context pointer to be left in x0/r0
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_INVALID_ADDRESS
+ */
+errval_t psci_cpu_default_suspend(lpaddr_t entry_point_address,
+                                  uintptr_t context_id)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_CPU_DEFAULT_SUSPEND64, entry_point_address, context_id,
+                0, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+
+/**
+ * @brief Enable the caller to request status of an affinity instance
+ *
+ * @param target_affinity       MPDIR of the target cpu
+ * @param lowest_affinity_level Denotes the lowest valid affinity level field
+ * @param ret_info
+ *
+ * @return
+ */
+errval_t psci_affinity_info(uintptr_t target_affinity,
+                            uint32_t lowest_affinity_level,
+                            psci_affinity_t *ret_info)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_AFFINITY_INFO64, target_affinity, lowest_affinity_level,
+                0, &retval);
+
+    errval_t err =  psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_info) {
+        *ret_info = (psci_affinity_t)retval.a0;
+    }
+
+    return err;
+}
+
+/**
+ * @brief Optional. This is used to ask a uniprocessor Trusted OS to migrate
+ *        its context to a specific core.
+ *
+ * @param target_cpu    MPDIR of the target core
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_PARAMETERS
+ *         PSCI_ERR_DENIED
+ *         PSCI_ERR_INTERNAL_FAILURE
+ *         PSCI_ERR_NOT_PRESENT
+ */
+errval_t psci_migrate(uintptr_t target_cpu)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_MIGRATE64, target_cpu, 0, 0, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Optional. This function allows a caller to identify the level of
+ *        multicore support present in the Trusted OS
+ *
+ * @param ret_migrate_type  Migration type capabilities
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED if the operation is not supported
+ */
+errval_t psci_migrate_info_type(psci_migrate_t *ret_migrate_type)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_MIGRATE_INFO_TYPE, 0, 0, 0, &retval);
+
+    errval_t err = psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_migrate_type) {
+        *ret_migrate_type = (psci_migrate_t)(retval.a0 & 0xffffffff);
+    }
+
+    return err;
+}
+
+
+/**
+ * @brief Optional. For a uniprocessor Trusted OS, this function returns the
+ *        current resident core
+ *
+ * @param ret_mpdir     MPIDR based value of core where the Trusted OS is resident
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_NOT_SUPPORTED if not supported
+ */
+errval_t psci_migrate_info_up_cpu(uintptr_t *ret_mpdir)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_MIGRATE_INFO_UP_CPU64, 0, 0, 0, &retval);
+
+    errval_t err = psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_mpdir) {
+        *ret_mpdir = retval.a0;
+    }
+
+    return err;
+}
+
+/**
+ * @brief Shutdown the system.
+ */
+void psci_system_off(void)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_SYSTEM_OFF, 0, 0, 0, &retval);
+    panic("SHOULD NOT BE REACHED!\n");
+}
+
+/**
+ * @brief Reset the system.
+ */
+void psci_system_reset(void)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_SYSTEM_REST, 0, 0, 0, &retval);
+    panic("SHOULD NOT BE REACHED!\n");
+}
+
+/**
+ * @brief Used to implement suspend to RAM. The semantics are equivalent to a
+ *        CPU_SUSPEND to the deepest low-power state.
+ *
+ * @param entry_point_address   physical address to be executed when returning
+ * @param context_id            context id to be stored in x0/r0
+ *
+ * @return does not retturn on success
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_ADDRESS
+ *         PSCI_ERR_ALREADY_ON
+ */
+errval_t psci_system_suspend(lpaddr_t entry_point_address, uintptr_t context_id)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_SYSTEM_SUPSEND64, entry_point_address, context_id, 0,
+                &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Query API to discover whether a specific PSCI function is implemented
+ *
+ * @param psci_fn_id            Function ID for a PSCI Function
+ * @param ret_feature_flags     Returns a set of feature flags of the function
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED if the function is not supported or invalid
+ */
+errval_t psci_features(uint32_t psci_fn_id, uint32_t *ret_feature_flags)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_PSCI_FEATURES, psci_fn_id, 0, 0, &retval);
+
+    errval_t err = psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_feature_flags) {
+        *ret_feature_flags = (uint32_t)(retval.a0 & 0x7ffffff);
+    }
+
+    return err;
+}
+
+
+/**
+ * @brief This API is intended to return the true HW state of a node in the
+ *        power domain topology of the system
+ *
+ * @param target_cpu    Target CPU MPDIR
+ * @param power_level   Power domain level for the node
+ * @param ret_node_hw   return the power node hw state
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_NOT_SUPPORTED
+ *          PSCI_ERR_INVALID_PARAMETERS
+ */
+errval_t psci_node_hw_state(uintptr_t target_cpu, uint32_t power_level,
+                            psci_node_hw_state_t *ret_node_hw)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_NODE_HW_STATE64, target_cpu, power_level,
+                0, &retval);
+
+    errval_t err =  psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_node_hw) {
+        *ret_node_hw = (psci_node_hw_state_t)retval.a0;
+    }
+
+    return err;
+}
+
+
+/**
+ * @brief This API allows setting the mode used by CPU_SUSPEND to coordinate
+ *        power states.
+ *
+ * @param mode  Mode to put the system in
+ *
+ * @return SYS_ERR_OK on success,
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_PARAMETERS
+ *         PSCI_ERR_DENIED
+ */
+errval_t psci_set_suspend_mode(psci_suspend_mode_t mode)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_PSCI_SET_SUSPEND_MODE, mode, 0, 0, &retval);
+
+    return psci_error_to_barrelfish(retval);
+}
+
+/**
+ * @brief Returns the amount of time the platform has spent in the given power
+ *        state since cold boot.
+ *
+ * @param target_cpu    target CPU MPDIR
+ * @param power_state   power state to query
+ * @param ret_residency Returns the amount of time, in microseconds, spent in state
+ *
+ * @return  SYS_ERR_OK
+ */
+errval_t psci_stat_residency(uintptr_t target_cpu, uint32_t power_state,
+                             uintptr_t *ret_residency)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_PSCI_STAT_RESIDENCY64, target_cpu, power_state,
+            0, &retval);
+
+    errval_t err =  psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && ret_residency) {
+        *ret_residency = retval.a0;
+    }
+
+    return err;
+}
+
+/**
+ * @brief Return the number of times the platform has used the given power state
+ *        since cold boot.
+ *
+ * @param target_cpu    target CPU MPDIR
+ * @param power_state   power state to query
+ * @param count         returns the count
+ *
+ * @return SYS_ERR_OK
+ */
+errval_t psci_stat_count(uintptr_t target_cpu, uint32_t power_state,
+                         uintptr_t *count)
+{
+    struct psci_retval retval;
+    psci_invoke(PSCI_FN_PSCI_STAT_COUNT64, target_cpu, power_state,
+            0, &retval);
+
+    errval_t err =  psci_error_to_barrelfish(retval);
+    if (err_is_ok(err) && count) {
+        *count = retval.a0;
+    }
+
+    return err;
+}
+
diff --git a/kernel/arch/armv8/smc.S b/kernel/arch/armv8/smc.S
new file mode 100644 (file)
index 0000000..d12de5e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <asmoffsets.h>
+#include <offsets.h>
+
+#define ARM_SMCCC_QUIRK_NONE        0
+#define ARM_SMCCC_QUIRK_QCOM_A6     1 /* Save/restore register a6 */
+
+.global invoke_arm_smc64
+.global invoke_arm_hvc64
+
+/*
+ * void invoke_arm_smc(uintptr_t fn, uintptr_t a1, uintptr_t a2,
+ *                     uintptr_t a3, uintptr_t a4, uintptr_t a5,
+ *                     uintptr_t a6, uintptr_t a7, struct psci_retval *res);
+ */
+invoke_arm_smc64:
+    smc  #0
+    ldr x4, [sp]
+    stp x0, x1, [x4]
+    ret
+
+/*
+ * void invoke_arm_smc(uintptr_t fn, uintptr_t a1, uintptr_t a2,
+ *                     uintptr_t a3, uintptr_t a4, uintptr_t a5,
+ *                     uintptr_t a6, uintptr_t a7, struct psci_retval *res,);
+ */
+invoke_arm_hvc64:
+    hvc  #0
+    ldr x4, [sp]
+    stp x0, x1, [x4]
+    ret
diff --git a/kernel/include/arch/armv8/psci.h b/kernel/include/arch/armv8/psci.h
new file mode 100644 (file)
index 0000000..be12d0f
--- /dev/null
@@ -0,0 +1,333 @@
+/**
+ * \file
+ * \brief
+ */
+
+
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef ARM_PSCI_H_
+#define ARM_PSCI_H_
+
+
+/**
+ * Function Prototypes for the PSCI interface
+ */
+typedef enum {
+    PSCI_FN_VERSION               = 0x84000000,
+    PSCI_FN_CPU_SUSPEND           = 0x84000001,          //!< PSCI_FN_CPU_SUSPEND
+    PSCI_FN_CPU_SUSPEND64         = 0xC4000001,          //!< PSCI_FN_CPU_SUSPEND
+    PSCI_FN_CPU_OFF               = 0x84000002,              //!< PSCI_FN_CPU_OFF
+    PSCI_FN_CPU_ON                = 0x84000003,               //!< PSCI_FN_CPU_ON
+    PSCI_FN_CPU_ON64              = 0xC4000003,               //!< PSCI_FN_CPU_ON
+    PSCI_FN_AFFINITY_INFO         = 0x84000004,        //!< PSCI_FN_AFFINITY_INFO
+    PSCI_FN_AFFINITY_INFO64       = 0xC4000004,        //!< PSCI_FN_AFFINITY_INFO
+    PSCI_FN_MIGRATE               = 0x84000005,              //!< PSCI_FN_MIGRATE
+    PSCI_FN_MIGRATE64             = 0xC4000005,              //!< PSCI_FN_MIGRATE
+    PSCI_FN_MIGRATE_INFO_TYPE     = 0x84000006,    //!< PSCI_FN_MIGRATE_INFO_TYPE
+    PSCI_FN_MIGRATE_INFO_UP_CPU   = 0x84000007,  //!< PSCI_FN_MIGRATE_INFO_UP_CPU
+    PSCI_FN_MIGRATE_INFO_UP_CPU64 = 0xC4000007,  //!< PSCI_FN_MIGRATE_INFO_UP_CPU
+    PSCI_FN_SYSTEM_OFF            = 0x84000008,           //!< PSCI_FN_SYSTEM_OFF
+    PSCI_FN_SYSTEM_REST           = 0x84000009,          //!< PSCI_FN_SYSTEM_REST
+    PSCI_FN_PSCI_FEATURES         = 0x8400000A,//!< PSCI_FN_PSCI_FEATURES
+    PSCI_FN_CPU_FREEZE            = 0x8400000B,           //!< PSCI_FN_CPU_FREEZE
+    PSCI_FN_CPU_DEFAULT_SUSPEND   = 0x8400000C,  //!< PSCI_FN_CPU_DEFAULT_SUSPEND
+    PSCI_FN_CPU_DEFAULT_SUSPEND64 = 0xC400000C,  //!< PSCI_FN_CPU_DEFAULT_SUSPEND
+    PSCI_FN_NODE_HW_STATE         = 0x8400000D,        //!< PSCI_FN_NODE_HW_STATE
+    PSCI_FN_NODE_HW_STATE64       = 0xC400000D,        //!< PSCI_FN_NODE_HW_STATE
+    PSCI_FN_SYSTEM_SUPSEND        = 0x8400000E,       //!< PSCI_FN_SYSTEM_SUPSEND
+    PSCI_FN_SYSTEM_SUPSEND64      = 0xC400000E,       //!< PSCI_FN_SYSTEM_SUPSEND
+    PSCI_FN_PSCI_SET_SUSPEND_MODE = 0x8400000F,//!< PSCI_FN_PSCI_SET_SUSPEND_MODE
+    PSCI_FN_PSCI_STAT_RESIDENCY   = 0x84000010,  //!< PSCI_FN_PSCI_STAT_RESIDENCY
+    PSCI_FN_PSCI_STAT_RESIDENCY64 = 0xC4000010,  //!< PSCI_FN_PSCI_STAT_RESIDENCY
+    PSCI_FN_PSCI_STAT_COUNT       = 0x84000011,      //!< PSCI_FN_PSCI_STAT_COUNT
+    PSCI_FN_PSCI_STAT_COUNT64     = 0x84000012,      //!< PSCI_FN_PSCI_STAT_COUNT
+} psci_fn_t;
+
+
+/**
+ *
+ * Table 7 defines the values for error codes used with PSCI functions. All
+ * errors are considered to be 32-bit signed integers. Therefore, when using the
+ * SMC64 calling convention, the upper word will be zero.
+ */
+typedef enum {
+    PSCI_ERRNO_SUCCESS = 0,          //!< PSCI_ERRNO_SUCCESS
+    PSCI_ERRNO_NOT_SUPPORTED = -1,   //!< PSCI_ERRNO_NOT_SUPPORTED
+    PSCI_ERRNO_INVALID_PARAMETER = -2,//!< PSCI_ERRNO_INVALID_PARAMTER
+    PSCI_ERRNO_DENIED = -3,          //!< PSCI_ERRNO_DENIED
+    PSCI_ERRNO_ALREADY_ON  =-4,      //!< PSCI_ERRNO_ALREADY_ON
+    PSCI_ERRNO_ON_PENDING = -5,      //!< PSCI_ERRNO_ON_PENDING
+    PSCI_ERRNO_INTERNAL_FAILURE = -6,//!< PSCI_ERRNO_INTERNAL_FAILURE
+    PSCI_ERRNO_NOT_PRESENT = -7,     //!< PSCI_ERRNO_NOT_PRESENT
+    PSCI_ERRNO_DISABLED = -8,        //!< PSCI_ERRNO_DISABLED
+    PSCI_ERRNO_INVALID_ADDRESS = -9, //!< PSCI_ERRNO_INVALID_ADDRESS
+    PSCI_ERRNO_LAST = -10
+} psci_errno_t;
+
+/**
+ *
+ */
+typedef enum {
+    PSCI_AFFINITY_ON = 0,        //!< At least one core in the instance is ON
+    PSCI_AFFINITY_OFF = 1,       //!< All cores in the affinity instance are OFF
+    PSCI_AFFINITY_ON_PENDING = 2,//!< instance is transitioning to an ON state
+    PSCI_AFFINITY_INVALID = 3,   //!< Invalid affinity state
+} psci_affinity_t;
+
+/**
+ *
+ */
+typedef enum {
+    PSCI_MIGRATE_CAPABLE = 0,    //!< Uniprocessor migrate capable Trusted OS
+    PSCI_MIGRATE_NOT_CAPABLE = 1,//!< Uniprocessor not migrate capable Trusted OS
+    PSCI_MIGRATE_NOT_PRESENT = 2,//!< Trusted OS is either not present
+    PSCI_MIGRATE_INVALID = 2,    //!< Invalid migration type
+} psci_migrate_t;
+
+typedef enum {
+    PSCI_NODE_HW_ON = 0,
+    PSCI_NODE_HW_OFF = 1,
+    PSCI_NODE_HW_STANDBY = 2,
+    PSCI_NODE_HW_INVALID = 3,
+} psci_node_hw_state_t;
+
+typedef enum {
+    PSCI_SUSPEND_MODE_PLATFORM = 0,
+    PSCI_SUSPEND_MODE_OS       = 1,
+} psci_suspend_mode_t;
+
+
+/**
+ * @brief Return the version of PSCI implemented.
+ *
+ * @param major returns the major version
+ * @param minor returns the minor version
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_* on failure
+ */
+errval_t psci_version(uint16_t *major, uint16_t *minor);
+
+/**
+ * @brief Suspend execution on a core or higher level topology node.
+ *
+ * @param power_state   the power state to
+ * @param entry_point   Physical address of the location to resume execution
+ * @param context_id    Value left in x0/r0 when resuming execution
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_INVALID_PARAMTER
+ *         PSCI_ERR_INVALID_ADDRESS
+ *         PSCI_ERR_DENIED
+ *
+ * This call is intended for use in idle subsystems where the core is expected
+ * to return to execution through a wakeup event. See section 5.4.
+ */
+errval_t psci_cpu_suspend(uint32_t power_state, lpaddr_t entry_point,
+                          uintptr_t context_id);
+
+/**
+ * @brief Power down the calling core.
+ *
+ * @return PSCI_ERR_DENIED on failure
+ *         The call does not return on success
+ *
+ * This call is intended for use in hotplug. A core that is powered down by
+ * CPU_OFF can only be powered up again in response to a CPU_ON.
+ */
+errval_t psci_cpu_off(void);
+
+/**
+ * @brief Power up a core.
+ *
+ * @param target_cpu    MPIDR of the target processors
+ * @param entry_point   Address at which the core must commence execution
+ * @param context_id    Value left in x0/r0 when resuming execution
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_INVALID_PARAMETERS
+ *          PSCI_ERR_INVALID_ADDRESS
+ *          PSCI_ERR_ALREADY_ON
+ *          PSCI_ERR_ON_PENDING
+ *          PSCI_ERR_INTERNAL_FAILURE
+ *
+ * This call is used to power up cores that either:
+ * - Have not yet been booted into the calling supervisory software.
+ * - Have been previously powered down with a CPU_OFF call.
+ */
+errval_t psci_cpu_on(uintptr_t target_cpu, lpaddr_t entry_point,
+                     uintptr_t context_id);
+
+/**
+ * @brief Places the core into an IMPLEMENTATION DEFINED low-power state
+ *
+ * @return on success, does not return
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_DENIED
+ */
+errval_t psci_cpu_freeze(void);
+
+/**
+ * @brief Will place a core into an IMPLEMENTATION DEFINED low-power state
+ *
+ * @param entry_point_address   Address to be executed when waking up
+ * @param context_id            Context pointer to be left in x0/r0
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_INVALID_ADDRESS
+ */
+errval_t psci_cpu_default_suspend(lpaddr_t entry_point_address,
+                                  uintptr_t context_id);
+
+
+/**
+ * @brief Enable the caller to request status of an affinity instance
+ *
+ * @param target_affinity       MPDIR of the target cpu
+ * @param lowest_affinity_level Denotes the lowest valid affinity level field
+ * @param ret_info
+ *
+ * @return
+ */
+errval_t psci_affinity_info(uintptr_t target_affinity,
+                            uint32_t lowest_affinity_level,
+                            psci_affinity_t *ret_info);
+
+/**
+ * @brief Optional. This is used to ask a uniprocessor Trusted OS to migrate
+ *        its context to a specific core.
+ *
+ * @param target_cpu    MPDIR of the target core
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_PARAMETERS
+ *         PSCI_ERR_DENIED
+ *         PSCI_ERR_INTERNAL_FAILURE
+ *         PSCI_ERR_NOT_PRESENT
+ */
+errval_t psci_migrate(uintptr_t target_cpu);
+
+/**
+ * @brief Optional. This function allows a caller to identify the level of
+ *        multicore support present in the Trusted OS
+ *
+ * @param ret_migrate_type  Migration type capabilities
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED if the operation is not supported
+ */
+errval_t psci_migrate_info_type(psci_migrate_t *ret_migrate_type);
+
+
+/**
+ * @brief Optional. For a uniprocessor Trusted OS, this function returns the
+ *        current resident core
+ *
+ * @param ret_mpdir     MPIDR based value of core where the Trusted OS is resident
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_NOT_SUPPORTED if not supported
+ */
+errval_t psci_migrate_info_up_cpu(uintptr_t *ret_mpdir);
+
+/**
+ * @brief Shutdown the system.
+ */
+void psci_system_off(void)__attribute__((noreturn));
+
+/**
+ * @brief Reset the system.
+ */
+void psci_system_reset(void)__attribute__((noreturn));
+
+/**
+ * @brief Used to implement suspend to RAM. The semantics are equivalent to a
+ *        CPU_SUSPEND to the deepest low-power state.
+ *
+ * @param entry_point_address   physical address to be executed when returning
+ * @param context_id            context id to be stored in x0/r0
+ *
+ * @return does not retturn on success
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_ADDRESS
+ *         PSCI_ERR_ALREADY_ON
+ */
+errval_t psci_system_suspend(lpaddr_t entry_point_address, uintptr_t context_id);
+
+/**
+ * @brief Query API to discover whether a specific PSCI function is implemented
+ *
+ * @param psci_fn_id            Function ID for a PSCI Function
+ * @param ret_feature_flags     Returns a set of feature flags of the function
+ *
+ * @return SYS_ERR_OK on success
+ *         PSCI_ERR_NOT_SUPPORTED if the function is not supported or invalid
+ */
+errval_t psci_features(uint32_t psci_fn_id, uint32_t *ret_feature_flags);
+
+
+/**
+ * @brief This API is intended to return the true HW state of a node in the
+ *        power domain topology of the system
+ *
+ * @param target_cpu    Target CPU MPDIR
+ * @param power_level   Power domain level for the node
+ * @param ret_node_hw   return the power node hw state
+ *
+ * @return  SYS_ERR_OK on success
+ *          PSCI_ERR_NOT_SUPPORTED
+ *          PSCI_ERR_INVALID_PARAMETERS
+ */
+errval_t psci_node_hw_state(uintptr_t target_cpu, uint32_t power_level,
+                            psci_node_hw_state_t *ret_node_hw);
+
+
+/**
+ * @brief This API allows setting the mode used by CPU_SUSPEND to coordinate
+ *        power states.
+ *
+ * @param mode  Mode to put the system in
+ *
+ * @return SYS_ERR_OK on success,
+ *         PSCI_ERR_NOT_SUPPORTED
+ *         PSCI_ERR_INVALID_PARAMETERS
+ *         PSCI_ERR_DENIED
+ */
+errval_t psci_set_suspend_mode(psci_suspend_mode_t mode);
+
+/**
+ * @brief Returns the amount of time the platform has spent in the given power
+ *        state since cold boot.
+ *
+ * @param target_cpu    target CPU MPDIR
+ * @param power_state   power state to query
+ * @param ret_residency Returns the amount of time, in microseconds, spent in state
+ *
+ * @return  SYS_ERR_OK
+ */
+errval_t psci_stat_residency(uintptr_t target_cpu, uint32_t power_state,
+                             uintptr_t *ret_residency);
+
+/**
+ * @brief Return the number of times the platform has used the given power state
+ *        since cold boot.
+ *
+ * @param target_cpu    target CPU MPDIR
+ * @param power_state   power state to query
+ * @param count         returns the count
+ *
+ * @return SYS_ERR_OK
+ */
+errval_t psci_stat_count(uintptr_t target_cpu, uint32_t power_state,
+                         uintptr_t *count);
+
+#endif