feat(gicv3): introduce GIC component identification
The GIC specification describes ID registers in each GIC register frame
(PIDRx), which can be used to identify a GIC component. The Arm Ltd. GIC
implementations use certain ID values to identify the distributor, the
redistributors and other parts like ITSes.
Introduce a function that reads those part number IDs, which are spread
over two registers. The actual numbers are only meaningful in connection
with a certain GIC model, which would need to be checked beforehand, by
the caller.
Change-Id: Ia6ff326a1e8b12664e4637bc8e2683d2b5c7721c
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index d752013..753d995 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -393,3 +393,18 @@
return count;
}
+
+unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame)
+{
+ unsigned int part_id;
+
+ /*
+ * The lower 8 bits of PIDR0, complemented by the lower 4 bits of
+ * PIDR1 contain a part number identifying the GIC component at a
+ * particular base address.
+ */
+ part_id = mmio_read_32(gic_frame + GICD_PIDR0_GICV3) & 0xff;
+ part_id |= (mmio_read_32(gic_frame + GICD_PIDR1_GICV3) << 8) & 0xf00;
+
+ return part_id;
+}
diff --git a/include/drivers/arm/arm_gicv3_common.h b/include/drivers/arm/arm_gicv3_common.h
index e5df311..d1e93be 100644
--- a/include/drivers/arm/arm_gicv3_common.h
+++ b/include/drivers/arm/arm_gicv3_common.h
@@ -21,4 +21,8 @@
#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b)
#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b)
+#define PIDR_COMPONENT_ARM_DIST U(0x492)
+#define PIDR_COMPONENT_ARM_REDIST U(0x493)
+#define PIDR_COMPONENT_ARM_ITS U(0x494)
+
#endif /* ARM_GICV3_COMMON_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index fa8946b..973a58b 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -104,6 +104,8 @@
#define GICD_IROUTER U(0x6000)
#define GICD_IROUTERE U(0x8000)
+#define GICD_PIDR0_GICV3 U(0xffe0)
+#define GICD_PIDR1_GICV3 U(0xffe4)
#define GICD_PIDR2_GICV3 U(0xffe8)
#define IGRPMODR_SHIFT 5
@@ -324,6 +326,8 @@
#endif
}
+unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame);
+
static inline bool gicv3_is_intr_id_special_identifier(unsigned int id)
{
return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT);