aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-26 16:31:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-26 16:31:05 -0400
commit7f9f44308c8993c9ab8078d174dad34bea3e82d7 (patch)
treecc6f3d146ff813e34ad0ab84673a7b2248a304c7
parent63905bba5b0170492777b327ac5e2aaef64989d6 (diff)
parentd939b52abe0cee9cc3167f554da6b864db86d3f2 (diff)
Merge tag 'cris-for-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper/cris
Pull arch/cris updates from Jesper Nilsson: "Some much needed love for the CRIS-port. There's a bunch of changes this time, giving the CRISv32 port a bit of modern makeover with device-tree, irq domain and gpiolib support, and more switchover to generic frameworks. Some small fixes and removal of the theoretical SMP support brings up the rear" * tag 'cris-for-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper/cris: cris: fix integer overflow in ELF_ET_DYN_BASE CRISv32: use GENERIC_SCHED_CLOCK CRISv32: use MMIO clocksource CRISv32: use generic clockevents CRIS: use generic headers via Kbuild CRIS: use generic cmpxchg.h CRIS: use generic atomic.h CRIS: use generic atomic bitops CRISv10: remove redundant macros from system.h CRIS: remove SMP code CRISv32: don't enable irqs in INIT_THREAD CRISv32: handle multiple signals CRISv32: prevent bogus restarts on sigreturn CRISv32: don't attempt syscall restart on irq exit Add binding documentation for CRIS CRIS: add Axis 88 board device tree CRISv32: add device tree support CRISv32: add irq domains support CRIS: enable GPIOLIB
-rw-r--r--Documentation/devicetree/bindings/cris/axis.txt9
-rw-r--r--Documentation/devicetree/bindings/cris/boards.txt8
-rw-r--r--Documentation/devicetree/bindings/cris/interrupts.txt23
-rw-r--r--arch/cris/Kconfig12
-rw-r--r--arch/cris/Makefile4
-rw-r--r--arch/cris/arch-v32/kernel/Makefile1
-rw-r--r--arch/cris/arch-v32/kernel/entry.S42
-rw-r--r--arch/cris/arch-v32/kernel/head.S32
-rw-r--r--arch/cris/arch-v32/kernel/irq.c31
-rw-r--r--arch/cris/arch-v32/kernel/setup.c5
-rw-r--r--arch/cris/arch-v32/kernel/signal.c5
-rw-r--r--arch/cris/arch-v32/kernel/smp.c358
-rw-r--r--arch/cris/arch-v32/kernel/time.c180
-rw-r--r--arch/cris/arch-v32/lib/Makefile2
-rw-r--r--arch/cris/arch-v32/lib/spinlock.S40
-rw-r--r--arch/cris/arch-v32/mm/init.c11
-rw-r--r--arch/cris/arch-v32/mm/mmu.S4
-rw-r--r--arch/cris/boot/dts/Makefile6
-rw-r--r--arch/cris/boot/dts/dev88.dts18
-rw-r--r--arch/cris/boot/dts/etraxfs.dtsi38
-rw-r--r--arch/cris/include/arch-v10/arch/atomic.h7
-rw-r--r--arch/cris/include/arch-v10/arch/system.h8
-rw-r--r--arch/cris/include/arch-v32/arch/atomic.h36
-rw-r--r--arch/cris/include/arch-v32/arch/processor.h3
-rw-r--r--arch/cris/include/arch-v32/arch/spinlock.h131
-rw-r--r--arch/cris/include/asm/Kbuild15
-rw-r--r--arch/cris/include/asm/atomic.h149
-rw-r--r--arch/cris/include/asm/bitops.h111
-rw-r--r--arch/cris/include/asm/cmpxchg.h53
-rw-r--r--arch/cris/include/asm/device.h7
-rw-r--r--arch/cris/include/asm/div64.h1
-rw-r--r--arch/cris/include/asm/elf.h2
-rw-r--r--arch/cris/include/asm/emergency-restart.h6
-rw-r--r--arch/cris/include/asm/futex.h6
-rw-r--r--arch/cris/include/asm/hardirq.h7
-rw-r--r--arch/cris/include/asm/irq_regs.h1
-rw-r--r--arch/cris/include/asm/kdebug.h1
-rw-r--r--arch/cris/include/asm/kmap_types.h10
-rw-r--r--arch/cris/include/asm/local.h1
-rw-r--r--arch/cris/include/asm/local64.h1
-rw-r--r--arch/cris/include/asm/percpu.h6
-rw-r--r--arch/cris/include/asm/smp.h10
-rw-r--r--arch/cris/include/asm/spinlock.h1
-rw-r--r--arch/cris/include/asm/tlbflush.h7
-rw-r--r--arch/cris/include/asm/topology.h6
-rw-r--r--arch/cris/kernel/Makefile1
-rw-r--r--arch/cris/kernel/devicetree.c14
-rw-r--r--arch/cris/kernel/ptrace.c23
-rw-r--r--arch/cris/kernel/setup.c15
-rw-r--r--arch/cris/kernel/time.c2
50 files changed, 325 insertions, 1145 deletions
diff --git a/Documentation/devicetree/bindings/cris/axis.txt b/Documentation/devicetree/bindings/cris/axis.txt
new file mode 100644
index 000000000000..d209ca2a47c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/cris/axis.txt
@@ -0,0 +1,9 @@
1Axis Communications AB
2ARTPEC series SoC Device Tree Bindings
3
4
5CRISv32 based SoCs are ETRAX FS and ARTPEC-3:
6
7 - compatible = "axis,crisv32";
8
9
diff --git a/Documentation/devicetree/bindings/cris/boards.txt b/Documentation/devicetree/bindings/cris/boards.txt
new file mode 100644
index 000000000000..533dd273ccf7
--- /dev/null
+++ b/Documentation/devicetree/bindings/cris/boards.txt
@@ -0,0 +1,8 @@
1Boards based on the CRIS SoCs:
2
3Required root node properties:
4 - compatible = should be one or more of the following:
5 - "axis,dev88" - for Axis devboard 88 with ETRAX FS
6
7Optional:
8
diff --git a/Documentation/devicetree/bindings/cris/interrupts.txt b/Documentation/devicetree/bindings/cris/interrupts.txt
new file mode 100644
index 000000000000..e8b123b0a5e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/cris/interrupts.txt
@@ -0,0 +1,23 @@
1* CRISv32 Interrupt Controller
2
3Interrupt controller for the CRISv32 SoCs.
4
5Main node required properties:
6
7- compatible : should be:
8 "axis,crisv32-intc"
9- interrupt-controller : Identifies the node as an interrupt controller
10- #interrupt-cells : Specifies the number of cells needed to encode an
11 interrupt source. The type shall be a <u32> and the value shall be 1.
12- reg: physical base address and size of the intc registers map.
13
14Example:
15
16 intc: interrupt-controller {
17 compatible = "axis,crisv32-intc";
18 reg = <0xb001c000 0x1000>;
19 interrupt-controller;
20 #interrupt-cells = <1>;
21 };
22
23
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 4a03911053ab..0314e325a669 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -46,12 +46,18 @@ config CRIS
46 select ARCH_WANT_IPC_PARSE_VERSION 46 select ARCH_WANT_IPC_PARSE_VERSION
47 select GENERIC_IRQ_SHOW 47 select GENERIC_IRQ_SHOW
48 select GENERIC_IOMAP 48 select GENERIC_IOMAP
49 select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
50 select GENERIC_CMOS_UPDATE 49 select GENERIC_CMOS_UPDATE
51 select MODULES_USE_ELF_RELA 50 select MODULES_USE_ELF_RELA
52 select CLONE_BACKWARDS2 51 select CLONE_BACKWARDS2
53 select OLD_SIGSUSPEND 52 select OLD_SIGSUSPEND
54 select OLD_SIGACTION 53 select OLD_SIGACTION
54 select ARCH_REQUIRE_GPIOLIB
55 select IRQ_DOMAIN if ETRAX_ARCH_V32
56 select OF if ETRAX_ARCH_V32
57 select OF_EARLY_FLATTREE if ETRAX_ARCH_V32
58 select CLKSRC_MMIO if ETRAX_ARCH_V32
59 select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32
60 select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32
55 61
56config HZ 62config HZ
57 int 63 int
@@ -61,6 +67,10 @@ config NR_CPUS
61 int 67 int
62 default "1" 68 default "1"
63 69
70config BUILTIN_DTB
71 string "DTB to build into the kernel image"
72 depends on OF
73
64source "init/Kconfig" 74source "init/Kconfig"
65 75
66source "kernel/Kconfig.freezer" 76source "kernel/Kconfig.freezer"
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index 39dc7d00083e..4a5404b3d0e4 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -40,6 +40,10 @@ else
40MACH := 40MACH :=
41endif 41endif
42 42
43ifneq ($(CONFIG_BUILTIN_DTB),"")
44core-$(CONFIG_OF) += arch/cris/boot/dts/
45endif
46
43LD = $(CROSS_COMPILE)ld -mcrislinux 47LD = $(CROSS_COMPILE)ld -mcrislinux
44 48
45OBJCOPYFLAGS := -O binary -R .note -R .comment -S 49OBJCOPYFLAGS := -O binary -R .note -R .comment -S
diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile
index 40358355d0cb..d9fc617ea253 100644
--- a/arch/cris/arch-v32/kernel/Makefile
+++ b/arch/cris/arch-v32/kernel/Makefile
@@ -9,7 +9,6 @@ obj-y := entry.o traps.o irq.o debugport.o \
9 process.o ptrace.o setup.o signal.o traps.o time.o \ 9 process.o ptrace.o setup.o signal.o traps.o time.o \
10 cache.o cacheflush.o 10 cache.o cacheflush.o
11 11
12obj-$(CONFIG_SMP) += smp.o
13obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o 12obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o
14obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o 13obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
15obj-$(CONFIG_MODULES) += crisksyms.o 14obj-$(CONFIG_MODULES) += crisksyms.o
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index 2f19ac6217aa..026a0b21b8f0 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -99,6 +99,8 @@ ret_from_kernel_thread:
99 99
100 .type ret_from_intr,@function 100 .type ret_from_intr,@function
101ret_from_intr: 101ret_from_intr:
102 moveq 0, $r9 ; not a syscall
103
102 ;; Check for resched if preemptive kernel, or if we're going back to 104 ;; Check for resched if preemptive kernel, or if we're going back to
103 ;; user-mode. This test matches the user_regs(regs) macro. Don't simply 105 ;; user-mode. This test matches the user_regs(regs) macro. Don't simply
104 ;; test CCS since that doesn't necessarily reflect what mode we'll 106 ;; test CCS since that doesn't necessarily reflect what mode we'll
@@ -145,7 +147,7 @@ system_call:
145 ;; Stack-frame similar to the irq heads, which is reversed in 147 ;; Stack-frame similar to the irq heads, which is reversed in
146 ;; ret_from_sys_call. 148 ;; ret_from_sys_call.
147 149
148 sub.d 92, $sp ; Skip EXS and EDA. 150 sub.d 92, $sp ; Skip EDA.
149 movem $r13, [$sp] 151 movem $r13, [$sp]
150 move.d $sp, $r8 152 move.d $sp, $r8
151 addq 14*4, $r8 153 addq 14*4, $r8
@@ -156,8 +158,9 @@ system_call:
156 move $ccs, $r4 158 move $ccs, $r4
157 move $srp, $r5 159 move $srp, $r5
158 move $erp, $r6 160 move $erp, $r6
161 move.d $r9, $r7 ; Store syscall number in EXS
159 subq 4, $sp 162 subq 4, $sp
160 movem $r6, [$r8] 163 movem $r7, [$r8]
161 ei ; Enable interrupts while processing syscalls. 164 ei ; Enable interrupts while processing syscalls.
162 move.d $r10, [$sp] 165 move.d $r10, [$sp]
163 166
@@ -278,43 +281,14 @@ _syscall_exit_work:
278 .type _work_pending,@function 281 .type _work_pending,@function
279_work_pending: 282_work_pending:
280 addoq +TI_flags, $r0, $acr 283 addoq +TI_flags, $r0, $acr
281 move.d [$acr], $r10
282 btstq TIF_NEED_RESCHED, $r10 ; Need resched?
283 bpl _work_notifysig ; No, must be signal/notify.
284 nop
285 .size _work_pending, . - _work_pending
286
287 .type _work_resched,@function
288_work_resched:
289 move.d $r9, $r1 ; Preserve R9.
290 jsr schedule
291 nop
292 move.d $r1, $r9
293 di
294
295 addoq +TI_flags, $r0, $acr
296 move.d [$acr], $r1
297 and.d _TIF_WORK_MASK, $r1 ; Ignore sycall trace counter.
298 beq _Rexit
299 nop
300 btstq TIF_NEED_RESCHED, $r1
301 bmi _work_resched ; current->work.need_resched.
302 nop
303 .size _work_resched, . - _work_resched
304
305 .type _work_notifysig,@function
306_work_notifysig:
307 ;; Deal with pending signals and notify-resume requests.
308
309 addoq +TI_flags, $r0, $acr
310 move.d [$acr], $r12 ; The thread_info_flags parameter. 284 move.d [$acr], $r12 ; The thread_info_flags parameter.
311 move.d $sp, $r11 ; The regs param. 285 move.d $sp, $r11 ; The regs param.
312 jsr do_notify_resume 286 jsr do_work_pending
313 move.d $r9, $r10 ; do_notify_resume syscall/irq param. 287 move.d $r9, $r10 ; The syscall/irq param.
314 288
315 ba _Rexit 289 ba _Rexit
316 nop 290 nop
317 .size _work_notifysig, . - _work_notifysig 291 .size _work_pending, . - _work_pending
318 292
319 ;; We get here as a sidetrack when we've entered a syscall with the 293 ;; We get here as a sidetrack when we've entered a syscall with the
320 ;; trace-bit set. We need to call do_syscall_trace and then continue 294 ;; trace-bit set. We need to call do_syscall_trace and then continue
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 51e34165ece7..74a66e0e3777 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -52,11 +52,6 @@ tstart:
52 52
53 GIO_INIT 53 GIO_INIT
54 54
55#ifdef CONFIG_SMP
56secondary_cpu_entry: /* Entry point for secondary CPUs */
57 di
58#endif
59
60 ;; Setup and enable the MMU. Use same configuration for both the data 55 ;; Setup and enable the MMU. Use same configuration for both the data
61 ;; and the instruction MMU. 56 ;; and the instruction MMU.
62 ;; 57 ;;
@@ -164,33 +159,6 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
164 nop 159 nop
165 nop 160 nop
166 161
167#ifdef CONFIG_SMP
168 ;; Read CPU ID
169 move 0, $srs
170 nop
171 nop
172 nop
173 move $s12, $r0
174 cmpq 0, $r0
175 beq master_cpu
176 nop
177slave_cpu:
178 ; Time to boot-up. Get stack location provided by master CPU.
179 move.d smp_init_current_idle_thread, $r1
180 move.d [$r1], $sp
181 add.d 8192, $sp
182 move.d ebp_start, $r0 ; Defined in linker-script.
183 move $r0, $ebp
184 jsr smp_callin
185 nop
186master_cpu:
187 /* Set up entry point for secondary CPUs. The boot ROM has set up
188 * EBP at start of internal memory. The CPU will get there
189 * later when we issue an IPI to them... */
190 move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0
191 move.d secondary_cpu_entry, $r1
192 move.d $r1, [$r0]
193#endif
194 ; Check if starting from DRAM (network->RAM boot or unpacked 162 ; Check if starting from DRAM (network->RAM boot or unpacked
195 ; compressed kernel), or directly from flash. 163 ; compressed kernel), or directly from flash.
196 lapcq ., $r0 164 lapcq ., $r0
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index 25437ae28128..6a881e0e92b4 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -10,6 +10,8 @@
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/profile.h> 12#include <linux/profile.h>
13#include <linux/of.h>
14#include <linux/of_irq.h>
13#include <linux/proc_fs.h> 15#include <linux/proc_fs.h>
14#include <linux/seq_file.h> 16#include <linux/seq_file.h>
15#include <linux/threads.h> 17#include <linux/threads.h>
@@ -56,9 +58,6 @@ struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] =
56static unsigned long irq_regs[NR_CPUS] = 58static unsigned long irq_regs[NR_CPUS] =
57{ 59{
58 regi_irq, 60 regi_irq,
59#ifdef CONFIG_SMP
60 regi_irq2,
61#endif
62}; 61};
63 62
64#if NR_REAL_IRQS > 32 63#if NR_REAL_IRQS > 32
@@ -431,6 +430,19 @@ crisv32_do_multiple(struct pt_regs* regs)
431 irq_exit(); 430 irq_exit();
432} 431}
433 432
433static int crisv32_irq_map(struct irq_domain *h, unsigned int virq,
434 irq_hw_number_t hw_irq_num)
435{
436 irq_set_chip_and_handler(virq, &crisv32_irq_type, handle_simple_irq);
437
438 return 0;
439}
440
441static struct irq_domain_ops crisv32_irq_ops = {
442 .map = crisv32_irq_map,
443 .xlate = irq_domain_xlate_onecell,
444};
445
434/* 446/*
435 * This is called by start_kernel. It fixes the IRQ masks and setup the 447 * This is called by start_kernel. It fixes the IRQ masks and setup the
436 * interrupt vector table to point to bad_interrupt pointers. 448 * interrupt vector table to point to bad_interrupt pointers.
@@ -441,6 +453,8 @@ init_IRQ(void)
441 int i; 453 int i;
442 int j; 454 int j;
443 reg_intr_vect_rw_mask vect_mask = {0}; 455 reg_intr_vect_rw_mask vect_mask = {0};
456 struct device_node *np;
457 struct irq_domain *domain;
444 458
445 /* Clear all interrupts masks. */ 459 /* Clear all interrupts masks. */
446 for (i = 0; i < NBR_REGS; i++) 460 for (i = 0; i < NBR_REGS; i++)
@@ -449,10 +463,15 @@ init_IRQ(void)
449 for (i = 0; i < 256; i++) 463 for (i = 0; i < 256; i++)
450 etrax_irv->v[i] = weird_irq; 464 etrax_irv->v[i] = weird_irq;
451 465
452 /* Point all IRQ's to bad handlers. */ 466 np = of_find_compatible_node(NULL, NULL, "axis,crisv32-intc");
467 domain = irq_domain_add_legacy(np, NR_IRQS - FIRST_IRQ,
468 FIRST_IRQ, FIRST_IRQ,
469 &crisv32_irq_ops, NULL);
470 BUG_ON(!domain);
471 irq_set_default_host(domain);
472 of_node_put(np);
473
453 for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) { 474 for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
454 irq_set_chip_and_handler(j, &crisv32_irq_type,
455 handle_simple_irq);
456 set_exception_vector(i, interrupt[j]); 475 set_exception_vector(i, interrupt[j]);
457 } 476 }
458 477
diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c
index 81715c683baf..cd1865d68b2e 100644
--- a/arch/cris/arch-v32/kernel/setup.c
+++ b/arch/cris/arch-v32/kernel/setup.c
@@ -63,11 +63,6 @@ int show_cpuinfo(struct seq_file *m, void *v)
63 63
64 info = &cpinfo[ARRAY_SIZE(cpinfo) - 1]; 64 info = &cpinfo[ARRAY_SIZE(cpinfo) - 1];
65 65
66#ifdef CONFIG_SMP
67 if (!cpu_online(cpu))
68 return 0;
69#endif
70
71 revision = rdvr(); 66 revision = rdvr();
72 67
73 for (i = 0; i < ARRAY_SIZE(cpinfo); i++) { 68 for (i = 0; i < ARRAY_SIZE(cpinfo); i++) {
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 0c9ce9eac614..3a36ae6b79d5 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -72,6 +72,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
72 /* Make that the user-mode flag is set. */ 72 /* Make that the user-mode flag is set. */
73 regs->ccs |= (1 << (U_CCS_BITNR + CCS_SHIFT)); 73 regs->ccs |= (1 << (U_CCS_BITNR + CCS_SHIFT));
74 74
75 /* Don't perform syscall restarting */
76 regs->exs = -1;
77
75 /* Restore the old USP. */ 78 /* Restore the old USP. */
76 err |= __get_user(old_usp, &sc->usp); 79 err |= __get_user(old_usp, &sc->usp);
77 wrusp(old_usp); 80 wrusp(old_usp);
@@ -425,6 +428,8 @@ do_signal(int canrestart, struct pt_regs *regs)
425{ 428{
426 struct ksignal ksig; 429 struct ksignal ksig;
427 430
431 canrestart = canrestart && ((int)regs->exs >= 0);
432
428 /* 433 /*
429 * The common case should go fast, which is why this point is 434 * The common case should go fast, which is why this point is
430 * reached from kernel-mode. If that's the case, just return 435 * reached from kernel-mode. If that's the case, just return
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
deleted file mode 100644
index 0698582467ca..000000000000
--- a/arch/cris/arch-v32/kernel/smp.c
+++ /dev/null
@@ -1,358 +0,0 @@
1#include <linux/types.h>
2#include <asm/delay.h>
3#include <irq.h>
4#include <hwregs/intr_vect.h>
5#include <hwregs/intr_vect_defs.h>
6#include <asm/tlbflush.h>
7#include <asm/mmu_context.h>
8#include <hwregs/asm/mmu_defs_asm.h>
9#include <hwregs/supp_reg.h>
10#include <linux/atomic.h>
11
12#include <linux/err.h>
13#include <linux/init.h>
14#include <linux/timex.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/cpumask.h>
18#include <linux/interrupt.h>
19#include <linux/module.h>
20
21#define IPI_SCHEDULE 1
22#define IPI_CALL 2
23#define IPI_FLUSH_TLB 4
24#define IPI_BOOT 8
25
26#define FLUSH_ALL (void*)0xffffffff
27
28/* Vector of locks used for various atomic operations */
29spinlock_t cris_atomic_locks[] = {
30 [0 ... LOCK_COUNT - 1] = __SPIN_LOCK_UNLOCKED(cris_atomic_locks)
31};
32
33/* CPU masks */
34cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
35EXPORT_SYMBOL(phys_cpu_present_map);
36
37/* Variables used during SMP boot */
38volatile int cpu_now_booting = 0;
39volatile struct thread_info *smp_init_current_idle_thread;
40
41/* Variables used during IPI */
42static DEFINE_SPINLOCK(call_lock);
43static DEFINE_SPINLOCK(tlbstate_lock);
44
45struct call_data_struct {
46 void (*func) (void *info);
47 void *info;
48 int wait;
49};
50
51static struct call_data_struct * call_data;
52
53static struct mm_struct* flush_mm;
54static struct vm_area_struct* flush_vma;
55static unsigned long flush_addr;
56
57/* Mode registers */
58static unsigned long irq_regs[NR_CPUS] = {
59 regi_irq,
60 regi_irq2
61};
62
63static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id);
64static int send_ipi(int vector, int wait, cpumask_t cpu_mask);
65static struct irqaction irq_ipi = {
66 .handler = crisv32_ipi_interrupt,
67 .flags = 0,
68 .name = "ipi",
69};
70
71extern void cris_mmu_init(void);
72extern void cris_timer_init(void);
73
74/* SMP initialization */
75void __init smp_prepare_cpus(unsigned int max_cpus)
76{
77 int i;
78
79 /* From now on we can expect IPIs so set them up */
80 setup_irq(IPI_INTR_VECT, &irq_ipi);
81
82 /* Mark all possible CPUs as present */
83 for (i = 0; i < max_cpus; i++)
84 cpumask_set_cpu(i, &phys_cpu_present_map);
85}
86
87void smp_prepare_boot_cpu(void)
88{
89 /* PGD pointer has moved after per_cpu initialization so
90 * update the MMU.
91 */
92 pgd_t **pgd;
93 pgd = (pgd_t**)&per_cpu(current_pgd, smp_processor_id());
94
95 SUPP_BANK_SEL(1);
96 SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
97 SUPP_BANK_SEL(2);
98 SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
99
100 set_cpu_online(0, true);
101 cpumask_set_cpu(0, &phys_cpu_present_map);
102 set_cpu_possible(0, true);
103}
104
105void __init smp_cpus_done(unsigned int max_cpus)
106{
107}
108
109/* Bring one cpu online.*/
110static int __init
111smp_boot_one_cpu(int cpuid, struct task_struct idle)
112{
113 unsigned timeout;
114 cpumask_t cpu_mask;
115
116 cpumask_clear(&cpu_mask);
117 task_thread_info(idle)->cpu = cpuid;
118
119 /* Information to the CPU that is about to boot */
120 smp_init_current_idle_thread = task_thread_info(idle);
121 cpu_now_booting = cpuid;
122
123 /* Kick it */
124 set_cpu_online(cpuid, true);
125 cpumask_set_cpu(cpuid, &cpu_mask);
126 send_ipi(IPI_BOOT, 0, cpu_mask);
127 set_cpu_online(cpuid, false);
128
129 /* Wait for CPU to come online */
130 for (timeout = 0; timeout < 10000; timeout++) {
131 if(cpu_online(cpuid)) {
132 cpu_now_booting = 0;
133 smp_init_current_idle_thread = NULL;
134 return 0; /* CPU online */
135 }
136 udelay(100);
137 barrier();
138 }
139
140 printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
141 return -1;
142}
143
144/* Secondary CPUs starts using C here. Here we need to setup CPU
145 * specific stuff such as the local timer and the MMU. */
146void __init smp_callin(void)
147{
148 int cpu = cpu_now_booting;
149 reg_intr_vect_rw_mask vect_mask = {0};
150
151 /* Initialise the idle task for this CPU */
152 atomic_inc(&init_mm.mm_count);
153 current->active_mm = &init_mm;
154
155 /* Set up MMU */
156 cris_mmu_init();
157 __flush_tlb_all();
158
159 /* Setup local timer. */
160 cris_timer_init();
161
162 /* Enable IRQ and idle */
163 REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
164 crisv32_unmask_irq(IPI_INTR_VECT);
165 crisv32_unmask_irq(TIMER0_INTR_VECT);
166 preempt_disable();
167 notify_cpu_starting(cpu);
168 local_irq_enable();
169
170 set_cpu_online(cpu, true);
171 cpu_startup_entry(CPUHP_ONLINE);
172}
173
174/* Stop execution on this CPU.*/
175void stop_this_cpu(void* dummy)
176{
177 local_irq_disable();
178 asm volatile("halt");
179}
180
181/* Other calls */
182void smp_send_stop(void)
183{
184 smp_call_function(stop_this_cpu, NULL, 0);
185}
186
187int setup_profiling_timer(unsigned int multiplier)
188{
189 return -EINVAL;
190}
191
192
193/* cache_decay_ticks is used by the scheduler to decide if a process
194 * is "hot" on one CPU. A higher value means a higher penalty to move
195 * a process to another CPU. Our cache is rather small so we report
196 * 1 tick.
197 */
198unsigned long cache_decay_ticks = 1;
199
200int __cpu_up(unsigned int cpu, struct task_struct *tidle)
201{
202 smp_boot_one_cpu(cpu, tidle);
203 return cpu_online(cpu) ? 0 : -ENOSYS;
204}
205
206void smp_send_reschedule(int cpu)
207{
208 cpumask_t cpu_mask;
209 cpumask_clear(&cpu_mask);
210 cpumask_set_cpu(cpu, &cpu_mask);
211 send_ipi(IPI_SCHEDULE, 0, cpu_mask);
212}
213
214/* TLB flushing
215 *
216 * Flush needs to be done on the local CPU and on any other CPU that
217 * may have the same mapping. The mm->cpu_vm_mask is used to keep track
218 * of which CPUs that a specific process has been executed on.
219 */
220void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned long addr)
221{
222 unsigned long flags;
223 cpumask_t cpu_mask;
224
225 spin_lock_irqsave(&tlbstate_lock, flags);
226 cpu_mask = (mm == FLUSH_ALL ? cpu_all_mask : *mm_cpumask(mm));
227 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
228 flush_mm = mm;
229 flush_vma = vma;
230 flush_addr = addr;
231 send_ipi(IPI_FLUSH_TLB, 1, cpu_mask);
232 spin_unlock_irqrestore(&tlbstate_lock, flags);
233}
234
235void flush_tlb_all(void)
236{
237 __flush_tlb_all();
238 flush_tlb_common(FLUSH_ALL, FLUSH_ALL, 0);
239}
240
241void flush_tlb_mm(struct mm_struct *mm)
242{
243 __flush_tlb_mm(mm);
244 flush_tlb_common(mm, FLUSH_ALL, 0);
245 /* No more mappings in other CPUs */
246 cpumask_clear(mm_cpumask(mm));
247 cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
248}
249
250void flush_tlb_page(struct vm_area_struct *vma,
251 unsigned long addr)
252{
253 __flush_tlb_page(vma, addr);
254 flush_tlb_common(vma->vm_mm, vma, addr);
255}
256
257/* Inter processor interrupts
258 *
259 * The IPIs are used for:
260 * * Force a schedule on a CPU
261 * * FLush TLB on other CPUs
262 * * Call a function on other CPUs
263 */
264
265int send_ipi(int vector, int wait, cpumask_t cpu_mask)
266{
267 int i = 0;
268 reg_intr_vect_rw_ipi ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi);
269 int ret = 0;
270
271 /* Calculate CPUs to send to. */
272 cpumask_and(&cpu_mask, &cpu_mask, cpu_online_mask);
273
274 /* Send the IPI. */
275 for_each_cpu(i, &cpu_mask)
276 {
277 ipi.vector |= vector;
278 REG_WR(intr_vect, irq_regs[i], rw_ipi, ipi);
279 }
280
281 /* Wait for IPI to finish on other CPUS */
282 if (wait) {
283 for_each_cpu(i, &cpu_mask) {
284 int j;
285 for (j = 0 ; j < 1000; j++) {
286 ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi);
287 if (!ipi.vector)
288 break;
289 udelay(100);
290 }
291
292 /* Timeout? */
293 if (ipi.vector) {
294 printk("SMP call timeout from %d to %d\n", smp_processor_id(), i);
295 ret = -ETIMEDOUT;
296 dump_stack();
297 }
298 }
299 }
300 return ret;
301}
302
303/*
304 * You must not call this function with disabled interrupts or from a
305 * hardware interrupt handler or from a bottom half handler.
306 */
307int smp_call_function(void (*func)(void *info), void *info, int wait)
308{
309 cpumask_t cpu_mask;
310 struct call_data_struct data;
311 int ret;
312
313 cpumask_setall(&cpu_mask);
314 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
315
316 WARN_ON(irqs_disabled());
317
318 data.func = func;
319 data.info = info;
320 data.wait = wait;
321
322 spin_lock(&call_lock);
323 call_data = &data;
324 ret = send_ipi(IPI_CALL, wait, cpu_mask);
325 spin_unlock(&call_lock);
326
327 return ret;
328}
329
330irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id)
331{
332 void (*func) (void *info) = call_data->func;
333 void *info = call_data->info;
334 reg_intr_vect_rw_ipi ipi;
335
336 ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi);
337
338 if (ipi.vector & IPI_SCHEDULE) {
339 scheduler_ipi();
340 }
341 if (ipi.vector & IPI_CALL) {
342 func(info);
343 }
344 if (ipi.vector & IPI_FLUSH_TLB) {
345 if (flush_mm == FLUSH_ALL)
346 __flush_tlb_all();
347 else if (flush_vma == FLUSH_ALL)
348 __flush_tlb_mm(flush_mm);
349 else
350 __flush_tlb_page(flush_vma, flush_addr);
351 }
352
353 ipi.vector = 0;
354 REG_WR(intr_vect, irq_regs[smp_processor_id()], rw_ipi, ipi);
355
356 return IRQ_HANDLED;
357}
358
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index c17b01abdc3b..4fce9f1f7cc0 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -8,12 +8,14 @@
8#include <linux/timex.h> 8#include <linux/timex.h>
9#include <linux/time.h> 9#include <linux/time.h>
10#include <linux/clocksource.h> 10#include <linux/clocksource.h>
11#include <linux/clockchips.h>
11#include <linux/interrupt.h> 12#include <linux/interrupt.h>
12#include <linux/swap.h> 13#include <linux/swap.h>
13#include <linux/sched.h> 14#include <linux/sched.h>
14#include <linux/init.h> 15#include <linux/init.h>
15#include <linux/threads.h> 16#include <linux/threads.h>
16#include <linux/cpufreq.h> 17#include <linux/cpufreq.h>
18#include <linux/sched_clock.h>
17#include <linux/mm.h> 19#include <linux/mm.h>
18#include <asm/types.h> 20#include <asm/types.h>
19#include <asm/signal.h> 21#include <asm/signal.h>
@@ -36,33 +38,11 @@
36/* Number of 763 counts before watchdog bites */ 38/* Number of 763 counts before watchdog bites */
37#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) 39#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1)
38 40
39/* Register the continuos readonly timer available in FS and ARTPEC-3. */ 41#define CRISV32_TIMER_FREQ (100000000lu)
40static cycle_t read_cont_rotime(struct clocksource *cs)
41{
42 return (u32)REG_RD(timer, regi_timer0, r_time);
43}
44
45static struct clocksource cont_rotime = {
46 .name = "crisv32_rotime",
47 .rating = 300,
48 .read = read_cont_rotime,
49 .mask = CLOCKSOURCE_MASK(32),
50 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
51};
52
53static int __init etrax_init_cont_rotime(void)
54{
55 clocksource_register_khz(&cont_rotime, 100000);
56 return 0;
57}
58arch_initcall(etrax_init_cont_rotime);
59 42
60unsigned long timer_regs[NR_CPUS] = 43unsigned long timer_regs[NR_CPUS] =
61{ 44{
62 regi_timer0, 45 regi_timer0,
63#ifdef CONFIG_SMP
64 regi_timer2
65#endif
66}; 46};
67 47
68extern int set_rtc_mmss(unsigned long nowtime); 48extern int set_rtc_mmss(unsigned long nowtime);
@@ -189,81 +169,104 @@ void handle_watchdog_bite(struct pt_regs *regs)
189#endif 169#endif
190} 170}
191 171
192/* 172extern void cris_profile_sample(struct pt_regs *regs);
193 * timer_interrupt() needs to keep up the real-time clock, 173static void __iomem *timer_base;
194 * as well as call the "xtime_update()" routine every clocktick.
195 */
196extern void cris_do_profile(struct pt_regs *regs);
197 174
198static inline irqreturn_t timer_interrupt(int irq, void *dev_id) 175static void crisv32_clkevt_mode(enum clock_event_mode mode,
176 struct clock_event_device *dev)
199{ 177{
200 struct pt_regs *regs = get_irq_regs(); 178 reg_timer_rw_tmr0_ctrl ctrl = {
201 int cpu = smp_processor_id(); 179 .op = regk_timer_hold,
202 reg_timer_r_masked_intr masked_intr; 180 .freq = regk_timer_f100,
203 reg_timer_rw_ack_intr ack_intr = { 0 }; 181 };
204
205 /* Check if the timer interrupt is for us (a tmr0 int) */
206 masked_intr = REG_RD(timer, timer_regs[cpu], r_masked_intr);
207 if (!masked_intr.tmr0)
208 return IRQ_NONE;
209 182
210 /* Acknowledge the timer irq. */ 183 REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
211 ack_intr.tmr0 = 1; 184}
212 REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr);
213 185
214 /* Reset watchdog otherwise it resets us! */ 186static int crisv32_clkevt_next_event(unsigned long evt,
215 reset_watchdog(); 187 struct clock_event_device *dev)
188{
189 reg_timer_rw_tmr0_ctrl ctrl = {
190 .op = regk_timer_ld,
191 .freq = regk_timer_f100,
192 };
193
194 REG_WR(timer, timer_base, rw_tmr0_div, evt);
195 REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
196
197 ctrl.op = regk_timer_run;
198 REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
199
200 return 0;
201}
202
203static irqreturn_t crisv32_timer_interrupt(int irq, void *dev_id)
204{
205 struct clock_event_device *evt = dev_id;
206 reg_timer_rw_tmr0_ctrl ctrl = {
207 .op = regk_timer_hold,
208 .freq = regk_timer_f100,
209 };
210 reg_timer_rw_ack_intr ack = { .tmr0 = 1 };
211 reg_timer_r_masked_intr intr;
212
213 intr = REG_RD(timer, timer_base, r_masked_intr);
214 if (!intr.tmr0)
215 return IRQ_NONE;
216 216
217 /* Update statistics. */ 217 REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
218 update_process_times(user_mode(regs)); 218 REG_WR(timer, timer_base, rw_ack_intr, ack);
219 219
220 cris_do_profile(regs); /* Save profiling information */ 220 reset_watchdog();
221#ifdef CONFIG_SYSTEM_PROFILER
222 cris_profile_sample(get_irq_regs());
223#endif
221 224
222 /* The master CPU is responsible for the time keeping. */ 225 evt->event_handler(evt);
223 if (cpu != 0)
224 return IRQ_HANDLED;
225 226
226 /* Call the real timer interrupt handler */
227 xtime_update(1);
228 return IRQ_HANDLED; 227 return IRQ_HANDLED;
229} 228}
230 229
230static struct clock_event_device crisv32_clockevent = {
231 .name = "crisv32-timer",
232 .rating = 300,
233 .features = CLOCK_EVT_FEAT_ONESHOT,
234 .set_mode = crisv32_clkevt_mode,
235 .set_next_event = crisv32_clkevt_next_event,
236};
237
231/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ 238/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */
232static struct irqaction irq_timer = { 239static struct irqaction irq_timer = {
233 .handler = timer_interrupt, 240 .handler = crisv32_timer_interrupt,
234 .flags = IRQF_SHARED, 241 .flags = IRQF_TIMER | IRQF_SHARED,
235 .name = "timer" 242 .name = "crisv32-timer",
243 .dev_id = &crisv32_clockevent,
236}; 244};
237 245
238void __init cris_timer_init(void) 246static u64 notrace crisv32_timer_sched_clock(void)
239{ 247{
240 int cpu = smp_processor_id(); 248 return REG_RD(timer, timer_base, r_time);
241 reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; 249}
242 reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV;
243 reg_timer_rw_intr_mask timer_intr_mask;
244 250
245 /* Setup the etrax timers. 251static void __init crisv32_timer_init(void)
246 * Base frequency is 100MHz, divider 1000000 -> 100 HZ 252{
247 * We use timer0, so timer1 is free. 253 reg_timer_rw_intr_mask timer_intr_mask;
248 * The trig timer is used by the fasttimer API if enabled. 254 reg_timer_rw_tmr0_ctrl ctrl = {
249 */ 255 .op = regk_timer_hold,
256 .freq = regk_timer_f100,
257 };
250 258
251 tmr0_ctrl.op = regk_timer_ld; 259 REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
252 tmr0_ctrl.freq = regk_timer_f100;
253 REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div);
254 REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */
255 tmr0_ctrl.op = regk_timer_run;
256 REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */
257 260
258 /* Enable the timer irq. */ 261 timer_intr_mask = REG_RD(timer, timer_base, rw_intr_mask);
259 timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask);
260 timer_intr_mask.tmr0 = 1; 262 timer_intr_mask.tmr0 = 1;
261 REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); 263 REG_WR(timer, timer_base, rw_intr_mask, timer_intr_mask);
262} 264}
263 265
264void __init time_init(void) 266void __init time_init(void)
265{ 267{
266 reg_intr_vect_rw_mask intr_mask; 268 int irq;
269 int ret;
267 270
268 /* Probe for the RTC and read it if it exists. 271 /* Probe for the RTC and read it if it exists.
269 * Before the RTC can be probed the loops_per_usec variable needs 272 * Before the RTC can be probed the loops_per_usec variable needs
@@ -273,17 +276,28 @@ void __init time_init(void)
273 */ 276 */
274 loops_per_usec = 50; 277 loops_per_usec = 50;
275 278
276 /* Start CPU local timer. */ 279 irq = TIMER0_INTR_VECT;
277 cris_timer_init(); 280 timer_base = (void __iomem *) regi_timer0;
281
282 crisv32_timer_init();
283
284 sched_clock_register(crisv32_timer_sched_clock, 32,
285 CRISV32_TIMER_FREQ);
286
287 clocksource_mmio_init(timer_base + REG_RD_ADDR_timer_r_time,
288 "crisv32-timer", CRISV32_TIMER_FREQ,
289 300, 32, clocksource_mmio_readl_up);
290
291 crisv32_clockevent.cpumask = cpu_possible_mask;
292 crisv32_clockevent.irq = irq;
278 293
279 /* Enable the timer irq in global config. */ 294 ret = setup_irq(irq, &irq_timer);
280 intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1); 295 if (ret)
281 intr_mask.timer0 = 1; 296 pr_warn("failed to setup irq %d\n", irq);
282 REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask);
283 297
284 /* Now actually register the timer irq handler that calls 298 clockevents_config_and_register(&crisv32_clockevent,
285 * timer_interrupt(). */ 299 CRISV32_TIMER_FREQ,
286 setup_irq(TIMER0_INTR_VECT, &irq_timer); 300 2, 0xffffffff);
287 301
288 /* Enable watchdog if we should use one. */ 302 /* Enable watchdog if we should use one. */
289 303
diff --git a/arch/cris/arch-v32/lib/Makefile b/arch/cris/arch-v32/lib/Makefile
index dd296b9db034..e91cf02f625d 100644
--- a/arch/cris/arch-v32/lib/Makefile
+++ b/arch/cris/arch-v32/lib/Makefile
@@ -3,5 +3,5 @@
3# 3#
4 4
5lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o \ 5lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o \
6 csumcpfruser.o spinlock.o delay.o strcmp.o 6 csumcpfruser.o delay.o strcmp.o
7 7
diff --git a/arch/cris/arch-v32/lib/spinlock.S b/arch/cris/arch-v32/lib/spinlock.S
deleted file mode 100644
index fe610b9d775f..000000000000
--- a/arch/cris/arch-v32/lib/spinlock.S
+++ /dev/null
@@ -1,40 +0,0 @@
1;; Core of the spinlock implementation
2;;
3;; Copyright (C) 2004 Axis Communications AB.
4;;
5;; Author: Mikael Starvik
6
7
8 .global cris_spin_lock
9 .type cris_spin_lock,@function
10 .global cris_spin_trylock
11 .type cris_spin_trylock,@function
12
13 .text
14
15cris_spin_lock:
16 clearf p
171: test.b [$r10]
18 beq 1b
19 clearf p
20 ax
21 clear.b [$r10]
22 bcs 1b
23 clearf p
24 ret
25 nop
26
27 .size cris_spin_lock, . - cris_spin_lock
28
29cris_spin_trylock:
30 clearf p
311: move.b [$r10], $r11
32 ax
33 clear.b [$r10]
34 bcs 1b
35 clearf p
36 ret
37 movu.b $r11,$r10
38
39 .size cris_spin_trylock, . - cris_spin_trylock
40
diff --git a/arch/cris/arch-v32/mm/init.c b/arch/cris/arch-v32/mm/init.c
index 3deca5253d91..f5438ca8122d 100644
--- a/arch/cris/arch-v32/mm/init.c
+++ b/arch/cris/arch-v32/mm/init.c
@@ -40,17 +40,6 @@ void __init cris_mmu_init(void)
40 */ 40 */
41 per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd; 41 per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
42 42
43#ifdef CONFIG_SMP
44 {
45 pgd_t **pgd;
46 pgd = (pgd_t**)&per_cpu(current_pgd, smp_processor_id());
47 SUPP_BANK_SEL(1);
48 SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
49 SUPP_BANK_SEL(2);
50 SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
51 }
52#endif
53
54 /* Initialise the TLB. Function found in tlb.c. */ 43 /* Initialise the TLB. Function found in tlb.c. */
55 tlb_init(); 44 tlb_init();
56 45
diff --git a/arch/cris/arch-v32/mm/mmu.S b/arch/cris/arch-v32/mm/mmu.S
index 72727c1d8e60..c0981044eccb 100644
--- a/arch/cris/arch-v32/mm/mmu.S
+++ b/arch/cris/arch-v32/mm/mmu.S
@@ -115,11 +115,7 @@
115 move.d $r0, [$r1] ; last_refill_cause = rw_mm_cause 115 move.d $r0, [$r1] ; last_refill_cause = rw_mm_cause
116 116
1173: ; Probably not in a loop, continue normal processing 1173: ; Probably not in a loop, continue normal processing
118#ifdef CONFIG_SMP
119 move $s7, $acr ; PGD
120#else
121 move.d current_pgd, $acr ; PGD 118 move.d current_pgd, $acr ; PGD
122#endif
123 ; Look up PMD in PGD 119 ; Look up PMD in PGD
124 lsrq 24, $r0 ; Get PMD index into PGD (bit 24-31) 120 lsrq 24, $r0 ; Get PMD index into PGD (bit 24-31)
125 move.d [$acr], $acr ; PGD for the current process 121 move.d [$acr], $acr ; PGD for the current process
diff --git a/arch/cris/boot/dts/Makefile b/arch/cris/boot/dts/Makefile
new file mode 100644
index 000000000000..faf69fb9919f
--- /dev/null
+++ b/arch/cris/boot/dts/Makefile
@@ -0,0 +1,6 @@
1BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
2ifneq ($(CONFIG_BUILTIN_DTB),"")
3obj-$(CONFIG_OF) += $(BUILTIN_DTB)
4endif
5
6clean-files := *.dtb.S
diff --git a/arch/cris/boot/dts/dev88.dts b/arch/cris/boot/dts/dev88.dts
new file mode 100644
index 000000000000..4fa5a3f9d0ec
--- /dev/null
+++ b/arch/cris/boot/dts/dev88.dts
@@ -0,0 +1,18 @@
1/dts-v1/;
2
3/include/ "etraxfs.dtsi"
4
5/ {
6 model = "Axis 88 Developer Board";
7 compatible = "axis,dev88";
8
9 aliases {
10 serial0 = &uart0;
11 };
12
13 soc {
14 uart0: serial@b00260000 {
15 status = "okay";
16 };
17 };
18};
diff --git a/arch/cris/boot/dts/etraxfs.dtsi b/arch/cris/boot/dts/etraxfs.dtsi
new file mode 100644
index 000000000000..909bcedc3565
--- /dev/null
+++ b/arch/cris/boot/dts/etraxfs.dtsi
@@ -0,0 +1,38 @@
1/ {
2 #address-cells = <1>;
3 #size-cells = <1>;
4 interrupt-parent = <&intc>;
5
6 cpus {
7 #address-cells = <1>;
8 #size-cells = <0>;
9
10 cpu@0 {
11 device_type = "cpu";
12 model = "axis,crisv32";
13 reg = <0>;
14 };
15 };
16
17 soc {
18 compatible = "simple-bus";
19 model = "etraxfs";
20 #address-cells = <1>;
21 #size-cells = <1>;
22 ranges;
23
24 intc: interrupt-controller {
25 compatible = "axis,crisv32-intc";
26 reg = <0xb001c000 0x1000>;
27 interrupt-controller;
28 #interrupt-cells = <1>;
29 };
30
31 serial@b00260000 {
32 compatible = "axis,etraxfs-uart";
33 reg = <0xb0026000 0x1000>;
34 interrupts = <68>;
35 status = "disabled";
36 };
37 };
38};
diff --git a/arch/cris/include/arch-v10/arch/atomic.h b/arch/cris/include/arch-v10/arch/atomic.h
deleted file mode 100644
index 6ef5e7d09024..000000000000
--- a/arch/cris/include/arch-v10/arch/atomic.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef __ASM_CRIS_ARCH_ATOMIC__
2#define __ASM_CRIS_ARCH_ATOMIC__
3
4#define cris_atomic_save(addr, flags) local_irq_save(flags);
5#define cris_atomic_restore(addr, flags) local_irq_restore(flags);
6
7#endif
diff --git a/arch/cris/include/arch-v10/arch/system.h b/arch/cris/include/arch-v10/arch/system.h
index 935fde34aa15..9b5580f58b96 100644
--- a/arch/cris/include/arch-v10/arch/system.h
+++ b/arch/cris/include/arch-v10/arch/system.h
@@ -36,12 +36,4 @@ static inline unsigned long _get_base(char * addr)
36 return 0; 36 return 0;
37} 37}
38 38
39#define nop() __asm__ __volatile__ ("nop");
40
41#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
42#define tas(ptr) (xchg((ptr),1))
43
44struct __xchg_dummy { unsigned long a[100]; };
45#define __xg(x) ((struct __xchg_dummy *)(x))
46
47#endif 39#endif
diff --git a/arch/cris/include/arch-v32/arch/atomic.h b/arch/cris/include/arch-v32/arch/atomic.h
deleted file mode 100644
index 852ceff8013f..000000000000
--- a/arch/cris/include/arch-v32/arch/atomic.h
+++ /dev/null
@@ -1,36 +0,0 @@
1#ifndef __ASM_CRIS_ARCH_ATOMIC__
2#define __ASM_CRIS_ARCH_ATOMIC__
3
4#include <linux/spinlock_types.h>
5
6extern void cris_spin_unlock(void *l, int val);
7extern void cris_spin_lock(void *l);
8extern int cris_spin_trylock(void* l);
9
10#ifndef CONFIG_SMP
11#define cris_atomic_save(addr, flags) local_irq_save(flags);
12#define cris_atomic_restore(addr, flags) local_irq_restore(flags);
13#else
14
15extern spinlock_t cris_atomic_locks[];
16#define LOCK_COUNT 128
17#define HASH_ADDR(a) (((int)a) & 127)
18
19#define cris_atomic_save(addr, flags) \
20 local_irq_save(flags); \
21 cris_spin_lock((void *)&cris_atomic_locks[HASH_ADDR(addr)].raw_lock.slock);
22
23#define cris_atomic_restore(addr, flags) \
24 { \
25 spinlock_t *lock = (void*)&cris_atomic_locks[HASH_ADDR(addr)]; \
26 __asm__ volatile ("move.d %1,%0" \
27 : "=m" (lock->raw_lock.slock) \
28 : "r" (1) \
29 : "memory"); \
30 local_irq_restore(flags); \
31 }
32
33#endif
34
35#endif
36
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h
index a024b7d32fed..568759271ab5 100644
--- a/arch/cris/include/arch-v32/arch/processor.h
+++ b/arch/cris/include/arch-v32/arch/processor.h
@@ -25,8 +25,7 @@ struct thread_struct {
25 */ 25 */
26#define TASK_SIZE (0xB0000000UL) 26#define TASK_SIZE (0xB0000000UL)
27 27
28/* CCS I=1, enable interrupts. */ 28#define INIT_THREAD { }
29#define INIT_THREAD { 0, 0, (1 << I_CCS_BITNR) }
30 29
31#define KSTK_EIP(tsk) \ 30#define KSTK_EIP(tsk) \
32({ \ 31({ \
diff --git a/arch/cris/include/arch-v32/arch/spinlock.h b/arch/cris/include/arch-v32/arch/spinlock.h
deleted file mode 100644
index f13275522f4d..000000000000
--- a/arch/cris/include/arch-v32/arch/spinlock.h
+++ /dev/null
@@ -1,131 +0,0 @@
1#ifndef __ASM_ARCH_SPINLOCK_H
2#define __ASM_ARCH_SPINLOCK_H
3
4#include <linux/spinlock_types.h>
5
6#define RW_LOCK_BIAS 0x01000000
7
8extern void cris_spin_unlock(void *l, int val);
9extern void cris_spin_lock(void *l);
10extern int cris_spin_trylock(void *l);
11
12static inline int arch_spin_is_locked(arch_spinlock_t *x)
13{
14 return *(volatile signed char *)(&(x)->slock) <= 0;
15}
16
17static inline void arch_spin_unlock(arch_spinlock_t *lock)
18{
19 __asm__ volatile ("move.d %1,%0" \
20 : "=m" (lock->slock) \
21 : "r" (1) \
22 : "memory");
23}
24
25static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
26{
27 while (arch_spin_is_locked(lock))
28 cpu_relax();
29}
30
31static inline int arch_spin_trylock(arch_spinlock_t *lock)
32{
33 return cris_spin_trylock((void *)&lock->slock);
34}
35
36static inline void arch_spin_lock(arch_spinlock_t *lock)
37{
38 cris_spin_lock((void *)&lock->slock);
39}
40
41static inline void
42arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
43{
44 arch_spin_lock(lock);
45}
46
47/*
48 * Read-write spinlocks, allowing multiple readers
49 * but only one writer.
50 *
51 * NOTE! it is quite common to have readers in interrupts
52 * but no interrupt writers. For those circumstances we
53 * can "mix" irq-safe locks - any writer needs to get a
54 * irq-safe write-lock, but readers can get non-irqsafe
55 * read-locks.
56 *
57 */
58
59static inline int arch_read_can_lock(arch_rwlock_t *x)
60{
61 return (int)(x)->lock > 0;
62}
63
64static inline int arch_write_can_lock(arch_rwlock_t *x)
65{
66 return (x)->lock == RW_LOCK_BIAS;
67}
68
69static inline void arch_read_lock(arch_rwlock_t *rw)
70{
71 arch_spin_lock(&rw->slock);
72 while (rw->lock == 0);
73 rw->lock--;
74 arch_spin_unlock(&rw->slock);
75}
76
77static inline void arch_write_lock(arch_rwlock_t *rw)
78{
79 arch_spin_lock(&rw->slock);
80 while (rw->lock != RW_LOCK_BIAS);
81 rw->lock = 0;
82 arch_spin_unlock(&rw->slock);
83}
84
85static inline void arch_read_unlock(arch_rwlock_t *rw)
86{
87 arch_spin_lock(&rw->slock);
88 rw->lock++;
89 arch_spin_unlock(&rw->slock);
90}
91
92static inline void arch_write_unlock(arch_rwlock_t *rw)
93{
94 arch_spin_lock(&rw->slock);
95 while (rw->lock != RW_LOCK_BIAS);
96 rw->lock = RW_LOCK_BIAS;
97 arch_spin_unlock(&rw->slock);
98}
99
100static inline int arch_read_trylock(arch_rwlock_t *rw)
101{
102 int ret = 0;
103 arch_spin_lock(&rw->slock);
104 if (rw->lock != 0) {
105 rw->lock--;
106 ret = 1;
107 }
108 arch_spin_unlock(&rw->slock);
109 return ret;
110}
111
112static inline int arch_write_trylock(arch_rwlock_t *rw)
113{
114 int ret = 0;
115 arch_spin_lock(&rw->slock);
116 if (rw->lock == RW_LOCK_BIAS) {
117 rw->lock = 0;
118 ret = 1;
119 }
120 arch_spin_unlock(&rw->slock);
121 return ret;
122}
123
124#define _raw_read_lock_flags(lock, flags) _raw_read_lock(lock)
125#define _raw_write_lock_flags(lock, flags) _raw_write_lock(lock)
126
127#define arch_spin_relax(lock) cpu_relax()
128#define arch_read_relax(lock) cpu_relax()
129#define arch_write_relax(lock) cpu_relax()
130
131#endif /* __ASM_ARCH_SPINLOCK_H */
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 889f2de050a3..057e51859b0a 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -1,16 +1,29 @@
1 1generic-y += atomic.h
2generic-y += barrier.h 2generic-y += barrier.h
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-y += cmpxchg.h
4generic-y += cputime.h 5generic-y += cputime.h
6generic-y += device.h
7generic-y += div64.h
5generic-y += exec.h 8generic-y += exec.h
9generic-y += emergency-restart.h
10generic-y += futex.h
11generic-y += hardirq.h
12generic-y += irq_regs.h
6generic-y += irq_work.h 13generic-y += irq_work.h
14generic-y += kdebug.h
15generic-y += kmap_types.h
7generic-y += kvm_para.h 16generic-y += kvm_para.h
8generic-y += linkage.h 17generic-y += linkage.h
18generic-y += local.h
19generic-y += local64.h
9generic-y += mcs_spinlock.h 20generic-y += mcs_spinlock.h
10generic-y += module.h 21generic-y += module.h
22generic-y += percpu.h
11generic-y += preempt.h 23generic-y += preempt.h
12generic-y += scatterlist.h 24generic-y += scatterlist.h
13generic-y += sections.h 25generic-y += sections.h
26generic-y += topology.h
14generic-y += trace_clock.h 27generic-y += trace_clock.h
15generic-y += vga.h 28generic-y += vga.h
16generic-y += xor.h 29generic-y += xor.h
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
deleted file mode 100644
index 279766a70664..000000000000
--- a/arch/cris/include/asm/atomic.h
+++ /dev/null
@@ -1,149 +0,0 @@
1/* $Id: atomic.h,v 1.3 2001/07/25 16:15:19 bjornw Exp $ */
2
3#ifndef __ASM_CRIS_ATOMIC__
4#define __ASM_CRIS_ATOMIC__
5
6#include <linux/compiler.h>
7#include <linux/types.h>
8#include <asm/cmpxchg.h>
9#include <arch/atomic.h>
10#include <arch/system.h>
11#include <asm/barrier.h>
12
13/*
14 * Atomic operations that C can't guarantee us. Useful for
15 * resource counting etc..
16 */
17
18#define ATOMIC_INIT(i) { (i) }
19
20#define atomic_read(v) ACCESS_ONCE((v)->counter)
21#define atomic_set(v,i) (((v)->counter) = (i))
22
23/* These should be written in asm but we do it in C for now. */
24
25#define ATOMIC_OP(op, c_op) \
26static inline void atomic_##op(int i, volatile atomic_t *v) \
27{ \
28 unsigned long flags; \
29 cris_atomic_save(v, flags); \
30 v->counter c_op i; \
31 cris_atomic_restore(v, flags); \
32} \
33
34#define ATOMIC_OP_RETURN(op, c_op) \
35static inline int atomic_##op##_return(int i, volatile atomic_t *v) \
36{ \
37 unsigned long flags; \
38 int retval; \
39 cris_atomic_save(v, flags); \
40 retval = (v->counter c_op i); \
41 cris_atomic_restore(v, flags); \
42 return retval; \
43}
44
45#define ATOMIC_OPS(op, c_op) ATOMIC_OP(op, c_op) ATOMIC_OP_RETURN(op, c_op)
46
47ATOMIC_OPS(add, +=)
48ATOMIC_OPS(sub, -=)
49
50#undef ATOMIC_OPS
51#undef ATOMIC_OP_RETURN
52#undef ATOMIC_OP
53
54#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
55
56static inline int atomic_sub_and_test(int i, volatile atomic_t *v)
57{
58 int retval;
59 unsigned long flags;
60 cris_atomic_save(v, flags);
61 retval = (v->counter -= i) == 0;
62 cris_atomic_restore(v, flags);
63 return retval;
64}
65
66static inline void atomic_inc(volatile atomic_t *v)
67{
68 unsigned long flags;
69 cris_atomic_save(v, flags);
70 (v->counter)++;
71 cris_atomic_restore(v, flags);
72}
73
74static inline void atomic_dec(volatile atomic_t *v)
75{
76 unsigned long flags;
77 cris_atomic_save(v, flags);
78 (v->counter)--;
79 cris_atomic_restore(v, flags);
80}
81
82static inline int atomic_inc_return(volatile atomic_t *v)
83{
84 unsigned long flags;
85 int retval;
86 cris_atomic_save(v, flags);
87 retval = ++(v->counter);
88 cris_atomic_restore(v, flags);
89 return retval;
90}
91
92static inline int atomic_dec_return(volatile atomic_t *v)
93{
94 unsigned long flags;
95 int retval;
96 cris_atomic_save(v, flags);
97 retval = --(v->counter);
98 cris_atomic_restore(v, flags);
99 return retval;
100}
101static inline int atomic_dec_and_test(volatile atomic_t *v)
102{
103 int retval;
104 unsigned long flags;
105 cris_atomic_save(v, flags);
106 retval = --(v->counter) == 0;
107 cris_atomic_restore(v, flags);
108 return retval;
109}
110
111static inline int atomic_inc_and_test(volatile atomic_t *v)
112{
113 int retval;
114 unsigned long flags;
115 cris_atomic_save(v, flags);
116 retval = ++(v->counter) == 0;
117 cris_atomic_restore(v, flags);
118 return retval;
119}
120
121static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
122{
123 int ret;
124 unsigned long flags;
125
126 cris_atomic_save(v, flags);
127 ret = v->counter;
128 if (likely(ret == old))
129 v->counter = new;
130 cris_atomic_restore(v, flags);
131 return ret;
132}
133
134#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
135
136static inline int __atomic_add_unless(atomic_t *v, int a, int u)
137{
138 int ret;
139 unsigned long flags;
140
141 cris_atomic_save(v, flags);
142 ret = v->counter;
143 if (ret != u)
144 v->counter += a;
145 cris_atomic_restore(v, flags);
146 return ret;
147}
148
149#endif
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index bd49a546f4f5..8062cb52d343 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -19,119 +19,10 @@
19#endif 19#endif
20 20
21#include <arch/bitops.h> 21#include <arch/bitops.h>
22#include <linux/atomic.h>
23#include <linux/compiler.h> 22#include <linux/compiler.h>
24#include <asm/barrier.h> 23#include <asm/barrier.h>
25 24
26/* 25#include <asm-generic/bitops/atomic.h>
27 * set_bit - Atomically set a bit in memory
28 * @nr: the bit to set
29 * @addr: the address to start counting from
30 *
31 * This function is atomic and may not be reordered. See __set_bit()
32 * if you do not require the atomic guarantees.
33 * Note that @nr may be almost arbitrarily large; this function is not
34 * restricted to acting on a single-word quantity.
35 */
36
37#define set_bit(nr, addr) (void)test_and_set_bit(nr, addr)
38
39/*
40 * clear_bit - Clears a bit in memory
41 * @nr: Bit to clear
42 * @addr: Address to start counting from
43 *
44 * clear_bit() is atomic and may not be reordered. However, it does
45 * not contain a memory barrier, so if it is used for locking purposes,
46 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
47 * in order to ensure changes are visible on other processors.
48 */
49
50#define clear_bit(nr, addr) (void)test_and_clear_bit(nr, addr)
51
52/*
53 * change_bit - Toggle a bit in memory
54 * @nr: Bit to change
55 * @addr: Address to start counting from
56 *
57 * change_bit() is atomic and may not be reordered.
58 * Note that @nr may be almost arbitrarily large; this function is not
59 * restricted to acting on a single-word quantity.
60 */
61
62#define change_bit(nr, addr) (void)test_and_change_bit(nr, addr)
63
64/**
65 * test_and_set_bit - Set a bit and return its old value
66 * @nr: Bit to set
67 * @addr: Address to count from
68 *
69 * This operation is atomic and cannot be reordered.
70 * It also implies a memory barrier.
71 */
72
73static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
74{
75 unsigned int mask, retval;
76 unsigned long flags;
77 unsigned int *adr = (unsigned int *)addr;
78
79 adr += nr >> 5;
80 mask = 1 << (nr & 0x1f);
81 cris_atomic_save(addr, flags);
82 retval = (mask & *adr) != 0;
83 *adr |= mask;
84 cris_atomic_restore(addr, flags);
85 return retval;
86}
87
88/**
89 * test_and_clear_bit - Clear a bit and return its old value
90 * @nr: Bit to clear
91 * @addr: Address to count from
92 *
93 * This operation is atomic and cannot be reordered.
94 * It also implies a memory barrier.
95 */
96
97static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
98{
99 unsigned int mask, retval;
100 unsigned long flags;
101 unsigned int *adr = (unsigned int *)addr;
102
103 adr += nr >> 5;
104 mask = 1 << (nr & 0x1f);
105 cris_atomic_save(addr, flags);
106 retval = (mask & *adr) != 0;
107 *adr &= ~mask;
108 cris_atomic_restore(addr, flags);
109 return retval;
110}
111
112/**
113 * test_and_change_bit - Change a bit and return its old value
114 * @nr: Bit to change
115 * @addr: Address to count from
116 *
117 * This operation is atomic and cannot be reordered.
118 * It also implies a memory barrier.
119 */
120
121static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
122{
123 unsigned int mask, retval;
124 unsigned long flags;
125 unsigned int *adr = (unsigned int *)addr;
126 adr += nr >> 5;
127 mask = 1 << (nr & 0x1f);
128 cris_atomic_save(addr, flags);
129 retval = (mask & *adr) != 0;
130 *adr ^= mask;
131 cris_atomic_restore(addr, flags);
132 return retval;
133}
134
135#include <asm-generic/bitops/non-atomic.h> 26#include <asm-generic/bitops/non-atomic.h>
136 27
137/* 28/*
diff --git a/arch/cris/include/asm/cmpxchg.h b/arch/cris/include/asm/cmpxchg.h
deleted file mode 100644
index b756dac8aa3f..000000000000
--- a/arch/cris/include/asm/cmpxchg.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef __ASM_CRIS_CMPXCHG__
2#define __ASM_CRIS_CMPXCHG__
3
4#include <linux/irqflags.h>
5
6static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
7{
8 /* since Etrax doesn't have any atomic xchg instructions, we need to disable
9 irq's (if enabled) and do it with move.d's */
10 unsigned long flags,temp;
11 local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
12 switch (size) {
13 case 1:
14 *((unsigned char *)&temp) = x;
15 x = *(unsigned char *)ptr;
16 *(unsigned char *)ptr = *((unsigned char *)&temp);
17 break;
18 case 2:
19 *((unsigned short *)&temp) = x;
20 x = *(unsigned short *)ptr;
21 *(unsigned short *)ptr = *((unsigned short *)&temp);
22 break;
23 case 4:
24 temp = x;
25 x = *(unsigned long *)ptr;
26 *(unsigned long *)ptr = temp;
27 break;
28 }
29 local_irq_restore(flags); /* restore irq enable bit */
30 return x;
31}
32
33#define xchg(ptr,x) \
34 ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
35
36#define tas(ptr) (xchg((ptr),1))
37
38#include <asm-generic/cmpxchg-local.h>
39
40/*
41 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
42 * them available.
43 */
44#define cmpxchg_local(ptr, o, n) \
45 ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
46 (unsigned long)(n), sizeof(*(ptr))))
47#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
48
49#ifndef CONFIG_SMP
50#include <asm-generic/cmpxchg.h>
51#endif
52
53#endif /* __ASM_CRIS_CMPXCHG__ */
diff --git a/arch/cris/include/asm/device.h b/arch/cris/include/asm/device.h
deleted file mode 100644
index d8f9872b0e2d..000000000000
--- a/arch/cris/include/asm/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/*
2 * Arch specific extensions to struct device
3 *
4 * This file is released under the GPLv2
5 */
6#include <asm-generic/device.h>
7
diff --git a/arch/cris/include/asm/div64.h b/arch/cris/include/asm/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/arch/cris/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/div64.h>
diff --git a/arch/cris/include/asm/elf.h b/arch/cris/include/asm/elf.h
index 30ded8fbf592..c2a394ff55ff 100644
--- a/arch/cris/include/asm/elf.h
+++ b/arch/cris/include/asm/elf.h
@@ -71,7 +71,7 @@ typedef unsigned long elf_fpregset_t;
71 the loader. We need to make sure that it is out of the way of the program 71 the loader. We need to make sure that it is out of the way of the program
72 that it will "exec", and that there is sufficient room for the brk. */ 72 that it will "exec", and that there is sufficient room for the brk. */
73 73
74#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) 74#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
75 75
76/* This yields a mask that user programs can use to figure out what 76/* This yields a mask that user programs can use to figure out what
77 instruction set this CPU supports. This could be done in user space, 77 instruction set this CPU supports. This could be done in user space,
diff --git a/arch/cris/include/asm/emergency-restart.h b/arch/cris/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/arch/cris/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _ASM_EMERGENCY_RESTART_H
2#define _ASM_EMERGENCY_RESTART_H
3
4#include <asm-generic/emergency-restart.h>
5
6#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/cris/include/asm/futex.h b/arch/cris/include/asm/futex.h
deleted file mode 100644
index 6a332a9f099c..000000000000
--- a/arch/cris/include/asm/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _ASM_FUTEX_H
2#define _ASM_FUTEX_H
3
4#include <asm-generic/futex.h>
5
6#endif
diff --git a/arch/cris/include/asm/hardirq.h b/arch/cris/include/asm/hardirq.h
deleted file mode 100644
index 04126f7bfab2..000000000000
--- a/arch/cris/include/asm/hardirq.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef __ASM_HARDIRQ_H
2#define __ASM_HARDIRQ_H
3
4#include <asm/irq.h>
5#include <asm-generic/hardirq.h>
6
7#endif /* __ASM_HARDIRQ_H */
diff --git a/arch/cris/include/asm/irq_regs.h b/arch/cris/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/cris/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/irq_regs.h>
diff --git a/arch/cris/include/asm/kdebug.h b/arch/cris/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b037665..000000000000
--- a/arch/cris/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/kdebug.h>
diff --git a/arch/cris/include/asm/kmap_types.h b/arch/cris/include/asm/kmap_types.h
deleted file mode 100644
index d2d643c4ea59..000000000000
--- a/arch/cris/include/asm/kmap_types.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef _ASM_KMAP_TYPES_H
2#define _ASM_KMAP_TYPES_H
3
4/* Dummy header just to define km_type. None of this
5 * is actually used on cris.
6 */
7
8#include <asm-generic/kmap_types.h>
9
10#endif
diff --git a/arch/cris/include/asm/local.h b/arch/cris/include/asm/local.h
deleted file mode 100644
index c11c530f74d0..000000000000
--- a/arch/cris/include/asm/local.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/local.h>
diff --git a/arch/cris/include/asm/local64.h b/arch/cris/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/cris/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/local64.h>
diff --git a/arch/cris/include/asm/percpu.h b/arch/cris/include/asm/percpu.h
deleted file mode 100644
index 6db9b43cf80a..000000000000
--- a/arch/cris/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _CRIS_PERCPU_H
2#define _CRIS_PERCPU_H
3
4#include <asm-generic/percpu.h>
5
6#endif /* _CRIS_PERCPU_H */
diff --git a/arch/cris/include/asm/smp.h b/arch/cris/include/asm/smp.h
deleted file mode 100644
index c615a06dd757..000000000000
--- a/arch/cris/include/asm/smp.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef __ASM_SMP_H
2#define __ASM_SMP_H
3
4#include <linux/cpumask.h>
5
6extern cpumask_t phys_cpu_present_map;
7
8#define raw_smp_processor_id() (current_thread_info()->cpu)
9
10#endif
diff --git a/arch/cris/include/asm/spinlock.h b/arch/cris/include/asm/spinlock.h
deleted file mode 100644
index ed816b57face..000000000000
--- a/arch/cris/include/asm/spinlock.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <arch/spinlock.h>
diff --git a/arch/cris/include/asm/tlbflush.h b/arch/cris/include/asm/tlbflush.h
index 20697e7ef4f2..b424f43a9fd6 100644
--- a/arch/cris/include/asm/tlbflush.h
+++ b/arch/cris/include/asm/tlbflush.h
@@ -22,16 +22,9 @@ extern void __flush_tlb_mm(struct mm_struct *mm);
22extern void __flush_tlb_page(struct vm_area_struct *vma, 22extern void __flush_tlb_page(struct vm_area_struct *vma,
23 unsigned long addr); 23 unsigned long addr);
24 24
25#ifdef CONFIG_SMP
26extern void flush_tlb_all(void);
27extern void flush_tlb_mm(struct mm_struct *mm);
28extern void flush_tlb_page(struct vm_area_struct *vma,
29 unsigned long addr);
30#else
31#define flush_tlb_all __flush_tlb_all 25#define flush_tlb_all __flush_tlb_all
32#define flush_tlb_mm __flush_tlb_mm 26#define flush_tlb_mm __flush_tlb_mm
33#define flush_tlb_page __flush_tlb_page 27#define flush_tlb_page __flush_tlb_page
34#endif
35 28
36static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end) 29static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
37{ 30{
diff --git a/arch/cris/include/asm/topology.h b/arch/cris/include/asm/topology.h
deleted file mode 100644
index 2ac613d32a89..000000000000
--- a/arch/cris/include/asm/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _ASM_CRIS_TOPOLOGY_H
2#define _ASM_CRIS_TOPOLOGY_H
3
4#include <asm-generic/topology.h>
5
6#endif /* _ASM_CRIS_TOPOLOGY_H */
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
index b45640b3e600..edef71f12bb8 100644
--- a/arch/cris/kernel/Makefile
+++ b/arch/cris/kernel/Makefile
@@ -7,6 +7,7 @@ CPPFLAGS_vmlinux.lds := -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
7extra-y := vmlinux.lds 7extra-y := vmlinux.lds
8 8
9obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o 9obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
10obj-y += devicetree.o
10 11
11obj-$(CONFIG_MODULES) += crisksyms.o 12obj-$(CONFIG_MODULES) += crisksyms.o
12obj-$(CONFIG_MODULES) += module.o 13obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/cris/kernel/devicetree.c b/arch/cris/kernel/devicetree.c
new file mode 100644
index 000000000000..53ff8d73e7e1
--- /dev/null
+++ b/arch/cris/kernel/devicetree.c
@@ -0,0 +1,14 @@
1#include <linux/init.h>
2#include <linux/bootmem.h>
3#include <linux/printk.h>
4
5void __init early_init_dt_add_memory_arch(u64 base, u64 size)
6{
7 pr_err("%s(%llx, %llx)\n",
8 __func__, base, size);
9}
10
11void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
12{
13 return alloc_bootmem_align(size, align);
14}
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index 58d44ee1a71f..fd3427e563c5 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -42,3 +42,26 @@ void do_notify_resume(int canrestart, struct pt_regs *regs,
42 tracehook_notify_resume(regs); 42 tracehook_notify_resume(regs);
43 } 43 }
44} 44}
45
46void do_work_pending(int syscall, struct pt_regs *regs,
47 unsigned int thread_flags)
48{
49 do {
50 if (likely(thread_flags & _TIF_NEED_RESCHED)) {
51 schedule();
52 } else {
53 if (unlikely(!user_mode(regs)))
54 return;
55 local_irq_enable();
56 if (thread_flags & _TIF_SIGPENDING) {
57 do_signal(syscall, regs);
58 syscall = 0;
59 } else {
60 clear_thread_flag(TIF_NOTIFY_RESUME);
61 tracehook_notify_resume(regs);
62 }
63 }
64 local_irq_disable();
65 thread_flags = current_thread_info()->flags;
66 } while (thread_flags & _TIF_WORK_MASK);
67}
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 905b70ea9939..bb12aa93201d 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -19,6 +19,9 @@
19#include <linux/utsname.h> 19#include <linux/utsname.h>
20#include <linux/pfn.h> 20#include <linux/pfn.h>
21#include <linux/cpu.h> 21#include <linux/cpu.h>
22#include <linux/of.h>
23#include <linux/of_fdt.h>
24#include <linux/of_platform.h>
22#include <asm/setup.h> 25#include <asm/setup.h>
23#include <arch/system.h> 26#include <arch/system.h>
24 27
@@ -64,6 +67,10 @@ void __init setup_arch(char **cmdline_p)
64 unsigned long start_pfn, max_pfn; 67 unsigned long start_pfn, max_pfn;
65 unsigned long memory_start; 68 unsigned long memory_start;
66 69
70#ifdef CONFIG_OF
71 early_init_dt_scan(__dtb_start);
72#endif
73
67 /* register an initial console printing routine for printk's */ 74 /* register an initial console printing routine for printk's */
68 75
69 init_etrax_debug(); 76 init_etrax_debug();
@@ -141,6 +148,8 @@ void __init setup_arch(char **cmdline_p)
141 148
142 reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT); 149 reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT);
143 150
151 unflatten_and_copy_device_tree();
152
144 /* paging_init() sets up the MMU and marks all pages as reserved */ 153 /* paging_init() sets up the MMU and marks all pages as reserved */
145 154
146 paging_init(); 155 paging_init();
@@ -204,3 +213,9 @@ static int __init topology_init(void)
204 213
205subsys_initcall(topology_init); 214subsys_initcall(topology_init);
206 215
216static int __init cris_of_init(void)
217{
218 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
219 return 0;
220}
221core_initcall(cris_of_init);
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index fe6acdabbc8d..7780d379522f 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -79,11 +79,13 @@ cris_do_profile(struct pt_regs* regs)
79#endif 79#endif
80} 80}
81 81
82#ifndef CONFIG_GENERIC_SCHED_CLOCK
82unsigned long long sched_clock(void) 83unsigned long long sched_clock(void)
83{ 84{
84 return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) + 85 return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) +
85 get_ns_in_jiffie(); 86 get_ns_in_jiffie();
86} 87}
88#endif
87 89
88static int 90static int
89__init init_udelay(void) 91__init init_udelay(void)