Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PSCI driver #30911

Merged
merged 2 commits into from
Jan 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
/drivers/peci/ @albertofloyd @franciscomunoz @scottwcpg
/drivers/pinmux/*hsdk* @iriszzw
/drivers/pinmux/*it8xxx2* @ite
/drivers/psci/ @carlocaione
/drivers/ps2/ @albertofloyd @franciscomunoz @scottwcpg
/drivers/pwm/*sam0* @nzmichaelh
/drivers/pwm/*stm32* @gmarull
Expand Down Expand Up @@ -350,6 +351,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
Expand All @@ -376,13 +378,15 @@
/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
/include/arch/arc/v2/irq.h @andrewboie
/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
Expand Down
11 changes: 11 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions arch/arm/core/aarch64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
40 changes: 40 additions & 0 deletions arch/arm/core/aarch64/smccc-call.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2019 Carlo Caione <ccaione@baylibre.com>
*
* 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 <toolchain.h>
#include <linker/sections.h>
#include <arch/cpu.h>

carlocaione marked this conversation as resolved.
Show resolved Hide resolved
.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
6 changes: 6 additions & 0 deletions boards/arm/qemu_cortex_a53/qemu_cortex_a53.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions boards/arm/qemu_cortex_a53/qemu_cortex_a53_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,6 @@ source "drivers/memc/Kconfig"

source "drivers/virtualization/Kconfig"

source "drivers/psci/Kconfig"

endmenu
6 changes: 6 additions & 0 deletions drivers/psci/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
22 changes: 22 additions & 0 deletions drivers/psci/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# PSCI driver configuration options

# Copyright (c) 2020 Carlo Caione <ccaione@baylibre.com>
# 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
159 changes: 159 additions & 0 deletions drivers/psci/psci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright 2020 Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT arm_psci_0_2

#define LOG_LEVEL CONFIG_PSCI_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(psci);

#include <kernel.h>
#include <arch/cpu.h>

#include <soc.h>
#include <device.h>
#include <init.h>

#include <drivers/psci.h>
#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);
63 changes: 63 additions & 0 deletions drivers/psci/psci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2020 Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_DRIVERS_PSCI_PSCI_H_
#define ZEPHYR_DRIVERS_PSCI_PSCI_H_

#include <drivers/psci.h>

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