/*
* 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
******************************************************************************/
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();
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) ||
}
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;
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)
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);
}
/* 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)
$(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))
/*
* 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
*/
#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.
/* 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
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");
/* 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
}
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)) {
}
/* 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;
/*
* 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
*/
#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>
{
unsigned int igroup, grpmodr;
uintptr_t gicr_base;
+ uintptr_t gicd_base;
assert(IS_IN_EL3());
assert(gicv3_driver_data != NULL);
} 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);
}
/*
******************************************************************************/
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);
}
/* 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);
}
/*******************************************************************************
******************************************************************************/
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);
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);
}
}
******************************************************************************/
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);
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();
unsigned int priority)
{
uintptr_t gicr_base;
+ uintptr_t gicd_base;
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
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);
}
}
{
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);
/* 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);
}
{
unsigned long long aff;
uint64_t router;
+ uintptr_t gicd_base;
assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U);
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();
******************************************************************************/
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);
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();
******************************************************************************/
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);
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);
}
}
/*
* 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
*/
/*******************************************************************************
* 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);
/*
* 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 */
PLAT_ARM_GICD_BASE >> 16
},
.spi_ids = {
- {32, 479},
- {512, 959}
+ {PLAT_ARM_GICD_BASE, 32, 479},
+ {PLAT_ARM_GICD_BASE, 512, 959}
}
};
(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}
}
};
#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
}
};
#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
}
};