fix(gic600): implement workaround to forward highest priority interrupt
If the interrupt being targeted is released from the CPU before the
CLEAR command is sent to the CPU then a subsequent SET command may not
be delivered in a finite time. To workaround this, issue an unblocking
event by toggling GICR_CTLR.DPG* bits after clearing the cpu group
enable (EnableGrp* bits of GIC CPU interface register)
This fix is implemented as per the errata 2384374-part 2 workaround
mentioned here:
https://developer.arm.com/documentation/sden892601/latest/
Change-Id: I13926ceeb7740fa4c05cc5b43170e7ce49598f70
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 753d995..f3852d2 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -408,3 +408,34 @@
return part_id;
}
+
+/*******************************************************************************
+ * Helper function to return product ID and revision of GIC
+ * @gicd_base: base address of the GIC distributor
+ * @gic_prod_id: retrieved product id of GIC
+ * @gic_rev: retrieved revision of GIC
+ ******************************************************************************/
+void gicv3_get_component_prodid_rev(const uintptr_t gicd_base,
+ unsigned int *gic_prod_id,
+ uint8_t *gic_rev)
+{
+ unsigned int gicd_iidr;
+ uint8_t gic_variant;
+
+ gicd_iidr = gicd_read_iidr(gicd_base);
+ *gic_prod_id = gicd_iidr >> IIDR_PRODUCT_ID_SHIFT;
+ *gic_prod_id &= IIDR_PRODUCT_ID_MASK;
+
+ gic_variant = gicd_iidr >> IIDR_VARIANT_SHIFT;
+ gic_variant &= IIDR_VARIANT_MASK;
+
+ *gic_rev = gicd_iidr >> IIDR_REV_SHIFT;
+ *gic_rev &= IIDR_REV_MASK;
+
+ /*
+ * pack gic variant and gic_rev in 1 byte
+ * gic_rev = gic_variant[7:4] and gic_rev[0:3]
+ */
+ *gic_rev = *gic_rev | gic_variant << 0x4;
+
+}