feat(gicv3): multichip: detect GIC-700 at runtime

At the moment we have a GIC_ENABLE_V4_EXTN build time variable to
determine whether the GIC interrupt controller is compliant to version
4.0 of the GIC spec or not.
In case of the GIC-600 multichip support we were somewhat abusing that
flag to differentiate between a GIC-700 and GIC-600 implementation
being used in the system.

To avoid a build time dependency on this flag, look at the GICD_IIDR
register and check if the hardware is a GIC-600 or not, to make this
decision at runtime. We then use the values for either GIC-700 or the
GIC-600, respectively.

Change-Id: I8c09ec1cd6fd60d28da879ed55ffef5506f9869d
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2021-05-18 15:46:58 +01:00
parent 1fe27d7135
commit feb7081863
2 changed files with 32 additions and 16 deletions

View File

@ -11,6 +11,7 @@
#include <assert.h>
#include <common/debug.h>
#include <drivers/arm/arm_gicv3_common.h>
#include <drivers/arm/gic600_multichip.h>
#include <drivers/arm/gicv3.h>
@ -73,6 +74,7 @@ static void set_gicd_chipr_n(uintptr_t base,
unsigned int spi_id_max)
{
unsigned int spi_block_min, spi_blocks;
unsigned int gicd_iidr_val = gicd_read_iidr(base);
uint64_t chipr_n_val;
/*
@ -100,8 +102,24 @@ static void set_gicd_chipr_n(uintptr_t base,
spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) |
GICD_CHIPRx_SOCKET_STATE;
switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
case IIDR_MODEL_ARM_GIC_600:
chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
spi_block_min,
spi_blocks);
break;
case IIDR_MODEL_ARM_GIC_700:
chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
spi_block_min,
spi_blocks);
break;
default:
ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
gicd_iidr_val);
panic();
break;
}
chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
/*
* Wait for DCHIPR.PUP to be zero before commencing writes to

View File

@ -27,17 +27,11 @@
#define GICD_CHIPSR_RTS_SHIFT 4
#define GICD_DCHIPR_RT_OWNER_SHIFT 4
/*
* If GIC v4 extension is enabled, then use SPI macros specific to GIC-700.
* Other shifts and mask remains same between GIC-600 and GIC-700.
*/
#if GIC_ENABLE_V4_EXTN
#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 9
#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 3
#else
#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 10
#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 5
#endif
/* Other shifts and masks remain the same between GIC-600 and GIC-700. */
#define GIC_700_SPI_BLOCK_MIN_SHIFT 9
#define GIC_700_SPI_BLOCKS_SHIFT 3
#define GIC_600_SPI_BLOCK_MIN_SHIFT 10
#define GIC_600_SPI_BLOCKS_SHIFT 5
#define GICD_CHIPSR_RTS_STATE_DISCONNECTED U(0)
#define GICD_CHIPSR_RTS_STATE_UPDATING U(1)
@ -59,10 +53,14 @@
#define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \
(((spi_id_max) - (spi_id_min) + 1) / \
GIC600_SPI_ID_MIN)
#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \
#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \
(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \
((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT))
((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \
((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT))
#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \
(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \
((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT))
/*
* Multichip data assertion macros