Commit 105b59e7 authored by danh-arm's avatar danh-arm
Browse files

Merge pull request #575 from soby-mathew/sm/new_tzc_driver

Refactor the TZC driver and add DMC-500 driver
parents 5d29c760 618f0fee
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <stddef.h>
#include <tzc400.h>
#include "tzc_common_private.c"
/*
* Macros which will be used by common core functions.
*/
#define TZC_400_REGION_BASE_LOW_0_OFFSET 0x100
#define TZC_400_REGION_BASE_HIGH_0_OFFSET 0x104
#define TZC_400_REGION_TOP_LOW_0_OFFSET 0x108
#define TZC_400_REGION_TOP_HIGH_0_OFFSET 0x10c
#define TZC_400_REGION_ATTR_0_OFFSET 0x110
#define TZC_400_REGION_ID_ACCESS_0_OFFSET 0x114
/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
typedef struct tzc400_instance {
uintptr_t base;
uint8_t addr_width;
uint8_t num_filters;
uint8_t num_regions;
} tzc400_instance_t;
tzc400_instance_t tzc400;
static inline unsigned int _tzc400_read_build_config(uintptr_t base)
{
return mmio_read_32(base + BUILD_CONFIG_OFF);
}
static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base)
{
return mmio_read_32(base + GATE_KEEPER_OFF);
}
static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GATE_KEEPER_OFF, val);
}
/*
* Get the open status information for all filter units.
*/
#define get_gate_keeper_os(base) ((_tzc400_read_gate_keeper(base) >> \
GATE_KEEPER_OS_SHIFT) & \
GATE_KEEPER_OS_MASK)
/* Define common core functions used across different TZC peripherals. */
DEFINE_TZC_COMMON_WRITE_ACTION(400, 400)
DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400)
DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
unsigned int filter)
{
unsigned int open_status;
open_status = get_gate_keeper_os(base);
return (open_status >> filter) & GATE_KEEPER_FILTER_MASK;
}
/* This function is not MP safe. */
static void _tzc400_set_gate_keeper(uintptr_t base,
unsigned int filter,
int val)
{
unsigned int open_status;
/* Upper half is current state. Lower half is requested state. */
open_status = get_gate_keeper_os(base);
if (val)
open_status |= (1 << filter);
else
open_status &= ~(1 << filter);
_tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
GATE_KEEPER_OR_SHIFT);
/* Wait here until we see the change reflected in the TZC status. */
while ((get_gate_keeper_os(base)) != open_status)
;
}
void tzc400_set_action(tzc_action_t action)
{
assert(tzc400.base);
assert(action <= TZC_ACTION_ERR_INT);
/*
* - Currently no handler is provided to trap an error via interrupt
* or exception.
* - The interrupt action has not been tested.
*/
_tzc400_write_action(tzc400.base, action);
}
void tzc400_init(uintptr_t base)
{
#if DEBUG
unsigned int tzc400_id;
#endif
unsigned int tzc400_build;
assert(base);
tzc400.base = base;
#if DEBUG
tzc400_id = _tzc_read_peripheral_id(base);
if (tzc400_id != TZC_400_PERIPHERAL_ID) {
ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
panic();
}
#endif
/* Save values we will use later. */
tzc400_build = _tzc400_read_build_config(tzc400.base);
tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
BUILD_CONFIG_NF_MASK) + 1;
tzc400.addr_width = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
BUILD_CONFIG_AW_MASK) + 1;
tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
BUILD_CONFIG_NR_MASK) + 1;
}
/*
* `tzc400_configure_region0` is used to program region 0 into the TrustZone
* controller. Region 0 covers the whole address space that is not mapped
* to any other region, and is enabled on all filters; this cannot be
* changed. This function only changes the access permissions.
*/
void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
unsigned int ns_device_access)
{
assert(tzc400.base);
assert(sec_attr <= TZC_REGION_S_RDWR);
_tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
}
/*
* `tzc400_configure_region` is used to program regions into the TrustZone
* controller. A region can be associated with more than one filter. The
* associated filters are passed in as a bitmap (bit0 = filter0).
* NOTE:
* Region 0 is special; it is preferable to use tzc400_configure_region0
* for this region (see comment for that function).
*/
void tzc400_configure_region(unsigned int filters,
int region,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int nsaid_permissions)
{
assert(tzc400.base);
/* Do range checks on filters and regions. */
assert(((filters >> tzc400.num_filters) == 0) &&
(region >= 0) && (region < tzc400.num_regions));
/*
* Do address range check based on TZC configuration. A 64bit address is
* the max and expected case.
*/
assert(((region_top <= (UINT64_MAX >> (64 - tzc400.addr_width))) &&
(region_base < region_top)));
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
assert(sec_attr <= TZC_REGION_S_RDWR);
_tzc400_configure_region(tzc400.base, filters, region, region_base,
region_top,
sec_attr, nsaid_permissions);
}
void tzc400_enable_filters(void)
{
unsigned int state;
unsigned int filter;
assert(tzc400.base);
for (filter = 0; filter < tzc400.num_filters; filter++) {
state = _tzc400_get_gate_keeper(tzc400.base, filter);
if (state) {
/* The TZC filter is already configured. Changing the
* programmer's view in an active system can cause
* unpredictable behavior therefore panic for now rather
* than try to determine whether this is safe in this
* instance. See:
* http://infocenter.arm.com/help/index.jsp?\
* topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
ERROR("TZC-400 : Filter %d Gatekeeper already"
" enabled.\n", filter);
panic();
}
_tzc400_set_gate_keeper(tzc400.base, filter, 1);
}
}
void tzc400_disable_filters(void)
{
unsigned int filter;
assert(tzc400.base);
/*
* We don't do the same state check as above as the Gatekeepers are
* disabled after reset.
*/
for (filter = 0; filter < tzc400.num_filters; filter++)
_tzc400_set_gate_keeper(tzc400.base, filter, 0);
}
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <mmio.h>
#include <tzc_common.h>
#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name) \
static inline void _tzc##fn_name##_write_action( \
uintptr_t base, \
tzc_action_t action) \
{ \
mmio_write_32(base + TZC_##macro_name##_ACTION_OFF, \
action); \
}
#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name) \
static inline void _tzc##fn_name##_write_region_base( \
uintptr_t base, \
int region_no, \
uintptr_t region_base) \
{ \
mmio_write_32(base + \
TZC_REGION_OFFSET( \
TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET, \
(unsigned int)region_base); \
mmio_write_32(base + \
TZC_REGION_OFFSET( \
TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET, \
(unsigned int)(region_base >> 32)); \
}
#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name) \
static inline void _tzc##fn_name##_write_region_top( \
uintptr_t base, \
int region_no, \
uintptr_t region_top) \
{ \
mmio_write_32(base + \
TZC_REGION_OFFSET \
(TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET, \
(unsigned int)region_top); \
mmio_write_32(base + \
TZC_REGION_OFFSET( \
TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET, \
(unsigned int)(region_top >> 32)); \
}
#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name) \
static inline void _tzc##fn_name##_write_region_attributes( \
uintptr_t base, \
int region_no, \
unsigned int attr) \
{ \
mmio_write_32(base + \
TZC_REGION_OFFSET( \
TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_ATTR_0_OFFSET, \
attr); \
}
#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name) \
static inline void _tzc##fn_name##_write_region_id_access( \
uintptr_t base, \
int region_no, \
unsigned int val) \
{ \
mmio_write_32(base + \
TZC_REGION_OFFSET( \
TZC_##macro_name##_REGION_SIZE, \
region_no) + \
TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET, \
val); \
}
/*
* It is used to program region 0 ATTRIBUTES and ACCESS register.
*/
#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \
void _tzc##fn_name##_configure_region0(uintptr_t base, \
tzc_region_attributes_t sec_attr, \
unsigned int ns_device_access) \
{ \
assert(base); \
VERBOSE("TrustZone : Configuring region 0 " \
"(TZC Interface Base=%p sec_attr=0x%x," \
" ns_devs=0x%x)\n", (void *)base, \
sec_attr, ns_device_access); \
\
/* Set secure attributes on region 0 */ \
_tzc##fn_name##_write_region_attributes(base, 0, \
sec_attr << TZC_REGION_ATTR_SEC_SHIFT); \
\
/***************************************************/ \
/* Specify which non-secure devices have permission*/ \
/* to access region 0. */ \
/***************************************************/ \
_tzc##fn_name##_write_region_id_access(base, \
0, \
ns_device_access); \
}
/*
* It is used to program a region from 1 to 8 in the TrustZone controller.
* NOTE:
* Region 0 is special; it is preferable to use
* ##fn_name##_configure_region0 for this region (see comment for
* that function).
*/
#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name) \
void _tzc##fn_name##_configure_region(uintptr_t base, \
unsigned int filters, \
int region_no, \
uintptr_t region_base, \
uintptr_t region_top, \
tzc_region_attributes_t sec_attr, \
unsigned int nsaid_permissions) \
{ \
assert(base); \
VERBOSE("TrustZone : Configuring region " \
"(TZC Interface Base: %p, region_no = %d)" \
"...\n", (void *)base, region_no); \
VERBOSE("TrustZone : ... base = %p, top = %p," \
"\n", (void *)region_base, (void *)region_top);\
VERBOSE("TrustZone : ... sec_attr = 0x%x," \
" ns_devs = 0x%x)\n", \
sec_attr, nsaid_permissions); \
\
/***************************************************/ \
/* Inputs look ok, start programming registers. */ \
/* All the address registers are 32 bits wide and */ \
/* have a LOW and HIGH */ \
/* component used to construct an address up to a */ \
/* 64bit. */ \
/***************************************************/ \
_tzc##fn_name##_write_region_base(base, \
region_no, region_base); \
_tzc##fn_name##_write_region_top(base, \
region_no, region_top); \
\
/* Enable filter to the region and set secure attributes */\
_tzc##fn_name##_write_region_attributes(base, \
region_no, \
(sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
(filters << TZC_REGION_ATTR_F_EN_SHIFT));\
\
/***************************************************/ \
/* Specify which non-secure devices have permission*/ \
/* to access this region. */ \
/***************************************************/ \
_tzc##fn_name##_write_region_id_access(base, \
region_no, \
nsaid_permissions); \
}
#if DEBUG
static unsigned int _tzc_read_peripheral_id(uintptr_t base)
{
unsigned int id;
id = mmio_read_32(base + PID0_OFF);
/* Masks DESC part in PID1 */
id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
return id;
}
#endif
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <tzc_dmc500.h>
#include "tzc_common.h"
#include "tzc_common_private.c"
/*
* Macros which will be used by common core functions.
*/
#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET 0x054
#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET 0x058
#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET 0x05C
#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET 0x060
#define TZC_DMC500_REGION_ATTR_0_OFFSET 0x064
#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET 0x068
#define TZC_DMC500_ACTION_OFF 0x50
/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
static const tzc_dmc500_driver_data_t *g_driver_data;
#define verify_region_attr(region, attr) \
((g_conf_regions[(region)].sec_attr == \
((attr) >> TZC_REGION_ATTR_SEC_SHIFT)) \
&& ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT)))
/*
* Structure for configured regions attributes in DMC500.
*/
typedef struct tzc_dmc500_regions {
tzc_region_attributes_t sec_attr;
int is_enabled;
} tzc_dmc500_regions_t;
/*
* Array storing the attributes of the configured regions. This array
* will be used by the `tzc_dmc500_verify_complete` to verify the flush
* completion.
*/
static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1];
/* Helper Macros for making the code readable */
#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance])
#define DMC_INST_SI_BASE(instance, interface) \
(DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface))
DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500)
DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500)
DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500)
DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500)
DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500)
DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500)
DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500)
static inline unsigned int _tzc_dmc500_read_region_attr_0(
uintptr_t dmc_si_base,
int region_no)
{
return mmio_read_32(dmc_si_base +
TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
TZC_DMC500_REGION_ATTR_0_OFFSET);
}
static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base)
{
mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1);
}
/*
* Sets the Flush controls for all the DMC Instances and System Interfaces.
* This initiates the flush of configuration settings from the shadow
* registers to the actual configuration register. The caller should poll
* changed register to confirm update.
*/
void tzc_dmc500_config_complete(void)
{
int dmc_inst, sys_if;
assert(g_driver_data);
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
_tzc_dmc500_write_flush_control(
DMC_INST_SI_BASE(dmc_inst, sys_if));
}
}
/*
* This function reads back the secure attributes from the configuration
* register for each DMC Instance and System Interface and compares it with
* the configured value. The successful verification of the region attributes
* confirms that the flush operation has completed.
* If the verification fails, the caller is expected to invoke this API again
* till it succeeds.
* Returns 0 on success and 1 on failure.
*/
int tzc_dmc500_verify_complete(void)
{
int dmc_inst, sys_if, region_no;
unsigned int attr;
assert(g_driver_data);
/* Region 0 must be configured */
assert(g_conf_regions[0].is_enabled);
/* Iterate over all configured regions */
for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) {
if (!g_conf_regions[region_no].is_enabled)
continue;
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
sys_if++) {
attr = _tzc_dmc500_read_region_attr_0(
DMC_INST_SI_BASE(dmc_inst, sys_if),
region_no);
VERBOSE("Verifying DMC500 region:%d"
" dmc_inst:%d sys_if:%d attr:%x\n",
region_no, dmc_inst, sys_if, attr);
if (!verify_region_attr(region_no, attr))
return 1;
}
}
}
return 0;
}
/*
* `tzc_dmc500_configure_region0` is used to program region 0 in both the
* system interfaces of all the DMC-500 instances. Region 0 covers the whole
* address space that is not mapped to any other region for a system interface,
* and is always enabled; this cannot be changed. This function only changes
* the access permissions.
*/
void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
unsigned int nsaid_permissions)
{
int dmc_inst, sys_if;
/* Assert if DMC-500 is not initialized */
assert(g_driver_data);
/* Configure region_0 in all DMC instances */
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
_tzc_dmc500_configure_region0(
DMC_INST_SI_BASE(dmc_inst, sys_if),
sec_attr, nsaid_permissions);
}
g_conf_regions[0].sec_attr = sec_attr;
g_conf_regions[0].is_enabled = 1;
}
/*
* `tzc_dmc500_configure_region` is used to program a region into all system
* interfaces of all the DMC instances.
* NOTE:
* Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
* for this region (see comment for that function).
*/
void tzc_dmc500_configure_region(int region_no,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int nsaid_permissions)
{
int dmc_inst, sys_if;
assert(g_driver_data);
/* Do range checks on regions. */
assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
/*
* Do address range check based on DMC-TZ configuration. A 43bit address
* is the max and expected case.
*/
assert(((region_top <= (UINT64_MAX >> (64 - 43))) &&
(region_base < region_top)));
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
_tzc_dmc500_configure_region(
DMC_INST_SI_BASE(dmc_inst, sys_if),
TZC_DMC500_REGION_ATTR_F_EN_MASK,
region_no, region_base, region_top,
sec_attr, nsaid_permissions);
}
g_conf_regions[region_no].sec_attr = sec_attr;
g_conf_regions[region_no].is_enabled = 1;
}
/* Sets the action value for all the DMC instances */
void tzc_dmc500_set_action(tzc_action_t action)
{
int dmc_inst;
assert(g_driver_data);
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
/*
* - Currently no handler is provided to trap an error via
* interrupt or exception.
* - The interrupt action has not been tested.
*/
_tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action);
}
}
/*
* A DMC-500 instance must be present at each base address provided by the
* platform. It also expects platform to pass at least one instance of
* DMC-500.
*/
static void validate_plat_driver_data(
const tzc_dmc500_driver_data_t *plat_driver_data)
{
#if DEBUG
int i;
unsigned int dmc_id;
uintptr_t dmc_base;
assert(plat_driver_data);
assert(plat_driver_data->dmc_count > 0 &&
(plat_driver_data->dmc_count <= MAX_DMC_COUNT));
for (i = 0; i < plat_driver_data->dmc_count; i++) {
dmc_base = plat_driver_data->dmc_base[i];
assert(dmc_base);
dmc_id = _tzc_read_peripheral_id(dmc_base);
assert(dmc_id == DMC500_PERIPHERAL_ID);
}
#endif /* DEBUG */
}
/*
* Initializes the base address and count of DMC instances.
*
* Note : Only pointer to plat_driver_data is saved, so it is caller's
* responsibility to keep it valid until the driver is used.
*/
void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data)
{
/* Check valid pointer is passed */
assert(plat_driver_data);
/*
* NOTE: This driver expects the DMC-500 controller is already in
* READY state. Hence, it uses the reconfiguration method for
* programming TrustZone regions
*/
/* Validates the information passed by platform */
validate_plat_driver_data(plat_driver_data);
g_driver_data = plat_driver_data;
}
/*
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
......@@ -28,313 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <stddef.h>
#include <tzc400.h>
/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
typedef struct tzc_instance {
uintptr_t base;
uint8_t addr_width;
uint8_t num_filters;
uint8_t num_regions;
} tzc_instance_t;
tzc_instance_t tzc;
static inline uint32_t tzc_read_build_config(uintptr_t base)
{
return mmio_read_32(base + BUILD_CONFIG_OFF);
}
static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
{
return mmio_read_32(base + GATE_KEEPER_OFF);
}
static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
{
mmio_write_32(base + GATE_KEEPER_OFF, val);
}
static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
{
mmio_write_32(base + ACTION_OFF, action);
}
static inline void tzc_write_region_base_low(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_BASE_LOW_OFF +
REGION_NUM_OFF(region), val);
}
static inline void tzc_write_region_base_high(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_BASE_HIGH_OFF +
REGION_NUM_OFF(region), val);
}
static inline void tzc_write_region_top_low(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_TOP_LOW_OFF +
REGION_NUM_OFF(region), val);
}
static inline void tzc_write_region_top_high(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_TOP_HIGH_OFF +
REGION_NUM_OFF(region), val);
}
static inline void tzc_write_region_attributes(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_ATTRIBUTES_OFF +
REGION_NUM_OFF(region), val);
}
static inline void tzc_write_region_id_access(uintptr_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_ID_ACCESS_OFF +
REGION_NUM_OFF(region), val);
}
static unsigned int tzc_read_peripheral_id(uintptr_t base)
{
unsigned int id;
id = mmio_read_8(base + PID0_OFF);
/* Masks jep106_id_3_0 part in PID1 */
id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
return id;
}
static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
{
uint32_t tmp;
tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK;
return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
}
/* This function is not MP safe. */
static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
{
uint32_t tmp;
/* Upper half is current state. Lower half is requested state. */
tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK;
if (val)
tmp |= (1 << filter);
else
tmp &= ~(1 << filter);
tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
GATE_KEEPER_OR_SHIFT);
/* Wait here until we see the change reflected in the TZC status. */
while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK) != tmp)
;
}
void tzc_init(uintptr_t base)
{
unsigned int tzc_id;
unsigned int tzc_build;
assert(base);
tzc.base = base;
/*
* We expect to see a tzc400. Check peripheral ID.
*/
tzc_id = tzc_read_peripheral_id(tzc.base);
if (tzc_id != TZC400_PERIPHERAL_ID) {
ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
panic();
}
/* Save values we will use later. */
tzc_build = tzc_read_build_config(tzc.base);
tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
BUILD_CONFIG_NF_MASK) + 1;
tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
BUILD_CONFIG_AW_MASK) + 1;
tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
BUILD_CONFIG_NR_MASK) + 1;
}
/*
* `tzc_configure_region0` is used to program region 0 into the TrustZone
* controller. Region 0 covers the whole address space that is not mapped
* to any other region, and is enabled on all filters; this cannot be
* changed. This function only changes the access permissions.
*/
void tzc_configure_region0(tzc_region_attributes_t sec_attr,
uint32_t ns_device_access)
{
assert(tzc.base);
VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
sec_attr, ns_device_access);
assert(sec_attr <= TZC_REGION_S_RDWR);
/* Set secure attributes on region 0 */
tzc_write_region_attributes(tzc.base, 0,
sec_attr << REG_ATTR_SEC_SHIFT);
/*
* Specify which non-secure devices have permission to access
* region 0.
*/
tzc_write_region_id_access(tzc.base, 0, ns_device_access);
}
/*
* `tzc_configure_region` is used to program regions into the TrustZone
* controller. A region can be associated with more than one filter. The
* associated filters are passed in as a bitmap (bit0 = filter0).
* NOTE:
* Region 0 is special; it is preferable to use tzc_configure_region0
* for this region (see comment for that function).
*/
void tzc_configure_region(uint32_t filters,
uint8_t region,
uint64_t region_base,
uint64_t region_top,
tzc_region_attributes_t sec_attr,
uint32_t ns_device_access)
{
assert(tzc.base);
VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
filters, region);
VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
region_base, region_top);
VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
sec_attr, ns_device_access);
/* Do range checks on filters and regions. */
assert(((filters >> tzc.num_filters) == 0) &&
(region < tzc.num_regions));
/*
* Do address range check based on TZC configuration. A 64bit address is
* the max and expected case.
*/
assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
(region_base < region_top)));
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
assert(sec_attr <= TZC_REGION_S_RDWR);
/*
* Inputs look ok, start programming registers.
* All the address registers are 32 bits wide and have a LOW and HIGH
* component used to construct a up to a 64bit address.
*/
tzc_write_region_base_low(tzc.base, region,
(uint32_t)(region_base));
tzc_write_region_base_high(tzc.base, region,
(uint32_t)(region_base >> 32));
tzc_write_region_top_low(tzc.base, region,
(uint32_t)(region_top));
tzc_write_region_top_high(tzc.base, region,
(uint32_t)(region_top >> 32));
/* Assign the region to a filter and set secure attributes */
tzc_write_region_attributes(tzc.base, region,
(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
/*
* Specify which non-secure devices have permission to access this
* region.
*/
tzc_write_region_id_access(tzc.base, region, ns_device_access);
}
void tzc_set_action(tzc_action_t action)
{
assert(tzc.base);
/*
* - Currently no handler is provided to trap an error via interrupt
* or exception.
* - The interrupt action has not been tested.
*/
tzc_write_action(tzc.base, action);
}
void tzc_enable_filters(void)
{
uint32_t state;
uint32_t filter;
assert(tzc.base);
for (filter = 0; filter < tzc.num_filters; filter++) {
state = tzc_get_gate_keeper(tzc.base, filter);
if (state) {
/* The TZC filter is already configured. Changing the
* programmer's view in an active system can cause
* unpredictable behavior therefore panic for now rather
* than try to determine whether this is safe in this
* instance. See:
* http://infocenter.arm.com/help/index.jsp?\
* topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
filter);
panic();
}
tzc_set_gate_keeper(tzc.base, filter, 1);
}
}
void tzc_disable_filters(void)
{
uint32_t filter;
assert(tzc.base);
/*
* We don't do the same state check as above as the Gatekeepers are
* disabled after reset.
*/
for (filter = 0; filter < tzc.num_filters; filter++)
tzc_set_gate_keeper(tzc.base, filter, 0);
}
#if ERROR_DEPRECATED
#error "Using deprecated TZC-400 source file"
#else
#include "../tzc/tzc400.c"
#endif /* ERROR_DEPRECATED */
/*
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
......@@ -31,178 +31,179 @@
#ifndef __TZC400_H__
#define __TZC400_H__
#include <tzc_common.h>
#define BUILD_CONFIG_OFF 0x000
#define ACTION_OFF 0x004
#define GATE_KEEPER_OFF 0x008
#define SPECULATION_CTRL_OFF 0x00c
#define INT_STATUS 0x010
#define INT_CLEAR 0x014
#define FAIL_ADDRESS_LOW_OFF 0x020
#define FAIL_ADDRESS_HIGH_OFF 0x024
#define FAIL_CONTROL_OFF 0x028
#define FAIL_ID 0x02c
#define REGION_BASE_LOW_OFF 0x100
#define REGION_BASE_HIGH_OFF 0x104
#define REGION_TOP_LOW_OFF 0x108
#define REGION_TOP_HIGH_OFF 0x10c
#define REGION_ATTRIBUTES_OFF 0x110
#define REGION_ID_ACCESS_OFF 0x114
#define REGION_NUM_OFF(region) (0x20 * region)
/* ID Registers */
#define PID0_OFF 0xfe0
#define PID1_OFF 0xfe4
#define PID2_OFF 0xfe8
#define PID3_OFF 0xfec
#define PID4_OFF 0xfd0
#define PID5_OFF 0xfd4
#define PID6_OFF 0xfd8
#define PID7_OFF 0xfdc
#define CID0_OFF 0xff0
#define CID1_OFF 0xff4
#define CID2_OFF 0xff8
#define CID3_OFF 0xffc
#define BUILD_CONFIG_NF_SHIFT 24
#define BUILD_CONFIG_NF_MASK 0x3
#define BUILD_CONFIG_AW_SHIFT 8
#define BUILD_CONFIG_AW_MASK 0x3f
#define BUILD_CONFIG_NR_SHIFT 0
#define BUILD_CONFIG_NR_MASK 0x1f
/* Not describing the case where regions 1 to 8 overlap */
#define ACTION_RV_SHIFT 0
#define ACTION_RV_MASK 0x3
#define ACTION_RV_LOWOK 0x0
#define ACTION_RV_LOWERR 0x1
#define ACTION_RV_HIGHOK 0x2
#define ACTION_RV_HIGHERR 0x3
#define BUILD_CONFIG_OFF 0x000
#define GATE_KEEPER_OFF 0x008
#define SPECULATION_CTRL_OFF 0x00c
#define INT_STATUS 0x010
#define INT_CLEAR 0x014
#define FAIL_ADDRESS_LOW_OFF 0x020
#define FAIL_ADDRESS_HIGH_OFF 0x024
#define FAIL_CONTROL_OFF 0x028
#define FAIL_ID 0x02c
/* ID registers not common across different varieties of TZC */
#define PID5 0xFD4
#define PID6 0xFD8
#define PID7 0xFDC
#define BUILD_CONFIG_NF_SHIFT 24
#define BUILD_CONFIG_NF_MASK 0x3
#define BUILD_CONFIG_AW_SHIFT 8
#define BUILD_CONFIG_AW_MASK 0x3f
#define BUILD_CONFIG_NR_SHIFT 0
#define BUILD_CONFIG_NR_MASK 0x1f
/*
* Number of gate keepers is implementation defined. But we know the max for
* this device is 4. Get implementation details from BUILD_CONFIG.
*/
#define GATE_KEEPER_OS_SHIFT 16
#define GATE_KEEPER_OS_MASK 0xf
#define GATE_KEEPER_OR_SHIFT 0
#define GATE_KEEPER_OR_MASK 0xf
#define GATE_KEEPER_FILTER_MASK 0x1
#define GATE_KEEPER_OS_SHIFT 16
#define GATE_KEEPER_OS_MASK 0xf
#define GATE_KEEPER_OR_SHIFT 0
#define GATE_KEEPER_OR_MASK 0xf
#define GATE_KEEPER_FILTER_MASK 0x1
/* Speculation is enabled by default. */
#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
/* Max number of filters allowed is 4. */
#define INT_STATUS_OVERLAP_SHIFT 16
#define INT_STATUS_OVERLAP_MASK 0xf
#define INT_STATUS_OVERRUN_SHIFT 8
#define INT_STATUS_OVERRUN_MASK 0xf
#define INT_STATUS_STATUS_SHIFT 0
#define INT_STATUS_STATUS_MASK 0xf
#define INT_CLEAR_CLEAR_SHIFT 0
#define INT_CLEAR_CLEAR_MASK 0xf
#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
#define FAIL_CONTROL_DIR_READ 0x0
#define FAIL_CONTROL_DIR_WRITE 0x1
#define FAIL_CONTROL_NS_SHIFT (1 << 21)
#define FAIL_CONTROL_NS_SECURE 0x0
#define FAIL_CONTROL_NS_NONSECURE 0x1
#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
#define FAIL_CONTROL_PRIV_PRIV 0x0
#define FAIL_CONTROL_PRIV_UNPRIV 0x1
#define INT_STATUS_OVERLAP_SHIFT 16
#define INT_STATUS_OVERLAP_MASK 0xf
#define INT_STATUS_OVERRUN_SHIFT 8
#define INT_STATUS_OVERRUN_MASK 0xf
#define INT_STATUS_STATUS_SHIFT 0
#define INT_STATUS_STATUS_MASK 0xf
#define INT_CLEAR_CLEAR_SHIFT 0
#define INT_CLEAR_CLEAR_MASK 0xf
#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
#define FAIL_CONTROL_DIR_READ 0x0
#define FAIL_CONTROL_DIR_WRITE 0x1
#define FAIL_CONTROL_NS_SHIFT (1 << 21)
#define FAIL_CONTROL_NS_SECURE 0x0
#define FAIL_CONTROL_NS_NONSECURE 0x1
#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
#define FAIL_CONTROL_PRIV_PRIV 0x0
#define FAIL_CONTROL_PRIV_UNPRIV 0x1
/*
* FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
* Platform should provide the value on initialisation.
*/
#define FAIL_ID_VNET_SHIFT 24
#define FAIL_ID_VNET_MASK 0xf
#define FAIL_ID_ID_SHIFT 0
/* Used along with 'tzc_region_attributes_t' below */
#define REG_ATTR_SEC_SHIFT 30
#define REG_ATTR_F_EN_SHIFT 0
#define REG_ATTR_F_EN_MASK 0xf
#define REG_ATTR_FILTER_BIT(x) ((1 << x) << REG_ATTR_F_EN_SHIFT)
#define REG_ATTR_FILTER_BIT_ALL (REG_ATTR_F_EN_MASK << \
REG_ATTR_F_EN_SHIFT)
#define FAIL_ID_VNET_SHIFT 24
#define FAIL_ID_VNET_MASK 0xf
#define FAIL_ID_ID_SHIFT 0
#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT 16
#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT 0
#define REGION_ID_ACCESS_NSAID_ID_MASK 0xf
#define TZC_400_PERIPHERAL_ID 0x460
/* Filter enable bits in a TZC */
#define TZC_400_REGION_ATTR_F_EN_MASK 0xf
#define TZC_400_REGION_ATTR_FILTER_BIT(x) ((1 << x) \
<< TZC_REGION_ATTR_F_EN_SHIFT)
#define TZC_400_REGION_ATTR_FILTER_BIT_ALL \
(TZC_400_REGION_ATTR_F_EN_MASK << \
TZC_REGION_ATTR_F_EN_SHIFT)
/* Macros for setting Region ID access permissions based on NSAID */
#define TZC_REGION_ACCESS_RD(id) \
((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
#define TZC_REGION_ACCESS_WR(id) \
((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
#define TZC_REGION_ACCESS_RDWR(id) \
(TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
/* Consist of part_number_1 and part_number_0 */
#define TZC400_PERIPHERAL_ID 0x0460
/*
* Define some macros for backward compatibility with existing tzc400 clients.
*/
#if !ERROR_DEPRECATED
#define REG_ATTR_FILTER_BIT(x) ((1 << x) \
<< TZC_REGION_ATTR_F_EN_SHIFT)
#define REG_ATTR_FILTER_BIT_ALL (TZC_400_REGION_ATTR_F_EN_MASK << \
TZC_REGION_ATTR_F_EN_SHIFT)
#endif /* __ERROR_DEPRECATED__ */
/*
* All TZC region configuration registers are placed one after another. It
* depicts size of block of registers for programming each region.
*/
#define TZC_400_REGION_SIZE 0x20
#define TZC_400_ACTION_OFF 0x4
#ifndef __ASSEMBLY__
#include <cdefs.h>
#include <stdint.h>
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
void tzc400_init(uintptr_t base);
void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
unsigned int ns_device_access);
void tzc400_configure_region(unsigned int filters,
int region,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int ns_device_access);
void tzc400_set_action(tzc_action_t action);
void tzc400_enable_filters(void);
void tzc400_disable_filters(void);
/*
* What type of action is expected when an access violation occurs.
* The memory requested is zeroed. But we can also raise and event to
* let the system know it happened.
* We can raise an interrupt(INT) and/or cause an exception(ERR).
* TZC_ACTION_NONE - No interrupt, no Exception
* TZC_ACTION_ERR - No interrupt, raise exception -> sync external
* data abort
* TZC_ACTION_INT - Raise interrupt, no exception
* TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
* external data abort
* Deprecated APIs
*/
typedef enum {
TZC_ACTION_NONE = 0,
TZC_ACTION_ERR = 1,
TZC_ACTION_INT = 2,
TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
} tzc_action_t;
/*
* Controls secure access to a region. If not enabled secure access is not
* allowed to region.
*/
typedef enum {
TZC_REGION_S_NONE = 0,
TZC_REGION_S_RD = 1,
TZC_REGION_S_WR = 2,
TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
} tzc_region_attributes_t;
void tzc_init(uintptr_t base);
void tzc_configure_region0(tzc_region_attributes_t sec_attr,
uint32_t ns_device_access);
void tzc_configure_region(uint32_t filters,
uint8_t region,
uint64_t region_base,
uint64_t region_top,
static inline void tzc_init(uintptr_t base) __deprecated;
static inline void tzc_configure_region0(
tzc_region_attributes_t sec_attr,
unsigned int ns_device_access) __deprecated;
static inline void tzc_configure_region(
unsigned int filters,
int region,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int ns_device_access) __deprecated;
static inline void tzc_set_action(tzc_action_t action) __deprecated;
static inline void tzc_enable_filters(void) __deprecated;
static inline void tzc_disable_filters(void) __deprecated;
static inline void tzc_init(uintptr_t base)
{
tzc400_init(base);
}
static inline void tzc_configure_region0(
tzc_region_attributes_t sec_attr,
uint32_t ns_device_access);
void tzc_enable_filters(void);
void tzc_disable_filters(void);
void tzc_set_action(tzc_action_t action);
unsigned int ns_device_access)
{
tzc400_configure_region0(sec_attr, ns_device_access);
}
static inline void tzc_configure_region(
unsigned int filters,
int region,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int ns_device_access)
{
tzc400_configure_region(filters, region, region_base,
region_top, sec_attr, ns_device_access);
}
static inline void tzc_set_action(tzc_action_t action)
{
tzc400_set_action(action);
}
static inline void tzc_enable_filters(void)
{
tzc400_enable_filters();
}
static inline void tzc_disable_filters(void)
{
tzc400_disable_filters();
}
#endif /* __ASSEMBLY__ */
......
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __TZC_COMMON_H__
#define __TZC_COMMON_H__
/*
* Offset of core registers from the start of the base of configuration
* registers for each region.
*/
/* ID Registers */
#define PID0_OFF 0xfe0
#define PID1_OFF 0xfe4
#define PID2_OFF 0xfe8
#define PID3_OFF 0xfec
#define PID4_OFF 0xfd0
#define CID0_OFF 0xff0
#define CID1_OFF 0xff4
#define CID2_OFF 0xff8
#define CID3_OFF 0xffc
/* Bit positions of TZC_ACTION registers */
#define TZC_ACTION_RV_SHIFT 0
#define TZC_ACTION_RV_MASK 0x3
#define TZC_ACTION_RV_LOWOK 0x0
#define TZC_ACTION_RV_LOWERR 0x1
#define TZC_ACTION_RV_HIGHOK 0x2
#define TZC_ACTION_RV_HIGHERR 0x3
/* Used along with 'tzc_region_attributes_t' below */
#define TZC_REGION_ATTR_S_RD_SHIFT 30
#define TZC_REGION_ATTR_S_WR_SHIFT 31
#define TZC_REGION_ATTR_F_EN_SHIFT 0
#define TZC_REGION_ATTR_SEC_SHIFT 30
#define TZC_REGION_ATTR_S_RD_MASK 0x1
#define TZC_REGION_ATTR_S_WR_MASK 0x1
#define TZC_REGION_ATTR_SEC_MASK 0x3
#define TZC_REGION_ACCESS_WR_EN_SHIFT 16
#define TZC_REGION_ACCESS_RD_EN_SHIFT 0
#define TZC_REGION_ACCESS_ID_MASK 0xf
/* Macros for allowing Non-Secure access to a region based on NSAID */
#define TZC_REGION_ACCESS_RD(nsaid) \
((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
TZC_REGION_ACCESS_RD_EN_SHIFT)
#define TZC_REGION_ACCESS_WR(nsaid) \
((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
TZC_REGION_ACCESS_WR_EN_SHIFT)
#define TZC_REGION_ACCESS_RDWR(nsaid) \
(TZC_REGION_ACCESS_RD(nsaid) | \
TZC_REGION_ACCESS_WR(nsaid))
#ifndef __ASSEMBLY__
/* Returns offset of registers to program for a given region no */
#define TZC_REGION_OFFSET(region_size, region_no) \
((region_size) * (region_no))
/*
* What type of action is expected when an access violation occurs.
* The memory requested is returned as zero. But we can also raise an event to
* let the system know it happened.
* We can raise an interrupt(INT) and/or cause an exception(ERR).
* TZC_ACTION_NONE - No interrupt, no Exception
* TZC_ACTION_ERR - No interrupt, raise exception -> sync external
* data abort
* TZC_ACTION_INT - Raise interrupt, no exception
* TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
* external data abort
*/
typedef enum {
TZC_ACTION_NONE = 0,
TZC_ACTION_ERR = 1,
TZC_ACTION_INT = 2,
TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
} tzc_action_t;
/*
* Controls secure access to a region. If not enabled secure access is not
* allowed to region.
*/
typedef enum {
TZC_REGION_S_NONE = 0,
TZC_REGION_S_RD = 1,
TZC_REGION_S_WR = 2,
TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
} tzc_region_attributes_t;
#endif /* __ASSEMBLY__ */
#endif /* __TZC_COMMON_H__ */
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __TZC_DMC500_H__
#define __TZC_DMC500_H__
#include <tzc_common.h>
#define SI_STATUS_OFFSET 0x000
#define SI_STATE_CTRL_OFFSET 0x030
#define SI_FLUSH_CTRL_OFFSET 0x034
#define SI_INT_CONTROL_OFFSET 0x048
#define SI_INT_STATUS_OFFSET 0x004
#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET 0x008
#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET 0x00c
#define SI_FAIL_CONTROL_OFFSET 0x010
#define SI_FAIL_ID_OFFSET 0x014
#define SI_INT_CLR_OFFSET 0x04c
/*
* DMC-500 has 2 system interfaces each having a similar set of regs
* to configure each interface.
*/
#define SI0_BASE 0x0000
#define SI1_BASE 0x0200
/* Bit positions of SIx_SI_STATUS */
#define SI_EMPTY_SHIFT 0x01
#define SI_STALL_ACK_SHIFT 0x00
#define SI_EMPTY_MASK 0x01
#define SI_STALL_ACK_MASK 0x01
/* Bit positions of SIx_SI_INT_STATUS */
#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT 18
#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT 16
#define PMU_REQ_INT_STATUS_SHIFT 2
#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT 1
#define FAILED_ACCESS_INT_STATUS_SHIFT 0
#define PMU_REQ_INT_OVERFLOW_STATUS_MASK 0x1
#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK 0x1
#define PMU_REQ_INT_STATUS_MASK 0x1
#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK 0x1
#define FAILED_ACCESS_INT_STATUS_MASK 0x1
/* Bit positions of SIx_TZ_FAIL_CONTROL */
#define DIRECTION_SHIFT 24
#define NON_SECURE_SHIFT 21
#define PRIVILEGED_SHIFT 20
#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT 3
#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT 2
#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT 0x1
#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT 0
#define DIRECTION_MASK 0x1
#define NON_SECURE_MASK 0x1
#define PRIVILEGED_MASK 0x1
#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK 0x1
#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK 0x1
#define FAILED_ACCESS_INT_TZ_FAIL_MASK 1
#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK 0x1
/* Bit positions of SIx_FAIL_STATUS */
#define FAIL_ID_VNET_SHIFT 24
#define FAIL_ID_ID_SHIFT 0
#define FAIL_ID_VNET_MASK 0xf
#define FAIL_ID_ID_MASK 0xffffff
/* Bit positions of SIx_SI_STATE_CONTRL */
#define SI_STALL_REQ_GO 0x0
#define SI_STALL_REQ_STALL 0x1
/* Bit positions of SIx_SI_FLUSH_CONTROL */
#define SI_FLUSH_REQ_INACTIVE 0x0
#define SI_FLUSH_REQ_ACTIVE 0x1
#define SI_FLUSH_REQ_MASK 0x1
/* Bit positions of SIx_SI_INT_CONTROL */
#define PMU_REQ_INT_EN_SHIFT 2
#define OVERLAP_DETECT_INT_EN_SHIFT 1
#define FAILED_ACCESS_INT_EN_SHIFT 0
#define PMU_REQ_INT_EN_MASK 0x1
#define OVERLAP_DETECT_INT_EN_MASK 0x1
#define FAILED_ACCESS_INT_EN_MASK 0x1
#define PMU_REQ_INT_EN 0x1
#define OVERLAP_DETECT_INT_EN 0x1
#define FAILED_ACCESS_INT_EN 0x1
/* Bit positions of SIx_SI_INT_CLR */
#define PMU_REQ_OFLOW_CLR_SHIFT 18
#define FAILED_ACCESS_OFLOW_CLR_SHIFT 16
#define PMU_REQ_INT_CLR_SHIFT 2
#define FAILED_ACCESS_INT_CLR_SHIFT 0
#define PMU_REQ_OFLOW_CLR_MASK 0x1
#define FAILED_ACCESS_OFLOW_CLR_MASK 0x1
#define PMU_REQ_INT_CLR_MASK 0x1
#define FAILED_ACCESS_INT_CLR_MASK 0x1
#define PMU_REQ_OFLOW_CLR 0x1
#define FAILED_ACCESS_OFLOW_CLR 0x1
#define PMU_REQ_INT_CLR 0x1
#define FAILED_ACCESS_INT_CLR 0x1
/* Macro to get the correct base register for a system interface */
#define IFACE_OFFSET(sys_if) ((sys_if) ? SI1_BASE : SI0_BASE)
#define MAX_SYS_IF_COUNT 2
#define MAX_REGION_VAL 8
/* DMC-500 supports striping across a max of 4 DMC instances */
#define MAX_DMC_COUNT 4
/* Consist of part_number_1 and part_number_0 */
#define DMC500_PERIPHERAL_ID 0x0450
/* Filter enable bits in a TZC */
#define TZC_DMC500_REGION_ATTR_F_EN_MASK 0x1
/* Length of registers for configuring each region */
#define TZC_DMC500_REGION_SIZE 0x018
#ifndef __ASSEMBLY__
#include <stdint.h>
/*
* Contains the base addresses of all the DMC instances.
*/
typedef struct tzc_dmc500_driver_data {
uintptr_t dmc_base[MAX_DMC_COUNT];
int dmc_count;
} tzc_dmc500_driver_data_t;
void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
unsigned int nsaid_permissions);
void tzc_dmc500_configure_region(int region_no,
uintptr_t region_base,
uintptr_t region_top,
tzc_region_attributes_t sec_attr,
unsigned int nsaid_permissions);
void tzc_dmc500_set_action(tzc_action_t action);
void tzc_dmc500_config_complete(void);
int tzc_dmc500_verify_complete(void);
#endif /* __ASSEMBLY__ */
#endif /* __TZC_DMC500_H__ */
......@@ -130,7 +130,9 @@ void arm_configure_mmu_el3(unsigned long total_base,
void arm_io_setup(void);
/* Security utility functions */
void arm_tzc_setup(void);
void arm_tzc400_setup(void);
struct tzc_dmc500_driver_data;
void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data);
/* Systimer utility function */
void arm_configure_sys_timer(void);
......
......@@ -143,7 +143,7 @@
#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000
/* TZC related constants */
#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT_ALL
#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL
/* Trusted mailbox base address common to all CSS */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
......
......@@ -46,5 +46,5 @@ void plat_arm_security_setup(void)
*/
if (get_arm_config()->flags & ARM_CONFIG_HAS_TZC)
arm_tzc_setup();
arm_tzc400_setup();
}
......@@ -113,7 +113,7 @@
* would normally use the default ID so allow that too.
*/
#define PLAT_ARM_TZC_BASE 0x2a4a0000
#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT(0)
#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \
......
......@@ -65,7 +65,7 @@ endif
FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
FVP_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/fvp/fvp_security.c \
plat/arm/common/arm_tzc400.c
......
......@@ -65,7 +65,7 @@ static void css_init_nic400(void)
void plat_arm_security_setup(void)
{
/* Initialize the TrustZone Controller */
arm_tzc_setup();
arm_tzc400_setup();
/* Do ARM CSS internal NIC setup */
css_init_nic400();
/* Do ARM CSS SoC security setup */
......
......@@ -37,7 +37,7 @@ JUNO_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
JUNO_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/juno/juno_security.c \
plat/arm/common/arm_tzc400.c
......
......@@ -48,53 +48,53 @@
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
void arm_tzc_setup(void)
void arm_tzc400_setup(void)
{
INFO("Configuring TrustZone Controller\n");
tzc_init(PLAT_ARM_TZC_BASE);
tzc400_init(PLAT_ARM_TZC_BASE);
/* Disable filters. */
tzc_disable_filters();
tzc400_disable_filters();
#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
tzc_configure_region0(TZC_REGION_S_NONE, 0);
tzc400_configure_region0(TZC_REGION_S_NONE, 0);
/* Region 1 set to cover Secure part of DRAM */
tzc_configure_region(PLAT_ARM_TZC_FILTERS, 1,
tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
TZC_REGION_S_RDWR,
0);
/* Region 2 set to cover Non-Secure access to 1st DRAM address range.
* Apply the same configuration to given filters in the TZC. */
tzc_configure_region(PLAT_ARM_TZC_FILTERS, 2,
tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 2,
ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
tzc_configure_region(PLAT_ARM_TZC_FILTERS, 3,
tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 3,
ARM_DRAM2_BASE, ARM_DRAM2_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
/* Allow secure access only to DRAM for EL3 payloads. */
tzc_configure_region0(TZC_REGION_S_RDWR, 0);
tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
#endif /* EL3_PAYLOAD_BASE */
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
tzc_set_action(TZC_ACTION_ERR);
tzc400_set_action(TZC_ACTION_ERR);
/* Enable filters. */
tzc_enable_filters();
tzc400_enable_filters();
}
void plat_arm_security_setup(void)
{
arm_tzc_setup();
arm_tzc400_setup();
}
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arm_def.h>
#include <assert.h>
#include <debug.h>
#include <platform_def.h>
#include <tzc_dmc500.h>
/*******************************************************************************
* Initialize the DMC500-TrustZone Controller for ARM standard platforms.
* Configure both the interfaces on Region 0 with no access, Region 1 with
* secure access only, and the remaining DRAM regions access from the
* given Non-Secure masters.
*
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
{
assert(plat_driver_data);
INFO("Configuring DMC-500 TZ Settings\n");
tzc_dmc500_driver_init(plat_driver_data);
#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
/* Region 1 set to cover Secure part of DRAM */
tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
ARM_AP_TZC_DRAM1_END,
TZC_REGION_S_RDWR,
0);
/* Region 2 set to cover Non-Secure access to 1st DRAM address range.*/
tzc_dmc500_configure_region(2,
ARM_NS_DRAM1_BASE,
ARM_NS_DRAM1_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
tzc_dmc500_configure_region(3,
ARM_DRAM2_BASE,
ARM_DRAM2_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
/* Allow secure access only to DRAM for EL3 payloads */
tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
#endif
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR);
/*
* Flush the configuration settings to have an affect. Validate
* flush by checking FILTER_EN is set on region 1 attributes
* register.
*/
tzc_dmc500_config_complete();
/*
* Wait for the flush to complete.
* TODO: Have a timeout for this loop
*/
while (tzc_dmc500_verify_complete())
;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment