aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-11-25 18:30:46 -0500
committerArnd Bergmann <arnd@arndb.de>2016-11-25 18:30:46 -0500
commit192a5e8c96d71c83190c96f737f6e780747204a4 (patch)
treef83b93303ad1c6d5c36ac25e51f0e441c54d9283
parent048f789b9531574894babde683e1c7ae2ae5e9de (diff)
parente330ea5e8cea7ba58f0ba9d40063b13cf8639555 (diff)
Merge tag 'oxnas-arm-soc-for-4.10-v2' of https://github.com/OXNAS/linux into next/soc
Pull "ARM: OXNAS SoC updates for 4.10" from Neil Armstrong: - Add SMP support for the Oxford Semiconductor OX820 SoC from http://lkml.kernel.org/r/20161021085848.1754-1-narmstrong@baylibre.com Changes since v1 Pull Request at : http://lkml.kernel.org/r/1305c61f-b1ef-7caf-7788-67e2b907e873@baylibre.com - Clarify copyright dates in commit message - Remove linux/arch/... lines from the top of the files * tag 'oxnas-arm-soc-for-4.10-v2' of https://github.com/OXNAS/linux: ARM: oxnas: Add OX820 config and makefile entry ARM: oxnas: Add OX820 SMP support
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/mach-oxnas/Kconfig30
-rw-r--r--arch/arm/mach-oxnas/Makefile2
-rw-r--r--arch/arm/mach-oxnas/headsmp.S26
-rw-r--r--arch/arm/mach-oxnas/hotplug.c109
-rw-r--r--arch/arm/mach-oxnas/platsmp.c102
6 files changed, 261 insertions, 9 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6be9ee148b78..68312a9f660a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_MXS) += mxs
191machine-$(CONFIG_ARCH_NETX) += netx 191machine-$(CONFIG_ARCH_NETX) += netx
192machine-$(CONFIG_ARCH_NOMADIK) += nomadik 192machine-$(CONFIG_ARCH_NOMADIK) += nomadik
193machine-$(CONFIG_ARCH_NSPIRE) += nspire 193machine-$(CONFIG_ARCH_NSPIRE) += nspire
194machine-$(CONFIG_ARCH_OXNAS) += oxnas
194machine-$(CONFIG_ARCH_OMAP1) += omap1 195machine-$(CONFIG_ARCH_OMAP1) += omap1
195machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 196machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
196machine-$(CONFIG_ARCH_ORION5X) += orion5x 197machine-$(CONFIG_ARCH_ORION5X) += orion5x
diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
index 29100beb2e7f..8fa4557e27a9 100644
--- a/arch/arm/mach-oxnas/Kconfig
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -1,9 +1,16 @@
1menuconfig ARCH_OXNAS 1menuconfig ARCH_OXNAS
2 bool "Oxford Semiconductor OXNAS Family SoCs" 2 bool "Oxford Semiconductor OXNAS Family SoCs"
3 select ARCH_HAS_RESET_CONTROLLER 3 select ARCH_HAS_RESET_CONTROLLER
4 select COMMON_CLK_OXNAS
4 select GPIOLIB 5 select GPIOLIB
6 select MFD_SYSCON
7 select OXNAS_RPS_TIMER
8 select PINCTRL_OXNAS
9 select RESET_CONTROLLER
10 select RESET_OXNAS
11 select VERSATILE_FPGA_IRQ
5 select PINCTRL 12 select PINCTRL
6 depends on ARCH_MULTI_V5 13 depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
7 help 14 help
8 Support for OxNas SoC family developed by Oxford Semiconductor. 15 Support for OxNas SoC family developed by Oxford Semiconductor.
9 16
@@ -11,16 +18,21 @@ if ARCH_OXNAS
11 18
12config MACH_OX810SE 19config MACH_OX810SE
13 bool "Support OX810SE Based Products" 20 bool "Support OX810SE Based Products"
14 select ARCH_HAS_RESET_CONTROLLER 21 depends on ARCH_MULTI_V5
15 select COMMON_CLK_OXNAS
16 select CPU_ARM926T 22 select CPU_ARM926T
17 select MFD_SYSCON
18 select OXNAS_RPS_TIMER
19 select PINCTRL_OXNAS
20 select RESET_CONTROLLER
21 select RESET_OXNAS
22 select VERSATILE_FPGA_IRQ
23 help 23 help
24 Include Support for the Oxford Semiconductor OX810SE SoC Based Products. 24 Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
25 25
26config MACH_OX820
27 bool "Support OX820 Based Products"
28 depends on ARCH_MULTI_V6
29 select ARM_GIC
30 select DMA_CACHE_RWFO if SMP
31 select CPU_V6K
32 select HAVE_SMP
33 select HAVE_ARM_SCU if SMP
34 select HAVE_ARM_TWD if SMP
35 help
36 Include Support for the Oxford Semiconductor OX820 SoC Based Products.
37
26endif 38endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 000000000000..b625906a9970
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_SMP) += platsmp.o headsmp.o
2obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-oxnas/headsmp.S b/arch/arm/mach-oxnas/headsmp.S
new file mode 100644
index 000000000000..25fd4f82ab3a
--- /dev/null
+++ b/arch/arm/mach-oxnas/headsmp.S
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
3 * Copyright (c) 2003 ARM Limited
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <linux/init.h>
12
13 __INIT
14
15/*
16 * OX820 specific entry point for secondary CPUs.
17 */
18ENTRY(ox820_secondary_startup)
19 mov r4, #0
20 /* invalidate both caches and branch target cache */
21 mcr p15, 0, r4, c7, c7, 0
22 /*
23 * we've been released from the holding pen: secondary_stack
24 * should now contain the SVC stack for this core
25 */
26 b secondary_startup
diff --git a/arch/arm/mach-oxnas/hotplug.c b/arch/arm/mach-oxnas/hotplug.c
new file mode 100644
index 000000000000..854f29b8cba6
--- /dev/null
+++ b/arch/arm/mach-oxnas/hotplug.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright (C) 2002 ARM Ltd.
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/smp.h>
12
13#include <asm/cp15.h>
14#include <asm/smp_plat.h>
15
16static inline void cpu_enter_lowpower(void)
17{
18 unsigned int v;
19
20 asm volatile(
21 " mcr p15, 0, %1, c7, c5, 0\n"
22 " mcr p15, 0, %1, c7, c10, 4\n"
23 /*
24 * Turn off coherency
25 */
26 " mrc p15, 0, %0, c1, c0, 1\n"
27 " bic %0, %0, #0x20\n"
28 " mcr p15, 0, %0, c1, c0, 1\n"
29 " mrc p15, 0, %0, c1, c0, 0\n"
30 " bic %0, %0, %2\n"
31 " mcr p15, 0, %0, c1, c0, 0\n"
32 : "=&r" (v)
33 : "r" (0), "Ir" (CR_C)
34 : "cc");
35}
36
37static inline void cpu_leave_lowpower(void)
38{
39 unsigned int v;
40
41 asm volatile( "mrc p15, 0, %0, c1, c0, 0\n"
42 " orr %0, %0, %1\n"
43 " mcr p15, 0, %0, c1, c0, 0\n"
44 " mrc p15, 0, %0, c1, c0, 1\n"
45 " orr %0, %0, #0x20\n"
46 " mcr p15, 0, %0, c1, c0, 1\n"
47 : "=&r" (v)
48 : "Ir" (CR_C)
49 : "cc");
50}
51
52static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
53{
54 /*
55 * there is no power-control hardware on this platform, so all
56 * we can do is put the core into WFI; this is safe as the calling
57 * code will have already disabled interrupts
58 */
59 for (;;) {
60 /*
61 * here's the WFI
62 */
63 asm(".word 0xe320f003\n"
64 :
65 :
66 : "memory", "cc");
67
68 if (pen_release == cpu_logical_map(cpu)) {
69 /*
70 * OK, proper wakeup, we're done
71 */
72 break;
73 }
74
75 /*
76 * Getting here, means that we have come out of WFI without
77 * having been woken up - this shouldn't happen
78 *
79 * Just note it happening - when we're woken, we can report
80 * its occurrence.
81 */
82 (*spurious)++;
83 }
84}
85
86/*
87 * platform-specific code to shutdown a CPU
88 *
89 * Called with IRQs disabled
90 */
91void ox820_cpu_die(unsigned int cpu)
92{
93 int spurious = 0;
94
95 /*
96 * we're ready for shutdown now, so do it
97 */
98 cpu_enter_lowpower();
99 platform_do_lowpower(cpu, &spurious);
100
101 /*
102 * bring this CPU back into the world of cache
103 * coherency, and then restore interrupts
104 */
105 cpu_leave_lowpower();
106
107 if (spurious)
108 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
109}
diff --git a/arch/arm/mach-oxnas/platsmp.c b/arch/arm/mach-oxnas/platsmp.c
new file mode 100644
index 000000000000..442cc8a2f7dc
--- /dev/null
+++ b/arch/arm/mach-oxnas/platsmp.c
@@ -0,0 +1,102 @@
1/*
2 * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
3 * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/io.h>
12#include <linux/delay.h>
13#include <linux/of.h>
14#include <linux/of_address.h>
15
16#include <asm/cacheflush.h>
17#include <asm/cp15.h>
18#include <asm/smp_plat.h>
19#include <asm/smp_scu.h>
20
21extern void ox820_secondary_startup(void);
22extern void ox820_cpu_die(unsigned int cpu);
23
24static void __iomem *cpu_ctrl;
25static void __iomem *gic_cpu_ctrl;
26
27#define HOLDINGPEN_CPU_OFFSET 0xc8
28#define HOLDINGPEN_LOCATION_OFFSET 0xc4
29
30#define GIC_NCPU_OFFSET(cpu) (0x100 + (cpu)*0x100)
31#define GIC_CPU_CTRL 0x00
32#define GIC_CPU_CTRL_ENABLE 1
33
34int __init ox820_boot_secondary(unsigned int cpu, struct task_struct *idle)
35{
36 /*
37 * Write the address of secondary startup into the
38 * system-wide flags register. The BootMonitor waits
39 * until it receives a soft interrupt, and then the
40 * secondary CPU branches to this address.
41 */
42 writel(virt_to_phys(ox820_secondary_startup),
43 cpu_ctrl + HOLDINGPEN_LOCATION_OFFSET);
44
45 writel(cpu, cpu_ctrl + HOLDINGPEN_CPU_OFFSET);
46
47 /*
48 * Enable GIC cpu interface in CPU Interface Control Register
49 */
50 writel(GIC_CPU_CTRL_ENABLE,
51 gic_cpu_ctrl + GIC_NCPU_OFFSET(cpu) + GIC_CPU_CTRL);
52
53 /*
54 * Send the secondary CPU a soft interrupt, thereby causing
55 * the boot monitor to read the system wide flags register,
56 * and branch to the address found there.
57 */
58 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
59
60 return 0;
61}
62
63static void __init ox820_smp_prepare_cpus(unsigned int max_cpus)
64{
65 struct device_node *np;
66 void __iomem *scu_base;
67
68 np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-scu");
69 scu_base = of_iomap(np, 0);
70 of_node_put(np);
71 if (!scu_base)
72 return;
73
74 /* Remap CPU Interrupt Interface Registers */
75 np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-gic");
76 gic_cpu_ctrl = of_iomap(np, 1);
77 of_node_put(np);
78 if (!gic_cpu_ctrl)
79 goto unmap_scu;
80
81 np = of_find_compatible_node(NULL, NULL, "oxsemi,ox820-sys-ctrl");
82 cpu_ctrl = of_iomap(np, 0);
83 of_node_put(np);
84 if (!cpu_ctrl)
85 goto unmap_scu;
86
87 scu_enable(scu_base);
88 flush_cache_all();
89
90unmap_scu:
91 iounmap(scu_base);
92}
93
94static const struct smp_operations ox820_smp_ops __initconst = {
95 .smp_prepare_cpus = ox820_smp_prepare_cpus,
96 .smp_boot_secondary = ox820_boot_secondary,
97#ifdef CONFIG_HOTPLUG_CPU
98 .cpu_die = ox820_cpu_die,
99#endif
100};
101
102CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops);