aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@marvell.com>2010-11-23 22:54:25 -0500
committerEric Miao <eric.y.miao@gmail.com>2010-12-20 10:07:36 -0500
commitef6c84454f8567d4968c210d7d194fb711ed3739 (patch)
treede7d0315aa2b9c2adaed5fd93cca1b6a74520f6b
parenta79a9ad94acdbd0106491f5a444167636562460f (diff)
ARM: pxa: add iwmmx support for PJ4
iwmmxt is used in XScale, XScale3, Mohawk and PJ4 core. But the instructions of accessing CP0 and CP1 is changed in PJ4. Append more files to support iwmmxt in PJ4 core. Signed-off-by: Zhou Zhu <zzhu3@marvell.com> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com> Acked-by: Nicolas Pitre <nico@fluxnic.net> Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/iwmmxt.S55
-rw-r--r--arch/arm/kernel/pj4-cp0.c94
4 files changed, 139 insertions, 15 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c0573..e2c79a24d3c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -999,8 +999,8 @@ source arch/arm/mm/Kconfig
999 999
1000config IWMMXT 1000config IWMMXT
1001 bool "Enable iWMMXt support" 1001 bool "Enable iWMMXt support"
1002 depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK 1002 depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
1003 default y if PXA27x || PXA3xx || ARCH_MMP 1003 default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
1004 help 1004 help
1005 Enable support for iWMMXt context switching at run time if 1005 Enable support for iWMMXt context switching at run time if
1006 running on a CPU that supports it. 1006 running on a CPU that supports it.
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5b9b268f4fb..b0f11fa7a4b 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -50,6 +50,7 @@ AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
50obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o 50obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o
51obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o 51obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
52obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o 52obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
53obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
53obj-$(CONFIG_IWMMXT) += iwmmxt.o 54obj-$(CONFIG_IWMMXT) += iwmmxt.o
54obj-$(CONFIG_CPU_HAS_PMU) += pmu.o 55obj-$(CONFIG_CPU_HAS_PMU) += pmu.o
55obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 56obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index b63b528f22a..7fa3bb0d239 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -19,6 +19,14 @@
19#include <asm/thread_info.h> 19#include <asm/thread_info.h>
20#include <asm/asm-offsets.h> 20#include <asm/asm-offsets.h>
21 21
22#if defined(CONFIG_CPU_PJ4)
23#define PJ4(code...) code
24#define XSC(code...)
25#else
26#define PJ4(code...)
27#define XSC(code...) code
28#endif
29
22#define MMX_WR0 (0x00) 30#define MMX_WR0 (0x00)
23#define MMX_WR1 (0x08) 31#define MMX_WR1 (0x08)
24#define MMX_WR2 (0x10) 32#define MMX_WR2 (0x10)
@@ -58,11 +66,17 @@
58 66
59ENTRY(iwmmxt_task_enable) 67ENTRY(iwmmxt_task_enable)
60 68
61 mrc p15, 0, r2, c15, c1, 0 69 XSC(mrc p15, 0, r2, c15, c1, 0)
62 tst r2, #0x3 @ CP0 and CP1 accessible? 70 PJ4(mrc p15, 0, r2, c1, c0, 2)
71 @ CP0 and CP1 accessible?
72 XSC(tst r2, #0x3)
73 PJ4(tst r2, #0xf)
63 movne pc, lr @ if so no business here 74 movne pc, lr @ if so no business here
64 orr r2, r2, #0x3 @ enable access to CP0 and CP1 75 @ enable access to CP0 and CP1
65 mcr p15, 0, r2, c15, c1, 0 76 XSC(orr r2, r2, #0x3)
77 XSC(mcr p15, 0, r2, c15, c1, 0)
78 PJ4(orr r2, r2, #0xf)
79 PJ4(mcr p15, 0, r2, c1, c0, 2)
66 80
67 ldr r3, =concan_owner 81 ldr r3, =concan_owner
68 add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area 82 add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area
@@ -179,17 +193,26 @@ ENTRY(iwmmxt_task_disable)
179 teqne r1, r2 @ or specified one? 193 teqne r1, r2 @ or specified one?
180 bne 1f @ no: quit 194 bne 1f @ no: quit
181 195
182 mrc p15, 0, r4, c15, c1, 0 196 @ enable access to CP0 and CP1
183 orr r4, r4, #0x3 @ enable access to CP0 and CP1 197 XSC(mrc p15, 0, r4, c15, c1, 0)
184 mcr p15, 0, r4, c15, c1, 0 198 XSC(orr r4, r4, #0xf)
199 XSC(mcr p15, 0, r4, c15, c1, 0)
200 PJ4(mrc p15, 0, r4, c1, c0, 2)
201 PJ4(orr r4, r4, #0x3)
202 PJ4(mcr p15, 0, r4, c1, c0, 2)
203
185 mov r0, #0 @ nothing to load 204 mov r0, #0 @ nothing to load
186 str r0, [r3] @ no more current owner 205 str r0, [r3] @ no more current owner
187 mrc p15, 0, r2, c2, c0, 0 206 mrc p15, 0, r2, c2, c0, 0
188 mov r2, r2 @ cpwait 207 mov r2, r2 @ cpwait
189 bl concan_save 208 bl concan_save
190 209
191 bic r4, r4, #0x3 @ disable access to CP0 and CP1 210 @ disable access to CP0 and CP1
192 mcr p15, 0, r4, c15, c1, 0 211 XSC(bic r4, r4, #0x3)
212 XSC(mcr p15, 0, r4, c15, c1, 0)
213 PJ4(bic r4, r4, #0xf)
214 PJ4(mcr p15, 0, r4, c1, c0, 2)
215
193 mrc p15, 0, r2, c2, c0, 0 216 mrc p15, 0, r2, c2, c0, 0
194 mov r2, r2 @ cpwait 217 mov r2, r2 @ cpwait
195 218
@@ -277,8 +300,11 @@ ENTRY(iwmmxt_task_restore)
277 */ 300 */
278ENTRY(iwmmxt_task_switch) 301ENTRY(iwmmxt_task_switch)
279 302
280 mrc p15, 0, r1, c15, c1, 0 303 XSC(mrc p15, 0, r1, c15, c1, 0)
281 tst r1, #0x3 @ CP0 and CP1 accessible? 304 PJ4(mrc p15, 0, r1, c1, c0, 2)
305 @ CP0 and CP1 accessible?
306 XSC(tst r1, #0x3)
307 PJ4(tst r1, #0xf)
282 bne 1f @ yes: block them for next task 308 bne 1f @ yes: block them for next task
283 309
284 ldr r2, =concan_owner 310 ldr r2, =concan_owner
@@ -287,8 +313,11 @@ ENTRY(iwmmxt_task_switch)
287 teq r2, r3 @ next task owns it? 313 teq r2, r3 @ next task owns it?
288 movne pc, lr @ no: leave Concan disabled 314 movne pc, lr @ no: leave Concan disabled
289 315
2901: eor r1, r1, #3 @ flip Concan access 3161: @ flip Conan access
291 mcr p15, 0, r1, c15, c1, 0 317 XSC(eor r1, r1, #0x3)
318 XSC(mcr p15, 0, r1, c15, c1, 0)
319 PJ4(eor r1, r1, #0xf)
320 PJ4(mcr p15, 0, r1, c1, c0, 2)
292 321
293 mrc p15, 0, r1, c2, c0, 0 322 mrc p15, 0, r1, c2, c0, 0
294 sub pc, lr, r1, lsr #32 @ cpwait and return 323 sub pc, lr, r1, lsr #32 @ cpwait and return
diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
new file mode 100644
index 00000000000..a4b1b0748fd
--- /dev/null
+++ b/arch/arm/kernel/pj4-cp0.c
@@ -0,0 +1,94 @@
1/*
2 * linux/arch/arm/kernel/pj4-cp0.c
3 *
4 * PJ4 iWMMXt coprocessor context switching and handling
5 *
6 * Copyright (c) 2010 Marvell International Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/signal.h>
17#include <linux/sched.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <asm/thread_notify.h>
21
22static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
23{
24 struct thread_info *thread = t;
25
26 switch (cmd) {
27 case THREAD_NOTIFY_FLUSH:
28 /*
29 * flush_thread() zeroes thread->fpstate, so no need
30 * to do anything here.
31 *
32 * FALLTHROUGH: Ensure we don't try to overwrite our newly
33 * initialised state information on the first fault.
34 */
35
36 case THREAD_NOTIFY_EXIT:
37 iwmmxt_task_release(thread);
38 break;
39
40 case THREAD_NOTIFY_SWITCH:
41 iwmmxt_task_switch(thread);
42 break;
43 }
44
45 return NOTIFY_DONE;
46}
47
48static struct notifier_block iwmmxt_notifier_block = {
49 .notifier_call = iwmmxt_do,
50};
51
52
53static u32 __init pj4_cp_access_read(void)
54{
55 u32 value;
56
57 __asm__ __volatile__ (
58 "mrc p15, 0, %0, c1, c0, 2\n\t"
59 : "=r" (value));
60 return value;
61}
62
63static void __init pj4_cp_access_write(u32 value)
64{
65 u32 temp;
66
67 __asm__ __volatile__ (
68 "mcr p15, 0, %1, c1, c0, 2\n\t"
69 "mrc p15, 0, %0, c1, c0, 2\n\t"
70 "mov %0, %0\n\t"
71 "sub pc, pc, #4\n\t"
72 : "=r" (temp) : "r" (value));
73}
74
75
76/*
77 * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
78 * switch code handle iWMMXt context switching.
79 */
80static int __init pj4_cp0_init(void)
81{
82 u32 cp_access;
83
84 cp_access = pj4_cp_access_read() & ~0xf;
85 pj4_cp_access_write(cp_access);
86
87 printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n");
88 elf_hwcap |= HWCAP_IWMMXT;
89 thread_register_notifier(&iwmmxt_notifier_block);
90
91 return 0;
92}
93
94late_initcall(pj4_cp0_init);