Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * 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_ */