summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacky Bai <ping.bai@nxp.com>2020-01-20 14:58:44 +0800
committerJacky Bai <ping.bai@nxp.com>2020-02-09 20:58:49 +0800
commit9dec5b6f55f236304f40f2181e3784c01708a97a (patch)
tree1413e377dea3742698767e95c30d0b941d1d2af0
parentb13615aab1a2ccccf10edab071086ca16da70d87 (diff)
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 <ping.bai@nxp.com>
-rw-r--r--plat/imx/imx8m/gpc_common.c24
-rw-r--r--plat/imx/imx8m/imx8m_psci_common.c2
-rw-r--r--plat/imx/imx8m/imx8mm/gpc.c66
-rw-r--r--plat/imx/imx8m/imx8mn/gpc.c62
-rw-r--r--plat/imx/imx8m/include/gpc.h11
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 <stdbool.h>
#include <common/debug.h>
+#include <drivers/arm/tzc380.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
@@ -18,6 +19,7 @@
#include <gpc.h>
#include <imx_sip_svc.h>
+#include <plat_imx8.h>
#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 <stdbool.h>
#include <common/debug.h>
+#include <drivers/arm/tzc380.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
@@ -18,6 +19,7 @@
#include <gpc.h>
#include <imx_sip_svc.h>
+#include <plat_imx8.h>
#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);