diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c new file mode 100644 index 0000000000000000000000000000000000000000..4abd0800b1dc5b034b3f0c7ac15cf746e8a1664c --- /dev/null +++ b/drivers/arm/tzc/tzc_dmc620.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <debug.h> +#include <mmio.h> +#include <tzc_dmc620.h> + +/* Mask to extract bit 31 to 16 */ +#define MASK_31_16 UINT64_C(0x0000ffff0000) +/* Mask to extract bit 47 to 32 */ +#define MASK_47_32 UINT64_C(0xffff00000000) + +/* Helper macro for getting dmc_base addr of a dmc_inst */ +#define DMC_BASE(plat_data, dmc_inst) \ + ((uintptr_t)(plat_data->dmc_base[dmc_inst])) + +/* Pointer to the tzc_dmc620_config_data structure populated by the platform */ +static const tzc_dmc620_config_data_t *g_plat_config_data; + +#if ENABLE_ASSERTIONS +/* + * Helper function to check if the DMC-620 instance is present at the + * base address provided by the platform and also check if at least + * one dmc instance is present. + */ +static void tzc_dmc620_validate_plat_driver_data( + const tzc_dmc620_driver_data_t *plat_driver_data) +{ + uint8_t dmc_inst, dmc_count; + unsigned int dmc_id; + uintptr_t base; + + assert(plat_driver_data != NULL); + + dmc_count = plat_driver_data->dmc_count; + assert(dmc_count > 0U); + + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + base = DMC_BASE(plat_driver_data, dmc_inst); + dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0); + assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE); + } +} +#endif + +/* + * Program a region with region base and region top addresses of all + * DMC-620 instances. + */ +static void tzc_dmc620_configure_region(int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr) +{ + uint32_t min_31_00, min_47_32; + uint32_t max_31_00, max_47_32; + uint8_t dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + assert(plat_driver_data != NULL); + + /* Do range checks on regions. */ + assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + min_31_00 = (region_base & MASK_31_16) | sec_attr; + min_47_32 = (region_base & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH; + max_31_00 = (region_top & MASK_31_16); + max_47_32 = (region_top & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH; + + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Configure access address region registers */ + mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no), + min_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no), + min_47_32); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no), + max_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no), + max_47_32); + } +} + +/* + * Set the action value for all the DMC-620 instances. + */ +static void tzc_dmc620_set_action(void) +{ + uint8_t dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Switch to READY */ + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO); + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE); + } +} + +/* + * Verify whether the DMC-620 configuration is complete by reading back + * configuration registers and comparing it with the configured value. If + * configuration is incomplete, loop till the configured value is reflected in + * the register. + */ +static void tzc_dmc620_verify_complete(void) +{ + uint8_t dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + while ((mmio_read_32(base + DMC620_MEMC_STATUS) & + DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) + continue; + } +} + +/* + * Initialize the DMC-620 TrustZone Controller using the region configuration + * supplied by the platform. The DMC620 controller should be enabled elsewhere + * before invoking this function. + */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data) +{ + int i; + + /* Check if valid pointer is passed */ + assert(plat_config_data != NULL); + + /* + * Check if access address count passed by the platform is less than or + * equal to DMC620's access address count + */ + assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT); + +#if ENABLE_ASSERTIONS + /* Validates the information passed by platform */ + tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data); +#endif + + g_plat_config_data = plat_config_data; + + INFO("Configuring DMC-620 TZC settings\n"); + for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) + tzc_dmc620_configure_region(i, + g_plat_config_data->plat_acc_addr_data[i].region_base, + g_plat_config_data->plat_acc_addr_data[i].region_top, + g_plat_config_data->plat_acc_addr_data[i].sec_attr); + + tzc_dmc620_set_action(); + tzc_dmc620_verify_complete(); + INFO("DMC-620 TZC setup completed\n"); +} diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h new file mode 100644 index 0000000000000000000000000000000000000000..074bbc1224108f2170c0280c7b85999d35b30081 --- /dev/null +++ b/include/drivers/arm/tzc_dmc620.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_DMC620_H +#define TZC_DMC620_H + +#include <utils_def.h> + +/* DMC-620 memc register offsets */ +#define DMC620_MEMC_STATUS U(0x0000) +#define DMC620_MEMC_CMD U(0x0008) + +/* Mask value to check the status of memc_cmd register */ +#define DMC620_MEMC_CMD_MASK U(0x00000007) + +/* memc_cmd register's action values */ +#define DMC620_MEMC_CMD_GO U(0x00000003) +#define DMC620_MEMC_CMD_EXECUTE U(0x00000004) + +/* Address offsets of access address next region 0 registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE U(0x0080) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE U(0x0084) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE U(0x0088) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE U(0x008c) + +/* Length of one block of access address next register region */ +#define DMC620_ACC_ADDR_NEXT_SIZE U(0x0010) + +/* Address offsets of access address next registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE + \ + (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE + \ + (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE + \ + (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE + \ + (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) + +/* Number of TZC address regions in DMC-620 */ +#define DMC620_ACC_ADDR_COUNT U(8) +/* Width of access address registers */ +#define DMC620_ACC_ADDR_WIDTH U(32) + +/* Peripheral ID registers offsets */ +#define DMC620_PERIPHERAL_ID_0 U(0x1fe0) + +/* Default values in id registers */ +#define DMC620_PERIPHERAL_ID_0_VALUE U(0x00000054) + +/* Secure access region attributes. */ +#define TZC_DMC620_REGION_NS_RD U(0x00000001) +#define TZC_DMC620_REGION_NS_WR U(0x00000002) +#define TZC_DMC620_REGION_NS_RDWR \ + (TZC_DMC620_REGION_NS_RD | TZC_DMC620_REGION_NS_WR) +#define TZC_DMC620_REGION_S_RD U(0x00000004) +#define TZC_DMC620_REGION_S_WR U(0x00000008) +#define TZC_DMC620_REGION_S_RDWR \ + (TZC_DMC620_REGION_S_RD | TZC_DMC620_REGION_S_WR) +#define TZC_DMC620_REGION_S_NS_RDWR \ + (TZC_DMC620_REGION_NS_RDWR | TZC_DMC620_REGION_S_RDWR) + +/* + * Contains pointer to the base addresses of all the DMC-620 instances. + * 'dmc_count' specifies the number of DMC base addresses contained in the + * array pointed to by dmc_base. + */ +typedef struct tzc_dmc620_driver_data { + const uintptr_t *dmc_base; + const unsigned int dmc_count; +} tzc_dmc620_driver_data_t; + +/* + * Contains region base, region top addresses and corresponding attributes + * for configuring TZC access region registers. + */ +typedef struct tzc_dmc620_acc_addr_data { + const unsigned long long region_base; + const unsigned long long region_top; + const unsigned int sec_attr; +} tzc_dmc620_acc_addr_data_t; + +/* + * Contains platform specific data for configuring TZC region base and + * region top address. 'acc_addr_count' specifies the number of + * valid entries in 'plat_acc_addr_data' array. + */ +typedef struct tzc_dmc620_config_data { + const tzc_dmc620_driver_data_t *plat_drv_data; + const tzc_dmc620_acc_addr_data_t *plat_acc_addr_data; + const uint8_t acc_addr_count; +} tzc_dmc620_config_data_t; + +/* Function prototypes */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data); + +#endif /* TZC_DMC620_H */ + diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h index 1870fc78aed86a1e830d8d8c7702b62fb2327006..c06a0a1fa8932dede1b340b92667aad26b851ee6 100644 --- a/plat/arm/board/sgi575/include/platform_def.h +++ b/plat/arm/board/sgi575/include/platform_def.h @@ -8,11 +8,16 @@ #define PLATFORM_DEF_H #include <sgi_base_platform_def.h> +#include <utils_def.h> #define PLAT_ARM_CLUSTER_COUNT 2 #define CSS_SGI_MAX_CPUS_PER_CLUSTER 4 #define CSS_SGI_MAX_PE_PER_CPU 1 -#define PLAT_CSS_MHU_BASE 0x45000000 +#define PLAT_CSS_MHU_BASE UL(0x45000000) + +/* Base address of DMC-620 instances */ +#define SGI575_DMC620_BASE0 UL(0x4e000000) +#define SGI575_DMC620_BASE1 UL(0x4e100000) #endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk index 8df8b1292a1764400bfee12c1d136d20a143b2df..dd82d2975f61d37e3d666487a9b7f228b648b648 100644 --- a/plat/arm/board/sgi575/platform.mk +++ b/plat/arm/board/sgi575/platform.mk @@ -14,7 +14,9 @@ SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S BL1_SOURCES += ${SGI_CPU_SOURCES} -BL2_SOURCES += lib/utils/mem_region.c \ +BL2_SOURCES += ${SGI575_BASE}/sgi575_security.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c BL31_SOURCES += ${SGI_CPU_SOURCES} \ diff --git a/plat/arm/board/sgi575/sgi575_security.c b/plat/arm/board/sgi575/sgi575_security.c new file mode 100644 index 0000000000000000000000000000000000000000..7ccc59a7bc696e9601cfb4a6f0786def760dd04e --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_security.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <platform_def.h> +#include <tzc_dmc620.h> + +uintptr_t sgi575_dmc_base[] = { + SGI575_DMC620_BASE0, + SGI575_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t sgi575_plat_driver_data = { + .dmc_base = sgi575_dmc_base, + .dmc_count = ARRAY_SIZE(sgi575_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t sgi575_acc_addr_data[] = { + { + .region_base = ARM_AP_TZC_DRAM1_BASE, + .region_top = ARM_AP_TZC_DRAM1_BASE + ARM_TZC_DRAM1_SIZE - 1, + .sec_attr = TZC_DMC620_REGION_S_RDWR + } +}; + +static const tzc_dmc620_config_data_t sgi575_plat_config_data = { + .plat_drv_data = &sgi575_plat_driver_data, + .plat_acc_addr_data = sgi575_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(sgi575_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&sgi575_plat_config_data); +} diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h index abc48d84cf6da854f7164eba9ae070d07ef34a3c..ba6d0434bb7eb1f63aaa7eb160521017d107a189 100644 --- a/plat/arm/board/sgiclarka/include/platform_def.h +++ b/plat/arm/board/sgiclarka/include/platform_def.h @@ -8,11 +8,16 @@ #define PLATFORM_DEF_H #include <sgi_base_platform_def.h> +#include <utils_def.h> #define PLAT_ARM_CLUSTER_COUNT 2 #define CSS_SGI_MAX_CPUS_PER_CLUSTER 4 #define CSS_SGI_MAX_PE_PER_CPU 1 -#define PLAT_CSS_MHU_BASE 0x45400000 +#define PLAT_CSS_MHU_BASE UL(0x45400000) + +/* Base address of DMC-620 instances */ +#define SGICLARKA_DMC620_BASE0 UL(0x4e000000) +#define SGICLARKA_DMC620_BASE1 UL(0x4e100000) #endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk index fc2f766704ef3fc180414423047fc6294f541715..cf02219fb9713f0fc3f85a5bdbb09d8cd9f19e69 100644 --- a/plat/arm/board/sgiclarka/platform.mk +++ b/plat/arm/board/sgiclarka/platform.mk @@ -14,7 +14,9 @@ SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_ares.S BL1_SOURCES += ${SGI_CPU_SOURCES} -BL2_SOURCES += lib/utils/mem_region.c \ +BL2_SOURCES += ${SGICLARKA_BASE}/sgiclarka_security.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c BL31_SOURCES += ${SGI_CPU_SOURCES} \ diff --git a/plat/arm/board/sgiclarka/sgiclarka_security.c b/plat/arm/board/sgiclarka/sgiclarka_security.c new file mode 100644 index 0000000000000000000000000000000000000000..29cd75474496f49e14ecdf2c3a4f3b1f30b34b21 --- /dev/null +++ b/plat/arm/board/sgiclarka/sgiclarka_security.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <platform_def.h> +#include <tzc_dmc620.h> + +uintptr_t sgiclarka_dmc_base[] = { + SGICLARKA_DMC620_BASE0, + SGICLARKA_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t sgiclarka_plat_driver_data = { + .dmc_base = sgiclarka_dmc_base, + .dmc_count = ARRAY_SIZE(sgiclarka_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t sgiclarka_acc_addr_data[] = { + { + .region_base = ARM_AP_TZC_DRAM1_BASE, + .region_top = ARM_AP_TZC_DRAM1_BASE + ARM_TZC_DRAM1_SIZE - 1, + .sec_attr = TZC_DMC620_REGION_S_RDWR + } +}; + +static const tzc_dmc620_config_data_t sgiclarka_plat_config_data = { + .plat_drv_data = &sgiclarka_plat_driver_data, + .plat_acc_addr_data = sgiclarka_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(sgiclarka_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&sgiclarka_plat_config_data); +} diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk index d6e5448de1542cc22c054fbd9f41ff2284ca6f4c..46fa7c4d798a015fe07f4899a3933ddb5dcdc607 100644 --- a/plat/arm/css/sgi/sgi-common.mk +++ b/plat/arm/css/sgi/sgi-common.mk @@ -35,8 +35,7 @@ PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c \ BL1_SOURCES += ${INTERCONNECT_SOURCES} -BL2_SOURCES += ${CSS_ENT_BASE}/sgi_security.c \ - ${CSS_ENT_BASE}/sgi_image_load.c +BL2_SOURCES += ${CSS_ENT_BASE}/sgi_image_load.c BL31_SOURCES += ${INTERCONNECT_SOURCES} \ ${ENT_GIC_SOURCES} \ diff --git a/plat/arm/css/sgi/sgi_security.c b/plat/arm/css/sgi/sgi_security.c deleted file mode 100644 index 23e1a64e51fe920db4f0daffef0281f6a44ef699..0000000000000000000000000000000000000000 --- a/plat/arm/css/sgi/sgi_security.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <arm_config.h> -#include <plat_arm.h> - -/* - * We assume that all security programming is done by the primary core. - */ -void plat_arm_security_setup(void) -{ -}