From 5552f0a57a01098925dcf6be298064863a9f1b19 Mon Sep 17 00:00:00 2001 From: Emekcan Date: Thu, 29 Sep 2022 15:53:54 +0100 Subject: [PATCH] Add corstone1000 platform Adds corstone1000 platform and related configurations under product folder as a new product. Signed-off-by: Emekcan Aras --- framework/src/Makefile | 9 +- product/corstone-1000/firmware/RTX_Config.h | 52 +++ .../firmware/config_eventhandler.c | 10 + product/corstone-1000/firmware/config_log.c | 60 +++ product/corstone-1000/firmware/config_mhuv2.c | 71 ++++ product/corstone-1000/firmware/firmware.mk | 23 ++ .../corstone-1000/firmware/fmw_memory.ld.S | 32 ++ product/corstone-1000/firmware/rtx_config.c | 81 ++++ product/corstone-1000/include/escm3_irq.h | 43 ++ product/corstone-1000/include/escm3_mmap.h | 45 +++ .../corstone-1000/include/escm3_system_mmap.h | 23 ++ product/corstone-1000/include/fmw_cmsis.h | 36 ++ product/corstone-1000/include/system_clock.h | 18 + .../eventhandler/include/mod_eventhandler.h | 18 + .../module/eventhandler/src/Makefile | 10 + .../eventhandler/src/mod_eventhandler.c | 146 +++++++ .../module/log/include/mod_log.h | 188 +++++++++ product/corstone-1000/module/log/src/Makefile | 10 + .../corstone-1000/module/log/src/mod_log.c | 380 ++++++++++++++++++ .../module/mhuv2/include/mod_mhuv2.h | 98 +++++ .../corstone-1000/module/mhuv2/src/Makefile | 10 + .../module/mhuv2/src/mod_mhuv2.c | 256 ++++++++++++ .../module/pl011/include/mod_pl011.h | 57 +++ .../corstone-1000/module/pl011/src/Makefile | 10 + .../module/pl011/src/mod_pl011.c | 216 ++++++++++ .../corstone-1000/module/pl011/src/pl011.h | 160 ++++++++ product/corstone-1000/product.mk | 7 + 27 files changed, 2067 insertions(+), 2 deletions(-) create mode 100644 product/corstone-1000/firmware/RTX_Config.h create mode 100644 product/corstone-1000/firmware/config_eventhandler.c create mode 100644 product/corstone-1000/firmware/config_log.c create mode 100755 product/corstone-1000/firmware/config_mhuv2.c create mode 100644 product/corstone-1000/firmware/firmware.mk create mode 100644 product/corstone-1000/firmware/fmw_memory.ld.S create mode 100644 product/corstone-1000/firmware/rtx_config.c create mode 100644 product/corstone-1000/include/escm3_irq.h create mode 100644 product/corstone-1000/include/escm3_mmap.h create mode 100644 product/corstone-1000/include/escm3_system_mmap.h create mode 100644 product/corstone-1000/include/fmw_cmsis.h create mode 100644 product/corstone-1000/include/system_clock.h create mode 100644 product/corstone-1000/module/eventhandler/include/mod_eventhandler.h create mode 100644 product/corstone-1000/module/eventhandler/src/Makefile create mode 100644 product/corstone-1000/module/eventhandler/src/mod_eventhandler.c create mode 100644 product/corstone-1000/module/log/include/mod_log.h create mode 100644 product/corstone-1000/module/log/src/Makefile create mode 100644 product/corstone-1000/module/log/src/mod_log.c create mode 100755 product/corstone-1000/module/mhuv2/include/mod_mhuv2.h create mode 100755 product/corstone-1000/module/mhuv2/src/Makefile create mode 100755 product/corstone-1000/module/mhuv2/src/mod_mhuv2.c create mode 100644 product/corstone-1000/module/pl011/include/mod_pl011.h create mode 100644 product/corstone-1000/module/pl011/src/Makefile create mode 100644 product/corstone-1000/module/pl011/src/mod_pl011.c create mode 100644 product/corstone-1000/module/pl011/src/pl011.h create mode 100644 product/corstone-1000/product.mk diff --git a/framework/src/Makefile b/framework/src/Makefile index 61512ce..a16ae37 100644 --- a/framework/src/Makefile +++ b/framework/src/Makefile @@ -32,7 +32,12 @@ BS_LIB_INCLUDES += $(FWK_DIR)/include BS_LIB_INCLUDES += $(FWK_DIR)/../module/mhuv2/include BS_LIB_INCLUDES += $(FWK_DIR)/../module/log/include -BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-700/include/ -BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-700/module/eventhandler/include/ +ifeq ($(PRODUCT), corstone-700) + BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-700/include/ + BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-700/module/eventhandler/include/ +else ifeq ($(PRODUCT), corstone-1000) + BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-1000/include/ + BS_LIB_INCLUDES += $(FWK_DIR)/../product/corstone-1000/module/eventhandler/include/ +endif include $(BS_DIR)/lib.mk diff --git a/product/corstone-1000/firmware/RTX_Config.h b/product/corstone-1000/firmware/RTX_Config.h new file mode 100644 index 0000000..b889222 --- /dev/null +++ b/product/corstone-1000/firmware/RTX_Config.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef RTX_CONFIG_H_ +#define RTX_CONFIG_H_ + +/* System */ +#define OS_DYNAMIC_MEM_SIZE 0 +#define OS_TICK_FREQ 1000 /* Hz */ +#define OS_ROBIN_ENABLE 0 +#define OS_ROBIN_TIMEOUT 0 +#define OS_ISR_FIFO_QUEUE 16 + +/* Thread */ +#define OS_THREAD_OBJ_MEM 0 +#define OS_THREAD_NUM 1 +#define OS_THREAD_DEF_STACK_NUM 0 +#define OS_THREAD_USER_STACK_SIZE 0 +#define OS_STACK_SIZE 200 +#define OS_IDLE_THREAD_STACK_SIZE 200 +#define OS_STACK_CHECK 1 +#define OS_STACK_WATERMARK 0 +#define OS_PRIVILEGE_MODE 1 + +/* Timer */ +#define OS_TIMER_OBJ_MEM 0 +#define OS_TIMER_NUM 1 +#define OS_TIMER_THREAD_PRIO 40 +#define OS_TIMER_THREAD_STACK_SIZE 200 +#define OS_TIMER_CB_QUEUE 4 + +/* Event flags */ +#define OS_EVFLAGS_OBJ_MEM 0 +#define OS_EVFLAGS_NUM 1 + +#define OS_MUTEX_OBJ_MEM 0 +#define OS_MUTEX_NUM 1 +#define OS_SEMAPHORE_OBJ_MEM 0 +#define OS_SEMAPHORE_NUM 1 +#define OS_MEMPOOL_OBJ_MEM 0 +#define OS_MEMPOOL_NUM 1 +#define OS_MEMPOOL_DATA_SIZE 0 +#define OS_MSGQUEUE_OBJ_MEM 0 +#define OS_MSGQUEUE_NUM 1 +#define OS_MSGQUEUE_DATA_SIZE 0 + +#endif /* RTX_CONFIG_H_ */ diff --git a/product/corstone-1000/firmware/config_eventhandler.c b/product/corstone-1000/firmware/config_eventhandler.c new file mode 100644 index 0000000..aa9656b --- /dev/null +++ b/product/corstone-1000/firmware/config_eventhandler.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +const struct fwk_module_config config_eventhandler = {}; diff --git a/product/corstone-1000/firmware/config_log.c b/product/corstone-1000/firmware/config_log.c new file mode 100644 index 0000000..78cbe09 --- /dev/null +++ b/product/corstone-1000/firmware/config_log.c @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * PL011 module + */ +static const struct fwk_element pl011_element_desc_table[] = { + [0] = { + .name = "uart", + .data = &((struct mod_pl011_device_config) { + .reg_base = ES_PL011_UART_BASE, + .baud_rate_bps = 115200, + .clock_rate_hz = 50 * UART_CLK_MHZ, + .clock_id = FWK_ID_NONE_INIT, + }), + }, + [1] = {}, +}; + +static const struct fwk_element *get_pl011_table(fwk_id_t module_id) +{ + return pl011_element_desc_table; +} + +struct fwk_module_config config_pl011 = { + .get_element_table = get_pl011_table, +}; + +/* + * Log module + */ +static const struct mod_log_config log_data = { + .device_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PL011, 0), + .api_id = FWK_ID_API(FWK_MODULE_IDX_PL011, 0), + .log_groups = MOD_LOG_GROUP_ERROR | + MOD_LOG_GROUP_INFO | + MOD_LOG_GROUP_WARNING | + MOD_LOG_GROUP_DEBUG, + .banner = FWK_BANNER_ES + BUILD_VERSION_DESCRIBE_STRING "\n", +}; + +struct fwk_module_config config_log = { + .data = &log_data, +}; diff --git a/product/corstone-1000/firmware/config_mhuv2.c b/product/corstone-1000/firmware/config_mhuv2.c new file mode 100755 index 0000000..74ef8ca --- /dev/null +++ b/product/corstone-1000/firmware/config_mhuv2.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#include +#include +#include +#include +#include +#include + +static const struct fwk_element mhu_element_table[] = { + [ES_H_MHU0_DEVICE_IDX] = { + .name = "MHU0_H", + .sub_element_count = 1, + .data = &((struct mod_mhu2_channel_config) { + .irq = HESMHU0_Combined_IRQn, + .recv = MHU0_H_ES_BASE, + .send = MHU0_ES_H_BASE, + .channel = 0, + }) + }, + + [ES_H_MHU1_DEVICE_IDX] = { + .name = "MHU1_H", + .sub_element_count = 1, + .data = &((struct mod_mhu2_channel_config) { + .irq = HESMHU1_Combined_IRQn, + .recv = MHU1_H_ES_BASE, + .send = MHU1_ES_H_BASE, + .channel = 0, + }) + }, + + [ES_SE_MHU0_DEVICE_IDX] = { + .name = "MHU0_SE", + .sub_element_count = 1, + .data = &((struct mod_mhu2_channel_config) { + .irq = SEESMHU0_Combined_IRQn, + .recv = MHU0_SE_ES_BASE, + .send = MHU0_ES_SE_BASE, + .channel = 0, + }) + }, + + [ES_SE_MHU1_DEVICE_IDX] = { + .name = "MHU1_SE", + .sub_element_count = 1, + .data = &((struct mod_mhu2_channel_config) { + .irq = SEESMHU1_Combined_IRQn, + .recv = MHU1_SE_ES_BASE, + .send = MHU1_ES_SE_BASE, + .channel = 0, + }) + }, + + [ES_MHU_DEVICE_IDX_COUNT] = {}, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return mhu_element_table; +} + +struct fwk_module_config config_mhuv2 = { + .get_element_table = mhu_get_element_table, +}; diff --git a/product/corstone-1000/firmware/firmware.mk b/product/corstone-1000/firmware/firmware.mk new file mode 100644 index 0000000..934e557 --- /dev/null +++ b/product/corstone-1000/firmware/firmware.mk @@ -0,0 +1,23 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_FIRMWARE_CPU := cortex-m3 +BS_FIRMWARE_HAS_MULTITHREADING := no +BS_FIRMWARE_HAS_NOTIFICATION := yes +BS_FIRMWARE_HAS_OPENAMP := yes + +BS_FIRMWARE_MODULES := \ + pl011 \ + log \ + mhuv2 \ + eventhandler + +BS_FIRMWARE_SOURCES := \ + config_log.c \ + config_mhuv2.c \ + config_eventhandler.c + +include $(BS_DIR)/firmware.mk diff --git a/product/corstone-1000/firmware/fmw_memory.ld.S b/product/corstone-1000/firmware/fmw_memory.ld.S new file mode 100644 index 0000000..95c278c --- /dev/null +++ b/product/corstone-1000/firmware/fmw_memory.ld.S @@ -0,0 +1,32 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Flash firmware memory layout for the linker script. + */ + +#ifndef FMW_MEMORY_LD_S +#define FMW_MEMORY_LD_S + +#include + +#define FIRMWARE_MEM_MODE FWK_MEM_MODE_DUAL_REGION_RELOCATION + +/* + * Flash memory + */ +#define FIRMWARE_MEM0_SIZE FLASH_SIZE +#define FIRMWARE_MEM0_BASE FLASH_START + +/* + * RAM memory + */ +#define FIRMWARE_MEM1_SIZE SRAM_SIZE +#define FIRMWARE_MEM1_BASE SRAM_START + +#define FIRMWARE_STACK_SIZE (2 * 1024) + +#endif /* FMW_MEMORY_LD_S */ diff --git a/product/corstone-1000/firmware/rtx_config.c b/product/corstone-1000/firmware/rtx_config.c new file mode 100644 index 0000000..928bdd7 --- /dev/null +++ b/product/corstone-1000/firmware/rtx_config.c @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#include +#include +#include +#include +#include + +#include + +/* + * Required by RTX to configure the SysTick timer. + */ +uint32_t SystemCoreClock = SYSTEM_CLOCK; + +/* + * Idle thread + */ +__NO_RETURN void osRtxIdleThread(void *argument) +{ + (void)argument; + + while (true) + __WFI(); +} + +/* + * OS error handler + */ +uint32_t osRtxErrorNotify(uint32_t code, void *object_id) +{ + (void)object_id; + + switch (code) { + case osRtxErrorStackUnderflow: + /* + * Stack underflow detected for thread + * thread_id=object_id + */ + break; + + case osRtxErrorISRQueueOverflow: + /* + * ISR Queue overflow detected when inserting object + * object_id + */ + break; + + case osRtxErrorTimerQueueOverflow: + /* + * User Timer Callback Queue overflow detected for timer + * timer_id=object_id + */ + break; + + case osRtxErrorClibSpace: + /* + * Standard C/C++ library libspace not available: + * increase OS_THREAD_LIBSPACE_NUM + */ + break; + + case osRtxErrorClibMutex: + /* + * Standard C/C++ library mutex initialization failed + */ + break; + + default: + break; + } + + osRtxIdleThread(object_id); +} diff --git a/product/corstone-1000/include/escm3_irq.h b/product/corstone-1000/include/escm3_irq.h new file mode 100644 index 0000000..f30aa43 --- /dev/null +++ b/product/corstone-1000/include/escm3_irq.h @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ESCM3_IRQ_H +#define ESCM3_IRQ_H + +#include + +typedef enum IRQn { + /* ------------------- Cortex-M3 Processor Exceptions Numbers ------------------- */ + NonMaskableInt_IRQn = -14, /* 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /* 3 HardFault Interrupt */ + MemoryManagement_IRQn = -12, /* 4 Memory Management Interrupt */ + BusFault_IRQn = -11, /* 5 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /* 6 Usage Fault Interrupt */ + SVCall_IRQn = -5, /* 11 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /* 12 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /* 14 Pend SV Interrupt */ + SysTick_IRQn = -1, /* 15 System Tick Interrupt */ + + /*------------------- CMSDK Specific Interrupt Numbers ----------------------------*/ + TIMER0_IRQn = 0, /* TIMER 0 Interrupt */ + TIMER1_IRQn = 1, /* TIMER 1 Interrupt */ + HESMHU0_Combined_IRQn = 2, /* Host to External System MHU0 Combined Interrupt */ + ESHMHU0_Combined_IRQn = 3, /* External System to Host MHU0 Combined Interrupt */ + HESMHU1_Combined_IRQn = 4, /* Host to External System MHU1 Combined Interrupt */ + ESHMHU1_Combined_IRQn = 5, /* External System to Host MHU1 Combined Interrupt */ + SEESMHU0_Combined_IRQn = 6, /* Boot processor to External System MHU0 Combined Interrupt */ + ESSEMHU0_Combined_IRQn = 7, /* External System to Boot processor MHU0 Combined Interrupt */ + SEESMHU1_Combined_IRQn = 8, /* Boot processor to External System MHU1 Combined Interrupt */ + ESSEMHU1_Combined_IRQn = 9, /* External System to Boot processor MHU1 Combined Interrupt */ + UART0_Tx_IRQn = 10, /* UART 0 TX Interrupt */ + UART0_Rx_IRQn = 11, /* UART 0 RX Interrupt */ + UART0_RxTimeout_IRQn = 12, /* UART 0 RX Timeout Interrupt */ +} IRQn_Type; + + +#endif /* ESCM3_IRQ_H */ diff --git a/product/corstone-1000/include/escm3_mmap.h b/product/corstone-1000/include/escm3_mmap.h new file mode 100644 index 0000000..926a516 --- /dev/null +++ b/product/corstone-1000/include/escm3_mmap.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ESCM3_MMAP_H +#define ESCM3_MMAP_H + +#include +#include + +/* ===========================================================================*/ +/* ============= Processor and Core Peripheral Section ============= */ +/* ========================================================================== */ + +/* ========================================================================== */ +/* ================ Peripheral memory map ============== */ +/* ========================================================================== */ +#define ES_PL011_UART_BASE (0x40002000ul) + +/* ============================== MHU Devices ================================*/ +#define MHU0_H_ES_BASE 0x40100000 +#define MHU0_ES_H_BASE 0x40110000 + +#define MHU1_H_ES_BASE 0x40120000 +#define MHU1_ES_H_BASE 0x40130000 + +#define MHU0_SE_ES_BASE 0x40140000 +#define MHU0_ES_SE_BASE 0x40150000 + +#define MHU1_SE_ES_BASE 0x40160000 +#define MHU1_ES_SE_BASE 0x40170000 + +enum se_mhu_device_idx { + ES_H_MHU0_DEVICE_IDX, + ES_H_MHU1_DEVICE_IDX, + ES_SE_MHU0_DEVICE_IDX, + ES_SE_MHU1_DEVICE_IDX, + ES_MHU_DEVICE_IDX_COUNT, +}; + +#endif /* ESCM3_MMAP_H */ diff --git a/product/corstone-1000/include/escm3_system_mmap.h b/product/corstone-1000/include/escm3_system_mmap.h new file mode 100644 index 0000000..49847d5 --- /dev/null +++ b/product/corstone-1000/include/escm3_system_mmap.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef ESCM3_SYSTEM_MMAP_H +#define ESCM3_SYSTEM_MMAP_H + +/*Memory*/ + +#define FLASH_START 0x00000000 +#define FLASH_SIZE 0x00040000 /* 256 KiB */ + + +/* Data memory zones */ +#define SRAM_START 0x20000000 +#define SRAM_SIZE 0x00008000 /* 32 KiB */ + +#endif /* ESCM3_SYSTEM_MMAP_H */ diff --git a/product/corstone-1000/include/fmw_cmsis.h b/product/corstone-1000/include/fmw_cmsis.h new file mode 100644 index 0000000..0031dbb --- /dev/null +++ b/product/corstone-1000/include/fmw_cmsis.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef FMW_CMSIS_H +#define FMW_CMSIS_H + +#define __CHECK_DEVICE_DEFINES +#define __CM7_REV 0x0000U +#define __FPU_PRESENT 0U +#define __MPU_PRESENT 1U +#define __ICACHE_PRESENT 0U +#define __DCACHE_PRESENT 0U +#define __DTCM_PRESENT 0U +#define __NVIC_PRIO_BITS 3U +#define __Vendor_SysTickConfig 0U + +typedef enum IRQn { + NonMaskableInt_IRQn = -14, + MemoryManagement_IRQn = -12, + BusFault_IRQn = -11, + UsageFault_IRQn = -10, + SVCall_IRQn = -5, + DebugMonitor_IRQn = -4, + PendSV_IRQn = -2, + SysTick_IRQn = -1, +} IRQn_Type; + +#include + +#endif /* FMW_CMSIS_H */ diff --git a/product/corstone-1000/include/system_clock.h b/product/corstone-1000/include/system_clock.h new file mode 100644 index 0000000..73c4557 --- /dev/null +++ b/product/corstone-1000/include/system_clock.h @@ -0,0 +1,18 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef SYSTEM_CLOCK_H +#define SYSTEM_CLOCK_H + +#define __XTAL (50000000UL) /* Oscillator frequency */ + +#define SYSTEM_CLOCK (__XTAL / 2) + + +#endif /* SYSTEM_CLOCK_H */ diff --git a/product/corstone-1000/module/eventhandler/include/mod_eventhandler.h b/product/corstone-1000/module/eventhandler/include/mod_eventhandler.h new file mode 100644 index 0000000..f59a7d1 --- /dev/null +++ b/product/corstone-1000/module/eventhandler/include/mod_eventhandler.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MOD_EVENTHANDLER_H +#define MOD_EVENTHANDLER_H + +#include +#include + +struct mod_eventhandler_api { + int (*handleRpmsgEvent)(struct rpmsg_endpoint *ept, void *data, size_t len); +}; + +#endif /* MOD_eventhandler_H */ \ No newline at end of file diff --git a/product/corstone-1000/module/eventhandler/src/Makefile b/product/corstone-1000/module/eventhandler/src/Makefile new file mode 100644 index 0000000..1a04be1 --- /dev/null +++ b/product/corstone-1000/module/eventhandler/src/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := eventhandler +BS_LIB_SOURCES := mod_eventhandler.c + +include $(BS_DIR)/lib.mk diff --git a/product/corstone-1000/module/eventhandler/src/mod_eventhandler.c b/product/corstone-1000/module/eventhandler/src/mod_eventhandler.c new file mode 100644 index 0000000..ff7d670 --- /dev/null +++ b/product/corstone-1000/module/eventhandler/src/mod_eventhandler.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct mod_log_api *log_api; + +/* MHU Test command syntax + bit 3 downto 0 : command + bit 31 downto 4 : value +*/ + +#define BITMASK(x) ((unsigned)-1 >> ((sizeof(int) * CHAR_BIT) - x)) +#define CMD_WIDTH 4 +#define COMMAND(message) (message & BITMASK(CMD_WIDTH)) +#define VALUE(message) ((unsigned)message >> CMD_WIDTH) +#define ENCODE(command, value) ((command & BITMASK(CMD_WIDTH)) | ((value) << CMD_WIDTH)) + +enum Command { + NONE, + INC_RETURN, // Increment the value and return the value to sender + INC_ECHO_SE, // increment, send to SE, make it increment and echo back + // to this ES + NUM_COMMANDS, +}; + +static int handleRpmsgEvent(struct rpmsg_endpoint *ept, void *data, size_t len){ + log_api->log(MOD_LOG_GROUP_INFO,"Received '%x' ", *(int*)data); + if (ept->dest_addr == MHU0_ES_H_BASE) + log_api->log(MOD_LOG_GROUP_INFO,"From Host MHU0\n"); + else if (ept->dest_addr == MHU1_ES_H_BASE) + log_api->log(MOD_LOG_GROUP_INFO,"From Host MHU1\n"); + else if (ept->dest_addr == MHU0_ES_SE_BASE) + log_api->log(MOD_LOG_GROUP_INFO,"From SE MHU0\n"); + else if (ept->dest_addr == MHU1_ES_SE_BASE) + log_api->log(MOD_LOG_GROUP_INFO,"From SE MHU1\n"); + else + log_api->log(MOD_LOG_GROUP_INFO,"From unknown source\n"); + + int message = *(int*)data; + switch (COMMAND(message)) { + case NONE: + log_api->log(MOD_LOG_GROUP_INFO, + "CMD: Do nothing...\r\n"); + break; + case INC_RETURN: { + log_api->log(MOD_LOG_GROUP_INFO, + "CMD: Increment and return to sender...\r\n"); + const int command = ENCODE(NONE, VALUE(message) + 1); + int status = rpmsg_send(ept, &command, sizeof(command)); + if(status != RPMSG_SUCCESS){ + log_api->log(MOD_LOG_GROUP_INFO, + "EventHandler: Could not send message via rpmsg_send\r\n"); + } + break; + } + case INC_ECHO_SE: { + struct rpmsg_endpoint* se_ept; + switch(ept->dest_addr) { + case MHU0_ES_H_BASE: + se_ept = get_endpoint(MHU0_ES_SE_BASE); + break; + case MHU1_ES_H_BASE: + se_ept = get_endpoint(MHU1_ES_SE_BASE); + break; + default: + log_api->log(MOD_LOG_GROUP_INFO, + "ECHO SE command should be triggered from a host MHU\r\n"); + return FWK_SUCCESS; + } + log_api->log(MOD_LOG_GROUP_INFO, + "CMD: Increment and echo to SE...\r\n"); + const int command = ENCODE(INC_RETURN, VALUE(message) + 1); + int status = rpmsg_send(se_ept, &command, sizeof(command)); + if(status != RPMSG_SUCCESS){ + log_api->log(MOD_LOG_GROUP_INFO, + "EventHandler: Could not send message via rpmsg_send\r\n"); + } + break; + } + default: { + log_api->log(MOD_LOG_GROUP_INFO, + "CMD: Unknwn command: %u\r\n", COMMAND(message)); + break; + } + } + return FWK_SUCCESS; +} + +static struct mod_eventhandler_api module_api = { + .handleRpmsgEvent = handleRpmsgEvent, +}; + +static int eventhandler_process_bind_request( + fwk_id_t requester_id, + fwk_id_t id, + fwk_id_t api_id, + const void **api) +{ + *api = &module_api; + return FWK_SUCCESS; +} + +static int eventhandler_init(fwk_id_t id, unsigned int element_count, + const void* data){ + return FWK_SUCCESS; +} + +static int eventhandler_bind(fwk_id_t id, unsigned int round) +{ + int status; + + if ((round == 1)) { + status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &log_api); + if (status != FWK_SUCCESS) { + /* Unable to bind back to SMT channel */ + assert(false); + return status; + } + + } + return FWK_SUCCESS; +} + +const struct fwk_module module_eventhandler = { + .name = "eventhandler", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .bind = eventhandler_bind, + .init = eventhandler_init, + .process_bind_request = eventhandler_process_bind_request, +}; diff --git a/product/corstone-1000/module/log/include/mod_log.h b/product/corstone-1000/module/log/include/mod_log.h new file mode 100644 index 0000000..ca687d4 --- /dev/null +++ b/product/corstone-1000/module/log/include/mod_log.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MOD_LOG_H +#define MOD_LOG_H + +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModuleLog Logging + * + * \brief Module used to write messages to an output device. + * + * \details This module is used to log messages (similar to a printf() call) + * using a configurable output device (for example, a UART). + * + * A grouping feature allows logged messages to be organized into + * categories that can be enabled or disabled through the module + * configuration. + * @{ + */ + +/*! + * \brief Log groups. + * + * \details Log groups are used for: + * * Categorizing a message during the \ref mod_log_api::log() + * call. + * * Selectively enabling or disabling certain message types. + * + * \note Log groups are not organized in a heirarchy and do not indicate any + * kind of priority. + */ +enum mod_log_group { + /*! Used only to indicate all log groups are muted */ + MOD_LOG_GROUP_NONE = 0, + + /*! The debug log group */ + MOD_LOG_GROUP_DEBUG = (1 << 0), + + /*! The error log group */ + MOD_LOG_GROUP_ERROR = (1 << 1), + + /*! The info log group */ + MOD_LOG_GROUP_INFO = (1 << 2), + + /*! The warning log group */ + MOD_LOG_GROUP_WARNING = (1 << 3), +}; + +/*! + * \brief Log module API identifier. + * + * \details The log module only has a single API, which is identified by this + * identifier. + */ +#define MOD_LOG_API_ID FWK_ID_API(FWK_MODULE_IDX_LOG, 0) + +/*! + * \brief Module configuration. + */ +struct mod_log_config { + /*! Module or element identifier of the device providing the I/O stream */ + const fwk_id_t device_id; + + /*! API identifier used to select the API provided by the I/O device */ + const fwk_id_t api_id; + + /*! Default log groups. Value is a mask (see \ref mod_log_group) */ + const unsigned int log_groups; + + /*! + * \brief A string that will be written automatically after the module + * is initialized. + * + * \details Allows a firmware to provide a string that is written before any + * other log messages. The banner uses the \ref MOD_LOG_GROUP_INFO log + * group. + * + * \note May be NULL, in which case the banner functionality is not used. + */ + const char *banner; +}; + +/*! + * \brief Log driver interface. + */ +struct mod_log_driver_api { + /*! + * \brief Pointer to the device's buffer flush function. + * + * \details When invoked, the device must ensure any buffered data is + * flushed out before it returns. + * + * \note This function is \b mandatory. + * + * \param device_id Device identifier. + * + * \retval FWK_SUCCESS Operation succeeded. + * \retval FWK_E_DEVICE Internal device error. + */ + int (*flush)(fwk_id_t device_id); + + /*! + * \brief Pointer to the function used to write a single character. + * + * \note This function is \b mandatory. + * + * \param device_id Device identifier. + * \param c The character to be written. + * + * \retval FWK_SUCCESS Operation succeeded. + * \retval FWK_E_DEVICE Internal device error. + */ + int (*putchar)(fwk_id_t device_id, char c); +}; + +/*! + * \brief Module interface + */ +struct mod_log_api { + /*! + * \brief Log formatted data. + * + * \details Log formatted data assigned to a log group. Only logs that are + * assigned to enabled groups will be output. The module configuration + * can be used to enable and disable log groups. + * + * \param group One of the log groups that the log is assigned to (\see + * log_group). + * + * \param fmt String containing the formatted data to be printed out. The + * following formats are supported: + * * \%c - character format + * * \%d and \%i - signed 32-bit decimal format + * * \%lx and \%llx - 64-bit hexadecimal format + * * \%s - string format + * * \%u - unsigned 32-bit decimal format + * * \%x - 32-bit hexadecimal format + * * \%e - framework error code format + * + * Numeric formats also accept a padding flag '0\' between the + * '\%' and the format specifier where the resulting string number will + * be left padded with zeros. Examples: + * * log("%04d", 1) results in "0001" + * * log("%04d", 9999) results in "9999" + * * __Note__: \ must be a number between 0 and 9 inclusive. + * + * \retval FWK_SUCCESS Operation succeeded. + * \retval FWK_E_DATA Invalid format specifier(s). + * \retval FWK_E_DEVICE Internal device error. + * \retval FWK_E_PARAM Invalid group. + * \retval FWK_E_PARAM Invalid 'fmt' pointer. + * \retval FWK_E_STATE Log module is not ready. + */ + int (*log)(enum mod_log_group group, const char *fmt, ...); + + /*! + * \brief Function used to flush the log's buffer. + * + * \details When invoked, any buffered log data will be flushed out before + * this function returns. + * + * \retval FWK_SUCCESS Operation succeeded. + * \retval FWK_E_DEVICE Internal device error. + * \retval FWK_E_STATE Log module is not ready. + */ + int (*flush)(void); +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_LOG_H */ diff --git a/product/corstone-1000/module/log/src/Makefile b/product/corstone-1000/module/log/src/Makefile new file mode 100644 index 0000000..ca7aa40 --- /dev/null +++ b/product/corstone-1000/module/log/src/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := Log +BS_LIB_SOURCES = mod_log.c + +include $(BS_DIR)/lib.mk diff --git a/product/corstone-1000/module/log/src/mod_log.c b/product/corstone-1000/module/log/src/mod_log.c new file mode 100644 index 0000000..8c385a4 --- /dev/null +++ b/product/corstone-1000/module/log/src/mod_log.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct mod_log_config *log_config; +static struct mod_log_driver_api *log_driver; + +#define ALL_GROUPS_MASK (MOD_LOG_GROUP_DEBUG | \ + MOD_LOG_GROUP_ERROR | \ + MOD_LOG_GROUP_INFO | \ + MOD_LOG_GROUP_WARNING) + +static const char * const errstr[] = { + [FWK_SUCCESS] = "SUCCESS", + [-FWK_E_PARAM] = "E_PARAM", + [-FWK_E_ALIGN] = "E_ALIGN", + [-FWK_E_SIZE] = "E_SIZE", + [-FWK_E_HANDLER] = "E_HANDLER", + [-FWK_E_ACCESS] = "E_ACCESS", + [-FWK_E_RANGE] = "E_RANGE", + [-FWK_E_TIMEOUT] = "E_TIMEOUT", + [-FWK_E_NOMEM] = "E_NOMEM", + [-FWK_E_PWRSTATE] = "E_PWRSTATE", + [-FWK_E_SUPPORT] = "E_SUPPORT", + [-FWK_E_DEVICE] = "E_DEVICE", + [-FWK_E_BUSY] = "E_BUSY", + [-FWK_E_OS] = "E_OS", + [-FWK_E_DATA] = "E_DATA", + [-FWK_E_STATE] = "E_STATE", + [-FWK_E_INIT] = "E_INIT", + [-FWK_E_OVERWRITTEN] = "E_OVERWRITTEN", + [-FWK_E_PANIC] = "E_PANIC", +}; + +static int do_putchar(char c) +{ + int status; + + /* Include a 'carriage return' before the new line */ + if (c == '\n') { + status = do_putchar('\r'); + if (status != FWK_SUCCESS) + return status; + } + + status = log_driver->putchar(log_config->device_id, c); + if (status != FWK_SUCCESS) + return FWK_E_DEVICE; + + return FWK_SUCCESS; +} + +static int print_uint64(uint64_t value, unsigned int base, unsigned int fill) +{ + /* Just need enough space to store 64 bit decimal integer */ + unsigned char str[20]; + unsigned int i = 0; + int status; + + /* Decimal or hexadecimal only */ + assert((base == 10) || (base == 16)); + + do { + str[i++] = "0123456789abcdef"[value % base]; + } while (value /= base); + + while (fill-- > i) { + status = do_putchar('0'); + if (status != FWK_SUCCESS) + return status; + } + + while (i > 0) { + status = do_putchar(str[--i]); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static int print_int32(int32_t num, unsigned int fill) +{ + int status; + uint64_t unum; + + if (num < 0) { + status = do_putchar('-'); + if (status != FWK_SUCCESS) + return status; + unum = (uint64_t)-num; + } else + unum = (uint64_t)num; + + return print_uint64(unum, 10, fill); +} + +static int print_string(const char *str) +{ + int status; + + while (*str) { + status = do_putchar(*str++); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static int do_print(const char *fmt, va_list *args) +{ + int status; + int bit64; + int64_t num; + uint64_t unum; + unsigned int fill; + + while (*fmt) { + + if (*fmt == '%') { + fmt++; + bit64 = 0; + fill = 0; + +next_symbol: + /* Check the format specifier */ + switch (*fmt) { + case 'e': + num = va_arg(*args, int); + unum = (uint64_t)(-num); + if ((num <= 0) && (unum < FWK_ARRAY_SIZE(errstr))) { + + status = print_string("FWK_"); + if (status != FWK_SUCCESS) + return status; + + status = print_string(errstr[unum]); + } else + status = print_int32(num, 0); + + if (status != FWK_SUCCESS) + return status; + break; + + case 'i': /* Fall through to next one */ + case 'd': + if (bit64) + return FWK_E_DATA; + + num = va_arg(*args, int32_t); + + status = print_int32(num, fill); + if (status != FWK_SUCCESS) + return status; + break; + + case 's': + status = print_string(va_arg(*args, const char *)); + if (status != FWK_SUCCESS) + return status; + break; + + case 'c': + status = do_putchar(va_arg(*args, int)); + if (status != FWK_SUCCESS) + return status; + break; + + case 'x': + if (bit64) + unum = va_arg(*args, uint64_t); + else + unum = va_arg(*args, uint32_t); + status = print_uint64(unum, 16, fill); + if (status != FWK_SUCCESS) + return status; + break; + + case 'l': + bit64 = 1; + fmt++; + goto next_symbol; + + case 'u': + if (bit64) + return FWK_E_DATA; + + unum = va_arg(*args, uint32_t); + + status = print_uint64(unum, 10, fill); + if (status != FWK_SUCCESS) + return status; + break; + + case '0': + fmt++; + if (((*fmt) < '0') || ((*fmt) > '9')) + return FWK_E_DATA; + fill = *(fmt++) - '0'; + goto next_symbol; + + default: + /* Exit on any other format specifier */ + return FWK_E_DATA; + } + fmt++; + continue; + } + status = do_putchar(*fmt++); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static bool is_valid_group(unsigned int group) +{ + /* Check if group is 'none' */ + if (group == MOD_LOG_GROUP_NONE) + return false; + + /* Check if group is within the limits of valid groups */ + if (group & ~ALL_GROUPS_MASK) + return false; + + /* Check if only one group was set */ + return !(group & (group - 1)); +} + +/* + * Module API + */ + +static int do_log(enum mod_log_group group, const char *fmt, ...) +{ + int status; + va_list args; + + /* API called too early */ + if (log_driver == NULL) + return FWK_E_STATE; + + status = fwk_module_check_call(FWK_ID_MODULE(FWK_MODULE_IDX_LOG)); + if (status != FWK_SUCCESS) + return status; + + if (!is_valid_group(group)) + return FWK_E_PARAM; + + if (fmt == NULL) + return FWK_E_PARAM; + + if (group & log_config->log_groups) { + va_start(args, fmt); + status = do_print(fmt, &args); + va_end(args); + + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static int do_flush(void) +{ + int status; + + /* API called too early */ + if (log_driver == NULL) + return FWK_E_STATE; + + status = fwk_module_check_call(FWK_ID_MODULE(FWK_MODULE_IDX_LOG)); + if (status != FWK_SUCCESS) + return status; + + status = log_driver->flush(log_config->device_id); + if (status != FWK_SUCCESS) + return FWK_E_DEVICE; + + return FWK_SUCCESS; +} + +static const struct mod_log_api module_api = { + .log = do_log, + .flush = do_flush, +}; + +/* + * Framework handlers + */ +static int log_init(fwk_id_t module_id, unsigned int element_count, + const void *data) +{ + const struct mod_log_config *config = data; + + /* Module does not support elements */ + if (element_count > 0) + return FWK_E_DATA; + + /* Check for invalid groups in the 'log_groups' mask */ + if (config->log_groups & ~ALL_GROUPS_MASK) + return FWK_E_PARAM; + + log_config = config; + + return FWK_SUCCESS; +} + +static int log_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct mod_log_driver_api *driver = NULL; + + /* Skip second round */ + if (round == 1) + return FWK_SUCCESS; + + /* Get the device driver's API */ + status = fwk_module_bind(log_config->device_id, + log_config->api_id, + &driver); + if (status != FWK_SUCCESS) + return FWK_E_HANDLER; + + /* Validate device driver's API */ + if ((driver == NULL) || + (driver->flush == NULL) || + (driver->putchar == NULL)) + return FWK_E_DATA; + + log_driver = driver; + + if (log_config->banner) { + status = do_log(MOD_LOG_GROUP_INFO, log_config->banner); + if (status != FWK_SUCCESS) + return status; + + status = do_flush(); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static int log_process_bind_request(fwk_id_t requester_id, fwk_id_t id, + fwk_id_t api_id, const void **api) +{ + *api = &module_api; + + return FWK_SUCCESS; +} + +/* Module descriptor */ +const struct fwk_module module_log = { + .name = "Log", + .type = FWK_MODULE_TYPE_HAL, + .api_count = 1, + .init = log_init, + .bind = log_bind, + .process_bind_request = log_process_bind_request, +}; diff --git a/product/corstone-1000/module/mhuv2/include/mod_mhuv2.h b/product/corstone-1000/module/mhuv2/include/mod_mhuv2.h new file mode 100755 index 0000000..cc8af7f --- /dev/null +++ b/product/corstone-1000/module/mhuv2/include/mod_mhuv2.h @@ -0,0 +1,98 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) v2 Device Driver. + */ + +#ifndef MOD_MHU2_H +#define MOD_MHU2_H + +#include +#include + +#define CHANNEL_MAX 124 + +enum mod_mhu2_api_idx { + MOD_MHU2_API_IDX_DRIVER, + MOD_MHU2_API_IDX_COUNT, +}; + +struct mod_mhu2_channel_config { + /*! IRQ number of the receive interrupt line */ + unsigned int irq; + + /*! Indicates whether interrupt is within NVIC or a collated IRQ */ + bool irq_is_collated; + + /*! Base address of the registers of the incoming MHU */ + uintptr_t recv; + + /*! Base address of the registers of the outgoing MHU */ + uintptr_t send; + + /*! Channel number */ + unsigned int channel; +}; + + +struct mhu2_id_reg { + FWK_R uint32_t PID4; + uint8_t RESERVED1[0x10 - 0x4]; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t COMPID0; + FWK_R uint32_t COMPID1; + FWK_R uint32_t COMPID2; + FWK_R uint32_t COMPID3; +}; + +struct mhu2_send_channel_reg { + FWK_R uint32_t STAT; + uint8_t RESERVED0[0xC - 0x4]; + FWK_W uint32_t STAT_SET; + uint8_t RESERVED1[0x20 - 0x10]; +}; + +struct mhu2_send_reg { + struct mhu2_send_channel_reg channel[CHANNEL_MAX]; + FWK_R uint32_t MSG_NO_CAP; + FWK_RW uint32_t RESP_CFG; + FWK_RW uint32_t ACCESS_REQUEST; + FWK_R uint32_t ACCESS_READY; + FWK_R uint32_t INT_ACCESS_STAT; + FWK_W uint32_t INT_ACCESS_CLR; + FWK_W uint32_t INT_ACCESS_EN; + uint8_t RESERVED0[0xFD0 - 0xF9C]; + struct mhu2_id_reg id; +}; + +struct mhu2_recv_channel_reg { + FWK_R uint32_t STAT; + FWK_R uint32_t STAT_PEND; + FWK_W uint32_t STAT_CLEAR; + uint8_t RESERVED0[0x10 - 0x0C]; + FWK_R uint32_t MASK; + FWK_W uint32_t MASK_SET; + FWK_W uint32_t MASK_CLEAR; + uint8_t RESERVED1[0x20 - 0x1C]; +}; + +struct mhu2_recv_reg { + struct mhu2_recv_channel_reg channel[CHANNEL_MAX]; + FWK_R uint32_t MSG_NO_CAP; + uint8_t RESERVED0[0xFD0 - 0xF84]; + struct mhu2_id_reg id; +}; + +struct mod_mhu_driver_api { + int (*send_message) (fwk_id_t slot_id, uint32_t message); + fwk_id_t (*lookup_channel) (uint32_t dst); +}; + +#endif /* MOD_MHU2_H */ diff --git a/product/corstone-1000/module/mhuv2/src/Makefile b/product/corstone-1000/module/mhuv2/src/Makefile new file mode 100755 index 0000000..4e5c1d7 --- /dev/null +++ b/product/corstone-1000/module/mhuv2/src/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := MHU2 +BS_LIB_SOURCES := mod_mhuv2.c + +include $(BS_DIR)/lib.mk diff --git a/product/corstone-1000/module/mhuv2/src/mod_mhuv2.c b/product/corstone-1000/module/mhuv2/src/mod_mhuv2.c new file mode 100755 index 0000000..dccd890 --- /dev/null +++ b/product/corstone-1000/module/mhuv2/src/mod_mhuv2.c @@ -0,0 +1,256 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) v2 Device Driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHU_V2_INT_EN_OFS 0xF98 +#define MHU_V2_AIDR_OFS 0xFCC + +#define MHU_V2_CHCOMB (1 << 2) + +#define MHU_V2_AIDR_MINOR(_reg) ((_reg) & 0xF) + +/* MHU channel context */ +struct mhu2_channel_ctx { + /* Pointer to the channel configuration */ + const struct mod_mhu2_channel_config *config; + + /* Pointer to send register set */ + struct mhu2_send_reg *send; + + /* Pointers to channel-specific register sets */ + struct mhu2_send_channel_reg *send_channel; + struct mhu2_recv_channel_reg *recv_channel; + fwk_id_t channel_id; + struct rpmsg_endpoint *ept; + const struct mod_log_api *log_api; +}; + +/* MHU v2 context */ +static struct mhu2_ctx { + /* Table of channel contexts */ + struct mhu2_channel_ctx *channel_ctx_table; + + /* Number of channels in the channel context table*/ + unsigned int channel_count; + struct rpmsg_device *rdev; +} ctx; + +static void mhu2_isr(uintptr_t ctx_param) +{ + struct mhu2_channel_ctx *channel_ctx = (struct mhu2_channel_ctx *)ctx_param; + uint32_t message; + assert(channel_ctx != NULL); + + message = channel_ctx->recv_channel->STAT; + + channel_ctx->log_api->log(MOD_LOG_GROUP_INFO, + "MHUv2: Message from \'%s\': 0x%x\n", + fwk_module_get_name(channel_ctx->channel_id), + message); + channel_ctx->ept->cb(channel_ctx->ept, &message, 4, RPMSG_ADDR_ANY, NULL); + channel_ctx->recv_channel->STAT_CLEAR = message; +} + +static fwk_id_t lookup_channel(uint32_t dst) { + struct mhu2_channel_ctx *channel_ctx; + int ch_i = -1; + for(unsigned int i = 0; i < ctx.channel_count; i++) { + channel_ctx = &ctx.channel_ctx_table[i]; + if(channel_ctx->config->send == dst) { + ch_i = i; + break; + } + } + assert(ch_i != -1); + return fwk_id_build_element_id(FWK_ID_MODULE(FWK_MODULE_IDX_MHUV2), ch_i); +} + +static int send_message(fwk_id_t channel_id, uint32_t message) +{ + int status; + struct mhu2_channel_ctx *channel_ctx; + struct mhu2_send_reg *send; + + status = fwk_module_check_call(channel_id); + if (status != FWK_SUCCESS) + return status; + + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + send = channel_ctx->send; + + /* Turn on receiver */ + send->ACCESS_REQUEST = 1; + while (send->ACCESS_READY != 1) + continue; + channel_ctx->send_channel->STAT_SET = message; + + /* Signal that the receiver is no longer needed */ + send->ACCESS_REQUEST = 0; + + return FWK_SUCCESS; +} + +static const struct mod_mhu_driver_api mhu2_mod_driver_api = { + .send_message = send_message, + .lookup_channel = lookup_channel, +}; + +/* + * Framework handlers + */ + +static int mhu2_init(fwk_id_t module_id, + unsigned int channel_count, + const void *unused) +{ + if (channel_count == 0) { + /* There must be at least 1 mhu channel */ + assert(false); + return FWK_E_PARAM; + } + + ctx.channel_ctx_table = fwk_mm_calloc(channel_count, + sizeof(ctx.channel_ctx_table[0])); + if (ctx.channel_ctx_table == NULL) { + /* Unable to allocate memory for channel context table */ + assert(false); + return FWK_E_NOMEM; + } + ctx.rdev = init_rpmsg(); + ctx.channel_count = channel_count; + + return FWK_SUCCESS; +} + +static int mhu2_channel_init(fwk_id_t channel_id, + unsigned int unused, + const void *data) +{ + const struct mod_mhu2_channel_config *config = data; + struct mhu2_channel_ctx *channel_ctx; + struct mhu2_recv_reg *recv_reg; + + if ((config == NULL) || (config->recv == 0) || (config->send == 0)) { + assert(false); + return FWK_E_DATA; + } + + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + channel_ctx->send = (struct mhu2_send_reg *)config->send; + + if (config->channel >= channel_ctx->send->MSG_NO_CAP) { + assert(false); + return FWK_E_DATA; + } + + channel_ctx->config = config; + + channel_ctx->send_channel = &channel_ctx->send->channel[config->channel]; + recv_reg = (struct mhu2_recv_reg *)config->recv; + channel_ctx->recv_channel = &recv_reg->channel[config->channel]; + channel_ctx->channel_id = channel_id; + channel_ctx->ept = endpoint_create(ctx.rdev, (void *)channel_ctx->send); + + const uint32_t aidr = *(uint32_t*)((void*)channel_ctx->recv_channel + MHU_V2_AIDR_OFS); + if(MHU_V2_AIDR_MINOR(aidr) >= 1) { + // Enable combined receiver interrupt for MHUv2.1 + uint32_t* reg_inten = ((void*)channel_ctx->recv_channel + MHU_V2_INT_EN_OFS); + *reg_inten = MHU_V2_CHCOMB; + } + + return FWK_SUCCESS; +} + +static int mhu2_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct mhu2_channel_ctx *channel_ctx; + + if ((round == 1) && fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) { + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + + status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &channel_ctx->log_api); + if (status != FWK_SUCCESS) { + /* Unable to bind back to SMT channel */ + assert(false); + return status; + } + } + return FWK_SUCCESS; +} + +static int mhu2_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &mhu2_mod_driver_api; + return FWK_SUCCESS; +} + +static int mhu2_start(fwk_id_t id) +{ + int status; + struct mhu2_channel_ctx *channel_ctx; + + if (fwk_id_get_type(id) == FWK_ID_TYPE_MODULE) + return FWK_SUCCESS; + + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + + // Route IRQ to NVIC + status = fwk_interrupt_set_isr_param(channel_ctx->config->irq, + &mhu2_isr, + (uintptr_t)channel_ctx); + if (status != FWK_SUCCESS) { + /* Failed to set isr */ + assert(false); + return status; + } + + status = fwk_interrupt_enable(channel_ctx->config->irq); + if (status != FWK_SUCCESS) { + /* Failed to enable isr */ + assert(false); + return status; + } + + + channel_ctx->log_api->log(MOD_LOG_GROUP_INFO, "MHUv2 module \'%s\' started\n", + fwk_module_get_name(id)); + + return FWK_SUCCESS; +} + +/* MHU v2 module definition */ +const struct fwk_module module_mhuv2 = { + .name = "MHUV2", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_MHU2_API_IDX_COUNT, + .init = mhu2_init, + .element_init = mhu2_channel_init, + .start = mhu2_start, + .bind = mhu2_bind, + .process_bind_request = mhu2_process_bind_request, +}; diff --git a/product/corstone-1000/module/pl011/include/mod_pl011.h b/product/corstone-1000/module/pl011/include/mod_pl011.h new file mode 100644 index 0000000..71a6dde --- /dev/null +++ b/product/corstone-1000/module/pl011/include/mod_pl011.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MOD_PL011_H +#define MOD_PL011_H + +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModulePl011 PL011 Driver + * + * \brief Arm PL011 device driver, fulfilling the Log module's driver API. + * + * \details This module implements a device driver for the Primecell® PL011 + * UART. + * @{ + */ + +#define UART_CLK_MHZ (1000UL * 1000UL) + +/*! + * \brief PL011 device configuration data. + */ +struct mod_pl011_device_config { + /*! Base address of the device registers */ + uintptr_t reg_base; + + /*! Baud rate (bits per second) */ + unsigned int baud_rate_bps; + + /*! Reference clock (Hertz) */ + uint64_t clock_rate_hz; + + /*! Identifier of the clock that this device depends on */ + fwk_id_t clock_id; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PL011_H */ diff --git a/product/corstone-1000/module/pl011/src/Makefile b/product/corstone-1000/module/pl011/src/Makefile new file mode 100644 index 0000000..900501a --- /dev/null +++ b/product/corstone-1000/module/pl011/src/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "PL011" +BS_LIB_SOURCES = mod_pl011.c + +include $(BS_DIR)/lib.mk diff --git a/product/corstone-1000/module/pl011/src/mod_pl011.c b/product/corstone-1000/module/pl011/src/mod_pl011.c new file mode 100644 index 0000000..084fb71 --- /dev/null +++ b/product/corstone-1000/module/pl011/src/mod_pl011.c @@ -0,0 +1,216 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct mod_pl011_device_config **device_config_table; + +static struct pl011_reg *get_device_reg(fwk_id_t device_id) +{ + unsigned int device_idx; + + device_idx = fwk_id_get_element_idx(device_id); + return (struct pl011_reg *)device_config_table[device_idx]->reg_base; +} + +/* + * For details on the constants and equations used to calculate the baud rate + * settings, please consult the PL011 TRM. + */ +static int set_baud_rate(unsigned int baud_rate_bps, uint64_t clock_rate_hz, + struct pl011_reg *reg) +{ + uint32_t divisor_integer; + uint32_t divisor_fractional; + uint32_t divisor; + uint32_t clock_rate_x4; + + assert(reg); + + if (baud_rate_bps == 0) + return FWK_E_PARAM; + + if ((clock_rate_hz < PL011_UARTCLK_MIN) || + (clock_rate_hz > PL011_UARTCLK_MAX)) + return FWK_E_PARAM; + + /* The highest clock x4 should still fit in 32 bits */ + assert((PL011_UARTCLK_MAX * UINT64_C(4)) < UINT32_MAX); + + /* Ensure baud rate is not higher than the clock can support */ + clock_rate_x4 = clock_rate_hz * 4; + if (baud_rate_bps > clock_rate_x4) + return FWK_E_RANGE; + + /* Calculate integer and fractional divisors */ + divisor = clock_rate_x4 / baud_rate_bps; + divisor_integer = divisor / 64; + divisor_fractional = divisor % 64; + + /* The integer divisor must fit in 16 bits */ + if (divisor_integer > 0xffff) + return FWK_E_RANGE; + + /* The fractional divisor must fit in 6 bits */ + if (divisor_fractional > 0x3f) + return FWK_E_RANGE; + + /* + * When the integer divisor is equals to 0xffff, the fractional divisor can + * only be 0. + */ + if ((divisor_integer == 0xffff) && (divisor_fractional != 0)) + return FWK_E_RANGE; + + /* Set registers */ + reg->IBRD = divisor_integer; + reg->FBRD = divisor_fractional; + + return FWK_SUCCESS; +} + +/* + * Module log driver API + */ + +static int do_putchar(fwk_id_t device_id, char c) +{ + int status; + struct pl011_reg *reg; + + status = fwk_module_check_call(device_id); + if (status != FWK_SUCCESS) + return status; + + reg = get_device_reg(device_id); + + while (reg->FR & PL011_FR_TXFF) + continue; + + reg->DR = c; + + return FWK_SUCCESS; +} + +static int do_flush(fwk_id_t device_id) +{ + int status; + struct pl011_reg *reg; + + status = fwk_module_check_call(device_id); + if (status != FWK_SUCCESS) + return status; + + reg = get_device_reg(device_id); + + while (reg->FR & PL011_FR_BUSY) + continue; + + return FWK_SUCCESS; +} + +static const struct mod_log_driver_api driver_api = { + .flush = do_flush, + .putchar = do_putchar, +}; + +/* + * Framework handlers + */ + +static int pl011_init(fwk_id_t module_id, unsigned int element_count, + const void *data) +{ + if (element_count == 0) + return FWK_E_DATA; + + /* + * Create an array of pointers used to store the configuration data pointer + * of each element. + */ + device_config_table = fwk_mm_calloc(element_count, + sizeof(*device_config_table)); + if (device_config_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int pl011_element_init(fwk_id_t element_id, unsigned int unused, + const void *data) +{ + struct pl011_reg *reg; + const struct mod_pl011_device_config *config = data; + int status; + + reg = (struct pl011_reg *)config->reg_base; + if (reg == NULL) + return FWK_E_DATA; + + status = set_baud_rate(config->baud_rate_bps, + config->clock_rate_hz, + reg); + if (status != FWK_SUCCESS) + return status; + + /* + * Initialize PL011 device + */ + reg->ECR = PL011_ECR_CLR; + reg->LCR_H = PL011_LCR_H_WLEN_8BITS | + PL011_LCR_H_FEN; + reg->CR = PL011_CR_UARTEN | + PL011_CR_RXE | + PL011_CR_TXE; + + device_config_table[fwk_id_get_element_idx(element_id)] = config; + + return FWK_SUCCESS; +} + +static int pl011_process_bind_request(fwk_id_t requester_id, fwk_id_t target_id, + fwk_id_t api_id, const void **api) +{ + *api = &driver_api; + + return FWK_SUCCESS; +} + +static int pl011_start(fwk_id_t id) +{ + const struct mod_pl011_device_config *config; + + if (!fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) + return FWK_SUCCESS; + + config = device_config_table[fwk_id_get_element_idx(id)]; + + if (fwk_id_is_type(config->clock_id, FWK_ID_TYPE_NONE)) + return FWK_SUCCESS; + + return FWK_SUCCESS; + +} + + +const struct fwk_module module_pl011 = { + .name = "PL011", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = pl011_init, + .element_init = pl011_element_init, + .start = pl011_start, + .process_bind_request = pl011_process_bind_request, +}; diff --git a/product/corstone-1000/module/pl011/src/pl011.h b/product/corstone-1000/module/pl011/src/pl011.h new file mode 100644 index 0000000..48815f4 --- /dev/null +++ b/product/corstone-1000/module/pl011/src/pl011.h @@ -0,0 +1,160 @@ +/* + * + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PL011_H +#define PL011_H + +#include + +struct pl011_reg { + FWK_RW uint16_t DR; + uint16_t RESERVED0; + union { + FWK_RW uint8_t RSR; + FWK_RW uint8_t ECR; + }; + uint8_t RESERVED1[0x18 - 0x05]; + FWK_R uint16_t FR; + uint16_t RESERVED2[3]; + FWK_RW uint8_t ILPR; + uint8_t RESERVED3[3]; + FWK_RW uint16_t IBRD; + uint16_t RESERVED4; + FWK_RW uint32_t FBRD; + FWK_RW uint16_t LCR_H; + uint16_t RESERVED5; + FWK_RW uint16_t CR; + uint16_t RESERVED6; + FWK_RW uint16_t IFLS; + uint16_t RESERVED7; + FWK_RW uint16_t IMSC; + uint16_t RESERVED8; + FWK_R uint16_t RIS; + uint16_t RESERVED9; + FWK_R uint16_t MIS; + uint16_t RESERVED10; + FWK_W uint16_t ICR; + uint16_t RESERVED11; + FWK_RW uint16_t DMACR; + uint8_t RESERVED12[0xFE0 - 0x4C]; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +#define PL011_DR_DATA UINT16_C(0x00FF) +#define PL011_DR_FE UINT16_C(0x0100) +#define PL011_DR_PE UINT16_C(0x0200) +#define PL011_DR_BE UINT16_C(0x0400) +#define PL011_DR_OE UINT16_C(0x0800) + +#define PL011_RSR_FE UINT8_C(0x01) +#define PL011_RSR_PE UINT8_C(0x02) +#define PL011_RSR_BE UINT8_C(0x04) +#define PL011_RSR_OE UINT8_C(0x08) +#define PL011_ECR_CLR UINT8_C(0xFF) + +#define PL011_FR_CTS UINT16_C(0x0001) +#define PL011_FR_DSR UINT16_C(0x0002) +#define PL011_FR_DCD UINT16_C(0x0004) +#define PL011_FR_BUSY UINT16_C(0x0008) +#define PL011_FR_RXFE UINT16_C(0x0010) +#define PL011_FR_TXFF UINT16_C(0x0020) +#define PL011_FR_RXFF UINT16_C(0x0040) +#define PL011_FR_TXFE UINT16_C(0x0080) +#define PL011_FR_RI UINT16_C(0x0100) + +#define PL011_LCR_H_BRK UINT16_C(0x0001) +#define PL011_LCR_H_PEN UINT16_C(0x0002) +#define PL011_LCR_H_EPS UINT16_C(0x0004) +#define PL011_LCR_H_STP2 UINT16_C(0x0008) +#define PL011_LCR_H_FEN UINT16_C(0x0010) +#define PL011_LCR_H_WLEN UINT16_C(0x0060) +#define PL011_LCR_H_WLEN_5BITS UINT16_C(0x0000) +#define PL011_LCR_H_WLEN_6BITS UINT16_C(0x0020) +#define PL011_LCR_H_WLEN_7BITS UINT16_C(0x0040) +#define PL011_LCR_H_WLEN_8BITS UINT16_C(0x0060) +#define PL011_LCR_H_SPS UINT16_C(0x0080) + +#define PL011_CR_UARTEN UINT16_C(0x0001) +#define PL011_CR_SIREN UINT16_C(0x0002) +#define PL011_CR_SIRLP UINT16_C(0x0004) +#define PL011_CR_LBE UINT16_C(0x0080) +#define PL011_CR_TXE UINT16_C(0x0100) +#define PL011_CR_RXE UINT16_C(0x0200) +#define PL011_CR_DTR UINT16_C(0x0400) +#define PL011_CR_RTS UINT16_C(0x0800) +#define PL011_CR_OUT1 UINT16_C(0x1000) +#define PL011_CR_OUT2 UINT16_C(0x2000) +#define PL011_CR_RTSEN UINT16_C(0x4000) +#define PL011_CR_CTSEN UINT16_C(0x8000) + +#define PL011_IFLS_TXIFLSEL UINT16_C(0x0007) +#define PL011_IFLS_RXIFLSEL UINT16_C(0x0038) + +#define PL011_IMSC_RIMIM UINT16_C(0x0001) +#define PL011_IMSC_CTSMIM UINT16_C(0x0002) +#define PL011_IMSC_DCDMIM UINT16_C(0x0004) +#define PL011_IMSC_DSRMIM UINT16_C(0x0008) +#define PL011_IMSC_RXIM UINT16_C(0x0010) +#define PL011_IMSC_TXIM UINT16_C(0x0020) +#define PL011_IMSC_RTIM UINT16_C(0x0040) +#define PL011_IMSC_FEIM UINT16_C(0x0080) +#define PL011_IMSC_PEIM UINT16_C(0x0100) +#define PL011_IMSC_BEIM UINT16_C(0x0200) +#define PL011_IMSC_OEIM UINT16_C(0x0400) + +#define PL011_RIS_RIRMIS UINT16_C(0x0001) +#define PL011_RIS_CTSRMIS UINT16_C(0x0002) +#define PL011_RIS_DCDRMIS UINT16_C(0x0004) +#define PL011_RIS_DSRRMIS UINT16_C(0x0008) +#define PL011_RIS_RXRIS UINT16_C(0x0010) +#define PL011_RIS_TXRIS UINT16_C(0x0020) +#define PL011_RIS_RTRIS UINT16_C(0x0040) +#define PL011_RIS_FERIS UINT16_C(0x0080) +#define PL011_RIS_PERIS UINT16_C(0x0100) +#define PL011_RIS_BERIS UINT16_C(0x0200) +#define PL011_RIS_OERIS UINT16_C(0x0400) + +#define PL011_MIS_RIMMIS UINT16_C(0x0001) +#define PL011_MIS_CTSMMIS UINT16_C(0x0002) +#define PL011_MIS_DCDMMIS UINT16_C(0x0004) +#define PL011_MIS_DSRMMIS UINT16_C(0x0008) +#define PL011_MIS_RXMIS UINT16_C(0x0010) +#define PL011_MIS_TXMIS UINT16_C(0x0020) +#define PL011_MIS_RTMIS UINT16_C(0x0040) +#define PL011_MIS_FEMIS UINT16_C(0x0080) +#define PL011_MIS_PEMIS UINT16_C(0x0100) +#define PL011_MIS_BEMIS UINT16_C(0x0200) +#define PL011_MIS_OEMIS UINT16_C(0x0400) + +#define PL011_ICR_RIMIC UINT16_C(0x0001) +#define PL011_ICR_CTSMIC UINT16_C(0x0002) +#define PL011_ICR_DCDMIC UINT16_C(0x0004) +#define PL011_ICR_DSRMIC UINT16_C(0x0008) +#define PL011_ICR_RXIC UINT16_C(0x0010) +#define PL011_ICR_TXIC UINT16_C(0x0020) +#define PL011_ICR_RTIC UINT16_C(0x0040) +#define PL011_ICR_FEIC UINT16_C(0x0080) +#define PL011_ICR_PEIC UINT16_C(0x0100) +#define PL011_ICR_BEIC UINT16_C(0x0200) +#define PL011_ICR_OEIC UINT16_C(0x0400) + +#define PL011_DMACR_RXDMAE UINT16_C(0x0001) +#define PL011_DMACR_TXDMAE UINT16_C(0x0002) +#define PL011_DMACR_DMAAONERR UINT16_C(0x0004) + +#define PL011_UARTCLK_MIN (1420 * FWK_KHZ) +#define PL011_UARTCLK_MAX (542720 * FWK_KHZ) + +#endif /* PL011 */ diff --git a/product/corstone-1000/product.mk b/product/corstone-1000/product.mk new file mode 100644 index 0000000..6cf79e1 --- /dev/null +++ b/product/corstone-1000/product.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +BS_PRODUCT_NAME := corstone-1000 +BS_FIRMWARE_LIST := firmware -- GitLab