diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 15:27:22 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 15:27:22 -0800 |
commit | bab588fcfb6335c767d811a8955979f5440328e0 (patch) | |
tree | 2a862ddf47a82be885a8e7945a17cc3ff7a658b9 /arch/arm/mach-shmobile/smp-sh73a0.c | |
parent | 3298a3511f1e73255a8dc023efd909e569eea037 (diff) | |
parent | 9cb0d1babfcb1b4ac248c09425f7d5de1e771133 (diff) |
Merge tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC-specific updates from Arnd Bergmann:
"This is a larger set of new functionality for the existing SoC
families, including:
- vt8500 gains support for new CPU cores, notably the Cortex-A9 based
wm8850
- prima2 gains support for the "marco" SoC family, its SMP based
cousin
- tegra gains support for the new Tegra4 (Tegra114) family
- socfpga now supports a newer version of the hardware including SMP
- i.mx31 and bcm2835 are now using DT probing for their clocks
- lots of updates for sh-mobile
- OMAP updates for clocks, power management and USB
- i.mx6q and tegra now support cpuidle
- kirkwood now supports PCIe hot plugging
- tegra clock support is updated
- tegra USB PHY probing gets implemented diffently"
* tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (148 commits)
ARM: prima2: remove duplicate v7_invalidate_l1
ARM: shmobile: r8a7779: Correct TMU clock support again
ARM: prima2: fix __init section for cpu hotplug
ARM: OMAP: Consolidate OMAP USB-HS platform data (part 3/3)
ARM: OMAP: Consolidate OMAP USB-HS platform data (part 1/3)
arm: socfpga: Add SMP support for actual socfpga harware
arm: Add v7_invalidate_l1 to cache-v7.S
arm: socfpga: Add entries to enable make dtbs socfpga
arm: socfpga: Add new device tree source for actual socfpga HW
ARM: tegra: sort Kconfig selects for Tegra114
ARM: tegra: enable ARCH_REQUIRE_GPIOLIB for Tegra114
ARM: tegra: Fix build error w/ ARCH_TEGRA_114_SOC w/o ARCH_TEGRA_3x_SOC
ARM: tegra: Fix build error for gic update
ARM: tegra: remove empty tegra_smp_init_cpus()
ARM: shmobile: Register ARM architected timer
ARM: MARCO: fix the build issue due to gic-vic-to-irqchip move
ARM: shmobile: r8a7779: Correct TMU clock support
ARM: mxs_defconfig: Select CONFIG_DEVTMPFS_MOUNT
ARM: mxs: decrease mxs_clockevent_device.min_delta_ns to 2 clock cycles
ARM: mxs: use apbx bus clock to drive the timers on timrotv2
...
Diffstat (limited to 'arch/arm/mach-shmobile/smp-sh73a0.c')
-rw-r--r-- | arch/arm/mach-shmobile/smp-sh73a0.c | 68 |
1 files changed, 35 insertions, 33 deletions
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 5c5bcb59535..acb46a94ccd 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <linux/irqchip/arm-gic.h> #include <mach/common.h> +#include <asm/cacheflush.h> #include <asm/smp_plat.h> #include <mach/sh73a0.h> #include <asm/smp_scu.h> @@ -36,14 +37,13 @@ #define SBAR IOMEM(0xe6180020) #define APARMBAREA IOMEM(0xe6f10020) +#define PSTR_SHUTDOWN_MODE 3 + static void __iomem *scu_base_addr(void) { return (void __iomem *)0xf0000000; } -static DEFINE_SPINLOCK(scu_lock); -static unsigned long tmp; - #ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); void __init sh73a0_register_twd(void) @@ -52,20 +52,6 @@ void __init sh73a0_register_twd(void) } #endif -static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) -{ - void __iomem *scu_base = scu_base_addr(); - - spin_lock(&scu_lock); - tmp = __raw_readl(scu_base + 8); - tmp &= ~clr; - tmp |= set; - spin_unlock(&scu_lock); - - /* disable cache coherency after releasing the lock */ - __raw_writel(tmp, scu_base + 8); -} - static unsigned int __init sh73a0_get_core_count(void) { void __iomem *scu_base = scu_base_addr(); @@ -82,9 +68,6 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct { cpu = cpu_logical_map(cpu); - /* enable cache coherency */ - modify_scu_cpu_psr(0, 3 << (cpu * 8)); - if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3) __raw_writel(1 << cpu, WUPCR); /* wake up */ else @@ -95,16 +78,14 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) { - int cpu = cpu_logical_map(0); - scu_enable(scu_base_addr()); - /* Map the reset vector (in headsmp.S) */ + /* Map the reset vector (in headsmp-sh73a0.S) */ __raw_writel(0, APARMBAREA); /* 4k */ - __raw_writel(__pa(shmobile_secondary_vector), SBAR); + __raw_writel(__pa(sh73a0_secondary_vector), SBAR); - /* enable cache coherency on CPU0 */ - modify_scu_cpu_psr(0, 3 << (cpu * 8)); + /* enable cache coherency on booting CPU */ + scu_power_mode(scu_base_addr(), SCU_PM_NORMAL); } static void __init sh73a0_smp_init_cpus(void) @@ -114,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void) shmobile_smp_init_cpus(ncores); } -static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) +#ifdef CONFIG_HOTPLUG_CPU +static int sh73a0_cpu_kill(unsigned int cpu) { + int k; + u32 pstr; - /* this function is running on another CPU than the offline target, - * here we need wait for shutdown code in platform_cpu_die() to - * finish before asking SoC-specific code to power off the CPU core. + /* + * wait until the power status register confirms the shutdown of the + * offline target */ for (k = 0; k < 1000; k++) { - if (shmobile_cpu_is_dead(cpu)) + pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3; + if (pstr == PSTR_SHUTDOWN_MODE) return 1; mdelay(1); @@ -132,6 +117,23 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) return 0; } +static void sh73a0_cpu_die(unsigned int cpu) +{ + /* + * The ARM MPcore does not issue a cache coherency request for the L1 + * cache when powering off single CPUs. We must take care of this and + * further caches. + */ + dsb(); + flush_cache_all(); + + /* Set power off mode. This takes the CPU out of the MP cluster */ + scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF); + + /* Enter shutdown mode */ + cpu_do_idle(); +} +#endif /* CONFIG_HOTPLUG_CPU */ struct smp_operations sh73a0_smp_ops __initdata = { .smp_init_cpus = sh73a0_smp_init_cpus, @@ -140,7 +142,7 @@ struct smp_operations sh73a0_smp_ops __initdata = { .smp_boot_secondary = sh73a0_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_kill = sh73a0_cpu_kill, - .cpu_die = shmobile_cpu_die, - .cpu_disable = shmobile_cpu_disable, + .cpu_die = sh73a0_cpu_die, + .cpu_disable = shmobile_cpu_disable_any, #endif }; |