GIC: Add helpers to set interrupt configuration
The helpers perform read-modify-write on GIC*_ICFGR registers, but don't
serialise callers. Any serialisation must be taken care of by the
callers.
Change-Id: I71995f82ff2c7f70d37af0ede30d6ee18682fd3f
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 71155a9..d523772 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -299,3 +299,15 @@
{
mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK);
}
+
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+ unsigned bit_num = id & ((1 << ICFGR_SHIFT) - 1);
+ uint32_t reg_val = gicd_read_icfgr(base, id);
+
+ /* Clear the field, and insert required configuration */
+ reg_val &= ~(GIC_CFG_MASK << bit_num);
+ reg_val |= ((cfg & GIC_CFG_MASK) << bit_num);
+
+ gicd_write_icfgr(base, id, reg_val);
+}
diff --git a/drivers/arm/gic/common/gic_common_private.h b/drivers/arm/gic/common/gic_common_private.h
index 8b96b37..2021f9a 100644
--- a/drivers/arm/gic/common/gic_common_private.h
+++ b/drivers/arm/gic/common/gic_common_private.h
@@ -77,5 +77,6 @@
void gicd_set_isactiver(uintptr_t base, unsigned int id);
void gicd_set_icactiver(uintptr_t base, unsigned int id);
void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri);
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg);
#endif /* GIC_COMMON_PRIVATE_H_ */
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 3abc6a5..33dbe2c 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -225,6 +225,38 @@
mmio_write_8(base + GICR_IPRIORITYR + id, pri & GIC_PRI_MASK);
}
+/*
+ * Accessor to set the bit fields corresponding to interrupt ID
+ * in GIC Re-distributor ICFGR0.
+ */
+void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+ unsigned bit_num = id & ((1 << ICFGR_SHIFT) - 1);
+ uint32_t reg_val = gicr_read_icfgr0(base);
+
+ /* Clear the field, and insert required configuration */
+ reg_val &= ~(GIC_CFG_MASK << bit_num);
+ reg_val |= ((cfg & GIC_CFG_MASK) << bit_num);
+
+ gicr_write_icfgr0(base, reg_val);
+}
+
+/*
+ * Accessor to set the bit fields corresponding to interrupt ID
+ * in GIC Re-distributor ICFGR1.
+ */
+void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+ unsigned bit_num = id & ((1 << ICFGR_SHIFT) - 1);
+ uint32_t reg_val = gicr_read_icfgr1(base);
+
+ /* Clear the field, and insert required configuration */
+ reg_val &= ~(GIC_CFG_MASK << bit_num);
+ reg_val |= ((cfg & GIC_CFG_MASK) << bit_num);
+
+ gicr_write_icfgr1(base, reg_val);
+}
+
/******************************************************************************
* This function marks the core as awake in the re-distributor and
* ensures that the interface is active.
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
index 14979cc..f7fc8ce 100644
--- a/include/drivers/arm/gic_common.h
+++ b/include/drivers/arm/gic_common.h
@@ -23,6 +23,9 @@
/* Mask for the priority field common to all GIC interfaces */
#define GIC_PRI_MASK 0xff
+/* Mask for the configuration field common to all GIC interfaces */
+#define GIC_CFG_MASK 0x3
+
/* Constant to indicate a spurious interrupt in all GIC versions */
#define GIC_SPURIOUS_INTERRUPT 1023