diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-08-22 12:04:15 +0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-08-22 12:04:15 +0400 |
commit | 80b304fd00e8b667775ff791121b61ecd7cd0c03 (patch) | |
tree | b4f2ec59fe062c43343ee4c2f10a6bcd0e4dcd1b /arch/arm/mach-berlin/platsmp.c | |
parent | fb21b84e7f809ef04b1e5aed5d463cf0d4866638 (diff) | |
parent | 6a7519e81321343165f89abb8b616df186d3e57a (diff) | |
download | linux-80b304fd00e8b667775ff791121b61ecd7cd0c03.tar.xz |
Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/urgent
Pull EFI fixes from Matt Fleming:
* WARN_ON(!spin_is_locked()) always triggers on non-SMP machines.
Swap it for the more canonical lockdep_assert_held() which always
does the right thing - Guenter Roeck
* Assign the correct value to efi.runtime_version on arm64 so that all
the runtime services can be invoked - Semen Protsenko
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/arm/mach-berlin/platsmp.c')
-rw-r--r-- | arch/arm/mach-berlin/platsmp.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c new file mode 100644 index 000000000000..702e7982015a --- /dev/null +++ b/arch/arm/mach-berlin/platsmp.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 Marvell Technology Group Ltd. + * + * Antoine Ténart <antoine.tenart@free-electrons.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/io.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> +#include <asm/smp_scu.h> + +#define CPU_RESET 0x00 + +#define RESET_VECT 0x00 +#define SW_RESET_ADDR 0x94 + +extern void berlin_secondary_startup(void); +extern u32 boot_inst; + +static void __iomem *cpu_ctrl; + +static inline void berlin_perform_reset_cpu(unsigned int cpu) +{ + u32 val; + + val = readl(cpu_ctrl + CPU_RESET); + val |= BIT(cpu_logical_map(cpu)); + writel(val, cpu_ctrl + CPU_RESET); +} + +static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + if (!cpu_ctrl) + return -EFAULT; + + /* + * Reset the CPU, making it to execute the instruction in the reset + * exception vector. + */ + berlin_perform_reset_cpu(cpu); + + return 0; +} + +static void __init berlin_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *np; + void __iomem *scu_base; + void __iomem *vectors_base; + + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + scu_base = of_iomap(np, 0); + of_node_put(np); + if (!scu_base) + return; + + np = of_find_compatible_node(NULL, NULL, "marvell,berlin-cpu-ctrl"); + cpu_ctrl = of_iomap(np, 0); + of_node_put(np); + if (!cpu_ctrl) + goto unmap_scu; + + vectors_base = ioremap(CONFIG_VECTORS_BASE, SZ_32K); + if (!vectors_base) + goto unmap_scu; + + scu_enable(scu_base); + flush_cache_all(); + + /* + * Write the first instruction the CPU will execute after being reset + * in the reset exception vector. + */ + writel(boot_inst, vectors_base + RESET_VECT); + + /* + * Write the secondary startup address into the SW reset address + * vector. This is used by boot_inst. + */ + writel(virt_to_phys(berlin_secondary_startup), vectors_base + SW_RESET_ADDR); + + iounmap(vectors_base); +unmap_scu: + iounmap(scu_base); +} + +static struct smp_operations berlin_smp_ops __initdata = { + .smp_prepare_cpus = berlin_smp_prepare_cpus, + .smp_boot_secondary = berlin_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops); |