feat(imx8m): add the PU power domain support on imx8mm/mn

Add the PU power domain support for imx8mm/mn.

Signed-off-by: Jacky Bai <ping.bai@nxp.com>
Change-Id: Ib88b4b5db956fdf2c77d2f2f3723d61a7060409d
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 21f7ec7..fae9750 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -37,6 +37,9 @@
 #if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
 	case IMX_SIP_DDR_DVFS:
 		return dram_dvfs_handler(smc_fid, handle, x1, x2, x3);
+	case IMX_SIP_GPC:
+		SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
+		break;
 #endif
 #if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx))
 	case  IMX_SIP_SRTC:
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index abe2bbd..c6e9879 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -8,6 +8,8 @@
 #define __IMX_SIP_SVC_H__
 
 /* SMC function IDs for SiP Service queries */
+#define IMX_SIP_GPC			0xC2000000
+
 #define IMX_SIP_CPUFREQ			0xC2000001
 #define IMX_SIP_SET_CPUFREQ		0x00
 
@@ -46,6 +48,9 @@
 #if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
 int dram_dvfs_handler(uint32_t smc_fid, void *handle,
 	u_register_t x1, u_register_t x2, u_register_t x3);
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1,
+		    u_register_t x2, u_register_t x3);
 #endif
 
 #if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
index 4ca9b02..e674d7a 100644
--- a/plat/imx/imx8m/gpc_common.c
+++ b/plat/imx/imx8m/gpc_common.c
@@ -9,6 +9,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/runtime_svc.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
 
@@ -22,6 +23,8 @@
 
 DEFINE_BAKERY_LOCK(gpc_lock);
 
+#define FSL_SIP_CONFIG_GPC_PM_DOMAIN		0x03
+
 #pragma weak imx_set_cpu_pwr_off
 #pragma weak imx_set_cpu_pwr_on
 #pragma weak imx_set_cpu_lpm
@@ -289,4 +292,17 @@
 			mmio_clrbits_32(IMX_ANAMIX_BASE + pll[i].reg, pll[i].override_mask);
 		}
 	}
+}
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3)
+{
+	switch (x1) {
+	case FSL_SIP_CONFIG_GPC_PM_DOMAIN:
+		imx_gpc_pm_domain_enable(x2, x3);
+		break;
+	default:
+		return SMC_UNK;
+	}
+
+	return 0;
 }
diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c
index ab59292..e3057ae 100644
--- a/plat/imx/imx8m/imx8mm/gpc.c
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,6 +19,332 @@
 #include <gpc.h>
 #include <imx_sip_svc.h>
 
+#define MIPI_PWR_REQ		BIT(0)
+#define PCIE_PWR_REQ		BIT(1)
+#define OTG1_PWR_REQ		BIT(2)
+#define OTG2_PWR_REQ		BIT(3)
+#define HSIOMIX_PWR_REQ		BIT(4)
+#define GPU2D_PWR_REQ		BIT(6)
+#define GPUMIX_PWR_REQ		BIT(7)
+#define VPUMIX_PWR_REQ		BIT(8)
+#define GPU3D_PWR_REQ		BIT(9)
+#define DISPMIX_PWR_REQ		BIT(10)
+#define VPU_G1_PWR_REQ		BIT(11)
+#define VPU_G2_PWR_REQ		BIT(12)
+#define VPU_H1_PWR_REQ		BIT(13)
+
+#define HSIOMIX_ADB400_SYNC	(0x3 << 5)
+#define DISPMIX_ADB400_SYNC	BIT(7)
+#define VPUMIX_ADB400_SYNC	BIT(8)
+#define GPU3D_ADB400_SYNC	BIT(9)
+#define GPU2D_ADB400_SYNC	BIT(10)
+#define GPUMIX_ADB400_SYNC	BIT(11)
+#define HSIOMIX_ADB400_ACK	(0x3 << 23)
+#define DISPMIX_ADB400_ACK	BIT(25)
+#define VPUMIX_ADB400_ACK	BIT(26)
+#define GPU3D_ADB400_ACK	BIT(27)
+#define GPU2D_ADB400_ACK	BIT(28)
+#define GPUMIX_ADB400_ACK	BIT(29)
+
+#define MIPI_PGC		0xc00
+#define PCIE_PGC		0xc40
+#define OTG1_PGC		0xc80
+#define OTG2_PGC		0xcc0
+#define HSIOMIX_PGC	        0xd00
+#define GPU2D_PGC		0xd80
+#define GPUMIX_PGC		0xdc0
+#define VPUMIX_PGC		0xe00
+#define GPU3D_PGC		0xe40
+#define DISPMIX_PGC		0xe80
+#define VPU_G1_PGC		0xec0
+#define VPU_G2_PGC		0xf00
+#define VPU_H1_PGC		0xf40
+
+enum pu_domain_id {
+	HSIOMIX,
+	PCIE,
+	OTG1,
+	OTG2,
+	GPUMIX,
+	VPUMIX,
+	VPU_G1,
+	VPU_G2,
+	VPU_H1,
+	DISPMIX,
+	MIPI,
+	/* below two domain only for ATF internal use */
+	GPU2D,
+	GPU3D,
+	MAX_DOMAINS,
+};
+
+/* PU domain */
+static struct imx_pwr_domain pu_domains[] = {
+	IMX_MIX_DOMAIN(HSIOMIX, false),
+	IMX_PD_DOMAIN(PCIE, false),
+	IMX_PD_DOMAIN(OTG1, true),
+	IMX_PD_DOMAIN(OTG2, true),
+	IMX_MIX_DOMAIN(GPUMIX, false),
+	IMX_MIX_DOMAIN(VPUMIX, false),
+	IMX_PD_DOMAIN(VPU_G1, false),
+	IMX_PD_DOMAIN(VPU_G2, false),
+	IMX_PD_DOMAIN(VPU_H1, false),
+	IMX_MIX_DOMAIN(DISPMIX, false),
+	IMX_PD_DOMAIN(MIPI, false),
+	/* below two domain only for ATF internal use */
+	IMX_MIX_DOMAIN(GPU2D, false),
+	IMX_MIX_DOMAIN(GPU3D, false),
+};
+
+static unsigned int pu_domain_status;
+
+#define GPU_RCR		0x40
+#define VPU_RCR		0x44
+
+#define VPU_CTL_BASE		0x38330000
+#define BLK_SFT_RSTN_CSR	0x0
+#define H1_SFT_RSTN		BIT(2)
+#define G1_SFT_RSTN		BIT(1)
+#define G2_SFT_RSTN		BIT(0)
+
+#define DISP_CTL_BASE		0x32e28000
+
+void vpu_sft_reset_assert(uint32_t domain_id)
+{
+	uint32_t val;
+
+	val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+	switch (domain_id) {
+	case VPU_G1:
+		val &= ~G1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_G2:
+		val &= ~G2_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_H1:
+		val &= ~H1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	default:
+		break;
+	}
+}
+
+void vpu_sft_reset_deassert(uint32_t domain_id)
+{
+	uint32_t val;
+
+	val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+	switch (domain_id) {
+	case VPU_G1:
+		val |= G1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_G2:
+		val |= G2_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_H1:
+		val |= H1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	default:
+		break;
+	}
+}
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	if (domain_id >= MAX_DOMAINS) {
+		return;
+	}
+
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+	if (on) {
+		pu_domain_status |= (1 << domain_id);
+
+		if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+		    domain_id == VPU_H1) {
+			vpu_sft_reset_assert(domain_id);
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* clear the PGC bit */
+			mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power up the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+
+		if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+		    domain_id == VPU_H1) {
+			vpu_sft_reset_deassert(domain_id);
+			/* dealy for a while to make sure reset done */
+			udelay(100);
+		}
+
+		if (domain_id == GPUMIX) {
+			/* assert reset */
+			mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x1);
+
+			/* power up GPU2D */
+			mmio_clrbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU2D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU2D_PWR_REQ) {
+				;
+			}
+
+			udelay(1);
+
+			/* power up GPU3D */
+			mmio_clrbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU3D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU3D_PWR_REQ) {
+				;
+			}
+
+			udelay(10);
+			/* release the gpumix reset */
+			mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x0);
+			udelay(10);
+		}
+
+		/* vpu sft clock enable */
+		if (domain_id == VPUMIX) {
+			mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x1);
+			udelay(5);
+			mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x0);
+			udelay(5);
+
+			/* enable all clock */
+			mmio_write_32(VPU_CTL_BASE + 0x4, 0x7);
+		}
+
+		if (domain_id == DISPMIX) {
+			/* special setting for DISPMIX */
+			mmio_write_32(DISP_CTL_BASE + 0x4, 0x1fff);
+			mmio_write_32(DISP_CTL_BASE, 0x7f);
+			mmio_write_32(DISP_CTL_BASE + 0x8, 0x30000);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		if (domain_id == GPUMIX) {
+			/* power up GPU2D ADB */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+				;
+			}
+
+			/* power up GPU3D ADB */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+				;
+			}
+		}
+	} else {
+		pu_domain_status &= ~(1 << domain_id);
+
+		if (domain_id == OTG1 || domain_id == OTG2) {
+			return;
+		}
+
+		/* GPU2D & GPU3D ADB power down */
+		if (domain_id == GPUMIX) {
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+				;
+			}
+
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+				/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+				;
+			}
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		if (domain_id == GPUMIX) {
+			/* power down GPU2D */
+			mmio_setbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU2D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU2D_PWR_REQ) {
+				;
+			}
+
+			/* power down GPU3D */
+			mmio_setbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU3D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU3D_PWR_REQ) {
+				;
+			}
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* set the PGC bit */
+			mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power down the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+	}
+}
+
 void imx_gpc_init(void)
 {
 	unsigned int val;
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index b34e01b..ba0db0c 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -37,6 +37,7 @@
 	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
 	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW), /* OCRAM_S */
 	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX */
+	MAP_REGION_FLAT(IMX_VPUMIX_BASE, IMX_VPUMIX_SIZE, MT_DEVICE | MT_RW), /* VPUMIX */
 	{0},
 };
 
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index c181212..84d86b9 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -86,7 +86,7 @@
 #define IMX_AIPSTZ4			U(0x32df0000)
 
 #define IMX_AIPS_BASE			U(0x30000000)
-#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_AIPS_SIZE			U(0x3000000)
 #define IMX_GPV_BASE			U(0x32000000)
 #define IMX_GPV_SIZE			U(0x800000)
 #define IMX_AIPS1_BASE			U(0x30200000)
@@ -108,6 +108,8 @@
 #define IMX_DDR_IPS_BASE		U(0x3d000000)
 #define IMX_DDR_IPS_SIZE		U(0x1800000)
 #define IMX_ROM_BASE			U(0x0)
+#define IMX_VPUMIX_BASE                U(0x38330000)
+#define IMX_VPUMIX_SIZE                U(0x100000)
 
 #define GPV_BASE			U(0x32000000)
 #define GPV_SIZE			U(0x800000)
diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c
index 37d4226..4fd75dd 100644
--- a/plat/imx/imx8m/imx8mn/gpc.c
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2020 NXP
+ * Copyright 2019-2022 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,124 @@
 
 #define CCGR(x)		(0x4000 + (x) * 0x10)
 
+#define MIPI_PWR_REQ		BIT(0)
+#define OTG1_PWR_REQ		BIT(2)
+#define HSIOMIX_PWR_REQ		BIT(4)
+#define GPUMIX_PWR_REQ		BIT(7)
+#define DISPMIX_PWR_REQ		BIT(10)
+
+#define HSIOMIX_ADB400_SYNC	BIT(5)
+#define DISPMIX_ADB400_SYNC	BIT(7)
+#define GPUMIX_ADB400_SYNC	(0x5 << 9)
+#define HSIOMIX_ADB400_ACK	BIT(23)
+#define DISPMIX_ADB400_ACK	BIT(25)
+#define GPUMIX_ADB400_ACK	(0x5 << 27)
+
+#define MIPI_PGC		0xc00
+#define OTG1_PGC		0xc80
+#define HSIOMIX_PGC	        0xd00
+#define GPUMIX_PGC		0xdc0
+#define DISPMIX_PGC		0xe80
+
+enum pu_domain_id {
+	HSIOMIX,
+	OTG1 = 2,
+	GPUMIX = 4,
+	DISPMIX = 9,
+	MIPI,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[11] = {
+	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+	[OTG1] = IMX_PD_DOMAIN(OTG1, true),
+	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+	[DISPMIX] = IMX_MIX_DOMAIN(DISPMIX, false),
+	[MIPI] = IMX_PD_DOMAIN(MIPI, true),
+};
+
+static unsigned int pu_domain_status;
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	if (domain_id > MIPI) {
+		return;
+	}
+
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+	if (on) {
+		if (pwr_domain->need_sync) {
+			pu_domain_status |= (1 << domain_id);
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* clear the PGC bit */
+			mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power up the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+
+		if (domain_id == DISPMIX) {
+			/* de-reset bus_blk clk and
+			 * enable bus_blk clk
+			 */
+			mmio_write_32(0x32e28000, 0x100);
+			mmio_write_32(0x32e28004, 0x100);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+	} else {
+		pu_domain_status &= ~(1 << domain_id);
+
+		if (domain_id == OTG1) {
+			return;
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* set the PGC bit */
+			mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power down the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+	}
+}
+
 void imx_gpc_init(void)
 {
 	unsigned int val;
diff --git a/plat/imx/imx8m/imx8mn/include/platform_def.h b/plat/imx/imx8m/imx8mn/include/platform_def.h
index 8106229..dbb4416 100644
--- a/plat/imx/imx8m/imx8mn/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -72,7 +72,7 @@
 #define IMX_AIPSTZ4			U(0x32df0000)
 
 #define IMX_AIPS_BASE			U(0x30000000)
-#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_AIPS_SIZE			U(0x3000000)
 #define IMX_GPV_BASE			U(0x32000000)
 #define IMX_GPV_SIZE			U(0x800000)
 #define IMX_AIPS1_BASE			U(0x30200000)
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
index 3d68b94..452e788 100644
--- a/plat/imx/imx8m/imx8mp/gpc.c
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -170,7 +170,7 @@
 	}
 }
 
-static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
 {
 	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
 	unsigned int i;
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 16129d1..a41030e 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -70,5 +70,6 @@
 void imx_set_rbc_count(void);
 void imx_clear_rbc_count(void);
 void imx_anamix_override(bool enter);
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on);
 
 #endif /*IMX8M_GPC_H */