summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacky Bai <ping.bai@nxp.com>2019-12-11 16:26:59 +0800
committerJacky Bai <ping.bai@nxp.com>2020-01-03 13:14:03 +0800
commit1536c58dd15bf0a75a93075fae67ed5480404851 (patch)
tree20aa59be198338ae77d22afc644f344358a3a833
parentcbab087cbffa801869ec9c448a1b0cd0bef47091 (diff)
plat: 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>
-rw-r--r--plat/imx/common/imx_sip_svc.c3
-rw-r--r--plat/imx/common/include/imx_sip_svc.h5
-rw-r--r--plat/imx/imx8m/gpc_common.c16
-rw-r--r--plat/imx/imx8m/imx8mm/gpc.c308
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c1
-rw-r--r--plat/imx/imx8m/imx8mm/include/platform_def.h4
-rw-r--r--plat/imx/imx8m/imx8mn/gpc.c107
-rw-r--r--plat/imx/imx8m/imx8mn/include/platform_def.h2
-rw-r--r--plat/imx/imx8m/include/gpc.h28
9 files changed, 472 insertions, 2 deletions
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 85231d10..c9c723f2 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -34,6 +34,9 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid,
#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn)
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 26daa8c6..dbf6ab87 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
@@ -43,6 +45,9 @@ int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn)
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_imx8qm) || defined(PLAT_imx8qx))
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
index 81755a70..d8d349fb 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>
@@ -16,6 +17,8 @@
#include <imx8m_psci.h>
#include <plat_imx8.h>
+#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03
+
static uint32_t gpc_imr_offset[] = { 0x30, 0x40, 0x1c0, 0x1d0, };
#pragma weak imx_set_cpu_pwr_off
@@ -272,3 +275,16 @@ void imx_anamix_override(bool enter)
}
}
}
+
+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 ab59292e..97b05efa 100644
--- a/plat/imx/imx8m/imx8mm/gpc.c
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -19,6 +19,314 @@
#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,
+};
+
+/* PU domain */
+static struct imx_pwr_domain pu_domains[] = {
+ IMX_MIX_DOMAIN(HSIOMIX),
+ IMX_PD_DOMAIN(PCIE),
+ IMX_PD_DOMAIN(OTG1),
+ IMX_PD_DOMAIN(OTG2),
+ IMX_MIX_DOMAIN(GPUMIX),
+ IMX_MIX_DOMAIN(VPUMIX),
+ IMX_PD_DOMAIN(VPU_G1),
+ IMX_PD_DOMAIN(VPU_G2),
+ IMX_PD_DOMAIN(VPU_H1),
+ IMX_MIX_DOMAIN(DISPMIX),
+ IMX_PD_DOMAIN(MIPI),
+ /* below two domain only for ATF internal use */
+ IMX_MIX_DOMAIN(GPU2D),
+ IMX_MIX_DOMAIN(GPU3D),
+};
+
+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)
+{
+ 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->init_on && 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->init_on && 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)
+ ;
+ }
+ }
+
+ pwr_domain->init_on = false;
+}
+
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 3ed4dee0..293daaf3 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -34,6 +34,7 @@ static const mmap_region_t imx_mmap[] = {
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 1c46c91d..cd184207 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -62,7 +62,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)
@@ -84,6 +84,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 9f9607d9..3e74708e 100644
--- a/plat/imx/imx8m/imx8mn/gpc.c
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -19,6 +19,113 @@
#include <gpc.h>
#include <imx_sip_svc.h>
+#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),
+ [OTG1] = IMX_PD_DOMAIN(OTG1),
+ [GPUMIX] = IMX_MIX_DOMAIN(GPUMIX),
+ [DISPMIX] = IMX_MIX_DOMAIN(DISPMIX),
+ [MIPI] = IMX_PD_DOMAIN(MIPI),
+};
+
+static unsigned int pu_domain_status;
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+ struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+ if (on) {
+ 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->init_on && 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->init_on && 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);
+ }
+ }
+
+ pwr_domain->init_on = false;
+}
+
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 101205d6..6d49bf66 100644
--- a/plat/imx/imx8m/imx8mn/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -62,7 +62,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/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index f27ab6a3..d7e72228 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -90,6 +90,33 @@
#define IRQ_IMR_NUM 4
#define IMR_MASK_ALL 0xffffffff
+#define IMX_PD_DOMAIN(name) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .need_sync = false, \
+ .init_on = true, \
+ }
+
+#define IMX_MIX_DOMAIN(name) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .adb400_sync = name##_ADB400_SYNC, \
+ .adb400_ack = name##_ADB400_ACK, \
+ .need_sync = true, \
+ .init_on = true, \
+ }
+
+struct imx_pwr_domain {
+ uint32_t pwr_req;
+ uint32_t adb400_sync;
+ uint32_t adb400_ack;
+ uint32_t pgc_offset;
+ bool need_sync;
+ bool init_on;
+};
+
/* function declare */
void imx_gpc_init(void);
void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
@@ -104,5 +131,6 @@ void imx_set_sys_lpm(unsigned last_core, bool retention);
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 */