aboutsummaryrefslogtreecommitdiff
path: root/product/morello
diff options
context:
space:
mode:
authorAnurag Koul <anurag.koul@arm.com>2020-07-13 15:42:07 +0100
committerjimqui01 <54316584+jimqui01@users.noreply.github.com>2020-09-15 17:03:53 +0100
commitc4f14de50db6ee0b4c888d3b991748ada27c17bb (patch)
tree1442fc2fca48eba67bdda554d06473fc5147e329 /product/morello
parent6dfbd253de223961505d989077678dc732ba351f (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.h133
-rw-r--r--product/morello/module/scmi_agent/src/Makefile11
-rw-r--r--product/morello/module/scmi_agent/src/mod_scmi_agent.c297
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,
+};