From 9dec5b6f55f236304f40f2181e3784c01708a97a Mon Sep 17 00:00:00 2001 From: Jacky Bai Date: Mon, 20 Jan 2020 14:58:44 +0800 Subject: plat: imx8m: Enable the noc power down support on imx8m Enable the NOC wrapper power down support for SoC that have switchable NOC power domain. Signed-off-by: Jacky Bai --- plat/imx/imx8m/gpc_common.c | 24 ++++++++------ plat/imx/imx8m/imx8m_psci_common.c | 2 ++ plat/imx/imx8m/imx8mm/gpc.c | 66 ++++++++++++++++++++++++++++++++++++++ plat/imx/imx8m/imx8mn/gpc.c | 62 +++++++++++++++++++++++++++++++++++ plat/imx/imx8m/include/gpc.h | 11 +++++++ 5 files changed, 155 insertions(+), 10 deletions(-) diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c index 091cf451..9dc1ec80 100644 --- a/plat/imx/imx8m/gpc_common.c +++ b/plat/imx/imx8m/gpc_common.c @@ -24,6 +24,8 @@ static uint32_t gpc_imr_offset[] = { 0x30, 0x40, 0x1c0, 0x1d0, }; DEFINE_BAKERY_LOCK(gpc_lock); +struct plat_gic_ctx imx_gicv3_ctx; + #pragma weak imx_set_cpu_pwr_off #pragma weak imx_set_cpu_pwr_on #pragma weak imx_set_cpu_lpm @@ -211,15 +213,20 @@ void imx_set_sys_wakeup(unsigned int last_core, bool pdn) } } -#pragma weak imx_noc_slot_config -/* - * this function only need to be override by platform - * that support noc power down, for example: imx8mm. - * otherwize, keep it empty. - */ void imx_noc_slot_config(bool pdn) { - + if (pdn) { + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), NOC_PDN_SLT_CTRL); + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), NOC_PUP_SLT_CTRL); + /* clear a53's PDN ack, use NOC's PDN ack */ + mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xffff, NOC_PGC_PDN_ACK); + mmio_setbits_32(IMX_GPC_BASE + NOC_PGC_PCR, 0x1); + } else { + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), NOC_PDN_SLT_CTRL); + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), NOC_PUP_SLT_CTRL); + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK); + mmio_clrbits_32(IMX_GPC_BASE + NOC_PGC_PCR, 0x1); + } } /* this is common for all imx8m soc */ @@ -237,9 +244,6 @@ void imx_set_sys_lpm(unsigned int last_core, bool retention) mmio_write_32(IMX_GPC_BASE + SLPCR, val); - /* config the noc power down */ - imx_noc_slot_config(retention); - /* config wakeup irqs' mask in gpc */ imx_set_sys_wakeup(last_core, retention); } diff --git a/plat/imx/imx8m/imx8m_psci_common.c b/plat/imx/imx8m/imx8m_psci_common.c index fc9a585e..fc649d51 100644 --- a/plat/imx/imx8m/imx8m_psci_common.c +++ b/plat/imx/imx8m/imx8m_psci_common.c @@ -124,6 +124,7 @@ void imx_domain_suspend(const psci_power_state_t *target_state) imx_set_sys_lpm(core_id, true); dram_enter_retention(); imx_anamix_override(true); + imx_noc_wrapper_pre_suspend(core_id); } } @@ -133,6 +134,7 @@ void imx_domain_suspend_finish(const psci_power_state_t *target_state) unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { + imx_noc_wrapper_post_resume(core_id); imx_anamix_override(false); dram_exit_retention(); imx_set_sys_lpm(core_id, false); diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c index a1bbe35b..afd39051 100644 --- a/plat/imx/imx8m/imx8mm/gpc.c +++ b/plat/imx/imx8m/imx8mm/gpc.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include #define MIPI_PWR_REQ BIT(0) #define PCIE_PWR_REQ BIT(1) @@ -60,6 +62,8 @@ #define VPU_G2_PGC 0xf00 #define VPU_H1_PGC 0xf40 +#define CCGR(x) (0x4000 + (x) * 16) + enum pu_domain_id { HSIOMIX, PCIE, @@ -327,6 +331,68 @@ void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on) pwr_domain->init_on = false; } +static void imx8mm_tz380_init(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + + +void imx_noc_wrapper_pre_suspend(unsigned int proc_num) +{ + /* enable MASTER1 & MASTER2 power down in A53 LPM mode */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC, MASTER1_LPM_HSK | MASTER2_LPM_HSK); + mmio_setbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, MASTER1_MAPPING | MASTER2_MAPPING); + + /* 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); + + /* + * below clocks must be enabled to make sure RDC MRCs + * can be successfully reloaded. + */ + mmio_setbits_32(IMX_CCM_BASE + 0xa300, (0x1 << 28)); + mmio_write_32(IMX_CCM_BASE + CCGR(5), 0x3); + mmio_write_32(IMX_CCM_BASE + CCGR(37), 0x3); + mmio_write_32(IMX_CCM_BASE + CCGR(87), 0x3); + } + + /* + * gic redistributor context save must be called when + * the GIC CPU interface is disabled and before distributor save. + */ + plat_gic_save(proc_num, &imx_gicv3_ctx); +} + +void imx_noc_wrapper_post_resume(unsigned int proc_num) +{ + /* disable MASTER1 & MASTER2 power down in A53 LPM mode */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC, MASTER1_LPM_HSK | MASTER2_LPM_HSK); + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, MASTER1_MAPPING | MASTER2_MAPPING); + + /* 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); +} + void imx_gpc_init(void) { unsigned int val; diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c index df921f4e..db48f803 100644 --- a/plat/imx/imx8m/imx8mn/gpc.c +++ b/plat/imx/imx8m/imx8mn/gpc.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include #define MIPI_PWR_REQ BIT(0) #define OTG1_PWR_REQ BIT(2) @@ -38,6 +40,8 @@ #define GPUMIX_PGC 0xdc0 #define DISPMIX_PGC 0xe80 +#define CCGR(x) (0x4000 + (x) * 16) + enum pu_domain_id { HSIOMIX, OTG1 = 2, @@ -126,6 +130,64 @@ void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on) pwr_domain->init_on = false; } +static void imx8mm_tz380_init(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) + | TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void imx_noc_wrapper_pre_suspend(unsigned int proc_num) +{ + /* enable MASTER1 & MASTER2 power down in A53 LPM mode */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC, MASTER1_LPM_HSK | MASTER2_LPM_HSK); + mmio_setbits_32(IMX_GPC_BASE+ MST_CPU_MAPPING, MASTER1_MAPPING | MASTER2_MAPPING); + + /* 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); + /* + * below clocks must be enabled to make sure RDC MRCs + * can be successfully reloaded. + */ + mmio_setbits_32(IMX_CCM_BASE + 0xa300, (0x1 << 28)); + mmio_write_32(IMX_CCM_BASE + CCGR(5), 0x3); + mmio_write_32(IMX_CCM_BASE + CCGR(87), 0x3); + } + /* + * gic redistributor context save must be called when + * the GIC CPU interface is disabled and before distributor save. + */ + plat_gic_save(proc_num, &imx_gicv3_ctx); +} + +void imx_noc_wrapper_post_resume(unsigned int proc_num) +{ + /* disable MASTER1 & MASTER2 power down in A53 LPM mode */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC, MASTER1_LPM_HSK | MASTER2_LPM_HSK); + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, MASTER1_MAPPING | MASTER2_MAPPING); + + /* 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); +} + void imx_gpc_init(void) { unsigned int val; diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h index a3319c64..66db543e 100644 --- a/plat/imx/imx8m/include/gpc.h +++ b/plat/imx/imx8m/include/gpc.h @@ -30,6 +30,7 @@ #define A53_CORE0_PGC 0x800 #define A53_PLAT_PGC 0x900 #define PLAT_PGC_PCR 0x900 +#define NOC_PGC_PCR 0xa40 #define PGC_SCU_TIMING 0x910 #define MASK_DSM_TRIGGER_A53 BIT(31) @@ -42,6 +43,8 @@ #define CPU_CLOCK_ON_LPM BIT(14) #define A53_CLK_ON_LPM BIT(14) #define MASTER0_LPM_HSK BIT(6) +#define MASTER1_LPM_HSK BIT(7) +#define MASTER2_LPM_HSK BIT(8) #define L2PGE BIT(31) #define EN_L2_WFI_PDN BIT(5) @@ -61,6 +64,10 @@ #define A53_DUMMY_PUP_ACK BIT(31) #define A53_PLAT_PDN_ACK BIT(2) #define A53_PLAT_PUP_ACK BIT(18) +#define NOC_PDN_SLT_CTRL BIT(10) +#define NOC_PUP_SLT_CTRL BIT(11) +#define NOC_PGC_PDN_ACK BIT(3) +#define NOC_PGC_PUP_ACK BIT(19) #define PLAT_PUP_SLT_CTRL BIT(9) #define PLAT_PDN_SLT_CTRL BIT(8) @@ -125,6 +132,8 @@ struct pll_override { DECLARE_BAKERY_LOCK(gpc_lock); +extern struct plat_gic_ctx imx_gicv3_ctx; + /* function declare */ void imx_gpc_init(void); void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint); @@ -140,6 +149,8 @@ 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); +void imx_noc_wrapper_pre_suspend(unsigned int proc_num); +void imx_noc_wrapper_post_resume(unsigned int proc_num); #if defined(PLAT_imx8mq) void imx_gpc_set_a53_core_awake(uint32_t core_id); -- cgit v1.2.3