From bfe3c449a748ee170718c2bcfddf2fe8f071f9bc Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 3 Apr 2018 14:58:17 +0100 Subject: [PATCH 1/2] Add support for SCMI AP core configuration protocol v1.0 Change-Id: If07000b6b19011e960336a305a784dd643301b97 Signed-off-by: Dimitris Papastamos --- plat/arm/css/common/css_common.mk | 1 + plat/arm/css/drivers/scmi/scmi.h | 18 +++++ .../arm/css/drivers/scmi/scmi_ap_core_proto.c | 77 +++++++++++++++++++ plat/arm/css/drivers/scmi/scmi_private.h | 11 +++ 4 files changed, 107 insertions(+) create mode 100644 plat/arm/css/drivers/scmi/scmi_ap_core_proto.c diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk index 72d5527b6..29dd01d19 100644 --- a/plat/arm/css/common/css_common.mk +++ b/plat/arm/css/common/css_common.mk @@ -32,6 +32,7 @@ BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scpi.c \ plat/arm/css/drivers/scpi/css_scpi.c else BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scmi.c \ + plat/arm/css/drivers/scmi/scmi_ap_core_proto.c \ plat/arm/css/drivers/scmi/scmi_common.c \ plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c \ plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c \ diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h index cf9ef5e9a..723fd06ed 100644 --- a/plat/arm/css/drivers/scmi/scmi.h +++ b/plat/arm/css/drivers/scmi/scmi.h @@ -12,6 +12,7 @@ #include /* Supported SCMI Protocol Versions */ +#define SCMI_AP_CORE_PROTO_VER MAKE_SCMI_VERSION(1, 0) #define SCMI_PWR_DMN_PROTO_VER MAKE_SCMI_VERSION(1, 0) #define SCMI_SYS_PWR_PROTO_VER MAKE_SCMI_VERSION(1, 0) @@ -29,6 +30,8 @@ /* SCMI Protocol identifiers */ #define SCMI_PWR_DMN_PROTO_ID 0x11 #define SCMI_SYS_PWR_PROTO_ID 0x12 +/* The AP core protocol is a CSS platform-specific extension */ +#define SCMI_AP_CORE_PROTO_ID 0x90 /* Mandatory messages IDs for all SCMI protocols */ #define SCMI_PROTO_VERSION_MSG 0x0 @@ -43,6 +46,10 @@ #define SCMI_SYS_PWR_STATE_SET_MSG 0x3 #define SCMI_SYS_PWR_STATE_GET_MSG 0x4 +/* SCMI AP core protocol message IDs */ +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG 0x3 +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG 0x4 + /* Helper macros for system power management protocol commands */ /* @@ -73,6 +80,13 @@ #define SCMI_SYS_PWR_POWER_UP 0x3 #define SCMI_SYS_PWR_SUSPEND 0x4 +/* + * Macros to describe the bit-fields of the `attribute` of AP core protocol + * AP_CORE_RESET_ADDR set/get messages. + */ +#define SCMI_AP_CORE_LOCK_ATTR_SHIFT 0x0 +#define SCMI_AP_CORE_LOCK_ATTR (1U << SCMI_AP_CORE_LOCK_ATTR_SHIFT) + /* SCMI Error code definitions */ #define SCMI_E_QUEUED 1 #define SCMI_E_SUCCESS 0 @@ -133,4 +147,8 @@ int scmi_pwr_state_get(void *p, uint32_t domain_id, uint32_t *scmi_pwr_state); int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state); int scmi_sys_pwr_state_get(void *p, uint32_t *system_state); +/* SCMI AP core configuration protocol commands. */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr); +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr); + #endif /* __CSS_SCMI_H__ */ diff --git a/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c b/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c new file mode 100644 index 000000000..1438cba46 --- /dev/null +++ b/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "scmi.h" +#include "scmi_private.h" + +/* + * API to set the SCMI AP core reset address and attributes + */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr) +{ + mailbox_mem_t *mbx_mem; + int token = 0, ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_SET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG3(mbx_mem->payload, reset_addr & 0xffffffff, + reset_addr >> 32, attr); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI AP core reset address and attributes + */ +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr) +{ + mailbox_mem_t *mbx_mem; + int token = 0, ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + uint32_t lo_addr, hi_addr; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_GET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL4(mbx_mem->payload, ret, lo_addr, hi_addr, *attr); + *reset_addr = lo_addr | (uint64_t)hi_addr << 32; + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/plat/arm/css/drivers/scmi/scmi_private.h b/plat/arm/css/drivers/scmi/scmi_private.h index 67fe7481f..39bc8ccb3 100644 --- a/plat/arm/css/drivers/scmi/scmi_private.h +++ b/plat/arm/css/drivers/scmi/scmi_private.h @@ -18,6 +18,12 @@ #define SCMI_PROTO_MSG_ATTR_MSG_LEN 8 #define SCMI_PROTO_MSG_ATTR_RESP_LEN 12 +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN 16 +#define SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN 8 + +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN 4 +#define SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN 20 + #define SCMI_PWR_STATE_SET_MSG_LEN 16 #define SCMI_PWR_STATE_SET_RESP_LEN 8 @@ -113,6 +119,11 @@ (val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \ } while (0) +#define SCMI_PAYLOAD_RET_VAL4(payld_arr, val1, val2, val3, val4) do { \ + SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3); \ + (val4) = mmio_read_32((uintptr_t)&payld_arr[3]); \ + } while (0) + /* * Private data structure for representing the mailbox memory layout. Refer * the SCMI specification for more details. From 2a246d2e3284d853d1276b9495518aa52d8dba3c Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Mon, 18 Jun 2018 13:01:06 +0100 Subject: [PATCH 2/2] CSS: Use SCMI AP core protocol to set the warm boot entrypoint Change-Id: Iaebbeac1a1d6fbd531e5694b95ed068b7a193e62 Signed-off-by: Dimitris Papastamos --- include/plat/arm/common/plat_arm.h | 2 +- plat/arm/common/arm_bl1_setup.c | 2 +- plat/arm/common/arm_common.mk | 2 +- plat/arm/common/arm_pm.c | 9 +++--- plat/arm/css/drivers/scp/css_pm_scmi.c | 41 ++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 33f2c7dbe..473b758a3 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -171,7 +171,6 @@ int arm_validate_psci_entrypoint(uintptr_t entrypoint); int arm_validate_ns_entrypoint(uintptr_t entrypoint); void arm_system_pwr_domain_save(void); void arm_system_pwr_domain_resume(void); -void arm_program_trusted_mailbox(uintptr_t address); int arm_psci_read_mem_protect(int *enabled); int arm_nor_psci_write_mem_protect(int val); void arm_nor_psci_do_static_mem_protect(void); @@ -250,6 +249,7 @@ void plat_arm_pwrc_setup(void); void plat_arm_interconnect_init(void); void plat_arm_interconnect_enter_coherency(void); void plat_arm_interconnect_exit_coherency(void); +void plat_arm_program_trusted_mailbox(uintptr_t address); #if ARM_PLAT_MT unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index d141f647e..34e0a29e3 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -144,7 +144,7 @@ void bl1_plat_prepare_exit(entry_point_info_t *ep_info) * in order to release secondary CPUs from their holding pen and make * them jump there. */ - arm_program_trusted_mailbox(ep_info->pc); + plat_arm_program_trusted_mailbox(ep_info->pc); dsbsy(); sev(); #endif diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 533084708..67b574de6 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -166,7 +166,7 @@ BL1_SOURCES += drivers/arm/sp805/sp805.c \ plat/arm/common/arm_err.c \ plat/arm/common/arm_io_storage.c ifdef EL3_PAYLOAD_BASE -# Need the arm_program_trusted_mailbox() function to release secondary CPUs from +# Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from # their holding pen BL1_SOURCES += plat/arm/common/arm_pm.c endif diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index 4632099e7..73d7106bd 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -14,8 +14,9 @@ #include #include -/* Allow ARM Standard platforms to override this function */ +/* Allow ARM Standard platforms to override these functions */ #pragma weak plat_arm_psci_override_pm_ops +#pragma weak plat_arm_program_trusted_mailbox /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ extern plat_psci_ops_t plat_arm_psci_pm_ops; @@ -192,11 +193,11 @@ void arm_system_pwr_domain_resume(void) } /******************************************************************************* - * Private function to program the mailbox for a cpu before it is released + * ARM platform function to program the mailbox for a cpu before it is released * from reset. This function assumes that the Trusted mail box base is within * the ARM_SHARED_RAM region ******************************************************************************/ -void arm_program_trusted_mailbox(uintptr_t address) +void plat_arm_program_trusted_mailbox(uintptr_t address) { uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; @@ -221,6 +222,6 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); /* Setup mailbox with entry point. */ - arm_program_trusted_mailbox(sec_entrypoint); + plat_arm_program_trusted_mailbox(sec_entrypoint); return 0; } diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c index 715bf980b..703226771 100644 --- a/plat/arm/css/drivers/scp/css_pm_scmi.c +++ b/plat/arm/css/drivers/scp/css_pm_scmi.c @@ -306,6 +306,28 @@ static scmi_channel_plat_info_t plat_css_scmi_plat_info = { .ring_doorbell = &mhu_ring_doorbell, }; +static int scmi_ap_core_init(scmi_channel_t *ch) +{ +#if PROGRAMMABLE_RESET_ADDRESS + uint32_t version; + int ret; + + ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version); + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI AP core protocol version message failed\n"); + return -1; + } + + if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) { + WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_AP_CORE_PROTO_VER); + return -1; + } + INFO("SCMI AP core protocol version 0x%x detected\n", version); +#endif + return 0; +} + void plat_arm_pwrc_setup(void) { channel.info = &plat_css_scmi_plat_info; @@ -315,6 +337,10 @@ void plat_arm_pwrc_setup(void) ERROR("SCMI Initialization failed\n"); panic(); } + if (scmi_ap_core_init(&channel) < 0) { + ERROR("SCMI AP core protocol initialization failed\n"); + panic(); + } } /****************************************************************************** @@ -386,3 +412,18 @@ int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie) */ return 0; } + +#if PROGRAMMABLE_RESET_ADDRESS +void plat_arm_program_trusted_mailbox(uintptr_t address) +{ + int ret; + + assert(scmi_handle); + ret = scmi_ap_core_set_reset_addr(scmi_handle, address, + SCMI_AP_CORE_LOCK_ATTR); + if (ret != SCMI_E_SUCCESS) { + ERROR("CSS: Failed to program reset address: %d\n", ret); + panic(); + } +} +#endif