fix(zynqmp): handling of type el3 interrrupts
The array type_el3_interrupt_table is defined for MAX_INTR_EL3(128)
elements and only two interrupts - ARM_IRQ_SEC_SGI_7(15), IRQ_TTC3_1(77)
are being handled. Current implementation is consuming 1024 bytes which
can be optimized for the number of interrupts to be handled.
The current array is replaced with the array of struct
zynmp_intr_info_type_el3_t (id and handler as member) and with
maximum number of interrupts to be handled as the size of array
(MAX_INTR_EL3 = 2). User is expected to adjust MAX_INTR_EL3 based on
how many interrupts are handled in TF-A.
With the updated implementation, a reduction of 960 bytes is observed.
Versal and Versal NET are using similar implementation introduced by
commit e497421d7f1e ("feat(versal): add infrastructure to handle
multiple interrupts") and commit 0654ab7f7544 ("feat(versal-net): add
support for platform management").
Signed-off-by: Prasad Kummari <prasad.kummari@amd.com>
Change-Id: I07aa388d38ac3ff3c0d25decbe0719087b27ee18
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index c5dbf41..2197b96 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -132,21 +132,29 @@
}
#if ZYNQMP_WDT_RESTART
-static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3];
+static zynmp_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3];
int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
{
+ static uint32_t index;
+ uint32_t i;
+
/* Validate 'handler' and 'id' parameters */
- if (!handler || id >= MAX_INTR_EL3) {
+ if (!handler || index >= MAX_INTR_EL3) {
return -EINVAL;
}
/* Check if a handler has already been registered */
- if (type_el3_interrupt_table[id]) {
- return -EALREADY;
+ for (i = 0; i < index; i++) {
+ if (id == type_el3_interrupt_table[i].id) {
+ return -EALREADY;
+ }
}
- type_el3_interrupt_table[id] = handler;
+ type_el3_interrupt_table[index].id = id;
+ type_el3_interrupt_table[index].handler = handler;
+
+ index++;
return 0;
}
@@ -155,12 +163,19 @@
void *handle, void *cookie)
{
uint32_t intr_id;
- interrupt_type_handler_t handler;
+ uint32_t i;
+ interrupt_type_handler_t handler = NULL;
intr_id = plat_ic_get_pending_interrupt_id();
- handler = type_el3_interrupt_table[intr_id];
+
+ for (i = 0; i < MAX_INTR_EL3; i++) {
+ if (intr_id == type_el3_interrupt_table[i].id) {
+ handler = type_el3_interrupt_table[i].handler;
+ }
+ }
+
if (handler != NULL) {
- handler(intr_id, flags, handle, cookie);
+ return handler(intr_id, flags, handle, cookie);
}
return 0;
diff --git a/plat/xilinx/zynqmp/include/plat_private.h b/plat/xilinx/zynqmp/include/plat_private.h
index 9ea052d..3526b94 100644
--- a/plat/xilinx/zynqmp/include/plat_private.h
+++ b/plat/xilinx/zynqmp/include/plat_private.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,8 +22,12 @@
uint32_t zynqmp_get_uart_clk(void);
uint32_t zynqmp_get_bootmode(void);
-
#if ZYNQMP_WDT_RESTART
+typedef struct zynqmp_intr_info_type_el3 {
+ uint32_t id;
+ interrupt_type_handler_t handler;
+} zynmp_intr_info_type_el3_t;
+
/*
* Register handler to specific GIC entrance
* for INTR_TYPE_EL3 type of interrupt
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 1de82b8..c9f555a 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -135,7 +135,8 @@
#define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_7 15
-#define MAX_INTR_EL3 128
+/* number of interrupt handlers. increase as required */
+#define MAX_INTR_EL3 2
/*******************************************************************************
* UART related constants