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)