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

Commit d686ce42 authored by Alan Tull's avatar Alan Tull Committed by Arnd Bergmann
Browse files

socfpga: hotplug: put cpu1 in wfi



Use WFI when putting CPU1 to sleep.  Don't hold CPU1 in reset
since that results in increased power consumption.

Reset CPU1 briefly during CPU1 bootup.

This has been tested for hotplug and suspend/resume and results
in no increased power consumption.

Signed-off-by: default avatarAlan Tull <atull@opensource.altera.com>
Acked-by: default avatarPavel Machek <pavel@denx.de>
Signed-off-by: default avatarDinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 6bea7562
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#define __MACH_CORE_H
#define __MACH_CORE_H


#define SOCFPGA_RSTMGR_CTRL	0x04
#define SOCFPGA_RSTMGR_CTRL	0x04
#define SOCFPGA_RSTMGR_MODMPURST	0x10
#define SOCFPGA_RSTMGR_MODPERRST	0x14
#define SOCFPGA_RSTMGR_MODPERRST	0x14
#define SOCFPGA_RSTMGR_BRGMODRST	0x1c
#define SOCFPGA_RSTMGR_BRGMODRST	0x1c


@@ -28,6 +29,8 @@
#define RSTMGR_CTRL_SWCOLDRSTREQ	0x1	/* Cold Reset */
#define RSTMGR_CTRL_SWCOLDRSTREQ	0x1	/* Cold Reset */
#define RSTMGR_CTRL_SWWARMRSTREQ	0x2	/* Warm Reset */
#define RSTMGR_CTRL_SWWARMRSTREQ	0x2	/* Warm Reset */


#define RSTMGR_MPUMODRST_CPU1		0x2     /* CPU1 Reset */

extern void socfpga_secondary_startup(void);
extern void socfpga_secondary_startup(void);
extern void __iomem *socfpga_scu_base_addr;
extern void __iomem *socfpga_scu_base_addr;


+11 −8
Original line number Original line Diff line number Diff line
@@ -34,17 +34,21 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;


	if (socfpga_cpu1start_addr) {
	if (socfpga_cpu1start_addr) {
		/* This will put CPU #1 into reset. */
		writel(RSTMGR_MPUMODRST_CPU1,
		       rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);

		memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
		memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);


		__raw_writel(virt_to_phys(socfpga_secondary_startup),
		writel(virt_to_phys(socfpga_secondary_startup),
			(sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)));
		       sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff));


		flush_cache_all();
		flush_cache_all();
		smp_wmb();
		smp_wmb();
		outer_clean_range(0, trampoline_size);
		outer_clean_range(0, trampoline_size);


		/* This will release CPU #1 out of reset. */
		/* This will release CPU #1 out of reset. */
		__raw_writel(0, rst_manager_base_addr + 0x10);
		writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
	}
	}


	return 0;
	return 0;
@@ -86,10 +90,9 @@ static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
 */
 */
static void socfpga_cpu_die(unsigned int cpu)
static void socfpga_cpu_die(unsigned int cpu)
{
{
	/* Do WFI. If we wake up early, go back into WFI */
	while (1)
		cpu_do_idle();
		cpu_do_idle();

	/* We should have never returned from idle */
	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
}
}


struct smp_operations socfpga_smp_ops __initdata = {
struct smp_operations socfpga_smp_ops __initdata = {