diff options
author | Anurag Koul <anurag.koul@arm.com> | 2020-06-09 15:21:56 +0100 |
---|---|---|
committer | jimqui01 <54316584+jimqui01@users.noreply.github.com> | 2020-09-15 17:03:53 +0100 |
commit | 6692e56d78e38aad58af382a3faa5f2d142d7e31 (patch) | |
tree | c9bc45d5c17d400106ee6fbe8302b3e1c4295a62 /product/morello | |
parent | d490f22a679365133e11f1db8dfe88ea730f61d4 (diff) |
morello: add morello_mhu module
This patch adds a module, morello_mhu, which is based on core
mhu module but is modified to work for Morello platform until
SCMI agent support is added.
Change-Id: I653f515d513011c10e1131b30ee0ba33fd1ef3ff
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/include/morello_mcp_mhu.h | 16 | ||||
-rw-r--r-- | product/morello/module/morello_mhu/include/internal/mhu.h | 31 | ||||
-rw-r--r-- | product/morello/module/morello_mhu/include/mod_mhu.h | 54 | ||||
-rw-r--r-- | product/morello/module/morello_mhu/src/Makefile | 11 | ||||
-rw-r--r-- | product/morello/module/morello_mhu/src/mod_mhu.c | 264 |
5 files changed, 376 insertions, 0 deletions
diff --git a/product/morello/include/morello_mcp_mhu.h b/product/morello/include/morello_mcp_mhu.h new file mode 100644 index 00000000..baafedb6 --- /dev/null +++ b/product/morello/include/morello_mcp_mhu.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MORELLO_MCP_MHU_H +#define MORELLO_MCP_MHU_H + +enum mcp_morello_mhu_device_idx { + MORELLO_MHU_DEVICE_IDX_S_SCP, + MORELLO_MHU_DEVICE_IDX_COUNT, +}; + +#endif /* MORELLO_MCP_MHU_H */ diff --git a/product/morello/module/morello_mhu/include/internal/mhu.h b/product/morello/module/morello_mhu/include/internal/mhu.h new file mode 100644 index 00000000..ec9fe2e7 --- /dev/null +++ b/product/morello/module/morello_mhu/include/internal/mhu.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERNAL_MHU_H +#define INTERNAL_MHU_H + +#include <mod_mhu.h> + +#include <fwk_macros.h> + +#include <stdint.h> + +/*! + * \brief MHU Register Definitions + */ +struct mhu_reg { + /*! Status register */ + FWK_R uint32_t STAT; + uint32_t RESERVED0; + /*! Set register (sets the value of STAT) */ + FWK_W uint32_t SET; + uint32_t RESERVED1; + /*! Clear register (clears STAT) */ + FWK_W uint32_t CLEAR; +}; + +#endif /* INTERNAL_MHU_H */ diff --git a/product/morello/module/morello_mhu/include/mod_mhu.h b/product/morello/module/morello_mhu/include/mod_mhu.h new file mode 100644 index 00000000..8b74e4a6 --- /dev/null +++ b/product/morello/module/morello_mhu/include/mod_mhu.h @@ -0,0 +1,54 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) Device Driver. + */ + +#ifndef MOD_MHU_H +#define MOD_MHU_H + +#include <fwk_macros.h> + +#include <stdint.h> + +/*! + * \addtogroup GroupMORELLOModule MORELLO Product Modules + * @{ + */ + +/*! + * \defgroup GroupMORELLOMHU MORELLO Message Handling Unit (MHU) Driver + * @{ + */ + +/*! + * \brief MHU device + * + * \details Abstract representation of a bidirectional MHU device that consists + * of a single receive interrupt line and a pair of register sets, one for + * each direction of communication. + */ +struct mod_mhu_device_config { + /*! IRQ number of the receive interrupt line */ + unsigned int irq; + + /*! Base address of the registers of the incoming MHU */ + uintptr_t in; + + /*! Base address of the registers of the outgoing MHU */ + uintptr_t out; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_MHU_H */ diff --git a/product/morello/module/morello_mhu/src/Makefile b/product/morello/module/morello_mhu/src/Makefile new file mode 100644 index 00000000..356bc110 --- /dev/null +++ b/product/morello/module/morello_mhu/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := MORELLO MHU +BS_LIB_SOURCES := mod_mhu.c + +include $(BS_DIR)/lib.mk diff --git a/product/morello/module/morello_mhu/src/mod_mhu.c b/product/morello/module/morello_mhu/src/mod_mhu.c new file mode 100644 index 00000000..e811e9cf --- /dev/null +++ b/product/morello/module/morello_mhu/src/mod_mhu.c @@ -0,0 +1,264 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) Device Driver. + */ + +#include <internal/mhu.h> + +#include <mod_mhu.h> +#include <mod_smt.h> + +#include <fwk_id.h> +#include <fwk_interrupt.h> +#include <fwk_mm.h> +#include <fwk_module.h> +#include <fwk_module_idx.h> +#include <fwk_status.h> + +#include <stddef.h> +#include <stdint.h> + +/* + * Maximum number of slots per MHU device. The maximum number of slots is 31 and + * not 32 because bit [31] in the MHU STAT register is reserved in secure MHUs + * for indicating that a non-secure access attempt occurred. This reservation + * also applies to non-secure MHUs for consistency, though the bit is unused. + */ +#define MHU_SLOT_COUNT_MAX 31 + +struct mhu_smt_channel { + fwk_id_t id; + struct mod_smt_driver_input_api *api; +}; + +/* MHU device context */ +struct mhu_device_ctx { + /* Pointer to the device configuration */ + const struct mod_mhu_device_config *config; + + /* Number of slots (represented by sub-elements) */ + unsigned int slot_count; + + /* Mask of slots that are bound to an SMT channel */ + uint32_t bound_slots; + + /* Table of SMT channels bound to the device */ + struct mhu_smt_channel *smt_channel_table; +}; + +/* MHU context */ +struct mhu_ctx { + /* Table of device contexts */ + struct mhu_device_ctx *device_ctx_table; + + /* Number of devices in the device context table*/ + unsigned int device_count; +}; + +static struct mhu_ctx mhu_ctx; + +static void mhu_isr(void) +{ + int status; + unsigned int interrupt; + unsigned int device_idx; + struct mhu_device_ctx *device_ctx; + struct mhu_reg *reg; + unsigned int slot; + struct mhu_smt_channel *smt_channel; + + status = fwk_interrupt_get_current(&interrupt); + if (status != FWK_SUCCESS) + return; + + for (device_idx = 0; device_idx < mhu_ctx.device_count; device_idx++) { + device_ctx = &mhu_ctx.device_ctx_table[device_idx]; + if (device_ctx->config->irq == interrupt) + break; + } + + if (device_idx >= mhu_ctx.device_count) + return; + + reg = (struct mhu_reg *)device_ctx->config->in; + + /* Loop over all the slots */ + while (reg->STAT != 0) { + slot = __builtin_ctz(reg->STAT); + + /* + * If the slot is bound to an SMT channel, signal the message to the + * SMT channel. + */ + if (device_ctx->bound_slots & (1 << slot)) { + smt_channel = &device_ctx->smt_channel_table[slot]; + smt_channel->api->signal_message(smt_channel->id); + } + + /* Acknowledge the interrupt */ + reg->CLEAR = 1 << slot; + } +} + +/* + * SMT module driver API + */ + +static int raise_interrupt(fwk_id_t slot_id) +{ + struct mhu_device_ctx *device_ctx; + unsigned int slot; + struct mhu_reg *reg; + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(slot_id)]; + slot = fwk_id_get_sub_element_idx(slot_id); + reg = (struct mhu_reg *)device_ctx->config->out; + + reg->SET |= (1 << slot); + + return FWK_SUCCESS; +} + +const struct mod_smt_driver_api mhu_mod_smt_driver_api = { + .raise_interrupt = raise_interrupt, +}; + +/* + * Framework handlers + */ + +static int mhu_init( + fwk_id_t module_id, + unsigned int device_count, + const void *unused) +{ + if (device_count == 0) + return FWK_E_PARAM; + + mhu_ctx.device_ctx_table = + fwk_mm_calloc(device_count, sizeof(mhu_ctx.device_ctx_table[0])); + if (mhu_ctx.device_ctx_table == NULL) + return FWK_E_NOMEM; + + mhu_ctx.device_count = device_count; + + return FWK_SUCCESS; +} + +static int mhu_device_init( + fwk_id_t device_id, + unsigned int slot_count, + const void *data) +{ + struct mod_mhu_device_config *config = (struct mod_mhu_device_config *)data; + struct mhu_device_ctx *device_ctx; + + if ((config->in == 0) || (config->out == 0)) + return FWK_E_PARAM; + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(device_id)]; + + device_ctx->smt_channel_table = + fwk_mm_calloc(slot_count, sizeof(device_ctx->smt_channel_table[0])); + if (device_ctx->smt_channel_table == NULL) + return FWK_E_NOMEM; + + device_ctx->config = config; + device_ctx->slot_count = slot_count; + + return FWK_SUCCESS; +} + +static int mhu_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct mhu_device_ctx *device_ctx; + unsigned int slot; + struct mhu_smt_channel *smt_channel; + + if ((round == 1) && fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) { + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + for (slot = 0; slot < MHU_SLOT_COUNT_MAX; slot++) { + if (!(device_ctx->bound_slots & (1 << slot))) + continue; + + smt_channel = &device_ctx->smt_channel_table[slot]; + + status = fwk_module_bind( + smt_channel->id, + FWK_ID_API( + FWK_MODULE_IDX_MORELLO_SMT, MOD_SMT_API_IDX_DRIVER_INPUT), + &smt_channel->api); + if (status != FWK_SUCCESS) + return status; + } + } + + return FWK_SUCCESS; +} + +static int mhu_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + struct mhu_device_ctx *device_ctx; + unsigned int slot; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_SUB_ELEMENT)) + return FWK_E_ACCESS; + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(target_id)]; + slot = fwk_id_get_sub_element_idx(target_id); + + if (device_ctx->bound_slots & (1 << slot)) + return FWK_E_ACCESS; + + device_ctx->smt_channel_table[slot].id = source_id; + device_ctx->bound_slots |= 1 << slot; + + *api = &mhu_mod_smt_driver_api; + + return FWK_SUCCESS; +} + +static int mhu_start(fwk_id_t id) +{ + int status; + struct mhu_device_ctx *device_ctx; + + if (fwk_id_get_type(id) == FWK_ID_TYPE_MODULE) + return FWK_SUCCESS; + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + if (device_ctx->bound_slots != 0) { + status = fwk_interrupt_set_isr(device_ctx->config->irq, &mhu_isr); + if (status != FWK_SUCCESS) + return status; + status = fwk_interrupt_enable(device_ctx->config->irq); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +/* MHU module definition */ +const struct fwk_module module_morello_mhu = { + .name = "MORELLO MHU", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = mhu_init, + .element_init = mhu_device_init, + .bind = mhu_bind, + .start = mhu_start, + .process_bind_request = mhu_process_bind_request, +}; |