diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 20:38:16 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 20:38:16 +0400 |
commit | 99c6bcf46d2233d33e441834e958ed0bc22b190a (patch) | |
tree | 25abf5e856bc0f08d75e623715eb5acc4d4de2b2 /arch/arm/mach-spear/platsmp.c | |
parent | 97b1007a2924aaa9126398623f6755a8c3c6a616 (diff) | |
parent | 2fdfe1c26fb9f24cfdf124384abb35396ca2cd3f (diff) | |
download | linux-99c6bcf46d2233d33e441834e958ed0bc22b190a.tar.xz |
Merge tag 'multiplatform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC multiplatform updates from Olof Johansson:
"More multiplatform enablement for ARM platforms. The ones converted
in this branch are:
- bcm2835
- cns3xxx
- sirf
- nomadik
- msx
- spear
- tegra
- ux500
We're getting close to having most of them converted!
One of the larger platforms remaining is Samsung Exynos, and there are
a bunch of supporting patches in this merge window for it. There was
a patch in this branch to a early version of multiplatform conversion,
but it ended up being reverted due to need of more bake time. The
revert commit is part of the branch since it would have required
rebasing multiple dependent branches and they were stable by then"
* tag 'multiplatform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (70 commits)
mmc: sdhci-s3c: Fix operation on non-single image Samsung platforms
clocksource: nomadik-mtu: fix up clocksource/timer
Revert "ARM: exynos: enable multiplatform support"
ARM: SPEAr13xx: Fix typo "ARCH_HAVE_CPUFREQ"
ARM: exynos: enable multiplatform support
rtc: s3c: make header file local
mtd: onenand/samsung: make regs-onenand.h file local
thermal/exynos: remove unnecessary header inclusions
mmc: sdhci-s3c: remove platform dependencies
ARM: samsung: move mfc device definition to s5p-dev-mfc.c
ARM: exynos: move debug-macro.S to include/debug/
ARM: exynos: prepare for sparse IRQ
ARM: exynos: introduce EXYNOS_ATAGS symbol
ARM: tegra: build assembly files with -march=armv7-a
ARM: Push selects for TWD/SCU into machine entries
ARM: ux500: build hotplug.o for ARMv7-a
ARM: ux500: move to multiplatform
ARM: ux500: make remaining headers local
ARM: ux500: make irqs.h local to platform
ARM: ux500: get rid of <mach/[hardware|db8500-regs].h>
...
Diffstat (limited to 'arch/arm/mach-spear/platsmp.c')
-rw-r--r-- | arch/arm/mach-spear/platsmp.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c new file mode 100644 index 000000000000..9c4c722c954e --- /dev/null +++ b/arch/arm/mach-spear/platsmp.c @@ -0,0 +1,122 @@ +/* + * arch/arm/mach-spear13xx/platsmp.c + * + * based upon linux/arch/arm/mach-realview/platsmp.c + * + * Copyright (C) 2012 ST Microelectronics Ltd. + * Shiraz Hashim <shiraz.hashim@st.com> + * + * 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/delay.h> +#include <linux/jiffies.h> +#include <linux/io.h> +#include <linux/smp.h> +#include <asm/cacheflush.h> +#include <asm/smp_scu.h> +#include <mach/spear.h> +#include "generic.h" + +static DEFINE_SPINLOCK(boot_lock); + +static void __iomem *scu_base = IOMEM(VA_SCU_BASE); + +static void __cpuinit spear13xx_secondary_init(unsigned int cpu) +{ + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu; + flush_cache_all(); + outer_flush_all(); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +static void __init spear13xx_smp_init_cpus(void) +{ + unsigned int i, ncores = scu_get_core_count(scu_base); + + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus) +{ + + scu_enable(scu_base); + + /* + * Write the address of secondary startup into the system-wide location + * (presently it is in SRAM). The BootMonitor waits until it receives a + * soft interrupt, and then the secondary CPU branches to this address. + */ + __raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION); +} + +struct smp_operations spear13xx_smp_ops __initdata = { + .smp_init_cpus = spear13xx_smp_init_cpus, + .smp_prepare_cpus = spear13xx_smp_prepare_cpus, + .smp_secondary_init = spear13xx_secondary_init, + .smp_boot_secondary = spear13xx_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = spear13xx_cpu_die, +#endif +}; |