fix(gicv3): incorrect impdef power down sequence

The GICR_WAKER.Sleep and GICR_WAKE.Quiescent functionality is solely
about flushing out the LPI cache and ensuring that the contents are
consistent with external memory.

Hence, as shown in GIC-700 TRM version r3p0, software must poll for
Quiescent bit only if LPIs are supported.

Change-Id: I7d69b208428e24d8a3ff30e81bd1a8ee3d0bda6e
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c
index 4489892..cc82ddb 100644
--- a/drivers/arm/gic/v3/arm_gicv3_common.c
+++ b/drivers/arm/gic/v3/arm_gicv3_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,10 +28,13 @@
 void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
 {
 	uintptr_t gicr_base = 0;
+	unsigned int typer_reg;
 
 	assert(gicv3_driver_data);
 	assert(gicv3_driver_data->rdistif_base_addrs);
+	assert(gicv3_driver_data->gicd_base != 0U);
 
+	typer_reg = gicd_read_typer(gicv3_driver_data->gicd_base);
 	/*
 	 * The GICR_WAKER.Sleep bit should be set only when both
 	 * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
@@ -60,9 +63,14 @@
 	 */
 	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
 
-	/* Wait until the GICR_WAKER.Quiescent bit is set */
-	while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
-		;
+	/*
+	 * If LPIs are supported, wait until the GICR_WAKER.Quiescent bit is
+	 * set.
+	 */
+	if ((typer_reg & TYPER_LPIS) != 0U) {
+		while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
+			;
+	}
 }
 
 /*
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index bfda31b..ca46eb1 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -150,6 +150,7 @@
 /* GICD_TYPER shifts and masks */
 #define	TYPER_ESPI		U(1 << 8)
 #define	TYPER_DVIS		U(1 << 18)
+#define	TYPER_LPIS		U(1 << 17)
 #define	TYPER_ESPI_RANGE_MASK	U(0x1f)
 #define	TYPER_ESPI_RANGE_SHIFT	U(27)
 #define	TYPER_ESPI_RANGE	U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT)