GICv3: ITS architectural save and restore helpers

This patch adds functions to save and restore GICv3 ITS registers during
system suspend. Please note that the power management of GIC ITS is
implementation defined. These functions only implements the
architectural part of the ITS power management and they do not restore
memory structures or register content required to support ITS. Even if
the ITS implementation stores structures in memory, an implementation
defined power down sequence is likely to be required to flush some
internal ITS caches to memory. If such implementation defined sequence
is not followed, the platform must ensure that the ITS is not power
gated during system suspend.

Change-Id: I5f31e5541975aa7dcaab69b0b7f67583c0e27678
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_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 83bf430..7282bdc 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -429,6 +429,74 @@
 }
 
 /*****************************************************************************
+ * Function to save and disable the GIC ITS register context. The power
+ * management of GIC ITS is implementation-defined and this function doesn't
+ * save any memory structures required to support ITS. As the sequence to save
+ * this state is implementation defined, it should be executed in platform
+ * specific code. Calling this function alone and then powering down the GIC and
+ * ITS without implementing the aforementioned platform specific code will
+ * corrupt the ITS state.
+ *
+ * This function must be invoked after the GIC CPU interface is disabled.
+ *****************************************************************************/
+void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx)
+{
+	int i;
+
+	assert(gicv3_driver_data);
+	assert(IS_IN_EL3());
+	assert(its_ctx);
+	assert(gits_base);
+
+	its_ctx->gits_ctlr = gits_read_ctlr(gits_base);
+
+	/* Disable the ITS */
+	gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
+					(~GITS_CTLR_ENABLED_BIT));
+
+	/* Wait for quiescent state */
+	gits_wait_for_quiescent_bit(gits_base);
+
+	its_ctx->gits_cbaser = gits_read_cbaser(gits_base);
+	its_ctx->gits_cwriter = gits_read_cwriter(gits_base);
+
+	for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
+		its_ctx->gits_baser[i] = gits_read_baser(gits_base, i);
+}
+
+/*****************************************************************************
+ * Function to restore the GIC ITS register context. The power
+ * management of GIC ITS is implementation defined and this function doesn't
+ * restore any memory structures required to support ITS. The assumption is
+ * that these structures are in memory and are retained during system suspend.
+ *
+ * This must be invoked before the GIC CPU interface is enabled.
+ *****************************************************************************/
+void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx)
+{
+	int i;
+
+	assert(gicv3_driver_data);
+	assert(IS_IN_EL3());
+	assert(its_ctx);
+	assert(gits_base);
+
+	/* Assert that the GITS is disabled and quiescent */
+	assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0);
+	assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 1);
+
+	gits_write_cbaser(gits_base, its_ctx->gits_cbaser);
+	gits_write_cwriter(gits_base, its_ctx->gits_cwriter);
+
+	for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
+		gits_write_baser(gits_base, i, its_ctx->gits_baser[i]);
+
+	/* Restore the ITS CTLR but leave the ITS disabled */
+	gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
+			(~GITS_CTLR_ENABLED_BIT));
+}
+
+/*****************************************************************************
  * Function to save the GIC Redistributor register context. This function
  * must be invoked after CPU interface disable and prior to Distributor save.
  *****************************************************************************/