Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -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);
+4 −4
Original line number Original line Diff line number Diff line
@@ -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
	 * 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
	 * 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)
+56 −13
Original line number Original line Diff line number Diff line
@@ -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,12 +191,13 @@ 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)


	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)
	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)
	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)


	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;
}
}


+3 −3
Original line number Original line Diff line number Diff line
@@ -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)


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)
		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;
	}
	}


+48 −10
Original line number Original line Diff line number Diff line
/*
/*
 * 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)
}
}


/**
/**
 * 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)
	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)
	 * 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)
	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)
	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)
	/* 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: