summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plat/imx/imx8dxl/imx8dxl_psci.c39
-rw-r--r--plat/imx/imx8m/ddr/clock.c3
-rw-r--r--plat/imx/imx8m/ddr/ddr4_dvfs.c18
-rw-r--r--plat/imx/imx8m/hab.c10
-rw-r--r--plat/imx/imx8m/imx8m_csu.c4
-rw-r--r--plat/imx/imx8m/imx8mp/include/platform_def.h1
-rw-r--r--plat/imx/imx8m/imx8mp/platform.mk3
-rw-r--r--plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c5
-rw-r--r--plat/imx/imx8qm/imx8qm_psci.c42
-rw-r--r--plat/imx/imx8qx/imx8qx_psci.c39
10 files changed, 130 insertions, 34 deletions
diff --git a/plat/imx/imx8dxl/imx8dxl_psci.c b/plat/imx/imx8dxl/imx8dxl_psci.c
index 6e6a6ad6..764c536f 100644
--- a/plat/imx/imx8dxl/imx8dxl_psci.c
+++ b/plat/imx/imx8dxl/imx8dxl_psci.c
@@ -18,6 +18,8 @@
#include "../../common/sci/imx8_mu.h"
+#define IRQSTR_PLAT_OS_MU_IRQ 119
+
const static int ap_core_index[PLATFORM_CORE_COUNT] = {
SC_R_A35_0, SC_R_A35_1
};
@@ -40,12 +42,6 @@ static void imx_enable_irqstr_wakeup(void)
irq_mask = dist_ctx->gicd_isenabler[i];
mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x2c - 0x4 * i, irq_mask);
}
-
- /* set IRQSTR low power mode */
- if (imx_is_wakeup_src_irqsteer())
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
- else
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
static void imx_disable_irqstr_wakeup(void)
@@ -128,6 +124,11 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ uint32_t irqstr_mu_reg = (IRQSTR_PLAT_OS_MU_IRQ / 32) - 1;
+ uint32_t irqstr_mu_mask = (1 << (IRQSTR_PLAT_OS_MU_IRQ % 32));
+ uint32_t irqstr_mu_status, reg;
+ bool irqstr_mu_wakeup = false;
+
plat_gic_cpuif_disable();
/* save gic context */
@@ -152,12 +153,32 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
/* Put GIC in OFF mode. */
sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
- if (imx_is_wakeup_src_irqsteer())
+
+ if (!imx_is_wakeup_src_irqsteer())
sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ /*
+ * Check to see if the MU interrupt is pending in the IRQSTR_SCU2
+ * If interrupt is pending it implies the wakeup interrupt triggered
+ * during suspend process and we should wakeup. Changing the wakeup src
+ * to SC_PM_WAKE_SRC_IRQSTEER will ensure the AP core wakes up as soon
+ * as WFI is executed.
+ */
+ reg = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0x2c - 4 * irqstr_mu_reg);
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x2c - 4 * irqstr_mu_reg, reg | irqstr_mu_mask);
+ irqstr_mu_status = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0x8c - 4 * irqstr_mu_reg);
+ if (irqstr_mu_status & irqstr_mu_mask)
+ irqstr_mu_wakeup = true;
else
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x2c - 4 * irqstr_mu_reg, reg);
+
+ /* set IRQSTR low power mode. IRQSTR is already in ON state at this point*/
+ if (imx_is_wakeup_src_irqsteer() || irqstr_mu_wakeup) {
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ } else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
}
diff --git a/plat/imx/imx8m/ddr/clock.c b/plat/imx/imx8m/ddr/clock.c
index 7ddc25cc..7eb989f9 100644
--- a/plat/imx/imx8m/ddr/clock.c
+++ b/plat/imx/imx8m/ddr/clock.c
@@ -84,6 +84,9 @@ void dram_pll_init(unsigned int drate)
mmio_clrbits_32(DRAM_PLL_CTRL, (1 << 9));
switch (drate) {
+ case 4000:
+ mmio_write_32(DRAM_PLL_CTRL + 0x4, (250 << 12) | (3 << 4) | 1);
+ break;
case 3200:
mmio_write_32(DRAM_PLL_CTRL + 0x4, (200 << 12) | (3 << 4) | 1);
break;
diff --git a/plat/imx/imx8m/ddr/ddr4_dvfs.c b/plat/imx/imx8m/ddr/ddr4_dvfs.c
index 52dd2066..d1c0d750 100644
--- a/plat/imx/imx8m/ddr/ddr4_dvfs.c
+++ b/plat/imx/imx8m/ddr/ddr4_dvfs.c
@@ -18,8 +18,22 @@ void ddr4_mr_write(uint32_t mr, uint32_t data, uint32_t mr_type,
* 1. Poll MRSTAT.mr_wr_busy until it is 0 to make sure
* that there is no outstanding MR transAction.
*/
- while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1)
- ;
+
+ /*
+ * ERR050712:
+ * When performing a software driven MR access, the following sequence
+ * must be done automatically before performing other APB register accesses.
+ * 1. Set MRCTRL0.mr_wr=1
+ * 2. Check for MRSTAT.mr_wr_busy=0. If not, go to step (2)
+ * 3. Check for MRSTAT.mr_wr_busy=0 again (for the second time). If not, go to step (2)
+ */
+ mmio_setbits_32(DDRC_MRCTRL0(0), BIT(31));
+
+ do {
+ while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1)
+ ;
+
+ } while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1);
/*
* 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank
diff --git a/plat/imx/imx8m/hab.c b/plat/imx/imx8m/hab.c
index 17ad4207..cc74cf07 100644
--- a/plat/imx/imx8m/hab.c
+++ b/plat/imx/imx8m/hab.c
@@ -90,6 +90,15 @@ int imx_hab_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
hab_rvt_failsafe_t *hab_rvt_failsafe;
hab_rvt_check_target_t *hab_rvt_check_target;
+/* work around gcc 12.1 false positives */
+/*
+| plat/imx/imx8m/hab.c: In function 'imx_hab_handler':
+| plat/imx/imx8m/hab.c:64:57: error: array subscript 0 is outside array bounds of 'uint32_t[0]' {aka 'unsigned int[]'} [-Werror=array-bounds]
+| 64 | #define HAB_RVT_CHECK_TARGET_ARM64 ((unsigned long)*(uint32_t *)(HAB_RVT_BASE + 0x18))
+| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
switch(x1) {
case IMX_SIP_HAB_AUTHENTICATE:
hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
@@ -117,6 +126,7 @@ int imx_hab_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
return SMC_UNK;
};
+#pragma GCC diagnostic pop
return 0;
}
diff --git a/plat/imx/imx8m/imx8m_csu.c b/plat/imx/imx8m/imx8m_csu.c
index 3405fa59..b1f6886e 100644
--- a/plat/imx/imx8m/imx8m_csu.c
+++ b/plat/imx/imx8m/imx8m_csu.c
@@ -34,14 +34,14 @@ void imx_csu_init(const struct imx_csu_cfg *csu_cfg)
if (val & CSU_SA_LOCK(csu->idx))
break;
mmio_clrsetbits_32(CSU_SA_REG(csu->idx), CSU_SA_CFG(0x1, csu->idx),
- CSU_SA_CFG(csu->hp | (csu->lock << 0x1), csu->idx));
+ CSU_SA_CFG(csu->sa | (csu->lock << 0x1), csu->idx));
break;
case CSU_HPCONTROL:
val = mmio_read_32(CSU_HPCONTROL_REG(csu->idx));
if (val & CSU_HPCONTROL_LOCK(csu->idx))
break;
mmio_clrsetbits_32(CSU_HPCONTROL_REG(csu->idx), CSU_HPCONTROL_CFG(0x1, csu->idx),
- CSU_HPCONTROL_CFG(csu->hp | (csu->lock << 0x1), csu->idx));
+ CSU_HPCONTROL_CFG(csu->hpctrl | (csu->lock << 0x1), csu->idx));
break;
default:
break;
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
index d32789c5..dc5e6627 100644
--- a/plat/imx/imx8m/imx8mp/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -51,7 +51,6 @@
#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */
-#define IMX_BOOT_UART_BASE U(0x30890000)
#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */
#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index c668ca70..f5a55948 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -66,3 +66,6 @@ $(eval $(call add_define,BL32_SIZE))
ifeq (${SPD},trusty)
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
endif
+
+IMX_BOOT_UART_BASE ?= 0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
index f4c45895..7b320f0e 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -94,7 +94,10 @@ static void imx8mq_soc_info_init(void)
ocotp_val = mmio_read_32(IMX_OCOTP_BASE + OCOTP_SOC_INFO_B1);
if (ocotp_val == 0xff0055aa) {
imx_soc_revision &= ~0xff;
- imx_soc_revision |= 0x21;
+ if (rom_version == 0x22)
+ imx_soc_revision |= 0x22;
+ else
+ imx_soc_revision |= 0x21;
return;
}
}
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
index 65cad5b0..befc1abb 100644
--- a/plat/imx/imx8qm/imx8qm_psci.c
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -26,7 +26,10 @@
#define SYSTEM_PWR_STATE(state) \
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
-const static int ap_core_index[PLATFORM_CORE_COUNT] = {
+
+#define IRQSTR_PLAT_OS_MU_IRQ 209
+
+const static int ap_core_index[PLATFORM_CLUSTER0_CORE_COUNT + PLATFORM_CLUSTER1_CORE_COUNT] = {
SC_R_A53_0, SC_R_A53_1, SC_R_A53_2,
SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
};
@@ -49,12 +52,6 @@ static void imx_enable_irqstr_wakeup(void)
irq_mask = dist_ctx->gicd_isenabler[i];
mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
}
-
- /* set IRQSTR low power mode */
- if (imx_is_wakeup_src_irqsteer())
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
- else
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
static void imx_disable_irqstr_wakeup(void)
@@ -157,6 +154,11 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
}
if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ uint32_t irqstr_mu_reg = (IRQSTR_PLAT_OS_MU_IRQ / 32) - 1;
+ uint32_t irqstr_mu_mask = (1 << (IRQSTR_PLAT_OS_MU_IRQ % 32));
+ uint32_t irqstr_mu_status, reg;
+ bool irqstr_mu_wakeup = false;
+
plat_gic_cpuif_disable();
/* save gic context */
@@ -195,14 +197,34 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
sc_pm_set_cpu_resume(ipc_handle,
ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
true, BL31_BASE);
- if (imx_is_wakeup_src_irqsteer())
+
+ if (!imx_is_wakeup_src_irqsteer())
sc_pm_req_cpu_low_power_mode(ipc_handle,
ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ /*
+ * Check to see if the MU interrupt is pending in the IRQSTR_SCU2
+ * If interrupt is pending it implies the wakeup interrupt triggered
+ * during suspend process and we should wakeup. Changing the wakeup src
+ * to SC_PM_WAKE_SRC_IRQSTEER will ensure the AP core wakes up as soon
+ * as WFI is executed.
+ */
+ reg = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg);
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg, reg | irqstr_mu_mask);
+ irqstr_mu_status = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0xbc - 4 * irqstr_mu_reg);
+ if (irqstr_mu_status & irqstr_mu_mask)
+ irqstr_mu_wakeup = true;
else
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg, reg);
+
+ /* set IRQSTR low power mode. IRQSTR is already in ON state at this point*/
+ if (imx_is_wakeup_src_irqsteer() || irqstr_mu_wakeup) {
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
sc_pm_req_cpu_low_power_mode(ipc_handle,
ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ } else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
}
diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
index 24a46f7a..1926044f 100644
--- a/plat/imx/imx8qx/imx8qx_psci.c
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -18,6 +18,8 @@
#include "../../common/sci/imx8_mu.h"
+#define IRQSTR_PLAT_OS_MU_IRQ 209
+
const static int ap_core_index[PLATFORM_CORE_COUNT] = {
SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
};
@@ -40,12 +42,6 @@ static void imx_enable_irqstr_wakeup(void)
irq_mask = dist_ctx->gicd_isenabler[i];
mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
}
-
- /* set IRQSTR low power mode */
- if (imx_is_wakeup_src_irqsteer())
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
- else
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
static void imx_disable_irqstr_wakeup(void)
@@ -128,6 +124,11 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ uint32_t irqstr_mu_reg = (IRQSTR_PLAT_OS_MU_IRQ / 32) - 1;
+ uint32_t irqstr_mu_mask = (1 << (IRQSTR_PLAT_OS_MU_IRQ % 32));
+ uint32_t irqstr_mu_status, reg;
+ bool irqstr_mu_wakeup = false;
+
plat_gic_cpuif_disable();
/* save gic context */
@@ -152,12 +153,32 @@ void imx_domain_suspend(const psci_power_state_t *target_state)
/* Put GIC in OFF mode. */
sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
- if (imx_is_wakeup_src_irqsteer())
+
+ if (!imx_is_wakeup_src_irqsteer())
sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ /*
+ * Check to see if the MU interrupt is pending in the IRQSTR_SCU2
+ * If interrupt is pending it implies the wakeup interrupt triggered
+ * during suspend process and we should wakeup. Changing the wakeup src
+ * to SC_PM_WAKE_SRC_IRQSTEER will ensure the AP core wakes up as soon
+ * as WFI is executed.
+ */
+ reg = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg);
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg, reg | irqstr_mu_mask);
+ irqstr_mu_status = mmio_read_32(IMX_WUP_IRQSTR_BASE + 0xbc - 4 * irqstr_mu_reg);
+ if (irqstr_mu_status & irqstr_mu_mask)
+ irqstr_mu_wakeup = true;
else
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 4 * irqstr_mu_reg, reg);
+
+ /* set IRQSTR low power mode. IRQSTR is already in ON state at this point*/
+ if (imx_is_wakeup_src_irqsteer() || irqstr_mu_wakeup) {
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ } else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
}
}