[PATCH 2/2] ARM: shmobile: sh73a0: Suspend-to-RAM Power Off mode
Simon Horman
horms at verge.net.au
Tue Apr 9 09:25:35 EDT 2013
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?
> ---
> 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