mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
PM changes for am335x and am437x for v5.7 merge window
A series of changes from Dave Gerlach to enable basic cpuidle support for am335x and am437x based on generic cpuidle-arm driver. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEkgNvrZJU/QSQYIcQG9Q+yVyrpXMFAl5ic/ERHHRvbnlAYXRv bWlkZS5jb20ACgkQG9Q+yVyrpXM3ZQ/9Gc7VbcShorVrHH1jMCtE21vSDxNmYq0f tO8FfP8NP31g5Vsx7LiyhKmk80IKADpaDdih+UAkAxZ58ar8uJOaIYjdwKkho4Ra d+upw8z6GX6C3nknmrwFTT0+31/BHC7w6kPR15f1IVz9BmXimtxGww7LX+2U1T1l iqBMAaftqNiyci/Enj5RNAQa7ahyreIaJeBLJAP/9cYexkYvBtmPJkzV073ayqoz 43YP39ozTvSRzg+FTvxZMy6u8LUUoJWRETpXWSVAMIbnxAOiZnVvHOXYRtQzmAMj WNgwpV7oZ34thFpg6ks61Eu56p1qH0qvYhEYev8JRqGSJHZ6j+6dvb3Mu1yNySDm 36K8Ko+U39P4OB/v4xtC/eSQux/C7aBbP3zbgzf/68f0GmE0Y33JvKE0uc0/vGPE Wd3s0wpeeBlzNJOrdtfgwPCE64HpsbFyR+Ys9PCYQMBRjnKEuZJm0nagQKfgPdIZ icS2aZhlAMeUMEB2LulagExHlUxh9YIobyL0fmw1WJEmcl33KXU4ECEI1Br0iLw+ oVb3+W1tXuDjnVrL4+IocjfGNP21qcIAULCrEK3GWFm71IA6fKsilRfwSus+jW6n zpn7H3/VspNWyyKEGfKg84JCcYsBTLDrU3l6eG9flrUBnHM9YmQinMEuva4ovcwf h1W7qwaau2s= =nQLE -----END PGP SIGNATURE----- Merge tag 'omap-for-v5.7/pm33xx-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into arm/soc PM changes for am335x and am437x for v5.7 merge window A series of changes from Dave Gerlach to enable basic cpuidle support for am335x and am437x based on generic cpuidle-arm driver. * tag 'omap-for-v5.7/pm33xx-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: omap2plus_defconfig: Add CONFIG_ARM_CPUIDLE soc: ti: pm33xx: Add base cpuidle support ARM: OMAP2+: pm33xx-core: Extend platform_data ops for cpuidle ARM: OMAP2+: pm33xx-core: Add cpuidle_ops for am335x/am437x dt-bindings: arm: cpu: Add TI AM335x and AM437x enable method Link: https://lore.kernel.org/r/pull-1583511417-919838@atomide.com-2 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
f40969fb56
5 changed files with 160 additions and 8 deletions
|
@ -201,6 +201,8 @@ properties:
|
|||
- rockchip,rk3066-smp
|
||||
- socionext,milbeaut-m10v-smp
|
||||
- ste,dbx500-smp
|
||||
- ti,am3352
|
||||
- ti,am4372
|
||||
|
||||
cpu-release-addr:
|
||||
$ref: '/schemas/types.yaml#/definitions/uint64'
|
||||
|
|
|
@ -56,6 +56,8 @@ CONFIG_CPUFREQ_DT=m
|
|||
# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
|
||||
CONFIG_ARM_TI_CPUFREQ=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_ARM_CPUIDLE=y
|
||||
CONFIG_DT_IDLE_STATES=y
|
||||
CONFIG_KERNEL_MODE_NEON=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_ARM_CRYPTO=y
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
* Dave Gerlach
|
||||
*/
|
||||
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/platform_data/pm33xx.h>
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/platform_data/pm33xx.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/wkup_m3_ipc.h>
|
||||
|
@ -35,6 +38,14 @@ static struct clockdomain *gfx_l4ls_clkdm;
|
|||
static void __iomem *scu_base;
|
||||
static struct omap_hwmod *rtc_oh;
|
||||
|
||||
static int (*idle_fn)(u32 wfi_flags);
|
||||
|
||||
struct amx3_idle_state {
|
||||
int wfi_flags;
|
||||
};
|
||||
|
||||
static struct amx3_idle_state *idle_states;
|
||||
|
||||
static int am43xx_map_scu(void)
|
||||
{
|
||||
scu_base = ioremap(scu_a9_get_base(), SZ_256);
|
||||
|
@ -68,7 +79,7 @@ static int am43xx_check_off_mode_enable(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int amx3_common_init(void)
|
||||
static int amx3_common_init(int (*idle)(u32 wfi_flags))
|
||||
{
|
||||
gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
|
||||
per_pwrdm = pwrdm_lookup("per_pwrdm");
|
||||
|
@ -88,10 +99,12 @@ static int amx3_common_init(void)
|
|||
else
|
||||
omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
|
||||
|
||||
idle_fn = idle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am33xx_suspend_init(void)
|
||||
static int am33xx_suspend_init(int (*idle)(u32 wfi_flags))
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -102,12 +115,12 @@ static int am33xx_suspend_init(void)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = amx3_common_init();
|
||||
ret = amx3_common_init(idle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int am43xx_suspend_init(void)
|
||||
static int am43xx_suspend_init(int (*idle)(u32 wfi_flags))
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -117,11 +130,17 @@ static int am43xx_suspend_init(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = amx3_common_init();
|
||||
ret = amx3_common_init(idle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amx3_suspend_deinit(void)
|
||||
{
|
||||
idle_fn = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amx3_pre_suspend_common(void)
|
||||
{
|
||||
omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
|
||||
|
@ -201,6 +220,43 @@ static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int am33xx_cpu_suspend(int (*fn)(unsigned long), unsigned long args)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (omap_irq_pending() || need_resched())
|
||||
return ret;
|
||||
|
||||
ret = cpu_suspend(args, fn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int am43xx_cpu_suspend(int (*fn)(unsigned long), unsigned long args)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!scu_base)
|
||||
return 0;
|
||||
|
||||
scu_power_mode(scu_base, SCU_PM_DORMANT);
|
||||
ret = cpu_suspend(args, fn);
|
||||
scu_power_mode(scu_base, SCU_PM_NORMAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void amx3_begin_suspend(void)
|
||||
{
|
||||
cpu_idle_poll_ctrl(true);
|
||||
}
|
||||
|
||||
static void amx3_finish_suspend(void)
|
||||
{
|
||||
cpu_idle_poll_ctrl(false);
|
||||
}
|
||||
|
||||
|
||||
static struct am33xx_pm_sram_addr *amx3_get_sram_addrs(void)
|
||||
{
|
||||
if (soc_is_am33xx())
|
||||
|
@ -253,7 +309,11 @@ static void am43xx_prepare_rtc_resume(void)
|
|||
|
||||
static struct am33xx_pm_platform_data am33xx_ops = {
|
||||
.init = am33xx_suspend_init,
|
||||
.deinit = amx3_suspend_deinit,
|
||||
.soc_suspend = am33xx_suspend,
|
||||
.cpu_suspend = am33xx_cpu_suspend,
|
||||
.begin_suspend = amx3_begin_suspend,
|
||||
.finish_suspend = amx3_finish_suspend,
|
||||
.get_sram_addrs = amx3_get_sram_addrs,
|
||||
.save_context = am33xx_save_context,
|
||||
.restore_context = am33xx_restore_context,
|
||||
|
@ -265,7 +325,11 @@ static struct am33xx_pm_platform_data am33xx_ops = {
|
|||
|
||||
static struct am33xx_pm_platform_data am43xx_ops = {
|
||||
.init = am43xx_suspend_init,
|
||||
.deinit = amx3_suspend_deinit,
|
||||
.soc_suspend = am43xx_suspend,
|
||||
.cpu_suspend = am43xx_cpu_suspend,
|
||||
.begin_suspend = amx3_begin_suspend,
|
||||
.finish_suspend = amx3_finish_suspend,
|
||||
.get_sram_addrs = amx3_get_sram_addrs,
|
||||
.save_context = am43xx_save_context,
|
||||
.restore_context = am43xx_restore_context,
|
||||
|
@ -301,3 +365,64 @@ int __init amx3_common_pm_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init amx3_idle_init(struct device_node *cpu_node, int cpu)
|
||||
{
|
||||
struct device_node *state_node;
|
||||
struct amx3_idle_state states[CPUIDLE_STATE_MAX];
|
||||
int i;
|
||||
int state_count = 1;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
|
||||
if (!state_node)
|
||||
break;
|
||||
|
||||
if (!of_device_is_available(state_node))
|
||||
continue;
|
||||
|
||||
if (i == CPUIDLE_STATE_MAX) {
|
||||
pr_warn("%s: cpuidle states reached max possible\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
states[state_count].wfi_flags = 0;
|
||||
|
||||
if (of_property_read_bool(state_node, "ti,idle-wkup-m3"))
|
||||
states[state_count].wfi_flags |= WFI_FLAG_WAKE_M3 |
|
||||
WFI_FLAG_FLUSH_CACHE;
|
||||
|
||||
state_count++;
|
||||
}
|
||||
|
||||
idle_states = kcalloc(state_count, sizeof(*idle_states), GFP_KERNEL);
|
||||
if (!idle_states)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 1; i < state_count; i++)
|
||||
idle_states[i].wfi_flags = states[i].wfi_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amx3_idle_enter(unsigned long index)
|
||||
{
|
||||
struct amx3_idle_state *idle_state = &idle_states[index];
|
||||
|
||||
if (!idle_state)
|
||||
return -EINVAL;
|
||||
|
||||
if (idle_fn)
|
||||
idle_fn(idle_state->wfi_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cpuidle_ops amx3_cpuidle_ops __initdata = {
|
||||
.init = amx3_idle_init,
|
||||
.suspend = amx3_idle_enter,
|
||||
};
|
||||
|
||||
CPUIDLE_METHOD_OF_DECLARE(pm33xx_idle, "ti,am3352", &amx3_cpuidle_ops);
|
||||
CPUIDLE_METHOD_OF_DECLARE(pm43xx_idle, "ti,am4372", &amx3_cpuidle_ops);
|
||||
|
|
|
@ -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();
|
||||
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 @@ static int am33xx_pm_probe(struct platform_device *pdev)
|
|||
|
||||
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();
|
||||
|
|
|
@ -46,9 +46,13 @@ struct am33xx_pm_sram_addr {
|
|||
};
|
||||
|
||||
struct am33xx_pm_platform_data {
|
||||
int (*init)(void);
|
||||
int (*init)(int (*idle)(u32 wfi_flags));
|
||||
int (*deinit)(void);
|
||||
int (*soc_suspend)(unsigned int state, int (*fn)(unsigned long),
|
||||
unsigned long args);
|
||||
int (*cpu_suspend)(int (*fn)(unsigned long), unsigned long args);
|
||||
void (*begin_suspend)(void);
|
||||
void (*finish_suspend)(void);
|
||||
struct am33xx_pm_sram_addr *(*get_sram_addrs)(void);
|
||||
void __iomem *(*get_rtc_base_addr)(void);
|
||||
void (*save_context)(void);
|
||||
|
|
Loading…
Reference in a new issue