summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBai Ping <ping.bai@nxp.com>2018-06-19 13:11:13 +0800
committerBai Ping <ping.bai@nxp.com>2018-07-26 10:39:14 +0800
commit1541d8a9e3c7704b6ca0aa66f6dacf6e10b70bb6 (patch)
tree69382f3eeb8f238d868a4516c8fb9d31bd5c50b2
parent249d90ab990f152efd899dfc51dc755fde4b7d49 (diff)
plat: imx8mm: enable power domain support
Enable the power domain support on imx8mm. Signed-off-by: Bai Ping <ping.bai@nxp.com>
-rw-r--r--plat/imx/imx8mm/gpc.c269
-rw-r--r--plat/imx/imx8mm/imx8mm_bl31_setup.c5
-rw-r--r--plat/imx/imx8mm/platform.mk6
3 files changed, 208 insertions, 72 deletions
diff --git a/plat/imx/imx8mm/gpc.c b/plat/imx/imx8mm/gpc.c
index 71dc15f8..d11acee3 100644
--- a/plat/imx/imx8mm/gpc.c
+++ b/plat/imx/imx8mm/gpc.c
@@ -18,6 +18,7 @@
#include <psci.h>
#include <fsl_sip.h>
#include <soc.h>
+#include <delay_timer.h>
#define GPC_PGC_ACK_SEL_A53 0x24
#define GPC_IMR1_CORE0_A53 0x30
@@ -88,23 +89,11 @@
#define PLAT_PGC_PCR 0x900
#define NOC_PGC_PCR 0xa40
-#define MIPI_PGC 0xc00
-#define PCIE_PGC 0xc40
-#define OTG1_PGC 0xc80
-#define OTG2_PGC 0xcc0
-#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
-
#define MIPI_PWR_REQ (1 << 0)
#define PCIE_PWR_REQ (1 << 1)
#define OTG1_PWR_REQ (1 << 2)
#define OTG2_PWR_REQ (1 << 3)
+#define HSIOMIX_PWR_REQ (1 << 4)
#define GPU2D_PWR_REQ (1 << 6)
#define GPUMIX_PWR_REQ (1 << 7)
#define VPUMIX_PWR_REQ (1 << 8)
@@ -114,11 +103,13 @@
#define VPU_G2_PWR_REQ (1 << 12)
#define VPU_H1_PWR_REQ (1 << 13)
+#define HSIOMIX_ADB400_SYNC (0x3 << 5)
#define DISPMIX_ADB400_SYNC (1 << 7)
#define VPUMIX_ADB400_SYNC (1 << 8)
#define GPU3D_ADB400_SYNC (1 << 9)
#define GPU2D_ADB400_SYNC (1 << 10)
#define GPUMIX_ADB400_SYNC (1 << 11)
+#define HSIOMIX_ADB400_ACK (0x3 << 23)
#define DISPMIX_ADB400_ACK (1 << 25)
#define VPUMIX_ADB400_ACK (1 << 26)
#define GPU3D_ADB400_ACK (1 << 27)
@@ -129,6 +120,7 @@
#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
@@ -174,19 +166,39 @@ struct imx_pwr_domain {
bool init_on;
};
+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_PD_DOMAIN(MIPI),
+ IMX_MIX_DOMAIN(HSIOMIX),
IMX_PD_DOMAIN(PCIE),
IMX_PD_DOMAIN(OTG1),
IMX_PD_DOMAIN(OTG2),
- IMX_MIX_DOMAIN(GPU2D),
IMX_MIX_DOMAIN(GPUMIX),
IMX_MIX_DOMAIN(VPUMIX),
- IMX_MIX_DOMAIN(GPU3D),
- IMX_MIX_DOMAIN(DISPMIX),
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 uint32_t gpc_wake_irqs[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, };
@@ -194,6 +206,8 @@ static uint32_t gpc_imr_offset[] = { 0x30, 0x40, 0x1c0, 0x1d0, };
/* save gic dist&redist context when NOC wrapper is power down */
static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int pu_domain_status;
+
void imx_set_cpu_secure_entry(int core_id, uint64_t sec_entrypoint)
{
uint64_t temp_base;
@@ -533,10 +547,10 @@ void noc_wrapper_pre_suspend(unsigned int proc_num)
val |= (0x3 << 1);
mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
- /* FIXME enable NOC power down on real silicon */
-#if 0
- imx_noc_slot_config(true);
-#endif
+ /* noc can only be power down when all the pu domain is off */
+// if (!pu_domain_status)
+// /* enable noc power down */
+// imx_noc_slot_config(true);
/*
* gic redistributor context save must be called when
* the GIC CPU interface is disabled and before distributor save.
@@ -558,10 +572,11 @@ void noc_wrapper_post_resume(unsigned int proc_num)
val &= ~(0x3 << 1);
mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
- /* FIXME enable NOC power down on real silicon */
-#if 0
- imx_noc_slot_config(false);
-#endif
+ /* noc can only be power down when all the pu domain is off */
+// if (!pu_domain_status)
+// /* disable noc power down */
+// imx_noc_slot_config(false);
+
/* restore gic context */
plat_gic_restore(proc_num, &imx_gicv3_ctx);
}
@@ -606,25 +621,86 @@ static void imx_gpc_set_wake_irq(uint32_t hwirq, uint32_t on)
gpc_wake_irqs[idx] | mask;
}
+
static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
{
uint32_t val;
struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
- /* FIXME, will remove after runtime PM is ok */
- return;
-
if (on) {
- /* clear the PGC bit */
- val = mmio_read_32(IMX_GPC_BASE + pwr_domain->pgc_offset);
- val &= ~(1 << 0);
- mmio_write_32(IMX_GPC_BASE + pwr_domain->pgc_offset, val);
+ pu_domain_status |= (1 << domain_id);
+
+ /* HSIOMIX has no PU bit, so skip for it */
+ if (domain_id != HSIOMIX) {
+ /* clear the PGC bit */
+ val = mmio_read_32(IMX_GPC_BASE + pwr_domain->pgc_offset);
+ val &= ~(1 << 0);
+ mmio_write_32(IMX_GPC_BASE + pwr_domain->pgc_offset, val);
+
+ /* power up the domain */
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG);
+ val |= pwr_domain->pwr_req;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, val);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req);
+ }
+
+ if (domain_id == GPUMIX) {
+ /* power up GPU2D */
+ val = mmio_read_32(IMX_GPC_BASE + GPU2D_PGC);
+ val &= ~(1 << 0);
+ mmio_write_32(IMX_GPC_BASE + GPU2D_PGC, val);
+
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG);
+ val |= GPU2D_PWR_REQ;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, val);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU2D_PWR_REQ);
+
+ udelay(1);
+
+ /* power up GPU3D */
+ val = mmio_read_32(IMX_GPC_BASE + GPU3D_PGC);
+ val &= ~(1 << 0);
+ mmio_write_32(IMX_GPC_BASE + GPU3D_PGC, val);
+
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG);
+ val |= GPU3D_PWR_REQ;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, val);
- /* power up the domain */
- val = mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG);
- val |= pwr_domain->pwr_req;
- mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, val);
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU3D_PWR_REQ);
+
+ udelay(1);
+
+ /* assert reset */
+ mmio_write_32(0x30390040, 0x1);
+ udelay(10);
+ mmio_write_32(0x30390040, 0x0);
+ udelay(10);
+ }
+
+ /* vpu sft clock enable */
+ if (domain_id == VPUMIX) {
+ mmio_write_32(0x30390044, 0x1);
+ udelay(5);
+ mmio_write_32(0x30390044, 0x0);
+ udelay(5);
+
+ /* enable all clock */
+ mmio_write_32(0x38330004, 0x7);
+ }
+
+ if (domain_id == DISPMIX) {
+ /* special setting for DISPMIX */
+ mmio_write_32(0x303845d0, 0x3);
+ mmio_write_32(0x32e28004, 0x1fff);
+ mmio_write_32(0x32e28000, 0x7f);
+ mmio_write_32(0x32e28008, 0x30000);
+ }
/* handle the ADB400 sync */
if (!pwr_domain->init_on && pwr_domain->need_sync) {
@@ -636,25 +712,55 @@ static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
/* wait for adb power request ack */
while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
;
- }
- /* special fixup for dispmix */
- if (pwr_domain->pwr_req == DISPMIX_PWR_REQ) {
- mmio_write_32(0x303845d0, 0x3);
- mmio_write_32(0x32e28000, 0x7f);
- mmio_write_32(0x32e28004, 0x1fff);
- mmio_write_32(0x32e28008, 0x30000);
+ if (domain_id == GPUMIX) {
+ /* power up GPU2D ADB */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK);
+ val |= GPU2D_ADB400_SYNC;
+ mmio_write_32(IMX_GPC_BASE + GPC_PU_PWRHSK, val);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK))
+ ;
+
+ /* power up GPU3D ADB */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK);
+ val |= GPU3D_ADB400_SYNC;
+ mmio_write_32(IMX_GPC_BASE + GPC_PU_PWRHSK, val);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK))
+ ;
+ }
}
} else {
- /* TODO for bringup purpose */
- return;
- /* set the PGC bit */
- val = mmio_read_32(IMX_GPC_BASE + pwr_domain->pgc_offset);
- val |= (1 << 0);
- mmio_write_32(IMX_GPC_BASE + pwr_domain->pgc_offset, val);
+ pu_domain_status &= ~(1 << domain_id);
+
+ if (domain_id == OTG1 || domain_id == OTG2)
+ return;
/* handle the ADB400 sync */
if (!pwr_domain->init_on && pwr_domain->need_sync) {
+
+ /* GPU2D & GPU3D ADB power down */
+ if (domain_id == GPUMIX) {
+ val = mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK);
+ val &= ~GPU2D_ADB400_SYNC;
+ mmio_write_32(IMX_GPC_BASE + GPC_PU_PWRHSK, val);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK))
+ ;
+
+ val = mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK);
+ val &= ~GPU3D_ADB400_SYNC;
+ mmio_write_32(IMX_GPC_BASE + GPC_PU_PWRHSK, val);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK))
+ ;
+ }
+
/* set adb power down request */
val = mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK);
val &= ~(pwr_domain->adb400_sync);
@@ -665,10 +771,50 @@ static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
;
}
- /* power down the domain */
- val = mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG);
- val |= pwr_domain->pwr_req;
- mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, val);
+ if (domain_id == GPUMIX) {
+ /* power down GPU2D */
+ val = mmio_read_32(IMX_GPC_BASE + GPU2D_PGC);
+ val |= (1 << 0);
+ mmio_write_32(IMX_GPC_BASE + GPU2D_PGC, val);
+
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG);
+ val |= GPU2D_PWR_REQ;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, val);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU2D_PWR_REQ);
+
+ /* power down GPU3D */
+ val = mmio_read_32(IMX_GPC_BASE + GPU3D_PGC);
+ val |= (1 << 0);
+ mmio_write_32(IMX_GPC_BASE + GPU3D_PGC, val);
+
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG);
+ val |= GPU3D_PWR_REQ;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, val);
+
+ /* 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) {
+ if (domain_id == GPUMIX || domain_id == VPUMIX)
+ return;
+
+ /* set the PGC bit */
+ val = mmio_read_32(IMX_GPC_BASE + pwr_domain->pgc_offset);
+ val |= (1 << 0);
+ mmio_write_32(IMX_GPC_BASE + pwr_domain->pgc_offset, val);
+
+ /* power down the domain */
+ val = mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG);
+ val |= pwr_domain->pwr_req;
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, val);
+
+ /* 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;
@@ -708,23 +854,6 @@ void imx_gpc_init(void)
/*set all mix/PU in A53 domain */
mmio_write_32(IMX_GPC_BASE + GPC_PGC_CPU_0_1_MAPPING, 0xffff);
- /* TODO release dispmix sft reset */
- /* enable all the PU for bringup up purpose */
- mmio_write_32(0x30384450, 0x3);
- mmio_write_32(0x303844d0, 0x3);
- mmio_write_32(0x303844f0, 0x3);
- mmio_write_32(0x30384560, 0x3);
- mmio_write_32(0x30384570, 0x3);
- mmio_write_32(0x30384590, 0x3);
- mmio_write_32(0x303845a0, 0x3);
- mmio_write_32(0x303845d0, 0x3);
- mmio_write_32(0x30384630, 0x3);
- mmio_write_32(0x30384660, 0x3);
- mmio_write_32(IMX_GPC_BASE + 0xf8, 0x3fcf);
- mmio_write_32(0x32e28000, 0x7f);
- mmio_write_32(0x32e28004, 0x1fff);
- mmio_write_32(0x32e28008, 0x30000);
-
/* set SCU timming */
mmio_write_32(IMX_GPC_BASE + GPC_PGC_SCU_TIMMING,
(0x59 << 10) | 0x5B | (0x2 << 20));
diff --git a/plat/imx/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8mm/imx8mm_bl31_setup.c
index 43309d31..cc30c7a4 100644
--- a/plat/imx/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8mm/imx8mm_bl31_setup.c
@@ -13,6 +13,7 @@
#include <debug.h>
#include <stdbool.h>
#include <dram.h>
+#include <generic_delay_timer.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
@@ -269,6 +270,8 @@ void bl31_plat_arch_setup(void)
mmap_add_region(0x180000, 0x180000, 0x8000, MT_MEMORY | MT_RW);
+ mmap_add_region(0x38330000, 0x38330000, 0x100000, MT_DEVICE | MT_RW);
+
#if USE_COHERENT_MEM
mmap_add_region(BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_BASE,
BL31_COHERENT_RAM_LIMIT - BL31_COHERENT_RAM_BASE,
@@ -283,6 +286,8 @@ void bl31_plat_arch_setup(void)
void bl31_platform_setup(void)
{
+ generic_delay_timer_init();
+
/* select the CKIL source to 32K OSC */
mmio_write_32(0x30360124, 0x1);
diff --git a/plat/imx/imx8mm/platform.mk b/plat/imx/imx8mm/platform.mk
index a38b99c1..4597fb96 100644
--- a/plat/imx/imx8mm/platform.mk
+++ b/plat/imx/imx8mm/platform.mk
@@ -31,8 +31,10 @@ BL31_SOURCES += plat/imx/common/imx8_helpers.S \
lib/xlat_tables/xlat_tables_common.c \
lib/cpus/aarch64/cortex_a53.S \
drivers/console/aarch64/console.S \
- ${PLAT_GIC_SOURCES} \
- ${PLAT_DRAM_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${PLAT_GIC_SOURCES} \
+ ${PLAT_DRAM_SOURCES} \
drivers/arm/tzc/tzc380.c
ENABLE_PLAT_COMPAT := 0