diff options
Diffstat (limited to 'plat')
-rw-r--r-- | plat/imx/imx8mm/gpc.c | 105 | ||||
-rw-r--r-- | plat/imx/imx8mm/imx8mm_bl31_setup.c | 5 | ||||
-rw-r--r-- | plat/imx/imx8mm/imx8mm_psci.c | 6 | ||||
-rw-r--r-- | plat/imx/imx8mm/include/soc.h | 5 |
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 */ |