summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2017-07-18 16:12:45 +0100
committerSoby Mathew <soby.mathew@arm.com>2017-10-05 16:47:53 +0100
commitb258278eec8d8a7b7291d6d4ba03f21e4aac7d22 (patch)
tree0c506fc912c3645eca05077f6542cc43804897d2 /drivers
parentebf1ca10e466f39c45fa4ae4043fd53487d32362 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/arm/gic/v3/gicv3_main.c68
-rw-r--r--drivers/arm/gic/v3/gicv3_private.h56
2 files changed, 124 insertions, 0 deletions
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 83bf430f..7282bdc4 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -429,6 +429,74 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
}
/*****************************************************************************
+ * 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.
*****************************************************************************/
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index 7224e067..59298edf 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -314,4 +314,60 @@ static inline void gicr_write_pendbaser(uintptr_t base, unsigned int val)
mmio_write_32(base + GICR_PENDBASER, val);
}
+/*******************************************************************************
+ * GIC ITS functions to read and write entire ITS registers.
+ ******************************************************************************/
+static inline uint32_t gits_read_ctlr(uintptr_t base)
+{
+ return mmio_read_32(base + GITS_CTLR);
+}
+
+static inline void gits_write_ctlr(uintptr_t base, unsigned int val)
+{
+ mmio_write_32(base + GITS_CTLR, val);
+}
+
+static inline uint64_t gits_read_cbaser(uintptr_t base)
+{
+ return mmio_read_64(base + GITS_CBASER);
+}
+
+static inline void gits_write_cbaser(uintptr_t base, uint64_t val)
+{
+ mmio_write_32(base + GITS_CBASER, val);
+}
+
+static inline uint64_t gits_read_cwriter(uintptr_t base)
+{
+ return mmio_read_64(base + GITS_CWRITER);
+}
+
+static inline void gits_write_cwriter(uintptr_t base, uint64_t val)
+{
+ mmio_write_32(base + GITS_CWRITER, val);
+}
+
+static inline uint64_t gits_read_baser(uintptr_t base, unsigned int its_table_id)
+{
+ assert(its_table_id < 8);
+ return mmio_read_64(base + GITS_BASER + (8 * its_table_id));
+}
+
+static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, uint64_t val)
+{
+ assert(its_table_id < 8);
+ mmio_write_64(base + GITS_BASER + (8 * its_table_id), val);
+}
+
+/*
+ * Wait for Quiescent bit when GIC ITS is disabled
+ */
+static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base)
+{
+ assert(!(gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT));
+ while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0)
+ ;
+}
+
+
#endif /* __GICV3_PRIVATE_H__ */