Commit 49a34fd5 authored by Tony Lindgren's avatar Tony Lindgren

Merge tag 'omap-pm-v3.10/cleanup/pm' of...

Merge tag 'omap-pm-v3.10/cleanup/pm' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-v3.11/pm

OMAP PM cleanups for v3.10
parents f722406f 705814b5
...@@ -237,8 +237,8 @@ extern void omap_do_wfi(void); ...@@ -237,8 +237,8 @@ extern void omap_do_wfi(void);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Needed for secondary core boot */ /* Needed for secondary core boot */
extern void omap_secondary_startup(void); extern void omap4_secondary_startup(void);
extern void omap_secondary_startup_4460(void); extern void omap4460_secondary_startup(void);
extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
extern void omap_auxcoreboot_addr(u32 cpu_addr); extern void omap_auxcoreboot_addr(u32 cpu_addr);
extern u32 omap_read_auxcoreboot0(void); extern u32 omap_read_auxcoreboot0(void);
......
...@@ -49,7 +49,7 @@ END(omap5_secondary_startup) ...@@ -49,7 +49,7 @@ END(omap5_secondary_startup)
* The primary core will update this flag using a hardware * The primary core will update this flag using a hardware
* register AuxCoreBoot0. * register AuxCoreBoot0.
*/ */
ENTRY(omap_secondary_startup) ENTRY(omap4_secondary_startup)
hold: ldr r12,=0x103 hold: ldr r12,=0x103
dsb dsb
smc #0 @ read from AuxCoreBoot0 smc #0 @ read from AuxCoreBoot0
...@@ -64,9 +64,9 @@ hold: ldr r12,=0x103 ...@@ -64,9 +64,9 @@ hold: ldr r12,=0x103
* should now contain the SVC stack for this core * should now contain the SVC stack for this core
*/ */
b secondary_startup 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 hold_2: ldr r12,=0x103
dsb dsb
smc #0 @ read from AuxCoreBoot0 smc #0 @ read from AuxCoreBoot0
...@@ -101,4 +101,4 @@ hold_2: ldr r12,=0x103 ...@@ -101,4 +101,4 @@ hold_2: ldr r12,=0x103
* should now contain the SVC stack for this core * should now contain the SVC stack for this core
*/ */
b secondary_startup b secondary_startup
ENDPROC(omap_secondary_startup_4460) ENDPROC(omap4460_secondary_startup)
...@@ -71,10 +71,43 @@ struct omap4_cpu_pm_info { ...@@ -71,10 +71,43 @@ struct omap4_cpu_pm_info {
void (*secondary_startup)(void); 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 DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
static struct powerdomain *mpuss_pd; static struct powerdomain *mpuss_pd;
static void __iomem *sar_base; 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 * Program the wakeup routine address for the CPU0 and CPU1
* used for OFF or DORMANT wakeup. * used for OFF or DORMANT wakeup.
...@@ -158,11 +191,12 @@ static void save_l2x0_context(void) ...@@ -158,11 +191,12 @@ static void save_l2x0_context(void)
{ {
u32 val; u32 val;
void __iomem *l2x0_base = omap4_get_l2cache_base(); void __iomem *l2x0_base = omap4_get_l2cache_base();
if (l2x0_base) {
val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
__raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL); val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
__raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
}
} }
#else #else
static void save_l2x0_context(void) static void save_l2x0_context(void)
...@@ -225,14 +259,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) ...@@ -225,14 +259,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
cpu_clear_prev_logic_pwrst(cpu); cpu_clear_prev_logic_pwrst(cpu);
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
scu_pwrst_prepare(cpu, power_state); omap_pm_ops.scu_prepare(cpu, power_state);
l2x0_pwrst_prepare(cpu, save_state); l2x0_pwrst_prepare(cpu, save_state);
/* /*
* Call low level function with targeted low power 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 * 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) ...@@ -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_clear_all_prev_pwrst(pm_info->pwrdm);
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); 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 never retuns back if targeted power state is OFF mode.
* CPU ONLINE follows normal CPU ONLINE ptah via * 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); pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
return 0; return 0;
...@@ -319,9 +356,9 @@ int __init omap4_mpuss_init(void) ...@@ -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->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
if (cpu_is_omap446x()) if (cpu_is_omap446x())
pm_info->secondary_startup = omap_secondary_startup_4460; pm_info->secondary_startup = omap4460_secondary_startup;
else else
pm_info->secondary_startup = omap_secondary_startup; pm_info->secondary_startup = omap4_secondary_startup;
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
if (!pm_info->pwrdm) { if (!pm_info->pwrdm) {
...@@ -352,6 +389,12 @@ int __init omap4_mpuss_init(void) ...@@ -352,6 +389,12 @@ int __init omap4_mpuss_init(void)
save_l2x0_context(); 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; return 0;
} }
......
...@@ -87,7 +87,7 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * ...@@ -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. * 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 * the AuxCoreBoot1 register is updated with cpu state
* A barrier is added to ensure that write buffer is drained * A barrier is added to ensure that write buffer is drained
*/ */
...@@ -200,7 +200,7 @@ static void __init omap4_smp_init_cpus(void) ...@@ -200,7 +200,7 @@ static void __init omap4_smp_init_cpus(void)
static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) 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(); void __iomem *base = omap_get_wakeupgen_base();
/* /*
...@@ -211,7 +211,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) ...@@ -211,7 +211,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
scu_enable(scu_base); scu_enable(scu_base);
if (cpu_is_omap446x()) { if (cpu_is_omap446x()) {
startup_addr = omap_secondary_startup_4460; startup_addr = omap4460_secondary_startup;
pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD; pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
} }
......
/* /*
* 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> * Rajendra Nayak <rnayak@ti.com>
* Santosh Shilimkar <santosh.shilimkar@ti.com> * Santosh Shilimkar <santosh.shilimkar@ti.com>
* *
...@@ -135,16 +135,16 @@ static void omap_default_idle(void) ...@@ -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 * Add needed static clockdomain dependencies on OMAP4 devices.
* and all PRCM settings. * 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 *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
struct clockdomain *ducati_clkdm, *l3_2_clkdm; struct clockdomain *ducati_clkdm, *l3_2_clkdm;
int ret = 0;
if (omap_rev() == OMAP4430_REV_ES1_0) { if (omap_rev() == OMAP4430_REV_ES1_0) {
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
...@@ -163,7 +163,7 @@ int __init omap4_pm_init(void) ...@@ -163,7 +163,7 @@ int __init omap4_pm_init(void)
ret = pwrdm_for_each(pwrdms_setup, NULL); ret = pwrdm_for_each(pwrdms_setup, NULL);
if (ret) { if (ret) {
pr_err("Failed to setup powerdomains\n"); pr_err("Failed to setup powerdomains\n");
goto err2; return ret;
} }
/* /*
...@@ -171,6 +171,10 @@ int __init omap4_pm_init(void) ...@@ -171,6 +171,10 @@ int __init omap4_pm_init(void)
* MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
* expected. The hardware recommendation is to enable static * expected. The hardware recommendation is to enable static
* dependencies for these to avoid system lock ups or random crashes. * 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"); mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
emif_clkdm = clkdm_lookup("l3_emif_clkdm"); emif_clkdm = clkdm_lookup("l3_emif_clkdm");
...@@ -179,7 +183,7 @@ int __init omap4_pm_init(void) ...@@ -179,7 +183,7 @@ int __init omap4_pm_init(void)
ducati_clkdm = clkdm_lookup("ducati_clkdm"); ducati_clkdm = clkdm_lookup("ducati_clkdm");
if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
(!l3_2_clkdm) || (!ducati_clkdm)) (!l3_2_clkdm) || (!ducati_clkdm))
goto err2; return -EINVAL;
ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm); ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm); ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
...@@ -188,6 +192,39 @@ int __init omap4_pm_init(void) ...@@ -188,6 +192,39 @@ int __init omap4_pm_init(void)
ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm); ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
if (ret) { if (ret) {
pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 wakeup dependency\n"); 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; goto err2;
} }
...@@ -206,6 +243,7 @@ int __init omap4_pm_init(void) ...@@ -206,6 +243,7 @@ int __init omap4_pm_init(void)
/* Overwrite the default cpu_do_idle() */ /* Overwrite the default cpu_do_idle() */
arm_pm_idle = omap_default_idle; arm_pm_idle = omap_default_idle;
if (cpu_is_omap44xx())
omap4_idle_init(); omap4_idle_init();
err2: err2:
......
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