]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
fix(gicv3): workaround for NVIDIA erratum T241-FABRIC-4
authorVarun Wadekar <vwadekar@nvidia.com>
Wed, 8 Mar 2023 16:47:38 +0000 (16:47 +0000)
committerVarun Wadekar <vwadekar@nvidia.com>
Thu, 23 Mar 2023 23:06:07 +0000 (23:06 +0000)
The purpose of this patch is to address the T241 erratum T241-FABRIC-4,
which causes unexpected behavior in the GIC when multiple transactions
are received simultaneously from different sources. This hardware issue
impacts NVIDIA server platforms that use more than two T241 chips
interconnected. Each chip has support for 320 {E}SPIs.

This issue occurs when multiple packets from different GICs are
incorrectly interleaved at the target chip. The erratum text below
specifies exactly what can cause multiple transfer packets susceptible
to interleaving and GIC state corruption. GIC state corruption can
lead to a range of problems, including kernel panics, and unexpected
behavior.

Erratum documentation:
https://developer.nvidia.com/docs/t241-fabric-4/nvidia-t241-fabric-4-errata.pdf

The workaround is to ensure that MMIO accesses target the GIC on the
socket that holds the data, for example SPI ranges owned by the socket’s
GIC. This ensures that the GIC will not utilize the inter-socket AXI
Stream interface for servicing these GIC MMIO accesses.

This patch updates the functions that use the GICD_In{E} registers to
ensure that the accesses are directed to the chip that owns the SPI,
instead of using the global alias.

Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Change-Id: I04e33ba64eb306bd5fdabb56e63cbe273d8cd632

drivers/arm/gic/v3/gic600_multichip.c
drivers/arm/gic/v3/gic600_multichip_private.h
drivers/arm/gic/v3/gicv3.mk
drivers/arm/gic/v3/gicv3_helpers.c
drivers/arm/gic/v3/gicv3_main.c
drivers/arm/gic/v3/gicv3_private.h
include/drivers/arm/gic600_multichip.h
plat/arm/board/n1sdp/n1sdp_bl31_setup.c
plat/arm/board/rdn1edge/rdn1edge_plat.c
plat/arm/board/rdn2/rdn2_plat.c
plat/arm/board/rdv1mc/rdv1mc_plat.c

index e85dbc13d61a6b3d24905049e4fc70a51a8d3582..f26e056c929e9c7f5540ad721acdfac320f65293 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019, Arm Limited. All rights reserved.
- * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2022-2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include "../common/gic_common_private.h"
 #include "gic600_multichip_private.h"
 
+static struct gic600_multichip_data *plat_gic_multichip_data;
+
+/*******************************************************************************
+ * Retrieve the address of the chip owner for a given SPI ID
+ ******************************************************************************/
+uintptr_t gic600_multichip_gicd_base_for_spi(uint32_t spi_id)
+{
+       unsigned int i;
+
+       /* Find the multichip instance */
+       for (i = 0U; i < GIC600_MAX_MULTICHIP; i++) {
+               if ((spi_id <= plat_gic_multichip_data->spi_ids[i].spi_id_max) &&
+                    (spi_id >= plat_gic_multichip_data->spi_ids[i].spi_id_min)) {
+                       break;
+               }
+       }
+
+       /* Ensure that plat_gic_multichip_data contains valid values */
+       assert(i < GIC600_MAX_MULTICHIP);
+
+       return plat_gic_multichip_data->spi_ids[i].gicd_base;
+}
+
 /*******************************************************************************
  * GIC-600 multichip operation related helper functions
  ******************************************************************************/
@@ -27,7 +50,7 @@ static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base)
        unsigned int retry = GICD_PUP_UPDATE_RETRIES;
 
        while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) {
-               if (retry-- == 0) {
+               if (retry-- == 0U) {
                        ERROR("GIC-600 connection to Routing Table Owner timed "
                                         "out\n");
                        panic();
@@ -186,11 +209,11 @@ static void gic600_multichip_validate_data(
                panic();
        }
 
-       for (i = 0; i < multichip_data->chip_count; i++) {
-               spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
-               spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
+       for (i = 0U; i < multichip_data->chip_count; i++) {
+               spi_id_min = multichip_data->spi_ids[i].spi_id_min;
+               spi_id_max = multichip_data->spi_ids[i].spi_id_max;
 
-               if ((spi_id_min != 0) || (spi_id_max != 0)) {
+               if ((spi_id_min != 0U) || (spi_id_max != 0U)) {
 
                        /* SPI IDs range check */
                        if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
@@ -232,8 +255,8 @@ static void gic700_multichip_validate_data(
        }
 
        for (i = 0U; i < multichip_data->chip_count; i++) {
-               spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
-               spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
+               spi_id_min = multichip_data->spi_ids[i].spi_id_min;
+               spi_id_max = multichip_data->spi_ids[i].spi_id_max;
 
                if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
                        continue;
@@ -342,9 +365,9 @@ void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
        set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
                        multichip_data->chip_addrs[multichip_data->rt_owner],
                        multichip_data->
-                       spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX],
+                       spi_ids[multichip_data->rt_owner].spi_id_min,
                        multichip_data->
-                       spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]);
+                       spi_ids[multichip_data->rt_owner].spi_id_max);
 
        for (i = 0; i < multichip_data->chip_count; i++) {
                if (i == multichip_data->rt_owner)
@@ -352,7 +375,17 @@ void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
 
                set_gicd_chipr_n(multichip_data->rt_owner_base, i,
                                multichip_data->chip_addrs[i],
-                               multichip_data->spi_ids[i][SPI_MIN_INDEX],
-                               multichip_data->spi_ids[i][SPI_MAX_INDEX]);
+                               multichip_data->spi_ids[i].spi_id_min,
+                               multichip_data->spi_ids[i].spi_id_max);
        }
+
+       plat_gic_multichip_data = multichip_data;
+}
+
+/*******************************************************************************
+ * Allow a way to query the status of the GIC600 multichip driver
+ ******************************************************************************/
+bool gic600_multichip_is_initialized(void)
+{
+       return (plat_gic_multichip_data != NULL);
 }
index 414bd5b8496c183a4d509bad1ad1c23fb60925ab..f6028adcb16c52733f068d3b6e6b21dfedbf7ed0 100644 (file)
@@ -49,9 +49,6 @@
 /* Number of retries for PUP update */
 #define GICD_PUP_UPDATE_RETRIES                10000
 
-#define SPI_MIN_INDEX                  0
-#define SPI_MAX_INDEX                  1
-
 #define SPI_BLOCK_MIN_VALUE(spi_id_min) \
                        (((spi_id_min) - GIC600_SPI_ID_MIN) / \
                        GIC600_SPI_ID_MIN)
index 1d20ff3a3aca49967293320a02e7acc87bfa8297..89bce95dedb20c10803f80fb0f7f7898834fe185 100644 (file)
@@ -41,6 +41,10 @@ $(eval $(call add_define,GICV3_SUPPORT_GIC600))
 $(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU))
 $(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU))
 
+# Set GIC-600 multichip support
+$(eval $(call assert_boolean,GICV3_IMPL_GIC600_MULTICHIP))
+$(eval $(call add_define,GICV3_IMPL_GIC600_MULTICHIP))
+
 # Set GICv4 extension
 $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
index 940c939af3ebbcc4a9b73610ac25724db594ef1e..00bd7a1f15a73a0ca8058df04822ce7a367f4b0d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +11,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <common/interrupt_props.h>
+#include <drivers/arm/gic600_multichip.h>
 #include <drivers/arm/gic_common.h>
 
 #include <platform_def.h>
 #include "../common/gic_common_private.h"
 #include "gicv3_private.h"
 
+uintptr_t gicv3_get_multichip_base(uint32_t spi_id, uintptr_t gicd_base)
+{
+#if GICV3_IMPL_GIC600_MULTICHIP
+       if (gic600_multichip_is_initialized()) {
+               return gic600_multichip_gicd_base_for_spi(spi_id);
+       }
+#endif
+       return gicd_base;
+}
+
 /******************************************************************************
  * This function marks the core as awake in the re-distributor and
  * ensures that the interface is active.
@@ -148,7 +160,7 @@ void gicv3_spis_config_defaults(uintptr_t gicd_base)
 
        /* Treat all (E)SPIs as G1NS by default. We do 32 at a time. */
        for (i = MIN_SPI_ID; i < num_ints; i += (1U << IGROUPR_SHIFT)) {
-               gicd_write_igroupr(gicd_base, i, ~0U);
+               gicd_write_igroupr(gicv3_get_multichip_base(i, gicd_base), i, ~0U);
        }
 
 #if GIC_EXT_INTID
@@ -158,7 +170,7 @@ void gicv3_spis_config_defaults(uintptr_t gicd_base)
 
                for (i = MIN_ESPI_ID; i < num_eints;
                                        i += (1U << IGROUPR_SHIFT)) {
-                       gicd_write_igroupr(gicd_base, i, ~0U);
+                       gicd_write_igroupr(gicv3_get_multichip_base(i, gicd_base), i, ~0U);
                }
        } else {
                INFO("ESPI range is not implemented.\n");
@@ -167,25 +179,25 @@ void gicv3_spis_config_defaults(uintptr_t gicd_base)
 
        /* Setup the default (E)SPI priorities doing four at a time */
        for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) {
-               gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL);
+               gicd_write_ipriorityr(gicv3_get_multichip_base(i, gicd_base), i, GICD_IPRIORITYR_DEF_VAL);
        }
 
 #if GIC_EXT_INTID
        for (i = MIN_ESPI_ID; i < num_eints;
                                        i += (1U << IPRIORITYR_SHIFT)) {
-               gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL);
+               gicd_write_ipriorityr(gicv3_get_multichip_base(i, gicd_base), i, GICD_IPRIORITYR_DEF_VAL);
        }
 #endif
        /*
         * Treat all (E)SPIs as level triggered by default, write 16 at a time
         */
        for (i = MIN_SPI_ID; i < num_ints; i += (1U << ICFGR_SHIFT)) {
-               gicd_write_icfgr(gicd_base, i, 0U);
+               gicd_write_icfgr(gicv3_get_multichip_base(i, gicd_base), i, 0U);
        }
 
 #if GIC_EXT_INTID
        for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) {
-               gicd_write_icfgr(gicd_base, i, 0U);
+               gicd_write_icfgr(gicv3_get_multichip_base(i, gicd_base), i, 0U);
        }
 #endif
 }
@@ -211,6 +223,7 @@ unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
                current_prop = &interrupt_props[i];
 
                unsigned int intr_num = current_prop->intr_num;
+               uintptr_t multichip_gicd_base = gicv3_get_multichip_base(intr_num, gicd_base);
 
                /* Skip SGI, (E)PPI and LPI interrupts */
                if (!IS_SPI(intr_num)) {
@@ -218,35 +231,36 @@ unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
                }
 
                /* Configure this interrupt as a secure interrupt */
-               gicd_clr_igroupr(gicd_base, intr_num);
+               gicd_clr_igroupr(multichip_gicd_base, intr_num);
 
                /* Configure this interrupt as G0 or a G1S interrupt */
                assert((current_prop->intr_grp == INTR_GROUP0) ||
                                (current_prop->intr_grp == INTR_GROUP1S));
 
                if (current_prop->intr_grp == INTR_GROUP1S) {
-                       gicd_set_igrpmodr(gicd_base, intr_num);
+                       gicd_set_igrpmodr(multichip_gicd_base, intr_num);
                        ctlr_enable |= CTLR_ENABLE_G1S_BIT;
                } else {
-                       gicd_clr_igrpmodr(gicd_base, intr_num);
+                       gicd_clr_igrpmodr(multichip_gicd_base, intr_num);
                        ctlr_enable |= CTLR_ENABLE_G0_BIT;
                }
 
                /* Set interrupt configuration */
-               gicd_set_icfgr(gicd_base, intr_num, current_prop->intr_cfg);
+               gicd_set_icfgr(multichip_gicd_base, intr_num,
+                               current_prop->intr_cfg);
 
                /* Set the priority of this interrupt */
-               gicd_set_ipriorityr(gicd_base, intr_num,
-                                       current_prop->intr_pri);
+               gicd_set_ipriorityr(multichip_gicd_base, intr_num,
+                               current_prop->intr_pri);
 
                /* Target (E)SPIs to the primary CPU */
                gic_affinity_val =
                        gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
-               gicd_write_irouter(gicd_base, intr_num,
-                                       gic_affinity_val);
+               gicd_write_irouter(multichip_gicd_base, intr_num,
+                       gic_affinity_val);
 
                /* Enable this interrupt */
-               gicd_set_isenabler(gicd_base, intr_num);
+               gicd_set_isenabler(multichip_gicd_base, intr_num);
        }
 
        return ctlr_enable;
index f6c251df9e9518d1fa0f6a035292f5fede0c286e..168d0ebc9f7aed1cd1986734032e854c7ef87363 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +11,7 @@
 #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>
@@ -430,6 +432,7 @@ unsigned int gicv3_get_interrupt_type(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);
@@ -453,8 +456,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);
        }
 
        /*
@@ -930,6 +934,8 @@ 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);
@@ -943,7 +949,8 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num)
        }
 
        /* 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);
 }
 
 /*******************************************************************************
@@ -953,6 +960,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);
@@ -971,7 +980,8 @@ void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num)
                        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);
        }
 }
 
@@ -982,6 +992,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);
@@ -1003,10 +1015,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();
@@ -1020,6 +1033,7 @@ 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);
@@ -1033,7 +1047,8 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int 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);
        }
 }
 
@@ -1047,6 +1062,7 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
 {
        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);
@@ -1086,10 +1102,12 @@ 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);
        }
@@ -1165,6 +1183,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);
@@ -1174,14 +1193,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();
@@ -1196,6 +1216,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);
@@ -1213,7 +1235,8 @@ void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num)
                        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();
@@ -1226,6 +1249,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);
@@ -1244,7 +1269,8 @@ void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num)
                        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);
        }
 }
 
index 3af05007137ecebd902af5f0ca0abb52d2a0490c..8ad251bf8f8bb6caf5c6f086a4c38cc63c73e696 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -233,6 +234,7 @@ void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg);
 /*******************************************************************************
  * Private GICv3 helper function prototypes
  ******************************************************************************/
+uintptr_t gicv3_get_multichip_base(uint32_t spi_id, uintptr_t gicd_base);
 unsigned int gicv3_get_spi_limit(uintptr_t gicd_base);
 unsigned int gicv3_get_espi_limit(uintptr_t gicd_base);
 void gicv3_spis_config_defaults(uintptr_t gicd_base);
index bda406bba399cd36a363b8568d2a15285caad8c4..978d7357c31fe55eaedbcbafe52038084bc4a0f2 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
  */
 #define GIC600_MAX_MULTICHIP   16
 
-/* SPI IDs array consist of min and max ids */
-#define GIC600_SPI_IDS_SIZE    2
+typedef struct multichip_spi_ids_desc {
+       uintptr_t gicd_base;
+       uint32_t spi_id_min;
+       uint32_t spi_id_max;
+} multichip_spi_ids_desc_t;
 
 /*******************************************************************************
  * GIC-600 multichip data structure describes platform specific attributes
  * The 'chip_addrs' field contains array of chip addresses. These addresses are
  * implementation specific values.
  *
- * The 'spi_ids' field contains array of minimum and maximum SPI interrupt ids
- * that each chip owns. Note that SPI interrupt ids can range from 32 to 960 and
- * it should be group of 32 (i.e., SPI minimum and (SPI maximum + 1) should be
- * a multiple of 32). If a chip doesn't own any SPI interrupts a value of {0, 0}
- * should be passed.
+ * The 'multichip_spi_ids_desc_t' field contains array of descriptors used to
+ * provide minimum and maximum SPI interrupt ids that each chip owns and the
+ * corresponding chip base address. Note that SPI interrupt ids can range from
+ * 32 to 960 and it should be group of 32 (i.e., SPI minimum and (SPI maximum +
+ * 1) should be a multiple of 32). If a chip doesn't own any SPI interrupts a
+ * value of {0, 0, 0} should be passed.
  ******************************************************************************/
 struct gic600_multichip_data {
        uintptr_t rt_owner_base;
        unsigned int rt_owner;
        unsigned int chip_count;
        uint64_t chip_addrs[GIC600_MAX_MULTICHIP];
-       unsigned int spi_ids[GIC600_MAX_MULTICHIP][GIC600_SPI_IDS_SIZE];
+       multichip_spi_ids_desc_t spi_ids[GIC600_MAX_MULTICHIP];
 };
 
+uintptr_t gic600_multichip_gicd_base_for_spi(uint32_t spi_id);
 void gic600_multichip_init(struct gic600_multichip_data *multichip_data);
+bool gic600_multichip_is_initialized(void);
+
 #endif /* GIC600_MULTICHIP_H */
index ad6c1f840f6aec0831c79a1bb230ee5608a94d03..4941a4bd439f1a08f98bdfdd0e76c76cdd6b80d6 100644 (file)
@@ -51,8 +51,8 @@ static struct gic600_multichip_data n1sdp_multichip_data __init = {
                PLAT_ARM_GICD_BASE >> 16
        },
        .spi_ids = {
-               {32, 479},
-               {512, 959}
+               {PLAT_ARM_GICD_BASE, 32, 479},
+               {PLAT_ARM_GICD_BASE, 512, 959}
        }
 };
 
index 045c316ee842134b5eaec121a2e0789e21f641a4..6da8bcd6dea128b905b7bdd80f572ade6639fddf 100644 (file)
@@ -27,8 +27,8 @@ static struct gic600_multichip_data rdn1e1_multichip_data __init = {
                (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
        },
        .spi_ids = {
-               {32, 255},
-               {0, 0}
+               {PLAT_ARM_GICD_BASE, 32, 255},
+               {0, 0, 0}
        }
 };
 
index 2506f9da056dde04ccdacc396c7d7af10e37d4f7..a5564ceaf07dab5a8904ae58e9f2514d0e01b535 100644 (file)
@@ -47,15 +47,15 @@ static struct gic600_multichip_data rdn2mc_multichip_data __init = {
 #endif
        },
        .spi_ids = {
-               {32, 511},
+               {PLAT_ARM_GICD_BASE, 32, 511},
        #if CSS_SGI_CHIP_COUNT > 1
-               {512, 991},
+               {PLAT_ARM_GICD_BASE, 512, 991},
        #endif
        #if CSS_SGI_CHIP_COUNT > 2
-               {4096, 4575},
+               {PLAT_ARM_GICD_BASE, 4096, 4575},
        #endif
        #if CSS_SGI_CHIP_COUNT > 3
-               {4576, 5055},
+               {PLAT_ARM_GICD_BASE, 4576, 5055},
        #endif
        }
 };
index d8594006679548bc50c4e0d3fa875d734a60d9d9..e4469dccfb006e1f2a98c5223b801436801bf9b3 100644 (file)
@@ -43,13 +43,13 @@ static struct gic600_multichip_data rdv1mc_multichip_data __init = {
 #endif
        },
        .spi_ids = {
-               {32, 255},
-               {0, 0},
+               {PLAT_ARM_GICD_BASE, 32, 255},
+               {0, 0, 0},
 #if (CSS_SGI_CHIP_COUNT > 2)
-               {0, 0},
+               {0, 0, 0},
 #endif
 #if (CSS_SGI_CHIP_COUNT > 3)
-               {0, 0},
+               {0, 0, 0},
 #endif
        }
 };