[PATCH 2/2] ARM: shmobile: sh73a0: Suspend-to-RAM Power Off mode
Bastian Hecht
hechtb at gmail.com
Tue Apr 9 11:02:33 EDT 2013
Hi Simon,
2013/4/9 Simon Horman <horms at verge.net.au>:
> On 木, 3月 21, 2013 at 02:31:37午後 +0100, Bastian Hecht wrote:
>> We add Power Off mode defined by the ARM architecture as our
>> Suspend-to-RAM mechanism. Here the L2 cache keeps its power and we only
>> take care to flush the L1. Different startup paths are added for the two
>> CPUs, one leading to cpu_resume() and the other to secondary_startup().
>>
>> Signed-off-by: Bastian Hecht <hechtb+renesas at gmail.com>
>
> Bastian, could you please let me know about the status of this patch?
> Is it awaiting review?
I want to have a look again at the part with the L1 take down, my code
might be incorrect there although I experienced no adverse effects.
Before that I want to get the r8a7740 PM code merged.
I've posted a patch "ARM: shmobile: r8a7740: Add power down modes and
CPUIdle". I will post a fresh patch tomorrow I think with a stripped
down version. I will remove Core Standby Mode for which it is unclear
why we need to flush the L2 cache.
Thanks,
Bastian
>> ---
>> arch/arm/mach-shmobile/Makefile | 2 +-
>> arch/arm/mach-shmobile/headsmp-sh73a0.S | 72 ++++++++++++++++++++++++++
>> arch/arm/mach-shmobile/include/mach/common.h | 1 +
>> arch/arm/mach-shmobile/pm-sh73a0.c | 32 ++++++++++--
>> arch/arm/mach-shmobile/smp-sh73a0.c | 9 +++-
>> 5 files changed, 109 insertions(+), 7 deletions(-)
>> create mode 100644 arch/arm/mach-shmobile/headsmp-sh73a0.S
>>
>> diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
>> index c621edf..1d33d89 100644
>> --- a/arch/arm/mach-shmobile/Makefile
>> +++ b/arch/arm/mach-shmobile/Makefile
>> @@ -14,7 +14,7 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
>>
>> # SMP objects
>> smp-y := platsmp.o headsmp.o
>> -smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o
>> +smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o headsmp-scu.o
>> smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o
>> smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o
>>
>> diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>> new file mode 100644
>> index 0000000..6ffed46
>> --- /dev/null
>> +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>> @@ -0,0 +1,72 @@
>> +/*
>> + * SMP support for SoC sh73a0
>> + *
>> + * Copyright (C) 2013 Bastian Hecht
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#include <linux/linkage.h>
>> +#include <linux/init.h>
>> +#include <asm/memory.h>
>> +
>> + __CPUINIT
>> +
>> +ENTRY(sh73a0_primary_resume)
>> + bl v7_invalidate_l1
>> + b cpu_resume
>> +ENDPROC(sh73a0_primary_resume)
>> +
>> +ENTRY(sh73a0_secondary_startup)
>> + bl v7_invalidate_l1
>> + b secondary_startup
>> +ENDPROC(sh73a0_primary_resume)
>> +
>> +/*
>> + * Reset vector for both CPUs.
>> + *
>> + * This function will be mapped to address 0 by the SBAR register and is the
>> + * general wakeup vector.
>> + * For both CPUs we need to set the SCU power flag to Run Mode and invalidate
>> + * the L1 cache so no random data get flushed out later.
>> + * We can't use v7_invalidate_l1() directly as a normal branch is out of range
>> + * here and so we need a long jump. We jump to the physical address as the
>> + * MMU is still turned off.
>> + *
>> + * We do not need to worry about CPU1 running ahead of CPU0 as the secondary
>> + * CPU of the sh73a0 needs to be woken using the WUPCR register. This is done
>> + * in sh73a0_boot_secondary().
>> + */
>> + .align 12
>> +ENTRY(sh73a0_reset_vector)
>> + /* Retrieve the CPU ID and keep it in r4 */
>> + mrc p15, 0, r4, c0, c0, 5 @ read MIPDR
>> + and r4, r4, #3 @ mask out cpu ID
>> +
>> + /*
>> + * We clear the SCU Power status flag to prepare for the
>> + * L1 coherency mode
>> + */
>> + mov r0, r4 @ copy CPU ID
>> + lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits
>> + ldr r1, 3f
>> + ldr r1, [r1] @ SCU base address
>> + ldr r2, [r1, #8] @ SCU Power Status Register
>> + mov r3, #3
>> + bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode)
>> + str r2, [r1, #8] @ write back
>> +
>> + /*
>> + * Depending on the CPU ID we either resume our primary core from
>> + * sleeping or bring up the secondary CPU
>> + */
>> + cmp r4, #0 @ if CPU0
>> + ldreq pc, 1f @ jump to sh73a0_primary_resume
>> + ldr pc, 2f @ jump to sh73a0_secondary_startup
>> +
>> +1: .long sh73a0_primary_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
>> +2: .long sh73a0_secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET
>> +3: .long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET
>> +ENDPROC(sh73a0_reset_vector)
>> diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
>> index 03f73de..842bb35 100644
>> --- a/arch/arm/mach-shmobile/include/mach/common.h
>> +++ b/arch/arm/mach-shmobile/include/mach/common.h
>> @@ -45,6 +45,7 @@ extern void sh73a0_add_standard_devices_dt(void);
>> extern void sh73a0_clock_init(void);
>> extern void sh73a0_pinmux_init(void);
>> extern void sh73a0_pm_init(void);
>> +extern void sh73a0_reset_vector(void);
>> extern struct clk sh73a0_extal1_clk;
>> extern struct clk sh73a0_extal2_clk;
>> extern struct clk sh73a0_extcki_clk;
>> diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c
>> index 99086e9..7e8e0a1 100644
>> --- a/arch/arm/mach-shmobile/pm-sh73a0.c
>> +++ b/arch/arm/mach-shmobile/pm-sh73a0.c
>> @@ -1,30 +1,54 @@
>> /*
>> * sh73a0 Power management support
>> *
>> - * Copyright (C) 2012 Bastian Hecht <hechtb+renesas at gmail.com>
>> + * Copyright (C) 2013 Bastian Hecht <hechtb+renesas at gmail.com>
>> *
>> * This file is subject to the terms and conditions of the GNU General Public
>> * License. See the file "COPYING" in the main directory of this archive
>> * for more details.
>> */
>>
>> +#include <linux/cpuidle.h>
>> +#include <linux/module.h>
>> #include <linux/suspend.h>
>> +#include <linux/io.h>
>> +#include <asm/cacheflush.h>
>> +#include <asm/smp_scu.h>
>> +#include <asm/suspend.h>
>> #include <mach/common.h>
>>
>> #ifdef CONFIG_SUSPEND
>> -static int sh73a0_enter_suspend(suspend_state_t suspend_state)
>> +/*
>> + * sh73a0_do_poweroff: Power off the main CPU
>> + *
>> + * The L2 cache doesn't loose power in Power Off mode - ignore it.
>> + * After flushing the L1 cache we don't take care to disable it as we
>> + * only work on temporary values in a UP environment and it gets invalidated
>> + * on startup. Just straight take down the ARM core.
>> + */
>> +static int sh73a0_do_poweroff(unsigned long unused)
>> {
>> + flush_cache_all();
>> + scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
>> cpu_do_idle();
>> +
>> + return 0;
>> +}
>> +
>> +static int sh73a0_enter_poweroff_suspend(suspend_state_t suspend_state)
>> +{
>> + cpu_suspend(0, sh73a0_do_poweroff);
>> +
>> return 0;
>> }
>>
>> static void sh73a0_suspend_init(void)
>> {
>> - shmobile_suspend_ops.enter = sh73a0_enter_suspend;
>> + shmobile_suspend_ops.enter = sh73a0_enter_poweroff_suspend;
>> }
>> #else
>> static void sh73a0_suspend_init(void) {}
>> -#endif
>> +#endif /* CONFIG_SUSPEND */
>>
>> void __init sh73a0_pm_init(void)
>> {
>> diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
>> index 5ae502b..348714e 100644
>> --- a/arch/arm/mach-shmobile/smp-sh73a0.c
>> +++ b/arch/arm/mach-shmobile/smp-sh73a0.c
>> @@ -70,9 +70,14 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
>> {
>> scu_enable(shmobile_scu_base);
>>
>> - /* Map the reset vector (in headsmp-scu.S) */
>> + /*
>> + * Map the general reset vector that is hit from multiple paths:
>> + * - Primary CPU resume at wakeup time
>> + * - Secondary startup at boot time
>> + * - Secondary startup at wakeup time
>> + */
>> __raw_writel(0, APARMBAREA); /* 4k */
>> - __raw_writel(__pa(shmobile_secondary_vector_scu), SBAR);
>> + __raw_writel(__pa(sh73a0_reset_vector), SBAR);
>>
>> /* enable cache coherency on booting CPU */
>> scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
More information about the linux-arm-kernel
mailing list