mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
Omap PM changes via Kevin Hilman <khilman@linaro.org>:
OMAP PM cleanups for v3.10 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRuLeiAAoJEBvUPslcq6Vz2HMP/1PPRVv0KK7ErdVAyYlR82Qq TQgYbu2601z77gNLVWT2QOf8vlSFcutiEMJ/pdEblvWeQoehdFKU0FZTvZwD1Fwp qXu/BdKqlmk/EmmIWHG6wix9yeQiH/Ee6hPDCTMT8z4nVPISg2R1e125j2Zr1gs1 F+ilhuFcCsmJVB6uu4yU2D0fdwFvh6MArAwryQv5iGyHJo9r5ZC90hZ1a/0fWeVH 7OdOesPEhTHXdxvMb4JpQsBBVB5ajBfej/5qiRXckvbaS2ADnVJBfCdvky5lCo2u Da9Ln+xA2XfdqO30HJFfVBAkS1T4d191oaDM+v/pQxEcMyHPHm76gwoQ4am8ZKgv cLYwZddtvwtGAOK8FlgFU+YSbvoSzyWAdGo89dtC4fcFLXhwHfABHBwHHBmVmvm2 IiBcsg7iIZCQuAplmTOrgEPAnkgOJOMLOvRJEX9FVvj9mVUA0TNJSMt7w4sj4fEf UIUXXCI/cbLjl//puuZf3wvq/VxrymYlxPyiVlr3f/aZ21XBYzyqp1L4z2tjwLt3 vtNVXxc4OEGflF+k52qOp5xbGrqDUBumtlRyePmXM6u9/y3MsN+TZrlSuiG4Ig5d r5PfHXWEe/eFjqjSUZXiEvEwYHV92Q7GpwBXOVGhFOaDpROA1pKB4jMATj9/bjKR 745XKPPscKG3AtsnK60q =9SyZ -----END PGP SIGNATURE----- Merge tag 'omap-for-v3.11/pm-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc From Tony Lindgren: Omap PM changes via Kevin Hilman <khilman@linaro.org>: OMAP PM cleanups for v3.10 * tag 'omap-for-v3.11/pm-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP4+: PM: Consolidate OMAP4 PM code to re-use it for OMAP5 ARM: OMAP4+: Make secondary_startup function name more consistent ARM: OMAP4+: PM: Consolidate MPU subsystem PM code for re-use ARM: OMAP4: PM: Avoid expensive cpu_suspend() path for all CPU power states except off
This commit is contained in:
commit
eb25862dee
@ -237,8 +237,8 @@ extern void omap_do_wfi(void);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Needed for secondary core boot */
|
||||
extern void omap_secondary_startup(void);
|
||||
extern void omap_secondary_startup_4460(void);
|
||||
extern void omap4_secondary_startup(void);
|
||||
extern void omap4460_secondary_startup(void);
|
||||
extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
|
||||
extern void omap_auxcoreboot_addr(u32 cpu_addr);
|
||||
extern u32 omap_read_auxcoreboot0(void);
|
||||
|
@ -49,7 +49,7 @@ END(omap5_secondary_startup)
|
||||
* The primary core will update this flag using a hardware
|
||||
* register AuxCoreBoot0.
|
||||
*/
|
||||
ENTRY(omap_secondary_startup)
|
||||
ENTRY(omap4_secondary_startup)
|
||||
hold: ldr r12,=0x103
|
||||
dsb
|
||||
smc #0 @ read from AuxCoreBoot0
|
||||
@ -64,9 +64,9 @@ hold: ldr r12,=0x103
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(omap_secondary_startup)
|
||||
ENDPROC(omap4_secondary_startup)
|
||||
|
||||
ENTRY(omap_secondary_startup_4460)
|
||||
ENTRY(omap4460_secondary_startup)
|
||||
hold_2: ldr r12,=0x103
|
||||
dsb
|
||||
smc #0 @ read from AuxCoreBoot0
|
||||
@ -101,4 +101,4 @@ hold_2: ldr r12,=0x103
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(omap_secondary_startup_4460)
|
||||
ENDPROC(omap4460_secondary_startup)
|
||||
|
@ -71,10 +71,43 @@ struct omap4_cpu_pm_info {
|
||||
void (*secondary_startup)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cpu_pm_ops - CPU pm operations
|
||||
* @finish_suspend: CPU suspend finisher function pointer
|
||||
* @resume: CPU resume function pointer
|
||||
* @scu_prepare: CPU Snoop Control program function pointer
|
||||
*
|
||||
* Structure holds functions pointer for CPU low power operations like
|
||||
* suspend, resume and scu programming.
|
||||
*/
|
||||
struct cpu_pm_ops {
|
||||
int (*finish_suspend)(unsigned long cpu_state);
|
||||
void (*resume)(void);
|
||||
void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
|
||||
static struct powerdomain *mpuss_pd;
|
||||
static void __iomem *sar_base;
|
||||
|
||||
static int default_finish_suspend(unsigned long cpu_state)
|
||||
{
|
||||
omap_do_wfi();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_cpu_resume(void)
|
||||
{}
|
||||
|
||||
static void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state)
|
||||
{}
|
||||
|
||||
struct cpu_pm_ops omap_pm_ops = {
|
||||
.finish_suspend = default_finish_suspend,
|
||||
.resume = dummy_cpu_resume,
|
||||
.scu_prepare = dummy_scu_prepare,
|
||||
};
|
||||
|
||||
/*
|
||||
* Program the wakeup routine address for the CPU0 and CPU1
|
||||
* used for OFF or DORMANT wakeup.
|
||||
@ -158,11 +191,12 @@ static void save_l2x0_context(void)
|
||||
{
|
||||
u32 val;
|
||||
void __iomem *l2x0_base = omap4_get_l2cache_base();
|
||||
|
||||
val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
|
||||
__raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
|
||||
val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
|
||||
__raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
|
||||
if (l2x0_base) {
|
||||
val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
|
||||
__raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
|
||||
val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
|
||||
__raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void save_l2x0_context(void)
|
||||
@ -225,14 +259,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
|
||||
|
||||
cpu_clear_prev_logic_pwrst(cpu);
|
||||
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
|
||||
set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
|
||||
scu_pwrst_prepare(cpu, power_state);
|
||||
set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
|
||||
omap_pm_ops.scu_prepare(cpu, power_state);
|
||||
l2x0_pwrst_prepare(cpu, save_state);
|
||||
|
||||
/*
|
||||
* Call low level function with targeted low power state.
|
||||
*/
|
||||
cpu_suspend(save_state, omap4_finish_suspend);
|
||||
if (save_state)
|
||||
cpu_suspend(save_state, omap_pm_ops.finish_suspend);
|
||||
else
|
||||
omap_pm_ops.finish_suspend(save_state);
|
||||
|
||||
/*
|
||||
* Restore the CPUx power state to ON otherwise CPUx
|
||||
@ -268,14 +305,14 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
|
||||
pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
|
||||
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
|
||||
set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
|
||||
scu_pwrst_prepare(cpu, power_state);
|
||||
omap_pm_ops.scu_prepare(cpu, power_state);
|
||||
|
||||
/*
|
||||
* CPU never retuns back if targeted power state is OFF mode.
|
||||
* CPU ONLINE follows normal CPU ONLINE ptah via
|
||||
* omap_secondary_startup().
|
||||
* omap4_secondary_startup().
|
||||
*/
|
||||
omap4_finish_suspend(cpu_state);
|
||||
omap_pm_ops.finish_suspend(cpu_state);
|
||||
|
||||
pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
|
||||
return 0;
|
||||
@ -319,9 +356,9 @@ int __init omap4_mpuss_init(void)
|
||||
pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
|
||||
pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
|
||||
if (cpu_is_omap446x())
|
||||
pm_info->secondary_startup = omap_secondary_startup_4460;
|
||||
pm_info->secondary_startup = omap4460_secondary_startup;
|
||||
else
|
||||
pm_info->secondary_startup = omap_secondary_startup;
|
||||
pm_info->secondary_startup = omap4_secondary_startup;
|
||||
|
||||
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
|
||||
if (!pm_info->pwrdm) {
|
||||
@ -352,6 +389,12 @@ int __init omap4_mpuss_init(void)
|
||||
|
||||
save_l2x0_context();
|
||||
|
||||
if (cpu_is_omap44xx()) {
|
||||
omap_pm_ops.finish_suspend = omap4_finish_suspend;
|
||||
omap_pm_ops.resume = omap4_cpu_resume;
|
||||
omap_pm_ops.scu_prepare = scu_pwrst_prepare;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
|
||||
|
||||
/*
|
||||
* Update the AuxCoreBoot0 with boot state for secondary core.
|
||||
* omap_secondary_startup() routine will hold the secondary core till
|
||||
* omap4_secondary_startup() routine will hold the secondary core till
|
||||
* the AuxCoreBoot1 register is updated with cpu state
|
||||
* A barrier is added to ensure that write buffer is drained
|
||||
*/
|
||||
@ -200,7 +200,7 @@ static void __init omap4_smp_init_cpus(void)
|
||||
|
||||
static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
void *startup_addr = omap_secondary_startup;
|
||||
void *startup_addr = omap4_secondary_startup;
|
||||
void __iomem *base = omap_get_wakeupgen_base();
|
||||
|
||||
/*
|
||||
@ -211,7 +211,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
|
||||
scu_enable(scu_base);
|
||||
|
||||
if (cpu_is_omap446x()) {
|
||||
startup_addr = omap_secondary_startup_4460;
|
||||
startup_addr = omap4460_secondary_startup;
|
||||
pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* OMAP4 Power Management Routines
|
||||
* OMAP4+ Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2010-2011 Texas Instruments, Inc.
|
||||
* Copyright (C) 2010-2013 Texas Instruments, Inc.
|
||||
* Rajendra Nayak <rnayak@ti.com>
|
||||
* Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
*
|
||||
@ -135,16 +135,16 @@ static void omap_default_idle(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* omap4_pm_init - Init routine for OMAP4 PM
|
||||
* omap4_init_static_deps - Add OMAP4 static dependencies
|
||||
*
|
||||
* Initializes all powerdomain and clockdomain target states
|
||||
* and all PRCM settings.
|
||||
* Add needed static clockdomain dependencies on OMAP4 devices.
|
||||
* Return: 0 on success or 'err' on failures
|
||||
*/
|
||||
int __init omap4_pm_init(void)
|
||||
static inline int omap4_init_static_deps(void)
|
||||
{
|
||||
int ret;
|
||||
struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
|
||||
struct clockdomain *ducati_clkdm, *l3_2_clkdm;
|
||||
int ret = 0;
|
||||
|
||||
if (omap_rev() == OMAP4430_REV_ES1_0) {
|
||||
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
|
||||
@ -163,7 +163,7 @@ int __init omap4_pm_init(void)
|
||||
ret = pwrdm_for_each(pwrdms_setup, NULL);
|
||||
if (ret) {
|
||||
pr_err("Failed to setup powerdomains\n");
|
||||
goto err2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -171,6 +171,10 @@ int __init omap4_pm_init(void)
|
||||
* MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
|
||||
* expected. The hardware recommendation is to enable static
|
||||
* dependencies for these to avoid system lock ups or random crashes.
|
||||
* The L4 wakeup depedency is added to workaround the OCP sync hardware
|
||||
* BUG with 32K synctimer which lead to incorrect timer value read
|
||||
* from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
|
||||
* are part of L4 wakeup clockdomain.
|
||||
*/
|
||||
mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
|
||||
emif_clkdm = clkdm_lookup("l3_emif_clkdm");
|
||||
@ -179,7 +183,7 @@ int __init omap4_pm_init(void)
|
||||
ducati_clkdm = clkdm_lookup("ducati_clkdm");
|
||||
if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
|
||||
(!l3_2_clkdm) || (!ducati_clkdm))
|
||||
goto err2;
|
||||
return -EINVAL;
|
||||
|
||||
ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
|
||||
ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
|
||||
@ -188,9 +192,42 @@ int __init omap4_pm_init(void)
|
||||
ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
|
||||
if (ret) {
|
||||
pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 wakeup dependency\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap4_pm_init - Init routine for OMAP4+ devices
|
||||
*
|
||||
* Initializes all powerdomain and clockdomain target states
|
||||
* and all PRCM settings.
|
||||
* Return: Returns the error code returned by called functions.
|
||||
*/
|
||||
int __init omap4_pm_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (omap_rev() == OMAP4430_REV_ES1_0) {
|
||||
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pr_info("Power Management for TI OMAP4+ devices.\n");
|
||||
|
||||
ret = pwrdm_for_each(pwrdms_setup, NULL);
|
||||
if (ret) {
|
||||
pr_err("Failed to setup powerdomains.\n");
|
||||
goto err2;
|
||||
}
|
||||
|
||||
if (cpu_is_omap44xx()) {
|
||||
ret = omap4_init_static_deps();
|
||||
if (ret)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
ret = omap4_mpuss_init();
|
||||
if (ret) {
|
||||
pr_err("Failed to initialise OMAP4 MPUSS\n");
|
||||
@ -206,7 +243,8 @@ int __init omap4_pm_init(void)
|
||||
/* Overwrite the default cpu_do_idle() */
|
||||
arm_pm_idle = omap_default_idle;
|
||||
|
||||
omap4_idle_init();
|
||||
if (cpu_is_omap44xx())
|
||||
omap4_idle_init();
|
||||
|
||||
err2:
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user