feat(gicv5): probe components

Asserts that the platform configuration is correct. No dynamic
discovery so only done in debug builds.

Change-Id: I56763cb422dcaa4a816a619ab4acfc6946427c64
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/drivers/arm/gicv5/gicv5_main.c b/drivers/arm/gicv5/gicv5_main.c
index 510cf7f..803a96d 100644
--- a/drivers/arm/gicv5/gicv5_main.c
+++ b/drivers/arm/gicv5/gicv5_main.c
@@ -15,6 +15,30 @@
 #include <common/debug.h>
 #include <drivers/arm/gicv5.h>
 
+/*
+ * Check for a bad platform configuration.
+ * Not expected to be called on release builds.
+ */
+static inline bool probe_component(uintptr_t base_addr, uint8_t component)
+{
+	uint32_t aidr = read_iri_aidr(base_addr);
+
+	if (EXTRACT(IRI_AIDR_COMPONENT, aidr) != component) {
+		ERROR("GICv5 frame belongs to wrong component\n");
+		return false;
+	}
+
+	if (EXTRACT(IRI_AIDR_ARCH_MAJOR, aidr) != IRI_AIDR_ARCH_MAJOR_V5) {
+		ERROR("Bad GICv5 major version\n");
+		return false;
+	}
+
+	/* there was a bump in architecture and we've not updated the driver */
+	assert(EXTRACT(IRI_AIDR_ARCH_MINOR, aidr) == IRI_AIDR_ARCH_MINOR_P0);
+
+	return true;
+}
+
 static inline bool iwb_domain_supported(uint32_t idr0, uint8_t domain)
 {
 	return (EXTRACT(IWB_IDR0_DOMAINS, idr0) & (1U << domain)) != 0U;
@@ -45,6 +69,8 @@
 	uint32_t idr0;
 	uint16_t num_regs;
 
+	assert(probe_component(base_addr, IRI_AIDR_COMPONENT_IWB));
+
 	idr0 = read_iwb_idr0(base_addr);
 	num_regs = EXTRACT(IWB_IDR0_IWRANGE, idr0) + 1U;
 
@@ -89,6 +115,8 @@
 	spi_base  = EXTRACT(IRS_IDR7_SPI_BASE, read_irs_idr7(base_addr));
 	spi_range = EXTRACT(IRS_IDR6_SPI_IRS_RANGE, read_irs_idr6(base_addr));
 
+	assert(probe_component(base_addr, IRI_AIDR_COMPONENT_IRS));
+
 	if (spi_range == 0U) {
 		assert(config->num_spis == 0U);
 	}
diff --git a/include/drivers/arm/gicv5.h b/include/drivers/arm/gicv5.h
index 763fea0..786d0bb 100644
--- a/include/drivers/arm/gicv5.h
+++ b/include/drivers/arm/gicv5.h
@@ -44,6 +44,20 @@
 #define PPI_DB_RL				1
 #define PPI_DB_S				0
 
+/* Register fields common to all IRI components.
+ * They have the same name and offset in every config frame */
+#define IRI_AIDR_COMPONENT_SHIFT		8
+#define IRI_AIDR_COMPONENT_WIDTH		4
+#define IRI_AIDR_COMPONENT_IRS			0
+#define IRI_AIDR_COMPONENT_ITS			1
+#define IRI_AIDR_COMPONENT_IWB			2
+#define IRI_AIDR_ARCH_MAJOR_SHIFT		4
+#define IRI_AIDR_ARCH_MAJOR_WIDTH		4
+#define IRI_AIDR_ARCH_MAJOR_V5			0
+#define IRI_AIDR_ARCH_MINOR_SHIFT		0
+#define IRI_AIDR_ARCH_MINOR_WIDTH		4
+#define IRI_AIDR_ARCH_MINOR_P0			0
+
 /* IRS register fields */
 #define IRS_IDR6_SPI_IRS_RANGE_SHIFT		0
 #define IRS_IDR6_SPI_IRS_RANGE_WIDTH		24
@@ -110,6 +124,8 @@
 	DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset)			\
 	DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset)
 
+DEFINE_GICV5_MMIO_READ_FUNC(iri_aidr,			0x44)
+
 DEFINE_GICV5_MMIO_READ_FUNC(iwb_idr0,			0x00)
 DEFINE_GICV5_MMIO_RW_FUNCS( iwb_cr0,			0x80)
 DEFINE_GICV5_MMIO_READ_FUNC(iwb_wenable_statusr,	0xc0)