summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2022-05-17 14:25:52 +0200
committerMax Krummenacher <max.krummenacher@toradex.com>2022-05-17 14:25:52 +0200
commit53b01a6d84ec33263b7a6f35b2ee339748686192 (patch)
treeed67dee911b28bc3f9cc5155c433f60d1222938e
parent835a8f67b2ca7aa3f2d05d6e6a1a51f7e1147266 (diff)
parent15e8ff164a8becfddb76cba2c68eeeae684cb398 (diff)
Merge remote-tracking branch 'nxp/imx_5.4.70_2.3.0' into HEAD
This merges in tag rel_imx_5.4.70_2.3.6. (rel_imx_5.4.70_2.3.7 didn't add any new commits to imx-atf.) Related-to: ELB-4410 Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r--plat/imx/imx8dxl/imx8dxl_psci.c39
-rw-r--r--plat/imx/imx8qm/imx8qm_psci.c42
-rw-r--r--plat/imx/imx8qx/imx8qx_psci.c39
3 files changed, 92 insertions, 28 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/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);
}
}