Browse Source

Merge "fix(gicv3): workaround for NVIDIA erratum T241-FABRIC-4" into integration

pull/1996/head
Manish Pandey 2 years ago
committed by TrustedFirmware Code Review
parent
commit
5a63aed223
  1. 57
      drivers/arm/gic/v3/gic600_multichip.c
  2. 3
      drivers/arm/gic/v3/gic600_multichip_private.h
  3. 4
      drivers/arm/gic/v3/gicv3.mk
  4. 44
      drivers/arm/gic/v3/gicv3_helpers.c
  5. 56
      drivers/arm/gic/v3/gicv3_main.c
  6. 2
      drivers/arm/gic/v3/gicv3_private.h
  7. 24
      include/drivers/arm/gic600_multichip.h
  8. 4
      plat/arm/board/n1sdp/n1sdp_bl31_setup.c
  9. 4
      plat/arm/board/rdn1edge/rdn1edge_plat.c
  10. 8
      plat/arm/board/rdn2/rdn2_plat.c
  11. 8
      plat/arm/board/rdv1mc/rdv1mc_plat.c

57
drivers/arm/gic/v3/gic600_multichip.c

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2019, Arm Limited. All rights reserved. * 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -19,6 +19,29 @@
#include "../common/gic_common_private.h" #include "../common/gic_common_private.h"
#include "gic600_multichip_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 * 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; unsigned int retry = GICD_PUP_UPDATE_RETRIES;
while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) { 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 " ERROR("GIC-600 connection to Routing Table Owner timed "
"out\n"); "out\n");
panic(); panic();
@ -186,11 +209,11 @@ static void gic600_multichip_validate_data(
panic(); panic();
} }
for (i = 0; i < multichip_data->chip_count; i++) { for (i = 0U; i < multichip_data->chip_count; i++) {
spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX]; spi_id_min = multichip_data->spi_ids[i].spi_id_min;
spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX]; 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 */ /* SPI IDs range check */
if (!(spi_id_min >= GIC600_SPI_ID_MIN) || 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++) { for (i = 0U; i < multichip_data->chip_count; i++) {
spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX]; spi_id_min = multichip_data->spi_ids[i].spi_id_min;
spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX]; spi_id_max = multichip_data->spi_ids[i].spi_id_max;
if ((spi_id_min == 0U) || (spi_id_max == 0U)) { if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
continue; 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, set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
multichip_data->chip_addrs[multichip_data->rt_owner], multichip_data->chip_addrs[multichip_data->rt_owner],
multichip_data-> multichip_data->
spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX], spi_ids[multichip_data->rt_owner].spi_id_min,
multichip_data-> 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++) { for (i = 0; i < multichip_data->chip_count; i++) {
if (i == multichip_data->rt_owner) 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, set_gicd_chipr_n(multichip_data->rt_owner_base, i,
multichip_data->chip_addrs[i], multichip_data->chip_addrs[i],
multichip_data->spi_ids[i][SPI_MIN_INDEX], multichip_data->spi_ids[i].spi_id_min,
multichip_data->spi_ids[i][SPI_MAX_INDEX]); 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);
} }

3
drivers/arm/gic/v3/gic600_multichip_private.h

@ -49,9 +49,6 @@
/* Number of retries for PUP update */ /* Number of retries for PUP update */
#define GICD_PUP_UPDATE_RETRIES 10000 #define GICD_PUP_UPDATE_RETRIES 10000
#define SPI_MIN_INDEX 0
#define SPI_MAX_INDEX 1
#define SPI_BLOCK_MIN_VALUE(spi_id_min) \ #define SPI_BLOCK_MIN_VALUE(spi_id_min) \
(((spi_id_min) - GIC600_SPI_ID_MIN) / \ (((spi_id_min) - GIC600_SPI_ID_MIN) / \
GIC600_SPI_ID_MIN) GIC600_SPI_ID_MIN)

4
drivers/arm/gic/v3/gicv3.mk

@ -41,6 +41,10 @@ $(eval $(call add_define,GICV3_SUPPORT_GIC600))
$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU)) $(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU))
$(eval $(call add_define,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 # Set GICv4 extension
$(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN)) $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
$(eval $(call add_define,GIC_ENABLE_V4_EXTN)) $(eval $(call add_define,GIC_ENABLE_V4_EXTN))

44
drivers/arm/gic/v3/gicv3_helpers.c

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -10,6 +11,7 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/debug.h> #include <common/debug.h>
#include <common/interrupt_props.h> #include <common/interrupt_props.h>
#include <drivers/arm/gic600_multichip.h>
#include <drivers/arm/gic_common.h> #include <drivers/arm/gic_common.h>
#include <platform_def.h> #include <platform_def.h>
@ -17,6 +19,16 @@
#include "../common/gic_common_private.h" #include "../common/gic_common_private.h"
#include "gicv3_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 * This function marks the core as awake in the re-distributor and
* ensures that the interface is active. * 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. */ /* 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)) { 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 #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; for (i = MIN_ESPI_ID; i < num_eints;
i += (1U << IGROUPR_SHIFT)) { i += (1U << IGROUPR_SHIFT)) {
gicd_write_igroupr(gicd_base, i, ~0U); gicd_write_igroupr(gicv3_get_multichip_base(i, gicd_base), i, ~0U);
} }
} else { } else {
INFO("ESPI range is not implemented.\n"); 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 */ /* Setup the default (E)SPI priorities doing four at a time */
for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) { 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 #if GIC_EXT_INTID
for (i = MIN_ESPI_ID; i < num_eints; for (i = MIN_ESPI_ID; i < num_eints;
i += (1U << IPRIORITYR_SHIFT)) { 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 #endif
/* /*
* Treat all (E)SPIs as level triggered by default, write 16 at a time * 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)) { 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 #if GIC_EXT_INTID
for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) { 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 #endif
} }
@ -211,6 +223,7 @@ unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
current_prop = &interrupt_props[i]; current_prop = &interrupt_props[i];
unsigned int intr_num = current_prop->intr_num; 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 */ /* Skip SGI, (E)PPI and LPI interrupts */
if (!IS_SPI(intr_num)) { 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 */ /* 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 */ /* Configure this interrupt as G0 or a G1S interrupt */
assert((current_prop->intr_grp == INTR_GROUP0) || assert((current_prop->intr_grp == INTR_GROUP0) ||
(current_prop->intr_grp == INTR_GROUP1S)); (current_prop->intr_grp == INTR_GROUP1S));
if (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; ctlr_enable |= CTLR_ENABLE_G1S_BIT;
} else { } else {
gicd_clr_igrpmodr(gicd_base, intr_num); gicd_clr_igrpmodr(multichip_gicd_base, intr_num);
ctlr_enable |= CTLR_ENABLE_G0_BIT; ctlr_enable |= CTLR_ENABLE_G0_BIT;
} }
/* Set interrupt configuration */ /* 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 */ /* Set the priority of this interrupt */
gicd_set_ipriorityr(gicd_base, intr_num, gicd_set_ipriorityr(multichip_gicd_base, intr_num,
current_prop->intr_pri); current_prop->intr_pri);
/* Target (E)SPIs to the primary CPU */ /* Target (E)SPIs to the primary CPU */
gic_affinity_val = gic_affinity_val =
gicd_irouter_val_from_mpidr(read_mpidr(), 0U); gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
gicd_write_irouter(gicd_base, intr_num, gicd_write_irouter(multichip_gicd_base, intr_num,
gic_affinity_val); gic_affinity_val);
/* Enable this interrupt */ /* Enable this interrupt */
gicd_set_isenabler(gicd_base, intr_num); gicd_set_isenabler(multichip_gicd_base, intr_num);
} }
return ctlr_enable; return ctlr_enable;

56
drivers/arm/gic/v3/gicv3_main.c

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -10,6 +11,7 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/debug.h> #include <common/debug.h>
#include <common/interrupt_props.h> #include <common/interrupt_props.h>
#include <drivers/arm/gic600_multichip.h>
#include <drivers/arm/gicv3.h> #include <drivers/arm/gicv3.h>
#include <lib/spinlock.h> #include <lib/spinlock.h>
#include <plat/common/platform.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; unsigned int igroup, grpmodr;
uintptr_t gicr_base; uintptr_t gicr_base;
uintptr_t gicd_base;
assert(IS_IN_EL3()); assert(IS_IN_EL3());
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
@ -453,8 +456,9 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num)
} else { } else {
/* SPIs: 32-1019, ESPIs: 4096-5119 */ /* SPIs: 32-1019, ESPIs: 4096-5119 */
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id); gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id); 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) 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 != NULL);
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num); 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 */ /* 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) void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num)
{ {
uintptr_t gicd_base;
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num); 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); gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else { } else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ /* 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) void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num)
{ {
uintptr_t gicd_base;
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num); 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]); gicv3_driver_data->rdistif_base_addrs[proc_num]);
} else { } else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ /* 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 */ /* 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(); dsbishst();
@ -1020,6 +1033,7 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num,
unsigned int priority) unsigned int priority)
{ {
uintptr_t gicr_base; uintptr_t gicr_base;
uintptr_t gicd_base;
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U); 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); gicr_set_ipriorityr(gicr_base, id, priority);
} else { } else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ /* 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; bool igroup = false, grpmod = false;
uintptr_t gicr_base; uintptr_t gicr_base;
uintptr_t gicd_base;
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U); 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 */ /* Serialize read-modify-write to Distributor registers */
spin_lock(&gic_lock); spin_lock(&gic_lock);
igroup ? gicd_set_igroupr(gicv3_driver_data->gicd_base, id) : gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base);
gicd_clr_igroupr(gicv3_driver_data->gicd_base, id);
grpmod ? gicd_set_igrpmodr(gicv3_driver_data->gicd_base, id) : igroup ? gicd_set_igroupr(gicd_base, id) :
gicd_clr_igrpmodr(gicv3_driver_data->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); 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; unsigned long long aff;
uint64_t router; uint64_t router;
uintptr_t gicd_base;
assert(gicv3_driver_data != NULL); assert(gicv3_driver_data != NULL);
assert(gicv3_driver_data->gicd_base != 0U); 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)); assert(IS_SPI(id));
aff = gicd_irouter_val_from_mpidr(mpidr, irm); 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, * In implementations that do not require 1 of N distribution of SPIs,
* IRM might be RAZ/WI. Read back and verify IRM bit. * IRM might be RAZ/WI. Read back and verify IRM bit.
*/ */
if (irm == GICV3_IRM_ANY) { 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) { if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) {
ERROR("GICv3 implementation doesn't support routing ANY\n"); ERROR("GICv3 implementation doesn't support routing ANY\n");
panic(); 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) 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 != NULL);
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num); 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); gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else { } else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ /* 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(); 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) 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 != NULL);
assert(gicv3_driver_data->gicd_base != 0U); assert(gicv3_driver_data->gicd_base != 0U);
assert(proc_num < gicv3_driver_data->rdistif_num); 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); gicv3_driver_data->rdistif_base_addrs[proc_num], id);
} else { } else {
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ /* 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);
} }
} }

2
drivers/arm/gic/v3/gicv3_private.h

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. * 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 * 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 * 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_spi_limit(uintptr_t gicd_base);
unsigned int gicv3_get_espi_limit(uintptr_t gicd_base); unsigned int gicv3_get_espi_limit(uintptr_t gicd_base);
void gicv3_spis_config_defaults(uintptr_t gicd_base); void gicv3_spis_config_defaults(uintptr_t gicd_base);

24
include/drivers/arm/gic600_multichip.h

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2019, ARM Limited. All rights reserved. * Copyright (c) 2019, ARM Limited. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -15,8 +16,11 @@
*/ */
#define GIC600_MAX_MULTICHIP 16 #define GIC600_MAX_MULTICHIP 16
/* SPI IDs array consist of min and max ids */ typedef struct multichip_spi_ids_desc {
#define GIC600_SPI_IDS_SIZE 2 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 * GIC-600 multichip data structure describes platform specific attributes
@ -37,19 +41,23 @@
* The 'chip_addrs' field contains array of chip addresses. These addresses are * The 'chip_addrs' field contains array of chip addresses. These addresses are
* implementation specific values. * implementation specific values.
* *
* The 'spi_ids' field contains array of minimum and maximum SPI interrupt ids * The 'multichip_spi_ids_desc_t' field contains array of descriptors used to
* that each chip owns. Note that SPI interrupt ids can range from 32 to 960 and * provide minimum and maximum SPI interrupt ids that each chip owns and the
* it should be group of 32 (i.e., SPI minimum and (SPI maximum + 1) should be * corresponding chip base address. Note that SPI interrupt ids can range from
* a multiple of 32). If a chip doesn't own any SPI interrupts a value of {0, 0} * 32 to 960 and it should be group of 32 (i.e., SPI minimum and (SPI maximum +
* should be passed. * 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 { struct gic600_multichip_data {
uintptr_t rt_owner_base; uintptr_t rt_owner_base;
unsigned int rt_owner; unsigned int rt_owner;
unsigned int chip_count; unsigned int chip_count;
uint64_t chip_addrs[GIC600_MAX_MULTICHIP]; 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); void gic600_multichip_init(struct gic600_multichip_data *multichip_data);
bool gic600_multichip_is_initialized(void);
#endif /* GIC600_MULTICHIP_H */ #endif /* GIC600_MULTICHIP_H */

4
plat/arm/board/n1sdp/n1sdp_bl31_setup.c

@ -51,8 +51,8 @@ static struct gic600_multichip_data n1sdp_multichip_data __init = {
PLAT_ARM_GICD_BASE >> 16 PLAT_ARM_GICD_BASE >> 16
}, },
.spi_ids = { .spi_ids = {
{32, 479}, {PLAT_ARM_GICD_BASE, 32, 479},
{512, 959} {PLAT_ARM_GICD_BASE, 512, 959}
} }
}; };

4
plat/arm/board/rdn1edge/rdn1edge_plat.c

@ -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 (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
}, },
.spi_ids = { .spi_ids = {
{32, 255}, {PLAT_ARM_GICD_BASE, 32, 255},
{0, 0} {0, 0, 0}
} }
}; };

8
plat/arm/board/rdn2/rdn2_plat.c

@ -47,15 +47,15 @@ static struct gic600_multichip_data rdn2mc_multichip_data __init = {
#endif #endif
}, },
.spi_ids = { .spi_ids = {
{32, 511}, {PLAT_ARM_GICD_BASE, 32, 511},
#if CSS_SGI_CHIP_COUNT > 1 #if CSS_SGI_CHIP_COUNT > 1
{512, 991}, {PLAT_ARM_GICD_BASE, 512, 991},
#endif #endif
#if CSS_SGI_CHIP_COUNT > 2 #if CSS_SGI_CHIP_COUNT > 2
{4096, 4575}, {PLAT_ARM_GICD_BASE, 4096, 4575},
#endif #endif
#if CSS_SGI_CHIP_COUNT > 3 #if CSS_SGI_CHIP_COUNT > 3
{4576, 5055}, {PLAT_ARM_GICD_BASE, 4576, 5055},
#endif #endif
} }
}; };

8
plat/arm/board/rdv1mc/rdv1mc_plat.c

@ -43,13 +43,13 @@ static struct gic600_multichip_data rdv1mc_multichip_data __init = {
#endif #endif
}, },
.spi_ids = { .spi_ids = {
{32, 255}, {PLAT_ARM_GICD_BASE, 32, 255},
{0, 0}, {0, 0, 0},
#if (CSS_SGI_CHIP_COUNT > 2) #if (CSS_SGI_CHIP_COUNT > 2)
{0, 0}, {0, 0, 0},
#endif #endif
#if (CSS_SGI_CHIP_COUNT > 3) #if (CSS_SGI_CHIP_COUNT > 3)
{0, 0}, {0, 0, 0},
#endif #endif
} }
}; };

Loading…
Cancel
Save