aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-08-06 09:00:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-06 09:00:05 -0400
commit1630e843e104528ddf0208dfc692c70c9bd05a89 (patch)
treeb75d583b719a0b1398162aceccf2f443e7d36858
parent194d6ad32e1eef433c61040385dcfd98e6fe2ef9 (diff)
parente61c10e468a42512f5fad74c00b62af5cc19f65f (diff)
Merge tag 'sh-for-4.8' of git://git.libc.org/linux-sh
Pull arch/sh updates from Rich Felker: "These changes improve device tree support (including builtin DTB), add support for the J-Core J2 processor, an open source synthesizable reimplementation of the SH-2 ISA, resolve a longstanding sigcontext ABI mismatch issue, and fix various bugs including nommu-specific issues and minor regressions introduced in 4.6. The J-Core arch support is included here but to be usable it needs drivers that are waiting on approval/inclusion from their subsystem maintainers" * tag 'sh-for-4.8' of git://git.libc.org/linux-sh: (23 commits) sh: add device tree source for J2 FPGA on Mimas v2 board sh: add defconfig for J-Core J2 sh: use common clock framework with device tree boards sh: system call wire up sh: Delete unnecessary checks before the function call "mempool_destroy" sh: do not perform IPI-based cache flush except on boards that need it sh: add SMP support for J2 sh: SMP support for SH2 entry.S sh: add working futex atomic ops on userspace addresses for smp sh: add J2 atomics using the cas.l instruction sh: add AT_HWCAP flag for J-Core cas.l instruction sh: add support for J-Core J2 processor sh: fix build regression with CONFIG_OF && !CONFIG_OF_FLATTREE sh: allow clocksource drivers to register sched_clock backends sh: make heartbeat driver explicitly non-modular sh: make board-secureedge5410 explicitly non-modular sh: make mm/asids-debugfs explicitly non-modular sh: make time.c explicitly non-modular sh: fix futex/robust_list on nommu models sh: disable aliased page logic on NOMMU models ...
-rw-r--r--arch/sh/Kconfig34
-rw-r--r--arch/sh/Makefile3
-rw-r--r--arch/sh/boards/Kconfig1
-rw-r--r--arch/sh/boards/board-secureedge5410.c3
-rw-r--r--arch/sh/boards/of-generic.c15
-rw-r--r--arch/sh/boot/dts/Makefile3
-rwxr-xr-xarch/sh/boot/dts/j2_mimas_v2.dts96
-rw-r--r--arch/sh/configs/j2_defconfig40
-rw-r--r--arch/sh/drivers/heartbeat.c32
-rw-r--r--arch/sh/include/asm/atomic.h8
-rw-r--r--arch/sh/include/asm/barrier.h5
-rw-r--r--arch/sh/include/asm/bitops-cas.h93
-rw-r--r--arch/sh/include/asm/bitops.h2
-rw-r--r--arch/sh/include/asm/cmpxchg-cas.h24
-rw-r--r--arch/sh/include/asm/cmpxchg-xchg.h2
-rw-r--r--arch/sh/include/asm/cmpxchg.h2
-rw-r--r--arch/sh/include/asm/futex-cas.h34
-rw-r--r--arch/sh/include/asm/futex-irq.h86
-rw-r--r--arch/sh/include/asm/futex-llsc.h41
-rw-r--r--arch/sh/include/asm/futex.h97
-rw-r--r--arch/sh/include/asm/processor.h2
-rw-r--r--arch/sh/include/asm/spinlock-cas.h117
-rw-r--r--arch/sh/include/asm/spinlock-llsc.h224
-rw-r--r--arch/sh/include/asm/spinlock.h222
-rw-r--r--arch/sh/include/uapi/asm/cpu-features.h1
-rw-r--r--arch/sh/include/uapi/asm/sigcontext.h3
-rw-r--r--arch/sh/include/uapi/asm/unistd_32.h16
-rw-r--r--arch/sh/include/uapi/asm/unistd_64.h16
-rw-r--r--arch/sh/kernel/cpu/clock.c4
-rw-r--r--arch/sh/kernel/cpu/init.c6
-rw-r--r--arch/sh/kernel/cpu/proc.c1
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile4
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S55
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh2/smp-j2.c139
-rw-r--r--arch/sh/kernel/dwarf.c6
-rw-r--r--arch/sh/kernel/head_32.S6
-rw-r--r--arch/sh/kernel/setup.c6
-rw-r--r--arch/sh/kernel/syscalls_32.S14
-rw-r--r--arch/sh/kernel/syscalls_64.S14
-rw-r--r--arch/sh/kernel/time.c3
-rw-r--r--arch/sh/mm/Makefile3
-rw-r--r--arch/sh/mm/asids-debugfs.c5
-rw-r--r--arch/sh/mm/cache-j2.c65
-rw-r--r--arch/sh/mm/cache.c13
45 files changed, 1206 insertions, 399 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 0d5f3a9bb315..ee086958b2b2 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -38,6 +38,7 @@ config SUPERH
38 select GENERIC_IDLE_POLL_SETUP 38 select GENERIC_IDLE_POLL_SETUP
39 select GENERIC_CLOCKEVENTS 39 select GENERIC_CLOCKEVENTS
40 select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST 40 select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
41 select GENERIC_SCHED_CLOCK
41 select GENERIC_STRNCPY_FROM_USER 42 select GENERIC_STRNCPY_FROM_USER
42 select GENERIC_STRNLEN_USER 43 select GENERIC_STRNLEN_USER
43 select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER 44 select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
@@ -45,6 +46,7 @@ config SUPERH
45 select OLD_SIGSUSPEND 46 select OLD_SIGSUSPEND
46 select OLD_SIGACTION 47 select OLD_SIGACTION
47 select HAVE_ARCH_AUDITSYSCALL 48 select HAVE_ARCH_AUDITSYSCALL
49 select HAVE_FUTEX_CMPXCHG if FUTEX
48 select HAVE_NMI 50 select HAVE_NMI
49 help 51 help
50 The SuperH is a RISC processor targeted for use in embedded systems 52 The SuperH is a RISC processor targeted for use in embedded systems
@@ -184,6 +186,12 @@ config CPU_SH2A
184 select CPU_SH2 186 select CPU_SH2
185 select UNCACHED_MAPPING 187 select UNCACHED_MAPPING
186 188
189config CPU_J2
190 bool
191 select CPU_SH2
192 select OF
193 select OF_EARLY_FLATTREE
194
187config CPU_SH3 195config CPU_SH3
188 bool 196 bool
189 select CPU_HAS_INTEVT 197 select CPU_HAS_INTEVT
@@ -250,6 +258,12 @@ config CPU_SUBTYPE_SH7619
250 select CPU_SH2 258 select CPU_SH2
251 select SYS_SUPPORTS_SH_CMT 259 select SYS_SUPPORTS_SH_CMT
252 260
261config CPU_SUBTYPE_J2
262 bool "Support J2 processor"
263 select CPU_J2
264 select SYS_SUPPORTS_SMP
265 select GENERIC_CLOCKEVENTS_BROADCAST if SMP
266
253# SH-2A Processor Support 267# SH-2A Processor Support
254 268
255config CPU_SUBTYPE_SH7201 269config CPU_SUBTYPE_SH7201
@@ -739,6 +753,26 @@ endmenu
739 753
740menu "Boot options" 754menu "Boot options"
741 755
756config USE_BUILTIN_DTB
757 bool "Use builtin DTB"
758 default n
759 depends on SH_DEVICE_TREE
760 help
761 Link a device tree blob for particular hardware into the kernel,
762 suppressing use of the DTB pointer provided by the bootloader.
763 This option should only be used with legacy bootloaders that are
764 not capable of providing a DTB to the kernel, or for experimental
765 hardware without stable device tree bindings.
766
767config BUILTIN_DTB_SOURCE
768 string "Source file for builtin DTB"
769 default ""
770 depends on USE_BUILTIN_DTB
771 help
772 Base name (without suffix, relative to arch/sh/boot/dts) for the
773 a DTS file that will be used to produce the DTB linked into the
774 kernel.
775
742config ZERO_PAGE_OFFSET 776config ZERO_PAGE_OFFSET
743 hex 777 hex
744 default "0x00010000" if PAGE_SIZE_64KB || SH_RTS7751R2D || \ 778 default "0x00010000" if PAGE_SIZE_64KB || SH_RTS7751R2D || \
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index bf5b3f5f4962..00476662ac2c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -31,6 +31,7 @@ isa-y := $(isa-y)-up
31endif 31endif
32 32
33cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,) 33cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,)
34cflags-$(CONFIG_CPU_J2) := $(call cc-option,-mj2,)
34cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \ 35cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \
35 $(call cc-option,-m2a-nofpu,) \ 36 $(call cc-option,-m2a-nofpu,) \
36 $(call cc-option,-m4-nofpu,) 37 $(call cc-option,-m4-nofpu,)
@@ -130,6 +131,8 @@ head-y := arch/sh/kernel/head_$(BITS).o
130core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/ 131core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
131core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/ 132core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
132 133
134core-$(CONFIG_USE_BUILTIN_DTB) += arch/sh/boot/dts/
135
133# Mach groups 136# Mach groups
134machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se 137machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se
135machdir-$(CONFIG_SH_HP6XX) += mach-hp6xx 138machdir-$(CONFIG_SH_HP6XX) += mach-hp6xx
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index e0db04664e2e..e9c2c42031fe 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -11,6 +11,7 @@ config SH_DEVICE_TREE
11 select OF 11 select OF
12 select OF_EARLY_FLATTREE 12 select OF_EARLY_FLATTREE
13 select CLKSRC_OF 13 select CLKSRC_OF
14 select COMMON_CLK
14 select GENERIC_CALIBRATE_DELAY 15 select GENERIC_CALIBRATE_DELAY
15 help 16 help
16 Select Board Described by Device Tree to build a kernel that 17 Select Board Described by Device Tree to build a kernel that
diff --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c
index 98b36205aa7b..97ec67ffec2b 100644
--- a/arch/sh/boards/board-secureedge5410.c
+++ b/arch/sh/boards/board-secureedge5410.c
@@ -14,7 +14,6 @@
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/timer.h> 15#include <linux/timer.h>
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/module.h>
18#include <linux/sched.h> 17#include <linux/sched.h>
19#include <asm/machvec.h> 18#include <asm/machvec.h>
20#include <mach/secureedge5410.h> 19#include <mach/secureedge5410.h>
@@ -49,7 +48,7 @@ static int __init eraseconfig_init(void)
49 irq); 48 irq);
50 return 0; 49 return 0;
51} 50}
52module_init(eraseconfig_init); 51device_initcall(eraseconfig_init);
53 52
54/* 53/*
55 * Initialize IRQ setting 54 * Initialize IRQ setting
diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
index 911ffb9f115b..1fb6d5714bae 100644
--- a/arch/sh/boards/of-generic.c
+++ b/arch/sh/boards/of-generic.c
@@ -124,13 +124,22 @@ static void __init sh_of_time_init(void)
124 124
125static void __init sh_of_setup(char **cmdline_p) 125static void __init sh_of_setup(char **cmdline_p)
126{ 126{
127 struct device_node *root;
128
129#ifdef CONFIG_USE_BUILTIN_DTB
130 unflatten_and_copy_device_tree();
131#else
127 unflatten_device_tree(); 132 unflatten_device_tree();
133#endif
128 134
129 board_time_init = sh_of_time_init; 135 board_time_init = sh_of_time_init;
130 136
131 sh_mv.mv_name = of_flat_dt_get_machine_name(); 137 sh_mv.mv_name = "Unknown SH model";
132 if (!sh_mv.mv_name) 138 root = of_find_node_by_path("/");
133 sh_mv.mv_name = "Unknown SH model"; 139 if (root) {
140 of_property_read_string(root, "model", &sh_mv.mv_name);
141 of_node_put(root);
142 }
134 143
135 sh_of_smp_probe(); 144 sh_of_smp_probe();
136} 145}
diff --git a/arch/sh/boot/dts/Makefile b/arch/sh/boot/dts/Makefile
new file mode 100644
index 000000000000..e5ce3a0de7f4
--- /dev/null
+++ b/arch/sh/boot/dts/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_USE_BUILTIN_DTB) += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
2
3clean-files := *.dtb.S
diff --git a/arch/sh/boot/dts/j2_mimas_v2.dts b/arch/sh/boot/dts/j2_mimas_v2.dts
new file mode 100755
index 000000000000..880de75360b3
--- /dev/null
+++ b/arch/sh/boot/dts/j2_mimas_v2.dts
@@ -0,0 +1,96 @@
1/dts-v1/;
2
3/ {
4 compatible = "jcore,j2-soc";
5 model = "J2 FPGA SoC on Mimas v2 board";
6
7 #address-cells = <1>;
8 #size-cells = <1>;
9
10 interrupt-parent = <&aic>;
11
12 cpus {
13 #address-cells = <1>;
14 #size-cells = <0>;
15
16 cpu@0 {
17 device_type = "cpu";
18 compatible = "jcore,j2";
19 reg = <0>;
20 clock-frequency = <50000000>;
21 d-cache-size = <8192>;
22 i-cache-size = <8192>;
23 d-cache-block-size = <16>;
24 i-cache-block-size = <16>;
25 };
26 };
27
28 memory@10000000 {
29 device_type = "memory";
30 reg = <0x10000000 0x4000000>;
31 };
32
33 aliases {
34 serial0 = &uart0;
35 spi0 = &spi0;
36 };
37
38 chosen {
39 stdout-path = "serial0";
40 };
41
42 soc@abcd0000 {
43 compatible = "simple-bus";
44 ranges = <0 0xabcd0000 0x100000>;
45
46 #address-cells = <1>;
47 #size-cells = <1>;
48
49 aic: interrupt-controller@200 {
50 compatible = "jcore,aic1";
51 reg = <0x200 0x10>;
52 interrupt-controller;
53 #interrupt-cells = <1>;
54 };
55
56 cache-controller@c0 {
57 compatible = "jcore,cache";
58 reg = <0xc0 4>;
59 };
60
61 timer@200 {
62 compatible = "jcore,pit";
63 reg = <0x200 0x30>;
64 interrupts = <0x48>;
65 };
66
67 spi0: spi@40 {
68 compatible = "jcore,spi2";
69
70 #address-cells = <1>;
71 #size-cells = <0>;
72
73 spi-max-frequency = <25000000>;
74
75 reg = <0x40 0x8>;
76
77 sdcard@0 {
78 compatible = "mmc-spi-slot";
79 reg = <0>;
80 spi-max-frequency = <25000000>;
81 voltage-ranges = <3200 3400>;
82 mode = <0>;
83 };
84 };
85
86 uart0: serial@100 {
87 clock-frequency = <125000000>;
88 compatible = "xlnx,xps-uartlite-1.00.a";
89 current-speed = <19200>;
90 device_type = "serial";
91 interrupts = <0x12>;
92 port-number = <0>;
93 reg = <0x100 0x10>;
94 };
95 };
96};
diff --git a/arch/sh/configs/j2_defconfig b/arch/sh/configs/j2_defconfig
new file mode 100644
index 000000000000..94d1eca52f72
--- /dev/null
+++ b/arch/sh/configs/j2_defconfig
@@ -0,0 +1,40 @@
1CONFIG_SMP=y
2CONFIG_SYSVIPC=y
3CONFIG_POSIX_MQUEUE=y
4CONFIG_NO_HZ=y
5CONFIG_HIGH_RES_TIMERS=y
6CONFIG_CPU_SUBTYPE_J2=y
7CONFIG_MEMORY_START=0x10000000
8CONFIG_MEMORY_SIZE=0x04000000
9CONFIG_CPU_BIG_ENDIAN=y
10CONFIG_SH_DEVICE_TREE=y
11CONFIG_HZ_100=y
12CONFIG_CMDLINE_OVERWRITE=y
13CONFIG_CMDLINE="console=ttyUL0 earlycon"
14CONFIG_BINFMT_ELF_FDPIC=y
15CONFIG_BINFMT_FLAT=y
16CONFIG_NET=y
17CONFIG_PACKET=y
18CONFIG_UNIX=y
19CONFIG_INET=y
20CONFIG_DEVTMPFS=y
21CONFIG_DEVTMPFS_MOUNT=y
22CONFIG_NETDEVICES=y
23CONFIG_SERIAL_UARTLITE=y
24CONFIG_SERIAL_UARTLITE_CONSOLE=y
25CONFIG_I2C=y
26CONFIG_SPI=y
27CONFIG_SPI_JCORE=y
28CONFIG_WATCHDOG=y
29CONFIG_MMC=y
30CONFIG_MMC_SPI=y
31CONFIG_CLKSRC_JCORE_PIT=y
32CONFIG_JCORE_AIC=y
33CONFIG_EXT4_FS=y
34CONFIG_VFAT_FS=y
35CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
36CONFIG_FAT_DEFAULT_UTF8=y
37CONFIG_NLS_DEFAULT="utf8"
38CONFIG_NLS_CODEPAGE_437=y
39CONFIG_NLS_ASCII=y
40CONFIG_NLS_UTF8=y
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
index 7efc9c354fc7..49bace446a1a 100644
--- a/arch/sh/drivers/heartbeat.c
+++ b/arch/sh/drivers/heartbeat.c
@@ -19,7 +19,6 @@
19 * for more details. 19 * for more details.
20 */ 20 */
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/platform_device.h> 22#include <linux/platform_device.h>
24#include <linux/sched.h> 23#include <linux/sched.h>
25#include <linux/timer.h> 24#include <linux/timer.h>
@@ -139,26 +138,11 @@ static int heartbeat_drv_probe(struct platform_device *pdev)
139 return mod_timer(&hd->timer, jiffies + 1); 138 return mod_timer(&hd->timer, jiffies + 1);
140} 139}
141 140
142static int heartbeat_drv_remove(struct platform_device *pdev)
143{
144 struct heartbeat_data *hd = platform_get_drvdata(pdev);
145
146 del_timer_sync(&hd->timer);
147 iounmap(hd->base);
148
149 platform_set_drvdata(pdev, NULL);
150
151 if (!pdev->dev.platform_data)
152 kfree(hd);
153
154 return 0;
155}
156
157static struct platform_driver heartbeat_driver = { 141static struct platform_driver heartbeat_driver = {
158 .probe = heartbeat_drv_probe, 142 .probe = heartbeat_drv_probe,
159 .remove = heartbeat_drv_remove,
160 .driver = { 143 .driver = {
161 .name = DRV_NAME, 144 .name = DRV_NAME,
145 .suppress_bind_attrs = true,
162 }, 146 },
163}; 147};
164 148
@@ -167,14 +151,4 @@ static int __init heartbeat_init(void)
167 printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION); 151 printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
168 return platform_driver_register(&heartbeat_driver); 152 return platform_driver_register(&heartbeat_driver);
169} 153}
170 154device_initcall(heartbeat_init);
171static void __exit heartbeat_exit(void)
172{
173 platform_driver_unregister(&heartbeat_driver);
174}
175module_init(heartbeat_init);
176module_exit(heartbeat_exit);
177
178MODULE_VERSION(DRV_VERSION);
179MODULE_AUTHOR("Paul Mundt");
180MODULE_LICENSE("GPL v2");
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index c399e1c55685..8a7bd80c8b33 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -1,6 +1,12 @@
1#ifndef __ASM_SH_ATOMIC_H 1#ifndef __ASM_SH_ATOMIC_H
2#define __ASM_SH_ATOMIC_H 2#define __ASM_SH_ATOMIC_H
3 3
4#if defined(CONFIG_CPU_J2)
5
6#include <asm-generic/atomic.h>
7
8#else
9
4/* 10/*
5 * Atomic operations that C can't guarantee us. Useful for 11 * Atomic operations that C can't guarantee us. Useful for
6 * resource counting etc.. 12 * resource counting etc..
@@ -63,4 +69,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
63 return c; 69 return c;
64} 70}
65 71
72#endif /* CONFIG_CPU_J2 */
73
66#endif /* __ASM_SH_ATOMIC_H */ 74#endif /* __ASM_SH_ATOMIC_H */
diff --git a/arch/sh/include/asm/barrier.h b/arch/sh/include/asm/barrier.h
index 8a84e05adb2e..3c30b6e166b6 100644
--- a/arch/sh/include/asm/barrier.h
+++ b/arch/sh/include/asm/barrier.h
@@ -29,6 +29,11 @@
29#define wmb() mb() 29#define wmb() mb()
30#define ctrl_barrier() __icbi(PAGE_OFFSET) 30#define ctrl_barrier() __icbi(PAGE_OFFSET)
31#else 31#else
32#if defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
33#define __smp_mb() do { int tmp = 0; __asm__ __volatile__ ("cas.l %0,%0,@%1" : "+r"(tmp) : "z"(&tmp) : "memory", "t"); } while(0)
34#define __smp_rmb() __smp_mb()
35#define __smp_wmb() __smp_mb()
36#endif
32#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop") 37#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
33#endif 38#endif
34 39
diff --git a/arch/sh/include/asm/bitops-cas.h b/arch/sh/include/asm/bitops-cas.h
new file mode 100644
index 000000000000..88f793c04d3c
--- /dev/null
+++ b/arch/sh/include/asm/bitops-cas.h
@@ -0,0 +1,93 @@
1#ifndef __ASM_SH_BITOPS_CAS_H
2#define __ASM_SH_BITOPS_CAS_H
3
4static inline unsigned __bo_cas(volatile unsigned *p, unsigned old, unsigned new)
5{
6 __asm__ __volatile__("cas.l %1,%0,@r0"
7 : "+r"(new)
8 : "r"(old), "z"(p)
9 : "t", "memory" );
10 return new;
11}
12
13static inline void set_bit(int nr, volatile void *addr)
14{
15 unsigned mask, old;
16 volatile unsigned *a = addr;
17
18 a += nr >> 5;
19 mask = 1U << (nr & 0x1f);
20
21 do old = *a;
22 while (__bo_cas(a, old, old|mask) != old);
23}
24
25static inline void clear_bit(int nr, volatile void *addr)
26{
27 unsigned mask, old;
28 volatile unsigned *a = addr;
29
30 a += nr >> 5;
31 mask = 1U << (nr & 0x1f);
32
33 do old = *a;
34 while (__bo_cas(a, old, old&~mask) != old);
35}
36
37static inline void change_bit(int nr, volatile void *addr)
38{
39 unsigned mask, old;
40 volatile unsigned *a = addr;
41
42 a += nr >> 5;
43 mask = 1U << (nr & 0x1f);
44
45 do old = *a;
46 while (__bo_cas(a, old, old^mask) != old);
47}
48
49static inline int test_and_set_bit(int nr, volatile void *addr)
50{
51 unsigned mask, old;
52 volatile unsigned *a = addr;
53
54 a += nr >> 5;
55 mask = 1U << (nr & 0x1f);
56
57 do old = *a;
58 while (__bo_cas(a, old, old|mask) != old);
59
60 return !!(old & mask);
61}
62
63static inline int test_and_clear_bit(int nr, volatile void *addr)
64{
65 unsigned mask, old;
66 volatile unsigned *a = addr;
67
68 a += nr >> 5;
69 mask = 1U << (nr & 0x1f);
70
71 do old = *a;
72 while (__bo_cas(a, old, old&~mask) != old);
73
74 return !!(old & mask);
75}
76
77static inline int test_and_change_bit(int nr, volatile void *addr)
78{
79 unsigned mask, old;
80 volatile unsigned *a = addr;
81
82 a += nr >> 5;
83 mask = 1U << (nr & 0x1f);
84
85 do old = *a;
86 while (__bo_cas(a, old, old^mask) != old);
87
88 return !!(old & mask);
89}
90
91#include <asm-generic/bitops/non-atomic.h>
92
93#endif /* __ASM_SH_BITOPS_CAS_H */
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652cf173..a8699d60a8c4 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -18,6 +18,8 @@
18#include <asm/bitops-op32.h> 18#include <asm/bitops-op32.h>
19#elif defined(CONFIG_CPU_SH4A) 19#elif defined(CONFIG_CPU_SH4A)
20#include <asm/bitops-llsc.h> 20#include <asm/bitops-llsc.h>
21#elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
22#include <asm/bitops-cas.h>
21#else 23#else
22#include <asm-generic/bitops/atomic.h> 24#include <asm-generic/bitops/atomic.h>
23#include <asm-generic/bitops/non-atomic.h> 25#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/sh/include/asm/cmpxchg-cas.h b/arch/sh/include/asm/cmpxchg-cas.h
new file mode 100644
index 000000000000..d0d86649e8c1
--- /dev/null
+++ b/arch/sh/include/asm/cmpxchg-cas.h
@@ -0,0 +1,24 @@
1#ifndef __ASM_SH_CMPXCHG_CAS_H
2#define __ASM_SH_CMPXCHG_CAS_H
3
4static inline unsigned long
5__cmpxchg_u32(volatile u32 *m, unsigned long old, unsigned long new)
6{
7 __asm__ __volatile__("cas.l %1,%0,@r0"
8 : "+r"(new)
9 : "r"(old), "z"(m)
10 : "t", "memory" );
11 return new;
12}
13
14static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
15{
16 unsigned long old;
17 do old = *m;
18 while (__cmpxchg_u32(m, old, val) != old);
19 return old;
20}
21
22#include <asm/cmpxchg-xchg.h>
23
24#endif /* __ASM_SH_CMPXCHG_CAS_H */
diff --git a/arch/sh/include/asm/cmpxchg-xchg.h b/arch/sh/include/asm/cmpxchg-xchg.h
index 7219719c23a3..1e881f5db659 100644
--- a/arch/sh/include/asm/cmpxchg-xchg.h
+++ b/arch/sh/include/asm/cmpxchg-xchg.h
@@ -21,7 +21,7 @@ static inline u32 __xchg_cmpxchg(volatile void *ptr, u32 x, int size)
21 int off = (unsigned long)ptr % sizeof(u32); 21 int off = (unsigned long)ptr % sizeof(u32);
22 volatile u32 *p = ptr - off; 22 volatile u32 *p = ptr - off;
23#ifdef __BIG_ENDIAN 23#ifdef __BIG_ENDIAN
24 int bitoff = (sizeof(u32) - 1 - off) * BITS_PER_BYTE; 24 int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
25#else 25#else
26 int bitoff = off * BITS_PER_BYTE; 26 int bitoff = off * BITS_PER_BYTE;
27#endif 27#endif
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
index 5225916c1057..3dfe0467a773 100644
--- a/arch/sh/include/asm/cmpxchg.h
+++ b/arch/sh/include/asm/cmpxchg.h
@@ -13,6 +13,8 @@
13#include <asm/cmpxchg-grb.h> 13#include <asm/cmpxchg-grb.h>
14#elif defined(CONFIG_CPU_SH4A) 14#elif defined(CONFIG_CPU_SH4A)
15#include <asm/cmpxchg-llsc.h> 15#include <asm/cmpxchg-llsc.h>
16#elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
17#include <asm/cmpxchg-cas.h>
16#else 18#else
17#include <asm/cmpxchg-irq.h> 19#include <asm/cmpxchg-irq.h>
18#endif 20#endif
diff --git a/arch/sh/include/asm/futex-cas.h b/arch/sh/include/asm/futex-cas.h
new file mode 100644
index 000000000000..267cb7a5f101
--- /dev/null
+++ b/arch/sh/include/asm/futex-cas.h
@@ -0,0 +1,34 @@
1#ifndef __ASM_SH_FUTEX_CAS_H
2#define __ASM_SH_FUTEX_CAS_H
3
4static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
5 u32 __user *uaddr,
6 u32 oldval, u32 newval)
7{
8 int err = 0;
9 __asm__ __volatile__(
10 "1:\n\t"
11 "cas.l %2, %1, @r0\n"
12 "2:\n\t"
13#ifdef CONFIG_MMU
14 ".section .fixup,\"ax\"\n"
15 "3:\n\t"
16 "mov.l 4f, %0\n\t"
17 "jmp @%0\n\t"
18 " mov %3, %0\n\t"
19 ".balign 4\n"
20 "4: .long 2b\n\t"
21 ".previous\n"
22 ".section __ex_table,\"a\"\n\t"
23 ".long 1b, 3b\n\t"
24 ".previous"
25#endif
26 :"+r" (err), "+r" (newval)
27 :"r" (oldval), "i" (-EFAULT), "z" (uaddr)
28 :"t", "memory");
29 if (err) return err;
30 *uval = newval;
31 return 0;
32}
33
34#endif /* __ASM_SH_FUTEX_CAS_H */
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index 63d33129ea23..ab01dbee0a82 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -1,92 +1,6 @@
1#ifndef __ASM_SH_FUTEX_IRQ_H 1#ifndef __ASM_SH_FUTEX_IRQ_H
2#define __ASM_SH_FUTEX_IRQ_H 2#define __ASM_SH_FUTEX_IRQ_H
3 3
4
5static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
6 int *oldval)
7{
8 unsigned long flags;
9 int ret;
10
11 local_irq_save(flags);
12
13 ret = get_user(*oldval, uaddr);
14 if (!ret)
15 ret = put_user(oparg, uaddr);
16
17 local_irq_restore(flags);
18
19 return ret;
20}
21
22static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
23 int *oldval)
24{
25 unsigned long flags;
26 int ret;
27
28 local_irq_save(flags);
29
30 ret = get_user(*oldval, uaddr);
31 if (!ret)
32 ret = put_user(*oldval + oparg, uaddr);
33
34 local_irq_restore(flags);
35
36 return ret;
37}
38
39static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
40 int *oldval)
41{
42 unsigned long flags;
43 int ret;
44
45 local_irq_save(flags);
46
47 ret = get_user(*oldval, uaddr);
48 if (!ret)
49 ret = put_user(*oldval | oparg, uaddr);
50
51 local_irq_restore(flags);
52
53 return ret;
54}
55
56static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
57 int *oldval)
58{
59 unsigned long flags;
60 int ret;
61
62 local_irq_save(flags);
63
64 ret = get_user(*oldval, uaddr);
65 if (!ret)
66 ret = put_user(*oldval & oparg, uaddr);
67
68 local_irq_restore(flags);
69
70 return ret;
71}
72
73static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
74 int *oldval)
75{
76 unsigned long flags;
77 int ret;
78
79 local_irq_save(flags);
80
81 ret = get_user(*oldval, uaddr);
82 if (!ret)
83 ret = put_user(*oldval ^ oparg, uaddr);
84
85 local_irq_restore(flags);
86
87 return ret;
88}
89
90static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval, 4static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
91 u32 __user *uaddr, 5 u32 __user *uaddr,
92 u32 oldval, u32 newval) 6 u32 oldval, u32 newval)
diff --git a/arch/sh/include/asm/futex-llsc.h b/arch/sh/include/asm/futex-llsc.h
new file mode 100644
index 000000000000..23591703bec0
--- /dev/null
+++ b/arch/sh/include/asm/futex-llsc.h
@@ -0,0 +1,41 @@
1#ifndef __ASM_SH_FUTEX_LLSC_H
2#define __ASM_SH_FUTEX_LLSC_H
3
4static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
5 u32 __user *uaddr,
6 u32 oldval, u32 newval)
7{
8 int err = 0;
9 __asm__ __volatile__(
10 "synco\n"
11 "1:\n\t"
12 "movli.l @%2, r0\n\t"
13 "mov r0, %1\n\t"
14 "cmp/eq %1, %4\n\t"
15 "bf 2f\n\t"
16 "mov %5, r0\n\t"
17 "movco.l r0, @%2\n\t"
18 "bf 1b\n"
19 "2:\n\t"
20 "synco\n\t"
21#ifdef CONFIG_MMU
22 ".section .fixup,\"ax\"\n"
23 "3:\n\t"
24 "mov.l 4f, %0\n\t"
25 "jmp @%0\n\t"
26 " mov %3, %0\n\t"
27 ".balign 4\n"
28 "4: .long 2b\n\t"
29 ".previous\n"
30 ".section __ex_table,\"a\"\n\t"
31 ".long 1b, 3b\n\t"
32 ".previous"
33#endif
34 :"+r" (err), "=&r" (*uval)
35 :"r" (uaddr), "i" (-EFAULT), "r" (oldval), "r" (newval)
36 :"t", "memory", "r0");
37 if (err) return err;
38 return 0;
39}
40
41#endif /* __ASM_SH_FUTEX_LLSC_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 7be39a646fbd..d0078747d308 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -7,16 +7,34 @@
7#include <linux/uaccess.h> 7#include <linux/uaccess.h>
8#include <asm/errno.h> 8#include <asm/errno.h>
9 9
10/* XXX: UP variants, fix for SH-4A and SMP.. */ 10#if !defined(CONFIG_SMP)
11#include <asm/futex-irq.h> 11#include <asm/futex-irq.h>
12#elif defined(CONFIG_CPU_J2)
13#include <asm/futex-cas.h>
14#elif defined(CONFIG_CPU_SH4A)
15#include <asm/futex-llsc.h>
16#else
17#error SMP not supported on this configuration.
18#endif
19
20static inline int
21futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
22 u32 oldval, u32 newval)
23{
24 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
25 return -EFAULT;
26
27 return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
28}
12 29
13static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 30static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
14{ 31{
15 int op = (encoded_op >> 28) & 7; 32 int op = (encoded_op >> 28) & 7;
16 int cmp = (encoded_op >> 24) & 15; 33 int cmp = (encoded_op >> 24) & 15;
17 int oparg = (encoded_op << 8) >> 20; 34 u32 oparg = (encoded_op << 8) >> 20;
18 int cmparg = (encoded_op << 20) >> 20; 35 u32 cmparg = (encoded_op << 20) >> 20;
19 int oldval = 0, ret; 36 u32 oldval, newval, prev;
37 int ret;
20 38
21 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 39 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
22 oparg = 1 << oparg; 40 oparg = 1 << oparg;
@@ -26,26 +44,39 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
26 44
27 pagefault_disable(); 45 pagefault_disable();
28 46
29 switch (op) { 47 do {
30 case FUTEX_OP_SET: 48 if (op == FUTEX_OP_SET)
31 ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); 49 ret = oldval = 0;
32 break; 50 else
33 case FUTEX_OP_ADD: 51 ret = get_user(oldval, uaddr);
34 ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); 52
35 break; 53 if (ret) break;
36 case FUTEX_OP_OR: 54
37 ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); 55 switch (op) {
38 break; 56 case FUTEX_OP_SET:
39 case FUTEX_OP_ANDN: 57 newval = oparg;
40 ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); 58 break;
41 break; 59 case FUTEX_OP_ADD:
42 case FUTEX_OP_XOR: 60 newval = oldval + oparg;
43 ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); 61 break;
44 break; 62 case FUTEX_OP_OR:
45 default: 63 newval = oldval | oparg;
46 ret = -ENOSYS; 64 break;
47 break; 65 case FUTEX_OP_ANDN:
48 } 66 newval = oldval & ~oparg;
67 break;
68 case FUTEX_OP_XOR:
69 newval = oldval ^ oparg;
70 break;
71 default:
72 ret = -ENOSYS;
73 break;
74 }
75
76 if (ret) break;
77
78 ret = futex_atomic_cmpxchg_inatomic(&prev, uaddr, oldval, newval);
79 } while (!ret && prev != oldval);
49 80
50 pagefault_enable(); 81 pagefault_enable();
51 82
@@ -53,10 +84,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
53 switch (cmp) { 84 switch (cmp) {
54 case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; 85 case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
55 case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; 86 case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
56 case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; 87 case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;
57 case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; 88 case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;
58 case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; 89 case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;
59 case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; 90 case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;
60 default: ret = -ENOSYS; 91 default: ret = -ENOSYS;
61 } 92 }
62 } 93 }
@@ -64,15 +95,5 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
64 return ret; 95 return ret;
65} 96}
66 97
67static inline int
68futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
69 u32 oldval, u32 newval)
70{
71 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
72 return -EFAULT;
73
74 return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
75}
76
77#endif /* __KERNEL__ */ 98#endif /* __KERNEL__ */
78#endif /* __ASM_SH_FUTEX_H */ 99#endif /* __ASM_SH_FUTEX_H */
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 1506897648aa..f9a09942a32d 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -15,7 +15,7 @@
15 */ 15 */
16enum cpu_type { 16enum cpu_type {
17 /* SH-2 types */ 17 /* SH-2 types */
18 CPU_SH7619, 18 CPU_SH7619, CPU_J2,
19 19
20 /* SH-2A types */ 20 /* SH-2A types */
21 CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269, 21 CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269,
diff --git a/arch/sh/include/asm/spinlock-cas.h b/arch/sh/include/asm/spinlock-cas.h
new file mode 100644
index 000000000000..c46e8cc7b515
--- /dev/null
+++ b/arch/sh/include/asm/spinlock-cas.h
@@ -0,0 +1,117 @@
1/*
2 * include/asm-sh/spinlock-cas.h
3 *
4 * Copyright (C) 2015 SEI
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#ifndef __ASM_SH_SPINLOCK_CAS_H
11#define __ASM_SH_SPINLOCK_CAS_H
12
13#include <asm/barrier.h>
14#include <asm/processor.h>
15
16static inline unsigned __sl_cas(volatile unsigned *p, unsigned old, unsigned new)
17{
18 __asm__ __volatile__("cas.l %1,%0,@r0"
19 : "+r"(new)
20 : "r"(old), "z"(p)
21 : "t", "memory" );
22 return new;
23}
24
25/*
26 * Your basic SMP spinlocks, allowing only a single CPU anywhere
27 */
28
29#define arch_spin_is_locked(x) ((x)->lock <= 0)
30#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
31
32static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
33{
34 smp_cond_load_acquire(&lock->lock, VAL > 0);
35}
36
37static inline void arch_spin_lock(arch_spinlock_t *lock)
38{
39 while (!__sl_cas(&lock->lock, 1, 0));
40}
41
42static inline void arch_spin_unlock(arch_spinlock_t *lock)
43{
44 __sl_cas(&lock->lock, 0, 1);
45}
46
47static inline int arch_spin_trylock(arch_spinlock_t *lock)
48{
49 return __sl_cas(&lock->lock, 1, 0);
50}
51
52/*
53 * Read-write spinlocks, allowing multiple readers but only one writer.
54 *
55 * NOTE! it is quite common to have readers in interrupts but no interrupt
56 * writers. For those circumstances we can "mix" irq-safe locks - any writer
57 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
58 * read-locks.
59 */
60
61/**
62 * read_can_lock - would read_trylock() succeed?
63 * @lock: the rwlock in question.
64 */
65#define arch_read_can_lock(x) ((x)->lock > 0)
66
67/**
68 * write_can_lock - would write_trylock() succeed?
69 * @lock: the rwlock in question.
70 */
71#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
72
73static inline void arch_read_lock(arch_rwlock_t *rw)
74{
75 unsigned old;
76 do old = rw->lock;
77 while (!old || __sl_cas(&rw->lock, old, old-1) != old);
78}
79
80static inline void arch_read_unlock(arch_rwlock_t *rw)
81{
82 unsigned old;
83 do old = rw->lock;
84 while (__sl_cas(&rw->lock, old, old+1) != old);
85}
86
87static inline void arch_write_lock(arch_rwlock_t *rw)
88{
89 while (__sl_cas(&rw->lock, RW_LOCK_BIAS, 0) != RW_LOCK_BIAS);
90}
91
92static inline void arch_write_unlock(arch_rwlock_t *rw)
93{
94 __sl_cas(&rw->lock, 0, RW_LOCK_BIAS);
95}
96
97static inline int arch_read_trylock(arch_rwlock_t *rw)
98{
99 unsigned old;
100 do old = rw->lock;
101 while (old && __sl_cas(&rw->lock, old, old-1) != old);
102 return !!old;
103}
104
105static inline int arch_write_trylock(arch_rwlock_t *rw)
106{
107 return __sl_cas(&rw->lock, RW_LOCK_BIAS, 0) == RW_LOCK_BIAS;
108}
109
110#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
111#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
112
113#define arch_spin_relax(lock) cpu_relax()
114#define arch_read_relax(lock) cpu_relax()
115#define arch_write_relax(lock) cpu_relax()
116
117#endif /* __ASM_SH_SPINLOCK_CAS_H */
diff --git a/arch/sh/include/asm/spinlock-llsc.h b/arch/sh/include/asm/spinlock-llsc.h
new file mode 100644
index 000000000000..cec78143fa83
--- /dev/null
+++ b/arch/sh/include/asm/spinlock-llsc.h
@@ -0,0 +1,224 @@
1/*
2 * include/asm-sh/spinlock-llsc.h
3 *
4 * Copyright (C) 2002, 2003 Paul Mundt
5 * Copyright (C) 2006, 2007 Akio Idehara
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11#ifndef __ASM_SH_SPINLOCK_LLSC_H
12#define __ASM_SH_SPINLOCK_LLSC_H
13
14#include <asm/barrier.h>
15#include <asm/processor.h>
16
17/*
18 * Your basic SMP spinlocks, allowing only a single CPU anywhere
19 */
20
21#define arch_spin_is_locked(x) ((x)->lock <= 0)
22#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
23
24static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
25{
26 smp_cond_load_acquire(&lock->lock, VAL > 0);
27}
28
29/*
30 * Simple spin lock operations. There are two variants, one clears IRQ's
31 * on the local processor, one does not.
32 *
33 * We make no fairness assumptions. They have a cost.
34 */
35static inline void arch_spin_lock(arch_spinlock_t *lock)
36{
37 unsigned long tmp;
38 unsigned long oldval;
39
40 __asm__ __volatile__ (
41 "1: \n\t"
42 "movli.l @%2, %0 ! arch_spin_lock \n\t"
43 "mov %0, %1 \n\t"
44 "mov #0, %0 \n\t"
45 "movco.l %0, @%2 \n\t"
46 "bf 1b \n\t"
47 "cmp/pl %1 \n\t"
48 "bf 1b \n\t"
49 : "=&z" (tmp), "=&r" (oldval)
50 : "r" (&lock->lock)
51 : "t", "memory"
52 );
53}
54
55static inline void arch_spin_unlock(arch_spinlock_t *lock)
56{
57 unsigned long tmp;
58
59 __asm__ __volatile__ (
60 "mov #1, %0 ! arch_spin_unlock \n\t"
61 "mov.l %0, @%1 \n\t"
62 : "=&z" (tmp)
63 : "r" (&lock->lock)
64 : "t", "memory"
65 );
66}
67
68static inline int arch_spin_trylock(arch_spinlock_t *lock)
69{
70 unsigned long tmp, oldval;
71
72 __asm__ __volatile__ (
73 "1: \n\t"
74 "movli.l @%2, %0 ! arch_spin_trylock \n\t"
75 "mov %0, %1 \n\t"
76 "mov #0, %0 \n\t"
77 "movco.l %0, @%2 \n\t"
78 "bf 1b \n\t"
79 "synco \n\t"
80 : "=&z" (tmp), "=&r" (oldval)
81 : "r" (&lock->lock)
82 : "t", "memory"
83 );
84
85 return oldval;
86}
87
88/*
89 * Read-write spinlocks, allowing multiple readers but only one writer.
90 *
91 * NOTE! it is quite common to have readers in interrupts but no interrupt
92 * writers. For those circumstances we can "mix" irq-safe locks - any writer
93 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
94 * read-locks.
95 */
96
97/**
98 * read_can_lock - would read_trylock() succeed?
99 * @lock: the rwlock in question.
100 */
101#define arch_read_can_lock(x) ((x)->lock > 0)
102
103/**
104 * write_can_lock - would write_trylock() succeed?
105 * @lock: the rwlock in question.
106 */
107#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
108
109static inline void arch_read_lock(arch_rwlock_t *rw)
110{
111 unsigned long tmp;
112
113 __asm__ __volatile__ (
114 "1: \n\t"
115 "movli.l @%1, %0 ! arch_read_lock \n\t"
116 "cmp/pl %0 \n\t"
117 "bf 1b \n\t"
118 "add #-1, %0 \n\t"
119 "movco.l %0, @%1 \n\t"
120 "bf 1b \n\t"
121 : "=&z" (tmp)
122 : "r" (&rw->lock)
123 : "t", "memory"
124 );
125}
126
127static inline void arch_read_unlock(arch_rwlock_t *rw)
128{
129 unsigned long tmp;
130
131 __asm__ __volatile__ (
132 "1: \n\t"
133 "movli.l @%1, %0 ! arch_read_unlock \n\t"
134 "add #1, %0 \n\t"
135 "movco.l %0, @%1 \n\t"
136 "bf 1b \n\t"
137 : "=&z" (tmp)
138 : "r" (&rw->lock)
139 : "t", "memory"
140 );
141}
142
143static inline void arch_write_lock(arch_rwlock_t *rw)
144{
145 unsigned long tmp;
146
147 __asm__ __volatile__ (
148 "1: \n\t"
149 "movli.l @%1, %0 ! arch_write_lock \n\t"
150 "cmp/hs %2, %0 \n\t"
151 "bf 1b \n\t"
152 "sub %2, %0 \n\t"
153 "movco.l %0, @%1 \n\t"
154 "bf 1b \n\t"
155 : "=&z" (tmp)
156 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
157 : "t", "memory"
158 );
159}
160
161static inline void arch_write_unlock(arch_rwlock_t *rw)
162{
163 __asm__ __volatile__ (
164 "mov.l %1, @%0 ! arch_write_unlock \n\t"
165 :
166 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
167 : "t", "memory"
168 );
169}
170
171static inline int arch_read_trylock(arch_rwlock_t *rw)
172{
173 unsigned long tmp, oldval;
174
175 __asm__ __volatile__ (
176 "1: \n\t"
177 "movli.l @%2, %0 ! arch_read_trylock \n\t"
178 "mov %0, %1 \n\t"
179 "cmp/pl %0 \n\t"
180 "bf 2f \n\t"
181 "add #-1, %0 \n\t"
182 "movco.l %0, @%2 \n\t"
183 "bf 1b \n\t"
184 "2: \n\t"
185 "synco \n\t"
186 : "=&z" (tmp), "=&r" (oldval)
187 : "r" (&rw->lock)
188 : "t", "memory"
189 );
190
191 return (oldval > 0);
192}
193
194static inline int arch_write_trylock(arch_rwlock_t *rw)
195{
196 unsigned long tmp, oldval;
197
198 __asm__ __volatile__ (
199 "1: \n\t"
200 "movli.l @%2, %0 ! arch_write_trylock \n\t"
201 "mov %0, %1 \n\t"
202 "cmp/hs %3, %0 \n\t"
203 "bf 2f \n\t"
204 "sub %3, %0 \n\t"
205 "2: \n\t"
206 "movco.l %0, @%2 \n\t"
207 "bf 1b \n\t"
208 "synco \n\t"
209 : "=&z" (tmp), "=&r" (oldval)
210 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
211 : "t", "memory"
212 );
213
214 return (oldval > (RW_LOCK_BIAS - 1));
215}
216
217#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
218#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
219
220#define arch_spin_relax(lock) cpu_relax()
221#define arch_read_relax(lock) cpu_relax()
222#define arch_write_relax(lock) cpu_relax()
223
224#endif /* __ASM_SH_SPINLOCK_LLSC_H */
diff --git a/arch/sh/include/asm/spinlock.h b/arch/sh/include/asm/spinlock.h
index 416834b60ad0..c2c61ea6a8e2 100644
--- a/arch/sh/include/asm/spinlock.h
+++ b/arch/sh/include/asm/spinlock.h
@@ -11,222 +11,12 @@
11#ifndef __ASM_SH_SPINLOCK_H 11#ifndef __ASM_SH_SPINLOCK_H
12#define __ASM_SH_SPINLOCK_H 12#define __ASM_SH_SPINLOCK_H
13 13
14/* 14#if defined(CONFIG_CPU_SH4A)
15 * The only locking implemented here uses SH-4A opcodes. For others, 15#include <asm/spinlock-llsc.h>
16 * split this out as per atomic-*.h. 16#elif defined(CONFIG_CPU_J2)
17 */ 17#include <asm/spinlock-cas.h>
18#ifndef CONFIG_CPU_SH4A 18#else
19#error "Need movli.l/movco.l for spinlocks" 19#error "The configured cpu type does not support spinlocks"
20#endif 20#endif
21 21
22#include <asm/barrier.h>
23#include <asm/processor.h>
24
25/*
26 * Your basic SMP spinlocks, allowing only a single CPU anywhere
27 */
28
29#define arch_spin_is_locked(x) ((x)->lock <= 0)
30#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
31
32static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
33{
34 smp_cond_load_acquire(&lock->lock, VAL > 0);
35}
36
37/*
38 * Simple spin lock operations. There are two variants, one clears IRQ's
39 * on the local processor, one does not.
40 *
41 * We make no fairness assumptions. They have a cost.
42 */
43static inline void arch_spin_lock(arch_spinlock_t *lock)
44{
45 unsigned long tmp;
46 unsigned long oldval;
47
48 __asm__ __volatile__ (
49 "1: \n\t"
50 "movli.l @%2, %0 ! arch_spin_lock \n\t"
51 "mov %0, %1 \n\t"
52 "mov #0, %0 \n\t"
53 "movco.l %0, @%2 \n\t"
54 "bf 1b \n\t"
55 "cmp/pl %1 \n\t"
56 "bf 1b \n\t"
57 : "=&z" (tmp), "=&r" (oldval)
58 : "r" (&lock->lock)
59 : "t", "memory"
60 );
61}
62
63static inline void arch_spin_unlock(arch_spinlock_t *lock)
64{
65 unsigned long tmp;
66
67 __asm__ __volatile__ (
68 "mov #1, %0 ! arch_spin_unlock \n\t"
69 "mov.l %0, @%1 \n\t"
70 : "=&z" (tmp)
71 : "r" (&lock->lock)
72 : "t", "memory"
73 );
74}
75
76static inline int arch_spin_trylock(arch_spinlock_t *lock)
77{
78 unsigned long tmp, oldval;
79
80 __asm__ __volatile__ (
81 "1: \n\t"
82 "movli.l @%2, %0 ! arch_spin_trylock \n\t"
83 "mov %0, %1 \n\t"
84 "mov #0, %0 \n\t"
85 "movco.l %0, @%2 \n\t"
86 "bf 1b \n\t"
87 "synco \n\t"
88 : "=&z" (tmp), "=&r" (oldval)
89 : "r" (&lock->lock)
90 : "t", "memory"
91 );
92
93 return oldval;
94}
95
96/*
97 * Read-write spinlocks, allowing multiple readers but only one writer.
98 *
99 * NOTE! it is quite common to have readers in interrupts but no interrupt
100 * writers. For those circumstances we can "mix" irq-safe locks - any writer
101 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
102 * read-locks.
103 */
104
105/**
106 * read_can_lock - would read_trylock() succeed?
107 * @lock: the rwlock in question.
108 */
109#define arch_read_can_lock(x) ((x)->lock > 0)
110
111/**
112 * write_can_lock - would write_trylock() succeed?
113 * @lock: the rwlock in question.
114 */
115#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
116
117static inline void arch_read_lock(arch_rwlock_t *rw)
118{
119 unsigned long tmp;
120
121 __asm__ __volatile__ (
122 "1: \n\t"
123 "movli.l @%1, %0 ! arch_read_lock \n\t"
124 "cmp/pl %0 \n\t"
125 "bf 1b \n\t"
126 "add #-1, %0 \n\t"
127 "movco.l %0, @%1 \n\t"
128 "bf 1b \n\t"
129 : "=&z" (tmp)
130 : "r" (&rw->lock)
131 : "t", "memory"
132 );
133}
134
135static inline void arch_read_unlock(arch_rwlock_t *rw)
136{
137 unsigned long tmp;
138
139 __asm__ __volatile__ (
140 "1: \n\t"
141 "movli.l @%1, %0 ! arch_read_unlock \n\t"
142 "add #1, %0 \n\t"
143 "movco.l %0, @%1 \n\t"
144 "bf 1b \n\t"
145 : "=&z" (tmp)
146 : "r" (&rw->lock)
147 : "t", "memory"
148 );
149}
150
151static inline void arch_write_lock(arch_rwlock_t *rw)
152{
153 unsigned long tmp;
154
155 __asm__ __volatile__ (
156 "1: \n\t"
157 "movli.l @%1, %0 ! arch_write_lock \n\t"
158 "cmp/hs %2, %0 \n\t"
159 "bf 1b \n\t"
160 "sub %2, %0 \n\t"
161 "movco.l %0, @%1 \n\t"
162 "bf 1b \n\t"
163 : "=&z" (tmp)
164 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
165 : "t", "memory"
166 );
167}
168
169static inline void arch_write_unlock(arch_rwlock_t *rw)
170{
171 __asm__ __volatile__ (
172 "mov.l %1, @%0 ! arch_write_unlock \n\t"
173 :
174 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
175 : "t", "memory"
176 );
177}
178
179static inline int arch_read_trylock(arch_rwlock_t *rw)
180{
181 unsigned long tmp, oldval;
182
183 __asm__ __volatile__ (
184 "1: \n\t"
185 "movli.l @%2, %0 ! arch_read_trylock \n\t"
186 "mov %0, %1 \n\t"
187 "cmp/pl %0 \n\t"
188 "bf 2f \n\t"
189 "add #-1, %0 \n\t"
190 "movco.l %0, @%2 \n\t"
191 "bf 1b \n\t"
192 "2: \n\t"
193 "synco \n\t"
194 : "=&z" (tmp), "=&r" (oldval)
195 : "r" (&rw->lock)
196 : "t", "memory"
197 );
198
199 return (oldval > 0);
200}
201
202static inline int arch_write_trylock(arch_rwlock_t *rw)
203{
204 unsigned long tmp, oldval;
205
206 __asm__ __volatile__ (
207 "1: \n\t"
208 "movli.l @%2, %0 ! arch_write_trylock \n\t"
209 "mov %0, %1 \n\t"
210 "cmp/hs %3, %0 \n\t"
211 "bf 2f \n\t"
212 "sub %3, %0 \n\t"
213 "2: \n\t"
214 "movco.l %0, @%2 \n\t"
215 "bf 1b \n\t"
216 "synco \n\t"
217 : "=&z" (tmp), "=&r" (oldval)
218 : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
219 : "t", "memory"
220 );
221
222 return (oldval > (RW_LOCK_BIAS - 1));
223}
224
225#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
226#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
227
228#define arch_spin_relax(lock) cpu_relax()
229#define arch_read_relax(lock) cpu_relax()
230#define arch_write_relax(lock) cpu_relax()
231
232#endif /* __ASM_SH_SPINLOCK_H */ 22#endif /* __ASM_SH_SPINLOCK_H */
diff --git a/arch/sh/include/uapi/asm/cpu-features.h b/arch/sh/include/uapi/asm/cpu-features.h
index 694abe490edb..2f1bc851042a 100644
--- a/arch/sh/include/uapi/asm/cpu-features.h
+++ b/arch/sh/include/uapi/asm/cpu-features.h
@@ -22,5 +22,6 @@
22#define CPU_HAS_L2_CACHE 0x0080 /* Secondary cache / URAM */ 22#define CPU_HAS_L2_CACHE 0x0080 /* Secondary cache / URAM */
23#define CPU_HAS_OP32 0x0100 /* 32-bit instruction support */ 23#define CPU_HAS_OP32 0x0100 /* 32-bit instruction support */
24#define CPU_HAS_PTEAEX 0x0200 /* PTE ASID Extension support */ 24#define CPU_HAS_PTEAEX 0x0200 /* PTE ASID Extension support */
25#define CPU_HAS_CAS_L 0x0400 /* cas.l atomic compare-and-swap */
25 26
26#endif /* __ASM_SH_CPU_FEATURES_H */ 27#endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/arch/sh/include/uapi/asm/sigcontext.h b/arch/sh/include/uapi/asm/sigcontext.h
index 8ce1435bc0bf..faa5d0833412 100644
--- a/arch/sh/include/uapi/asm/sigcontext.h
+++ b/arch/sh/include/uapi/asm/sigcontext.h
@@ -25,8 +25,6 @@ struct sigcontext {
25 unsigned long sc_mach; 25 unsigned long sc_mach;
26 unsigned long sc_macl; 26 unsigned long sc_macl;
27 27
28#if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \
29 defined(__SH2A__) || defined(CONFIG_CPU_SH2A)
30 /* FPU registers */ 28 /* FPU registers */
31 unsigned long sc_fpregs[16]; 29 unsigned long sc_fpregs[16];
32 unsigned long sc_xfpregs[16]; 30 unsigned long sc_xfpregs[16];
@@ -34,7 +32,6 @@ struct sigcontext {
34 unsigned int sc_fpul; 32 unsigned int sc_fpul;
35 unsigned int sc_ownedfp; 33 unsigned int sc_ownedfp;
36#endif 34#endif
37#endif
38}; 35};
39 36
40#endif /* __ASM_SH_SIGCONTEXT_H */ 37#endif /* __ASM_SH_SIGCONTEXT_H */
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h
index d13a1d623736..c801bde9e6f5 100644
--- a/arch/sh/include/uapi/asm/unistd_32.h
+++ b/arch/sh/include/uapi/asm/unistd_32.h
@@ -380,7 +380,21 @@
380#define __NR_process_vm_writev 366 380#define __NR_process_vm_writev 366
381#define __NR_kcmp 367 381#define __NR_kcmp 367
382#define __NR_finit_module 368 382#define __NR_finit_module 368
383#define __NR_sched_getattr 369
384#define __NR_sched_setattr 370
385#define __NR_renameat2 371
386#define __NR_seccomp 372
387#define __NR_getrandom 373
388#define __NR_memfd_create 374
389#define __NR_bpf 375
390#define __NR_execveat 376
391#define __NR_userfaultfd 377
392#define __NR_membarrier 378
393#define __NR_mlock2 379
394#define __NR_copy_file_range 380
395#define __NR_preadv2 381
396#define __NR_pwritev2 382
383 397
384#define NR_syscalls 369 398#define NR_syscalls 383
385 399
386#endif /* __ASM_SH_UNISTD_32_H */ 400#endif /* __ASM_SH_UNISTD_32_H */
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
index 47ebd5b5ed55..ce0cb3598b62 100644
--- a/arch/sh/include/uapi/asm/unistd_64.h
+++ b/arch/sh/include/uapi/asm/unistd_64.h
@@ -400,7 +400,21 @@
400#define __NR_process_vm_writev 377 400#define __NR_process_vm_writev 377
401#define __NR_kcmp 378 401#define __NR_kcmp 378
402#define __NR_finit_module 379 402#define __NR_finit_module 379
403#define __NR_sched_getattr 380
404#define __NR_sched_setattr 381
405#define __NR_renameat2 382
406#define __NR_seccomp 383
407#define __NR_getrandom 384
408#define __NR_memfd_create 385
409#define __NR_bpf 386
410#define __NR_execveat 387
411#define __NR_userfaultfd 388
412#define __NR_membarrier 389
413#define __NR_mlock2 390
414#define __NR_copy_file_range 391
415#define __NR_preadv2 392
416#define __NR_pwritev2 393
403 417
404#define NR_syscalls 380 418#define NR_syscalls 394
405 419
406#endif /* __ASM_SH_UNISTD_64_H */ 420#endif /* __ASM_SH_UNISTD_64_H */
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 4187cf4fe185..fca9b1e78a63 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -24,11 +24,13 @@ int __init clk_init(void)
24{ 24{
25 int ret; 25 int ret;
26 26
27#ifndef CONFIG_COMMON_CLK
27 ret = arch_clk_init(); 28 ret = arch_clk_init();
28 if (unlikely(ret)) { 29 if (unlikely(ret)) {
29 pr_err("%s: CPU clock registration failed.\n", __func__); 30 pr_err("%s: CPU clock registration failed.\n", __func__);
30 return ret; 31 return ret;
31 } 32 }
33#endif
32 34
33 if (sh_mv.mv_clk_init) { 35 if (sh_mv.mv_clk_init) {
34 ret = sh_mv.mv_clk_init(); 36 ret = sh_mv.mv_clk_init();
@@ -39,11 +41,13 @@ int __init clk_init(void)
39 } 41 }
40 } 42 }
41 43
44#ifndef CONFIG_COMMON_CLK
42 /* Kick the child clocks.. */ 45 /* Kick the child clocks.. */
43 recalculate_root_clocks(); 46 recalculate_root_clocks();
44 47
45 /* Enable the necessary init clocks */ 48 /* Enable the necessary init clocks */
46 clk_enable_init_clocks(); 49 clk_enable_init_clocks();
50#endif
47 51
48 return ret; 52 return ret;
49} 53}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 0d7360d549c1..c8b3be1b54e6 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void)
106/* 106/*
107 * Generic first-level cache init 107 * Generic first-level cache init
108 */ 108 */
109#ifdef CONFIG_SUPERH32 109#if defined(CONFIG_SUPERH32) && !defined(CONFIG_CPU_J2)
110static void cache_init(void) 110static void cache_init(void)
111{ 111{
112 unsigned long ccr, flags; 112 unsigned long ccr, flags;
@@ -323,9 +323,13 @@ asmlinkage void cpu_init(void)
323 cache_init(); 323 cache_init();
324 324
325 if (raw_smp_processor_id() == 0) { 325 if (raw_smp_processor_id() == 0) {
326#ifdef CONFIG_MMU
326 shm_align_mask = max_t(unsigned long, 327 shm_align_mask = max_t(unsigned long,
327 current_cpu_data.dcache.way_size - 1, 328 current_cpu_data.dcache.way_size - 1,
328 PAGE_SIZE - 1); 329 PAGE_SIZE - 1);
330#else
331 shm_align_mask = PAGE_SIZE - 1;
332#endif
329 333
330 /* Boot CPU sets the cache shape */ 334 /* Boot CPU sets the cache shape */
331 detect_cache_shape(); 335 detect_cache_shape();
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
index 9e6624c9108b..4df4b284f591 100644
--- a/arch/sh/kernel/cpu/proc.c
+++ b/arch/sh/kernel/cpu/proc.c
@@ -27,6 +27,7 @@ static const char *cpu_name[] = {
27 [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723", 27 [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
28 [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724", 28 [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
29 [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734", 29 [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
30 [CPU_J2] = "J2",
30 [CPU_SH_NONE] = "Unknown" 31 [CPU_SH_NONE] = "Unknown"
31}; 32};
32 33
diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile
index f0f059acfcfb..904c4283d923 100644
--- a/arch/sh/kernel/cpu/sh2/Makefile
+++ b/arch/sh/kernel/cpu/sh2/Makefile
@@ -5,3 +5,7 @@
5obj-y := ex.o probe.o entry.o 5obj-y := ex.o probe.o entry.o
6 6
7obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o 7obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
8
9# SMP setup
10smp-$(CONFIG_CPU_J2) := smp-j2.o
11obj-$(CONFIG_SMP) += $(smp-y)
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index a1505956ef28..1ee0a6e774c6 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -47,6 +47,13 @@ ENTRY(exception_handler)
47 mov.l r3,@-sp 47 mov.l r3,@-sp
48 cli 48 cli
49 mov.l $cpu_mode,r2 49 mov.l $cpu_mode,r2
50#ifdef CONFIG_SMP
51 mov.l $cpuid,r3
52 mov.l @r3,r3
53 mov.l @r3,r3
54 shll2 r3
55 add r3,r2
56#endif
50 mov.l @r2,r0 57 mov.l @r2,r0
51 mov.l @(5*4,r15),r3 ! previous SR 58 mov.l @(5*4,r15),r3 ! previous SR
52 or r0,r3 ! set MD 59 or r0,r3 ! set MD
@@ -57,6 +64,13 @@ ENTRY(exception_handler)
57 mov.l __md_bit,r0 64 mov.l __md_bit,r0
58 mov.l r0,@r2 ! enter kernel mode 65 mov.l r0,@r2 ! enter kernel mode
59 mov.l $current_thread_info,r2 66 mov.l $current_thread_info,r2
67#ifdef CONFIG_SMP
68 mov.l $cpuid,r0
69 mov.l @r0,r0
70 mov.l @r0,r0
71 shll2 r0
72 add r0,r2
73#endif
60 mov.l @r2,r2 74 mov.l @r2,r2
61 mov #(THREAD_SIZE >> 8),r0 75 mov #(THREAD_SIZE >> 8),r0
62 shll8 r0 76 shll8 r0
@@ -147,6 +161,11 @@ ENTRY(exception_handler)
147 mov #31,r8 161 mov #31,r8
148 cmp/hs r8,r9 162 cmp/hs r8,r9
149 bt trap_entry ! 64 > vec >= 31 is trap 163 bt trap_entry ! 64 > vec >= 31 is trap
164#ifdef CONFIG_CPU_J2
165 mov #16,r8
166 cmp/hs r8,r9
167 bt interrupt_entry ! 31 > vec >= 16 is interrupt
168#endif
150 169
151 mov.l 4f,r8 170 mov.l 4f,r8
152 mov r9,r4 171 mov r9,r4
@@ -260,6 +279,13 @@ restore_all:
260 lds.l @r0+,macl 279 lds.l @r0+,macl
261 mov r15,r0 280 mov r15,r0
262 mov.l $cpu_mode,r2 281 mov.l $cpu_mode,r2
282#ifdef CONFIG_SMP
283 mov.l $cpuid,r3
284 mov.l @r3,r3
285 mov.l @r3,r3
286 shll2 r3
287 add r3,r2
288#endif
263 mov #OFF_SR,r3 289 mov #OFF_SR,r3
264 mov.l @(r0,r3),r1 290 mov.l @(r0,r3),r1
265 mov.l __md_bit,r3 291 mov.l __md_bit,r3
@@ -276,6 +302,13 @@ restore_all:
276 mov.l r1,@r2 ! set pc 302 mov.l r1,@r2 ! set pc
277 get_current_thread_info r0, r1 303 get_current_thread_info r0, r1
278 mov.l $current_thread_info,r1 304 mov.l $current_thread_info,r1
305#ifdef CONFIG_SMP
306 mov.l $cpuid,r3
307 mov.l @r3,r3
308 mov.l @r3,r3
309 shll2 r3
310 add r3,r1
311#endif
279 mov.l r0,@r1 312 mov.l r0,@r1
280 mov.l @r15+,r0 313 mov.l @r15+,r0
281 mov.l @r15+,r1 314 mov.l @r15+,r1
@@ -303,19 +336,41 @@ $current_thread_info:
303 .long __current_thread_info 336 .long __current_thread_info
304$cpu_mode: 337$cpu_mode:
305 .long __cpu_mode 338 .long __cpu_mode
339#ifdef CONFIG_SMP
340$cpuid:
341 .long sh2_cpuid_addr
342#endif
306 343
307! common exception handler 344! common exception handler
308#include "../../entry-common.S" 345#include "../../entry-common.S"
346
347#ifdef CONFIG_NR_CPUS
348#define NR_CPUS CONFIG_NR_CPUS
349#else
350#define NR_CPUS 1
351#endif
309 352
310 .data 353 .data
311! cpu operation mode 354! cpu operation mode
312! bit30 = MD (compatible SH3/4) 355! bit30 = MD (compatible SH3/4)
313__cpu_mode: 356__cpu_mode:
357 .rept NR_CPUS
314 .long 0x40000000 358 .long 0x40000000
359 .endr
360
361#ifdef CONFIG_SMP
362.global sh2_cpuid_addr
363sh2_cpuid_addr:
364 .long dummy_cpuid
365dummy_cpuid:
366 .long 0
367#endif
315 368
316 .section .bss 369 .section .bss
317__current_thread_info: 370__current_thread_info:
371 .rept NR_CPUS
318 .long 0 372 .long 0
373 .endr
319 374
320ENTRY(exception_handling_table) 375ENTRY(exception_handling_table)
321 .space 4*32 376 .space 4*32
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 6c687ae812ef..4205f6d42b69 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -10,10 +10,27 @@
10 * for more details. 10 * for more details.
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/of_fdt.h>
14#include <linux/smp.h>
15#include <linux/io.h>
13#include <asm/processor.h> 16#include <asm/processor.h>
14#include <asm/cache.h> 17#include <asm/cache.h>
15 18
16void cpu_probe(void) 19#if defined(CONFIG_CPU_J2)
20extern u32 __iomem *j2_ccr_base;
21static int __init scan_cache(unsigned long node, const char *uname,
22 int depth, void *data)
23{
24 if (!of_flat_dt_is_compatible(node, "jcore,cache"))
25 return 0;
26
27 j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node);
28
29 return 1;
30}
31#endif
32
33void __ref cpu_probe(void)
17{ 34{
18#if defined(CONFIG_CPU_SUBTYPE_SH7619) 35#if defined(CONFIG_CPU_SUBTYPE_SH7619)
19 boot_cpu_data.type = CPU_SH7619; 36 boot_cpu_data.type = CPU_SH7619;
@@ -24,10 +41,30 @@ void cpu_probe(void)
24 boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; 41 boot_cpu_data.dcache.linesz = L1_CACHE_BYTES;
25 boot_cpu_data.dcache.flags = 0; 42 boot_cpu_data.dcache.flags = 0;
26#endif 43#endif
44
45#if defined(CONFIG_CPU_J2)
46 unsigned cpu = hard_smp_processor_id();
47 if (cpu == 0) of_scan_flat_dt(scan_cache, NULL);
48 if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu);
49 if (cpu != 0) return;
50 boot_cpu_data.type = CPU_J2;
51
52 /* These defaults are appropriate for the original/current
53 * J2 cache. Once there is a proper framework for getting cache
54 * info from device tree, we should switch to that. */
55 boot_cpu_data.dcache.ways = 1;
56 boot_cpu_data.dcache.sets = 256;
57 boot_cpu_data.dcache.entry_shift = 5;
58 boot_cpu_data.dcache.linesz = 32;
59 boot_cpu_data.dcache.flags = 0;
60
61 boot_cpu_data.flags |= CPU_HAS_CAS_L;
62#else
27 /* 63 /*
28 * SH-2 doesn't have separate caches 64 * SH-2 doesn't have separate caches
29 */ 65 */
30 boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED; 66 boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
67#endif
31 boot_cpu_data.icache = boot_cpu_data.dcache; 68 boot_cpu_data.icache = boot_cpu_data.dcache;
32 boot_cpu_data.family = CPU_FAMILY_SH2; 69 boot_cpu_data.family = CPU_FAMILY_SH2;
33} 70}
diff --git a/arch/sh/kernel/cpu/sh2/smp-j2.c b/arch/sh/kernel/cpu/sh2/smp-j2.c
new file mode 100644
index 000000000000..6ccd7e4dc008
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/smp-j2.c
@@ -0,0 +1,139 @@
1/*
2 * SMP support for J2 processor
3 *
4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/smp.h>
12#include <linux/interrupt.h>
13#include <linux/io.h>
14#include <linux/of_address.h>
15#include <linux/of_irq.h>
16#include <asm/cmpxchg.h>
17
18DEFINE_PER_CPU(unsigned, j2_ipi_messages);
19
20extern u32 *sh2_cpuid_addr;
21static u32 *j2_ipi_trigger;
22static int j2_ipi_irq;
23
24static irqreturn_t j2_ipi_interrupt_handler(int irq, void *arg)
25{
26 unsigned cpu = hard_smp_processor_id();
27 volatile unsigned *pmsg = &per_cpu(j2_ipi_messages, cpu);
28 unsigned messages, i;
29
30 do messages = *pmsg;
31 while (cmpxchg(pmsg, messages, 0) != messages);
32
33 if (!messages) return IRQ_NONE;
34
35 for (i=0; i<SMP_MSG_NR; i++)
36 if (messages & (1U<<i))
37 smp_message_recv(i);
38
39 return IRQ_HANDLED;
40}
41
42static void j2_smp_setup(void)
43{
44}
45
46static void j2_prepare_cpus(unsigned int max_cpus)
47{
48 struct device_node *np;
49 unsigned i, max = 1;
50
51 np = of_find_compatible_node(NULL, NULL, "jcore,ipi-controller");
52 if (!np)
53 goto out;
54
55 j2_ipi_irq = irq_of_parse_and_map(np, 0);
56 j2_ipi_trigger = of_iomap(np, 0);
57 if (!j2_ipi_irq || !j2_ipi_trigger)
58 goto out;
59
60 np = of_find_compatible_node(NULL, NULL, "jcore,cpuid-mmio");
61 if (!np)
62 goto out;
63
64 sh2_cpuid_addr = of_iomap(np, 0);
65 if (!sh2_cpuid_addr)
66 goto out;
67
68 if (request_irq(j2_ipi_irq, j2_ipi_interrupt_handler, IRQF_PERCPU,
69 "ipi", (void *)j2_ipi_interrupt_handler) != 0)
70 goto out;
71
72 max = max_cpus;
73out:
74 /* Disable any cpus past max_cpus, or all secondaries if we didn't
75 * get the necessary resources to support SMP. */
76 for (i=max; i<NR_CPUS; i++) {
77 set_cpu_possible(i, false);
78 set_cpu_present(i, false);
79 }
80}
81
82static void j2_start_cpu(unsigned int cpu, unsigned long entry_point)
83{
84 struct device_node *np;
85 u32 regs[2];
86 void __iomem *release, *initpc;
87
88 if (!cpu) return;
89
90 np = of_get_cpu_node(cpu, NULL);
91 if (!np) return;
92
93 if (of_property_read_u32_array(np, "cpu-release-addr", regs, 2)) return;
94 release = ioremap_nocache(regs[0], sizeof(u32));
95 initpc = ioremap_nocache(regs[1], sizeof(u32));
96
97 __raw_writel(entry_point, initpc);
98 __raw_writel(1, release);
99
100 iounmap(initpc);
101 iounmap(release);
102
103 pr_info("J2 SMP: requested start of cpu %u\n", cpu);
104}
105
106static unsigned int j2_smp_processor_id(void)
107{
108 return __raw_readl(sh2_cpuid_addr);
109}
110
111static void j2_send_ipi(unsigned int cpu, unsigned int message)
112{
113 volatile unsigned *pmsg;
114 unsigned old;
115 unsigned long val;
116
117 /* There is only one IPI interrupt shared by all messages, so
118 * we keep a separate interrupt flag per message type in sw. */
119 pmsg = &per_cpu(j2_ipi_messages, cpu);
120 do old = *pmsg;
121 while (cmpxchg(pmsg, old, old|(1U<<message)) != old);
122
123 /* Generate the actual interrupt by writing to CCRn bit 28. */
124 val = __raw_readl(j2_ipi_trigger + cpu);
125 __raw_writel(val | (1U<<28), j2_ipi_trigger + cpu);
126}
127
128static struct plat_smp_ops j2_smp_ops = {
129 .smp_setup = j2_smp_setup,
130 .prepare_cpus = j2_prepare_cpus,
131 .start_cpu = j2_start_cpu,
132 .smp_processor_id = j2_smp_processor_id,
133 .send_ipi = j2_send_ipi,
134 .cpu_die = native_cpu_die,
135 .cpu_disable = native_cpu_disable,
136 .play_dead = native_play_dead,
137};
138
139CPU_METHOD_OF_DECLARE(j2_cpu_method, "jcore,spin-table", &j2_smp_ops);
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 9d209a07235e..e1d751ae2498 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -1009,10 +1009,8 @@ static void __init dwarf_unwinder_cleanup(void)
1009 rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node) 1009 rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node)
1010 kfree(cie); 1010 kfree(cie);
1011 1011
1012 if (dwarf_reg_pool) 1012 mempool_destroy(dwarf_reg_pool);
1013 mempool_destroy(dwarf_reg_pool); 1013 mempool_destroy(dwarf_frame_pool);
1014 if (dwarf_frame_pool)
1015 mempool_destroy(dwarf_frame_pool);
1016 kmem_cache_destroy(dwarf_reg_cachep); 1014 kmem_cache_destroy(dwarf_reg_cachep);
1017 kmem_cache_destroy(dwarf_frame_cachep); 1015 kmem_cache_destroy(dwarf_frame_cachep);
1018} 1016}
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 974bc152cc84..4e352c3f79e6 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -67,7 +67,7 @@ ENTRY(_stext)
67 ldc r0, r6_bank 67 ldc r0, r6_bank
68#endif 68#endif
69 69
70#ifdef CONFIG_OF 70#ifdef CONFIG_OF_FLATTREE
71 mov r4, r12 ! Store device tree blob pointer in r12 71 mov r4, r12 ! Store device tree blob pointer in r12
72#endif 72#endif
73 73
@@ -318,7 +318,7 @@ ENTRY(_stext)
31810: 31810:
319#endif 319#endif
320 320
321#ifdef CONFIG_OF 321#ifdef CONFIG_OF_FLATTREE
322 mov.l 8f, r0 ! Make flat device tree available early. 322 mov.l 8f, r0 ! Make flat device tree available early.
323 jsr @r0 323 jsr @r0
324 mov r12, r4 324 mov r12, r4
@@ -349,7 +349,7 @@ ENTRY(stack_start)
3495: .long start_kernel 3495: .long start_kernel
3506: .long cpu_init 3506: .long cpu_init
3517: .long init_thread_union 3517: .long init_thread_union
352#if defined(CONFIG_OF) 352#if defined(CONFIG_OF_FLATTREE)
3538: .long sh_fdt_init 3538: .long sh_fdt_init
354#endif 354#endif
355 355
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 5d34605b58b5..e7b49d81053e 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -242,7 +242,7 @@ void __init __weak plat_early_device_setup(void)
242{ 242{
243} 243}
244 244
245#ifdef CONFIG_OF 245#ifdef CONFIG_OF_FLATTREE
246void __ref sh_fdt_init(phys_addr_t dt_phys) 246void __ref sh_fdt_init(phys_addr_t dt_phys)
247{ 247{
248 static int done = 0; 248 static int done = 0;
@@ -251,7 +251,11 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
251 /* Avoid calling an __init function on secondary cpus. */ 251 /* Avoid calling an __init function on secondary cpus. */
252 if (done) return; 252 if (done) return;
253 253
254#ifdef CONFIG_USE_BUILTIN_DTB
255 dt_virt = __dtb_start;
256#else
254 dt_virt = phys_to_virt(dt_phys); 257 dt_virt = phys_to_virt(dt_phys);
258#endif
255 259
256 if (!dt_virt || !early_init_dt_scan(dt_virt)) { 260 if (!dt_virt || !early_init_dt_scan(dt_virt)) {
257 pr_crit("Error: invalid device tree blob" 261 pr_crit("Error: invalid device tree blob"
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 734234be2f01..254bc22ee57d 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -386,3 +386,17 @@ ENTRY(sys_call_table)
386 .long sys_process_vm_writev 386 .long sys_process_vm_writev
387 .long sys_kcmp 387 .long sys_kcmp
388 .long sys_finit_module 388 .long sys_finit_module
389 .long sys_sched_getattr
390 .long sys_sched_setattr /* 370 */
391 .long sys_renameat2
392 .long sys_seccomp
393 .long sys_getrandom
394 .long sys_memfd_create
395 .long sys_bpf /* 375 */
396 .long sys_execveat
397 .long sys_userfaultfd
398 .long sys_membarrier
399 .long sys_mlock2
400 .long sys_copy_file_range /* 380 */
401 .long sys_preadv2
402 .long sys_pwritev2
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 579fcb9a896b..d6a27f7a4c54 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -406,3 +406,17 @@ sys_call_table:
406 .long sys_process_vm_writev 406 .long sys_process_vm_writev
407 .long sys_kcmp 407 .long sys_kcmp
408 .long sys_finit_module 408 .long sys_finit_module
409 .long sys_sched_getattr /* 380 */
410 .long sys_sched_setattr
411 .long sys_renameat2
412 .long sys_seccomp
413 .long sys_getrandom
414 .long sys_memfd_create /* 385 */
415 .long sys_bpf
416 .long sys_execveat
417 .long sys_userfaultfd
418 .long sys_membarrier
419 .long sys_mlock2 /* 390 */
420 .long sys_copy_file_range
421 .long sys_preadv2
422 .long sys_pwritev2
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index a4a7862b489a..fcd5e41977d1 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -11,7 +11,6 @@
11 * for more details. 11 * for more details.
12 */ 12 */
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/profile.h> 15#include <linux/profile.h>
17#include <linux/timex.h> 16#include <linux/timex.h>
@@ -90,7 +89,7 @@ static int __init rtc_generic_init(void)
90 89
91 return PTR_ERR_OR_ZERO(pdev); 90 return PTR_ERR_OR_ZERO(pdev);
92} 91}
93module_init(rtc_generic_init); 92device_initcall(rtc_generic_init);
94 93
95void (*board_time_init)(void); 94void (*board_time_init)(void);
96 95
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index cee6b9999d86..92c3bd96aee5 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -4,7 +4,8 @@
4 4
5obj-y := alignment.o cache.o init.o consistent.o mmap.o 5obj-y := alignment.o cache.o init.o consistent.o mmap.o
6 6
7cacheops-$(CONFIG_CPU_SH2) := cache-sh2.o 7cacheops-$(CONFIG_CPU_J2) := cache-j2.o
8cacheops-$(CONFIG_CPU_SUBTYPE_SH7619) := cache-sh2.o
8cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o 9cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o
9cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o 10cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o
10cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o 11cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o
diff --git a/arch/sh/mm/asids-debugfs.c b/arch/sh/mm/asids-debugfs.c
index ecfc6b0c1da1..bf95fdaedd0c 100644
--- a/arch/sh/mm/asids-debugfs.c
+++ b/arch/sh/mm/asids-debugfs.c
@@ -17,7 +17,6 @@
17 * for more details. 17 * for more details.
18 */ 18 */
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/debugfs.h> 20#include <linux/debugfs.h>
22#include <linux/seq_file.h> 21#include <linux/seq_file.h>
23#include <linux/spinlock.h> 22#include <linux/spinlock.h>
@@ -70,6 +69,4 @@ static int __init asids_debugfs_init(void)
70 69
71 return PTR_ERR_OR_ZERO(asids_dentry); 70 return PTR_ERR_OR_ZERO(asids_dentry);
72} 71}
73module_init(asids_debugfs_init); 72device_initcall(asids_debugfs_init);
74
75MODULE_LICENSE("GPL v2");
diff --git a/arch/sh/mm/cache-j2.c b/arch/sh/mm/cache-j2.c
new file mode 100644
index 000000000000..391698bcac5b
--- /dev/null
+++ b/arch/sh/mm/cache-j2.c
@@ -0,0 +1,65 @@
1/*
2 * arch/sh/mm/cache-j2.c
3 *
4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
5 *
6 * Released under the terms of the GNU GPL v2.0.
7 */
8
9#include <linux/init.h>
10#include <linux/mm.h>
11#include <linux/cpumask.h>
12
13#include <asm/cache.h>
14#include <asm/addrspace.h>
15#include <asm/processor.h>
16#include <asm/cacheflush.h>
17#include <asm/io.h>
18
19#define ICACHE_ENABLE 0x1
20#define DCACHE_ENABLE 0x2
21#define CACHE_ENABLE (ICACHE_ENABLE | DCACHE_ENABLE)
22#define ICACHE_FLUSH 0x100
23#define DCACHE_FLUSH 0x200
24#define CACHE_FLUSH (ICACHE_FLUSH | DCACHE_FLUSH)
25
26u32 __iomem *j2_ccr_base;
27
28static void j2_flush_icache(void *args)
29{
30 unsigned cpu;
31 for_each_possible_cpu(cpu)
32 __raw_writel(CACHE_ENABLE | ICACHE_FLUSH, j2_ccr_base + cpu);
33}
34
35static void j2_flush_dcache(void *args)
36{
37 unsigned cpu;
38 for_each_possible_cpu(cpu)
39 __raw_writel(CACHE_ENABLE | DCACHE_FLUSH, j2_ccr_base + cpu);
40}
41
42static void j2_flush_both(void *args)
43{
44 unsigned cpu;
45 for_each_possible_cpu(cpu)
46 __raw_writel(CACHE_ENABLE | CACHE_FLUSH, j2_ccr_base + cpu);
47}
48
49void __init j2_cache_init(void)
50{
51 if (!j2_ccr_base)
52 return;
53
54 local_flush_cache_all = j2_flush_both;
55 local_flush_cache_mm = j2_flush_both;
56 local_flush_cache_dup_mm = j2_flush_both;
57 local_flush_cache_page = j2_flush_both;
58 local_flush_cache_range = j2_flush_both;
59 local_flush_dcache_page = j2_flush_dcache;
60 local_flush_icache_range = j2_flush_icache;
61 local_flush_icache_page = j2_flush_icache;
62 local_flush_cache_sigtramp = j2_flush_icache;
63
64 pr_info("Initial J2 CCR is %.8x\n", __raw_readl(j2_ccr_base));
65}
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index e58cfbf45150..36554a9ea99b 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -42,6 +42,8 @@ static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
42{ 42{
43 preempt_disable(); 43 preempt_disable();
44 44
45 /* Needing IPI for cross-core flush is SHX3-specific. */
46#ifdef CONFIG_CPU_SHX3
45 /* 47 /*
46 * It's possible that this gets called early on when IRQs are 48 * It's possible that this gets called early on when IRQs are
47 * still disabled due to ioremapping by the boot CPU, so don't 49 * still disabled due to ioremapping by the boot CPU, so don't
@@ -49,6 +51,7 @@ static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
49 */ 51 */
50 if (num_online_cpus() > 1) 52 if (num_online_cpus() > 1)
51 smp_call_function(func, info, wait); 53 smp_call_function(func, info, wait);
54#endif
52 55
53 func(info); 56 func(info);
54 57
@@ -244,7 +247,11 @@ void flush_cache_sigtramp(unsigned long address)
244 247
245static void compute_alias(struct cache_info *c) 248static void compute_alias(struct cache_info *c)
246{ 249{
250#ifdef CONFIG_MMU
247 c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1); 251 c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
252#else
253 c->alias_mask = 0;
254#endif
248 c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0; 255 c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0;
249} 256}
250 257
@@ -305,7 +312,11 @@ void __init cpu_cache_init(void)
305 if (unlikely(cache_disabled)) 312 if (unlikely(cache_disabled))
306 goto skip; 313 goto skip;
307 314
308 if (boot_cpu_data.family == CPU_FAMILY_SH2) { 315 if (boot_cpu_data.type == CPU_J2) {
316 extern void __weak j2_cache_init(void);
317
318 j2_cache_init();
319 } else if (boot_cpu_data.family == CPU_FAMILY_SH2) {
309 extern void __weak sh2_cache_init(void); 320 extern void __weak sh2_cache_init(void);
310 321
311 sh2_cache_init(); 322 sh2_cache_init();