GICv3: add functions for save and restore

During system suspend, the GICv3 Distributor and Redistributor context
can be lost due to power gating of the system power domain. This means
that the GICv3 context needs to be saved prior to system suspend and
restored on wakeup. Currently the consensus is that the Firmware should
be in charge of this. See tf-issues#464 for more details.

This patch introduces helper APIs in the GICv3 driver to save and
restore the Distributor and Redistributor contexts. The GICv3 ITS
context is not considered in this patch because the specification says
that the details of ITS power management is implementation-defined.
These APIs are expected to be appropriately invoked by the platform
layer during system suspend.

Fixes ARM-software/tf-issues#464

Change-Id: Iebb9c6770ab8c4d522546f161fa402d2fe02ec00
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index da4bcbf..7224e06 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -7,6 +7,7 @@
 #ifndef __GICV3_PRIVATE_H__
 #define __GICV3_PRIVATE_H__
 
+#include <assert.h>
 #include <gic_common.h>
 #include <gicv3.h>
 #include <mmio.h>
@@ -43,6 +44,11 @@
 #endif
 
 /*******************************************************************************
+ * GICv3 private global variables declarations
+ ******************************************************************************/
+extern const gicv3_driver_data_t *gicv3_driver_data;
+
+/*******************************************************************************
  * Private GICv3 function prototypes for accessing entire registers.
  * Note: The raw register values correspond to multiple interrupt IDs and
  * the number of interrupt IDs involved depends on the register accessed.
@@ -150,6 +156,11 @@
 	return mmio_read_64(base + GICR_CTLR);
 }
 
+static inline void gicr_write_ctlr(uintptr_t base, uint64_t val)
+{
+	mmio_write_64(base + GICR_CTLR, val);
+}
+
 static inline unsigned long long gicr_read_typer(uintptr_t base)
 {
 	return mmio_read_64(base + GICR_TYPER);
@@ -178,6 +189,16 @@
 		;
 }
 
+static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base)
+{
+	while (gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT)
+		;
+}
+
+/* Private implementation of Distributor power control hooks */
+void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num);
+void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num);
+
 /*******************************************************************************
  * GIC Re-distributor functions for accessing entire registers.
  * Note: The raw register values correspond to multiple interrupt IDs and
@@ -208,6 +229,16 @@
 	return mmio_read_32(base + GICR_IGROUPR0);
 }
 
+static inline unsigned int gicr_read_ispendr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ISPENDR0);
+}
+
+static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ISPENDR0, val);
+}
+
 static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_IGROUPR0, val);
@@ -223,14 +254,64 @@
 	mmio_write_32(base + GICR_IGRPMODR0, val);
 }
 
+static inline unsigned int gicr_read_nsacr(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_NSACR);
+}
+
+static inline void gicr_write_nsacr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_NSACR, val);
+}
+
+static inline unsigned int gicr_read_isactiver0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ISACTIVER0);
+}
+
+static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ISACTIVER0, val);
+}
+
+static inline unsigned int gicr_read_icfgr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ICFGR0);
+}
+
 static inline unsigned int gicr_read_icfgr1(uintptr_t base)
 {
 	return mmio_read_32(base + GICR_ICFGR1);
 }
 
+static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ICFGR0, val);
+}
+
 static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_ICFGR1, val);
 }
 
+static inline unsigned int gicr_read_propbaser(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_PROPBASER);
+}
+
+static inline void gicr_write_propbaser(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_PROPBASER, val);
+}
+
+static inline unsigned int gicr_read_pendbaser(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_PENDBASER);
+}
+
+static inline void gicr_write_pendbaser(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_PENDBASER, val);
+}
+
 #endif /* __GICV3_PRIVATE_H__ */