aboutsummaryrefslogtreecommitdiff
path: root/drivers/arm/gic/v3/gicv3_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/arm/gic/v3/gicv3_main.c')
-rw-r--r--drivers/arm/gic/v3/gicv3_main.c286
1 files changed, 170 insertions, 116 deletions
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 5a49b4f5ed..8ea164ce86 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,8 +11,10 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <common/interrupt_props.h>
+#include <drivers/arm/gic600_multichip.h>
#include <drivers/arm/gicv3.h>
#include <lib/spinlock.h>
+#include <plat/common/platform.h>
#include "gicv3_private.h"
@@ -31,8 +34,8 @@ static spinlock_t gic_lock;
#pragma weak gicv3_rdistif_off
#pragma weak gicv3_rdistif_on
-/* Check interrupt ID for SGI/(E)PPI and (E)SPIs */
-static bool is_sgi_ppi(unsigned int id);
+/* Check for valid SGI/PPI or SPI interrupt ID */
+static bool is_valid_interrupt(unsigned int id);
/*
* Helper macros to save and restore GICR and GICD registers
@@ -123,13 +126,7 @@ void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
gic_version &= PIDR2_ARCH_REV_MASK;
/* Check GIC version */
-#if GIC_ENABLE_V4_EXTN
- assert(gic_version == ARCH_REV_GICV4);
-
- /* GICv4 supports Direct Virtual LPI injection */
- assert((gicd_read_typer(plat_driver_data->gicd_base)
- & TYPER_DVIS) != 0);
-#else
+#if !GIC_ENABLE_V4_EXTN
assert(gic_version == ARCH_REV_GICV3);
#endif
/*
@@ -175,6 +172,8 @@ void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
flush_dcache_range((uintptr_t)gicv3_driver_data,
sizeof(*gicv3_driver_data));
#endif
+ gicv3_check_erratas_applies(plat_driver_data->gicd_base);
+
INFO("GICv%u with%s legacy support detected.\n", gic_version,
(gicv2_compat == 0U) ? "" : "out");
INFO("ARM GICv%u driver initialized in EL3\n", gic_version);
@@ -331,7 +330,11 @@ void gicv3_cpuif_enable(unsigned int proc_num)
/* Enable Group1 Secure interrupts */
write_icc_igrpen1_el3(read_icc_igrpen1_el3() |
IGRPEN1_EL3_ENABLE_G1S_BIT);
+ /* and restore the original */
+ write_scr_el3(scr_el3);
isb();
+ /* Add DSB to ensure visibility of System register writes */
+ dsb();
}
/*******************************************************************************
@@ -363,10 +366,20 @@ void gicv3_cpuif_disable(unsigned int proc_num)
/* Synchronise accesses to group enable registers */
isb();
+ /* Add DSB to ensure visibility of System register writes */
+ dsb();
- /* Mark the connected core as asleep */
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
- assert(gicr_base != 0U);
+ assert(gicr_base != 0UL);
+
+ /*
+ * dsb() already issued previously after clearing the CPU group
+ * enabled, apply below workaround to toggle the "DPG*"
+ * bits of GICR_CTLR register for unblocking event.
+ */
+ gicv3_apply_errata_wa_2384374(gicr_base);
+
+ /* Mark the connected core as asleep */
gicv3_rdistif_mark_core_asleep(gicr_base);
}
@@ -408,19 +421,19 @@ unsigned int gicv3_get_pending_interrupt_type(void)
}
/*******************************************************************************
- * This function returns the type of the interrupt id depending upon the group
- * this interrupt has been configured under by the interrupt controller i.e.
- * group0 or group1 Secure / Non Secure. The return value can be one of the
- * following :
+ * This function returns the group that has been configured under by the
+ * interrupt controller for the given interrupt id i.e. either group0 or group1
+ * Secure / Non Secure. The return value can be one of the following :
* INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt
* INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt
* INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure
* interrupt.
******************************************************************************/
-unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num)
+unsigned int gicv3_get_interrupt_group(unsigned int id, unsigned int proc_num)
{
unsigned int igroup, grpmodr;
uintptr_t gicr_base;
+ uintptr_t gicd_base;
assert(IS_IN_EL3());
assert(gicv3_driver_data != NULL);
@@ -434,8 +447,12 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num)
return INTR_GROUP1NS;
}
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
+
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */
assert(gicv3_driver_data->rdistif_base_addrs != NULL);
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
@@ -444,8 +461,9 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num)
} else {
/* SPIs: 32-1019, ESPIs: 4096-5119 */
assert(gicv3_driver_data->gicd_base != 0U);
- igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id);
- grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ igroup = gicd_get_igroupr(gicd_base, id);
+ grpmodr = gicd_get_igrpmodr(gicd_base, id);
}
/*
@@ -728,40 +746,17 @@ void gicv3_rdistif_init_restore(unsigned int proc_num,
*****************************************************************************/
void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx)
{
- unsigned int typer_reg, num_ints;
-#if GIC_EXT_INTID
- unsigned int num_eints;
-#endif
-
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(IS_IN_EL3());
assert(dist_ctx != NULL);
uintptr_t gicd_base = gicv3_driver_data->gicd_base;
-
- typer_reg = gicd_read_typer(gicd_base);
-
- /* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */
- num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5;
-
- /* Filter out special INTIDs 1020-1023 */
- if (num_ints > (MAX_SPI_ID + 1U)) {
- num_ints = MAX_SPI_ID + 1U;
- }
-
+ unsigned int num_ints = gicv3_get_spi_limit(gicd_base);
#if GIC_EXT_INTID
- /* Check if extended SPI range is implemented */
- if ((typer_reg & TYPER_ESPI) != 0U) {
- /*
- * Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095
- */
- num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) &
- TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID;
- } else {
- num_eints = 0U;
- }
+ unsigned int num_eints = gicv3_get_espi_limit(gicd_base);
#endif
+
/* Wait for pending write to complete */
gicd_wait_for_pending_write(gicd_base);
@@ -838,11 +833,6 @@ void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx)
*****************************************************************************/
void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)
{
- unsigned int typer_reg, num_ints;
-#if GIC_EXT_INTID
- unsigned int num_eints;
-#endif
-
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(IS_IN_EL3());
@@ -864,27 +854,9 @@ void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)
/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE);
- typer_reg = gicd_read_typer(gicd_base);
-
- /* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */
- num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5;
-
- /* Filter out special INTIDs 1020-1023 */
- if (num_ints > (MAX_SPI_ID + 1U)) {
- num_ints = MAX_SPI_ID + 1U;
- }
-
+ unsigned int num_ints = gicv3_get_spi_limit(gicd_base);
#if GIC_EXT_INTID
- /* Check if extended SPI range is implemented */
- if ((typer_reg & TYPER_ESPI) != 0U) {
- /*
- * Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095
- */
- num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) &
- TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID;
- } else {
- num_eints = 0U;
- }
+ unsigned int num_eints = gicv3_get_espi_limit(gicd_base);
#endif
/* Restore GICD_IGROUPR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP);
@@ -967,20 +939,26 @@ unsigned int gicv3_get_running_priority(void)
******************************************************************************/
unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num)
{
+ uintptr_t gicd_base;
+
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
assert(gicv3_driver_data->rdistif_base_addrs != NULL);
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
return gicr_get_isactiver(
gicv3_driver_data->rdistif_base_addrs[proc_num], id);
}
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- return gicd_get_isactiver(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ return gicd_get_isactiver(gicd_base, id);
}
/*******************************************************************************
@@ -990,6 +968,8 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num)
******************************************************************************/
void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num)
{
+ uintptr_t gicd_base;
+
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
@@ -1000,15 +980,18 @@ void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num)
* interrupt trigger are observed before enabling interrupt.
*/
dsbishst();
-
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_set_isenabler(
gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- gicd_set_isenabler(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_set_isenabler(gicd_base, id);
}
}
@@ -1019,6 +1002,8 @@ void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num)
******************************************************************************/
void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num)
{
+ uintptr_t gicd_base;
+
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
@@ -1028,9 +1013,11 @@ void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num)
* Disable interrupt, and ensure that any shared variable updates
* depending on out of band interrupt trigger are observed afterwards.
*/
-
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_set_icenabler(
gicv3_driver_data->rdistif_base_addrs[proc_num], id);
@@ -1040,10 +1027,11 @@ void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num)
gicv3_driver_data->rdistif_base_addrs[proc_num]);
} else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- gicd_set_icenabler(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_set_icenabler(gicd_base, id);
/* Write to clear enable requires waiting for pending writes */
- gicd_wait_for_pending_write(gicv3_driver_data->gicd_base);
+ gicd_wait_for_pending_write(gicd_base);
}
dsbishst();
@@ -1057,20 +1045,25 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num,
unsigned int priority)
{
uintptr_t gicr_base;
+ uintptr_t gicd_base;
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
assert(gicv3_driver_data->rdistif_base_addrs != NULL);
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
gicr_set_ipriorityr(gicr_base, id, priority);
} else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- gicd_set_ipriorityr(gicv3_driver_data->gicd_base, id, priority);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_set_ipriorityr(gicd_base, id, priority);
}
}
@@ -1079,18 +1072,19 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num,
* is used if the interrupt is SGI or (E)PPI, and programs the corresponding
* Redistributor interface. The group can be any of GICV3_INTR_GROUP*
******************************************************************************/
-void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
- unsigned int type)
+void gicv3_set_interrupt_group(unsigned int id, unsigned int proc_num,
+ unsigned int group)
{
bool igroup = false, grpmod = false;
uintptr_t gicr_base;
+ uintptr_t gicd_base;
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
assert(gicv3_driver_data->rdistif_base_addrs != NULL);
- switch (type) {
+ switch (group) {
case INTR_GROUP1S:
igroup = false;
grpmod = true;
@@ -1108,8 +1102,11 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
break;
}
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
@@ -1123,21 +1120,24 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
/* Serialize read-modify-write to Distributor registers */
spin_lock(&gic_lock);
- igroup ? gicd_set_igroupr(gicv3_driver_data->gicd_base, id) :
- gicd_clr_igroupr(gicv3_driver_data->gicd_base, id);
- grpmod ? gicd_set_igrpmodr(gicv3_driver_data->gicd_base, id) :
- gicd_clr_igrpmodr(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+
+ igroup ? gicd_set_igroupr(gicd_base, id) :
+ gicd_clr_igroupr(gicd_base, id);
+ grpmod ? gicd_set_igrpmodr(gicd_base, id) :
+ gicd_clr_igrpmodr(gicd_base, id);
spin_unlock(&gic_lock);
}
}
/*******************************************************************************
- * This function raises the specified Secure Group 0 SGI.
+ * This function raises the specified SGI of the specified group.
*
* The target parameter must be a valid MPIDR in the system.
******************************************************************************/
-void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target)
+void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group,
+ u_register_t target)
{
unsigned int tgt, aff3, aff2, aff1, aff0;
uint64_t sgi_val;
@@ -1167,7 +1167,22 @@ void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target)
* interrupt trigger are observed before raising SGI.
*/
dsbishst();
- write_icc_sgi0r_el1(sgi_val);
+
+ switch (group) {
+ case GICV3_G0:
+ write_icc_sgi0r_el1(sgi_val);
+ break;
+ case GICV3_G1NS:
+ write_icc_asgi1r(sgi_val);
+ break;
+ case GICV3_G1S:
+ write_icc_sgi1r(sgi_val);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
isb();
}
@@ -1186,6 +1201,7 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr
{
unsigned long long aff;
uint64_t router;
+ uintptr_t gicd_base;
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
@@ -1195,14 +1211,15 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr
assert(IS_SPI(id));
aff = gicd_irouter_val_from_mpidr(mpidr, irm);
- gicd_write_irouter(gicv3_driver_data->gicd_base, id, aff);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_write_irouter(gicd_base, id, aff);
/*
* In implementations that do not require 1 of N distribution of SPIs,
* IRM might be RAZ/WI. Read back and verify IRM bit.
*/
if (irm == GICV3_IRM_ANY) {
- router = gicd_read_irouter(gicv3_driver_data->gicd_base, id);
+ router = gicd_read_irouter(gicd_base, id);
if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) {
ERROR("GICv3 implementation doesn't support routing ANY\n");
panic();
@@ -1217,6 +1234,8 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr
******************************************************************************/
void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num)
{
+ uintptr_t gicd_base;
+
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
@@ -1226,15 +1245,18 @@ void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num)
* Clear pending interrupt, and ensure that any shared variable updates
* depending on out of band interrupt trigger are observed afterwards.
*/
-
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_set_icpendr(
- gicv3_driver_data->rdistif_base_addrs[proc_num], id);
+ gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- gicd_set_icpendr(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_set_icpendr(gicd_base, id);
}
dsbishst();
@@ -1247,6 +1269,8 @@ void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num)
******************************************************************************/
void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num)
{
+ uintptr_t gicd_base;
+
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num);
@@ -1258,14 +1282,19 @@ void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num)
*/
dsbishst();
+ if (!is_valid_interrupt(id)) {
+ panic();
+ }
+
/* Check interrupt ID */
- if (is_sgi_ppi(id)) {
+ if (IS_SGI_PPI(id)) {
/* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */
gicr_set_ispendr(
gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */
- gicd_set_ispendr(gicv3_driver_data->gicd_base, id);
+ gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
+ gicd_set_ispendr(gicd_base, id);
}
}
@@ -1292,6 +1321,31 @@ unsigned int gicv3_set_pmr(unsigned int mask)
}
/*******************************************************************************
+ * This function restores the PMR register to old value and also triggers
+ * gicv3_apply_errata_wa_2384374() that flushes the GIC buffer allowing any
+ * pending interrupts to processed. Returns the original PMR.
+ ******************************************************************************/
+unsigned int gicv3_deactivate_priority(unsigned int mask)
+{
+
+ unsigned int old_mask, proc_num;
+ uintptr_t gicr_base;
+
+ old_mask = gicv3_set_pmr(mask);
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ assert(gicr_base != 0UL);
+
+ /* Add DSB to ensure visibility of System register writes */
+ dsb();
+
+ gicv3_apply_errata_wa_2384374(gicr_base);
+
+ return old_mask;
+}
+
+/*******************************************************************************
* This function delegates the responsibility of discovering the corresponding
* Redistributor frames to each CPU itself. It is a modified version of
* gicv3_rdistif_base_addrs_probe() and is executed by each CPU in the platform
@@ -1309,12 +1363,14 @@ int gicv3_rdistif_probe(const uintptr_t gicr_frame)
assert(gicv3_driver_data->gicr_base == 0U);
+ if (plat_can_cmo()) {
/* Ensure this function is called with Data Cache enabled */
#ifndef __aarch64__
- assert((read_sctlr() & SCTLR_C_BIT) != 0U);
+ assert((read_sctlr() & SCTLR_C_BIT) != 0U);
#else
- assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
#endif /* !__aarch64__ */
+ }
mpidr_self = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
rdistif_base = gicr_frame;
@@ -1340,7 +1396,7 @@ int gicv3_rdistif_probe(const uintptr_t gicr_frame)
gicr_frame_found = true;
break;
}
- rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT);
+ rdistif_base += gicv3_redist_size(typer_val);
} while ((typer_val & TYPER_LAST_BIT) == 0U);
if (!gicr_frame_found) {
@@ -1363,21 +1419,19 @@ int gicv3_rdistif_probe(const uintptr_t gicr_frame)
}
/******************************************************************************
- * This function checks the interrupt ID and returns true for SGIs and (E)PPIs
- * and false for (E)SPIs IDs.
+ * This function checks the interrupt ID and returns true for SGIs, (E)PPIs
+ * and (E)SPIs IDs. Any interrupt ID outside the range is invalid and returns
+ * false.
*****************************************************************************/
-static bool is_sgi_ppi(unsigned int id)
+static bool is_valid_interrupt(unsigned int id)
{
- /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */
- if (IS_SGI_PPI(id)) {
+ /* Valid interrupts:
+ * SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119
+ * SPIs: 32-1019, ESPIs: 4096-5119
+ */
+ if ((IS_SGI_PPI(id)) || (IS_SPI(id))) {
return true;
}
- /* SPIs: 32-1019, ESPIs: 4096-5119 */
- if (IS_SPI(id)) {
- return false;
- }
-
- assert(false);
- panic();
+ return false;
}