summaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorDave Gerlach <d-gerlach@ti.com>2019-12-13 04:07:54 +0100
committerTony Lindgren <tony@atomide.com>2020-02-27 18:27:28 +0100
commit6afaff1c6624f8901940db13709d0dac2b39e6da (patch)
treede96151745deca6105692294ec5d810b7f6e8adb /drivers/soc
parentARM: OMAP2+: pm33xx-core: Extend platform_data ops for cpuidle (diff)
downloadlinux-6afaff1c6624f8901940db13709d0dac2b39e6da.tar.xz
linux-6afaff1c6624f8901940db13709d0dac2b39e6da.zip
soc: ti: pm33xx: Add base cpuidle support
Some cpuidle C-states supported on am335x and am437x, like C1 on am335x, require the use of the wkup_m3_ipc driver, and all C-states beyond C0 on both platforms require the use of the SRAM sleep code. Pass am33xx_do_sram_idle as the idle function to the platform pm core to be used by the cpuidle-arm driver when entering cpuidle states. am33xx_do_sram_idle will detect when the wkup_m3 is needed and ping it if necessary before calling the final cpu_suspend op which will execute the SRAM code to put the cpu into idle. Finally, use the begin_suspend and finish_suspend platform ops to be called at the beginning and end of suspend path to allow use of cpu_idle_poll_ctrl. This prevents races between cpuidle and suspend paths trying to communicate with the wkup_m3, as during suspend we only want it configured for entry to suspend. Acked-by: Santosh Shilimkar <ssantosh@kernel.org> Signed-off-by: Dave Gerlach <d-gerlach@ti.com> Acked-by: Santosh Shilimkar <ssantosh@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/ti/pm33xx.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 19bdcaca1f21..de0123ec8ad6 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -130,6 +130,19 @@ static int am33xx_push_sram_idle(void)
return 0;
}
+static int am33xx_do_sram_idle(u32 wfi_flags)
+{
+ int ret = 0;
+
+ if (!m3_ipc || !pm_ops)
+ return 0;
+
+ if (wfi_flags & WFI_FLAG_WAKE_M3)
+ ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_IDLE);
+
+ return pm_ops->cpu_suspend(am33xx_do_wfi_sram, wfi_flags);
+}
+
static int __init am43xx_map_gic(void)
{
gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K);
@@ -260,6 +273,8 @@ static int am33xx_pm_begin(suspend_state_t state)
rtc_only_idle = 0;
}
+ pm_ops->begin_suspend();
+
switch (state) {
case PM_SUSPEND_MEM:
ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP);
@@ -301,6 +316,8 @@ static void am33xx_pm_end(void)
}
rtc_only_idle = 0;
+
+ pm_ops->finish_suspend();
}
static int am33xx_pm_valid(suspend_state_t state)
@@ -503,7 +520,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
#endif /* CONFIG_SUSPEND */
- ret = pm_ops->init(NULL);
+ ret = pm_ops->init(am33xx_do_sram_idle);
if (ret) {
dev_err(dev, "Unable to call core pm init!\n");
ret = -ENODEV;
@@ -522,6 +539,8 @@ err_free_sram:
static int am33xx_pm_remove(struct platform_device *pdev)
{
+ if (pm_ops->deinit)
+ pm_ops->deinit();
suspend_set_ops(NULL);
wkup_m3_ipc_put(m3_ipc);
am33xx_pm_free_sram();