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

Commit 68847edc authored by Kukjin Kim's avatar Kukjin Kim
Browse files

Merge branch 'v3.19-next/cleanup-samsung' into v3.19-next/mach-exynos

parents 03c1b760 13cfa6c4
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -17,9 +17,6 @@ obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o

obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o

obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
CFLAGS_hotplug.o		+= -march=armv7-a

plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_exynos-smc.o		:=-Wa,-march=armv7-a$(plus_sec)
AFLAGS_sleep.o			:=-Wa,-march=armv7-a$(plus_sec)
+0 −2
Original line number Diff line number Diff line
@@ -139,8 +139,6 @@ extern void exynos_cpu_resume_ns(void);

extern struct smp_operations exynos_smp_ops;

extern void exynos_cpu_die(unsigned int cpu);

/* PMU(Power Management Unit) support */

#define PMU_TABLE_END	(-1U)

arch/arm/mach-exynos/hotplug.c

deleted100644 → 0
+0 −91
Original line number Diff line number Diff line
/*
 *  Cloned from linux/arch/arm/mach-realview/hotplug.c
 *
 *  Copyright (C) 2002 ARM Ltd.
 *  All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/io.h>

#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h>

#include "common.h"
#include "regs-pmu.h"

static inline void cpu_leave_lowpower(void)
{
	unsigned int v;

	asm volatile(
	"mrc	p15, 0, %0, c1, c0, 0\n"
	"	orr	%0, %0, %1\n"
	"	mcr	p15, 0, %0, c1, c0, 0\n"
	"	mrc	p15, 0, %0, c1, c0, 1\n"
	"	orr	%0, %0, %2\n"
	"	mcr	p15, 0, %0, c1, c0, 1\n"
	  : "=&r" (v)
	  : "Ir" (CR_C), "Ir" (0x40)
	  : "cc");
}

static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
	u32 mpidr = cpu_logical_map(cpu);
	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);

	for (;;) {

		/* Turn the CPU off on next WFI instruction. */
		exynos_cpu_power_down(core_id);

		wfi();

		if (pen_release == core_id) {
			/*
			 * OK, proper wakeup, we're done
			 */
			break;
		}

		/*
		 * Getting here, means that we have come out of WFI without
		 * having been woken up - this shouldn't happen
		 *
		 * Just note it happening - when we're woken, we can report
		 * its occurrence.
		 */
		(*spurious)++;
	}
}

/*
 * platform-specific code to shutdown a CPU
 *
 * Called with IRQs disabled
 */
void __ref exynos_cpu_die(unsigned int cpu)
{
	int spurious = 0;

	v7_exit_coherency_flush(louis);

	platform_do_lowpower(cpu, &spurious);

	/*
	 * bring this CPU back into the world of cache
	 * coherency, and then restore interrupts
	 */
	cpu_leave_lowpower();

	if (spurious)
		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
+113 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/of_address.h>

#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/firmware.h>
@@ -33,6 +34,88 @@

extern void exynos4_secondary_startup(void);

/*
 * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
 * during hot-(un)plugging CPUx.
 *
 * The feature can be cleared safely during first boot of secondary CPU.
 *
 * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
 * down a CPU so the CPU idle clock down feature could properly detect global
 * idle state when CPUx is off.
 */
static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
{
	if (soc_is_exynos4()) {
		unsigned int tmp;

		tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
		if (enable)
			tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
		else
			tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
		pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
	}
}

#ifdef CONFIG_HOTPLUG_CPU
static inline void cpu_leave_lowpower(u32 core_id)
{
	unsigned int v;

	asm volatile(
	"mrc	p15, 0, %0, c1, c0, 0\n"
	"	orr	%0, %0, %1\n"
	"	mcr	p15, 0, %0, c1, c0, 0\n"
	"	mrc	p15, 0, %0, c1, c0, 1\n"
	"	orr	%0, %0, %2\n"
	"	mcr	p15, 0, %0, c1, c0, 1\n"
	  : "=&r" (v)
	  : "Ir" (CR_C), "Ir" (0x40)
	  : "cc");

	 exynos_set_delayed_reset_assertion(core_id, false);
}

static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
	u32 mpidr = cpu_logical_map(cpu);
	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);

	for (;;) {

		/* Turn the CPU off on next WFI instruction. */
		exynos_cpu_power_down(core_id);

		/*
		 * Exynos4 SoCs require setting
		 * USE_DELAYED_RESET_ASSERTION so the CPU idle
		 * clock down feature could properly detect
		 * global idle state when CPUx is off.
		 */
		exynos_set_delayed_reset_assertion(core_id, true);

		wfi();

		if (pen_release == core_id) {
			/*
			 * OK, proper wakeup, we're done
			 */
			break;
		}

		/*
		 * Getting here, means that we have come out of WFI without
		 * having been woken up - this shouldn't happen
		 *
		 * Just note it happening - when we're woken, we can report
		 * its occurrence.
		 */
		(*spurious)++;
	}
}
#endif /* CONFIG_HOTPLUG_CPU */

/**
 * exynos_core_power_down : power down the specified cpu
 * @cpu : the cpu to power down
@@ -260,6 +343,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
		udelay(10);
	}

	/* No harm if this is called during first boot of secondary CPU */
	exynos_set_delayed_reset_assertion(core_id, false);

	/*
	 * now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
@@ -341,6 +427,33 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
	}
}

#ifdef CONFIG_HOTPLUG_CPU
/*
 * platform-specific code to shutdown a CPU
 *
 * Called with IRQs disabled
 */
static void exynos_cpu_die(unsigned int cpu)
{
	int spurious = 0;
	u32 mpidr = cpu_logical_map(cpu);
	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);

	v7_exit_coherency_flush(louis);

	platform_do_lowpower(cpu, &spurious);

	/*
	 * bring this CPU back into the world of cache
	 * coherency, and then restore interrupts
	 */
	cpu_leave_lowpower(core_id);

	if (spurious)
		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
#endif /* CONFIG_HOTPLUG_CPU */

struct smp_operations exynos_smp_ops __initdata = {
	.smp_init_cpus		= exynos_smp_init_cpus,
	.smp_prepare_cpus	= exynos_smp_prepare_cpus,
+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#define S5P_USE_STANDBY_WFI0			(1 << 16)
#define S5P_USE_STANDBY_WFE0			(1 << 24)
#define S5P_USE_DELAYED_RESET_ASSERTION		BIT(12)

#define EXYNOS_CORE_PO_RESET(n)			((1 << 4) << n)
#define EXYNOS_WAKEUP_FROM_LOWPWR		(1 << 28)
@@ -108,6 +109,8 @@
			(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
#define EXYNOS_ARM_CORE_STATUS(_nr)		\
			(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
#define EXYNOS_ARM_CORE_OPTION(_nr)		\
			(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x8)

#define EXYNOS_ARM_COMMON_CONFIGURATION		0x2500
#define EXYNOS_COMMON_CONFIGURATION(_nr)	\