Commit 6afaff1c authored by Dave Gerlach's avatar Dave Gerlach Committed by Tony Lindgren

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: default avatarSantosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: default avatarDave Gerlach <d-gerlach@ti.com>
Acked-by: default avatarSantosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 65880ab1
...@@ -130,6 +130,19 @@ static int am33xx_push_sram_idle(void) ...@@ -130,6 +130,19 @@ static int am33xx_push_sram_idle(void)
return 0; 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) static int __init am43xx_map_gic(void)
{ {
gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K); gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K);
...@@ -260,6 +273,8 @@ static int am33xx_pm_begin(suspend_state_t state) ...@@ -260,6 +273,8 @@ static int am33xx_pm_begin(suspend_state_t state)
rtc_only_idle = 0; rtc_only_idle = 0;
} }
pm_ops->begin_suspend();
switch (state) { switch (state) {
case PM_SUSPEND_MEM: case PM_SUSPEND_MEM:
ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP); ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP);
...@@ -301,6 +316,8 @@ static void am33xx_pm_end(void) ...@@ -301,6 +316,8 @@ static void am33xx_pm_end(void)
} }
rtc_only_idle = 0; rtc_only_idle = 0;
pm_ops->finish_suspend();
} }
static int am33xx_pm_valid(suspend_state_t state) static int am33xx_pm_valid(suspend_state_t state)
...@@ -503,7 +520,7 @@ static int am33xx_pm_probe(struct platform_device *pdev) ...@@ -503,7 +520,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
suspend_wfi_flags |= WFI_FLAG_WAKE_M3; suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
#endif /* CONFIG_SUSPEND */ #endif /* CONFIG_SUSPEND */
ret = pm_ops->init(NULL); ret = pm_ops->init(am33xx_do_sram_idle);
if (ret) { if (ret) {
dev_err(dev, "Unable to call core pm init!\n"); dev_err(dev, "Unable to call core pm init!\n");
ret = -ENODEV; ret = -ENODEV;
...@@ -522,6 +539,8 @@ static int am33xx_pm_probe(struct platform_device *pdev) ...@@ -522,6 +539,8 @@ static int am33xx_pm_probe(struct platform_device *pdev)
static int am33xx_pm_remove(struct platform_device *pdev) static int am33xx_pm_remove(struct platform_device *pdev)
{ {
if (pm_ops->deinit)
pm_ops->deinit();
suspend_set_ops(NULL); suspend_set_ops(NULL);
wkup_m3_ipc_put(m3_ipc); wkup_m3_ipc_put(m3_ipc);
am33xx_pm_free_sram(); am33xx_pm_free_sram();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment