Merge changes from topic "tzc400_stm32mp" into integration
* changes:
stm32mp1: add TZC400 interrupt management
stm32mp1: use TZC400 macro to describe filters
tzc400: add support for interrupts
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index 9798ed4..9fc1578 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -10,6 +10,7 @@
#include <common/debug.h>
#include <drivers/arm/tzc400.h>
#include <lib/mmio.h>
+#include <lib/utils_def.h>
#include "tzc_common_private.h"
@@ -70,6 +71,77 @@
DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+static void _tzc400_clear_it(uintptr_t base, uint32_t filter)
+{
+ mmio_write_32(base + INT_CLEAR, BIT_32(filter));
+}
+
+static uint32_t _tzc400_get_int_by_filter(uintptr_t base, uint32_t filter)
+{
+ return mmio_read_32(base + INT_STATUS) & BIT_32(filter);
+}
+
+#if DEBUG
+static unsigned long _tzc400_get_fail_address(uintptr_t base, uint32_t filter)
+{
+ unsigned long fail_address;
+
+ fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF +
+ (filter * FILTER_OFFSET));
+#ifdef __aarch64__
+ fail_address += (unsigned long)mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF +
+ (filter * FILTER_OFFSET)) << 32;
+#endif
+
+ return fail_address;
+}
+
+static uint32_t _tzc400_get_fail_id(uintptr_t base, uint32_t filter)
+{
+ return mmio_read_32(base + FAIL_ID + (filter * FILTER_OFFSET));
+}
+
+static uint32_t _tzc400_get_fail_control(uintptr_t base, uint32_t filter)
+{
+ return mmio_read_32(base + FAIL_CONTROL_OFF + (filter * FILTER_OFFSET));
+}
+
+static void _tzc400_dump_fail_filter(uintptr_t base, uint32_t filter)
+{
+ uint32_t control_fail;
+ uint32_t fail_id;
+ unsigned long address_fail;
+
+ address_fail = _tzc400_get_fail_address(base, filter);
+ ERROR("Illegal access to 0x%lx:\n", address_fail);
+
+ fail_id = _tzc400_get_fail_id(base, filter);
+ ERROR("\tFAIL_ID = 0x%x\n", fail_id);
+
+ control_fail = _tzc400_get_fail_control(base, filter);
+ if (((control_fail & BIT_32(FAIL_CONTROL_NS_SHIFT)) >> FAIL_CONTROL_NS_SHIFT) ==
+ FAIL_CONTROL_NS_NONSECURE) {
+ ERROR("\tNon-Secure\n");
+ } else {
+ ERROR("\tSecure\n");
+ }
+
+ if (((control_fail & BIT_32(FAIL_CONTROL_PRIV_SHIFT)) >> FAIL_CONTROL_PRIV_SHIFT) ==
+ FAIL_CONTROL_PRIV_PRIV) {
+ ERROR("\tPrivilege\n");
+ } else {
+ ERROR("\tUnprivilege\n");
+ }
+
+ if (((control_fail & BIT_32(FAIL_CONTROL_DIR_SHIFT)) >> FAIL_CONTROL_DIR_SHIFT) ==
+ FAIL_CONTROL_DIR_WRITE) {
+ ERROR("\tWrite\n");
+ } else {
+ ERROR("\tRead\n");
+ }
+}
+#endif /* DEBUG */
+
static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
unsigned int filter)
{
@@ -108,11 +180,6 @@
assert(tzc400.base != 0U);
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);
}
@@ -245,3 +312,31 @@
for (filter = 0; filter < tzc400.num_filters; filter++)
_tzc400_set_gate_keeper(tzc400.base, filter, 0);
}
+
+int tzc400_it_handler(void)
+{
+ uint32_t filter;
+ uint32_t filter_it_pending = tzc400.num_filters;
+
+ assert(tzc400.base != 0U);
+
+ for (filter = 0U; filter < tzc400.num_filters; filter++) {
+ if (_tzc400_get_int_by_filter(tzc400.base, filter) != 0U) {
+ filter_it_pending = filter;
+ break;
+ }
+ }
+
+ if (filter_it_pending == tzc400.num_filters) {
+ ERROR("TZC-400: No interrupt pending!\n");
+ return -1;
+ }
+
+#if DEBUG
+ _tzc400_dump_fail_filter(tzc400.base, filter_it_pending);
+#endif
+
+ _tzc400_clear_it(tzc400.base, filter_it_pending);
+
+ return 0;
+}
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index aacd5df..5f8a48f 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -90,6 +90,8 @@
#define TZC_400_REGION_SIZE U(0x20)
#define TZC_400_ACTION_OFF U(0x4)
+#define FILTER_OFFSET U(0x10)
+
#ifndef __ASSEMBLER__
#include <cdefs.h>
@@ -110,6 +112,7 @@
void tzc400_set_action(unsigned int action);
void tzc400_enable_filters(void);
void tzc400_disable_filters(void);
+int tzc400_it_handler(void);
static inline void tzc_init(uintptr_t base)
{
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index b639fcb..9b8c3ea 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -45,7 +45,7 @@
{
switch (id & INT_ID_MASK) {
case STM32MP1_IRQ_TZC400:
- ERROR("STM32MP1_IRQ_TZC400 generated\n");
+ (void)tzc400_it_handler();
panic();
break;
case STM32MP1_IRQ_AXIERRIRQ:
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index ee04a23..f4aeab5 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -381,7 +381,8 @@
#define STM32MP1_TZC_ETH_ID U(10)
#define STM32MP1_TZC_DAP_ID U(15)
-#define STM32MP1_FILTER_BIT_ALL U(3)
+#define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \
+ TZC_400_REGION_ATTR_FILTER_BIT(1))
/*******************************************************************************
* STM32MP1 SDMMC
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 3a29ba9..195b3a5 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -75,8 +75,7 @@
TZC_REGION_NSEC_ALL_ACCESS_RDWR);
#endif
- /* Raise an exception if a NS device tries to access secure memory */
- tzc400_set_action(TZC_ACTION_ERR);
+ tzc400_set_action(TZC_ACTION_INT);
tzc400_enable_filters();
}