summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plat/imx/imx8mm/gpc.c105
-rw-r--r--plat/imx/imx8mm/imx8mm_bl31_setup.c5
-rw-r--r--plat/imx/imx8mm/imx8mm_psci.c6
-rw-r--r--plat/imx/imx8mm/include/soc.h5
4 files changed, 87 insertions, 34 deletions
diff --git a/plat/imx/imx8mm/gpc.c b/plat/imx/imx8mm/gpc.c
index f35eae38..e6db4116 100644
--- a/plat/imx/imx8mm/gpc.c
+++ b/plat/imx/imx8mm/gpc.c
@@ -131,6 +131,9 @@
#define VPU_G2_PGC 0xf00
#define VPU_H1_PGC 0xf40
+#define M4RCR 0xC
+#define SRC_SCR_M4C_NON_SCLR_RST_MASK (1 << 0)
+
#define IMX_PD_DOMAIN(name) \
{ \
.pwr_req = name##_PWR_REQ, \
@@ -209,6 +212,21 @@ static struct plat_gic_ctx imx_gicv3_ctx;
static unsigned int pu_domain_status;
+bool imx_is_m4_enabled(void)
+{
+ return !( mmio_read_32(IMX_SRC_BASE + M4RCR)
+ & SRC_SCR_M4C_NON_SCLR_RST_MASK);
+}
+
+#define M4_LPA_ACTIVE 0x5555
+#define M4_LPA_IDLE 0x0
+#define SRC_GPR9 0x94
+
+bool imx_m4_lpa_active(void)
+{
+ return mmio_read_32(IMX_SRC_BASE + SRC_GPR9) & M4_LPA_ACTIVE;
+}
+
void imx_set_cpu_secure_entry(int core_id, uint64_t sec_entrypoint)
{
uint64_t temp_base;
@@ -462,6 +480,20 @@ void imx_set_sys_lpm(bool retention)
SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN);
mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ if (imx_is_m4_enabled() && imx_m4_lpa_active()) {
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val |= SLPCR_A53_FASTWUP_STOP;
+ mmio_write_32(IMX_GPC_BASE + 0x14, val);
+ return;
+ }
+
+ if (!imx_is_m4_enabled()) {
+ /* mask M4 DSM trigger if M4 is NOT enabled */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_M4);
+ val |= 1 << 31;
+ mmio_write_32(IMX_GPC_BASE + LPCR_M4, val);
+ }
}
void imx_set_rbc_count(void)
@@ -490,6 +522,8 @@ void imx_anamix_pre_suspend()
{
int i;
uint32_t pll_ctrl;
+ if (imx_is_m4_enabled() && imx_m4_lpa_active())
+ return;
/* bypass all the plls before enter DSM mode */
for (i = 0; i < ARRAY_SIZE(pll_ctrl_offset); i++) {
pll_ctrl = mmio_read_32(IMX_ANAMIX_BASE + pll_ctrl_offset[i]);
@@ -514,6 +548,8 @@ void imx_anamix_post_resume(void)
{
int i;
uint32_t pll_ctrl;
+ if (imx_is_m4_enabled() && imx_m4_lpa_active())
+ return;
/* unbypass all the plls after exit from DSM mode */
for (i = 0; i < ARRAY_SIZE(pll_ctrl_offset); i++) {
pll_ctrl = mmio_read_32(IMX_ANAMIX_BASE + pll_ctrl_offset[i]);
@@ -555,20 +591,22 @@ void noc_wrapper_pre_suspend(unsigned int proc_num)
{
uint32_t val;
- /* enable MASTER1 & MASTER2 power down in A53 LPM mode */
- val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
- val &= ~(1 << 7);
- val &= ~(1 << 8);
- mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+ if (!imx_is_m4_enabled() || !imx_m4_lpa_active()) {
+ /* enable MASTER1 & MASTER2 power down in A53 LPM mode */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val &= ~(1 << 7);
+ val &= ~(1 << 8);
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
- val = mmio_read_32(IMX_GPC_BASE + MST_CPU_MAPPING);
- val |= (0x3 << 1);
- mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
+ val = mmio_read_32(IMX_GPC_BASE + MST_CPU_MAPPING);
+ val |= (0x3 << 1);
+ mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
- /* 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);
+ /* 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.
@@ -580,24 +618,25 @@ void noc_wrapper_post_resume(unsigned int proc_num)
{
uint32_t val;
- /* disable MASTER1 & MASTER2 power down in A53 LPM mode */
- val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
- val |= (1 << 7);
- val |= (1 << 8);
- mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+ if (!imx_is_m4_enabled() || !imx_m4_lpa_active()) {
+ /* disable MASTER1 & MASTER2 power down in A53 LPM mode */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val |= (1 << 7);
+ val |= (1 << 8);
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
- val = mmio_read_32(IMX_GPC_BASE + MST_CPU_MAPPING);
- val &= ~(0x3 << 1);
- mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
+ val = mmio_read_32(IMX_GPC_BASE + MST_CPU_MAPPING);
+ val &= ~(0x3 << 1);
+ mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
- /* noc can only be power down when all the pu domain is off */
- if (!pu_domain_status) {
- /* re-init the tz380 if resume from noc power down */
- imx8mm_tz380_init();
- /* disable noc power down */
- imx_noc_slot_config(false);
+ /* noc can only be power down when all the pu domain is off */
+ if (!pu_domain_status) {
+ /* re-init the tz380 if resume from noc power down */
+ imx8mm_tz380_init();
+ /* disable noc power down */
+ imx_noc_slot_config(false);
+ }
}
-
/* restore gic context */
plat_gic_restore(proc_num, &imx_gicv3_ctx);
}
@@ -630,6 +669,13 @@ void imx_set_sys_wakeup(int last_core, bool pdn)
mmio_write_32(IMX_GPC_BASE + gpc_imr_offset[last_core] + i * 4,
irq_mask);
}
+
+ /* enable the MU wakeup */
+ if (imx_is_m4_enabled()) {
+ val = mmio_read_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + 0x8);
+ val &= ~(1 << 24);
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + 0x8, val);
+ }
}
static void imx_gpc_set_wake_irq(uint32_t hwirq, uint32_t on)
@@ -864,11 +910,6 @@ void imx_gpc_init(void)
val &= ~(0x3 << 1);
mmio_write_32(IMX_GPC_BASE + MST_CPU_MAPPING, val);
- /* mask M4 DSM trigger if M4 is NOT enabled */
- val = mmio_read_32(IMX_GPC_BASE + LPCR_M4);
- val |= 1 << 31;
- mmio_write_32(IMX_GPC_BASE + LPCR_M4, val);
-
/*set all mix/PU in A53 domain */
mmio_write_32(IMX_GPC_BASE + GPC_PGC_CPU_0_1_MAPPING, 0xffff);
diff --git a/plat/imx/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8mm/imx8mm_bl31_setup.c
index 587b74dd..9b3145c4 100644
--- a/plat/imx/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8mm/imx8mm_bl31_setup.c
@@ -234,6 +234,11 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
#endif
bl31_tzc380_setup();
+ /* Assign M4 to domain 1 */
+ mmio_write_32(IMX_RDC_BASE + 0x204, 0x1);
+ mmio_write_32(IMX_RDC_BASE + 0x518, 0xfc);
+ mmio_write_32(IMX_RDC_BASE + 0x5A4, 0xf3);
+
#if defined (CSU_RDC_TEST)
csu_test();
rdc_test();
diff --git a/plat/imx/imx8mm/imx8mm_psci.c b/plat/imx/imx8mm/imx8mm_psci.c
index eb82ec33..ec3a8c1a 100644
--- a/plat/imx/imx8mm/imx8mm_psci.c
+++ b/plat/imx/imx8mm/imx8mm_psci.c
@@ -130,7 +130,8 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
/* do system level power mode setting */
if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
- dram_enter_retention();
+ if (!imx_is_m4_enabled() || !imx_m4_lpa_active())
+ dram_enter_retention();
imx_set_sys_lpm(true);
imx_anamix_pre_suspend();
noc_wrapper_pre_suspend(core_id);
@@ -151,7 +152,8 @@ void imx_domain_suspend_finish(const psci_power_state_t *target_state)
imx_set_sys_wakeup(core_id, false);
imx_anamix_post_resume();
imx_clear_rbc_count();
- dram_exit_retention();
+ if (!imx_is_m4_enabled() || !imx_m4_lpa_active())
+ dram_exit_retention();
noc_wrapper_post_resume(core_id);
}
diff --git a/plat/imx/imx8mm/include/soc.h b/plat/imx/imx8mm/include/soc.h
index 475b0bc8..00052d32 100644
--- a/plat/imx/imx8mm/include/soc.h
+++ b/plat/imx/imx8mm/include/soc.h
@@ -7,6 +7,8 @@
#ifndef __IMX_SOC_H
#define __IMX_SOC_H
+#include <stdbool.h>
+
void imx_gpc_set_m_core_pgc(unsigned int cpu, bool pdn);
void imx_anamix_pre_suspend(void);
void imx_anamix_post_resume(void);
@@ -30,4 +32,7 @@ void noc_wrapper_post_resume(unsigned int proc_num);
void ddrc_enter_retention(void);
void ddrc_exit_retention(void);
+bool imx_is_m4_enabled(void);
+bool imx_m4_lpa_active(void);
+
#endif /* __IMX_SOC_H */