diff --git a/CODEOWNERS b/CODEOWNERS index 4dcc9d1190a..4ff14b44d85 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -239,6 +239,7 @@ /drivers/peci/ @albertofloyd @franciscomunoz @scottwcpg /drivers/pinmux/*hsdk* @iriszzw /drivers/pinmux/*it8xxx2* @ite +/drivers/psci/ @carlocaione /drivers/ps2/ @albertofloyd @franciscomunoz @scottwcpg /drivers/pwm/*rv32m1* @henrikbrixandersen /drivers/pwm/*sam0* @nzmichaelh @@ -359,6 +360,7 @@ /dts/bindings/*/sifive* @mateusz-holenko @kgugala @pgielda @nategraff-sifive /dts/bindings/*/litex* @mateusz-holenko @kgugala @pgielda /dts/bindings/*/vexriscv* @mateusz-holenko @kgugala @pgielda +/dts/bindings/psci/* @carlocaione /dts/posix/ @aescolar @vanwinkeljan @daor-oti /dts/bindings/sensor/*bme680* @BoschSensortec /dts/bindings/sensor/st* @avisconti @@ -385,6 +387,7 @@ /include/drivers/spi.h @tbursztyka /include/drivers/lora.h @Mani-Sadhasivam /include/drivers/peci.h @albertofloyd @franciscomunoz @scottwcpg +/include/drivers/psci.h @carlocaione /include/app_memory/ @andrewboie /include/arch/arc/ @abrodkin @ruuddw /include/arch/arc/arch.h @andrewboie @@ -392,6 +395,7 @@ /include/arch/arm/aarch32/ @MaureenHelm @galak @ioannisg /include/arch/arm/aarch32/cortex_a_r/ @stephanosio /include/arch/arm/aarch64/ @carlocaione +/include/arch/arm/arm-smccc.h @carlocaione /include/arch/arm/aarch32/irq.h @andrewboie /include/arch/nios2/ @andrewboie /include/arch/nios2/arch.h @andrewboie diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 7e934202c90..58cbb3f5fe2 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -654,6 +654,17 @@ Documentation: labels: - "area: Clocks" +"Drivers: PSCI": + status: maintained + maintainers: + - carlocaione + files: + - drivers/psci/ + - include/drivers/psci.h + - include/arch/arm/arm-smccc.h + labels: + - "area: PSCI" + "Drivers: PWM": status: maintained maintainers: diff --git a/arch/arm/core/aarch64/CMakeLists.txt b/arch/arm/core/aarch64/CMakeLists.txt index 3ce4a174971..7f4c8db9558 100644 --- a/arch/arm/core/aarch64/CMakeLists.txt +++ b/arch/arm/core/aarch64/CMakeLists.txt @@ -30,5 +30,6 @@ endif () zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S) zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE ../common/tls.c) +zephyr_library_sources_ifdef(CONFIG_ARM_PSCI smccc-call.S) add_subdirectory_ifdef(CONFIG_ARM_MMU mmu) diff --git a/arch/arm/core/aarch64/smccc-call.S b/arch/arm/core/aarch64/smccc-call.S new file mode 100644 index 00000000000..10e32ccaafb --- /dev/null +++ b/arch/arm/core/aarch64/smccc-call.S @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file implements the common calling mechanism to be used with the Secure + * Monitor Call (SMC) and Hypervisor Call (HVC). + * + * See http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ + +#include +#include +#include + +.macro SMCCC instr + \instr #0 + ldr x4, [sp] + stp x0, x1, [x4] + stp x2, x3, [x4, #16] + ret +.endm + +/* + * The SMC instruction is used to generate a synchronous exception that is + * handled by Secure Monitor code running in EL3. + */ +GTEXT(arm_smccc_smc) +SECTION_FUNC(TEXT, arm_smccc_smc) + SMCCC smc + +/* + * The HVC instruction is used to generate a synchronous exception that is + * handled by a hypervisor running in EL2. + */ +GTEXT(arm_smccc_hvc) +SECTION_FUNC(TEXT, arm_smccc_hvc) + SMCCC hvc diff --git a/boards/arm/qemu_cortex_a53/qemu_cortex_a53.dts b/boards/arm/qemu_cortex_a53/qemu_cortex_a53.dts index ee7358df6a8..d93f42735d2 100644 --- a/boards/arm/qemu_cortex_a53/qemu_cortex_a53.dts +++ b/boards/arm/qemu_cortex_a53/qemu_cortex_a53.dts @@ -12,6 +12,12 @@ model = "QEMU Cortex-A53"; compatible = "qemu,arm-cortex-a53"; + psci { + compatible = "arm,psci-0.2"; + method = "hvc"; + label = "PSCI"; + }; + chosen { zephyr,sram = &sram0; zephyr,console = &uart0; diff --git a/boards/arm/qemu_cortex_a53/qemu_cortex_a53_defconfig b/boards/arm/qemu_cortex_a53/qemu_cortex_a53_defconfig index f37de02c004..e6ac5b542ec 100644 --- a/boards/arm/qemu_cortex_a53/qemu_cortex_a53_defconfig +++ b/boards/arm/qemu_cortex_a53/qemu_cortex_a53_defconfig @@ -11,6 +11,9 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y +# PSCI is supported +CONFIG_ARM_PSCI=y + # Enable serial port CONFIG_UART_PL011=y CONFIG_UART_PL011_PORT0=y diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 1e09fe0f749..03aed8fa953 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -42,6 +42,7 @@ add_subdirectory_ifdef(CONFIG_PECI peci) add_subdirectory_ifdef(CONFIG_REGULATOR regulator) add_subdirectory_ifdef(CONFIG_MEMC memc) add_subdirectory_ifdef(CONFIG_VIRTUALIZATION virtualization) +add_subdirectory_ifdef(CONFIG_ARM_PSCI psci) add_subdirectory_ifdef(CONFIG_FLASH_HAS_DRIVER_ENABLED flash) add_subdirectory_ifdef(CONFIG_SERIAL_HAS_DRIVER serial) diff --git a/drivers/Kconfig b/drivers/Kconfig index e49f06a9217..f544db0b6ee 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -105,4 +105,6 @@ source "drivers/memc/Kconfig" source "drivers/virtualization/Kconfig" +source "drivers/psci/Kconfig" + endmenu diff --git a/drivers/psci/CMakeLists.txt b/drivers/psci/CMakeLists.txt new file mode 100644 index 00000000000..98afb5ce09b --- /dev/null +++ b/drivers/psci/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_ARM_PSCI psci.c) +zephyr_library_sources_ifdef(CONFIG_USERSPACE psci_handlers.c) diff --git a/drivers/psci/Kconfig b/drivers/psci/Kconfig new file mode 100644 index 00000000000..cc2e7167d9d --- /dev/null +++ b/drivers/psci/Kconfig @@ -0,0 +1,22 @@ +# PSCI driver configuration options + +# Copyright (c) 2020 Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +config ARM_PSCI + bool "Support for the ARM Power State Coordination Interface (PSCI)" + depends on ARMV8_A + help + Say Y here if you want Zephyr to communicate with system firmware + implementing the PSCI specification for CPU-centric power + management operations described in ARM document number ARM DEN + 0022A ("Power State Coordination Interface System Software on + ARM processors"). + +if ARM_PSCI + +module = PSCI +module-str = psci +source "subsys/logging/Kconfig.template.log_config" + +endif diff --git a/drivers/psci/psci.c b/drivers/psci/psci.c new file mode 100644 index 00000000000..91eb52f411d --- /dev/null +++ b/drivers/psci/psci.c @@ -0,0 +1,159 @@ +/* + * Copyright 2020 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT arm_psci_0_2 + +#define LOG_LEVEL CONFIG_PSCI_LOG_LEVEL +#include +LOG_MODULE_REGISTER(psci); + +#include +#include + +#include +#include +#include + +#include +#include "psci.h" + +static int psci_to_dev_err(int ret) +{ + switch (ret) { + case PSCI_RET_SUCCESS: + return 0; + case PSCI_RET_NOT_SUPPORTED: + return -ENOTSUP; + case PSCI_RET_INVALID_PARAMS: + case PSCI_RET_INVALID_ADDRESS: + return -EINVAL; + case PSCI_RET_DENIED: + return -EPERM; + }; + + return -EINVAL; +} + +static uint32_t psci_api_get_version(const struct device *dev) +{ + struct psci *data = dev->data; + + return data->invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); +} + +static int psci_api_cpu_off(const struct device *dev, uint32_t state) +{ + struct psci *data = dev->data; + int ret; + + ret = data->invoke_psci_fn(PSCI_0_2_FN_CPU_OFF, state, 0, 0); + + return psci_to_dev_err(ret); +} + +static int psci_api_cpu_on(const struct device *dev, unsigned long cpuid, + unsigned long entry_point) +{ + struct psci *data = dev->data; + int ret; + + ret = data->invoke_psci_fn(PSCI_FN_NATIVE(0_2, CPU_ON), cpuid, + entry_point, 0); + + return psci_to_dev_err(ret); +} + +static int psci_api_affinity_info(const struct device *dev, + unsigned long target_affinity, + unsigned long lowest_affinity_level) +{ + struct psci *data = dev->data; + + return data->invoke_psci_fn(PSCI_FN_NATIVE(0_2, AFFINITY_INFO), + target_affinity, lowest_affinity_level, 0); +} + +static unsigned long __invoke_psci_fn_hvc(unsigned long function_id, + unsigned long arg0, + unsigned long arg1, + unsigned long arg2) +{ + struct arm_smccc_res res; + + arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); + return res.a0; +} + +static unsigned long __invoke_psci_fn_smc(unsigned long function_id, + unsigned long arg0, + unsigned long arg1, + unsigned long arg2) +{ + struct arm_smccc_res res; + + arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); + return res.a0; +} + +static int set_conduit_method(struct psci *data) +{ + const char *method; + + method = DT_PROP(DT_INST(0, DT_DRV_COMPAT), method); + + if (!strcmp("hvc", method)) { + data->conduit = SMCCC_CONDUIT_HVC; + data->invoke_psci_fn = __invoke_psci_fn_hvc; + } else if (!strcmp("smc", method)) { + data->conduit = SMCCC_CONDUIT_SMC; + data->invoke_psci_fn = __invoke_psci_fn_smc; + } else { + LOG_ERR("Invalid conduit method"); + return -EINVAL; + } + + return 0; +} + +static int psci_detect(const struct device *dev) +{ + uint32_t ver = psci_api_get_version(dev); + + LOG_DBG("Detected PSCIv%d.%d", + PSCI_VERSION_MAJOR(ver), + PSCI_VERSION_MINOR(ver)); + + if (PSCI_VERSION_MAJOR(ver) == 0 && PSCI_VERSION_MINOR(ver) < 2) { + LOG_ERR("PSCI unsupported version"); + return -ENOTSUP; + } + + return 0; +} + +static int psci_init(const struct device *dev) +{ + struct psci *data = dev->data; + + if (set_conduit_method(data)) { + return -ENOTSUP; + } + + return psci_detect(dev); +} + +static const struct psci_driver_api psci_api = { + .get_version = psci_api_get_version, + .cpu_off = psci_api_cpu_off, + .cpu_on = psci_api_cpu_on, + .affinity_info = psci_api_affinity_info, +}; + +static struct psci psci_data; + +DEVICE_DT_INST_DEFINE(0, psci_init, device_pm_control_nop, + &psci_data, NULL, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &psci_api); diff --git a/drivers/psci/psci.h b/drivers/psci/psci.h new file mode 100644 index 00000000000..8271180e97c --- /dev/null +++ b/drivers/psci/psci.h @@ -0,0 +1,63 @@ +/* + * Copyright 2020 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_PSCI_PSCI_H_ +#define ZEPHYR_DRIVERS_PSCI_PSCI_H_ + +#include + +#ifdef CONFIG_64BIT +#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name +#else +#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name +#endif + +/* PSCI v0.2 interface */ +#define PSCI_0_2_FN_BASE 0x84000000 +#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n)) +#define PSCI_0_2_64BIT 0x40000000 +#define PSCI_0_2_FN64_BASE \ + (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT) +#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n)) + +#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0) +#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1) +#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2) +#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3) +#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4) +#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5) +#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6) +#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7) +#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8) +#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9) + +#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1) +#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3) +#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4) +#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5) +#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7) + +/* PSCI return values (inclusive of all PSCI versions) */ +#define PSCI_RET_SUCCESS 0 +#define PSCI_RET_NOT_SUPPORTED -1 +#define PSCI_RET_INVALID_PARAMS -2 +#define PSCI_RET_DENIED -3 +#define PSCI_RET_ALREADY_ON -4 +#define PSCI_RET_ON_PENDING -5 +#define PSCI_RET_INTERNAL_FAILURE -6 +#define PSCI_RET_NOT_PRESENT -7 +#define PSCI_RET_DISABLED -8 +#define PSCI_RET_INVALID_ADDRESS -9 + +typedef unsigned long (psci_fn)(unsigned long, unsigned long, + unsigned long, unsigned long); + +struct psci { + psci_fn *invoke_psci_fn; + enum arm_smccc_conduit conduit; +}; + +#endif /* ZEPHYR_DRIVERS_PSCI_PSCI_H_ */ diff --git a/drivers/psci/psci_handlers.c b/drivers/psci/psci_handlers.c new file mode 100644 index 00000000000..9149889049b --- /dev/null +++ b/drivers/psci/psci_handlers.c @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static inline uint32_t z_vrfy_psci_get_version(const struct device *dev) +{ + Z_OOPS(Z_SYSCALL_DRIVER_PSCI(dev, get_version)); + + return z_impl_psci_get_version(dev); +} +#include + +static inline int z_vrfy_psci_cpu_off(const struct device *dev, uint32_t state) +{ + Z_OOPS(Z_SYSCALL_DRIVER_PSCI(dev, cpu_off)); + + return z_impl_psci_cpu_off(dev, state); +} +#include + +static inline int z_vrfy_psci_cpu_on(const struct device *dev, + unsigned long cpuid, + unsigned long entry_point) { + Z_OOPS(Z_SYSCALL_DRIVER_PSCI(dev, cpu_on)); + + return z_impl_psci_cpu_on(dev, cpuid, entry_point); +} +#include + +static inline int z_vrfy_psci_affinity_info(const struct device *dev, + unsigned long target_affinity, + unsigned long lowest_affinity_level) +{ + Z_OOPS(Z_SYSCALL_DRIVER_PSCI(dev, affinity_info)); + + return z_impl_psci_affinity_info(dev, target_affinity, + lowest_affinity_level); +} +#include diff --git a/dts/bindings/psci/arm,psci.yaml b/dts/bindings/psci/arm,psci.yaml new file mode 100644 index 00000000000..3f82067466a --- /dev/null +++ b/dts/bindings/psci/arm,psci.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +description: PSCI + +compatible: "arm,psci-0.2" + +include: base.yaml + +properties: + label: + required: true + + method: + type: string + required: true + description: The method of calling the PSCI firmware. + enum: + - smc + - hvc diff --git a/include/arch/arm/arm-smccc.h b/include/arch/arm/arm-smccc.h new file mode 100644 index 00000000000..90b5f42cf7f --- /dev/null +++ b/include/arch/arm/arm-smccc.h @@ -0,0 +1,53 @@ +/* + * Copyright 2020 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_ARM_SMCCC_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_ARM_SMCCC_H_ + +/* + * Result from SMC/HVC call + * @a0-a3 result values from registers 0 to 3 + */ +struct arm_smccc_res { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; +}; + +enum arm_smccc_conduit { + SMCCC_CONDUIT_NONE, + SMCCC_CONDUIT_SMC, + SMCCC_CONDUIT_HVC, +}; + +/* + * @brief Make HVC calls + * + * @param a0 function identifier + * @param a1-a7 parameters registers + * @param res results + */ +void arm_smccc_hvc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res); + +/* + * @brief Make SMC calls + * + * @param a0 function identifier + * @param a1-a7 parameters registers + * @param res results + */ +void arm_smccc_smc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res); + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_ARM_SMCCC_H_ */ diff --git a/include/drivers/psci.h b/include/drivers/psci.h new file mode 100644 index 00000000000..10dfc5c20cf --- /dev/null +++ b/include/drivers/psci.h @@ -0,0 +1,160 @@ +/* + * Copyright 2020 Carlo Caione + * + * 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 +#include +#include +#include + +#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 + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PSCI_H_ */