diff options
author | Arnd Bergmann <arnd@arndb.de> | 2016-11-25 18:30:46 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2016-11-25 18:30:46 -0500 |
commit | 192a5e8c96d71c83190c96f737f6e780747204a4 (patch) | |
tree | f83b93303ad1c6d5c36ac25e51f0e441c54d9283 | |
parent | 048f789b9531574894babde683e1c7ae2ae5e9de (diff) | |
parent | e330ea5e8cea7ba58f0ba9d40063b13cf8639555 (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/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-oxnas/Kconfig | 30 | ||||
-rw-r--r-- | arch/arm/mach-oxnas/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-oxnas/headsmp.S | 26 | ||||
-rw-r--r-- | arch/arm/mach-oxnas/hotplug.c | 109 | ||||
-rw-r--r-- | arch/arm/mach-oxnas/platsmp.c | 102 |
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 | |||
191 | machine-$(CONFIG_ARCH_NETX) += netx | 191 | machine-$(CONFIG_ARCH_NETX) += netx |
192 | machine-$(CONFIG_ARCH_NOMADIK) += nomadik | 192 | machine-$(CONFIG_ARCH_NOMADIK) += nomadik |
193 | machine-$(CONFIG_ARCH_NSPIRE) += nspire | 193 | machine-$(CONFIG_ARCH_NSPIRE) += nspire |
194 | machine-$(CONFIG_ARCH_OXNAS) += oxnas | ||
194 | machine-$(CONFIG_ARCH_OMAP1) += omap1 | 195 | machine-$(CONFIG_ARCH_OMAP1) += omap1 |
195 | machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 | 196 | machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 |
196 | machine-$(CONFIG_ARCH_ORION5X) += orion5x | 197 | machine-$(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 @@ | |||
1 | menuconfig ARCH_OXNAS | 1 | menuconfig 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 | ||
12 | config MACH_OX810SE | 19 | config 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 | ||
26 | config 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 | |||
26 | endif | 38 | endif |
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 @@ | |||
1 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | ||
2 | obj-$(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 | */ | ||
18 | ENTRY(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 | |||
16 | static 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 | |||
37 | static 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 | |||
52 | static 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 | */ | ||
91 | void 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 | |||
21 | extern void ox820_secondary_startup(void); | ||
22 | extern void ox820_cpu_die(unsigned int cpu); | ||
23 | |||
24 | static void __iomem *cpu_ctrl; | ||
25 | static 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 | |||
34 | int __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 | |||
63 | static 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 | |||
90 | unmap_scu: | ||
91 | iounmap(scu_base); | ||
92 | } | ||
93 | |||
94 | static 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 | |||
102 | CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops); | ||