From 6dfbd253de223961505d989077678dc732ba351f Mon Sep 17 00:00:00 2001 From: Anurag Koul Date: Thu, 10 Sep 2020 18:50:20 +0100 Subject: morello/module: add scmi_management module Add a protocol type module for facilitating SCMI communication between MCP and SCP. Signed-off-by: Anurag Koul Change-Id: Ie62493f90af6b29674b45a74f3e1dbe3e8f0c5ca --- product/morello/include/morello_mcp_scmi.h | 17 ++ .../scmi_management/include/mod_scmi_management.h | 77 +++++ .../morello/module/scmi_management/src/Makefile | 11 + .../scmi_management/src/mod_scmi_management.c | 323 +++++++++++++++++++++ .../morello/scp_ramfw_fvp/config_scmi_management.c | 11 + product/morello/scp_ramfw_fvp/firmware.mk | 2 + 6 files changed, 441 insertions(+) create mode 100644 product/morello/include/morello_mcp_scmi.h create mode 100644 product/morello/module/scmi_management/include/mod_scmi_management.h create mode 100644 product/morello/module/scmi_management/src/Makefile create mode 100644 product/morello/module/scmi_management/src/mod_scmi_management.c create mode 100644 product/morello/scp_ramfw_fvp/config_scmi_management.c diff --git a/product/morello/include/morello_mcp_scmi.h b/product/morello/include/morello_mcp_scmi.h new file mode 100644 index 00000000..b7124088 --- /dev/null +++ b/product/morello/include/morello_mcp_scmi.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MORELLO_MCP_SCMI_H +#define MORELLO_MCP_SCMI_H + +/* SCMI agent identifiers */ +enum mcp_morello_scmi_agent_idx { + MCP_MORELLO_SCMI_AGENT_IDX_MANAGEMENT, + MCP_MORELLO_SCMI_AGENT_IDX_COUNT, +}; + +#endif /* MORELLO_MCP_SCMI_H */ diff --git a/product/morello/module/scmi_management/include/mod_scmi_management.h b/product/morello/module/scmi_management/include/mod_scmi_management.h new file mode 100644 index 00000000..3de45193 --- /dev/null +++ b/product/morello/module/scmi_management/include/mod_scmi_management.h @@ -0,0 +1,77 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCMI Management Protocol Support. + */ + +#ifndef MOD_SCMI_MANAGEMENT_H +#define MOD_SCMI_MANAGEMENT_H + +#include +#include + +/*! + * \addtogroup GroupMORELLOModule MORELLO Product Modules + * @{ + */ + +/*! + * \defgroup GroupMORELLOSCMI_MANAGEMENT SCMI Management Protocol + * @{ + */ + +/*! + * \brief Macro defining the SCMI Management Protocol's ID. + */ +#define SCMI_PROTOCOL_ID_MANAGEMENT UINT32_C(0x89) + +/*! + * \brief Macro defining the SCMI Management Protocol's version. + */ +#define SCMI_PROTOCOL_VERSION_MANAGEMENT UINT32_C(0x10000) + +/*! + * \brief Identifiers of the SCMI Management Protocol commands. + */ +enum scmi_management_command_id { + /*! Command ID for getting clock status */ + SCMI_MANAGEMENT_CLOCK_STATUS_GET = 0x3, + /*! Commmand ID for chip ID information */ + SCMI_MANAGEMENT_CHIPID_INFO_GET = 0x4, +}; + +/*! + * \brief Protocol handler for getting clock status from SCP. + */ +struct scmi_management_clock_status_get_p2a { + /*! SCMI status */ + int32_t status; + /*! Clock status */ + uint32_t clock_status; +}; + +/*! + * \brief Protocol handler for chip ID information. + */ +struct scmi_management_chipid_info_get_p2a { + /*! SCMI status */ + int32_t status; + /*! Multi chip mode identifier */ + uint32_t multi_chip_mode; + /*! Chip ID of the chip if multi_chip_mode is set */ + uint32_t chipid; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SCMI_MANAGEMENT_H */ diff --git a/product/morello/module/scmi_management/src/Makefile b/product/morello/module/scmi_management/src/Makefile new file mode 100644 index 00000000..313077a5 --- /dev/null +++ b/product/morello/module/scmi_management/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := SCMI Management Protocol +BS_LIB_SOURCES := mod_scmi_management.c + +include $(BS_DIR)/lib.mk diff --git a/product/morello/module/scmi_management/src/mod_scmi_management.c b/product/morello/module/scmi_management/src/mod_scmi_management.c new file mode 100644 index 00000000..9e781343 --- /dev/null +++ b/product/morello/module/scmi_management/src/mod_scmi_management.c @@ -0,0 +1,323 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCMI Management Protocol Support. + */ + +#include "morello_scc_reg.h" +#include "morello_scp_pik.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct scmi_management_ctx { + /* SCMI module API */ + const struct mod_scmi_from_protocol_api *scmi_api; +}; + +static int scmi_management_protocol_version_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_management_protocol_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_management_protocol_message_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_management_clock_status_get_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_management_chipid_info_get_handler( + fwk_id_t service_id, + const uint32_t *payload); + +/* + * Internal variables. + */ +static struct scmi_management_ctx scmi_management_ctx; + +static int (*const handler_table[])(fwk_id_t, const uint32_t *) = { + [MOD_SCMI_PROTOCOL_VERSION] = scmi_management_protocol_version_handler, + [MOD_SCMI_PROTOCOL_ATTRIBUTES] = + scmi_management_protocol_attributes_handler, + [MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = + scmi_management_protocol_message_attributes_handler, + [SCMI_MANAGEMENT_CLOCK_STATUS_GET] = + scmi_management_clock_status_get_handler, + [SCMI_MANAGEMENT_CHIPID_INFO_GET] = scmi_management_chipid_info_get_handler, +}; + +static const unsigned int payload_size_table[] = { + [MOD_SCMI_PROTOCOL_VERSION] = 0, + [MOD_SCMI_PROTOCOL_ATTRIBUTES] = 0, + [MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = 0, + [SCMI_MANAGEMENT_CLOCK_STATUS_GET] = 0, + [SCMI_MANAGEMENT_CHIPID_INFO_GET] = 0, +}; + +/* + * Protocol Version + */ +static int scmi_management_protocol_version_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_MANAGEMENT, + }; + + scmi_management_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + return FWK_SUCCESS; +} + +/* + * Protocol Attributes + */ +static int scmi_management_protocol_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = 0, + }; + + scmi_management_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + + return FWK_SUCCESS; +} + +/* + * Protocol Message Attributes + */ +static int scmi_management_protocol_message_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + size_t response_size; + const struct scmi_protocol_message_attributes_a2p *parameters; + unsigned int message_id; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = 0, + }; + + parameters = (const struct scmi_protocol_message_attributes_a2p *)payload; + message_id = parameters->message_id; + + if ((message_id >= FWK_ARRAY_SIZE(handler_table)) || + (handler_table[message_id] == NULL)) + return_values.status = SCMI_NOT_FOUND; + + response_size = (return_values.status == SCMI_SUCCESS) ? + sizeof(return_values) : + sizeof(return_values.status); + + scmi_management_ctx.scmi_api->respond( + service_id, &return_values, response_size); + + return FWK_SUCCESS; +} + +/* + * Clock Status Get + */ +static int scmi_management_clock_status_get_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + int status; + unsigned int agent_id; + enum scmi_agent_type agent_type; + struct scmi_management_clock_status_get_p2a return_values = { + .status = SCMI_GENERIC_ERROR, + }; + + status = scmi_management_ctx.scmi_api->get_agent_id(service_id, &agent_id); + if (status != FWK_SUCCESS) + goto exit; + + status = + scmi_management_ctx.scmi_api->get_agent_type(agent_id, &agent_type); + if (status != FWK_SUCCESS) + goto exit; + + /* Only the Management agent may get the clock status */ + if (agent_type != SCMI_AGENT_TYPE_MANAGEMENT) { + return_values.status = SCMI_DENIED; + status = FWK_E_ACCESS; + goto exit; + } + + return_values.status = SCMI_SUCCESS; + return_values.clock_status = 1; + +exit: + scmi_management_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + return status; +} + +/* + * CHIP ID Information Get + */ +static int scmi_management_chipid_info_get_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + int status; + uint32_t chip_info; + unsigned int agent_id; + enum scmi_agent_type agent_type; + struct scmi_management_chipid_info_get_p2a return_values = { + .status = SCMI_GENERIC_ERROR, + }; + + status = scmi_management_ctx.scmi_api->get_agent_id(service_id, &agent_id); + if (status != FWK_SUCCESS) + goto exit; + + status = + scmi_management_ctx.scmi_api->get_agent_type(agent_id, &agent_type); + if (status != FWK_SUCCESS) + goto exit; + + /* Only the Management agent may get the CHIP ID information */ + if (agent_type != SCMI_AGENT_TYPE_MANAGEMENT) { + return_values.status = SCMI_DENIED; + status = FWK_E_ACCESS; + goto exit; + } + + chip_info = SCC->PLATFORM_CTRL; + return_values.status = SCMI_SUCCESS; + return_values.multi_chip_mode = + ((chip_info & SCC_PLATFORM_CTRL_MULTI_CHIP_MODE_MASK) >> + SCC_PLATFORM_CTRL_MULTI_CHIP_MODE_POS); + return_values.chipid = + ((chip_info & SCC_PLATFORM_CTRL_CHIPID_MASK) >> + SCC_PLATFORM_CTRL_CHIPID_POS); + +exit: + scmi_management_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + return status; +} + +/* + * SCMI module -> SCMI Management module interface + */ +static int scmi_management_get_scmi_protocol_id( + fwk_id_t protocol_id, + uint8_t *scmi_protocol_id) +{ + *scmi_protocol_id = SCMI_PROTOCOL_ID_MANAGEMENT; + + return FWK_SUCCESS; +} + +static int scmi_management_message_handler( + fwk_id_t protocol_id, + fwk_id_t service_id, + const uint32_t *payload, + size_t payload_size, + unsigned int message_id) +{ + int32_t return_value; + + static_assert( + FWK_ARRAY_SIZE(handler_table) == FWK_ARRAY_SIZE(payload_size_table), + "[SCMI] Management protocol table sizes not consistent"); + assert(payload != NULL); + + if (message_id >= FWK_ARRAY_SIZE(handler_table)) { + return_value = SCMI_NOT_FOUND; + goto error; + } + + if (payload_size != payload_size_table[message_id]) { + return_value = SCMI_PROTOCOL_ERROR; + goto error; + } + + return handler_table[message_id](service_id, payload); + +error: + scmi_management_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); + + return FWK_SUCCESS; +} + +static struct mod_scmi_to_protocol_api + scmi_management_mod_scmi_to_protocol_api = { + .get_scmi_protocol_id = scmi_management_get_scmi_protocol_id, + .message_handler = scmi_management_message_handler + }; + +/* + * Framework handlers + */ + +static int scmi_management_init( + fwk_id_t module_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int scmi_management_bind(fwk_id_t id, unsigned int round) +{ + if (round == 1) + return FWK_SUCCESS; + + /* Bind to the SCMI module, storing an API pointer for later use. */ + return fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_SCMI), + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_PROTOCOL), + &scmi_management_ctx.scmi_api); +} + +static int scmi_management_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + /* Only accept binding requests from the SCMI module. */ + if (!fwk_id_is_equal(source_id, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI))) + return FWK_E_ACCESS; + + *api = &scmi_management_mod_scmi_to_protocol_api; + + return FWK_SUCCESS; +} + +const struct fwk_module module_scmi_management = { + .name = "SCMI Management Protocol", + .api_count = 1, + .type = FWK_MODULE_TYPE_PROTOCOL, + .init = scmi_management_init, + .bind = scmi_management_bind, + .process_bind_request = scmi_management_process_bind_request, +}; diff --git a/product/morello/scp_ramfw_fvp/config_scmi_management.c b/product/morello/scp_ramfw_fvp/config_scmi_management.c new file mode 100644 index 00000000..87862581 --- /dev/null +++ b/product/morello/scp_ramfw_fvp/config_scmi_management.c @@ -0,0 +1,11 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_management = { 0 }; diff --git a/product/morello/scp_ramfw_fvp/firmware.mk b/product/morello/scp_ramfw_fvp/firmware.mk index 754226f3..6f54ed8b 100644 --- a/product/morello/scp_ramfw_fvp/firmware.mk +++ b/product/morello/scp_ramfw_fvp/firmware.mk @@ -35,6 +35,7 @@ BS_FIRMWARE_MODULES := \ timer \ scmi_power_domain \ scmi_system_power \ + scmi_management \ fip \ ssc \ system_info \ @@ -60,6 +61,7 @@ BS_FIRMWARE_SOURCES := \ config_scmi_system_power.c \ config_scmi_power_domain.c \ config_pl011.c \ + config_scmi_management.c \ config_morello_pll.c \ config_pik_clock.c \ config_css_clock.c \ -- cgit v1.2.3