diff options
author | Anurag Koul <anurag.koul@arm.com> | 2020-07-13 15:42:07 +0100 |
---|---|---|
committer | jimqui01 <54316584+jimqui01@users.noreply.github.com> | 2020-09-15 17:03:53 +0100 |
commit | c4f14de50db6ee0b4c888d3b991748ada27c17bb (patch) | |
tree | 1442fc2fca48eba67bdda554d06473fc5147e329 /product/morello | |
parent | 6dfbd253de223961505d989077678dc732ba351f (diff) |
morello/module: add scmi_agent module
Add a new module, scmi_agent, to be used by MCP
for SCMI communication with SCP.
Change-Id: I6c63542e640bdba577a8458b4050efcf3f2e89fe
Signed-off-by: Anurag Koul <anurag.koul@arm.com>
Co-authored-by: Manoj Kumar <manoj.kumar3@arm.com>
Diffstat (limited to 'product/morello')
-rw-r--r-- | product/morello/module/scmi_agent/include/mod_scmi_agent.h | 133 | ||||
-rw-r--r-- | product/morello/module/scmi_agent/src/Makefile | 11 | ||||
-rw-r--r-- | product/morello/module/scmi_agent/src/mod_scmi_agent.c | 297 |
3 files changed, 441 insertions, 0 deletions
diff --git a/product/morello/module/scmi_agent/include/mod_scmi_agent.h b/product/morello/module/scmi_agent/include/mod_scmi_agent.h new file mode 100644 index 00000000..f93c9a61 --- /dev/null +++ b/product/morello/module/scmi_agent/include/mod_scmi_agent.h @@ -0,0 +1,133 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCMI Agent Support + */ + +#ifndef MOD_SCMI_AGENT_H +#define MOD_SCMI_AGENT_H + +#include <fwk_id.h> + +#include <stdint.h> + +/*! + * \addtogroup GroupMORELLOModule MORELLO Product Modules + * @{ + */ + +/*! + * \defgroup GroupMORELLOScmiAgent SCMI Agent Support + * @{ + */ + +/*! + * \brief SCMI agent - Management protocol ID definition. + */ +#define SCMI_PROTOCOL_ID_MANAGEMENT UINT32_C(0x89) +/*! + * \brief SCMI agent - Management protocol version definition. + */ +#define SCMI_PROTOCOL_VERSION_MANAGEMENT UINT32_C(0x10000) + +/*! + * \brief SCMI agent - Management protocol message IDs. + */ +enum scmi_management_message_id { + /*! Message ID for getting protocol version */ + SCMI_MANAGEMENT_PROTOCOL_VERSION_GET = 0x0, + /*! Message ID for getting protocol attributes */ + SCMI_MANAGEMENT_PROTOCOL_ATTRIBUTES_GET = 0x1, + /*! Message ID for getting message attributes */ + SCMI_MANAGEMENT_MESSAGE_ATTRIBUTES_GET = 0x2, + /*! Message ID for getting clock status */ + SCMI_MANAGEMENT_CLOCK_STATUS_GET = 0x3, + /*! Message ID for getting chip ID information */ + SCMI_MANAGEMENT_CHIPID_INFO_GET = 0x4, +}; + +/*! + * \brief SCMI agent configuration data. + */ +struct mod_scmi_agent_config { + /*! + * \brief Identifier of the transport entity. + */ + fwk_id_t transport_id; + + /*! + * \brief Identifier of the API of the transport entity. + */ + fwk_id_t transport_api_id; +}; + +/*! + * \brief SCMI Management Agent API Interface + * + * \details Interface used for MCP System -> SCMI Agent. + */ +struct mod_scmi_agent_api { + /*! + * \brief Get the management protocol version from SCP + * + * \param agent_id Agent identifier + * \param[out] version Protocol version. + * + * \retval FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_protocol_version)(fwk_id_t agent_id, uint32_t *version); + + /*! + * \brief Get the PLL clock status from SCP + * + * \param agent_id Agent identifier + * \param[out] clock_status SCP clock status. + * + * \retval FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_clock_status)(fwk_id_t agent_id, uint32_t *clock_status); + + /*! + * \brief Get the chip ID information from SCP + * + * \param agent_id Agent identifier + * \param[out] multichip_mode Multi-chip mode value. + * \param[out] chipid Chip ID value. + * + * \retval FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_chipid_info)( + fwk_id_t agent_id, + uint8_t *multichip_mode, + uint8_t *chipid); +}; + +/*! + * \brief API types exposed by SCMI agent module. + */ +enum mod_scmi_agent_api_idx { + /*! API ID to be binded by system module */ + MOD_SCMI_AGENT_API_IDX_SYSTEM, + /*! API ID count */ + MOD_SCMI_AGENT_API_IDX_COUNT, +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SCMI_AGENT_H */ diff --git a/product/morello/module/scmi_agent/src/Makefile b/product/morello/module/scmi_agent/src/Makefile new file mode 100644 index 00000000..72d33492 --- /dev/null +++ b/product/morello/module/scmi_agent/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 Agent +BS_LIB_SOURCES = mod_scmi_agent.c + +include $(BS_DIR)/lib.mk diff --git a/product/morello/module/scmi_agent/src/mod_scmi_agent.c b/product/morello/module/scmi_agent/src/mod_scmi_agent.c new file mode 100644 index 00000000..2a0ac31a --- /dev/null +++ b/product/morello/module/scmi_agent/src/mod_scmi_agent.c @@ -0,0 +1,297 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCMI Agent Support. + */ + +#include "internal/smt.h" +#include "morello_mcp_software_mmap.h" + +#include <mod_scmi_agent.h> +#include <mod_smt.h> + +#include <fwk_event.h> +#include <fwk_id.h> +#include <fwk_log.h> +#include <fwk_mm.h> +#include <fwk_module.h> +#include <fwk_module_idx.h> +#include <fwk_status.h> +#include <fwk_thread.h> + +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> + +/* SCMI agent context */ +struct scmi_agent_ctx { + /* Pointer to agent configuration data */ + struct mod_scmi_agent_config *config; + + /* Pointer to received payload data */ + const void *payload; + + /* Size of received payload */ + size_t size; +}; + +/* Module context */ +struct mod_scmi_agent_module_ctx { + /* Pointer to agent configuration table */ + struct scmi_agent_ctx *agent_ctx_table; + + /* SMT API pointer */ + const struct mod_scmi_agent_to_transport_api *smt_api; +}; + +enum scmi_agent_event { + MOD_SCMI_AGENT_EVENT_RUN, + MOD_SCMI_AGENT_EVENT_COUNT, +}; + +static struct mod_scmi_agent_module_ctx ctx; + +static int _scmi_agent_transact( + fwk_id_t agent_id, + struct mod_smt_command_config *cmd) +{ + struct scmi_agent_ctx *agent_ctx; + int status; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(agent_id)]; + + /* Check if channel is free */ + if (!ctx.smt_api->is_channel_free(agent_ctx->config->transport_id)) { + FWK_LOG_INFO("[SCMI AGENT] Channel Busy!"); + return FWK_E_BUSY; + } + + /* Send SCMI command to platform */ + status = ctx.smt_api->send(agent_ctx->config->transport_id, cmd); + if (status != FWK_SUCCESS) { + ctx.smt_api->put_channel(agent_ctx->config->transport_id); + return status; + } + + /* Wait until platform responds */ + while (!ctx.smt_api->is_channel_free(agent_ctx->config->transport_id)) + ; + + /* Get response payload */ + status = ctx.smt_api->get_payload( + agent_ctx->config->transport_id, &agent_ctx->payload, &agent_ctx->size); + if (status != FWK_SUCCESS) + return status; + + /* Release channel */ + status = ctx.smt_api->put_channel(agent_ctx->config->transport_id); + if (status != FWK_SUCCESS) + return status; + + return FWK_SUCCESS; +} + +/* + * SCMI Management Agent API interface + */ +static int agent_get_protocol_version(fwk_id_t agent_id, uint32_t *version) +{ + int status; + struct scmi_agent_ctx *agent_ctx; + struct mod_smt_command_config cmd = { + .protocol_id = SCMI_PROTOCOL_ID_MANAGEMENT, + .message_id = SCMI_MANAGEMENT_PROTOCOL_VERSION_GET, + .payload = NULL, + .size = 0, + }; + + if (version == NULL) + return FWK_E_PARAM; + + /* + * TODO: Temporary workaround to synchronize on MCP-SCP mailbox + * initialization performed by SCP. This should be replaced with + * notification based synchronization mechanism. + */ + while ((((volatile struct mod_smt_memory *)SCMI_PAYLOAD_SCP_TO_MCP_S) + ->status) != 1) + ; + + status = _scmi_agent_transact(agent_id, &cmd); + if (status != FWK_SUCCESS) + return status; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(agent_id)]; + *version = *(((uint32_t *)agent_ctx->payload) + 1); + + return FWK_SUCCESS; +} + +static int agent_get_clock_status(fwk_id_t agent_id, uint32_t *clock_status) +{ + int status; + struct scmi_agent_ctx *agent_ctx; + struct mod_smt_command_config cmd = { + .protocol_id = SCMI_PROTOCOL_ID_MANAGEMENT, + .message_id = SCMI_MANAGEMENT_CLOCK_STATUS_GET, + .payload = NULL, + .size = 0, + }; + + if (clock_status == NULL) + return FWK_E_PARAM; + + status = _scmi_agent_transact(agent_id, &cmd); + if (status != FWK_SUCCESS) + return status; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(agent_id)]; + *clock_status = *(((uint32_t *)agent_ctx->payload) + 1); + + return FWK_SUCCESS; +} + +static int agent_get_chipid_info( + fwk_id_t agent_id, + uint8_t *multichip_mode, + uint8_t *chipid) +{ + int status; + struct scmi_agent_ctx *agent_ctx; + struct mod_smt_command_config cmd = { + .protocol_id = SCMI_PROTOCOL_ID_MANAGEMENT, + .message_id = SCMI_MANAGEMENT_CHIPID_INFO_GET, + .payload = NULL, + .size = 0, + }; + + if ((multichip_mode == NULL) || (chipid == NULL)) + return FWK_E_PARAM; + + status = _scmi_agent_transact(agent_id, &cmd); + if (status != FWK_SUCCESS) + return status; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(agent_id)]; + *multichip_mode = (uint8_t)(*(((uint32_t *)agent_ctx->payload) + 1)); + *chipid = (uint8_t)(*(((uint32_t *)agent_ctx->payload) + 2)); + + return FWK_SUCCESS; +} + +struct mod_scmi_agent_api scmi_agent_api = { + .get_protocol_version = agent_get_protocol_version, + .get_clock_status = agent_get_clock_status, + .get_chipid_info = agent_get_chipid_info, +}; + +/* + * Functions fulfilling the framework's module interface + */ + +static int scmi_agent_init( + fwk_id_t module_id, + unsigned int agent_count, + const void *unused2) +{ + ctx.agent_ctx_table = + fwk_mm_calloc(agent_count, sizeof(ctx.agent_ctx_table[0])); + if (ctx.agent_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int scmi_agent_element_init( + fwk_id_t agent_id, + unsigned int unused, + const void *data) +{ + struct scmi_agent_ctx *agent_ctx; + struct mod_scmi_agent_config *config = (struct mod_scmi_agent_config *)data; + + if (config == NULL) + return FWK_E_PARAM; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(agent_id)]; + agent_ctx->config = config; + + return FWK_SUCCESS; +} + +static int scmi_agent_bind(fwk_id_t id, unsigned int round) +{ + struct scmi_agent_ctx *agent_ctx; + + if (round == 0) { + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + + agent_ctx = &ctx.agent_ctx_table[fwk_id_get_element_idx(id)]; + return fwk_module_bind( + agent_ctx->config->transport_id, + agent_ctx->config->transport_api_id, + &ctx.smt_api); + } + return FWK_SUCCESS; +} + +static int scmi_agent_start(fwk_id_t id) +{ + /* Process only in the element start stage */ + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + + struct fwk_event event = { + .source_id = id, + .target_id = id, + .id = FWK_ID_EVENT(FWK_MODULE_IDX_SCMI_AGENT, MOD_SCMI_AGENT_EVENT_RUN), + }; + + return fwk_thread_put_event(&event); +} + +static int scmi_agent_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &scmi_agent_api; + return FWK_SUCCESS; +} + +static int scmi_agent_process_event( + const struct fwk_event *event, + struct fwk_event *resp) +{ + int status; + uint32_t temp = 0; + + status = agent_get_protocol_version(event->target_id, &temp); + if (status != FWK_SUCCESS) + return status; + + FWK_LOG_INFO( + "[SCMI AGENT] Found management protocol version: 0x%x", + (unsigned int)temp); + + return status; +} + +const struct fwk_module module_scmi_agent = { + .name = "SCMI AGENT", + .type = FWK_MODULE_TYPE_SERVICE, + .api_count = MOD_SCMI_AGENT_API_IDX_COUNT, + .event_count = MOD_SCMI_AGENT_EVENT_COUNT, + .init = scmi_agent_init, + .element_init = scmi_agent_element_init, + .bind = scmi_agent_bind, + .start = scmi_agent_start, + .process_bind_request = scmi_agent_process_bind_request, + .process_event = scmi_agent_process_event, +}; |