blob: 10dfc5c20cfa50107370fc1b398d3b758759964e [file] [log] [blame]
/*
* Copyright 2020 Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_PSCI_H_
#define ZEPHYR_INCLUDE_DRIVERS_PSCI_H_
/**
* @file
* @brief Public API for ARM PSCI
*/
#include <zephyr/types.h>
#include <arch/arm/arm-smccc.h>
#include <stddef.h>
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
/* PSCI version decoding (independent of PSCI version) */
#define PSCI_VERSION_MAJOR_SHIFT 16
#define PSCI_VERSION_MINOR_MASK \
((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
#define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
#define PSCI_VERSION_MAJOR(ver) \
(((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
#define PSCI_VERSION_MINOR(ver) \
((ver) & PSCI_VERSION_MINOR_MASK)
/**
* @brief ARM PSCI Driver API
* @defgroup arm_psci ARM PSCI Driver API
* @{
*/
typedef uint32_t (*psci_get_version_f)(const struct device *dev);
typedef int (*psci_cpu_off_f)(const struct device *dev, uint32_t state);
typedef int (*psci_cpu_on_f)(const struct device *dev, unsigned long cpuid,
unsigned long entry_point);
typedef int (*psci_affinity_info_f)(const struct device *dev,
unsigned long target_affinity,
unsigned long lowest_affinity_level);
__subsystem struct psci_driver_api {
psci_get_version_f get_version;
psci_cpu_off_f cpu_off;
psci_cpu_on_f cpu_on;
psci_affinity_info_f affinity_info;
};
/**
* @brief Return the version of PSCI implemented
*
* @param dev Pointer to the device structure for the driver instance
*
* @return The PSCI version
*/
__syscall uint32_t psci_get_version(const struct device *dev);
static inline uint32_t z_impl_psci_get_version(const struct device *dev)
{
const struct psci_driver_api *api =
(const struct psci_driver_api *)dev->api;
return api->get_version(dev);
}
/**
* @brief Power down the calling core
*
* This call is intended foruse in hotplug. A core that is powered down by
* CPU_OFF can only be powered up again in response to a CPU_ON
*
* @param dev Pointer to the device structure for the driver instance
* @param state Not used
*
* @return The call does not return when successful
*/
__syscall int psci_cpu_off(const struct device *dev, uint32_t state);
static inline int z_impl_psci_cpu_off(const struct device *dev, uint32_t state)
{
const struct psci_driver_api *api =
(const struct psci_driver_api *)dev->api;
return api->cpu_off(dev, state);
}
/**
* @brief Power up a core
*
* This call is used to power up cores that either have not yet been booted
* into the calling supervisory software or have been previously powered down
* with a CPU_OFF call
*
* @param dev Pointer to the device structure for the driver instance
* @param cpuid This parameter contains a copy of the affinity fields of the
* MPIDR register
* @param entry_point Address at which the core must commence execution, when
* it enters the return Non-secure Exception level.
*
* @return 0 on success, a negative errno otherwise
*/
__syscall int psci_cpu_on(const struct device *dev, unsigned long cpuid,
unsigned long entry_point);
static inline int z_impl_psci_cpu_on(const struct device *dev,
unsigned long cpuid,
unsigned long entry_point) {
const struct psci_driver_api *api =
(const struct psci_driver_api *)dev->api;
return api->cpu_on(dev, cpuid, entry_point);
}
/**
* @brief Enable the caller to request status of an affinity instance
*
* @param dev Pointer to the device structure for the driver instance
* @param target_affinity This parameter contains a copy of the affinity fields
* of the MPIDR register
* @param lowest_affinity_level Denotes the lowest affinity level field that is
* valid in the target_affinity parameter
*
* @return 2 if the affinity instance is transitioning to an ON sate, 1 off, 0
* on, a negative errno otherwise
*/
__syscall int psci_affinity_info(const struct device *dev,
unsigned long target_affinity,
unsigned long lowest_affinity_level);
static inline int z_impl_psci_affinity_info(const struct device *dev,
unsigned long target_affinity,
unsigned long lowest_affinity_level)
{
const struct psci_driver_api *api =
(const struct psci_driver_api *)dev->api;
return api->affinity_info(dev, target_affinity, lowest_affinity_level);
}
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#include <syscalls/psci.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_PSCI_H_ */