Merge pull request #1691 from vijayenthiran-arm/sgi-dmc620-tzc
Add support for dmc620 tzc driver
This commit is contained in:
commit
9165684996
|
@ -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");
|
||||
}
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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} \
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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} \
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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} \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
Loading…
Reference in New Issue