diff options
80 files changed, 4495 insertions, 482 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index debde0128cd0..1e6b6bdf6340 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4448,7 +4448,7 @@ L: platform-driver-x86@vger.kernel.org | |||
4448 | S: Maintained | 4448 | S: Maintained |
4449 | F: drivers/platform/x86/panasonic-laptop.c | 4449 | F: drivers/platform/x86/panasonic-laptop.c |
4450 | 4450 | ||
4451 | PANASONIC MN10300/AM33 PORT | 4451 | PANASONIC MN10300/AM33/AM34 PORT |
4452 | M: David Howells <dhowells@redhat.com> | 4452 | M: David Howells <dhowells@redhat.com> |
4453 | M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> | 4453 | M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> |
4454 | L: linux-am33-list@redhat.com (moderated for non-subscribers) | 4454 | L: linux-am33-list@redhat.com (moderated for non-subscribers) |
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index a0a16e6e4a4e..81e27816aaf8 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -48,7 +48,7 @@ config GENERIC_CALIBRATE_DELAY | |||
48 | def_bool y | 48 | def_bool y |
49 | 49 | ||
50 | config GENERIC_CMOS_UPDATE | 50 | config GENERIC_CMOS_UPDATE |
51 | def_bool y | 51 | def_bool n |
52 | 52 | ||
53 | config GENERIC_FIND_NEXT_BIT | 53 | config GENERIC_FIND_NEXT_BIT |
54 | def_bool y | 54 | def_bool y |
@@ -72,10 +72,6 @@ config GENERIC_HARDIRQS | |||
72 | config HOTPLUG_CPU | 72 | config HOTPLUG_CPU |
73 | def_bool n | 73 | def_bool n |
74 | 74 | ||
75 | config HZ | ||
76 | int | ||
77 | default 1000 | ||
78 | |||
79 | mainmenu "Matsushita MN10300/AM33 Kernel Configuration" | 75 | mainmenu "Matsushita MN10300/AM33 Kernel Configuration" |
80 | 76 | ||
81 | source "init/Kconfig" | 77 | source "init/Kconfig" |
@@ -98,6 +94,9 @@ config MN10300_UNIT_ASB2303 | |||
98 | config MN10300_UNIT_ASB2305 | 94 | config MN10300_UNIT_ASB2305 |
99 | bool "ASB2305" | 95 | bool "ASB2305" |
100 | 96 | ||
97 | config MN10300_UNIT_ASB2364 | ||
98 | bool "ASB2364" | ||
99 | |||
101 | endchoice | 100 | endchoice |
102 | 101 | ||
103 | choice | 102 | choice |
@@ -115,17 +114,13 @@ config MN10300_PROC_MN103E010 | |||
115 | select MN10300_PROC_HAS_TTYSM1 | 114 | select MN10300_PROC_HAS_TTYSM1 |
116 | select MN10300_PROC_HAS_TTYSM2 | 115 | select MN10300_PROC_HAS_TTYSM2 |
117 | 116 | ||
118 | endchoice | 117 | config MN10300_PROC_MN2WS0050 |
119 | 118 | bool "MN2WS0050" | |
120 | choice | 119 | depends on MN10300_UNIT_ASB2364 |
121 | prompt "Processor core support" | 120 | select AM34_2 |
122 | default MN10300_CPU_AM33V2 | 121 | select MN10300_PROC_HAS_TTYSM0 |
123 | help | 122 | select MN10300_PROC_HAS_TTYSM1 |
124 | This option specifies the processor core for which the kernel will be | 123 | select MN10300_PROC_HAS_TTYSM2 |
125 | compiled. It affects the instruction set used. | ||
126 | |||
127 | config MN10300_CPU_AM33V2 | ||
128 | bool "AM33v2" | ||
129 | 124 | ||
130 | endchoice | 125 | endchoice |
131 | 126 | ||
@@ -138,7 +133,7 @@ config MN10300_HAS_ATOMIC_OPS_UNIT | |||
138 | config FPU | 133 | config FPU |
139 | bool "FPU present" | 134 | bool "FPU present" |
140 | default y | 135 | default y |
141 | depends on MN10300_PROC_MN103E010 | 136 | depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050 |
142 | 137 | ||
143 | config LAZY_SAVE_FPU | 138 | config LAZY_SAVE_FPU |
144 | bool "Save FPU state lazily" | 139 | bool "Save FPU state lazily" |
@@ -179,24 +174,55 @@ config KERNEL_TEXT_ADDRESS | |||
179 | 174 | ||
180 | config KERNEL_ZIMAGE_BASE_ADDRESS | 175 | config KERNEL_ZIMAGE_BASE_ADDRESS |
181 | hex "Base address of compressed vmlinux image" | 176 | hex "Base address of compressed vmlinux image" |
182 | default "0x90700000" | 177 | default "0x50700000" |
178 | |||
179 | config BOOT_STACK_OFFSET | ||
180 | hex | ||
181 | default "0xF00" if SMP | ||
182 | default "0xFF0" if !SMP | ||
183 | 183 | ||
184 | config BOOT_STACK_SIZE | ||
185 | hex | ||
186 | depends on SMP | ||
187 | default "0x100" | ||
184 | endmenu | 188 | endmenu |
185 | 189 | ||
186 | config PREEMPT | 190 | config SMP |
187 | bool "Preemptible Kernel" | 191 | bool "Symmetric multi-processing support" |
188 | help | 192 | default y |
189 | This option reduces the latency of the kernel when reacting to | 193 | depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050 |
190 | real-time or interactive events by allowing a low priority process to | 194 | ---help--- |
191 | be preempted even if it is in kernel mode executing a system call. | 195 | This enables support for systems with more than one CPU. If you have |
192 | This allows applications to run more reliably even when the system is | 196 | a system with only one CPU, like most personal computers, say N. If |
193 | under load. | 197 | you have a system with more than one CPU, say Y. |
198 | |||
199 | If you say N here, the kernel will run on single and multiprocessor | ||
200 | machines, but will use only one CPU of a multiprocessor machine. If | ||
201 | you say Y here, the kernel will run on many, but not all, | ||
202 | singleprocessor machines. On a singleprocessor machine, the kernel | ||
203 | will run faster if you say N here. | ||
204 | |||
205 | See also <file:Documentation/i386/IO-APIC.txt>, | ||
206 | <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at | ||
207 | <http://www.tldp.org/docs.html#howto>. | ||
194 | 208 | ||
195 | Say Y here if you are building a kernel for a desktop, embedded | 209 | If you don't know what to do here, say N. |
196 | or real-time system. Say N if you are unsure. | 210 | |
211 | config NR_CPUS | ||
212 | int | ||
213 | depends on SMP | ||
214 | default "2" | ||
215 | |||
216 | config USE_GENERIC_SMP_HELPERS | ||
217 | bool | ||
218 | depends on SMP | ||
219 | default y | ||
220 | |||
221 | source "kernel/Kconfig.preempt" | ||
197 | 222 | ||
198 | config MN10300_CURRENT_IN_E2 | 223 | config MN10300_CURRENT_IN_E2 |
199 | bool "Hold current task address in E2 register" | 224 | bool "Hold current task address in E2 register" |
225 | depends on !SMP | ||
200 | default y | 226 | default y |
201 | help | 227 | help |
202 | This option removes the E2/R2 register from the set available to gcc | 228 | This option removes the E2/R2 register from the set available to gcc |
@@ -218,12 +244,14 @@ config MN10300_USING_JTAG | |||
218 | suppresses the use of certain hardware debugging features, such as | 244 | suppresses the use of certain hardware debugging features, such as |
219 | single-stepping, which are taken over completely by the JTAG unit. | 245 | single-stepping, which are taken over completely by the JTAG unit. |
220 | 246 | ||
247 | source "kernel/Kconfig.hz" | ||
248 | |||
221 | config MN10300_RTC | 249 | config MN10300_RTC |
222 | bool "Using MN10300 RTC" | 250 | bool "Using MN10300 RTC" |
223 | depends on MN10300_PROC_MN103E010 | 251 | depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050 |
252 | select GENERIC_CMOS_UPDATE | ||
224 | default n | 253 | default n |
225 | help | 254 | help |
226 | |||
227 | This option enables support for the RTC, thus enabling time to be | 255 | This option enables support for the RTC, thus enabling time to be |
228 | tracked, even when system is powered down. This is available on-chip | 256 | tracked, even when system is powered down. This is available on-chip |
229 | on the MN103E010. | 257 | on the MN103E010. |
@@ -315,14 +343,23 @@ config MN10300_TTYSM1 | |||
315 | 343 | ||
316 | choice | 344 | choice |
317 | prompt "Select the timer to supply the clock for SIF1" | 345 | prompt "Select the timer to supply the clock for SIF1" |
318 | default MN10300_TTYSM0_TIMER9 | 346 | default MN10300_TTYSM1_TIMER12 \ |
347 | if !(AM33_2 || AM33_3) | ||
348 | default MN10300_TTYSM1_TIMER9 \ | ||
349 | if AM33_2 || AM33_3 | ||
319 | depends on MN10300_TTYSM1 | 350 | depends on MN10300_TTYSM1 |
320 | 351 | ||
352 | config MN10300_TTYSM1_TIMER12 | ||
353 | bool "Use timer 12 (16-bit)" | ||
354 | depends on !(AM33_2 || AM33_3) | ||
355 | |||
321 | config MN10300_TTYSM1_TIMER9 | 356 | config MN10300_TTYSM1_TIMER9 |
322 | bool "Use timer 9 (16-bit)" | 357 | bool "Use timer 9 (16-bit)" |
358 | depends on AM33_2 || AM33_3 | ||
323 | 359 | ||
324 | config MN10300_TTYSM1_TIMER3 | 360 | config MN10300_TTYSM1_TIMER3 |
325 | bool "Use timer 3 (8-bit)" | 361 | bool "Use timer 3 (8-bit)" |
362 | depends on AM33_2 || AM33_3 | ||
326 | 363 | ||
327 | endchoice | 364 | endchoice |
328 | 365 | ||
@@ -337,17 +374,33 @@ config MN10300_TTYSM2 | |||
337 | 374 | ||
338 | choice | 375 | choice |
339 | prompt "Select the timer to supply the clock for SIF2" | 376 | prompt "Select the timer to supply the clock for SIF2" |
340 | default MN10300_TTYSM0_TIMER10 | 377 | default MN10300_TTYSM2_TIMER3 \ |
378 | if !(AM33_2 || AM33_3) | ||
379 | default MN10300_TTYSM2_TIMER10 \ | ||
380 | if AM33_2 || AM33_3 | ||
341 | depends on MN10300_TTYSM2 | 381 | depends on MN10300_TTYSM2 |
342 | 382 | ||
383 | config MN10300_TTYSM2_TIMER9 | ||
384 | bool "Use timer 9 (16-bit)" | ||
385 | depends on !(AM33_2 || AM33_3) | ||
386 | |||
387 | config MN10300_TTYSM2_TIMER1 | ||
388 | bool "Use timer 1 (8-bit)" | ||
389 | depends on !(AM33_2 || AM33_3) | ||
390 | |||
391 | config MN10300_TTYSM2_TIMER3 | ||
392 | bool "Use timer 3 (8-bit)" | ||
393 | depends on !(AM33_2 || AM33_3) | ||
394 | |||
343 | config MN10300_TTYSM2_TIMER10 | 395 | config MN10300_TTYSM2_TIMER10 |
344 | bool "Use timer 10 (16-bit)" | 396 | bool "Use timer 10 (16-bit)" |
397 | depends on AM33_2 || AM33_3 | ||
345 | 398 | ||
346 | endchoice | 399 | endchoice |
347 | 400 | ||
348 | config MN10300_TTYSM2_CTS | 401 | config MN10300_TTYSM2_CTS |
349 | bool "Enable the use of the CTS line /dev/ttySM2" | 402 | bool "Enable the use of the CTS line /dev/ttySM2" |
350 | depends on MN10300_TTYSM2 | 403 | depends on MN10300_TTYSM2 && AM33_2 |
351 | 404 | ||
352 | endmenu | 405 | endmenu |
353 | 406 | ||
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index ac5c6bdb2f05..7120282bf0d8 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile | |||
@@ -36,6 +36,9 @@ endif | |||
36 | ifeq ($(CONFIG_MN10300_PROC_MN103E010),y) | 36 | ifeq ($(CONFIG_MN10300_PROC_MN103E010),y) |
37 | PROCESSOR := mn103e010 | 37 | PROCESSOR := mn103e010 |
38 | endif | 38 | endif |
39 | ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y) | ||
40 | PROCESSOR := mn2ws0050 | ||
41 | endif | ||
39 | 42 | ||
40 | ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y) | 43 | ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y) |
41 | UNIT := asb2303 | 44 | UNIT := asb2303 |
@@ -43,6 +46,9 @@ endif | |||
43 | ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y) | 46 | ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y) |
44 | UNIT := asb2305 | 47 | UNIT := asb2305 |
45 | endif | 48 | endif |
49 | ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y) | ||
50 | UNIT := asb2364 | ||
51 | endif | ||
46 | 52 | ||
47 | 53 | ||
48 | head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o | 54 | head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o |
diff --git a/arch/mn10300/boot/compressed/head.S b/arch/mn10300/boot/compressed/head.S index 4ef608a62416..7b50345b9e84 100644 --- a/arch/mn10300/boot/compressed/head.S +++ b/arch/mn10300/boot/compressed/head.S | |||
@@ -15,10 +15,28 @@ | |||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <asm/cpu-regs.h> | 16 | #include <asm/cpu-regs.h> |
17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
18 | #ifdef CONFIG_SMP | ||
19 | #include <proc/smp-regs.h> | ||
20 | #endif | ||
18 | 21 | ||
19 | .globl startup_32 | 22 | .globl startup_32 |
20 | startup_32: | 23 | startup_32: |
21 | # first save off parameters from bootloader | 24 | #ifdef CONFIG_SMP |
25 | # | ||
26 | # Secondary CPUs jump directly to the kernel entry point | ||
27 | # | ||
28 | # Must save primary CPU's D0-D2 registers as they hold boot parameters | ||
29 | # | ||
30 | mov (CPUID), d3 | ||
31 | and CPUID_MASK,d3 | ||
32 | beq startup_primary | ||
33 | mov CONFIG_KERNEL_TEXT_ADDRESS,a0 | ||
34 | jmp (a0) | ||
35 | |||
36 | startup_primary: | ||
37 | #endif /* CONFIG_SMP */ | ||
38 | |||
39 | # first save parameters from bootloader | ||
22 | mov param_save_area,a0 | 40 | mov param_save_area,a0 |
23 | mov d0,(a0) | 41 | mov d0,(a0) |
24 | mov d1,(4,a0) | 42 | mov d1,(4,a0) |
diff --git a/arch/mn10300/include/asm/exceptions.h b/arch/mn10300/include/asm/exceptions.h index 7d8080bc6590..ca3e20508c77 100644 --- a/arch/mn10300/include/asm/exceptions.h +++ b/arch/mn10300/include/asm/exceptions.h | |||
@@ -114,6 +114,8 @@ extern void die(const char *, struct pt_regs *, enum exception_code) | |||
114 | 114 | ||
115 | extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code); | 115 | extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code); |
116 | 116 | ||
117 | #define NUM2EXCEP_IRQ_LEVEL(num) (EXCEP_IRQ_LEVEL0 + (num) * 8) | ||
118 | |||
117 | #endif /* __ASSEMBLY__ */ | 119 | #endif /* __ASSEMBLY__ */ |
118 | 120 | ||
119 | #endif /* _ASM_EXCEPTIONS_H */ | 121 | #endif /* _ASM_EXCEPTIONS_H */ |
diff --git a/arch/mn10300/include/asm/frame.inc b/arch/mn10300/include/asm/frame.inc index 5b1949bdf039..406060e5e1c0 100644 --- a/arch/mn10300/include/asm/frame.inc +++ b/arch/mn10300/include/asm/frame.inc | |||
@@ -18,6 +18,9 @@ | |||
18 | #ifndef __ASM_OFFSETS_H__ | 18 | #ifndef __ASM_OFFSETS_H__ |
19 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
20 | #endif | 20 | #endif |
21 | #ifdef CONFIG_SMP | ||
22 | #include <proc/smp-regs.h> | ||
23 | #endif | ||
21 | 24 | ||
22 | #define pi break | 25 | #define pi break |
23 | 26 | ||
@@ -37,9 +40,25 @@ | |||
37 | movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp) | 40 | movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp) |
38 | mov sp,fp # FRAME pointer in A3 | 41 | mov sp,fp # FRAME pointer in A3 |
39 | add -12,sp # allow for calls to be made | 42 | add -12,sp # allow for calls to be made |
43 | #ifdef CONFIG_SMP | ||
44 | #ifdef CONFIG_PREEMPT /* FIXME */ | ||
45 | mov epsw,d2 | ||
46 | and ~EPSW_IE,epsw | ||
47 | #endif | ||
48 | mov (CPUID),a0 | ||
49 | add a0,a0 | ||
50 | add a0,a0 | ||
51 | mov (___frame,a0),a1 | ||
52 | mov a1,(REG_NEXT,fp) | ||
53 | mov fp,(___frame,a0) | ||
54 | #ifdef CONFIG_PREEMPT /* FIXME */ | ||
55 | mov d2,epsw | ||
56 | #endif | ||
57 | #else /* CONFIG_SMP */ | ||
40 | mov (__frame),a1 | 58 | mov (__frame),a1 |
41 | mov a1,(REG_NEXT,fp) | 59 | mov a1,(REG_NEXT,fp) |
42 | mov fp,(__frame) | 60 | mov fp,(__frame) |
61 | #endif /* CONFIG_SMP */ | ||
43 | 62 | ||
44 | and ~EPSW_FE,epsw # disable the FPU inside the kernel | 63 | and ~EPSW_FE,epsw # disable the FPU inside the kernel |
45 | 64 | ||
@@ -57,10 +76,27 @@ | |||
57 | .macro RESTORE_ALL | 76 | .macro RESTORE_ALL |
58 | # peel back the stack to the calling frame | 77 | # peel back the stack to the calling frame |
59 | # - this permits execve() to discard extra frames due to kernel syscalls | 78 | # - this permits execve() to discard extra frames due to kernel syscalls |
79 | #ifdef CONFIG_SMP | ||
80 | #ifdef CONFIG_PREEMPT /* FIXME */ | ||
81 | mov epsw,d2 | ||
82 | and ~EPSW_IE,epsw | ||
83 | #endif | ||
84 | mov (CPUID),a0 | ||
85 | add a0,a0 | ||
86 | add a0,a0 | ||
87 | mov (___frame,a0),fp | ||
88 | mov fp,sp | ||
89 | mov (REG_NEXT,fp),d0 # userspace has regs->next == 0 | ||
90 | mov d0,(___frame,a0) | ||
91 | #ifdef CONFIG_PREEMPT /* FIXME */ | ||
92 | mov d2,epsw | ||
93 | #endif | ||
94 | #else /* CONFIG_SMP */ | ||
60 | mov (__frame),fp | 95 | mov (__frame),fp |
61 | mov fp,sp | 96 | mov fp,sp |
62 | mov (REG_NEXT,fp),d0 # userspace has regs->next == 0 | 97 | mov (REG_NEXT,fp),d0 # userspace has regs->next == 0 |
63 | mov d0,(__frame) | 98 | mov d0,(__frame) |
99 | #endif /* CONFIG_SMP */ | ||
64 | 100 | ||
65 | #ifndef CONFIG_MN10300_USING_JTAG | 101 | #ifndef CONFIG_MN10300_USING_JTAG |
66 | mov (REG_EPSW,fp),d0 | 102 | mov (REG_EPSW,fp),d0 |
diff --git a/arch/mn10300/include/asm/hardirq.h b/arch/mn10300/include/asm/hardirq.h index 7bd9b7cc2451..0000d650b55f 100644 --- a/arch/mn10300/include/asm/hardirq.h +++ b/arch/mn10300/include/asm/hardirq.h | |||
@@ -19,8 +19,10 @@ | |||
19 | /* assembly code in softirq.h is sensitive to the offsets of these fields */ | 19 | /* assembly code in softirq.h is sensitive to the offsets of these fields */ |
20 | typedef struct { | 20 | typedef struct { |
21 | unsigned int __softirq_pending; | 21 | unsigned int __softirq_pending; |
22 | #ifdef CONFIG_MN10300_WD_TIMER | ||
22 | unsigned int __nmi_count; /* arch dependent */ | 23 | unsigned int __nmi_count; /* arch dependent */ |
23 | unsigned int __irq_count; /* arch dependent */ | 24 | unsigned int __irq_count; /* arch dependent */ |
25 | #endif | ||
24 | } ____cacheline_aligned irq_cpustat_t; | 26 | } ____cacheline_aligned irq_cpustat_t; |
25 | 27 | ||
26 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | 28 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ |
diff --git a/arch/mn10300/include/asm/intctl-regs.h b/arch/mn10300/include/asm/intctl-regs.h index ba544c796c5a..585b708c2bc0 100644 --- a/arch/mn10300/include/asm/intctl-regs.h +++ b/arch/mn10300/include/asm/intctl-regs.h | |||
@@ -15,24 +15,19 @@ | |||
15 | 15 | ||
16 | #ifdef __KERNEL__ | 16 | #ifdef __KERNEL__ |
17 | 17 | ||
18 | /* interrupt controller registers */ | 18 | /* |
19 | #define GxICR(X) __SYSREG(0xd4000000 + (X) * 4, u16) /* group irq ctrl regs */ | 19 | * Interrupt controller registers |
20 | 20 | * - Registers 64-191 are at addresses offset from the main array | |
21 | #define IAGR __SYSREG(0xd4000100, u16) /* intr acceptance group reg */ | 21 | */ |
22 | #define IAGR_GN 0x00fc /* group number register | 22 | #define GxICR(X) \ |
23 | * (documentation _has_ to be wrong) | 23 | __SYSREG(0xd4000000 + (X) * 4 + \ |
24 | */ | 24 | (((X) >= 64) && ((X) < 192)) * 0xf00, u16) |
25 | 25 | ||
26 | #define EXTMD __SYSREG(0xd4000200, u16) /* external pin intr spec reg */ | 26 | #define GxICR_u8(X) \ |
27 | #define GET_XIRQ_TRIGGER(X) ((EXTMD >> ((X) * 2)) & 3) | 27 | __SYSREG(0xd4000000 + (X) * 4 + \ |
28 | (((X) >= 64) && ((X) < 192)) * 0xf00, u8) | ||
28 | 29 | ||
29 | #define SET_XIRQ_TRIGGER(X,Y) \ | 30 | #include <proc/intctl-regs.h> |
30 | do { \ | ||
31 | u16 x = EXTMD; \ | ||
32 | x &= ~(3 << ((X) * 2)); \ | ||
33 | x |= ((Y) & 3) << ((X) * 2); \ | ||
34 | EXTMD = x; \ | ||
35 | } while (0) | ||
36 | 31 | ||
37 | #define XIRQ_TRIGGER_LOWLEVEL 0 | 32 | #define XIRQ_TRIGGER_LOWLEVEL 0 |
38 | #define XIRQ_TRIGGER_HILEVEL 1 | 33 | #define XIRQ_TRIGGER_HILEVEL 1 |
@@ -59,10 +54,18 @@ do { \ | |||
59 | #define GxICR_LEVEL_5 0x5000 /* - level 5 */ | 54 | #define GxICR_LEVEL_5 0x5000 /* - level 5 */ |
60 | #define GxICR_LEVEL_6 0x6000 /* - level 6 */ | 55 | #define GxICR_LEVEL_6 0x6000 /* - level 6 */ |
61 | #define GxICR_LEVEL_SHIFT 12 | 56 | #define GxICR_LEVEL_SHIFT 12 |
57 | #define GxICR_NMI 0x8000 /* nmi request flag */ | ||
58 | |||
59 | #define NUM2GxICR_LEVEL(num) ((num) << GxICR_LEVEL_SHIFT) | ||
62 | 60 | ||
63 | #ifndef __ASSEMBLY__ | 61 | #ifndef __ASSEMBLY__ |
64 | extern void set_intr_level(int irq, u16 level); | 62 | extern void set_intr_level(int irq, u16 level); |
65 | extern void set_intr_postackable(int irq); | 63 | extern void mn10300_intc_set_level(unsigned int irq, unsigned int level); |
64 | extern void mn10300_intc_clear(unsigned int irq); | ||
65 | extern void mn10300_intc_set(unsigned int irq); | ||
66 | extern void mn10300_intc_enable(unsigned int irq); | ||
67 | extern void mn10300_intc_disable(unsigned int irq); | ||
68 | extern void mn10300_set_lateack_irq_type(int irq); | ||
66 | #endif | 69 | #endif |
67 | 70 | ||
68 | /* external interrupts */ | 71 | /* external interrupts */ |
diff --git a/arch/mn10300/include/asm/irq.h b/arch/mn10300/include/asm/irq.h index 25c045d16d1c..b7b8e175b167 100644 --- a/arch/mn10300/include/asm/irq.h +++ b/arch/mn10300/include/asm/irq.h | |||
@@ -22,7 +22,11 @@ | |||
22 | #define NO_IRQ INT_MAX | 22 | #define NO_IRQ INT_MAX |
23 | 23 | ||
24 | /* hardware irq numbers */ | 24 | /* hardware irq numbers */ |
25 | #ifdef CONFIG_SMP | ||
26 | #define NR_IRQS GxICR_NUM_EXT_IRQS | ||
27 | #else | ||
25 | #define NR_IRQS GxICR_NUM_IRQS | 28 | #define NR_IRQS GxICR_NUM_IRQS |
29 | #endif | ||
26 | 30 | ||
27 | /* external hardware irq numbers */ | 31 | /* external hardware irq numbers */ |
28 | #define NR_XIRQS GxICR_NUM_XIRQS | 32 | #define NR_XIRQS GxICR_NUM_XIRQS |
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index b3ab2071354d..7a7ae12c7119 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h | |||
@@ -13,6 +13,9 @@ | |||
13 | #define _ASM_IRQFLAGS_H | 13 | #define _ASM_IRQFLAGS_H |
14 | 14 | ||
15 | #include <asm/cpu-regs.h> | 15 | #include <asm/cpu-regs.h> |
16 | #ifndef __ASSEMBLY__ | ||
17 | #include <linux/smp.h> | ||
18 | #endif | ||
16 | 19 | ||
17 | /* | 20 | /* |
18 | * interrupt control | 21 | * interrupt control |
@@ -60,11 +63,12 @@ static inline unsigned long arch_local_irq_save(void) | |||
60 | /* | 63 | /* |
61 | * we make sure arch_irq_enable() doesn't cause priority inversion | 64 | * we make sure arch_irq_enable() doesn't cause priority inversion |
62 | */ | 65 | */ |
63 | extern unsigned long __mn10300_irq_enabled_epsw; | 66 | extern unsigned long __mn10300_irq_enabled_epsw[]; |
64 | 67 | ||
65 | static inline void arch_local_irq_enable(void) | 68 | static inline void arch_local_irq_enable(void) |
66 | { | 69 | { |
67 | unsigned long tmp; | 70 | unsigned long tmp; |
71 | int cpu = raw_smp_processor_id(); | ||
68 | 72 | ||
69 | asm volatile( | 73 | asm volatile( |
70 | " mov epsw,%0 \n" | 74 | " mov epsw,%0 \n" |
@@ -72,8 +76,8 @@ static inline void arch_local_irq_enable(void) | |||
72 | " or %2,%0 \n" | 76 | " or %2,%0 \n" |
73 | " mov %0,epsw \n" | 77 | " mov %0,epsw \n" |
74 | : "=&d"(tmp) | 78 | : "=&d"(tmp) |
75 | : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw) | 79 | : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu]) |
76 | : "memory"); | 80 | : "memory", "cc"); |
77 | } | 81 | } |
78 | 82 | ||
79 | static inline void arch_local_irq_restore(unsigned long flags) | 83 | static inline void arch_local_irq_restore(unsigned long flags) |
@@ -105,6 +109,9 @@ static inline bool arch_irqs_disabled(void) | |||
105 | */ | 109 | */ |
106 | static inline void arch_safe_halt(void) | 110 | static inline void arch_safe_halt(void) |
107 | { | 111 | { |
112 | #ifdef CONFIG_SMP | ||
113 | arch_local_irq_enable(); | ||
114 | #else | ||
108 | asm volatile( | 115 | asm volatile( |
109 | " or %0,epsw \n" | 116 | " or %0,epsw \n" |
110 | " nop \n" | 117 | " nop \n" |
@@ -113,8 +120,21 @@ static inline void arch_safe_halt(void) | |||
113 | : | 120 | : |
114 | : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP) | 121 | : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP) |
115 | : "cc"); | 122 | : "cc"); |
123 | #endif | ||
116 | } | 124 | } |
117 | 125 | ||
126 | #define __sleep_cpu() \ | ||
127 | do { \ | ||
128 | asm volatile( \ | ||
129 | " bset %1,(%0)\n" \ | ||
130 | "1: btst %1,(%0)\n" \ | ||
131 | " bne 1b\n" \ | ||
132 | : \ | ||
133 | : "i"(&CPUM), "i"(CPUM_SLEEP) \ | ||
134 | : "cc" \ | ||
135 | ); \ | ||
136 | } while (0) | ||
137 | |||
118 | static inline void arch_local_cli(void) | 138 | static inline void arch_local_cli(void) |
119 | { | 139 | { |
120 | asm volatile( | 140 | asm volatile( |
diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h index 05dda641af80..cd568bf5407e 100644 --- a/arch/mn10300/include/asm/pgtable.h +++ b/arch/mn10300/include/asm/pgtable.h | |||
@@ -90,9 +90,15 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
90 | * The vmalloc() routines also leaves a hole of 4kB between each vmalloced | 90 | * The vmalloc() routines also leaves a hole of 4kB between each vmalloced |
91 | * area to catch addressing errors. | 91 | * area to catch addressing errors. |
92 | */ | 92 | */ |
93 | #ifndef __ASSEMBLY__ | ||
94 | #define VMALLOC_OFFSET (8UL * 1024 * 1024) | ||
95 | #define VMALLOC_START (0x70000000UL) | ||
96 | #define VMALLOC_END (0x7C000000UL) | ||
97 | #else | ||
93 | #define VMALLOC_OFFSET (8 * 1024 * 1024) | 98 | #define VMALLOC_OFFSET (8 * 1024 * 1024) |
94 | #define VMALLOC_START (0x70000000) | 99 | #define VMALLOC_START (0x70000000) |
95 | #define VMALLOC_END (0x7C000000) | 100 | #define VMALLOC_END (0x7C000000) |
101 | #endif | ||
96 | 102 | ||
97 | #ifndef __ASSEMBLY__ | 103 | #ifndef __ASSEMBLY__ |
98 | extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; | 104 | extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; |
@@ -329,11 +335,7 @@ static inline int pte_exec_kernel(pte_t pte) | |||
329 | return 1; | 335 | return 1; |
330 | } | 336 | } |
331 | 337 | ||
332 | /* | 338 | #define PTE_FILE_MAX_BITS 30 |
333 | * Bits 0 and 1 are taken, split up the 29 bits of offset | ||
334 | * into this range: | ||
335 | */ | ||
336 | #define PTE_FILE_MAX_BITS 29 | ||
337 | 339 | ||
338 | #define pte_to_pgoff(pte) (pte_val(pte) >> 2) | 340 | #define pte_to_pgoff(pte) (pte_val(pte) >> 2) |
339 | #define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) | 341 | #define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) |
@@ -379,8 +381,13 @@ static inline void ptep_mkdirty(pte_t *ptep) | |||
379 | * Macro to mark a page protection value as "uncacheable". On processors which | 381 | * Macro to mark a page protection value as "uncacheable". On processors which |
380 | * do not support it, this is a no-op. | 382 | * do not support it, this is a no-op. |
381 | */ | 383 | */ |
382 | #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE) | 384 | #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHE) |
383 | 385 | ||
386 | /* | ||
387 | * Macro to mark a page protection value as "Write-Through". | ||
388 | * On processors which do not support it, this is a no-op. | ||
389 | */ | ||
390 | #define pgprot_through(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE_WT) | ||
384 | 391 | ||
385 | /* | 392 | /* |
386 | * Conversion functions: convert a page and protection to a page entry, | 393 | * Conversion functions: convert a page and protection to a page entry, |
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h index 0032fc76c8ba..75c422abcd6b 100644 --- a/arch/mn10300/include/asm/processor.h +++ b/arch/mn10300/include/asm/processor.h | |||
@@ -33,6 +33,8 @@ struct mm_struct; | |||
33 | __pc; \ | 33 | __pc; \ |
34 | }) | 34 | }) |
35 | 35 | ||
36 | extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size); | ||
37 | |||
36 | extern void show_registers(struct pt_regs *regs); | 38 | extern void show_registers(struct pt_regs *regs); |
37 | 39 | ||
38 | /* | 40 | /* |
@@ -43,17 +45,22 @@ extern void show_registers(struct pt_regs *regs); | |||
43 | 45 | ||
44 | struct mn10300_cpuinfo { | 46 | struct mn10300_cpuinfo { |
45 | int type; | 47 | int type; |
46 | unsigned long loops_per_sec; | 48 | unsigned long loops_per_jiffy; |
47 | char hard_math; | 49 | char hard_math; |
48 | unsigned long *pgd_quick; | ||
49 | unsigned long *pte_quick; | ||
50 | unsigned long pgtable_cache_sz; | ||
51 | }; | 50 | }; |
52 | 51 | ||
53 | extern struct mn10300_cpuinfo boot_cpu_data; | 52 | extern struct mn10300_cpuinfo boot_cpu_data; |
54 | 53 | ||
54 | #ifdef CONFIG_SMP | ||
55 | #if CONFIG_NR_CPUS < 2 || CONFIG_NR_CPUS > 8 | ||
56 | # error Sorry, NR_CPUS should be 2 to 8 | ||
57 | #endif | ||
58 | extern struct mn10300_cpuinfo cpu_data[]; | ||
59 | #define current_cpu_data cpu_data[smp_processor_id()] | ||
60 | #else /* CONFIG_SMP */ | ||
55 | #define cpu_data &boot_cpu_data | 61 | #define cpu_data &boot_cpu_data |
56 | #define current_cpu_data boot_cpu_data | 62 | #define current_cpu_data boot_cpu_data |
63 | #endif /* CONFIG_SMP */ | ||
57 | 64 | ||
58 | extern void identify_cpu(struct mn10300_cpuinfo *); | 65 | extern void identify_cpu(struct mn10300_cpuinfo *); |
59 | extern void print_cpu_info(struct mn10300_cpuinfo *); | 66 | extern void print_cpu_info(struct mn10300_cpuinfo *); |
@@ -92,21 +99,21 @@ struct thread_struct { | |||
92 | unsigned long a3; /* kernel FP */ | 99 | unsigned long a3; /* kernel FP */ |
93 | unsigned long wchan; | 100 | unsigned long wchan; |
94 | unsigned long usp; | 101 | unsigned long usp; |
95 | struct pt_regs *__frame; | 102 | struct pt_regs *frame; |
96 | unsigned long fpu_flags; | 103 | unsigned long fpu_flags; |
97 | #define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */ | 104 | #define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */ |
98 | #define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */ | 105 | #define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */ |
99 | struct fpu_state_struct fpu_state; | 106 | struct fpu_state_struct fpu_state; |
100 | }; | 107 | }; |
101 | 108 | ||
102 | #define INIT_THREAD \ | 109 | #define INIT_THREAD \ |
103 | { \ | 110 | { \ |
104 | .uregs = init_uregs, \ | 111 | .uregs = init_uregs, \ |
105 | .pc = 0, \ | 112 | .pc = 0, \ |
106 | .sp = 0, \ | 113 | .sp = 0, \ |
107 | .a3 = 0, \ | 114 | .a3 = 0, \ |
108 | .wchan = 0, \ | 115 | .wchan = 0, \ |
109 | .__frame = NULL, \ | 116 | .frame = NULL, \ |
110 | } | 117 | } |
111 | 118 | ||
112 | #define INIT_MMAP \ | 119 | #define INIT_MMAP \ |
@@ -118,6 +125,19 @@ struct thread_struct { | |||
118 | * - need to discard the frame stacked by the kernel thread invoking the execve | 125 | * - need to discard the frame stacked by the kernel thread invoking the execve |
119 | * syscall (see RESTORE_ALL macro) | 126 | * syscall (see RESTORE_ALL macro) |
120 | */ | 127 | */ |
128 | #if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) /* FIXME */ | ||
129 | #define start_thread(regs, new_pc, new_sp) do { \ | ||
130 | int cpu; \ | ||
131 | preempt_disable(); \ | ||
132 | cpu = CPUID; \ | ||
133 | set_fs(USER_DS); \ | ||
134 | ___frame[cpu] = current->thread.uregs; \ | ||
135 | ___frame[cpu]->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;\ | ||
136 | ___frame[cpu]->pc = new_pc; \ | ||
137 | ___frame[cpu]->sp = new_sp; \ | ||
138 | preempt_enable(); \ | ||
139 | } while (0) | ||
140 | #else /* CONFIG_SMP && CONFIG_PREEMPT */ | ||
121 | #define start_thread(regs, new_pc, new_sp) do { \ | 141 | #define start_thread(regs, new_pc, new_sp) do { \ |
122 | set_fs(USER_DS); \ | 142 | set_fs(USER_DS); \ |
123 | __frame = current->thread.uregs; \ | 143 | __frame = current->thread.uregs; \ |
@@ -125,6 +145,7 @@ struct thread_struct { | |||
125 | __frame->pc = new_pc; \ | 145 | __frame->pc = new_pc; \ |
126 | __frame->sp = new_sp; \ | 146 | __frame->sp = new_sp; \ |
127 | } while (0) | 147 | } while (0) |
148 | #endif /* CONFIG_SMP && CONFIG_PREEMPT */ | ||
128 | 149 | ||
129 | /* Free all resources held by a thread. */ | 150 | /* Free all resources held by a thread. */ |
130 | extern void release_thread(struct task_struct *); | 151 | extern void release_thread(struct task_struct *); |
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h index 7c2e911052b6..c2b77bd3064a 100644 --- a/arch/mn10300/include/asm/ptrace.h +++ b/arch/mn10300/include/asm/ptrace.h | |||
@@ -40,7 +40,6 @@ | |||
40 | #define PT_PC 26 | 40 | #define PT_PC 26 |
41 | #define NR_PTREGS 27 | 41 | #define NR_PTREGS 27 |
42 | 42 | ||
43 | #ifndef __ASSEMBLY__ | ||
44 | /* | 43 | /* |
45 | * This defines the way registers are stored in the event of an exception | 44 | * This defines the way registers are stored in the event of an exception |
46 | * - the strange order is due to the MOVM instruction | 45 | * - the strange order is due to the MOVM instruction |
@@ -75,7 +74,6 @@ struct pt_regs { | |||
75 | unsigned long epsw; | 74 | unsigned long epsw; |
76 | unsigned long pc; | 75 | unsigned long pc; |
77 | }; | 76 | }; |
78 | #endif | ||
79 | 77 | ||
80 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ | 78 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ |
81 | #define PTRACE_GETREGS 12 | 79 | #define PTRACE_GETREGS 12 |
@@ -86,12 +84,13 @@ struct pt_regs { | |||
86 | /* options set using PTRACE_SETOPTIONS */ | 84 | /* options set using PTRACE_SETOPTIONS */ |
87 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 85 | #define PTRACE_O_TRACESYSGOOD 0x00000001 |
88 | 86 | ||
89 | #if defined(__KERNEL__) | 87 | #ifdef __KERNEL__ |
90 | 88 | ||
89 | #ifdef CONFIG_SMP | ||
90 | extern struct pt_regs *___frame[]; /* current frame pointer */ | ||
91 | #else | ||
91 | extern struct pt_regs *__frame; /* current frame pointer */ | 92 | extern struct pt_regs *__frame; /* current frame pointer */ |
92 | 93 | #endif | |
93 | #if !defined(__ASSEMBLY__) | ||
94 | struct task_struct; | ||
95 | 94 | ||
96 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) | 95 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) |
97 | #define instruction_pointer(regs) ((regs)->pc) | 96 | #define instruction_pointer(regs) ((regs)->pc) |
@@ -100,9 +99,7 @@ extern void show_regs(struct pt_regs *); | |||
100 | 99 | ||
101 | #define arch_has_single_step() (1) | 100 | #define arch_has_single_step() (1) |
102 | 101 | ||
103 | #endif /* !__ASSEMBLY */ | ||
104 | |||
105 | #define profile_pc(regs) ((regs)->pc) | 102 | #define profile_pc(regs) ((regs)->pc) |
106 | 103 | ||
107 | #endif /* __KERNEL__ */ | 104 | #endif /* __KERNEL__ */ |
108 | #endif /* _ASM_PTRACE_H */ | 105 | #endif /* _ASM_PTRACE_H */ |
diff --git a/arch/mn10300/include/asm/reset-regs.h b/arch/mn10300/include/asm/reset-regs.h index 174523d50132..10c7502a113f 100644 --- a/arch/mn10300/include/asm/reset-regs.h +++ b/arch/mn10300/include/asm/reset-regs.h | |||
@@ -50,7 +50,7 @@ static inline void mn10300_proc_hard_reset(void) | |||
50 | RSTCTR |= RSTCTR_CHIPRST; | 50 | RSTCTR |= RSTCTR_CHIPRST; |
51 | } | 51 | } |
52 | 52 | ||
53 | extern unsigned int watchdog_alert_counter; | 53 | extern unsigned int watchdog_alert_counter[]; |
54 | 54 | ||
55 | extern void watchdog_go(void); | 55 | extern void watchdog_go(void); |
56 | extern asmlinkage void watchdog_handler(void); | 56 | extern asmlinkage void watchdog_handler(void); |
diff --git a/arch/mn10300/include/asm/rtc.h b/arch/mn10300/include/asm/rtc.h index c295194cc703..6c14bb1d0d9b 100644 --- a/arch/mn10300/include/asm/rtc.h +++ b/arch/mn10300/include/asm/rtc.h | |||
@@ -15,25 +15,14 @@ | |||
15 | 15 | ||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | 17 | ||
18 | extern void check_rtc_time(void); | ||
19 | extern void __init calibrate_clock(void); | 18 | extern void __init calibrate_clock(void); |
20 | extern unsigned long __init get_initial_rtc_time(void); | ||
21 | 19 | ||
22 | #else /* !CONFIG_MN10300_RTC */ | 20 | #else /* !CONFIG_MN10300_RTC */ |
23 | 21 | ||
24 | static inline void check_rtc_time(void) | ||
25 | { | ||
26 | } | ||
27 | |||
28 | static inline void calibrate_clock(void) | 22 | static inline void calibrate_clock(void) |
29 | { | 23 | { |
30 | } | 24 | } |
31 | 25 | ||
32 | static inline unsigned long get_initial_rtc_time(void) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | #endif /* !CONFIG_MN10300_RTC */ | 26 | #endif /* !CONFIG_MN10300_RTC */ |
38 | 27 | ||
39 | #include <asm-generic/rtc.h> | 28 | #include <asm-generic/rtc.h> |
diff --git a/arch/mn10300/include/asm/rwlock.h b/arch/mn10300/include/asm/rwlock.h new file mode 100644 index 000000000000..6d594d4a0e10 --- /dev/null +++ b/arch/mn10300/include/asm/rwlock.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Helpers used by both rw spinlocks and rw semaphores. | ||
3 | * | ||
4 | * Based in part on code from semaphore.h and | ||
5 | * spinlock.h Copyright 1996 Linus Torvalds. | ||
6 | * | ||
7 | * Copyright 1999 Red Hat, Inc. | ||
8 | * | ||
9 | * Written by Benjamin LaHaise. | ||
10 | * | ||
11 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
12 | * Modifications: | ||
13 | * 13-Nov-2006 MEI Temporarily delete lock functions for SMP support. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the Free | ||
17 | * Software Foundation; either version 2 of the License, or (at your option) | ||
18 | * any later version. | ||
19 | */ | ||
20 | #ifndef _ASM_RWLOCK_H | ||
21 | #define _ASM_RWLOCK_H | ||
22 | |||
23 | #define RW_LOCK_BIAS 0x01000000 | ||
24 | |||
25 | #ifndef CONFIG_SMP | ||
26 | |||
27 | typedef struct { unsigned long a[100]; } __dummy_lock_t; | ||
28 | #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) | ||
29 | |||
30 | #define RW_LOCK_BIAS_STR "0x01000000" | ||
31 | |||
32 | #define __build_read_lock_ptr(rw, helper) \ | ||
33 | do { \ | ||
34 | asm volatile( \ | ||
35 | " mov (%0),d3 \n" \ | ||
36 | " sub 1,d3 \n" \ | ||
37 | " mov d3,(%0) \n" \ | ||
38 | " blt 1f \n" \ | ||
39 | " bra 2f \n" \ | ||
40 | "1: jmp 3f \n" \ | ||
41 | "2: \n" \ | ||
42 | " .section .text.lock,\"ax\" \n" \ | ||
43 | "3: call "helper"[],0 \n" \ | ||
44 | " jmp 2b \n" \ | ||
45 | " .previous" \ | ||
46 | : \ | ||
47 | : "d" (rw) \ | ||
48 | : "memory", "d3", "cc"); \ | ||
49 | } while (0) | ||
50 | |||
51 | #define __build_read_lock_const(rw, helper) \ | ||
52 | do { \ | ||
53 | asm volatile( \ | ||
54 | " mov (%0),d3 \n" \ | ||
55 | " sub 1,d3 \n" \ | ||
56 | " mov d3,(%0) \n" \ | ||
57 | " blt 1f \n" \ | ||
58 | " bra 2f \n" \ | ||
59 | "1: jmp 3f \n" \ | ||
60 | "2: \n" \ | ||
61 | " .section .text.lock,\"ax\" \n" \ | ||
62 | "3: call "helper"[],0 \n" \ | ||
63 | " jmp 2b \n" \ | ||
64 | " .previous" \ | ||
65 | : \ | ||
66 | : "d" (rw) \ | ||
67 | : "memory", "d3", "cc"); \ | ||
68 | } while (0) | ||
69 | |||
70 | #define __build_read_lock(rw, helper) \ | ||
71 | do { \ | ||
72 | if (__builtin_constant_p(rw)) \ | ||
73 | __build_read_lock_const(rw, helper); \ | ||
74 | else \ | ||
75 | __build_read_lock_ptr(rw, helper); \ | ||
76 | } while (0) | ||
77 | |||
78 | #define __build_write_lock_ptr(rw, helper) \ | ||
79 | do { \ | ||
80 | asm volatile( \ | ||
81 | " mov (%0),d3 \n" \ | ||
82 | " sub 1,d3 \n" \ | ||
83 | " mov d3,(%0) \n" \ | ||
84 | " blt 1f \n" \ | ||
85 | " bra 2f \n" \ | ||
86 | "1: jmp 3f \n" \ | ||
87 | "2: \n" \ | ||
88 | " .section .text.lock,\"ax\" \n" \ | ||
89 | "3: call "helper"[],0 \n" \ | ||
90 | " jmp 2b \n" \ | ||
91 | " .previous" \ | ||
92 | : \ | ||
93 | : "d" (rw) \ | ||
94 | : "memory", "d3", "cc"); \ | ||
95 | } while (0) | ||
96 | |||
97 | #define __build_write_lock_const(rw, helper) \ | ||
98 | do { \ | ||
99 | asm volatile( \ | ||
100 | " mov (%0),d3 \n" \ | ||
101 | " sub 1,d3 \n" \ | ||
102 | " mov d3,(%0) \n" \ | ||
103 | " blt 1f \n" \ | ||
104 | " bra 2f \n" \ | ||
105 | "1: jmp 3f \n" \ | ||
106 | "2: \n" \ | ||
107 | " .section .text.lock,\"ax\" \n" \ | ||
108 | "3: call "helper"[],0 \n" \ | ||
109 | " jmp 2b \n" \ | ||
110 | " .previous" \ | ||
111 | : \ | ||
112 | : "d" (rw) \ | ||
113 | : "memory", "d3", "cc"); \ | ||
114 | } while (0) | ||
115 | |||
116 | #define __build_write_lock(rw, helper) \ | ||
117 | do { \ | ||
118 | if (__builtin_constant_p(rw)) \ | ||
119 | __build_write_lock_const(rw, helper); \ | ||
120 | else \ | ||
121 | __build_write_lock_ptr(rw, helper); \ | ||
122 | } while (0) | ||
123 | |||
124 | #endif /* CONFIG_SMP */ | ||
125 | #endif /* _ASM_RWLOCK_H */ | ||
diff --git a/arch/mn10300/include/asm/serial-regs.h b/arch/mn10300/include/asm/serial-regs.h index 6498469e93ac..8320cda32f5a 100644 --- a/arch/mn10300/include/asm/serial-regs.h +++ b/arch/mn10300/include/asm/serial-regs.h | |||
@@ -20,18 +20,25 @@ | |||
20 | /* serial port 0 */ | 20 | /* serial port 0 */ |
21 | #define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */ | 21 | #define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */ |
22 | #define SC01CTR_CK 0x0007 /* clock source select */ | 22 | #define SC01CTR_CK 0x0007 /* clock source select */ |
23 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ | ||
24 | #define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */ | ||
25 | #define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ | 23 | #define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ |
26 | #define SC01CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 24 | #define SC01CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ |
25 | #define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | ||
26 | #define SC01CTR_CK_EXTERN 0x0007 /* - external closk */ | ||
27 | #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) | ||
28 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ | ||
27 | #define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */ | 29 | #define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */ |
28 | #define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */ | 30 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */ |
29 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 0 only) */ | ||
30 | #define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 2 underflow (serial port 1 only) */ | ||
31 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ | 31 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ |
32 | #define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */ | ||
33 | #define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */ | ||
34 | #define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 1 only) */ | ||
32 | #define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */ | 35 | #define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */ |
33 | #define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | 36 | #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ |
34 | #define SC01CTR_CK_EXTERN 0x0007 /* - external closk */ | 37 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ |
38 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */ | ||
39 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ | ||
40 | #define SC1CTR_CK_TM12UFLOW_8 0x0000 /* - 1/8 timer 12 underflow (serial port 1 only) */ | ||
41 | #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
35 | #define SC01CTR_STB 0x0008 /* stop bit select */ | 42 | #define SC01CTR_STB 0x0008 /* stop bit select */ |
36 | #define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 43 | #define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */ |
37 | #define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 44 | #define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */ |
@@ -100,11 +107,23 @@ | |||
100 | 107 | ||
101 | /* serial port 2 */ | 108 | /* serial port 2 */ |
102 | #define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */ | 109 | #define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */ |
110 | #ifdef CONFIG_AM33_2 | ||
103 | #define SC2CTR_CK 0x0003 /* clock source select */ | 111 | #define SC2CTR_CK 0x0003 /* clock source select */ |
104 | #define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */ | 112 | #define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */ |
105 | #define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */ | 113 | #define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */ |
106 | #define SC2CTR_CK_EXTERN 0x0002 /* - external closk */ | 114 | #define SC2CTR_CK_EXTERN 0x0002 /* - external closk */ |
107 | #define SC2CTR_CK_TM3UFLOW 0x0003 /* - timer 3 underflow */ | 115 | #define SC2CTR_CK_TM3UFLOW 0x0003 /* - timer 3 underflow */ |
116 | #else /* CONFIG_AM33_2 */ | ||
117 | #define SC2CTR_CK 0x0007 /* clock source select */ | ||
118 | #define SC2CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow */ | ||
119 | #define SC2CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ | ||
120 | #define SC2CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | ||
121 | #define SC2CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow */ | ||
122 | #define SC2CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow */ | ||
123 | #define SC2CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow */ | ||
124 | #define SC2CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | ||
125 | #define SC2CTR_CK_EXTERN 0x0007 /* - external closk */ | ||
126 | #endif /* CONFIG_AM33_2 */ | ||
108 | #define SC2CTR_STB 0x0008 /* stop bit select */ | 127 | #define SC2CTR_STB 0x0008 /* stop bit select */ |
109 | #define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 128 | #define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */ |
110 | #define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 129 | #define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */ |
@@ -134,9 +153,14 @@ | |||
134 | #define SC2ICR_RES 0x04 /* receive error select */ | 153 | #define SC2ICR_RES 0x04 /* receive error select */ |
135 | #define SC2ICR_RI 0x01 /* receive interrupt cause */ | 154 | #define SC2ICR_RI 0x01 /* receive interrupt cause */ |
136 | 155 | ||
137 | #define SC2TXB __SYSREG(0xd4002018, u8) /* transmit buffer reg */ | 156 | #define SC2TXB __SYSREG(0xd4002028, u8) /* transmit buffer reg */ |
138 | #define SC2RXB __SYSREG(0xd4002019, u8) /* receive buffer reg */ | 157 | #define SC2RXB __SYSREG(0xd4002029, u8) /* receive buffer reg */ |
139 | #define SC2STR __SYSREG(0xd400201c, u8) /* status reg */ | 158 | |
159 | #ifdef CONFIG_AM33_2 | ||
160 | #define SC2STR __SYSREG(0xd400202c, u8) /* status reg */ | ||
161 | #else /* CONFIG_AM33_2 */ | ||
162 | #define SC2STR __SYSREG(0xd400202c, u16) /* status reg */ | ||
163 | #endif /* CONFIG_AM33_2 */ | ||
140 | #define SC2STR_OEF 0x0001 /* overrun error found */ | 164 | #define SC2STR_OEF 0x0001 /* overrun error found */ |
141 | #define SC2STR_PEF 0x0002 /* parity error found */ | 165 | #define SC2STR_PEF 0x0002 /* parity error found */ |
142 | #define SC2STR_FEF 0x0004 /* framing error found */ | 166 | #define SC2STR_FEF 0x0004 /* framing error found */ |
@@ -146,10 +170,17 @@ | |||
146 | #define SC2STR_RXF 0x0040 /* receive status */ | 170 | #define SC2STR_RXF 0x0040 /* receive status */ |
147 | #define SC2STR_TXF 0x0080 /* transmit status */ | 171 | #define SC2STR_TXF 0x0080 /* transmit status */ |
148 | 172 | ||
173 | #ifdef CONFIG_AM33_2 | ||
149 | #define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */ | 174 | #define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */ |
175 | #endif | ||
150 | 176 | ||
177 | #ifdef CONFIG_AM33_2 | ||
151 | #define SC2RXIRQ 24 /* serial 2 Receive IRQ */ | 178 | #define SC2RXIRQ 24 /* serial 2 Receive IRQ */ |
152 | #define SC2TXIRQ 25 /* serial 2 Transmit IRQ */ | 179 | #define SC2TXIRQ 25 /* serial 2 Transmit IRQ */ |
180 | #else /* CONFIG_AM33_2 */ | ||
181 | #define SC2RXIRQ 68 /* serial 2 Receive IRQ */ | ||
182 | #define SC2TXIRQ 69 /* serial 2 Transmit IRQ */ | ||
183 | #endif /* CONFIG_AM33_2 */ | ||
153 | 184 | ||
154 | #define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */ | 185 | #define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */ |
155 | #define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */ | 186 | #define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */ |
diff --git a/arch/mn10300/include/asm/serial.h b/arch/mn10300/include/asm/serial.h index a29445cddd6f..23a799293599 100644 --- a/arch/mn10300/include/asm/serial.h +++ b/arch/mn10300/include/asm/serial.h | |||
@@ -9,10 +9,8 @@ | |||
9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | #ifndef _ASM_SERIAL_H |
13 | * The ASB2305 has an 18.432 MHz clock the UART | 13 | #define _ASM_SERIAL_H |
14 | */ | ||
15 | #define BASE_BAUD (18432000 / 16) | ||
16 | 14 | ||
17 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ | 15 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ |
18 | #ifdef CONFIG_SERIAL_DETECT_IRQ | 16 | #ifdef CONFIG_SERIAL_DETECT_IRQ |
@@ -34,3 +32,5 @@ | |||
34 | #endif | 32 | #endif |
35 | 33 | ||
36 | #include <unit/serial.h> | 34 | #include <unit/serial.h> |
35 | |||
36 | #endif /* _ASM_SERIAL_H */ | ||
diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index 4eb8c61b7dab..b8585b4e8cdf 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h | |||
@@ -3,6 +3,16 @@ | |||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
7 | * Modifications: | ||
8 | * 13-Nov-2006 MEI Define IPI-IRQ number and add inline/macro function | ||
9 | * for SMP support. | ||
10 | * 22-Jan-2007 MEI Add the define related to SMP_BOOT_IRQ. | ||
11 | * 23-Feb-2007 MEI Add the define related to SMP icahce invalidate. | ||
12 | * 23-Jun-2008 MEI Delete INTC_IPI. | ||
13 | * 22-Jul-2008 MEI Add smp_nmi_call_function and related defines. | ||
14 | * 04-Aug-2008 MEI Delete USE_DOIRQ_CACHE_IPI. | ||
15 | * | ||
6 | * This program is free software; you can redistribute it and/or | 16 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public Licence | 17 | * modify it under the terms of the GNU General Public Licence |
8 | * as published by the Free Software Foundation; either version | 18 | * as published by the Free Software Foundation; either version |
@@ -11,8 +21,98 @@ | |||
11 | #ifndef _ASM_SMP_H | 21 | #ifndef _ASM_SMP_H |
12 | #define _ASM_SMP_H | 22 | #define _ASM_SMP_H |
13 | 23 | ||
24 | #ifndef __ASSEMBLY__ | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/cpumask.h> | ||
27 | #endif | ||
28 | |||
14 | #ifdef CONFIG_SMP | 29 | #ifdef CONFIG_SMP |
15 | #error SMP not yet supported for MN10300 | 30 | #include <proc/smp-regs.h> |
31 | |||
32 | #define RESCHEDULE_IPI 63 | ||
33 | #define CALL_FUNC_SINGLE_IPI 192 | ||
34 | #define LOCAL_TIMER_IPI 193 | ||
35 | #define FLUSH_CACHE_IPI 194 | ||
36 | #define CALL_FUNCTION_NMI_IPI 195 | ||
37 | #define GDB_NMI_IPI 196 | ||
38 | |||
39 | #define SMP_BOOT_IRQ 195 | ||
40 | |||
41 | #define RESCHEDULE_GxICR_LV GxICR_LEVEL_6 | ||
42 | #define CALL_FUNCTION_GxICR_LV GxICR_LEVEL_4 | ||
43 | #define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4 | ||
44 | #define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0 | ||
45 | #define SMP_BOOT_GxICR_LV GxICR_LEVEL_0 | ||
46 | |||
47 | #define TIME_OUT_COUNT_BOOT_IPI 100 | ||
48 | #define DELAY_TIME_BOOT_IPI 75000 | ||
49 | |||
50 | |||
51 | #ifndef __ASSEMBLY__ | ||
52 | |||
53 | /** | ||
54 | * raw_smp_processor_id - Determine the raw CPU ID of the CPU running it | ||
55 | * | ||
56 | * What we really want to do is to use the CPUID hardware CPU register to get | ||
57 | * this information, but accesses to that aren't cached, and run at system bus | ||
58 | * speed, not CPU speed. A copy of this value is, however, stored in the | ||
59 | * thread_info struct, and that can be cached. | ||
60 | * | ||
61 | * An alternate way of dealing with this could be to use the EPSW.S bits to | ||
62 | * cache this information for systems with up to four CPUs. | ||
63 | */ | ||
64 | #if 0 | ||
65 | #define raw_smp_processor_id() (CPUID) | ||
66 | #else | ||
67 | #define raw_smp_processor_id() (current_thread_info()->cpu) | ||
16 | #endif | 68 | #endif |
17 | 69 | ||
70 | static inline int cpu_logical_map(int cpu) | ||
71 | { | ||
72 | return cpu; | ||
73 | } | ||
74 | |||
75 | static inline int cpu_number_map(int cpu) | ||
76 | { | ||
77 | return cpu; | ||
78 | } | ||
79 | |||
80 | |||
81 | extern cpumask_t cpu_boot_map; | ||
82 | |||
83 | extern void smp_init_cpus(void); | ||
84 | extern void smp_cache_interrupt(void); | ||
85 | extern void send_IPI_allbutself(int irq); | ||
86 | extern int smp_nmi_call_function(smp_call_func_t func, void *info, int wait); | ||
87 | |||
88 | extern void arch_send_call_function_single_ipi(int cpu); | ||
89 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | ||
90 | |||
91 | #ifdef CONFIG_HOTPLUG_CPU | ||
92 | extern int __cpu_disable(void); | ||
93 | extern void __cpu_die(unsigned int cpu); | ||
94 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
95 | |||
96 | #ifdef CONFIG_PREEMPT /* FIXME */ | ||
97 | #define __frame \ | ||
98 | ({ \ | ||
99 | struct pt_regs *f; \ | ||
100 | preempt_disable(); \ | ||
101 | f = ___frame[CPUID]; \ | ||
102 | preempt_enable(); \ | ||
103 | f; \ | ||
104 | }) | ||
105 | #else | ||
106 | #define __frame ___frame[CPUID] | ||
18 | #endif | 107 | #endif |
108 | |||
109 | #endif /* __ASSEMBLY__ */ | ||
110 | #else /* CONFIG_SMP */ | ||
111 | #ifndef __ASSEMBLY__ | ||
112 | |||
113 | static inline void smp_init_cpus(void) {} | ||
114 | |||
115 | #endif /* __ASSEMBLY__ */ | ||
116 | #endif /* CONFIG_SMP */ | ||
117 | |||
118 | #endif /* _ASM_SMP_H */ | ||
diff --git a/arch/mn10300/include/asm/spinlock.h b/arch/mn10300/include/asm/spinlock.h index 4bf9c8b169e0..93429154e898 100644 --- a/arch/mn10300/include/asm/spinlock.h +++ b/arch/mn10300/include/asm/spinlock.h | |||
@@ -11,6 +11,183 @@ | |||
11 | #ifndef _ASM_SPINLOCK_H | 11 | #ifndef _ASM_SPINLOCK_H |
12 | #define _ASM_SPINLOCK_H | 12 | #define _ASM_SPINLOCK_H |
13 | 13 | ||
14 | #error SMP spinlocks not implemented for MN10300 | 14 | #include <asm/atomic.h> |
15 | #include <asm/rwlock.h> | ||
16 | #include <asm/page.h> | ||
15 | 17 | ||
18 | /* | ||
19 | * Simple spin lock operations. There are two variants, one clears IRQ's | ||
20 | * on the local processor, one does not. | ||
21 | * | ||
22 | * We make no fairness assumptions. They have a cost. | ||
23 | */ | ||
24 | |||
25 | #define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) != 0) | ||
26 | #define arch_spin_unlock_wait(x) do { barrier(); } while (arch_spin_is_locked(x)) | ||
27 | |||
28 | static inline void arch_spin_unlock(arch_spinlock_t *lock) | ||
29 | { | ||
30 | asm volatile( | ||
31 | " bclr 1,(0,%0) \n" | ||
32 | : | ||
33 | : "a"(&lock->slock) | ||
34 | : "memory", "cc"); | ||
35 | } | ||
36 | |||
37 | static inline int arch_spin_trylock(arch_spinlock_t *lock) | ||
38 | { | ||
39 | int ret; | ||
40 | |||
41 | asm volatile( | ||
42 | " mov 1,%0 \n" | ||
43 | " bset %0,(%1) \n" | ||
44 | " bne 1f \n" | ||
45 | " clr %0 \n" | ||
46 | "1: xor 1,%0 \n" | ||
47 | : "=d"(ret) | ||
48 | : "a"(&lock->slock) | ||
49 | : "memory", "cc"); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static inline void arch_spin_lock(arch_spinlock_t *lock) | ||
55 | { | ||
56 | asm volatile( | ||
57 | "1: bset 1,(0,%0) \n" | ||
58 | " bne 1b \n" | ||
59 | : | ||
60 | : "a"(&lock->slock) | ||
61 | : "memory", "cc"); | ||
62 | } | ||
63 | |||
64 | static inline void arch_spin_lock_flags(arch_spinlock_t *lock, | ||
65 | unsigned long flags) | ||
66 | { | ||
67 | int temp; | ||
68 | |||
69 | asm volatile( | ||
70 | "1: bset 1,(0,%2) \n" | ||
71 | " beq 3f \n" | ||
72 | " mov %1,epsw \n" | ||
73 | "2: mov (0,%2),%0 \n" | ||
74 | " or %0,%0 \n" | ||
75 | " bne 2b \n" | ||
76 | " mov %3,%0 \n" | ||
77 | " mov %0,epsw \n" | ||
78 | " nop \n" | ||
79 | " nop \n" | ||
80 | " bra 1b\n" | ||
81 | "3: \n" | ||
82 | : "=&d" (temp) | ||
83 | : "d" (flags), "a"(&lock->slock), "i"(EPSW_IE | MN10300_CLI_LEVEL) | ||
84 | : "memory", "cc"); | ||
85 | } | ||
86 | |||
87 | #ifdef __KERNEL__ | ||
88 | |||
89 | /* | ||
90 | * Read-write spinlocks, allowing multiple readers | ||
91 | * but only one writer. | ||
92 | * | ||
93 | * NOTE! it is quite common to have readers in interrupts | ||
94 | * but no interrupt writers. For those circumstances we | ||
95 | * can "mix" irq-safe locks - any writer needs to get a | ||
96 | * irq-safe write-lock, but readers can get non-irqsafe | ||
97 | * read-locks. | ||
98 | */ | ||
99 | |||
100 | /** | ||
101 | * read_can_lock - would read_trylock() succeed? | ||
102 | * @lock: the rwlock in question. | ||
103 | */ | ||
104 | #define arch_read_can_lock(x) ((int)(x)->lock > 0) | ||
105 | |||
106 | /** | ||
107 | * write_can_lock - would write_trylock() succeed? | ||
108 | * @lock: the rwlock in question. | ||
109 | */ | ||
110 | #define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS) | ||
111 | |||
112 | /* | ||
113 | * On mn10300, we implement read-write locks as a 32-bit counter | ||
114 | * with the high bit (sign) being the "contended" bit. | ||
115 | */ | ||
116 | static inline void arch_read_lock(arch_rwlock_t *rw) | ||
117 | { | ||
118 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
119 | __build_read_lock(rw, "__read_lock_failed"); | ||
120 | #else | ||
121 | { | ||
122 | atomic_t *count = (atomic_t *)rw; | ||
123 | while (atomic_dec_return(count) < 0) | ||
124 | atomic_inc(count); | ||
125 | } | ||
126 | #endif | ||
127 | } | ||
128 | |||
129 | static inline void arch_write_lock(arch_rwlock_t *rw) | ||
130 | { | ||
131 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
132 | __build_write_lock(rw, "__write_lock_failed"); | ||
133 | #else | ||
134 | { | ||
135 | atomic_t *count = (atomic_t *)rw; | ||
136 | while (!atomic_sub_and_test(RW_LOCK_BIAS, count)) | ||
137 | atomic_add(RW_LOCK_BIAS, count); | ||
138 | } | ||
139 | #endif | ||
140 | } | ||
141 | |||
142 | static inline void arch_read_unlock(arch_rwlock_t *rw) | ||
143 | { | ||
144 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
145 | __build_read_unlock(rw); | ||
146 | #else | ||
147 | { | ||
148 | atomic_t *count = (atomic_t *)rw; | ||
149 | atomic_inc(count); | ||
150 | } | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | static inline void arch_write_unlock(arch_rwlock_t *rw) | ||
155 | { | ||
156 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
157 | __build_write_unlock(rw); | ||
158 | #else | ||
159 | { | ||
160 | atomic_t *count = (atomic_t *)rw; | ||
161 | atomic_add(RW_LOCK_BIAS, count); | ||
162 | } | ||
163 | #endif | ||
164 | } | ||
165 | |||
166 | static inline int arch_read_trylock(arch_rwlock_t *lock) | ||
167 | { | ||
168 | atomic_t *count = (atomic_t *)lock; | ||
169 | atomic_dec(count); | ||
170 | if (atomic_read(count) >= 0) | ||
171 | return 1; | ||
172 | atomic_inc(count); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static inline int arch_write_trylock(arch_rwlock_t *lock) | ||
177 | { | ||
178 | atomic_t *count = (atomic_t *)lock; | ||
179 | if (atomic_sub_and_test(RW_LOCK_BIAS, count)) | ||
180 | return 1; | ||
181 | atomic_add(RW_LOCK_BIAS, count); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) | ||
186 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) | ||
187 | |||
188 | #define _raw_spin_relax(lock) cpu_relax() | ||
189 | #define _raw_read_relax(lock) cpu_relax() | ||
190 | #define _raw_write_relax(lock) cpu_relax() | ||
191 | |||
192 | #endif /* __KERNEL__ */ | ||
16 | #endif /* _ASM_SPINLOCK_H */ | 193 | #endif /* _ASM_SPINLOCK_H */ |
diff --git a/arch/mn10300/include/asm/spinlock_types.h b/arch/mn10300/include/asm/spinlock_types.h new file mode 100644 index 000000000000..653dc519b405 --- /dev/null +++ b/arch/mn10300/include/asm/spinlock_types.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef _ASM_SPINLOCK_TYPES_H | ||
2 | #define _ASM_SPINLOCK_TYPES_H | ||
3 | |||
4 | #ifndef __LINUX_SPINLOCK_TYPES_H | ||
5 | # error "please don't include this file directly" | ||
6 | #endif | ||
7 | |||
8 | typedef struct arch_spinlock { | ||
9 | unsigned int slock; | ||
10 | } arch_spinlock_t; | ||
11 | |||
12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } | ||
13 | |||
14 | typedef struct { | ||
15 | unsigned int lock; | ||
16 | } arch_rwlock_t; | ||
17 | |||
18 | #define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
19 | |||
20 | #endif /* _ASM_SPINLOCK_TYPES_H */ | ||
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h index 7de90bc4cf80..8ff3e5aaca41 100644 --- a/arch/mn10300/include/asm/system.h +++ b/arch/mn10300/include/asm/system.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define _ASM_SYSTEM_H | 12 | #define _ASM_SYSTEM_H |
13 | 13 | ||
14 | #include <asm/cpu-regs.h> | 14 | #include <asm/cpu-regs.h> |
15 | #include <asm/intctl-regs.h> | ||
15 | 16 | ||
16 | #ifdef __KERNEL__ | 17 | #ifdef __KERNEL__ |
17 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
@@ -57,8 +58,6 @@ do { \ | |||
57 | 58 | ||
58 | #define nop() asm volatile ("nop") | 59 | #define nop() asm volatile ("nop") |
59 | 60 | ||
60 | #endif /* !__ASSEMBLY__ */ | ||
61 | |||
62 | /* | 61 | /* |
63 | * Force strict CPU ordering. | 62 | * Force strict CPU ordering. |
64 | * And yes, this is required on UP too when we're talking | 63 | * And yes, this is required on UP too when we're talking |
@@ -85,17 +84,19 @@ do { \ | |||
85 | #define smp_mb() mb() | 84 | #define smp_mb() mb() |
86 | #define smp_rmb() rmb() | 85 | #define smp_rmb() rmb() |
87 | #define smp_wmb() wmb() | 86 | #define smp_wmb() wmb() |
88 | #else | 87 | #define set_mb(var, value) do { xchg(&var, value); } while (0) |
88 | #else /* CONFIG_SMP */ | ||
89 | #define smp_mb() barrier() | 89 | #define smp_mb() barrier() |
90 | #define smp_rmb() barrier() | 90 | #define smp_rmb() barrier() |
91 | #define smp_wmb() barrier() | 91 | #define smp_wmb() barrier() |
92 | #endif | ||
93 | |||
94 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 92 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
93 | #endif /* CONFIG_SMP */ | ||
94 | |||
95 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | 95 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) |
96 | 96 | ||
97 | #define read_barrier_depends() do {} while (0) | 97 | #define read_barrier_depends() do {} while (0) |
98 | #define smp_read_barrier_depends() do {} while (0) | 98 | #define smp_read_barrier_depends() do {} while (0) |
99 | 99 | ||
100 | #endif /* !__ASSEMBLY__ */ | ||
100 | #endif /* __KERNEL__ */ | 101 | #endif /* __KERNEL__ */ |
101 | #endif /* _ASM_SYSTEM_H */ | 102 | #endif /* _ASM_SYSTEM_H */ |
diff --git a/arch/mn10300/include/asm/timer-regs.h b/arch/mn10300/include/asm/timer-regs.h index 1d883b7f94ab..c634977caf66 100644 --- a/arch/mn10300/include/asm/timer-regs.h +++ b/arch/mn10300/include/asm/timer-regs.h | |||
@@ -17,21 +17,27 @@ | |||
17 | 17 | ||
18 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ |
19 | 19 | ||
20 | /* timer prescalar control */ | 20 | /* |
21 | * Timer prescalar control | ||
22 | */ | ||
21 | #define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */ | 23 | #define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */ |
22 | #define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */ | 24 | #define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */ |
23 | #define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */ | 25 | #define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */ |
24 | 26 | ||
25 | /* 8 bit timers */ | 27 | /* |
28 | * 8-bit timers | ||
29 | */ | ||
26 | #define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */ | 30 | #define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */ |
27 | #define TM0MD_SRC 0x07 /* timer source */ | 31 | #define TM0MD_SRC 0x07 /* timer source */ |
28 | #define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */ | 32 | #define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */ |
29 | #define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 33 | #define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ |
30 | #define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 34 | #define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ |
31 | #define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */ | ||
32 | #define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 35 | #define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
33 | #define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 36 | #define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
37 | #if defined(CONFIG_AM33_2) | ||
38 | #define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */ | ||
34 | #define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */ | 39 | #define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */ |
40 | #endif /* CONFIG_AM33_2 */ | ||
35 | #define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 41 | #define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
36 | #define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */ | 42 | #define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */ |
37 | 43 | ||
@@ -43,7 +49,9 @@ | |||
43 | #define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */ | 49 | #define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */ |
44 | #define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 50 | #define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
45 | #define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 51 | #define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
52 | #if defined(CONFIG_AM33_2) | ||
46 | #define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */ | 53 | #define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */ |
54 | #endif /* CONFIG_AM33_2 */ | ||
47 | #define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 55 | #define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
48 | #define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */ | 56 | #define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */ |
49 | 57 | ||
@@ -55,7 +63,9 @@ | |||
55 | #define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */ | 63 | #define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */ |
56 | #define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 64 | #define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
57 | #define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 65 | #define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
66 | #if defined(CONFIG_AM33_2) | ||
58 | #define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */ | 67 | #define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */ |
68 | #endif /* CONFIG_AM33_2 */ | ||
59 | #define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 69 | #define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
60 | #define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */ | 70 | #define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */ |
61 | 71 | ||
@@ -64,11 +74,13 @@ | |||
64 | #define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */ | 74 | #define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */ |
65 | #define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 75 | #define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ |
66 | #define TM3MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 76 | #define TM3MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ |
67 | #define TM3MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 2 */ | 77 | #define TM3MD_SRC_TM2CASCADE 0x03 /* - cascade with timer 2 */ |
68 | #define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 78 | #define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
69 | #define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 79 | #define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
70 | #define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 80 | #define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
81 | #if defined(CONFIG_AM33_2) | ||
71 | #define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */ | 82 | #define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */ |
83 | #endif /* CONFIG_AM33_2 */ | ||
72 | #define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 84 | #define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
73 | #define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */ | 85 | #define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */ |
74 | 86 | ||
@@ -96,7 +108,9 @@ | |||
96 | #define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */ | 108 | #define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */ |
97 | #define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */ | 109 | #define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */ |
98 | 110 | ||
99 | /* 16-bit timers 4,5 & 7-11 */ | 111 | /* |
112 | * 16-bit timers 4,5 & 7-15 | ||
113 | */ | ||
100 | #define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */ | 114 | #define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */ |
101 | #define TM4MD_SRC 0x07 /* timer source */ | 115 | #define TM4MD_SRC 0x07 /* timer source */ |
102 | #define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */ | 116 | #define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */ |
@@ -105,7 +119,9 @@ | |||
105 | #define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 119 | #define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
106 | #define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 120 | #define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
107 | #define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 121 | #define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
122 | #if defined(CONFIG_AM33_2) | ||
108 | #define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */ | 123 | #define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */ |
124 | #endif /* CONFIG_AM33_2 */ | ||
109 | #define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 125 | #define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
110 | #define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */ | 126 | #define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */ |
111 | 127 | ||
@@ -118,7 +134,11 @@ | |||
118 | #define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 134 | #define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
119 | #define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 135 | #define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
120 | #define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 136 | #define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
137 | #if defined(CONFIG_AM33_2) | ||
121 | #define TM5MD_SRC_TM5IO 0x07 /* - TM5IO pin input */ | 138 | #define TM5MD_SRC_TM5IO 0x07 /* - TM5IO pin input */ |
139 | #else /* !CONFIG_AM33_2 */ | ||
140 | #define TM5MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
141 | #endif /* CONFIG_AM33_2 */ | ||
122 | #define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 142 | #define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
123 | #define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */ | 143 | #define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */ |
124 | 144 | ||
@@ -130,7 +150,9 @@ | |||
130 | #define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 150 | #define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
131 | #define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 151 | #define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
132 | #define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 152 | #define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
153 | #if defined(CONFIG_AM33_2) | ||
133 | #define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */ | 154 | #define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */ |
155 | #endif /* CONFIG_AM33_2 */ | ||
134 | #define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 156 | #define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
135 | #define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */ | 157 | #define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */ |
136 | 158 | ||
@@ -143,7 +165,11 @@ | |||
143 | #define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 165 | #define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
144 | #define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 166 | #define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
145 | #define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 167 | #define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
168 | #if defined(CONFIG_AM33_2) | ||
146 | #define TM8MD_SRC_TM8IO 0x07 /* - TM8IO pin input */ | 169 | #define TM8MD_SRC_TM8IO 0x07 /* - TM8IO pin input */ |
170 | #else /* !CONFIG_AM33_2 */ | ||
171 | #define TM8MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
172 | #endif /* CONFIG_AM33_2 */ | ||
147 | #define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 173 | #define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
148 | #define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */ | 174 | #define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */ |
149 | 175 | ||
@@ -156,7 +182,11 @@ | |||
156 | #define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 182 | #define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
157 | #define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 183 | #define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
158 | #define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 184 | #define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
185 | #if defined(CONFIG_AM33_2) | ||
159 | #define TM9MD_SRC_TM9IO 0x07 /* - TM9IO pin input */ | 186 | #define TM9MD_SRC_TM9IO 0x07 /* - TM9IO pin input */ |
187 | #else /* !CONFIG_AM33_2 */ | ||
188 | #define TM9MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
189 | #endif /* CONFIG_AM33_2 */ | ||
160 | #define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 190 | #define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
161 | #define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */ | 191 | #define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */ |
162 | 192 | ||
@@ -169,7 +199,11 @@ | |||
169 | #define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 199 | #define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
170 | #define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 200 | #define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
171 | #define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 201 | #define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
202 | #if defined(CONFIG_AM33_2) | ||
172 | #define TM10MD_SRC_TM10IO 0x07 /* - TM10IO pin input */ | 203 | #define TM10MD_SRC_TM10IO 0x07 /* - TM10IO pin input */ |
204 | #else /* !CONFIG_AM33_2 */ | ||
205 | #define TM10MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
206 | #endif /* CONFIG_AM33_2 */ | ||
173 | #define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 207 | #define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
174 | #define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */ | 208 | #define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */ |
175 | 209 | ||
@@ -178,32 +212,101 @@ | |||
178 | #define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */ | 212 | #define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */ |
179 | #define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 213 | #define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ |
180 | #define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 214 | #define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ |
181 | #define TM11MD_SRC_TM7CASCADE 0x03 /* - cascade with timer 7 */ | ||
182 | #define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 215 | #define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ |
183 | #define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 216 | #define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ |
184 | #define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 217 | #define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ |
218 | #if defined(CONFIG_AM33_2) | ||
185 | #define TM11MD_SRC_TM11IO 0x07 /* - TM11IO pin input */ | 219 | #define TM11MD_SRC_TM11IO 0x07 /* - TM11IO pin input */ |
220 | #else /* !CONFIG_AM33_2 */ | ||
221 | #define TM11MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
222 | #endif /* CONFIG_AM33_2 */ | ||
186 | #define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 223 | #define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ |
187 | #define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */ | 224 | #define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */ |
188 | 225 | ||
226 | #if defined(CONFIG_AM34_2) | ||
227 | #define TM12MD __SYSREG(0xd4003180, u8) /* timer 11 mode register */ | ||
228 | #define TM12MD_SRC 0x07 /* timer source */ | ||
229 | #define TM12MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
230 | #define TM12MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
231 | #define TM12MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
232 | #define TM12MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
233 | #define TM12MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
234 | #define TM12MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
235 | #define TM12MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
236 | #define TM12MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
237 | #define TM12MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
238 | |||
239 | #define TM13MD __SYSREG(0xd4003182, u8) /* timer 11 mode register */ | ||
240 | #define TM13MD_SRC 0x07 /* timer source */ | ||
241 | #define TM13MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
242 | #define TM13MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
243 | #define TM13MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
244 | #define TM13MD_SRC_TM12CASCADE 0x03 /* - cascade with timer 12 */ | ||
245 | #define TM13MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
246 | #define TM13MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
247 | #define TM13MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
248 | #define TM13MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
249 | #define TM13MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
250 | #define TM13MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
251 | |||
252 | #define TM14MD __SYSREG(0xd4003184, u8) /* timer 11 mode register */ | ||
253 | #define TM14MD_SRC 0x07 /* timer source */ | ||
254 | #define TM14MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
255 | #define TM14MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
256 | #define TM14MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
257 | #define TM14MD_SRC_TM13CASCADE 0x03 /* - cascade with timer 13 */ | ||
258 | #define TM14MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
259 | #define TM14MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
260 | #define TM14MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
261 | #define TM14MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
262 | #define TM14MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
263 | #define TM14MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
264 | |||
265 | #define TM15MD __SYSREG(0xd4003186, u8) /* timer 11 mode register */ | ||
266 | #define TM15MD_SRC 0x07 /* timer source */ | ||
267 | #define TM15MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
268 | #define TM15MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
269 | #define TM15MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
270 | #define TM15MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
271 | #define TM15MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
272 | #define TM15MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
273 | #define TM15MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
274 | #define TM15MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
275 | #define TM15MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
276 | #endif /* CONFIG_AM34_2 */ | ||
277 | |||
278 | |||
189 | #define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */ | 279 | #define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */ |
190 | #define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */ | 280 | #define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */ |
281 | #define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */ | ||
191 | #define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */ | 282 | #define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */ |
192 | #define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */ | 283 | #define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */ |
193 | #define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */ | 284 | #define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */ |
285 | #define TM89BR __SYSREG(0xd4003098, u32) /* timer 8:9 base register */ | ||
194 | #define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */ | 286 | #define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */ |
195 | #define TM11BR __SYSREG(0xd400309e, u16) /* timer 11 base register */ | 287 | #define TM11BR __SYSREG(0xd400309e, u16) /* timer 11 base register */ |
196 | #define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */ | 288 | #if defined(CONFIG_AM34_2) |
289 | #define TM12BR __SYSREG(0xd4003190, u16) /* timer 12 base register */ | ||
290 | #define TM13BR __SYSREG(0xd4003192, u16) /* timer 13 base register */ | ||
291 | #define TM14BR __SYSREG(0xd4003194, u16) /* timer 14 base register */ | ||
292 | #define TM15BR __SYSREG(0xd4003196, u16) /* timer 15 base register */ | ||
293 | #endif /* CONFIG_AM34_2 */ | ||
197 | 294 | ||
198 | #define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */ | 295 | #define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */ |
199 | #define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */ | 296 | #define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */ |
200 | #define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */ | 297 | #define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */ |
201 | |||
202 | #define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */ | 298 | #define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */ |
203 | #define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */ | 299 | #define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */ |
204 | #define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */ | 300 | #define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */ |
301 | #define TM89BC __SYSREG(0xd40030a8, u32) /* timer 8:9 binary counter */ | ||
205 | #define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */ | 302 | #define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */ |
206 | #define TM11BC __SYSREG(0xd40030ae, u16) /* timer 11 binary counter */ | 303 | #define TM11BC __SYSREG(0xd40030ae, u16) /* timer 11 binary counter */ |
304 | #if defined(CONFIG_AM34_2) | ||
305 | #define TM12BC __SYSREG(0xd40031a0, u16) /* timer 12 binary counter */ | ||
306 | #define TM13BC __SYSREG(0xd40031a2, u16) /* timer 13 binary counter */ | ||
307 | #define TM14BC __SYSREG(0xd40031a4, u16) /* timer 14 binary counter */ | ||
308 | #define TM15BC __SYSREG(0xd40031a6, u16) /* timer 15 binary counter */ | ||
309 | #endif /* CONFIG_AM34_2 */ | ||
207 | 310 | ||
208 | #define TM4IRQ 6 /* timer 4 IRQ */ | 311 | #define TM4IRQ 6 /* timer 4 IRQ */ |
209 | #define TM5IRQ 7 /* timer 5 IRQ */ | 312 | #define TM5IRQ 7 /* timer 5 IRQ */ |
@@ -212,6 +315,12 @@ | |||
212 | #define TM9IRQ 13 /* timer 9 IRQ */ | 315 | #define TM9IRQ 13 /* timer 9 IRQ */ |
213 | #define TM10IRQ 14 /* timer 10 IRQ */ | 316 | #define TM10IRQ 14 /* timer 10 IRQ */ |
214 | #define TM11IRQ 15 /* timer 11 IRQ */ | 317 | #define TM11IRQ 15 /* timer 11 IRQ */ |
318 | #if defined(CONFIG_AM34_2) | ||
319 | #define TM12IRQ 64 /* timer 12 IRQ */ | ||
320 | #define TM13IRQ 65 /* timer 13 IRQ */ | ||
321 | #define TM14IRQ 66 /* timer 14 IRQ */ | ||
322 | #define TM15IRQ 67 /* timer 15 IRQ */ | ||
323 | #endif /* CONFIG_AM34_2 */ | ||
215 | 324 | ||
216 | #define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */ | 325 | #define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */ |
217 | #define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */ | 326 | #define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */ |
@@ -220,8 +329,16 @@ | |||
220 | #define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */ | 329 | #define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */ |
221 | #define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */ | 330 | #define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */ |
222 | #define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */ | 331 | #define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */ |
223 | 332 | #if defined(CONFIG_AM34_2) | |
224 | /* 16-bit timer 6 */ | 333 | #define TM12ICR GxICR(TM12IRQ) /* timer 12 uflow intr ctrl reg */ |
334 | #define TM13ICR GxICR(TM13IRQ) /* timer 13 uflow intr ctrl reg */ | ||
335 | #define TM14ICR GxICR(TM14IRQ) /* timer 14 uflow intr ctrl reg */ | ||
336 | #define TM15ICR GxICR(TM15IRQ) /* timer 15 uflow intr ctrl reg */ | ||
337 | #endif /* CONFIG_AM34_2 */ | ||
338 | |||
339 | /* | ||
340 | * 16-bit timer 6 | ||
341 | */ | ||
225 | #define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */ | 342 | #define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */ |
226 | #define TM6MD_SRC 0x0007 /* timer source */ | 343 | #define TM6MD_SRC 0x0007 /* timer source */ |
227 | #define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */ | 344 | #define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */ |
@@ -229,10 +346,14 @@ | |||
229 | #define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 346 | #define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */ |
230 | #define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */ | 347 | #define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */ |
231 | #define TM6MD_SRC_TM1UFLOW 0x0005 /* - timer 1 underflow */ | 348 | #define TM6MD_SRC_TM1UFLOW 0x0005 /* - timer 1 underflow */ |
232 | #define TM6MD_SRC_TM6IOB_BOTH 0x0006 /* - TM6IOB pin input (both edges) */ | 349 | #define TM6MD_SRC_TM2UFLOW 0x0006 /* - timer 2 underflow */ |
350 | #if defined(CONFIG_AM33_2) | ||
351 | /* #define TM6MD_SRC_TM6IOB_BOTH 0x0006 */ /* - TM6IOB pin input (both edges) */ | ||
233 | #define TM6MD_SRC_TM6IOB_SINGLE 0x0007 /* - TM6IOB pin input (single edge) */ | 352 | #define TM6MD_SRC_TM6IOB_SINGLE 0x0007 /* - TM6IOB pin input (single edge) */ |
234 | #define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */ | 353 | #endif /* CONFIG_AM33_2 */ |
235 | #define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */ | 354 | #define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */ |
355 | #define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */ | ||
356 | #if defined(CONFIG_AM33_2) | ||
236 | #define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */ | 357 | #define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */ |
237 | #define TM6MD_PWM 0x3800 /* PWM output mode */ | 358 | #define TM6MD_PWM 0x3800 /* PWM output mode */ |
238 | #define TM6MD_PWM_DIS 0x0000 /* - disabled */ | 359 | #define TM6MD_PWM_DIS 0x0000 /* - disabled */ |
@@ -240,10 +361,15 @@ | |||
240 | #define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */ | 361 | #define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */ |
241 | #define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */ | 362 | #define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */ |
242 | #define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */ | 363 | #define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */ |
364 | #endif /* CONFIG_AM33_2 */ | ||
365 | |||
243 | #define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */ | 366 | #define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */ |
244 | #define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */ | 367 | #define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */ |
245 | 368 | ||
246 | #define TM6MDA __SYSREG(0xd40030b4, u8) /* timer6 cmp/cap A mode reg */ | 369 | #define TM6MDA __SYSREG(0xd40030b4, u8) /* timer6 cmp/cap A mode reg */ |
370 | #define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
371 | #define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
372 | #if defined(CONFIG_AM33_2) | ||
247 | #define TM6MDA_OUT 0x07 /* output select */ | 373 | #define TM6MDA_OUT 0x07 /* output select */ |
248 | #define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */ | 374 | #define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */ |
249 | #define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */ | 375 | #define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */ |
@@ -251,30 +377,35 @@ | |||
251 | #define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */ | 377 | #define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */ |
252 | #define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */ | 378 | #define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */ |
253 | #define TM6MDA_MODE 0xc0 /* compare A register mode */ | 379 | #define TM6MDA_MODE 0xc0 /* compare A register mode */ |
254 | #define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
255 | #define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
256 | #define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 380 | #define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ |
257 | #define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 381 | #define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ |
258 | #define TM6MDA_EDGE 0x20 /* compare A edge select */ | 382 | #define TM6MDA_EDGE 0x20 /* compare A edge select */ |
259 | #define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */ | 383 | #define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */ |
260 | #define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */ | 384 | #define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */ |
261 | #define TM6MDA_CAPTURE_ENABLE 0x10 /* capture enable */ | 385 | #define TM6MDA_CAPTURE_ENABLE 0x10 /* capture enable */ |
386 | #else /* !CONFIG_AM33_2 */ | ||
387 | #define TM6MDA_MODE 0x40 /* compare A register mode */ | ||
388 | #endif /* CONFIG_AM33_2 */ | ||
262 | 389 | ||
263 | #define TM6MDB __SYSREG(0xd40030b5, u8) /* timer6 cmp/cap B mode reg */ | 390 | #define TM6MDB __SYSREG(0xd40030b5, u8) /* timer6 cmp/cap B mode reg */ |
391 | #define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
392 | #define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
393 | #if defined(CONFIG_AM33_2) | ||
264 | #define TM6MDB_OUT 0x07 /* output select */ | 394 | #define TM6MDB_OUT 0x07 /* output select */ |
265 | #define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */ | 395 | #define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */ |
266 | #define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */ | 396 | #define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */ |
267 | #define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */ | 397 | #define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */ |
268 | #define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */ | 398 | #define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */ |
269 | #define TM6MDB_MODE 0xc0 /* compare B register mode */ | 399 | #define TM6MDB_MODE 0xc0 /* compare B register mode */ |
270 | #define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
271 | #define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
272 | #define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 400 | #define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ |
273 | #define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 401 | #define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ |
274 | #define TM6MDB_EDGE 0x20 /* compare B edge select */ | 402 | #define TM6MDB_EDGE 0x20 /* compare B edge select */ |
275 | #define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */ | 403 | #define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */ |
276 | #define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */ | 404 | #define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */ |
277 | #define TM6MDB_CAPTURE_ENABLE 0x10 /* capture enable */ | 405 | #define TM6MDB_CAPTURE_ENABLE 0x10 /* capture enable */ |
406 | #else /* !CONFIG_AM33_2 */ | ||
407 | #define TM6MDB_MODE 0x40 /* compare B register mode */ | ||
408 | #endif /* CONFIG_AM33_2 */ | ||
278 | 409 | ||
279 | #define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */ | 410 | #define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */ |
280 | #define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */ | 411 | #define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */ |
@@ -288,6 +419,34 @@ | |||
288 | #define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */ | 419 | #define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */ |
289 | #define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */ | 420 | #define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */ |
290 | 421 | ||
422 | #if defined(CONFIG_AM34_2) | ||
423 | /* | ||
424 | * MTM: OS Tick-Timer | ||
425 | */ | ||
426 | #define TMTMD __SYSREG(0xd4004100, u8) /* Tick Timer mode register */ | ||
427 | #define TMTMD_TMTLDE 0x40 /* initialize TMTBC = TMTBR */ | ||
428 | #define TMTMD_TMTCNE 0x80 /* timer count enable */ | ||
429 | |||
430 | #define TMTBR __SYSREG(0xd4004110, u32) /* Tick Timer mode reg */ | ||
431 | #define TMTBC __SYSREG(0xd4004120, u32) /* Tick Timer mode reg */ | ||
432 | |||
433 | /* | ||
434 | * MTM: OS Timestamp-Timer | ||
435 | */ | ||
436 | #define TMSMD __SYSREG(0xd4004140, u8) /* Tick Timer mode register */ | ||
437 | #define TMSMD_TMSLDE 0x40 /* initialize TMSBC = TMSBR */ | ||
438 | #define TMSMD_TMSCNE 0x80 /* timer count enable */ | ||
439 | |||
440 | #define TMSBR __SYSREG(0xd4004150, u32) /* Tick Timer mode register */ | ||
441 | #define TMSBC __SYSREG(0xd4004160, u32) /* Tick Timer mode register */ | ||
442 | |||
443 | #define TMTIRQ 119 /* OS Tick timer IRQ */ | ||
444 | #define TMSIRQ 120 /* Timestamp timer IRQ */ | ||
445 | |||
446 | #define TMTICR GxICR(TMTIRQ) /* OS Tick timer uflow intr ctrl reg */ | ||
447 | #define TMSICR GxICR(TMSIRQ) /* Timestamp timer uflow intr ctrl reg */ | ||
448 | #endif /* CONFIG_AM34_2 */ | ||
449 | |||
291 | #endif /* __KERNEL__ */ | 450 | #endif /* __KERNEL__ */ |
292 | 451 | ||
293 | #endif /* _ASM_TIMER_REGS_H */ | 452 | #endif /* _ASM_TIMER_REGS_H */ |
diff --git a/arch/mn10300/include/asm/timex.h b/arch/mn10300/include/asm/timex.h index 8d031f9e117d..ce5719a2ce7c 100644 --- a/arch/mn10300/include/asm/timex.h +++ b/arch/mn10300/include/asm/timex.h | |||
@@ -16,8 +16,7 @@ | |||
16 | 16 | ||
17 | #define TICK_SIZE (tick_nsec / 1000) | 17 | #define TICK_SIZE (tick_nsec / 1000) |
18 | 18 | ||
19 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ - this should probably be set | 19 | #define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */ |
20 | * to something appropriate, but what? */ | ||
21 | 20 | ||
22 | extern cycles_t cacheflush_time; | 21 | extern cycles_t cacheflush_time; |
23 | 22 | ||
diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 197a7af3dd8a..47e7951e6893 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h | |||
@@ -377,7 +377,7 @@ unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, | |||
377 | 377 | ||
378 | 378 | ||
379 | #if 0 | 379 | #if 0 |
380 | #error don't use - these macros don't increment to & from pointers | 380 | #error "don't use - these macros don't increment to & from pointers" |
381 | /* Optimize just a little bit when we know the size of the move. */ | 381 | /* Optimize just a little bit when we know the size of the move. */ |
382 | #define __constant_copy_user(to, from, size) \ | 382 | #define __constant_copy_user(to, from, size) \ |
383 | do { \ | 383 | do { \ |
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 99022351717a..5b41192f496b 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile | |||
@@ -10,8 +10,9 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ | |||
10 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ | 10 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ |
11 | switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) | 11 | switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) |
12 | 12 | ||
13 | obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o | 13 | obj-$(CONFIG_SMP) += smp.o smp-low.o |
14 | 14 | ||
15 | obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o | ||
15 | 16 | ||
16 | obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ | 17 | obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ |
17 | mn10300-debug.o | 18 | mn10300-debug.o |
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c index 78e290e342fc..54cc5b6b13f2 100644 --- a/arch/mn10300/kernel/asm-offsets.c +++ b/arch/mn10300/kernel/asm-offsets.c | |||
@@ -66,7 +66,7 @@ void foo(void) | |||
66 | OFFSET(THREAD_SP, thread_struct, sp); | 66 | OFFSET(THREAD_SP, thread_struct, sp); |
67 | OFFSET(THREAD_A3, thread_struct, a3); | 67 | OFFSET(THREAD_A3, thread_struct, a3); |
68 | OFFSET(THREAD_USP, thread_struct, usp); | 68 | OFFSET(THREAD_USP, thread_struct, usp); |
69 | OFFSET(THREAD_FRAME, thread_struct, __frame); | 69 | OFFSET(THREAD_FRAME, thread_struct, frame); |
70 | #ifdef CONFIG_FPU | 70 | #ifdef CONFIG_FPU |
71 | OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags); | 71 | OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags); |
72 | OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state); | 72 | OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state); |
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 355f68176771..f00b9bafcd3e 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S | |||
@@ -28,25 +28,17 @@ | |||
28 | #include <asm/asm-offsets.h> | 28 | #include <asm/asm-offsets.h> |
29 | #include <asm/frame.inc> | 29 | #include <asm/frame.inc> |
30 | 30 | ||
31 | #if defined(CONFIG_SMP) && defined(CONFIG_GDBSTUB) | ||
32 | #include <asm/gdb-stub.h> | ||
33 | #endif /* CONFIG_SMP && CONFIG_GDBSTUB */ | ||
34 | |||
31 | #ifdef CONFIG_PREEMPT | 35 | #ifdef CONFIG_PREEMPT |
32 | #define preempt_stop __cli | 36 | #define preempt_stop LOCAL_IRQ_DISABLE |
33 | #else | 37 | #else |
34 | #define preempt_stop | 38 | #define preempt_stop |
35 | #define resume_kernel restore_all | 39 | #define resume_kernel restore_all |
36 | #endif | 40 | #endif |
37 | 41 | ||
38 | .macro __cli | ||
39 | and ~EPSW_IM,epsw | ||
40 | or EPSW_IE|MN10300_CLI_LEVEL,epsw | ||
41 | nop | ||
42 | nop | ||
43 | nop | ||
44 | .endm | ||
45 | .macro __sti | ||
46 | or EPSW_IE|EPSW_IM_7,epsw | ||
47 | .endm | ||
48 | |||
49 | |||
50 | .am33_2 | 42 | .am33_2 |
51 | 43 | ||
52 | ############################################################################### | 44 | ############################################################################### |
@@ -88,7 +80,7 @@ syscall_call: | |||
88 | syscall_exit: | 80 | syscall_exit: |
89 | # make sure we don't miss an interrupt setting need_resched or | 81 | # make sure we don't miss an interrupt setting need_resched or |
90 | # sigpending between sampling and the rti | 82 | # sigpending between sampling and the rti |
91 | __cli | 83 | LOCAL_IRQ_DISABLE |
92 | mov (TI_flags,a2),d2 | 84 | mov (TI_flags,a2),d2 |
93 | btst _TIF_ALLWORK_MASK,d2 | 85 | btst _TIF_ALLWORK_MASK,d2 |
94 | bne syscall_exit_work | 86 | bne syscall_exit_work |
@@ -105,7 +97,7 @@ restore_all: | |||
105 | syscall_exit_work: | 97 | syscall_exit_work: |
106 | btst _TIF_SYSCALL_TRACE,d2 | 98 | btst _TIF_SYSCALL_TRACE,d2 |
107 | beq work_pending | 99 | beq work_pending |
108 | __sti # could let syscall_trace_exit() call | 100 | LOCAL_IRQ_ENABLE # could let syscall_trace_exit() call |
109 | # schedule() instead | 101 | # schedule() instead |
110 | mov fp,d0 | 102 | mov fp,d0 |
111 | call syscall_trace_exit[],0 # do_syscall_trace(regs) | 103 | call syscall_trace_exit[],0 # do_syscall_trace(regs) |
@@ -121,7 +113,7 @@ work_resched: | |||
121 | 113 | ||
122 | # make sure we don't miss an interrupt setting need_resched or | 114 | # make sure we don't miss an interrupt setting need_resched or |
123 | # sigpending between sampling and the rti | 115 | # sigpending between sampling and the rti |
124 | __cli | 116 | LOCAL_IRQ_DISABLE |
125 | 117 | ||
126 | # is there any work to be done other than syscall tracing? | 118 | # is there any work to be done other than syscall tracing? |
127 | mov (TI_flags,a2),d2 | 119 | mov (TI_flags,a2),d2 |
@@ -168,7 +160,7 @@ ret_from_intr: | |||
168 | ENTRY(resume_userspace) | 160 | ENTRY(resume_userspace) |
169 | # make sure we don't miss an interrupt setting need_resched or | 161 | # make sure we don't miss an interrupt setting need_resched or |
170 | # sigpending between sampling and the rti | 162 | # sigpending between sampling and the rti |
171 | __cli | 163 | LOCAL_IRQ_DISABLE |
172 | 164 | ||
173 | # is there any work to be done on int/exception return? | 165 | # is there any work to be done on int/exception return? |
174 | mov (TI_flags,a2),d2 | 166 | mov (TI_flags,a2),d2 |
@@ -178,7 +170,7 @@ ENTRY(resume_userspace) | |||
178 | 170 | ||
179 | #ifdef CONFIG_PREEMPT | 171 | #ifdef CONFIG_PREEMPT |
180 | ENTRY(resume_kernel) | 172 | ENTRY(resume_kernel) |
181 | __cli | 173 | LOCAL_IRQ_DISABLE |
182 | mov (TI_preempt_count,a2),d0 # non-zero preempt_count ? | 174 | mov (TI_preempt_count,a2),d0 # non-zero preempt_count ? |
183 | cmp 0,d0 | 175 | cmp 0,d0 |
184 | bne restore_all | 176 | bne restore_all |
@@ -281,6 +273,79 @@ ENTRY(nmi_handler) | |||
281 | add -4,sp | 273 | add -4,sp |
282 | mov d0,(sp) | 274 | mov d0,(sp) |
283 | mov (TBR),d0 | 275 | mov (TBR),d0 |
276 | |||
277 | #ifdef CONFIG_SMP | ||
278 | add -4,sp | ||
279 | mov d0,(sp) # save d0(TBR) | ||
280 | movhu (NMIAGR),d0 | ||
281 | and NMIAGR_GN,d0 | ||
282 | lsr 0x2,d0 | ||
283 | cmp CALL_FUNCTION_NMI_IPI,d0 | ||
284 | bne 5f # if not call function, jump | ||
285 | |||
286 | # function call nmi ipi | ||
287 | add 4,sp # no need to store TBR | ||
288 | mov GxICR_DETECT,d0 # clear NMI request | ||
289 | movbu d0,(GxICR(CALL_FUNCTION_NMI_IPI)) | ||
290 | movhu (GxICR(CALL_FUNCTION_NMI_IPI)),d0 | ||
291 | and ~EPSW_NMID,epsw # enable NMI | ||
292 | |||
293 | mov (sp),d0 # restore d0 | ||
294 | SAVE_ALL | ||
295 | call smp_nmi_call_function_interrupt[],0 | ||
296 | RESTORE_ALL | ||
297 | |||
298 | 5: | ||
299 | #ifdef CONFIG_GDBSTUB | ||
300 | cmp GDB_NMI_IPI,d0 | ||
301 | bne 3f # if not gdb nmi ipi, jump | ||
302 | |||
303 | # gdb nmi ipi | ||
304 | add 4,sp # no need to store TBR | ||
305 | mov GxICR_DETECT,d0 # clear NMI | ||
306 | movbu d0,(GxICR(GDB_NMI_IPI)) | ||
307 | movhu (GxICR(GDB_NMI_IPI)),d0 | ||
308 | and ~EPSW_NMID,epsw # enable NMI | ||
309 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
310 | mov (gdbstub_nmi_opr_type),d0 | ||
311 | cmp GDBSTUB_NMI_CACHE_PURGE,d0 | ||
312 | bne 4f # if not gdb cache purge, jump | ||
313 | |||
314 | # gdb cache purge nmi ipi | ||
315 | add -20,sp | ||
316 | mov d1,(4,sp) | ||
317 | mov a0,(8,sp) | ||
318 | mov a1,(12,sp) | ||
319 | mov mdr,d0 | ||
320 | mov d0,(16,sp) | ||
321 | call gdbstub_local_purge_cache[],0 | ||
322 | mov 0x1,d0 | ||
323 | mov (CPUID),d1 | ||
324 | asl d1,d0 | ||
325 | mov gdbstub_nmi_cpumask,a0 | ||
326 | bclr d0,(a0) | ||
327 | mov (4,sp),d1 | ||
328 | mov (8,sp),a0 | ||
329 | mov (12,sp),a1 | ||
330 | mov (16,sp),d0 | ||
331 | mov d0,mdr | ||
332 | add 20,sp | ||
333 | mov (sp),d0 | ||
334 | add 4,sp | ||
335 | rti | ||
336 | 4: | ||
337 | #endif /* CONFIG_MN10300_CACHE_ENABLED */ | ||
338 | # gdb wait nmi ipi | ||
339 | mov (sp),d0 | ||
340 | SAVE_ALL | ||
341 | call gdbstub_nmi_wait[],0 | ||
342 | RESTORE_ALL | ||
343 | 3: | ||
344 | #endif /* CONFIG_GDBSTUB */ | ||
345 | mov (sp),d0 # restore TBR to d0 | ||
346 | add 4,sp | ||
347 | #endif /* CONFIG_SMP */ | ||
348 | |||
284 | bra __common_exception_nonmi | 349 | bra __common_exception_nonmi |
285 | 350 | ||
286 | ENTRY(__common_exception) | 351 | ENTRY(__common_exception) |
@@ -314,15 +379,21 @@ __common_exception_nonmi: | |||
314 | mov d0,(REG_ORIG_D0,fp) | 379 | mov d0,(REG_ORIG_D0,fp) |
315 | 380 | ||
316 | #ifdef CONFIG_GDBSTUB | 381 | #ifdef CONFIG_GDBSTUB |
382 | #ifdef CONFIG_SMP | ||
383 | call gdbstub_busy_check[],0 | ||
384 | and d0,d0 # check return value | ||
385 | beq 2f | ||
386 | #else /* CONFIG_SMP */ | ||
317 | btst 0x01,(gdbstub_busy) | 387 | btst 0x01,(gdbstub_busy) |
318 | beq 2f | 388 | beq 2f |
389 | #endif /* CONFIG_SMP */ | ||
319 | and ~EPSW_IE,epsw | 390 | and ~EPSW_IE,epsw |
320 | mov fp,d0 | 391 | mov fp,d0 |
321 | mov a2,d1 | 392 | mov a2,d1 |
322 | call gdbstub_exception[],0 # gdbstub itself caused an exception | 393 | call gdbstub_exception[],0 # gdbstub itself caused an exception |
323 | bra restore_all | 394 | bra restore_all |
324 | 2: | 395 | 2: |
325 | #endif | 396 | #endif /* CONFIG_GDBSTUB */ |
326 | 397 | ||
327 | mov fp,d0 # arg 0: stacked register file | 398 | mov fp,d0 # arg 0: stacked register file |
328 | mov a2,d1 # arg 1: exception number | 399 | mov a2,d1 # arg 1: exception number |
@@ -357,11 +428,7 @@ ENTRY(set_excp_vector) | |||
357 | add exception_table,d0 | 428 | add exception_table,d0 |
358 | mov d1,(d0) | 429 | mov d1,(d0) |
359 | mov 4,d1 | 430 | mov 4,d1 |
360 | #if defined(CONFIG_MN10300_CACHE_WBACK) | ||
361 | jmp mn10300_dcache_flush_inv_range2 | ||
362 | #else | ||
363 | ret [],0 | 431 | ret [],0 |
364 | #endif | ||
365 | 432 | ||
366 | ############################################################################### | 433 | ############################################################################### |
367 | # | 434 | # |
diff --git a/arch/mn10300/kernel/gdb-io-serial-low.S b/arch/mn10300/kernel/gdb-io-serial-low.S index 4998b24f5d3a..b1d0152e96cb 100644 --- a/arch/mn10300/kernel/gdb-io-serial-low.S +++ b/arch/mn10300/kernel/gdb-io-serial-low.S | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> |
19 | #include <asm/frame.inc> | 19 | #include <asm/frame.inc> |
20 | #include <asm/intctl-regs.h> | 20 | #include <asm/intctl-regs.h> |
21 | #include <asm/irqflags.h> | ||
21 | #include <unit/serial.h> | 22 | #include <unit/serial.h> |
22 | 23 | ||
23 | .text | 24 | .text |
@@ -69,7 +70,7 @@ gdbstub_io_rx_overflow: | |||
69 | bra gdbstub_io_rx_done | 70 | bra gdbstub_io_rx_done |
70 | 71 | ||
71 | gdbstub_io_rx_enter: | 72 | gdbstub_io_rx_enter: |
72 | or EPSW_IE|EPSW_IM_1,epsw | 73 | LOCAL_CHANGE_INTR_MASK_LEVEL(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL+1)) |
73 | add -4,sp | 74 | add -4,sp |
74 | SAVE_ALL | 75 | SAVE_ALL |
75 | 76 | ||
@@ -80,7 +81,7 @@ gdbstub_io_rx_enter: | |||
80 | mov fp,d0 | 81 | mov fp,d0 |
81 | call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep) | 82 | call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep) |
82 | 83 | ||
83 | and ~EPSW_IE,epsw | 84 | LOCAL_CLI |
84 | bclr 0x01,(gdbstub_busy) | 85 | bclr 0x01,(gdbstub_busy) |
85 | 86 | ||
86 | .globl gdbstub_return | 87 | .globl gdbstub_return |
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c index ae663dc717e9..0d5d63c91dc3 100644 --- a/arch/mn10300/kernel/gdb-io-serial.c +++ b/arch/mn10300/kernel/gdb-io-serial.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/exceptions.h> | 23 | #include <asm/exceptions.h> |
24 | #include <asm/serial-regs.h> | 24 | #include <asm/serial-regs.h> |
25 | #include <unit/serial.h> | 25 | #include <unit/serial.h> |
26 | #include <asm/smp.h> | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * initialise the GDB stub | 29 | * initialise the GDB stub |
@@ -45,22 +46,34 @@ void gdbstub_io_init(void) | |||
45 | XIRQxICR(GDBPORT_SERIAL_IRQ) = 0; | 46 | XIRQxICR(GDBPORT_SERIAL_IRQ) = 0; |
46 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 47 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); |
47 | 48 | ||
49 | #if CONFIG_GDBSTUB_IRQ_LEVEL == 0 | ||
48 | IVAR0 = EXCEP_IRQ_LEVEL0; | 50 | IVAR0 = EXCEP_IRQ_LEVEL0; |
49 | set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler); | 51 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 1 |
52 | IVAR1 = EXCEP_IRQ_LEVEL1; | ||
53 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 2 | ||
54 | IVAR2 = EXCEP_IRQ_LEVEL2; | ||
55 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 3 | ||
56 | IVAR3 = EXCEP_IRQ_LEVEL3; | ||
57 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 4 | ||
58 | IVAR4 = EXCEP_IRQ_LEVEL4; | ||
59 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 5 | ||
60 | IVAR5 = EXCEP_IRQ_LEVEL5; | ||
61 | #else | ||
62 | #error "Unknown irq level for gdbstub." | ||
63 | #endif | ||
64 | |||
65 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), | ||
66 | gdbstub_io_rx_handler); | ||
50 | 67 | ||
51 | XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST; | 68 | XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST; |
52 | XIRQxICR(GDBPORT_SERIAL_IRQ) = GxICR_ENABLE | GxICR_LEVEL_0; | 69 | XIRQxICR(GDBPORT_SERIAL_IRQ) = |
70 | GxICR_ENABLE | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL); | ||
53 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 71 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); |
54 | 72 | ||
55 | GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI; | 73 | GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI; |
56 | 74 | ||
57 | /* permit level 0 IRQs to take place */ | 75 | /* permit level 0 IRQs to take place */ |
58 | asm volatile( | 76 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); |
59 | " and %0,epsw \n" | ||
60 | " or %1,epsw \n" | ||
61 | : | ||
62 | : "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1) | ||
63 | ); | ||
64 | } | 77 | } |
65 | 78 | ||
66 | /* | 79 | /* |
@@ -87,6 +100,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
87 | { | 100 | { |
88 | unsigned ix; | 101 | unsigned ix; |
89 | u8 ch, st; | 102 | u8 ch, st; |
103 | #if defined(CONFIG_MN10300_WD_TIMER) | ||
104 | int cpu; | ||
105 | #endif | ||
90 | 106 | ||
91 | *_ch = 0xff; | 107 | *_ch = 0xff; |
92 | 108 | ||
@@ -104,8 +120,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
104 | if (nonblock) | 120 | if (nonblock) |
105 | return -EAGAIN; | 121 | return -EAGAIN; |
106 | #ifdef CONFIG_MN10300_WD_TIMER | 122 | #ifdef CONFIG_MN10300_WD_TIMER |
107 | watchdog_alert_counter = 0; | 123 | for (cpu = 0; cpu < NR_CPUS; cpu++) |
108 | #endif /* CONFIG_MN10300_WD_TIMER */ | 124 | watchdog_alert_counter[cpu] = 0; |
125 | #endif | ||
109 | goto try_again; | 126 | goto try_again; |
110 | } | 127 | } |
111 | 128 | ||
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c index a560bbc3137d..97dfda23342c 100644 --- a/arch/mn10300/kernel/gdb-io-ttysm.c +++ b/arch/mn10300/kernel/gdb-io-ttysm.c | |||
@@ -58,9 +58,12 @@ void __init gdbstub_io_init(void) | |||
58 | gdbstub_io_set_baud(115200); | 58 | gdbstub_io_set_baud(115200); |
59 | 59 | ||
60 | /* we want to get serial receive interrupts */ | 60 | /* we want to get serial receive interrupts */ |
61 | set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0); | 61 | set_intr_level(gdbstub_port->rx_irq, |
62 | set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0); | 62 | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); |
63 | set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler); | 63 | set_intr_level(gdbstub_port->tx_irq, |
64 | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); | ||
65 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), | ||
66 | gdbstub_io_rx_handler); | ||
64 | 67 | ||
65 | *gdbstub_port->rx_icr |= GxICR_ENABLE; | 68 | *gdbstub_port->rx_icr |= GxICR_ENABLE; |
66 | tmp = *gdbstub_port->rx_icr; | 69 | tmp = *gdbstub_port->rx_icr; |
@@ -84,12 +87,7 @@ void __init gdbstub_io_init(void) | |||
84 | tmp = *gdbstub_port->_control; | 87 | tmp = *gdbstub_port->_control; |
85 | 88 | ||
86 | /* permit level 0 IRQs only */ | 89 | /* permit level 0 IRQs only */ |
87 | asm volatile( | 90 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); |
88 | " and %0,epsw \n" | ||
89 | " or %1,epsw \n" | ||
90 | : | ||
91 | : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1) | ||
92 | ); | ||
93 | } | 91 | } |
94 | 92 | ||
95 | /* | 93 | /* |
@@ -184,6 +182,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
184 | { | 182 | { |
185 | unsigned ix; | 183 | unsigned ix; |
186 | u8 ch, st; | 184 | u8 ch, st; |
185 | #if defined(CONFIG_MN10300_WD_TIMER) | ||
186 | int cpu; | ||
187 | #endif | ||
187 | 188 | ||
188 | *_ch = 0xff; | 189 | *_ch = 0xff; |
189 | 190 | ||
@@ -201,8 +202,9 @@ try_again: | |||
201 | if (nonblock) | 202 | if (nonblock) |
202 | return -EAGAIN; | 203 | return -EAGAIN; |
203 | #ifdef CONFIG_MN10300_WD_TIMER | 204 | #ifdef CONFIG_MN10300_WD_TIMER |
204 | watchdog_alert_counter = 0; | 205 | for (cpu = 0; cpu < NR_CPUS; cpu++) |
205 | #endif /* CONFIG_MN10300_WD_TIMER */ | 206 | watchdog_alert_counter[cpu] = 0; |
207 | #endif | ||
206 | goto try_again; | 208 | goto try_again; |
207 | } | 209 | } |
208 | 210 | ||
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index 41b11706c8ed..a5fc3f05309b 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c | |||
@@ -440,15 +440,11 @@ static const unsigned char gdbstub_insn_sizes[256] = | |||
440 | 440 | ||
441 | static int __gdbstub_mark_bp(u8 *addr, int ix) | 441 | static int __gdbstub_mark_bp(u8 *addr, int ix) |
442 | { | 442 | { |
443 | if (addr < (u8 *) 0x70000000UL) | 443 | /* vmalloc area */ |
444 | return 0; | 444 | if (((u8 *) VMALLOC_START <= addr) && (addr < (u8 *) VMALLOC_END)) |
445 | /* 70000000-7fffffff: vmalloc area */ | ||
446 | if (addr < (u8 *) 0x80000000UL) | ||
447 | goto okay; | 445 | goto okay; |
448 | if (addr < (u8 *) 0x8c000000UL) | 446 | /* SRAM, SDRAM */ |
449 | return 0; | 447 | if (((u8 *) 0x80000000UL <= addr) && (addr < (u8 *) 0xa0000000UL)) |
450 | /* 8c000000-93ffffff: SRAM, SDRAM */ | ||
451 | if (addr < (u8 *) 0x94000000UL) | ||
452 | goto okay; | 448 | goto okay; |
453 | return 0; | 449 | return 0; |
454 | 450 | ||
@@ -1197,9 +1193,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) | |||
1197 | mn10300_set_gdbleds(1); | 1193 | mn10300_set_gdbleds(1); |
1198 | 1194 | ||
1199 | asm volatile("mov mdr,%0" : "=d"(mdr)); | 1195 | asm volatile("mov mdr,%0" : "=d"(mdr)); |
1200 | asm volatile("mov epsw,%0" : "=d"(epsw)); | 1196 | local_save_flags(epsw); |
1201 | asm volatile("mov %0,epsw" | 1197 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); |
1202 | :: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1)); | ||
1203 | 1198 | ||
1204 | gdbstub_store_fpu(); | 1199 | gdbstub_store_fpu(); |
1205 | 1200 | ||
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S index a81e34fba651..73e00fc78072 100644 --- a/arch/mn10300/kernel/head.S +++ b/arch/mn10300/kernel/head.S | |||
@@ -19,6 +19,12 @@ | |||
19 | #include <asm/frame.inc> | 19 | #include <asm/frame.inc> |
20 | #include <asm/param.h> | 20 | #include <asm/param.h> |
21 | #include <unit/serial.h> | 21 | #include <unit/serial.h> |
22 | #ifdef CONFIG_SMP | ||
23 | #include <asm/smp.h> | ||
24 | #include <asm/intctl-regs.h> | ||
25 | #include <asm/cpu-regs.h> | ||
26 | #include <proc/smp-regs.h> | ||
27 | #endif /* CONFIG_SMP */ | ||
22 | 28 | ||
23 | __HEAD | 29 | __HEAD |
24 | 30 | ||
@@ -30,17 +36,51 @@ | |||
30 | .globl _start | 36 | .globl _start |
31 | .type _start,@function | 37 | .type _start,@function |
32 | _start: | 38 | _start: |
39 | #ifdef CONFIG_SMP | ||
40 | # | ||
41 | # If this is a secondary CPU (AP), then deal with that elsewhere | ||
42 | # | ||
43 | mov (CPUID),d3 | ||
44 | and CPUID_MASK,d3 | ||
45 | bne startup_secondary | ||
46 | |||
47 | # | ||
48 | # We're dealing with the primary CPU (BP) here, then. | ||
49 | # Keep BP's D0,D1,D2 register for boot check. | ||
50 | # | ||
51 | |||
52 | # Set up the Boot IPI for each secondary CPU | ||
53 | mov 0x1,a0 | ||
54 | loop_set_secondary_icr: | ||
55 | mov a0,a1 | ||
56 | asl CROSS_ICR_CPU_SHIFT,a1 | ||
57 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a1 | ||
58 | movhu (a1),d3 | ||
59 | or GxICR_ENABLE|GxICR_LEVEL_0,d3 | ||
60 | movhu d3,(a1) | ||
61 | movhu (a1),d3 # flush | ||
62 | inc a0 | ||
63 | cmp NR_CPUS,a0 | ||
64 | bne loop_set_secondary_icr | ||
65 | #endif /* CONFIG_SMP */ | ||
66 | |||
33 | # save commandline pointer | 67 | # save commandline pointer |
34 | mov d0,a3 | 68 | mov d0,a3 |
35 | 69 | ||
36 | # preload the PGD pointer register | 70 | # preload the PGD pointer register |
37 | mov swapper_pg_dir,d0 | 71 | mov swapper_pg_dir,d0 |
38 | mov d0,(PTBR) | 72 | mov d0,(PTBR) |
73 | clr d0 | ||
74 | movbu d0,(PIDR) | ||
39 | 75 | ||
40 | # turn on the TLBs | 76 | # turn on the TLBs |
41 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | 77 | mov MMUCTR_IIV|MMUCTR_DIV,d0 |
42 | mov d0,(MMUCTR) | 78 | mov d0,(MMUCTR) |
79 | #ifdef CONFIG_AM34_2 | ||
80 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | ||
81 | #else | ||
43 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | 82 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 |
83 | #endif | ||
44 | mov d0,(MMUCTR) | 84 | mov d0,(MMUCTR) |
45 | 85 | ||
46 | # turn on AM33v2 exception handling mode and set the trap table base | 86 | # turn on AM33v2 exception handling mode and set the trap table base |
@@ -51,6 +91,11 @@ _start: | |||
51 | mov d0,(TBR) | 91 | mov d0,(TBR) |
52 | 92 | ||
53 | # invalidate and enable both of the caches | 93 | # invalidate and enable both of the caches |
94 | #ifdef CONFIG_SMP | ||
95 | mov ECHCTR,a0 | ||
96 | clr d0 | ||
97 | mov d0,(a0) | ||
98 | #endif | ||
54 | mov CHCTR,a0 | 99 | mov CHCTR,a0 |
55 | clr d0 | 100 | clr d0 |
56 | movhu d0,(a0) # turn off first | 101 | movhu d0,(a0) # turn off first |
@@ -206,6 +251,44 @@ __no_parameters: | |||
206 | call processor_init[],0 | 251 | call processor_init[],0 |
207 | call unit_init[],0 | 252 | call unit_init[],0 |
208 | 253 | ||
254 | #ifdef CONFIG_SMP | ||
255 | # mark the primary CPU in cpu_boot_map | ||
256 | mov cpu_boot_map,a0 | ||
257 | mov 0x1,d0 | ||
258 | mov d0,(a0) | ||
259 | |||
260 | # signal each secondary CPU to begin booting | ||
261 | mov 0x1,d2 # CPU ID | ||
262 | |||
263 | loop_request_boot_secondary: | ||
264 | mov d2,a0 | ||
265 | # send SMP_BOOT_IPI to secondary CPU | ||
266 | asl CROSS_ICR_CPU_SHIFT,a0 | ||
267 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a0 | ||
268 | movhu (a0),d0 | ||
269 | or GxICR_REQUEST|GxICR_DETECT,d0 | ||
270 | movhu d0,(a0) | ||
271 | movhu (a0),d0 # flush | ||
272 | |||
273 | # wait up to 100ms for AP's IPI to be received | ||
274 | clr d3 | ||
275 | wait_on_secondary_boot: | ||
276 | mov DELAY_TIME_BOOT_IPI,d0 | ||
277 | call __delay[],0 | ||
278 | inc d3 | ||
279 | mov cpu_boot_map,a0 | ||
280 | mov (a0),d0 | ||
281 | lsr d2,d0 | ||
282 | btst 0x1,d0 | ||
283 | bne 1f | ||
284 | cmp TIME_OUT_COUNT_BOOT_IPI,d3 | ||
285 | bne wait_on_secondary_boot | ||
286 | 1: | ||
287 | inc d2 | ||
288 | cmp NR_CPUS,d2 | ||
289 | bne loop_request_boot_secondary | ||
290 | #endif /* CONFIG_SMP */ | ||
291 | |||
209 | #ifdef CONFIG_GDBSTUB | 292 | #ifdef CONFIG_GDBSTUB |
210 | call gdbstub_init[],0 | 293 | call gdbstub_init[],0 |
211 | 294 | ||
@@ -217,7 +300,118 @@ __gdbstub_pause: | |||
217 | #endif | 300 | #endif |
218 | 301 | ||
219 | jmp start_kernel | 302 | jmp start_kernel |
220 | .size _start, _start-. | 303 | .size _start,.-_start |
304 | |||
305 | ############################################################################### | ||
306 | # | ||
307 | # Secondary CPU boot point | ||
308 | # | ||
309 | ############################################################################### | ||
310 | #ifdef CONFIG_SMP | ||
311 | startup_secondary: | ||
312 | # preload the PGD pointer register | ||
313 | mov swapper_pg_dir,d0 | ||
314 | mov d0,(PTBR) | ||
315 | clr d0 | ||
316 | movbu d0,(PIDR) | ||
317 | |||
318 | # turn on the TLBs | ||
319 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | ||
320 | mov d0,(MMUCTR) | ||
321 | #ifdef CONFIG_AM34_2 | ||
322 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | ||
323 | #else | ||
324 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | ||
325 | #endif | ||
326 | mov d0,(MMUCTR) | ||
327 | |||
328 | # turn on AM33v2 exception handling mode and set the trap table base | ||
329 | movhu (CPUP),d0 | ||
330 | or CPUP_EXM_AM33V2,d0 | ||
331 | movhu d0,(CPUP) | ||
332 | |||
333 | # set the interrupt vector table | ||
334 | mov CONFIG_INTERRUPT_VECTOR_BASE,d0 | ||
335 | mov d0,(TBR) | ||
336 | |||
337 | # invalidate and enable both of the caches | ||
338 | mov ECHCTR,a0 | ||
339 | clr d0 | ||
340 | mov d0,(a0) | ||
341 | mov CHCTR,a0 | ||
342 | clr d0 | ||
343 | movhu d0,(a0) # turn off first | ||
344 | mov CHCTR_ICINV|CHCTR_DCINV,d0 | ||
345 | movhu d0,(a0) | ||
346 | setlb | ||
347 | mov (a0),d0 | ||
348 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | ||
349 | lne | ||
350 | |||
351 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
352 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
353 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | ||
354 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | ||
355 | #else | ||
356 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | ||
357 | #endif /* !NOWRALLOC */ | ||
358 | #else | ||
359 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | ||
360 | #endif /* WBACK */ | ||
361 | movhu d0,(a0) # enable | ||
362 | #endif /* ENABLED */ | ||
363 | |||
364 | # Clear the boot IPI interrupt for this CPU | ||
365 | movhu (GxICR(SMP_BOOT_IRQ)),d0 | ||
366 | and ~GxICR_REQUEST,d0 | ||
367 | movhu d0,(GxICR(SMP_BOOT_IRQ)) | ||
368 | movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush | ||
369 | |||
370 | /* get stack */ | ||
371 | mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0 | ||
372 | mov (CPUID),d0 | ||
373 | and CPUID_MASK,d0 | ||
374 | mulu CONFIG_BOOT_STACK_SIZE,d0 | ||
375 | sub d0,a0 | ||
376 | mov a0,sp | ||
377 | |||
378 | # init interrupt for AP | ||
379 | call smp_prepare_cpu_init[],0 | ||
380 | |||
381 | # mark this secondary CPU in cpu_boot_map | ||
382 | mov (CPUID),d0 | ||
383 | mov 0x1,d1 | ||
384 | asl d0,d1 | ||
385 | mov cpu_boot_map,a0 | ||
386 | bset d1,(a0) | ||
387 | |||
388 | or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts | ||
389 | nop | ||
390 | nop | ||
391 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
392 | # flush the local cache if it's in writeback mode | ||
393 | call mn10300_local_dcache_flush_inv[],0 | ||
394 | setlb | ||
395 | mov (CHCTR),d0 | ||
396 | btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | ||
397 | lne | ||
398 | #endif | ||
399 | |||
400 | # now sleep waiting for further instructions | ||
401 | secondary_sleep: | ||
402 | mov CPUM_SLEEP,d0 | ||
403 | movhu d0,(CPUM) | ||
404 | nop | ||
405 | nop | ||
406 | bra secondary_sleep | ||
407 | .size startup_secondary,.-startup_secondary | ||
408 | #endif /* CONFIG_SMP */ | ||
409 | |||
410 | ############################################################################### | ||
411 | # | ||
412 | # | ||
413 | # | ||
414 | ############################################################################### | ||
221 | ENTRY(__head_end) | 415 | ENTRY(__head_end) |
222 | 416 | ||
223 | /* | 417 | /* |
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index eee2eee86267..3b1f48b7e7f4 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h | |||
@@ -18,3 +18,15 @@ extern int kernel_thread_helper(int); | |||
18 | * entry.S | 18 | * entry.S |
19 | */ | 19 | */ |
20 | extern void ret_from_fork(struct task_struct *) __attribute__((noreturn)); | 20 | extern void ret_from_fork(struct task_struct *) __attribute__((noreturn)); |
21 | |||
22 | /* | ||
23 | * smp-low.S | ||
24 | */ | ||
25 | #ifdef CONFIG_SMP | ||
26 | extern void mn10300_low_ipi_handler(void); | ||
27 | #endif | ||
28 | |||
29 | /* | ||
30 | * time.c | ||
31 | */ | ||
32 | extern irqreturn_t local_timer_interrupt(void); | ||
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index b5b970d2954a..80f15725ecad 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
@@ -12,11 +12,34 @@ | |||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/kernel_stat.h> | 13 | #include <linux/kernel_stat.h> |
14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
15 | #include <linux/cpumask.h> | ||
15 | #include <asm/setup.h> | 16 | #include <asm/setup.h> |
17 | #include <asm/serial-regs.h> | ||
16 | 18 | ||
17 | unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7; | 19 | #ifdef CONFIG_SMP |
20 | #undef GxICR | ||
21 | #define GxICR(X) CROSS_GxICR(X, irq_affinity_online[X]) | ||
22 | |||
23 | #undef GxICR_u8 | ||
24 | #define GxICR_u8(X) CROSS_GxICR_u8(X, irq_affinity_online[X]) | ||
25 | #endif /* CONFIG_SMP */ | ||
26 | |||
27 | unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = { | ||
28 | [0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7 | ||
29 | }; | ||
18 | EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); | 30 | EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); |
19 | 31 | ||
32 | #ifdef CONFIG_SMP | ||
33 | static char irq_affinity_online[NR_IRQS] = { | ||
34 | [0 ... NR_IRQS - 1] = 0 | ||
35 | }; | ||
36 | |||
37 | #define NR_IRQ_WORDS ((NR_IRQS + 31) / 32) | ||
38 | static unsigned long irq_affinity_request[NR_IRQ_WORDS] = { | ||
39 | [0 ... NR_IRQ_WORDS - 1] = 0 | ||
40 | }; | ||
41 | #endif /* CONFIG_SMP */ | ||
42 | |||
20 | atomic_t irq_err_count; | 43 | atomic_t irq_err_count; |
21 | 44 | ||
22 | /* | 45 | /* |
@@ -24,30 +47,65 @@ atomic_t irq_err_count; | |||
24 | */ | 47 | */ |
25 | static void mn10300_cpupic_ack(unsigned int irq) | 48 | static void mn10300_cpupic_ack(unsigned int irq) |
26 | { | 49 | { |
50 | unsigned long flags; | ||
51 | u16 tmp; | ||
52 | |||
53 | flags = arch_local_cli_save(); | ||
54 | GxICR_u8(irq) = GxICR_DETECT; | ||
55 | tmp = GxICR(irq); | ||
56 | arch_local_irq_restore(flags); | ||
57 | } | ||
58 | |||
59 | static void __mask_and_set_icr(unsigned int irq, | ||
60 | unsigned int mask, unsigned int set) | ||
61 | { | ||
62 | unsigned long flags; | ||
27 | u16 tmp; | 63 | u16 tmp; |
28 | *(volatile u8 *) &GxICR(irq) = GxICR_DETECT; | 64 | |
65 | flags = arch_local_cli_save(); | ||
29 | tmp = GxICR(irq); | 66 | tmp = GxICR(irq); |
67 | GxICR(irq) = (tmp & mask) | set; | ||
68 | tmp = GxICR(irq); | ||
69 | arch_local_irq_restore(flags); | ||
30 | } | 70 | } |
31 | 71 | ||
32 | static void mn10300_cpupic_mask(unsigned int irq) | 72 | static void mn10300_cpupic_mask(unsigned int irq) |
33 | { | 73 | { |
34 | u16 tmp = GxICR(irq); | 74 | __mask_and_set_icr(irq, GxICR_LEVEL, 0); |
35 | GxICR(irq) = (tmp & GxICR_LEVEL); | ||
36 | tmp = GxICR(irq); | ||
37 | } | 75 | } |
38 | 76 | ||
39 | static void mn10300_cpupic_mask_ack(unsigned int irq) | 77 | static void mn10300_cpupic_mask_ack(unsigned int irq) |
40 | { | 78 | { |
41 | u16 tmp = GxICR(irq); | 79 | #ifdef CONFIG_SMP |
42 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | 80 | unsigned long flags; |
43 | tmp = GxICR(irq); | 81 | u16 tmp; |
82 | |||
83 | flags = arch_local_cli_save(); | ||
84 | |||
85 | if (!test_and_clear_bit(irq, irq_affinity_request)) { | ||
86 | tmp = GxICR(irq); | ||
87 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | ||
88 | tmp = GxICR(irq); | ||
89 | } else { | ||
90 | u16 tmp2; | ||
91 | tmp = GxICR(irq); | ||
92 | GxICR(irq) = (tmp & GxICR_LEVEL); | ||
93 | tmp2 = GxICR(irq); | ||
94 | |||
95 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | ||
96 | GxICR(irq) = (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; | ||
97 | tmp = GxICR(irq); | ||
98 | } | ||
99 | |||
100 | arch_local_irq_restore(flags); | ||
101 | #else /* CONFIG_SMP */ | ||
102 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_DETECT); | ||
103 | #endif /* CONFIG_SMP */ | ||
44 | } | 104 | } |
45 | 105 | ||
46 | static void mn10300_cpupic_unmask(unsigned int irq) | 106 | static void mn10300_cpupic_unmask(unsigned int irq) |
47 | { | 107 | { |
48 | u16 tmp = GxICR(irq); | 108 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE); |
49 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; | ||
50 | tmp = GxICR(irq); | ||
51 | } | 109 | } |
52 | 110 | ||
53 | static void mn10300_cpupic_unmask_clear(unsigned int irq) | 111 | static void mn10300_cpupic_unmask_clear(unsigned int irq) |
@@ -56,11 +114,89 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) | |||
56 | * device has ceased to assert its interrupt line and the interrupt | 114 | * device has ceased to assert its interrupt line and the interrupt |
57 | * channel has been disabled in the PIC, so for level-triggered | 115 | * channel has been disabled in the PIC, so for level-triggered |
58 | * interrupts we need to clear the request bit when we re-enable */ | 116 | * interrupts we need to clear the request bit when we re-enable */ |
59 | u16 tmp = GxICR(irq); | 117 | #ifdef CONFIG_SMP |
60 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | 118 | unsigned long flags; |
61 | tmp = GxICR(irq); | 119 | u16 tmp; |
120 | |||
121 | flags = arch_local_cli_save(); | ||
122 | |||
123 | if (!test_and_clear_bit(irq, irq_affinity_request)) { | ||
124 | tmp = GxICR(irq); | ||
125 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | ||
126 | tmp = GxICR(irq); | ||
127 | } else { | ||
128 | tmp = GxICR(irq); | ||
129 | |||
130 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | ||
131 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | ||
132 | tmp = GxICR(irq); | ||
133 | } | ||
134 | |||
135 | arch_local_irq_restore(flags); | ||
136 | #else /* CONFIG_SMP */ | ||
137 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE | GxICR_DETECT); | ||
138 | #endif /* CONFIG_SMP */ | ||
62 | } | 139 | } |
63 | 140 | ||
141 | #ifdef CONFIG_SMP | ||
142 | static int | ||
143 | mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) | ||
144 | { | ||
145 | unsigned long flags; | ||
146 | int err; | ||
147 | |||
148 | flags = arch_local_cli_save(); | ||
149 | |||
150 | /* check irq no */ | ||
151 | switch (irq) { | ||
152 | case TMJCIRQ: | ||
153 | case RESCHEDULE_IPI: | ||
154 | case CALL_FUNC_SINGLE_IPI: | ||
155 | case LOCAL_TIMER_IPI: | ||
156 | case FLUSH_CACHE_IPI: | ||
157 | case CALL_FUNCTION_NMI_IPI: | ||
158 | case GDB_NMI_IPI: | ||
159 | #ifdef CONFIG_MN10300_TTYSM0 | ||
160 | case SC0RXIRQ: | ||
161 | case SC0TXIRQ: | ||
162 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | ||
163 | case TM8IRQ: | ||
164 | #elif CONFIG_MN10300_TTYSM0_TIMER2 | ||
165 | case TM2IRQ: | ||
166 | #endif /* CONFIG_MN10300_TTYSM0_TIMER8 */ | ||
167 | #endif /* CONFIG_MN10300_TTYSM0 */ | ||
168 | |||
169 | #ifdef CONFIG_MN10300_TTYSM1 | ||
170 | case SC1RXIRQ: | ||
171 | case SC1TXIRQ: | ||
172 | #ifdef CONFIG_MN10300_TTYSM1_TIMER12 | ||
173 | case TM12IRQ: | ||
174 | #elif CONFIG_MN10300_TTYSM1_TIMER9 | ||
175 | case TM9IRQ: | ||
176 | #elif CONFIG_MN10300_TTYSM1_TIMER3 | ||
177 | case TM3IRQ: | ||
178 | #endif /* CONFIG_MN10300_TTYSM1_TIMER12 */ | ||
179 | #endif /* CONFIG_MN10300_TTYSM1 */ | ||
180 | |||
181 | #ifdef CONFIG_MN10300_TTYSM2 | ||
182 | case SC2RXIRQ: | ||
183 | case SC2TXIRQ: | ||
184 | case TM10IRQ: | ||
185 | #endif /* CONFIG_MN10300_TTYSM2 */ | ||
186 | err = -1; | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | set_bit(irq, irq_affinity_request); | ||
191 | err = 0; | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | arch_local_irq_restore(flags); | ||
196 | return err; | ||
197 | } | ||
198 | #endif /* CONFIG_SMP */ | ||
199 | |||
64 | /* | 200 | /* |
65 | * MN10300 PIC level-triggered IRQ handling. | 201 | * MN10300 PIC level-triggered IRQ handling. |
66 | * | 202 | * |
@@ -79,6 +215,9 @@ static struct irq_chip mn10300_cpu_pic_level = { | |||
79 | .mask = mn10300_cpupic_mask, | 215 | .mask = mn10300_cpupic_mask, |
80 | .mask_ack = mn10300_cpupic_mask, | 216 | .mask_ack = mn10300_cpupic_mask, |
81 | .unmask = mn10300_cpupic_unmask_clear, | 217 | .unmask = mn10300_cpupic_unmask_clear, |
218 | #ifdef CONFIG_SMP | ||
219 | .set_affinity = mn10300_cpupic_setaffinity, | ||
220 | #endif /* CONFIG_SMP */ | ||
82 | }; | 221 | }; |
83 | 222 | ||
84 | /* | 223 | /* |
@@ -94,6 +233,9 @@ static struct irq_chip mn10300_cpu_pic_edge = { | |||
94 | .mask = mn10300_cpupic_mask, | 233 | .mask = mn10300_cpupic_mask, |
95 | .mask_ack = mn10300_cpupic_mask_ack, | 234 | .mask_ack = mn10300_cpupic_mask_ack, |
96 | .unmask = mn10300_cpupic_unmask, | 235 | .unmask = mn10300_cpupic_unmask, |
236 | #ifdef CONFIG_SMP | ||
237 | .set_affinity = mn10300_cpupic_setaffinity, | ||
238 | #endif /* CONFIG_SMP */ | ||
97 | }; | 239 | }; |
98 | 240 | ||
99 | /* | 241 | /* |
@@ -111,14 +253,34 @@ void ack_bad_irq(int irq) | |||
111 | */ | 253 | */ |
112 | void set_intr_level(int irq, u16 level) | 254 | void set_intr_level(int irq, u16 level) |
113 | { | 255 | { |
114 | u16 tmp; | 256 | BUG_ON(in_interrupt()); |
115 | 257 | ||
116 | if (in_interrupt()) | 258 | __mask_and_set_icr(irq, GxICR_ENABLE, level); |
117 | BUG(); | 259 | } |
118 | 260 | ||
119 | tmp = GxICR(irq); | 261 | void mn10300_intc_set_level(unsigned int irq, unsigned int level) |
120 | GxICR(irq) = (tmp & GxICR_ENABLE) | level; | 262 | { |
121 | tmp = GxICR(irq); | 263 | set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL); |
264 | } | ||
265 | |||
266 | void mn10300_intc_clear(unsigned int irq) | ||
267 | { | ||
268 | __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT); | ||
269 | } | ||
270 | |||
271 | void mn10300_intc_set(unsigned int irq) | ||
272 | { | ||
273 | __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT); | ||
274 | } | ||
275 | |||
276 | void mn10300_intc_enable(unsigned int irq) | ||
277 | { | ||
278 | mn10300_cpupic_unmask(irq); | ||
279 | } | ||
280 | |||
281 | void mn10300_intc_disable(unsigned int irq) | ||
282 | { | ||
283 | mn10300_cpupic_mask(irq); | ||
122 | } | 284 | } |
123 | 285 | ||
124 | /* | 286 | /* |
@@ -126,7 +288,7 @@ void set_intr_level(int irq, u16 level) | |||
126 | * than before | 288 | * than before |
127 | * - see Documentation/mn10300/features.txt | 289 | * - see Documentation/mn10300/features.txt |
128 | */ | 290 | */ |
129 | void set_intr_postackable(int irq) | 291 | void mn10300_set_lateack_irq_type(int irq) |
130 | { | 292 | { |
131 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, | 293 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, |
132 | handle_level_irq); | 294 | handle_level_irq); |
@@ -147,6 +309,7 @@ void __init init_IRQ(void) | |||
147 | * interrupts */ | 309 | * interrupts */ |
148 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, | 310 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, |
149 | handle_level_irq); | 311 | handle_level_irq); |
312 | |||
150 | unit_init_IRQ(); | 313 | unit_init_IRQ(); |
151 | } | 314 | } |
152 | 315 | ||
@@ -156,6 +319,7 @@ void __init init_IRQ(void) | |||
156 | asmlinkage void do_IRQ(void) | 319 | asmlinkage void do_IRQ(void) |
157 | { | 320 | { |
158 | unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw; | 321 | unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw; |
322 | unsigned int cpu_id = smp_processor_id(); | ||
159 | int irq; | 323 | int irq; |
160 | 324 | ||
161 | sp = current_stack_pointer(); | 325 | sp = current_stack_pointer(); |
@@ -163,12 +327,14 @@ asmlinkage void do_IRQ(void) | |||
163 | 327 | ||
164 | /* make sure local_irq_enable() doesn't muck up the interrupt priority | 328 | /* make sure local_irq_enable() doesn't muck up the interrupt priority |
165 | * setting in EPSW */ | 329 | * setting in EPSW */ |
166 | old_irq_enabled_epsw = __mn10300_irq_enabled_epsw; | 330 | old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id]; |
167 | local_save_flags(epsw); | 331 | local_save_flags(epsw); |
168 | __mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw); | 332 | __mn10300_irq_enabled_epsw[cpu_id] = EPSW_IE | (EPSW_IM & epsw); |
169 | irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL; | 333 | irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL; |
170 | 334 | ||
171 | __IRQ_STAT(smp_processor_id(), __irq_count)++; | 335 | #ifdef CONFIG_MN10300_WD_TIMER |
336 | __IRQ_STAT(cpu_id, __irq_count)++; | ||
337 | #endif | ||
172 | 338 | ||
173 | irq_enter(); | 339 | irq_enter(); |
174 | 340 | ||
@@ -188,7 +354,7 @@ asmlinkage void do_IRQ(void) | |||
188 | local_irq_restore(epsw); | 354 | local_irq_restore(epsw); |
189 | } | 355 | } |
190 | 356 | ||
191 | __mn10300_irq_enabled_epsw = old_irq_enabled_epsw; | 357 | __mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw; |
192 | 358 | ||
193 | irq_exit(); | 359 | irq_exit(); |
194 | } | 360 | } |
@@ -239,11 +405,13 @@ int show_interrupts(struct seq_file *p, void *v) | |||
239 | 405 | ||
240 | /* polish off with NMI and error counters */ | 406 | /* polish off with NMI and error counters */ |
241 | case NR_IRQS: | 407 | case NR_IRQS: |
408 | #ifdef CONFIG_MN10300_WD_TIMER | ||
242 | seq_printf(p, "NMI: "); | 409 | seq_printf(p, "NMI: "); |
243 | for (j = 0; j < NR_CPUS; j++) | 410 | for (j = 0; j < NR_CPUS; j++) |
244 | if (cpu_online(j)) | 411 | if (cpu_online(j)) |
245 | seq_printf(p, "%10u ", nmi_count(j)); | 412 | seq_printf(p, "%10u ", nmi_count(j)); |
246 | seq_putc(p, '\n'); | 413 | seq_putc(p, '\n'); |
414 | #endif | ||
247 | 415 | ||
248 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | 416 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); |
249 | break; | 417 | break; |
@@ -251,3 +419,51 @@ int show_interrupts(struct seq_file *p, void *v) | |||
251 | 419 | ||
252 | return 0; | 420 | return 0; |
253 | } | 421 | } |
422 | |||
423 | #ifdef CONFIG_HOTPLUG_CPU | ||
424 | void migrate_irqs(void) | ||
425 | { | ||
426 | irq_desc_t *desc; | ||
427 | int irq; | ||
428 | unsigned int self, new; | ||
429 | unsigned long flags; | ||
430 | |||
431 | self = smp_processor_id(); | ||
432 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
433 | desc = irq_desc + irq; | ||
434 | |||
435 | if (desc->status == IRQ_PER_CPU) | ||
436 | continue; | ||
437 | |||
438 | if (cpu_isset(self, irq_desc[irq].affinity) && | ||
439 | !cpus_intersects(irq_affinity[irq], cpu_online_map)) { | ||
440 | int cpu_id; | ||
441 | cpu_id = first_cpu(cpu_online_map); | ||
442 | cpu_set(cpu_id, irq_desc[irq].affinity); | ||
443 | } | ||
444 | /* We need to operate irq_affinity_online atomically. */ | ||
445 | arch_local_cli_save(flags); | ||
446 | if (irq_affinity_online[irq] == self) { | ||
447 | u16 x, tmp; | ||
448 | |||
449 | x = CROSS_GxICR(irq, self); | ||
450 | CROSS_GxICR(irq, self) = x & GxICR_LEVEL; | ||
451 | tmp = CROSS_GxICR(irq, self); | ||
452 | |||
453 | new = any_online_cpu(irq_desc[irq].affinity); | ||
454 | irq_affinity_online[irq] = new; | ||
455 | |||
456 | CROSS_GxICR(irq, new) = | ||
457 | (x & GxICR_LEVEL) | GxICR_DETECT; | ||
458 | tmp = CROSS_GxICR(irq, new); | ||
459 | |||
460 | x &= GxICR_LEVEL | GxICR_ENABLE; | ||
461 | if (CROSS_GxICR(irq, self) & GxICR_REQUEST) | ||
462 | x |= GxICR_REQUEST | GxICR_DETECT; | ||
463 | CROSS_GxICR(irq, new) = x; | ||
464 | tmp = CROSS_GxICR(irq, new); | ||
465 | } | ||
466 | arch_local_irq_restore(flags); | ||
467 | } | ||
468 | } | ||
469 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S index 66702d256610..dfc1b6f2fa9a 100644 --- a/arch/mn10300/kernel/mn10300-serial-low.S +++ b/arch/mn10300/kernel/mn10300-serial-low.S | |||
@@ -39,7 +39,7 @@ | |||
39 | ############################################################################### | 39 | ############################################################################### |
40 | .balign L1_CACHE_BYTES | 40 | .balign L1_CACHE_BYTES |
41 | ENTRY(mn10300_serial_vdma_interrupt) | 41 | ENTRY(mn10300_serial_vdma_interrupt) |
42 | or EPSW_IE,psw # permit overriding by | 42 | # or EPSW_IE,psw # permit overriding by |
43 | # debugging interrupts | 43 | # debugging interrupts |
44 | movm [d2,d3,a2,a3,exreg0],(sp) | 44 | movm [d2,d3,a2,a3,exreg0],(sp) |
45 | 45 | ||
@@ -164,7 +164,7 @@ mnsc_vdma_tx_noint: | |||
164 | rti | 164 | rti |
165 | 165 | ||
166 | mnsc_vdma_tx_empty: | 166 | mnsc_vdma_tx_empty: |
167 | mov +(GxICR_LEVEL_1|GxICR_DETECT),d2 | 167 | mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 |
168 | movhu d2,(e3) # disable the interrupt | 168 | movhu d2,(e3) # disable the interrupt |
169 | movhu (e3),d2 # flush | 169 | movhu (e3),d2 # flush |
170 | 170 | ||
@@ -175,7 +175,7 @@ mnsc_vdma_tx_break: | |||
175 | movhu (SCxCTR,e2),d2 # turn on break mode | 175 | movhu (SCxCTR,e2),d2 # turn on break mode |
176 | or SC01CTR_BKE,d2 | 176 | or SC01CTR_BKE,d2 |
177 | movhu d2,(SCxCTR,e2) | 177 | movhu d2,(SCxCTR,e2) |
178 | mov +(GxICR_LEVEL_1|GxICR_DETECT),d2 | 178 | mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 |
179 | movhu d2,(e3) # disable transmit interrupts on this | 179 | movhu d2,(e3) # disable transmit interrupts on this |
180 | # channel | 180 | # channel |
181 | movhu (e3),d2 # flush | 181 | movhu (e3),d2 # flush |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index db509dd80565..996384dba45d 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
@@ -44,6 +44,11 @@ static const char serial_revdate[] = "2007-11-06"; | |||
44 | #include <unit/timex.h> | 44 | #include <unit/timex.h> |
45 | #include "mn10300-serial.h" | 45 | #include "mn10300-serial.h" |
46 | 46 | ||
47 | #ifdef CONFIG_SMP | ||
48 | #undef GxICR | ||
49 | #define GxICR(X) CROSS_GxICR(X, 0) | ||
50 | #endif /* CONFIG_SMP */ | ||
51 | |||
47 | #define kenter(FMT, ...) \ | 52 | #define kenter(FMT, ...) \ |
48 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | 53 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) |
49 | #define _enter(FMT, ...) \ | 54 | #define _enter(FMT, ...) \ |
@@ -57,6 +62,11 @@ static const char serial_revdate[] = "2007-11-06"; | |||
57 | #define _proto(FMT, ...) \ | 62 | #define _proto(FMT, ...) \ |
58 | no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) | 63 | no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) |
59 | 64 | ||
65 | #ifndef CODMSB | ||
66 | /* c_cflag bit meaning */ | ||
67 | #define CODMSB 004000000000 /* change Transfer bit-order */ | ||
68 | #endif | ||
69 | |||
60 | #define NR_UARTS 3 | 70 | #define NR_UARTS 3 |
61 | 71 | ||
62 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | 72 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE |
@@ -152,26 +162,35 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { | |||
152 | .name = "ttySM0", | 162 | .name = "ttySM0", |
153 | ._iobase = &SC0CTR, | 163 | ._iobase = &SC0CTR, |
154 | ._control = &SC0CTR, | 164 | ._control = &SC0CTR, |
155 | ._status = (volatile u8 *) &SC0STR, | 165 | ._status = (volatile u8 *)&SC0STR, |
156 | ._intr = &SC0ICR, | 166 | ._intr = &SC0ICR, |
157 | ._rxb = &SC0RXB, | 167 | ._rxb = &SC0RXB, |
158 | ._txb = &SC0TXB, | 168 | ._txb = &SC0TXB, |
159 | .rx_name = "ttySM0:Rx", | 169 | .rx_name = "ttySM0:Rx", |
160 | .tx_name = "ttySM0:Tx", | 170 | .tx_name = "ttySM0:Tx", |
161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | 171 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) |
162 | .tm_name = "ttySM0:Timer8", | 172 | .tm_name = "ttySM0:Timer8", |
163 | ._tmxmd = &TM8MD, | 173 | ._tmxmd = &TM8MD, |
164 | ._tmxbr = &TM8BR, | 174 | ._tmxbr = &TM8BR, |
165 | ._tmicr = &TM8ICR, | 175 | ._tmicr = &TM8ICR, |
166 | .tm_irq = TM8IRQ, | 176 | .tm_irq = TM8IRQ, |
167 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 177 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ | 178 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) |
179 | .tm_name = "ttySM0:Timer0", | ||
180 | ._tmxmd = &TM0MD, | ||
181 | ._tmxbr = (volatile u16 *)&TM0BR, | ||
182 | ._tmicr = &TM0ICR, | ||
183 | .tm_irq = TM0IRQ, | ||
184 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
185 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | ||
169 | .tm_name = "ttySM0:Timer2", | 186 | .tm_name = "ttySM0:Timer2", |
170 | ._tmxmd = &TM2MD, | 187 | ._tmxmd = &TM2MD, |
171 | ._tmxbr = (volatile u16 *) &TM2BR, | 188 | ._tmxbr = (volatile u16 *)&TM2BR, |
172 | ._tmicr = &TM2ICR, | 189 | ._tmicr = &TM2ICR, |
173 | .tm_irq = TM2IRQ, | 190 | .tm_irq = TM2IRQ, |
174 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 191 | .div_timer = MNSCx_DIV_TIMER_8BIT, |
192 | #else | ||
193 | #error "Unknown config for ttySM0" | ||
175 | #endif | 194 | #endif |
176 | .rx_irq = SC0RXIRQ, | 195 | .rx_irq = SC0RXIRQ, |
177 | .tx_irq = SC0TXIRQ, | 196 | .tx_irq = SC0TXIRQ, |
@@ -205,26 +224,35 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { | |||
205 | .name = "ttySM1", | 224 | .name = "ttySM1", |
206 | ._iobase = &SC1CTR, | 225 | ._iobase = &SC1CTR, |
207 | ._control = &SC1CTR, | 226 | ._control = &SC1CTR, |
208 | ._status = (volatile u8 *) &SC1STR, | 227 | ._status = (volatile u8 *)&SC1STR, |
209 | ._intr = &SC1ICR, | 228 | ._intr = &SC1ICR, |
210 | ._rxb = &SC1RXB, | 229 | ._rxb = &SC1RXB, |
211 | ._txb = &SC1TXB, | 230 | ._txb = &SC1TXB, |
212 | .rx_name = "ttySM1:Rx", | 231 | .rx_name = "ttySM1:Rx", |
213 | .tx_name = "ttySM1:Tx", | 232 | .tx_name = "ttySM1:Tx", |
214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 | 233 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) |
215 | .tm_name = "ttySM1:Timer9", | 234 | .tm_name = "ttySM1:Timer9", |
216 | ._tmxmd = &TM9MD, | 235 | ._tmxmd = &TM9MD, |
217 | ._tmxbr = &TM9BR, | 236 | ._tmxbr = &TM9BR, |
218 | ._tmicr = &TM9ICR, | 237 | ._tmicr = &TM9ICR, |
219 | .tm_irq = TM9IRQ, | 238 | .tm_irq = TM9IRQ, |
220 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 239 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ | 240 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) |
222 | .tm_name = "ttySM1:Timer3", | 241 | .tm_name = "ttySM1:Timer3", |
223 | ._tmxmd = &TM3MD, | 242 | ._tmxmd = &TM3MD, |
224 | ._tmxbr = (volatile u16 *) &TM3BR, | 243 | ._tmxbr = (volatile u16 *)&TM3BR, |
225 | ._tmicr = &TM3ICR, | 244 | ._tmicr = &TM3ICR, |
226 | .tm_irq = TM3IRQ, | 245 | .tm_irq = TM3IRQ, |
227 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 246 | .div_timer = MNSCx_DIV_TIMER_8BIT, |
247 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER12) | ||
248 | .tm_name = "ttySM1/Timer12", | ||
249 | ._tmxmd = &TM12MD, | ||
250 | ._tmxbr = &TM12BR, | ||
251 | ._tmicr = &TM12ICR, | ||
252 | .tm_irq = TM12IRQ, | ||
253 | .div_timer = MNSCx_DIV_TIMER_16BIT, | ||
254 | #else | ||
255 | #error "Unknown config for ttySM1" | ||
228 | #endif | 256 | #endif |
229 | .rx_irq = SC1RXIRQ, | 257 | .rx_irq = SC1RXIRQ, |
230 | .tx_irq = SC1TXIRQ, | 258 | .tx_irq = SC1TXIRQ, |
@@ -260,20 +288,45 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { | |||
260 | .uart.lock = | 288 | .uart.lock = |
261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 289 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), |
262 | .name = "ttySM2", | 290 | .name = "ttySM2", |
263 | .rx_name = "ttySM2:Rx", | ||
264 | .tx_name = "ttySM2:Tx", | ||
265 | .tm_name = "ttySM2:Timer10", | ||
266 | ._iobase = &SC2CTR, | 291 | ._iobase = &SC2CTR, |
267 | ._control = &SC2CTR, | 292 | ._control = &SC2CTR, |
268 | ._status = &SC2STR, | 293 | ._status = (volatile u8 *)&SC2STR, |
269 | ._intr = &SC2ICR, | 294 | ._intr = &SC2ICR, |
270 | ._rxb = &SC2RXB, | 295 | ._rxb = &SC2RXB, |
271 | ._txb = &SC2TXB, | 296 | ._txb = &SC2TXB, |
297 | .rx_name = "ttySM2:Rx", | ||
298 | .tx_name = "ttySM2:Tx", | ||
299 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | ||
300 | .tm_name = "ttySM2/Timer10", | ||
272 | ._tmxmd = &TM10MD, | 301 | ._tmxmd = &TM10MD, |
273 | ._tmxbr = &TM10BR, | 302 | ._tmxbr = &TM10BR, |
274 | ._tmicr = &TM10ICR, | 303 | ._tmicr = &TM10ICR, |
275 | .tm_irq = TM10IRQ, | 304 | .tm_irq = TM10IRQ, |
276 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 305 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
306 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER9) | ||
307 | .tm_name = "ttySM2/Timer9", | ||
308 | ._tmxmd = &TM9MD, | ||
309 | ._tmxbr = &TM9BR, | ||
310 | ._tmicr = &TM9ICR, | ||
311 | .tm_irq = TM9IRQ, | ||
312 | .div_timer = MNSCx_DIV_TIMER_16BIT, | ||
313 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | ||
314 | .tm_name = "ttySM2/Timer1", | ||
315 | ._tmxmd = &TM1MD, | ||
316 | ._tmxbr = (volatile u16 *)&TM1BR, | ||
317 | ._tmicr = &TM1ICR, | ||
318 | .tm_irq = TM1IRQ, | ||
319 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
320 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | ||
321 | .tm_name = "ttySM2/Timer3", | ||
322 | ._tmxmd = &TM3MD, | ||
323 | ._tmxbr = (volatile u16 *)&TM3BR, | ||
324 | ._tmicr = &TM3ICR, | ||
325 | .tm_irq = TM3IRQ, | ||
326 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
327 | #else | ||
328 | #error "Unknown config for ttySM2" | ||
329 | #endif | ||
277 | .rx_irq = SC2RXIRQ, | 330 | .rx_irq = SC2RXIRQ, |
278 | .tx_irq = SC2TXIRQ, | 331 | .tx_irq = SC2TXIRQ, |
279 | .rx_icr = &GxICR(SC2RXIRQ), | 332 | .rx_icr = &GxICR(SC2RXIRQ), |
@@ -322,9 +375,13 @@ struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = { | |||
322 | */ | 375 | */ |
323 | static void mn10300_serial_mask_ack(unsigned int irq) | 376 | static void mn10300_serial_mask_ack(unsigned int irq) |
324 | { | 377 | { |
378 | unsigned long flags; | ||
325 | u16 tmp; | 379 | u16 tmp; |
380 | |||
381 | flags = arch_local_cli_save(); | ||
326 | GxICR(irq) = GxICR_LEVEL_6; | 382 | GxICR(irq) = GxICR_LEVEL_6; |
327 | tmp = GxICR(irq); /* flush write buffer */ | 383 | tmp = GxICR(irq); /* flush write buffer */ |
384 | arch_local_irq_restore(flags); | ||
328 | } | 385 | } |
329 | 386 | ||
330 | static void mn10300_serial_nop(unsigned int irq) | 387 | static void mn10300_serial_nop(unsigned int irq) |
@@ -348,23 +405,36 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS]; | |||
348 | 405 | ||
349 | static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) | 406 | static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) |
350 | { | 407 | { |
408 | unsigned long flags; | ||
351 | u16 x; | 409 | u16 x; |
352 | *port->tx_icr = GxICR_LEVEL_1 | GxICR_DETECT; | 410 | |
411 | flags = arch_local_cli_save(); | ||
412 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
353 | x = *port->tx_icr; | 413 | x = *port->tx_icr; |
414 | arch_local_irq_restore(flags); | ||
354 | } | 415 | } |
355 | 416 | ||
356 | static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) | 417 | static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) |
357 | { | 418 | { |
419 | unsigned long flags; | ||
358 | u16 x; | 420 | u16 x; |
359 | *port->tx_icr = GxICR_LEVEL_1 | GxICR_ENABLE; | 421 | |
422 | flags = arch_local_cli_save(); | ||
423 | *port->tx_icr = | ||
424 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; | ||
360 | x = *port->tx_icr; | 425 | x = *port->tx_icr; |
426 | arch_local_irq_restore(flags); | ||
361 | } | 427 | } |
362 | 428 | ||
363 | static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) | 429 | static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) |
364 | { | 430 | { |
431 | unsigned long flags; | ||
365 | u16 x; | 432 | u16 x; |
366 | *port->rx_icr = GxICR_LEVEL_1 | GxICR_DETECT; | 433 | |
434 | flags = arch_local_cli_save(); | ||
435 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
367 | x = *port->rx_icr; | 436 | x = *port->rx_icr; |
437 | arch_local_irq_restore(flags); | ||
368 | } | 438 | } |
369 | 439 | ||
370 | /* | 440 | /* |
@@ -650,7 +720,7 @@ static unsigned int mn10300_serial_tx_empty(struct uart_port *_port) | |||
650 | static void mn10300_serial_set_mctrl(struct uart_port *_port, | 720 | static void mn10300_serial_set_mctrl(struct uart_port *_port, |
651 | unsigned int mctrl) | 721 | unsigned int mctrl) |
652 | { | 722 | { |
653 | struct mn10300_serial_port *port = | 723 | struct mn10300_serial_port *port __attribute__ ((unused)) = |
654 | container_of(_port, struct mn10300_serial_port, uart); | 724 | container_of(_port, struct mn10300_serial_port, uart); |
655 | 725 | ||
656 | _enter("%s,%x", port->name, mctrl); | 726 | _enter("%s,%x", port->name, mctrl); |
@@ -706,6 +776,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port) | |||
706 | UART_XMIT_SIZE)); | 776 | UART_XMIT_SIZE)); |
707 | 777 | ||
708 | /* kick the virtual DMA controller */ | 778 | /* kick the virtual DMA controller */ |
779 | arch_local_cli(); | ||
709 | x = *port->tx_icr; | 780 | x = *port->tx_icr; |
710 | x |= GxICR_ENABLE; | 781 | x |= GxICR_ENABLE; |
711 | 782 | ||
@@ -716,10 +787,14 @@ static void mn10300_serial_start_tx(struct uart_port *_port) | |||
716 | 787 | ||
717 | _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", | 788 | _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", |
718 | *port->_control, *port->_intr, *port->_status, | 789 | *port->_control, *port->_intr, *port->_status, |
719 | *port->_tmxmd, *port->_tmxbr, *port->tx_icr); | 790 | *port->_tmxmd, |
791 | (port->div_timer == MNSCx_DIV_TIMER_8BIT) ? | ||
792 | *(volatile u8 *)port->_tmxbr : *port->_tmxbr, | ||
793 | *port->tx_icr); | ||
720 | 794 | ||
721 | *port->tx_icr = x; | 795 | *port->tx_icr = x; |
722 | x = *port->tx_icr; | 796 | x = *port->tx_icr; |
797 | arch_local_sti(); | ||
723 | } | 798 | } |
724 | 799 | ||
725 | /* | 800 | /* |
@@ -842,8 +917,10 @@ static int mn10300_serial_startup(struct uart_port *_port) | |||
842 | pint->port = port; | 917 | pint->port = port; |
843 | pint->vdma = mn10300_serial_vdma_tx_handler; | 918 | pint->vdma = mn10300_serial_vdma_tx_handler; |
844 | 919 | ||
845 | set_intr_level(port->rx_irq, GxICR_LEVEL_1); | 920 | set_intr_level(port->rx_irq, |
846 | set_intr_level(port->tx_irq, GxICR_LEVEL_1); | 921 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); |
922 | set_intr_level(port->tx_irq, | ||
923 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | ||
847 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); | 924 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); |
848 | 925 | ||
849 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | 926 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, |
@@ -876,6 +953,7 @@ error: | |||
876 | */ | 953 | */ |
877 | static void mn10300_serial_shutdown(struct uart_port *_port) | 954 | static void mn10300_serial_shutdown(struct uart_port *_port) |
878 | { | 955 | { |
956 | u16 x; | ||
879 | struct mn10300_serial_port *port = | 957 | struct mn10300_serial_port *port = |
880 | container_of(_port, struct mn10300_serial_port, uart); | 958 | container_of(_port, struct mn10300_serial_port, uart); |
881 | 959 | ||
@@ -897,8 +975,12 @@ static void mn10300_serial_shutdown(struct uart_port *_port) | |||
897 | free_irq(port->rx_irq, port); | 975 | free_irq(port->rx_irq, port); |
898 | free_irq(port->tx_irq, port); | 976 | free_irq(port->tx_irq, port); |
899 | 977 | ||
900 | *port->rx_icr = GxICR_LEVEL_1; | 978 | arch_local_cli(); |
901 | *port->tx_icr = GxICR_LEVEL_1; | 979 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); |
980 | x = *port->rx_icr; | ||
981 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
982 | x = *port->tx_icr; | ||
983 | arch_local_sti(); | ||
902 | } | 984 | } |
903 | 985 | ||
904 | /* | 986 | /* |
@@ -947,11 +1029,66 @@ static void mn10300_serial_change_speed(struct mn10300_serial_port *port, | |||
947 | /* Determine divisor based on baud rate */ | 1029 | /* Determine divisor based on baud rate */ |
948 | battempt = 0; | 1030 | battempt = 0; |
949 | 1031 | ||
950 | if (div_timer == MNSCx_DIV_TIMER_16BIT) | 1032 | switch (port->uart.line) { |
951 | scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8 | 1033 | #ifdef CONFIG_MN10300_TTYSM0 |
952 | * == SC2CTR_CK_TM10UFLOW) */ | 1034 | case 0: /* ttySM0 */ |
953 | else if (div_timer == MNSCx_DIV_TIMER_8BIT) | 1035 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) |
1036 | scxctr |= SC0CTR_CK_TM8UFLOW_8; | ||
1037 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) | ||
1038 | scxctr |= SC0CTR_CK_TM0UFLOW_8; | ||
1039 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | ||
954 | scxctr |= SC0CTR_CK_TM2UFLOW_8; | 1040 | scxctr |= SC0CTR_CK_TM2UFLOW_8; |
1041 | #else | ||
1042 | #error "Unknown config for ttySM0" | ||
1043 | #endif | ||
1044 | break; | ||
1045 | #endif /* CONFIG_MN10300_TTYSM0 */ | ||
1046 | |||
1047 | #ifdef CONFIG_MN10300_TTYSM1 | ||
1048 | case 1: /* ttySM1 */ | ||
1049 | #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) | ||
1050 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) | ||
1051 | scxctr |= SC1CTR_CK_TM9UFLOW_8; | ||
1052 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) | ||
1053 | scxctr |= SC1CTR_CK_TM3UFLOW_8; | ||
1054 | #else | ||
1055 | #error "Unknown config for ttySM1" | ||
1056 | #endif | ||
1057 | #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
1058 | #if defined(CONFIG_MN10300_TTYSM1_TIMER12) | ||
1059 | scxctr |= SC1CTR_CK_TM12UFLOW_8; | ||
1060 | #else | ||
1061 | #error "Unknown config for ttySM1" | ||
1062 | #endif | ||
1063 | #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
1064 | break; | ||
1065 | #endif /* CONFIG_MN10300_TTYSM1 */ | ||
1066 | |||
1067 | #ifdef CONFIG_MN10300_TTYSM2 | ||
1068 | case 2: /* ttySM2 */ | ||
1069 | #if defined(CONFIG_AM33_2) | ||
1070 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | ||
1071 | scxctr |= SC2CTR_CK_TM10UFLOW; | ||
1072 | #else | ||
1073 | #error "Unknown config for ttySM2" | ||
1074 | #endif | ||
1075 | #else /* CONFIG_AM33_2 */ | ||
1076 | #if defined(CONFIG_MN10300_TTYSM2_TIMER9) | ||
1077 | scxctr |= SC2CTR_CK_TM9UFLOW_8; | ||
1078 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | ||
1079 | scxctr |= SC2CTR_CK_TM1UFLOW_8; | ||
1080 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | ||
1081 | scxctr |= SC2CTR_CK_TM3UFLOW_8; | ||
1082 | #else | ||
1083 | #error "Unknown config for ttySM2" | ||
1084 | #endif | ||
1085 | #endif /* CONFIG_AM33_2 */ | ||
1086 | break; | ||
1087 | #endif /* CONFIG_MN10300_TTYSM2 */ | ||
1088 | |||
1089 | default: | ||
1090 | break; | ||
1091 | } | ||
955 | 1092 | ||
956 | try_alternative: | 1093 | try_alternative: |
957 | baud = uart_get_baud_rate(&port->uart, new, old, 0, | 1094 | baud = uart_get_baud_rate(&port->uart, new, old, 0, |
@@ -1195,6 +1332,12 @@ static void mn10300_serial_set_termios(struct uart_port *_port, | |||
1195 | ctr &= ~SC2CTR_TWE; | 1332 | ctr &= ~SC2CTR_TWE; |
1196 | *port->_control = ctr; | 1333 | *port->_control = ctr; |
1197 | } | 1334 | } |
1335 | |||
1336 | /* change Transfer bit-order (LSB/MSB) */ | ||
1337 | if (new->c_cflag & CODMSB) | ||
1338 | *port->_control |= SC01CTR_OD_MSBFIRST; /* MSB MODE */ | ||
1339 | else | ||
1340 | *port->_control &= ~SC01CTR_OD_MSBFIRST; /* LSB MODE */ | ||
1198 | } | 1341 | } |
1199 | 1342 | ||
1200 | /* | 1343 | /* |
@@ -1302,11 +1445,16 @@ static int __init mn10300_serial_init(void) | |||
1302 | printk(KERN_INFO "%s version %s (%s)\n", | 1445 | printk(KERN_INFO "%s version %s (%s)\n", |
1303 | serial_name, serial_version, serial_revdate); | 1446 | serial_name, serial_version, serial_revdate); |
1304 | 1447 | ||
1305 | #ifdef CONFIG_MN10300_TTYSM2 | 1448 | #if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2) |
1306 | SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */ | 1449 | { |
1450 | int tmp; | ||
1451 | SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */ | ||
1452 | tmp = SC2TIM; | ||
1453 | } | ||
1307 | #endif | 1454 | #endif |
1308 | 1455 | ||
1309 | set_intr_stub(EXCEP_IRQ_LEVEL1, mn10300_serial_vdma_interrupt); | 1456 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL), |
1457 | mn10300_serial_vdma_interrupt); | ||
1310 | 1458 | ||
1311 | ret = uart_register_driver(&mn10300_serial_driver); | 1459 | ret = uart_register_driver(&mn10300_serial_driver); |
1312 | if (!ret) { | 1460 | if (!ret) { |
@@ -1366,9 +1514,11 @@ static void mn10300_serial_console_write(struct console *co, | |||
1366 | port = mn10300_serial_ports[co->index]; | 1514 | port = mn10300_serial_ports[co->index]; |
1367 | 1515 | ||
1368 | /* firstly hijack the serial port from the "virtual DMA" controller */ | 1516 | /* firstly hijack the serial port from the "virtual DMA" controller */ |
1517 | arch_local_cli(); | ||
1369 | txicr = *port->tx_icr; | 1518 | txicr = *port->tx_icr; |
1370 | *port->tx_icr = GxICR_LEVEL_1; | 1519 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); |
1371 | tmp = *port->tx_icr; | 1520 | tmp = *port->tx_icr; |
1521 | arch_local_sti(); | ||
1372 | 1522 | ||
1373 | /* the transmitter may be disabled */ | 1523 | /* the transmitter may be disabled */ |
1374 | scxctr = *port->_control; | 1524 | scxctr = *port->_control; |
@@ -1422,8 +1572,10 @@ static void mn10300_serial_console_write(struct console *co, | |||
1422 | if (!(scxctr & SC01CTR_TXE)) | 1572 | if (!(scxctr & SC01CTR_TXE)) |
1423 | *port->_control = scxctr; | 1573 | *port->_control = scxctr; |
1424 | 1574 | ||
1575 | arch_local_cli(); | ||
1425 | *port->tx_icr = txicr; | 1576 | *port->tx_icr = txicr; |
1426 | tmp = *port->tx_icr; | 1577 | tmp = *port->tx_icr; |
1578 | arch_local_sti(); | ||
1427 | } | 1579 | } |
1428 | 1580 | ||
1429 | /* | 1581 | /* |
diff --git a/arch/mn10300/kernel/mn10300-watchdog-low.S b/arch/mn10300/kernel/mn10300-watchdog-low.S index 996244745cca..f2f5c9cfaabd 100644 --- a/arch/mn10300/kernel/mn10300-watchdog-low.S +++ b/arch/mn10300/kernel/mn10300-watchdog-low.S | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/intctl-regs.h> | 16 | #include <asm/intctl-regs.h> |
17 | #include <asm/timer-regs.h> | 17 | #include <asm/timer-regs.h> |
18 | #include <asm/frame.inc> | 18 | #include <asm/frame.inc> |
19 | #include <linux/threads.h> | ||
19 | 20 | ||
20 | .text | 21 | .text |
21 | 22 | ||
@@ -53,7 +54,13 @@ watchdog_handler: | |||
53 | .type touch_nmi_watchdog,@function | 54 | .type touch_nmi_watchdog,@function |
54 | touch_nmi_watchdog: | 55 | touch_nmi_watchdog: |
55 | clr d0 | 56 | clr d0 |
56 | mov d0,(watchdog_alert_counter) | 57 | clr d1 |
58 | mov watchdog_alert_counter, a0 | ||
59 | setlb | ||
60 | mov d0, (a0+) | ||
61 | inc d1 | ||
62 | cmp NR_CPUS, d1 | ||
63 | lne | ||
57 | ret [],0 | 64 | ret [],0 |
58 | 65 | ||
59 | .size touch_nmi_watchdog,.-touch_nmi_watchdog | 66 | .size touch_nmi_watchdog,.-touch_nmi_watchdog |
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c index f362d9d138f1..965dd61656c3 100644 --- a/arch/mn10300/kernel/mn10300-watchdog.c +++ b/arch/mn10300/kernel/mn10300-watchdog.c | |||
@@ -30,7 +30,7 @@ | |||
30 | static DEFINE_SPINLOCK(watchdog_print_lock); | 30 | static DEFINE_SPINLOCK(watchdog_print_lock); |
31 | static unsigned int watchdog; | 31 | static unsigned int watchdog; |
32 | static unsigned int watchdog_hz = 1; | 32 | static unsigned int watchdog_hz = 1; |
33 | unsigned int watchdog_alert_counter; | 33 | unsigned int watchdog_alert_counter[NR_CPUS]; |
34 | 34 | ||
35 | EXPORT_SYMBOL(touch_nmi_watchdog); | 35 | EXPORT_SYMBOL(touch_nmi_watchdog); |
36 | 36 | ||
@@ -39,9 +39,6 @@ EXPORT_SYMBOL(touch_nmi_watchdog); | |||
39 | * is to check its timer makes IRQ counts. If they are not | 39 | * is to check its timer makes IRQ counts. If they are not |
40 | * changing then that CPU has some problem. | 40 | * changing then that CPU has some problem. |
41 | * | 41 | * |
42 | * as these watchdog NMI IRQs are generated on every CPU, we only | ||
43 | * have to check the current processor. | ||
44 | * | ||
45 | * since NMIs dont listen to _any_ locks, we have to be extremely | 42 | * since NMIs dont listen to _any_ locks, we have to be extremely |
46 | * careful not to rely on unsafe variables. The printk might lock | 43 | * careful not to rely on unsafe variables. The printk might lock |
47 | * up though, so we have to break up any console locks first ... | 44 | * up though, so we have to break up any console locks first ... |
@@ -69,8 +66,8 @@ int __init check_watchdog(void) | |||
69 | 66 | ||
70 | printk(KERN_INFO "OK.\n"); | 67 | printk(KERN_INFO "OK.\n"); |
71 | 68 | ||
72 | /* now that we know it works we can reduce NMI frequency to | 69 | /* now that we know it works we can reduce NMI frequency to something |
73 | * something more reasonable; makes a difference in some configs | 70 | * more reasonable; makes a difference in some configs |
74 | */ | 71 | */ |
75 | watchdog_hz = 1; | 72 | watchdog_hz = 1; |
76 | 73 | ||
@@ -121,15 +118,22 @@ void __init watchdog_go(void) | |||
121 | } | 118 | } |
122 | } | 119 | } |
123 | 120 | ||
121 | #ifdef CONFIG_SMP | ||
122 | static void watchdog_dump_register(void *dummy) | ||
123 | { | ||
124 | printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID); | ||
125 | show_registers(__frame); | ||
126 | } | ||
127 | #endif | ||
128 | |||
124 | asmlinkage | 129 | asmlinkage |
125 | void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | 130 | void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) |
126 | { | 131 | { |
127 | |||
128 | /* | 132 | /* |
129 | * Since current-> is always on the stack, and we always switch | 133 | * Since current-> is always on the stack, and we always switch |
130 | * the stack NMI-atomically, it's safe to use smp_processor_id(). | 134 | * the stack NMI-atomically, it's safe to use smp_processor_id(). |
131 | */ | 135 | */ |
132 | int sum, cpu = smp_processor_id(); | 136 | int sum, cpu; |
133 | int irq = NMIIRQ; | 137 | int irq = NMIIRQ; |
134 | u8 wdt, tmp; | 138 | u8 wdt, tmp; |
135 | 139 | ||
@@ -138,43 +142,61 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | |||
138 | tmp = WDCTR; | 142 | tmp = WDCTR; |
139 | NMICR = NMICR_WDIF; | 143 | NMICR = NMICR_WDIF; |
140 | 144 | ||
141 | nmi_count(cpu)++; | 145 | nmi_count(smp_processor_id())++; |
142 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 146 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); |
143 | sum = irq_stat[cpu].__irq_count; | 147 | |
144 | 148 | for_each_online_cpu(cpu) { | |
145 | if (last_irq_sums[cpu] == sum) { | 149 | |
146 | /* | 150 | sum = irq_stat[cpu].__irq_count; |
147 | * Ayiee, looks like this CPU is stuck ... | 151 | |
148 | * wait a few IRQs (5 seconds) before doing the oops ... | 152 | if ((last_irq_sums[cpu] == sum) |
149 | */ | 153 | #if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP) |
150 | watchdog_alert_counter++; | 154 | && !(CHK_GDBSTUB_BUSY() |
151 | if (watchdog_alert_counter == 5 * watchdog_hz) { | 155 | || atomic_read(&cpu_doing_single_step)) |
152 | spin_lock(&watchdog_print_lock); | 156 | #endif |
157 | ) { | ||
153 | /* | 158 | /* |
154 | * We are in trouble anyway, lets at least try | 159 | * Ayiee, looks like this CPU is stuck ... |
155 | * to get a message out. | 160 | * wait a few IRQs (5 seconds) before doing the oops ... |
156 | */ | 161 | */ |
157 | bust_spinlocks(1); | 162 | watchdog_alert_counter[cpu]++; |
158 | printk(KERN_ERR | 163 | if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) { |
159 | "NMI Watchdog detected LOCKUP on CPU%d," | 164 | spin_lock(&watchdog_print_lock); |
160 | " pc %08lx, registers:\n", | 165 | /* |
161 | cpu, regs->pc); | 166 | * We are in trouble anyway, lets at least try |
162 | show_registers(regs); | 167 | * to get a message out. |
163 | printk("console shuts up ...\n"); | 168 | */ |
164 | console_silent(); | 169 | bust_spinlocks(1); |
165 | spin_unlock(&watchdog_print_lock); | 170 | printk(KERN_ERR |
166 | bust_spinlocks(0); | 171 | "NMI Watchdog detected LOCKUP on CPU%d," |
172 | " pc %08lx, registers:\n", | ||
173 | cpu, regs->pc); | ||
174 | #ifdef CONFIG_SMP | ||
175 | printk(KERN_ERR | ||
176 | "--- Register Dump (CPU%d) ---\n", | ||
177 | CPUID); | ||
178 | #endif | ||
179 | show_registers(regs); | ||
180 | #ifdef CONFIG_SMP | ||
181 | smp_nmi_call_function(watchdog_dump_register, | ||
182 | NULL, 1); | ||
183 | #endif | ||
184 | printk(KERN_NOTICE "console shuts up ...\n"); | ||
185 | console_silent(); | ||
186 | spin_unlock(&watchdog_print_lock); | ||
187 | bust_spinlocks(0); | ||
167 | #ifdef CONFIG_GDBSTUB | 188 | #ifdef CONFIG_GDBSTUB |
168 | if (gdbstub_busy) | 189 | if (CHK_GDBSTUB_BUSY_AND_ACTIVE()) |
169 | gdbstub_exception(regs, excep); | 190 | gdbstub_exception(regs, excep); |
170 | else | 191 | else |
171 | gdbstub_intercept(regs, excep); | 192 | gdbstub_intercept(regs, excep); |
172 | #endif | 193 | #endif |
173 | do_exit(SIGSEGV); | 194 | do_exit(SIGSEGV); |
195 | } | ||
196 | } else { | ||
197 | last_irq_sums[cpu] = sum; | ||
198 | watchdog_alert_counter[cpu] = 0; | ||
174 | } | 199 | } |
175 | } else { | ||
176 | last_irq_sums[cpu] = sum; | ||
177 | watchdog_alert_counter = 0; | ||
178 | } | 200 | } |
179 | 201 | ||
180 | WDCTR = wdt | WDCTR_WDRST; | 202 | WDCTR = wdt | WDCTR_WDRST; |
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 243e33cd874b..b2e85ed73a54 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
@@ -57,6 +57,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
57 | void (*pm_power_off)(void); | 57 | void (*pm_power_off)(void); |
58 | EXPORT_SYMBOL(pm_power_off); | 58 | EXPORT_SYMBOL(pm_power_off); |
59 | 59 | ||
60 | #if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU) | ||
60 | /* | 61 | /* |
61 | * we use this if we don't have any better idle routine | 62 | * we use this if we don't have any better idle routine |
62 | */ | 63 | */ |
@@ -69,6 +70,35 @@ static void default_idle(void) | |||
69 | local_irq_enable(); | 70 | local_irq_enable(); |
70 | } | 71 | } |
71 | 72 | ||
73 | #else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
74 | /* | ||
75 | * On SMP it's slightly faster (but much more power-consuming!) | ||
76 | * to poll the ->work.need_resched flag instead of waiting for the | ||
77 | * cross-CPU IPI to arrive. Use this option with caution. | ||
78 | */ | ||
79 | static inline void poll_idle(void) | ||
80 | { | ||
81 | int oldval; | ||
82 | |||
83 | local_irq_enable(); | ||
84 | |||
85 | /* | ||
86 | * Deal with another CPU just having chosen a thread to | ||
87 | * run here: | ||
88 | */ | ||
89 | oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); | ||
90 | |||
91 | if (!oldval) { | ||
92 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
93 | while (!need_resched()) | ||
94 | cpu_relax(); | ||
95 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
96 | } else { | ||
97 | set_need_resched(); | ||
98 | } | ||
99 | } | ||
100 | #endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
101 | |||
72 | /* | 102 | /* |
73 | * the idle thread | 103 | * the idle thread |
74 | * - there's no useful work to be done, so just try to conserve power and have | 104 | * - there's no useful work to be done, so just try to conserve power and have |
@@ -77,8 +107,6 @@ static void default_idle(void) | |||
77 | */ | 107 | */ |
78 | void cpu_idle(void) | 108 | void cpu_idle(void) |
79 | { | 109 | { |
80 | int cpu = smp_processor_id(); | ||
81 | |||
82 | /* endless idle loop with no priority at all */ | 110 | /* endless idle loop with no priority at all */ |
83 | for (;;) { | 111 | for (;;) { |
84 | while (!need_resched()) { | 112 | while (!need_resched()) { |
@@ -86,8 +114,13 @@ void cpu_idle(void) | |||
86 | 114 | ||
87 | smp_rmb(); | 115 | smp_rmb(); |
88 | idle = pm_idle; | 116 | idle = pm_idle; |
89 | if (!idle) | 117 | if (!idle) { |
118 | #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) | ||
119 | idle = poll_idle; | ||
120 | #else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | ||
90 | idle = default_idle; | 121 | idle = default_idle; |
122 | #endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | ||
123 | } | ||
91 | idle(); | 124 | idle(); |
92 | } | 125 | } |
93 | 126 | ||
@@ -233,7 +266,7 @@ int copy_thread(unsigned long clone_flags, | |||
233 | } | 266 | } |
234 | 267 | ||
235 | /* set up things up so the scheduler can start the new task */ | 268 | /* set up things up so the scheduler can start the new task */ |
236 | p->thread.__frame = c_kregs; | 269 | p->thread.frame = c_kregs; |
237 | p->thread.a3 = (unsigned long) c_kregs; | 270 | p->thread.a3 = (unsigned long) c_kregs; |
238 | p->thread.sp = c_ksp; | 271 | p->thread.sp = c_ksp; |
239 | p->thread.pc = (unsigned long) ret_from_fork; | 272 | p->thread.pc = (unsigned long) ret_from_fork; |
diff --git a/arch/mn10300/kernel/profile.c b/arch/mn10300/kernel/profile.c index 20d7d0306b16..4f342f75d00c 100644 --- a/arch/mn10300/kernel/profile.c +++ b/arch/mn10300/kernel/profile.c | |||
@@ -41,7 +41,7 @@ static __init int profile_init(void) | |||
41 | tmp = TM11ICR; | 41 | tmp = TM11ICR; |
42 | 42 | ||
43 | printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n", | 43 | printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n", |
44 | mn10300_ioclk / 8 / (TM11BR + 1)); | 44 | MN10300_IOCLK / 8 / (TM11BR + 1)); |
45 | printk(KERN_INFO "Profile histogram stored %p-%p\n", | 45 | printk(KERN_INFO "Profile histogram stored %p-%p\n", |
46 | prof_buffer, (u8 *)(prof_buffer + prof_len) - 1); | 46 | prof_buffer, (u8 *)(prof_buffer + prof_len) - 1); |
47 | 47 | ||
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c index 4eef0e7224f6..e9e20f9a4dd3 100644 --- a/arch/mn10300/kernel/rtc.c +++ b/arch/mn10300/kernel/rtc.c | |||
@@ -20,18 +20,22 @@ | |||
20 | DEFINE_SPINLOCK(rtc_lock); | 20 | DEFINE_SPINLOCK(rtc_lock); |
21 | EXPORT_SYMBOL(rtc_lock); | 21 | EXPORT_SYMBOL(rtc_lock); |
22 | 22 | ||
23 | /* time for RTC to update itself in ioclks */ | 23 | /* |
24 | static unsigned long mn10300_rtc_update_period; | 24 | * Read the current RTC time |
25 | 25 | */ | |
26 | void read_persistent_clock(struct timespec *ts) | 26 | void read_persistent_clock(struct timespec *ts) |
27 | { | 27 | { |
28 | struct rtc_time tm; | 28 | struct rtc_time tm; |
29 | 29 | ||
30 | get_rtc_time(&tm); | 30 | get_rtc_time(&tm); |
31 | 31 | ||
32 | ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
33 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
34 | ts->tv_nsec = 0; | 32 | ts->tv_nsec = 0; |
33 | ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
34 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
35 | |||
36 | /* if rtc is way off in the past, set something reasonable */ | ||
37 | if (ts->tv_sec < 0) | ||
38 | ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0); | ||
35 | } | 39 | } |
36 | 40 | ||
37 | /* | 41 | /* |
@@ -115,39 +119,14 @@ int update_persistent_clock(struct timespec now) | |||
115 | */ | 119 | */ |
116 | void __init calibrate_clock(void) | 120 | void __init calibrate_clock(void) |
117 | { | 121 | { |
118 | unsigned long count0, counth, count1; | ||
119 | unsigned char status; | 122 | unsigned char status; |
120 | 123 | ||
121 | /* make sure the RTC is running and is set to operate in 24hr mode */ | 124 | /* make sure the RTC is running and is set to operate in 24hr mode */ |
122 | status = RTSRC; | 125 | status = RTSRC; |
123 | RTCRB |= RTCRB_SET; | 126 | RTCRB |= RTCRB_SET; |
124 | RTCRB |= RTCRB_TM_24HR; | 127 | RTCRB |= RTCRB_TM_24HR; |
128 | RTCRB &= ~RTCRB_DM_BINARY; | ||
125 | RTCRA |= RTCRA_DVR; | 129 | RTCRA |= RTCRA_DVR; |
126 | RTCRA &= ~RTCRA_DVR; | 130 | RTCRA &= ~RTCRA_DVR; |
127 | RTCRB &= ~RTCRB_SET; | 131 | RTCRB &= ~RTCRB_SET; |
128 | |||
129 | /* work out the clock speed by counting clock cycles between ends of | ||
130 | * the RTC update cycle - track the RTC through one complete update | ||
131 | * cycle (1 second) | ||
132 | */ | ||
133 | startup_timestamp_counter(); | ||
134 | |||
135 | while (!(RTCRA & RTCRA_UIP)) {} | ||
136 | while ((RTCRA & RTCRA_UIP)) {} | ||
137 | |||
138 | count0 = TMTSCBC; | ||
139 | |||
140 | while (!(RTCRA & RTCRA_UIP)) {} | ||
141 | |||
142 | counth = TMTSCBC; | ||
143 | |||
144 | while ((RTCRA & RTCRA_UIP)) {} | ||
145 | |||
146 | count1 = TMTSCBC; | ||
147 | |||
148 | shutdown_timestamp_counter(); | ||
149 | |||
150 | MN10300_TSCCLK = count0 - count1; /* the timers count down */ | ||
151 | mn10300_rtc_update_period = counth - count1; | ||
152 | MN10300_TSC_PER_HZ = MN10300_TSCCLK / HZ; | ||
153 | } | 132 | } |
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c index d464affcba0e..12514570ed5d 100644 --- a/arch/mn10300/kernel/setup.c +++ b/arch/mn10300/kernel/setup.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/cpu.h> | ||
25 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
26 | #include <linux/console.h> | 27 | #include <linux/console.h> |
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
@@ -30,7 +31,6 @@ | |||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
32 | #include <proc/proc.h> | 33 | #include <proc/proc.h> |
33 | #include <asm/busctl-regs.h> | ||
34 | #include <asm/fpu.h> | 34 | #include <asm/fpu.h> |
35 | #include <asm/sections.h> | 35 | #include <asm/sections.h> |
36 | 36 | ||
@@ -64,11 +64,13 @@ unsigned long memory_size; | |||
64 | struct thread_info *__current_ti = &init_thread_union.thread_info; | 64 | struct thread_info *__current_ti = &init_thread_union.thread_info; |
65 | struct task_struct *__current = &init_task; | 65 | struct task_struct *__current = &init_task; |
66 | 66 | ||
67 | #define mn10300_known_cpus 3 | 67 | #define mn10300_known_cpus 5 |
68 | static const char *const mn10300_cputypes[] = { | 68 | static const char *const mn10300_cputypes[] = { |
69 | "am33v1", | 69 | "am33-1", |
70 | "am33v2", | 70 | "am33-2", |
71 | "am34v1", | 71 | "am34-1", |
72 | "am33-3", | ||
73 | "am34-2", | ||
72 | "unknown" | 74 | "unknown" |
73 | }; | 75 | }; |
74 | 76 | ||
@@ -123,6 +125,7 @@ void __init setup_arch(char **cmdline_p) | |||
123 | 125 | ||
124 | cpu_init(); | 126 | cpu_init(); |
125 | unit_setup(); | 127 | unit_setup(); |
128 | smp_init_cpus(); | ||
126 | parse_mem_cmdline(cmdline_p); | 129 | parse_mem_cmdline(cmdline_p); |
127 | 130 | ||
128 | init_mm.start_code = (unsigned long)&_text; | 131 | init_mm.start_code = (unsigned long)&_text; |
@@ -179,7 +182,6 @@ void __init setup_arch(char **cmdline_p) | |||
179 | void __init cpu_init(void) | 182 | void __init cpu_init(void) |
180 | { | 183 | { |
181 | unsigned long cpurev = CPUREV, type; | 184 | unsigned long cpurev = CPUREV, type; |
182 | unsigned long base, size; | ||
183 | 185 | ||
184 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | 186 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; |
185 | if (type > mn10300_known_cpus) | 187 | if (type > mn10300_known_cpus) |
@@ -189,47 +191,46 @@ void __init cpu_init(void) | |||
189 | mn10300_cputypes[type], | 191 | mn10300_cputypes[type], |
190 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); | 192 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); |
191 | 193 | ||
192 | /* determine the memory size and base from the memory controller regs */ | 194 | get_mem_info(&phys_memory_base, &memory_size); |
193 | memory_size = 0; | 195 | phys_memory_end = phys_memory_base + memory_size; |
194 | |||
195 | base = SDBASE(0); | ||
196 | if (base & SDBASE_CE) { | ||
197 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
198 | size = ~size + 1; | ||
199 | base &= SDBASE_CBA; | ||
200 | 196 | ||
201 | printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); | 197 | fpu_init_state(); |
202 | memory_size += size; | 198 | } |
203 | phys_memory_base = base; | ||
204 | } | ||
205 | 199 | ||
206 | base = SDBASE(1); | 200 | static struct cpu cpu_devices[NR_CPUS]; |
207 | if (base & SDBASE_CE) { | ||
208 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
209 | size = ~size + 1; | ||
210 | base &= SDBASE_CBA; | ||
211 | 201 | ||
212 | printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); | 202 | static int __init topology_init(void) |
213 | memory_size += size; | 203 | { |
214 | if (phys_memory_base == 0) | 204 | int i; |
215 | phys_memory_base = base; | ||
216 | } | ||
217 | 205 | ||
218 | phys_memory_end = phys_memory_base + memory_size; | 206 | for_each_present_cpu(i) |
207 | register_cpu(&cpu_devices[i], i); | ||
219 | 208 | ||
220 | #ifdef CONFIG_FPU | 209 | return 0; |
221 | fpu_init_state(); | ||
222 | #endif | ||
223 | } | 210 | } |
224 | 211 | ||
212 | subsys_initcall(topology_init); | ||
213 | |||
225 | /* | 214 | /* |
226 | * Get CPU information for use by the procfs. | 215 | * Get CPU information for use by the procfs. |
227 | */ | 216 | */ |
228 | static int show_cpuinfo(struct seq_file *m, void *v) | 217 | static int show_cpuinfo(struct seq_file *m, void *v) |
229 | { | 218 | { |
219 | #ifdef CONFIG_SMP | ||
220 | struct mn10300_cpuinfo *c = v; | ||
221 | unsigned long cpu_id = c - cpu_data; | ||
222 | unsigned long cpurev = c->type, type, icachesz, dcachesz; | ||
223 | #else /* CONFIG_SMP */ | ||
224 | unsigned long cpu_id = 0; | ||
230 | unsigned long cpurev = CPUREV, type, icachesz, dcachesz; | 225 | unsigned long cpurev = CPUREV, type, icachesz, dcachesz; |
226 | #endif /* CONFIG_SMP */ | ||
231 | 227 | ||
232 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | 228 | #ifdef CONFIG_SMP |
229 | if (!cpu_online(cpu_id)) | ||
230 | return 0; | ||
231 | #endif | ||
232 | |||
233 | type = (cpurev & CPUREV_TYPE) >> CPUREV_TYPE_S; | ||
233 | if (type > mn10300_known_cpus) | 234 | if (type > mn10300_known_cpus) |
234 | type = mn10300_known_cpus; | 235 | type = mn10300_known_cpus; |
235 | 236 | ||
@@ -244,13 +245,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
244 | 1024; | 245 | 1024; |
245 | 246 | ||
246 | seq_printf(m, | 247 | seq_printf(m, |
247 | "processor : 0\n" | 248 | "processor : %ld\n" |
248 | "vendor_id : Matsushita\n" | 249 | "vendor_id : Matsushita\n" |
249 | "cpu core : %s\n" | 250 | "cpu core : %s\n" |
250 | "cpu rev : %lu\n" | 251 | "cpu rev : %lu\n" |
251 | "model name : " PROCESSOR_MODEL_NAME "\n" | 252 | "model name : " PROCESSOR_MODEL_NAME "\n" |
252 | "icache size: %lu\n" | 253 | "icache size: %lu\n" |
253 | "dcache size: %lu\n", | 254 | "dcache size: %lu\n", |
255 | cpu_id, | ||
254 | mn10300_cputypes[type], | 256 | mn10300_cputypes[type], |
255 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, | 257 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, |
256 | icachesz, | 258 | icachesz, |
@@ -262,8 +264,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
262 | "bogomips : %lu.%02lu\n\n", | 264 | "bogomips : %lu.%02lu\n\n", |
263 | MN10300_IOCLK / 1000000, | 265 | MN10300_IOCLK / 1000000, |
264 | (MN10300_IOCLK / 10000) % 100, | 266 | (MN10300_IOCLK / 10000) % 100, |
267 | #ifdef CONFIG_SMP | ||
268 | c->loops_per_jiffy / (500000 / HZ), | ||
269 | (c->loops_per_jiffy / (5000 / HZ)) % 100 | ||
270 | #else /* CONFIG_SMP */ | ||
265 | loops_per_jiffy / (500000 / HZ), | 271 | loops_per_jiffy / (500000 / HZ), |
266 | (loops_per_jiffy / (5000 / HZ)) % 100 | 272 | (loops_per_jiffy / (5000 / HZ)) % 100 |
273 | #endif /* CONFIG_SMP */ | ||
267 | ); | 274 | ); |
268 | 275 | ||
269 | return 0; | 276 | return 0; |
diff --git a/arch/mn10300/kernel/smp-low.S b/arch/mn10300/kernel/smp-low.S new file mode 100644 index 000000000000..72938cefc05e --- /dev/null +++ b/arch/mn10300/kernel/smp-low.S | |||
@@ -0,0 +1,97 @@ | |||
1 | /* SMP IPI low-level handler | ||
2 | * | ||
3 | * Copyright (C) 2006-2007 Matsushita Electric Industrial Co., Ltd. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/sys.h> | ||
14 | #include <linux/linkage.h> | ||
15 | #include <asm/smp.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/thread_info.h> | ||
18 | #include <asm/cpu-regs.h> | ||
19 | #include <proc/smp-regs.h> | ||
20 | #include <asm/asm-offsets.h> | ||
21 | #include <asm/frame.inc> | ||
22 | |||
23 | .am33_2 | ||
24 | |||
25 | ############################################################################### | ||
26 | # | ||
27 | # IPI interrupt handler | ||
28 | # | ||
29 | ############################################################################### | ||
30 | .globl mn10300_low_ipi_handler | ||
31 | mn10300_low_ipi_handler: | ||
32 | add -4,sp | ||
33 | mov d0,(sp) | ||
34 | movhu (IAGR),d0 | ||
35 | and IAGR_GN,d0 | ||
36 | lsr 0x2,d0 | ||
37 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
38 | cmp FLUSH_CACHE_IPI,d0 | ||
39 | beq mn10300_flush_cache_ipi | ||
40 | #endif | ||
41 | cmp SMP_BOOT_IRQ,d0 | ||
42 | beq mn10300_smp_boot_ipi | ||
43 | /* OTHERS */ | ||
44 | mov (sp),d0 | ||
45 | add 4,sp | ||
46 | #ifdef CONFIG_GDBSTUB | ||
47 | jmp gdbstub_io_rx_handler | ||
48 | #else | ||
49 | jmp end | ||
50 | #endif | ||
51 | |||
52 | ############################################################################### | ||
53 | # | ||
54 | # Cache flush IPI interrupt handler | ||
55 | # | ||
56 | ############################################################################### | ||
57 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
58 | mn10300_flush_cache_ipi: | ||
59 | mov (sp),d0 | ||
60 | add 4,sp | ||
61 | |||
62 | /* FLUSH_CACHE_IPI */ | ||
63 | add -4,sp | ||
64 | SAVE_ALL | ||
65 | mov GxICR_DETECT,d2 | ||
66 | movbu d2,(GxICR(FLUSH_CACHE_IPI)) # ACK the interrupt | ||
67 | movhu (GxICR(FLUSH_CACHE_IPI)),d2 | ||
68 | call smp_cache_interrupt[],0 | ||
69 | RESTORE_ALL | ||
70 | jmp end | ||
71 | #endif | ||
72 | |||
73 | ############################################################################### | ||
74 | # | ||
75 | # SMP boot CPU IPI interrupt handler | ||
76 | # | ||
77 | ############################################################################### | ||
78 | mn10300_smp_boot_ipi: | ||
79 | /* clear interrupt */ | ||
80 | movhu (GxICR(SMP_BOOT_IRQ)),d0 | ||
81 | and ~GxICR_REQUEST,d0 | ||
82 | movhu d0,(GxICR(SMP_BOOT_IRQ)) | ||
83 | mov (sp),d0 | ||
84 | add 4,sp | ||
85 | |||
86 | # get stack | ||
87 | mov (CPUID),a0 | ||
88 | add -1,a0 | ||
89 | add a0,a0 | ||
90 | add a0,a0 | ||
91 | mov (start_stack,a0),a0 | ||
92 | mov a0,sp | ||
93 | jmp initialize_secondary | ||
94 | |||
95 | |||
96 | # Jump here after RTI to suppress the icache lookahead | ||
97 | end: | ||
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c new file mode 100644 index 000000000000..b80234c28e0d --- /dev/null +++ b/arch/mn10300/kernel/smp.c | |||
@@ -0,0 +1,1141 @@ | |||
1 | /* SMP support routines. | ||
2 | * | ||
3 | * Copyright (C) 2006-2008 Panasonic Corporation | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/cpumask.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/profile.h> | ||
26 | #include <linux/smp.h> | ||
27 | #include <asm/tlbflush.h> | ||
28 | #include <asm/system.h> | ||
29 | #include <asm/bitops.h> | ||
30 | #include <asm/processor.h> | ||
31 | #include <asm/bug.h> | ||
32 | #include <asm/exceptions.h> | ||
33 | #include <asm/hardirq.h> | ||
34 | #include <asm/fpu.h> | ||
35 | #include <asm/mmu_context.h> | ||
36 | #include <asm/thread_info.h> | ||
37 | #include <asm/cpu-regs.h> | ||
38 | #include <asm/intctl-regs.h> | ||
39 | #include "internal.h" | ||
40 | |||
41 | #ifdef CONFIG_HOTPLUG_CPU | ||
42 | #include <linux/cpu.h> | ||
43 | #include <asm/cacheflush.h> | ||
44 | |||
45 | static unsigned long sleep_mode[NR_CPUS]; | ||
46 | |||
47 | static void run_sleep_cpu(unsigned int cpu); | ||
48 | static void run_wakeup_cpu(unsigned int cpu); | ||
49 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
50 | |||
51 | /* | ||
52 | * Debug Message function | ||
53 | */ | ||
54 | |||
55 | #undef DEBUG_SMP | ||
56 | #ifdef DEBUG_SMP | ||
57 | #define Dprintk(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__) | ||
58 | #else | ||
59 | #define Dprintk(fmt, ...) no_printk(KERN_DEBUG fmt, ##__VA_ARGS__) | ||
60 | #endif | ||
61 | |||
62 | /* timeout value in msec for smp_nmi_call_function. zero is no timeout. */ | ||
63 | #define CALL_FUNCTION_NMI_IPI_TIMEOUT 0 | ||
64 | |||
65 | /* | ||
66 | * Structure and data for smp_nmi_call_function(). | ||
67 | */ | ||
68 | struct nmi_call_data_struct { | ||
69 | smp_call_func_t func; | ||
70 | void *info; | ||
71 | cpumask_t started; | ||
72 | cpumask_t finished; | ||
73 | int wait; | ||
74 | char size_alignment[0] | ||
75 | __attribute__ ((__aligned__(SMP_CACHE_BYTES))); | ||
76 | } __attribute__ ((__aligned__(SMP_CACHE_BYTES))); | ||
77 | |||
78 | static DEFINE_SPINLOCK(smp_nmi_call_lock); | ||
79 | static struct nmi_call_data_struct *nmi_call_data; | ||
80 | |||
81 | /* | ||
82 | * Data structures and variables | ||
83 | */ | ||
84 | static cpumask_t cpu_callin_map; /* Bitmask of callin CPUs */ | ||
85 | static cpumask_t cpu_callout_map; /* Bitmask of callout CPUs */ | ||
86 | cpumask_t cpu_boot_map; /* Bitmask of boot APs */ | ||
87 | unsigned long start_stack[NR_CPUS - 1]; | ||
88 | |||
89 | /* | ||
90 | * Per CPU parameters | ||
91 | */ | ||
92 | struct mn10300_cpuinfo cpu_data[NR_CPUS] __cacheline_aligned; | ||
93 | |||
94 | static int cpucount; /* The count of boot CPUs */ | ||
95 | static cpumask_t smp_commenced_mask; | ||
96 | cpumask_t cpu_initialized __initdata = CPU_MASK_NONE; | ||
97 | |||
98 | /* | ||
99 | * Function Prototypes | ||
100 | */ | ||
101 | static int do_boot_cpu(int); | ||
102 | static void smp_show_cpu_info(int cpu_id); | ||
103 | static void smp_callin(void); | ||
104 | static void smp_online(void); | ||
105 | static void smp_store_cpu_info(int); | ||
106 | static void smp_cpu_init(void); | ||
107 | static void smp_tune_scheduling(void); | ||
108 | static void send_IPI_mask(const cpumask_t *cpumask, int irq); | ||
109 | static void init_ipi(void); | ||
110 | |||
111 | /* | ||
112 | * IPI Initialization interrupt definitions | ||
113 | */ | ||
114 | static void mn10300_ipi_disable(unsigned int irq); | ||
115 | static void mn10300_ipi_enable(unsigned int irq); | ||
116 | static void mn10300_ipi_ack(unsigned int irq); | ||
117 | static void mn10300_ipi_nop(unsigned int irq); | ||
118 | |||
119 | static struct irq_chip mn10300_ipi_type = { | ||
120 | .name = "cpu_ipi", | ||
121 | .disable = mn10300_ipi_disable, | ||
122 | .enable = mn10300_ipi_enable, | ||
123 | .ack = mn10300_ipi_ack, | ||
124 | .eoi = mn10300_ipi_nop | ||
125 | }; | ||
126 | |||
127 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); | ||
128 | static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id); | ||
129 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); | ||
130 | |||
131 | static struct irqaction reschedule_ipi = { | ||
132 | .handler = smp_reschedule_interrupt, | ||
133 | .name = "smp reschedule IPI" | ||
134 | }; | ||
135 | static struct irqaction call_function_ipi = { | ||
136 | .handler = smp_call_function_interrupt, | ||
137 | .name = "smp call function IPI" | ||
138 | }; | ||
139 | static struct irqaction local_timer_ipi = { | ||
140 | .handler = smp_ipi_timer_interrupt, | ||
141 | .flags = IRQF_DISABLED, | ||
142 | .name = "smp local timer IPI" | ||
143 | }; | ||
144 | |||
145 | /** | ||
146 | * init_ipi - Initialise the IPI mechanism | ||
147 | */ | ||
148 | static void init_ipi(void) | ||
149 | { | ||
150 | unsigned long flags; | ||
151 | u16 tmp16; | ||
152 | |||
153 | /* set up the reschedule IPI */ | ||
154 | set_irq_chip_and_handler(RESCHEDULE_IPI, | ||
155 | &mn10300_ipi_type, handle_percpu_irq); | ||
156 | setup_irq(RESCHEDULE_IPI, &reschedule_ipi); | ||
157 | set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV); | ||
158 | mn10300_ipi_enable(RESCHEDULE_IPI); | ||
159 | |||
160 | /* set up the call function IPI */ | ||
161 | set_irq_chip_and_handler(CALL_FUNC_SINGLE_IPI, | ||
162 | &mn10300_ipi_type, handle_percpu_irq); | ||
163 | setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi); | ||
164 | set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV); | ||
165 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); | ||
166 | |||
167 | /* set up the local timer IPI */ | ||
168 | set_irq_chip_and_handler(LOCAL_TIMER_IPI, | ||
169 | &mn10300_ipi_type, handle_percpu_irq); | ||
170 | setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi); | ||
171 | set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV); | ||
172 | mn10300_ipi_enable(LOCAL_TIMER_IPI); | ||
173 | |||
174 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
175 | /* set up the cache flush IPI */ | ||
176 | flags = arch_local_cli_save(); | ||
177 | __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV), | ||
178 | mn10300_low_ipi_handler); | ||
179 | GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT; | ||
180 | mn10300_ipi_enable(FLUSH_CACHE_IPI); | ||
181 | arch_local_irq_restore(flags); | ||
182 | #endif | ||
183 | |||
184 | /* set up the NMI call function IPI */ | ||
185 | flags = arch_local_cli_save(); | ||
186 | GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; | ||
187 | tmp16 = GxICR(CALL_FUNCTION_NMI_IPI); | ||
188 | arch_local_irq_restore(flags); | ||
189 | |||
190 | /* set up the SMP boot IPI */ | ||
191 | flags = arch_local_cli_save(); | ||
192 | __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV), | ||
193 | mn10300_low_ipi_handler); | ||
194 | arch_local_irq_restore(flags); | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * mn10300_ipi_shutdown - Shut down handling of an IPI | ||
199 | * @irq: The IPI to be shut down. | ||
200 | */ | ||
201 | static void mn10300_ipi_shutdown(unsigned int irq) | ||
202 | { | ||
203 | unsigned long flags; | ||
204 | u16 tmp; | ||
205 | |||
206 | flags = arch_local_cli_save(); | ||
207 | |||
208 | tmp = GxICR(irq); | ||
209 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | ||
210 | tmp = GxICR(irq); | ||
211 | |||
212 | arch_local_irq_restore(flags); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * mn10300_ipi_enable - Enable an IPI | ||
217 | * @irq: The IPI to be enabled. | ||
218 | */ | ||
219 | static void mn10300_ipi_enable(unsigned int irq) | ||
220 | { | ||
221 | unsigned long flags; | ||
222 | u16 tmp; | ||
223 | |||
224 | flags = arch_local_cli_save(); | ||
225 | |||
226 | tmp = GxICR(irq); | ||
227 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; | ||
228 | tmp = GxICR(irq); | ||
229 | |||
230 | arch_local_irq_restore(flags); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * mn10300_ipi_disable - Disable an IPI | ||
235 | * @irq: The IPI to be disabled. | ||
236 | */ | ||
237 | static void mn10300_ipi_disable(unsigned int irq) | ||
238 | { | ||
239 | unsigned long flags; | ||
240 | u16 tmp; | ||
241 | |||
242 | flags = arch_local_cli_save(); | ||
243 | |||
244 | tmp = GxICR(irq); | ||
245 | GxICR(irq) = tmp & GxICR_LEVEL; | ||
246 | tmp = GxICR(irq); | ||
247 | |||
248 | arch_local_irq_restore(flags); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC | ||
253 | * @irq: The IPI to be acknowledged. | ||
254 | * | ||
255 | * Clear the interrupt detection flag for the IPI on the appropriate interrupt | ||
256 | * channel in the PIC. | ||
257 | */ | ||
258 | static void mn10300_ipi_ack(unsigned int irq) | ||
259 | { | ||
260 | unsigned long flags; | ||
261 | u16 tmp; | ||
262 | |||
263 | flags = arch_local_cli_save(); | ||
264 | GxICR_u8(irq) = GxICR_DETECT; | ||
265 | tmp = GxICR(irq); | ||
266 | arch_local_irq_restore(flags); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * mn10300_ipi_nop - Dummy IPI action | ||
271 | * @irq: The IPI to be acted upon. | ||
272 | */ | ||
273 | static void mn10300_ipi_nop(unsigned int irq) | ||
274 | { | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * send_IPI_mask - Send IPIs to all CPUs in list | ||
279 | * @cpumask: The list of CPUs to target. | ||
280 | * @irq: The IPI request to be sent. | ||
281 | * | ||
282 | * Send the specified IPI to all the CPUs in the list, not waiting for them to | ||
283 | * finish before returning. The caller is responsible for synchronisation if | ||
284 | * that is needed. | ||
285 | */ | ||
286 | static void send_IPI_mask(const cpumask_t *cpumask, int irq) | ||
287 | { | ||
288 | int i; | ||
289 | u16 tmp; | ||
290 | |||
291 | for (i = 0; i < NR_CPUS; i++) { | ||
292 | if (cpu_isset(i, *cpumask)) { | ||
293 | /* send IPI */ | ||
294 | tmp = CROSS_GxICR(irq, i); | ||
295 | CROSS_GxICR(irq, i) = | ||
296 | tmp | GxICR_REQUEST | GxICR_DETECT; | ||
297 | tmp = CROSS_GxICR(irq, i); /* flush write buffer */ | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * send_IPI_self - Send an IPI to this CPU. | ||
304 | * @irq: The IPI request to be sent. | ||
305 | * | ||
306 | * Send the specified IPI to the current CPU. | ||
307 | */ | ||
308 | void send_IPI_self(int irq) | ||
309 | { | ||
310 | send_IPI_mask(cpumask_of(smp_processor_id()), irq); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * send_IPI_allbutself - Send IPIs to all the other CPUs. | ||
315 | * @irq: The IPI request to be sent. | ||
316 | * | ||
317 | * Send the specified IPI to all CPUs in the system barring the current one, | ||
318 | * not waiting for them to finish before returning. The caller is responsible | ||
319 | * for synchronisation if that is needed. | ||
320 | */ | ||
321 | void send_IPI_allbutself(int irq) | ||
322 | { | ||
323 | cpumask_t cpumask; | ||
324 | |||
325 | cpumask = cpu_online_map; | ||
326 | cpu_clear(smp_processor_id(), cpumask); | ||
327 | send_IPI_mask(&cpumask, irq); | ||
328 | } | ||
329 | |||
330 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
331 | { | ||
332 | BUG(); | ||
333 | /*send_IPI_mask(mask, CALL_FUNCTION_IPI);*/ | ||
334 | } | ||
335 | |||
336 | void arch_send_call_function_single_ipi(int cpu) | ||
337 | { | ||
338 | send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_IPI); | ||
339 | } | ||
340 | |||
341 | /** | ||
342 | * smp_send_reschedule - Send reschedule IPI to a CPU | ||
343 | * @cpu: The CPU to target. | ||
344 | */ | ||
345 | void smp_send_reschedule(int cpu) | ||
346 | { | ||
347 | send_IPI_mask(cpumask_of(cpu), RESCHEDULE_IPI); | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * smp_nmi_call_function - Send a call function NMI IPI to all CPUs | ||
352 | * @func: The function to ask to be run. | ||
353 | * @info: The context data to pass to that function. | ||
354 | * @wait: If true, wait (atomically) until function is run on all CPUs. | ||
355 | * | ||
356 | * Send a non-maskable request to all CPUs in the system, requesting them to | ||
357 | * run the specified function with the given context data, and, potentially, to | ||
358 | * wait for completion of that function on all CPUs. | ||
359 | * | ||
360 | * Returns 0 if successful, -ETIMEDOUT if we were asked to wait, but hit the | ||
361 | * timeout. | ||
362 | */ | ||
363 | int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) | ||
364 | { | ||
365 | struct nmi_call_data_struct data; | ||
366 | unsigned long flags; | ||
367 | unsigned int cnt; | ||
368 | int cpus, ret = 0; | ||
369 | |||
370 | cpus = num_online_cpus() - 1; | ||
371 | if (cpus < 1) | ||
372 | return 0; | ||
373 | |||
374 | data.func = func; | ||
375 | data.info = info; | ||
376 | data.started = cpu_online_map; | ||
377 | cpu_clear(smp_processor_id(), data.started); | ||
378 | data.wait = wait; | ||
379 | if (wait) | ||
380 | data.finished = data.started; | ||
381 | |||
382 | spin_lock_irqsave(&smp_nmi_call_lock, flags); | ||
383 | nmi_call_data = &data; | ||
384 | smp_mb(); | ||
385 | |||
386 | /* Send a message to all other CPUs and wait for them to respond */ | ||
387 | send_IPI_allbutself(CALL_FUNCTION_NMI_IPI); | ||
388 | |||
389 | /* Wait for response */ | ||
390 | if (CALL_FUNCTION_NMI_IPI_TIMEOUT > 0) { | ||
391 | for (cnt = 0; | ||
392 | cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT && | ||
393 | !cpus_empty(data.started); | ||
394 | cnt++) | ||
395 | mdelay(1); | ||
396 | |||
397 | if (wait && cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT) { | ||
398 | for (cnt = 0; | ||
399 | cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT && | ||
400 | !cpus_empty(data.finished); | ||
401 | cnt++) | ||
402 | mdelay(1); | ||
403 | } | ||
404 | |||
405 | if (cnt >= CALL_FUNCTION_NMI_IPI_TIMEOUT) | ||
406 | ret = -ETIMEDOUT; | ||
407 | |||
408 | } else { | ||
409 | /* If timeout value is zero, wait until cpumask has been | ||
410 | * cleared */ | ||
411 | while (!cpus_empty(data.started)) | ||
412 | barrier(); | ||
413 | if (wait) | ||
414 | while (!cpus_empty(data.finished)) | ||
415 | barrier(); | ||
416 | } | ||
417 | |||
418 | spin_unlock_irqrestore(&smp_nmi_call_lock, flags); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * stop_this_cpu - Callback to stop a CPU. | ||
424 | * @unused: Callback context (ignored). | ||
425 | */ | ||
426 | void stop_this_cpu(void *unused) | ||
427 | { | ||
428 | static volatile int stopflag; | ||
429 | unsigned long flags; | ||
430 | |||
431 | #ifdef CONFIG_GDBSTUB | ||
432 | /* In case of single stepping smp_send_stop by other CPU, | ||
433 | * clear procindebug to avoid deadlock. | ||
434 | */ | ||
435 | atomic_set(&procindebug[smp_processor_id()], 0); | ||
436 | #endif /* CONFIG_GDBSTUB */ | ||
437 | |||
438 | flags = arch_local_cli_save(); | ||
439 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
440 | |||
441 | while (!stopflag) | ||
442 | cpu_relax(); | ||
443 | |||
444 | cpu_set(smp_processor_id(), cpu_online_map); | ||
445 | arch_local_irq_restore(flags); | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * smp_send_stop - Send a stop request to all CPUs. | ||
450 | */ | ||
451 | void smp_send_stop(void) | ||
452 | { | ||
453 | smp_nmi_call_function(stop_this_cpu, NULL, 0); | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * smp_reschedule_interrupt - Reschedule IPI handler | ||
458 | * @irq: The interrupt number. | ||
459 | * @dev_id: The device ID. | ||
460 | * | ||
461 | * We need do nothing here, since the scheduling will be effected on our way | ||
462 | * back through entry.S. | ||
463 | * | ||
464 | * Returns IRQ_HANDLED to indicate we handled the interrupt successfully. | ||
465 | */ | ||
466 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id) | ||
467 | { | ||
468 | /* do nothing */ | ||
469 | return IRQ_HANDLED; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * smp_call_function_interrupt - Call function IPI handler | ||
474 | * @irq: The interrupt number. | ||
475 | * @dev_id: The device ID. | ||
476 | * | ||
477 | * Returns IRQ_HANDLED to indicate we handled the interrupt successfully. | ||
478 | */ | ||
479 | static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id) | ||
480 | { | ||
481 | /* generic_smp_call_function_interrupt(); */ | ||
482 | generic_smp_call_function_single_interrupt(); | ||
483 | return IRQ_HANDLED; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * smp_nmi_call_function_interrupt - Non-maskable call function IPI handler | ||
488 | */ | ||
489 | void smp_nmi_call_function_interrupt(void) | ||
490 | { | ||
491 | smp_call_func_t func = nmi_call_data->func; | ||
492 | void *info = nmi_call_data->info; | ||
493 | int wait = nmi_call_data->wait; | ||
494 | |||
495 | /* Notify the initiating CPU that I've grabbed the data and am about to | ||
496 | * execute the function | ||
497 | */ | ||
498 | smp_mb(); | ||
499 | cpu_clear(smp_processor_id(), nmi_call_data->started); | ||
500 | (*func)(info); | ||
501 | |||
502 | if (wait) { | ||
503 | smp_mb(); | ||
504 | cpu_clear(smp_processor_id(), nmi_call_data->finished); | ||
505 | } | ||
506 | } | ||
507 | |||
508 | /** | ||
509 | * smp_ipi_timer_interrupt - Local timer IPI handler | ||
510 | * @irq: The interrupt number. | ||
511 | * @dev_id: The device ID. | ||
512 | * | ||
513 | * Returns IRQ_HANDLED to indicate we handled the interrupt successfully. | ||
514 | */ | ||
515 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id) | ||
516 | { | ||
517 | return local_timer_interrupt(); | ||
518 | } | ||
519 | |||
520 | void __init smp_init_cpus(void) | ||
521 | { | ||
522 | int i; | ||
523 | for (i = 0; i < NR_CPUS; i++) { | ||
524 | set_cpu_possible(i, true); | ||
525 | set_cpu_present(i, true); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * smp_cpu_init - Initialise AP in start_secondary. | ||
531 | * | ||
532 | * For this Application Processor, set up init_mm, initialise FPU and set | ||
533 | * interrupt level 0-6 setting. | ||
534 | */ | ||
535 | static void __init smp_cpu_init(void) | ||
536 | { | ||
537 | unsigned long flags; | ||
538 | int cpu_id = smp_processor_id(); | ||
539 | u16 tmp16; | ||
540 | |||
541 | if (test_and_set_bit(cpu_id, &cpu_initialized)) { | ||
542 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id); | ||
543 | for (;;) | ||
544 | local_irq_enable(); | ||
545 | } | ||
546 | printk(KERN_INFO "Initializing CPU#%d\n", cpu_id); | ||
547 | |||
548 | atomic_inc(&init_mm.mm_count); | ||
549 | current->active_mm = &init_mm; | ||
550 | BUG_ON(current->mm); | ||
551 | |||
552 | enter_lazy_tlb(&init_mm, current); | ||
553 | |||
554 | /* Force FPU initialization */ | ||
555 | clear_using_fpu(current); | ||
556 | |||
557 | GxICR(CALL_FUNC_SINGLE_IPI) = CALL_FUNCTION_GxICR_LV | GxICR_DETECT; | ||
558 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); | ||
559 | |||
560 | GxICR(LOCAL_TIMER_IPI) = LOCAL_TIMER_GxICR_LV | GxICR_DETECT; | ||
561 | mn10300_ipi_enable(LOCAL_TIMER_IPI); | ||
562 | |||
563 | GxICR(RESCHEDULE_IPI) = RESCHEDULE_GxICR_LV | GxICR_DETECT; | ||
564 | mn10300_ipi_enable(RESCHEDULE_IPI); | ||
565 | |||
566 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
567 | GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT; | ||
568 | mn10300_ipi_enable(FLUSH_CACHE_IPI); | ||
569 | #endif | ||
570 | |||
571 | mn10300_ipi_shutdown(SMP_BOOT_IRQ); | ||
572 | |||
573 | /* Set up the non-maskable call function IPI */ | ||
574 | flags = arch_local_cli_save(); | ||
575 | GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; | ||
576 | tmp16 = GxICR(CALL_FUNCTION_NMI_IPI); | ||
577 | arch_local_irq_restore(flags); | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * smp_prepare_cpu_init - Initialise CPU in startup_secondary | ||
582 | * | ||
583 | * Set interrupt level 0-6 setting and init ICR of gdbstub. | ||
584 | */ | ||
585 | void smp_prepare_cpu_init(void) | ||
586 | { | ||
587 | int loop; | ||
588 | |||
589 | /* Set the interrupt vector registers */ | ||
590 | IVAR0 = EXCEP_IRQ_LEVEL0; | ||
591 | IVAR1 = EXCEP_IRQ_LEVEL1; | ||
592 | IVAR2 = EXCEP_IRQ_LEVEL2; | ||
593 | IVAR3 = EXCEP_IRQ_LEVEL3; | ||
594 | IVAR4 = EXCEP_IRQ_LEVEL4; | ||
595 | IVAR5 = EXCEP_IRQ_LEVEL5; | ||
596 | IVAR6 = EXCEP_IRQ_LEVEL6; | ||
597 | |||
598 | /* Disable all interrupts and set to priority 6 (lowest) */ | ||
599 | for (loop = 0; loop < GxICR_NUM_IRQS; loop++) | ||
600 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | ||
601 | |||
602 | #ifdef CONFIG_GDBSTUB | ||
603 | /* initialise GDB-stub */ | ||
604 | do { | ||
605 | unsigned long flags; | ||
606 | u16 tmp16; | ||
607 | |||
608 | flags = arch_local_cli_save(); | ||
609 | GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; | ||
610 | tmp16 = GxICR(GDB_NMI_IPI); | ||
611 | arch_local_irq_restore(flags); | ||
612 | } while (0); | ||
613 | #endif | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * start_secondary - Activate a secondary CPU (AP) | ||
618 | * @unused: Thread parameter (ignored). | ||
619 | */ | ||
620 | int __init start_secondary(void *unused) | ||
621 | { | ||
622 | smp_cpu_init(); | ||
623 | |||
624 | smp_callin(); | ||
625 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) | ||
626 | cpu_relax(); | ||
627 | |||
628 | local_flush_tlb(); | ||
629 | preempt_disable(); | ||
630 | smp_online(); | ||
631 | |||
632 | cpu_idle(); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | /** | ||
637 | * smp_prepare_cpus - Boot up secondary CPUs (APs) | ||
638 | * @max_cpus: Maximum number of CPUs to boot. | ||
639 | * | ||
640 | * Call do_boot_cpu, and boot up APs. | ||
641 | */ | ||
642 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
643 | { | ||
644 | int phy_id; | ||
645 | |||
646 | /* Setup boot CPU information */ | ||
647 | smp_store_cpu_info(0); | ||
648 | smp_tune_scheduling(); | ||
649 | |||
650 | init_ipi(); | ||
651 | |||
652 | /* If SMP should be disabled, then finish */ | ||
653 | if (max_cpus == 0) { | ||
654 | printk(KERN_INFO "SMP mode deactivated.\n"); | ||
655 | goto smp_done; | ||
656 | } | ||
657 | |||
658 | /* Boot secondary CPUs (for which phy_id > 0) */ | ||
659 | for (phy_id = 0; phy_id < NR_CPUS; phy_id++) { | ||
660 | /* Don't boot primary CPU */ | ||
661 | if (max_cpus <= cpucount + 1) | ||
662 | continue; | ||
663 | if (phy_id != 0) | ||
664 | do_boot_cpu(phy_id); | ||
665 | set_cpu_possible(phy_id, true); | ||
666 | smp_show_cpu_info(phy_id); | ||
667 | } | ||
668 | |||
669 | smp_done: | ||
670 | Dprintk("Boot done.\n"); | ||
671 | } | ||
672 | |||
673 | /** | ||
674 | * smp_store_cpu_info - Save a CPU's information | ||
675 | * @cpu: The CPU to save for. | ||
676 | * | ||
677 | * Save boot_cpu_data and jiffy for the specified CPU. | ||
678 | */ | ||
679 | static void __init smp_store_cpu_info(int cpu) | ||
680 | { | ||
681 | struct mn10300_cpuinfo *ci = &cpu_data[cpu]; | ||
682 | |||
683 | *ci = boot_cpu_data; | ||
684 | ci->loops_per_jiffy = loops_per_jiffy; | ||
685 | ci->type = CPUREV; | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * smp_tune_scheduling - Set time slice value | ||
690 | * | ||
691 | * Nothing to do here. | ||
692 | */ | ||
693 | static void __init smp_tune_scheduling(void) | ||
694 | { | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * do_boot_cpu: Boot up one CPU | ||
699 | * @phy_id: Physical ID of CPU to boot. | ||
700 | * | ||
701 | * Send an IPI to a secondary CPU to boot it. Returns 0 on success, 1 | ||
702 | * otherwise. | ||
703 | */ | ||
704 | static int __init do_boot_cpu(int phy_id) | ||
705 | { | ||
706 | struct task_struct *idle; | ||
707 | unsigned long send_status, callin_status; | ||
708 | int timeout, cpu_id; | ||
709 | |||
710 | send_status = GxICR_REQUEST; | ||
711 | callin_status = 0; | ||
712 | timeout = 0; | ||
713 | cpu_id = phy_id; | ||
714 | |||
715 | cpucount++; | ||
716 | |||
717 | /* Create idle thread for this CPU */ | ||
718 | idle = fork_idle(cpu_id); | ||
719 | if (IS_ERR(idle)) | ||
720 | panic("Failed fork for CPU#%d.", cpu_id); | ||
721 | |||
722 | idle->thread.pc = (unsigned long)start_secondary; | ||
723 | |||
724 | printk(KERN_NOTICE "Booting CPU#%d\n", cpu_id); | ||
725 | start_stack[cpu_id - 1] = idle->thread.sp; | ||
726 | |||
727 | task_thread_info(idle)->cpu = cpu_id; | ||
728 | |||
729 | /* Send boot IPI to AP */ | ||
730 | send_IPI_mask(cpumask_of(phy_id), SMP_BOOT_IRQ); | ||
731 | |||
732 | Dprintk("Waiting for send to finish...\n"); | ||
733 | |||
734 | /* Wait for AP's IPI receive in 100[ms] */ | ||
735 | do { | ||
736 | udelay(1000); | ||
737 | send_status = | ||
738 | CROSS_GxICR(SMP_BOOT_IRQ, phy_id) & GxICR_REQUEST; | ||
739 | } while (send_status == GxICR_REQUEST && timeout++ < 100); | ||
740 | |||
741 | Dprintk("Waiting for cpu_callin_map.\n"); | ||
742 | |||
743 | if (send_status == 0) { | ||
744 | /* Allow AP to start initializing */ | ||
745 | cpu_set(cpu_id, cpu_callout_map); | ||
746 | |||
747 | /* Wait for setting cpu_callin_map */ | ||
748 | timeout = 0; | ||
749 | do { | ||
750 | udelay(1000); | ||
751 | callin_status = cpu_isset(cpu_id, cpu_callin_map); | ||
752 | } while (callin_status == 0 && timeout++ < 5000); | ||
753 | |||
754 | if (callin_status == 0) | ||
755 | Dprintk("Not responding.\n"); | ||
756 | } else { | ||
757 | printk(KERN_WARNING "IPI not delivered.\n"); | ||
758 | } | ||
759 | |||
760 | if (send_status == GxICR_REQUEST || callin_status == 0) { | ||
761 | cpu_clear(cpu_id, cpu_callout_map); | ||
762 | cpu_clear(cpu_id, cpu_callin_map); | ||
763 | cpu_clear(cpu_id, cpu_initialized); | ||
764 | cpucount--; | ||
765 | return 1; | ||
766 | } | ||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | /** | ||
771 | * smp_show_cpu_info - Show SMP CPU information | ||
772 | * @cpu: The CPU of interest. | ||
773 | */ | ||
774 | static void __init smp_show_cpu_info(int cpu) | ||
775 | { | ||
776 | struct mn10300_cpuinfo *ci = &cpu_data[cpu]; | ||
777 | |||
778 | printk(KERN_INFO | ||
779 | "CPU#%d : ioclk speed: %lu.%02luMHz : bogomips : %lu.%02lu\n", | ||
780 | cpu, | ||
781 | MN10300_IOCLK / 1000000, | ||
782 | (MN10300_IOCLK / 10000) % 100, | ||
783 | ci->loops_per_jiffy / (500000 / HZ), | ||
784 | (ci->loops_per_jiffy / (5000 / HZ)) % 100); | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * smp_callin - Set cpu_callin_map of the current CPU ID | ||
789 | */ | ||
790 | static void __init smp_callin(void) | ||
791 | { | ||
792 | unsigned long timeout; | ||
793 | int cpu; | ||
794 | |||
795 | cpu = smp_processor_id(); | ||
796 | timeout = jiffies + (2 * HZ); | ||
797 | |||
798 | if (cpu_isset(cpu, cpu_callin_map)) { | ||
799 | printk(KERN_ERR "CPU#%d already present.\n", cpu); | ||
800 | BUG(); | ||
801 | } | ||
802 | Dprintk("CPU#%d waiting for CALLOUT\n", cpu); | ||
803 | |||
804 | /* Wait for AP startup 2s total */ | ||
805 | while (time_before(jiffies, timeout)) { | ||
806 | if (cpu_isset(cpu, cpu_callout_map)) | ||
807 | break; | ||
808 | cpu_relax(); | ||
809 | } | ||
810 | |||
811 | if (!time_before(jiffies, timeout)) { | ||
812 | printk(KERN_ERR | ||
813 | "BUG: CPU#%d started up but did not get a callout!\n", | ||
814 | cpu); | ||
815 | BUG(); | ||
816 | } | ||
817 | |||
818 | #ifdef CONFIG_CALIBRATE_DELAY | ||
819 | calibrate_delay(); /* Get our bogomips */ | ||
820 | #endif | ||
821 | |||
822 | /* Save our processor parameters */ | ||
823 | smp_store_cpu_info(cpu); | ||
824 | |||
825 | /* Allow the boot processor to continue */ | ||
826 | cpu_set(cpu, cpu_callin_map); | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * smp_online - Set cpu_online_map | ||
831 | */ | ||
832 | static void __init smp_online(void) | ||
833 | { | ||
834 | int cpu; | ||
835 | |||
836 | cpu = smp_processor_id(); | ||
837 | |||
838 | local_irq_enable(); | ||
839 | |||
840 | cpu_set(cpu, cpu_online_map); | ||
841 | smp_wmb(); | ||
842 | } | ||
843 | |||
844 | /** | ||
845 | * smp_cpus_done - | ||
846 | * @max_cpus: Maximum CPU count. | ||
847 | * | ||
848 | * Do nothing. | ||
849 | */ | ||
850 | void __init smp_cpus_done(unsigned int max_cpus) | ||
851 | { | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * smp_prepare_boot_cpu - Set up stuff for the boot processor. | ||
856 | * | ||
857 | * Set up the cpu_online_map, cpu_callout_map and cpu_callin_map of the boot | ||
858 | * processor (CPU 0). | ||
859 | */ | ||
860 | void __devinit smp_prepare_boot_cpu(void) | ||
861 | { | ||
862 | cpu_set(0, cpu_callout_map); | ||
863 | cpu_set(0, cpu_callin_map); | ||
864 | current_thread_info()->cpu = 0; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * initialize_secondary - Initialise a secondary CPU (Application Processor). | ||
869 | * | ||
870 | * Set SP register and jump to thread's PC address. | ||
871 | */ | ||
872 | void initialize_secondary(void) | ||
873 | { | ||
874 | asm volatile ( | ||
875 | "mov %0,sp \n" | ||
876 | "jmp (%1) \n" | ||
877 | : | ||
878 | : "a"(current->thread.sp), "a"(current->thread.pc)); | ||
879 | } | ||
880 | |||
881 | /** | ||
882 | * __cpu_up - Set smp_commenced_mask for the nominated CPU | ||
883 | * @cpu: The target CPU. | ||
884 | */ | ||
885 | int __devinit __cpu_up(unsigned int cpu) | ||
886 | { | ||
887 | int timeout; | ||
888 | |||
889 | #ifdef CONFIG_HOTPLUG_CPU | ||
890 | if (num_online_cpus() == 1) | ||
891 | disable_hlt(); | ||
892 | if (sleep_mode[cpu]) | ||
893 | run_wakeup_cpu(cpu); | ||
894 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
895 | |||
896 | cpu_set(cpu, smp_commenced_mask); | ||
897 | |||
898 | /* Wait 5s total for a response */ | ||
899 | for (timeout = 0 ; timeout < 5000 ; timeout++) { | ||
900 | if (cpu_isset(cpu, cpu_online_map)) | ||
901 | break; | ||
902 | udelay(1000); | ||
903 | } | ||
904 | |||
905 | BUG_ON(!cpu_isset(cpu, cpu_online_map)); | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | /** | ||
910 | * setup_profiling_timer - Set up the profiling timer | ||
911 | * @multiplier - The frequency multiplier to use | ||
912 | * | ||
913 | * The frequency of the profiling timer can be changed by writing a multiplier | ||
914 | * value into /proc/profile. | ||
915 | */ | ||
916 | int setup_profiling_timer(unsigned int multiplier) | ||
917 | { | ||
918 | return -EINVAL; | ||
919 | } | ||
920 | |||
921 | /* | ||
922 | * CPU hotplug routines | ||
923 | */ | ||
924 | #ifdef CONFIG_HOTPLUG_CPU | ||
925 | |||
926 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
927 | |||
928 | static int __init topology_init(void) | ||
929 | { | ||
930 | int cpu, ret; | ||
931 | |||
932 | for_each_cpu(cpu) { | ||
933 | ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL); | ||
934 | if (ret) | ||
935 | printk(KERN_WARNING | ||
936 | "topology_init: register_cpu %d failed (%d)\n", | ||
937 | cpu, ret); | ||
938 | } | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | subsys_initcall(topology_init); | ||
943 | |||
944 | int __cpu_disable(void) | ||
945 | { | ||
946 | int cpu = smp_processor_id(); | ||
947 | if (cpu == 0) | ||
948 | return -EBUSY; | ||
949 | |||
950 | migrate_irqs(); | ||
951 | cpu_clear(cpu, current->active_mm->cpu_vm_mask); | ||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | void __cpu_die(unsigned int cpu) | ||
956 | { | ||
957 | run_sleep_cpu(cpu); | ||
958 | |||
959 | if (num_online_cpus() == 1) | ||
960 | enable_hlt(); | ||
961 | } | ||
962 | |||
963 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
964 | static inline void hotplug_cpu_disable_cache(void) | ||
965 | { | ||
966 | int tmp; | ||
967 | asm volatile( | ||
968 | " movhu (%1),%0 \n" | ||
969 | " and %2,%0 \n" | ||
970 | " movhu %0,(%1) \n" | ||
971 | "1: movhu (%1),%0 \n" | ||
972 | " btst %3,%0 \n" | ||
973 | " bne 1b \n" | ||
974 | : "=&r"(tmp) | ||
975 | : "a"(&CHCTR), | ||
976 | "i"(~(CHCTR_ICEN | CHCTR_DCEN)), | ||
977 | "i"(CHCTR_ICBUSY | CHCTR_DCBUSY) | ||
978 | : "memory", "cc"); | ||
979 | } | ||
980 | |||
981 | static inline void hotplug_cpu_enable_cache(void) | ||
982 | { | ||
983 | int tmp; | ||
984 | asm volatile( | ||
985 | "movhu (%1),%0 \n" | ||
986 | "or %2,%0 \n" | ||
987 | "movhu %0,(%1) \n" | ||
988 | : "=&r"(tmp) | ||
989 | : "a"(&CHCTR), | ||
990 | "i"(CHCTR_ICEN | CHCTR_DCEN) | ||
991 | : "memory", "cc"); | ||
992 | } | ||
993 | |||
994 | static inline void hotplug_cpu_invalidate_cache(void) | ||
995 | { | ||
996 | int tmp; | ||
997 | asm volatile ( | ||
998 | "movhu (%1),%0 \n" | ||
999 | "or %2,%0 \n" | ||
1000 | "movhu %0,(%1) \n" | ||
1001 | : "=&r"(tmp) | ||
1002 | : "a"(&CHCTR), | ||
1003 | "i"(CHCTR_ICINV | CHCTR_DCINV) | ||
1004 | : "cc"); | ||
1005 | } | ||
1006 | |||
1007 | #else /* CONFIG_MN10300_CACHE_ENABLED */ | ||
1008 | #define hotplug_cpu_disable_cache() do {} while (0) | ||
1009 | #define hotplug_cpu_enable_cache() do {} while (0) | ||
1010 | #define hotplug_cpu_invalidate_cache() do {} while (0) | ||
1011 | #endif /* CONFIG_MN10300_CACHE_ENABLED */ | ||
1012 | |||
1013 | /** | ||
1014 | * hotplug_cpu_nmi_call_function - Call a function on other CPUs for hotplug | ||
1015 | * @cpumask: List of target CPUs. | ||
1016 | * @func: The function to call on those CPUs. | ||
1017 | * @info: The context data for the function to be called. | ||
1018 | * @wait: Whether to wait for the calls to complete. | ||
1019 | * | ||
1020 | * Non-maskably call a function on another CPU for hotplug purposes. | ||
1021 | * | ||
1022 | * This function must be called with maskable interrupts disabled. | ||
1023 | */ | ||
1024 | static int hotplug_cpu_nmi_call_function(cpumask_t cpumask, | ||
1025 | smp_call_func_t func, void *info, | ||
1026 | int wait) | ||
1027 | { | ||
1028 | /* | ||
1029 | * The address and the size of nmi_call_func_mask_data | ||
1030 | * need to be aligned on L1_CACHE_BYTES. | ||
1031 | */ | ||
1032 | static struct nmi_call_data_struct nmi_call_func_mask_data | ||
1033 | __cacheline_aligned; | ||
1034 | unsigned long start, end; | ||
1035 | |||
1036 | start = (unsigned long)&nmi_call_func_mask_data; | ||
1037 | end = start + sizeof(struct nmi_call_data_struct); | ||
1038 | |||
1039 | nmi_call_func_mask_data.func = func; | ||
1040 | nmi_call_func_mask_data.info = info; | ||
1041 | nmi_call_func_mask_data.started = cpumask; | ||
1042 | nmi_call_func_mask_data.wait = wait; | ||
1043 | if (wait) | ||
1044 | nmi_call_func_mask_data.finished = cpumask; | ||
1045 | |||
1046 | spin_lock(&smp_nmi_call_lock); | ||
1047 | nmi_call_data = &nmi_call_func_mask_data; | ||
1048 | mn10300_local_dcache_flush_range(start, end); | ||
1049 | smp_wmb(); | ||
1050 | |||
1051 | send_IPI_mask(cpumask, CALL_FUNCTION_NMI_IPI); | ||
1052 | |||
1053 | do { | ||
1054 | mn10300_local_dcache_inv_range(start, end); | ||
1055 | barrier(); | ||
1056 | } while (!cpus_empty(nmi_call_func_mask_data.started)); | ||
1057 | |||
1058 | if (wait) { | ||
1059 | do { | ||
1060 | mn10300_local_dcache_inv_range(start, end); | ||
1061 | barrier(); | ||
1062 | } while (!cpus_empty(nmi_call_func_mask_data.finished)); | ||
1063 | } | ||
1064 | |||
1065 | spin_unlock(&smp_nmi_call_lock); | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static void restart_wakeup_cpu(void) | ||
1070 | { | ||
1071 | unsigned int cpu = smp_processor_id(); | ||
1072 | |||
1073 | cpu_set(cpu, cpu_callin_map); | ||
1074 | local_flush_tlb(); | ||
1075 | cpu_set(cpu, cpu_online_map); | ||
1076 | smp_wmb(); | ||
1077 | } | ||
1078 | |||
1079 | static void prepare_sleep_cpu(void *unused) | ||
1080 | { | ||
1081 | sleep_mode[smp_processor_id()] = 1; | ||
1082 | smp_mb(); | ||
1083 | mn10300_local_dcache_flush_inv(); | ||
1084 | hotplug_cpu_disable_cache(); | ||
1085 | hotplug_cpu_invalidate_cache(); | ||
1086 | } | ||
1087 | |||
1088 | /* when this function called, IE=0, NMID=0. */ | ||
1089 | static void sleep_cpu(void *unused) | ||
1090 | { | ||
1091 | unsigned int cpu_id = smp_processor_id(); | ||
1092 | /* | ||
1093 | * CALL_FUNCTION_NMI_IPI for wakeup_cpu() shall not be requested, | ||
1094 | * before this cpu goes in SLEEP mode. | ||
1095 | */ | ||
1096 | do { | ||
1097 | smp_mb(); | ||
1098 | __sleep_cpu(); | ||
1099 | } while (sleep_mode[cpu_id]); | ||
1100 | restart_wakeup_cpu(); | ||
1101 | } | ||
1102 | |||
1103 | static void run_sleep_cpu(unsigned int cpu) | ||
1104 | { | ||
1105 | unsigned long flags; | ||
1106 | cpumask_t cpumask = cpumask_of(cpu); | ||
1107 | |||
1108 | flags = arch_local_cli_save(); | ||
1109 | hotplug_cpu_nmi_call_function(cpumask, prepare_sleep_cpu, NULL, 1); | ||
1110 | hotplug_cpu_nmi_call_function(cpumask, sleep_cpu, NULL, 0); | ||
1111 | udelay(1); /* delay for the cpu to sleep. */ | ||
1112 | arch_local_irq_restore(flags); | ||
1113 | } | ||
1114 | |||
1115 | static void wakeup_cpu(void) | ||
1116 | { | ||
1117 | hotplug_cpu_invalidate_cache(); | ||
1118 | hotplug_cpu_enable_cache(); | ||
1119 | smp_mb(); | ||
1120 | sleep_mode[smp_processor_id()] = 0; | ||
1121 | } | ||
1122 | |||
1123 | static void run_wakeup_cpu(unsigned int cpu) | ||
1124 | { | ||
1125 | unsigned long flags; | ||
1126 | |||
1127 | flags = arch_local_cli_save(); | ||
1128 | #if NR_CPUS == 2 | ||
1129 | mn10300_local_dcache_flush_inv(); | ||
1130 | #else | ||
1131 | /* | ||
1132 | * Before waking up the cpu, | ||
1133 | * all online cpus should stop and flush D-Cache for global data. | ||
1134 | */ | ||
1135 | #error not support NR_CPUS > 2, when CONFIG_HOTPLUG_CPU=y. | ||
1136 | #endif | ||
1137 | hotplug_cpu_nmi_call_function(cpumask_of(cpu), wakeup_cpu, NULL, 1); | ||
1138 | arch_local_irq_restore(flags); | ||
1139 | } | ||
1140 | |||
1141 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S index 630aad71b946..b08cb2e3aebd 100644 --- a/arch/mn10300/kernel/switch_to.S +++ b/arch/mn10300/kernel/switch_to.S | |||
@@ -15,6 +15,9 @@ | |||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <asm/thread_info.h> | 16 | #include <asm/thread_info.h> |
17 | #include <asm/cpu-regs.h> | 17 | #include <asm/cpu-regs.h> |
18 | #ifdef CONFIG_SMP | ||
19 | #include <proc/smp-regs.h> | ||
20 | #endif /* CONFIG_SMP */ | ||
18 | 21 | ||
19 | .text | 22 | .text |
20 | 23 | ||
@@ -35,7 +38,14 @@ ENTRY(__switch_to) | |||
35 | mov d1,a1 | 38 | mov d1,a1 |
36 | 39 | ||
37 | # save prev context | 40 | # save prev context |
41 | #ifdef CONFIG_SMP | ||
42 | mov (CPUID),a2 | ||
43 | add a2,a2 | ||
44 | add a2,a2 | ||
45 | mov (___frame,a2),d0 | ||
46 | #else /* CONFIG_SMP */ | ||
38 | mov (__frame),d0 | 47 | mov (__frame),d0 |
48 | #endif /* CONFIG_SMP */ | ||
39 | mov d0,(THREAD_FRAME,a0) | 49 | mov d0,(THREAD_FRAME,a0) |
40 | mov __switch_back,d0 | 50 | mov __switch_back,d0 |
41 | mov d0,(THREAD_PC,a0) | 51 | mov d0,(THREAD_PC,a0) |
@@ -59,7 +69,14 @@ ENTRY(__switch_to) | |||
59 | #endif | 69 | #endif |
60 | 70 | ||
61 | mov (THREAD_FRAME,a1),a2 | 71 | mov (THREAD_FRAME,a1),a2 |
72 | #ifdef CONFIG_SMP | ||
73 | mov (CPUID),a0 | ||
74 | add a0,a0 | ||
75 | add a0,a0 | ||
76 | mov a2,(___frame,a0) | ||
77 | #else /* CONFIG_SMP */ | ||
62 | mov a2,(__frame) | 78 | mov a2,(__frame) |
79 | #endif /* CONFIG_SMP */ | ||
63 | mov (THREAD_PC,a1),a2 | 80 | mov (THREAD_PC,a1),a2 |
64 | mov d2,d0 # for ret_from_fork | 81 | mov d2,d0 # for ret_from_fork |
65 | mov d0,a0 # for __switch_to | 82 | mov d0,a0 # for __switch_to |
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 0b5c856b4266..0cb9bdb3b6bd 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c | |||
@@ -22,12 +22,7 @@ | |||
22 | #include <asm/processor.h> | 22 | #include <asm/processor.h> |
23 | #include <asm/intctl-regs.h> | 23 | #include <asm/intctl-regs.h> |
24 | #include <asm/rtc.h> | 24 | #include <asm/rtc.h> |
25 | 25 | #include "internal.h" | |
26 | #ifdef CONFIG_MN10300_RTC | ||
27 | unsigned long mn10300_ioclk; /* system I/O clock frequency */ | ||
28 | unsigned long mn10300_iobclk; /* system I/O clock frequency */ | ||
29 | unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */ | ||
30 | #endif /* CONFIG_MN10300_RTC */ | ||
31 | 26 | ||
32 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time | 27 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time |
33 | * interrupt occurred */ | 28 | * interrupt occurred */ |
@@ -95,6 +90,19 @@ static void __init mn10300_sched_clock_init(void) | |||
95 | __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); | 90 | __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); |
96 | } | 91 | } |
97 | 92 | ||
93 | /** | ||
94 | * local_timer_interrupt - Local timer interrupt handler | ||
95 | * | ||
96 | * Handle local timer interrupts for this CPU. They may have been propagated | ||
97 | * to this CPU from the CPU that actually gets them by way of an IPI. | ||
98 | */ | ||
99 | irqreturn_t local_timer_interrupt(void) | ||
100 | { | ||
101 | profile_tick(CPU_PROFILING); | ||
102 | update_process_times(user_mode(get_irq_regs())); | ||
103 | return IRQ_HANDLED; | ||
104 | } | ||
105 | |||
98 | /* | 106 | /* |
99 | * advance the kernel's time keeping clocks (xtime and jiffies) | 107 | * advance the kernel's time keeping clocks (xtime and jiffies) |
100 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time | 108 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time |
@@ -103,6 +111,7 @@ static void __init mn10300_sched_clock_init(void) | |||
103 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 111 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
104 | { | 112 | { |
105 | unsigned tsc, elapse; | 113 | unsigned tsc, elapse; |
114 | irqreturn_t ret; | ||
106 | 115 | ||
107 | write_seqlock(&xtime_lock); | 116 | write_seqlock(&xtime_lock); |
108 | 117 | ||
@@ -114,15 +123,16 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
114 | mn10300_last_tsc -= MN10300_TSC_PER_HZ; | 123 | mn10300_last_tsc -= MN10300_TSC_PER_HZ; |
115 | 124 | ||
116 | /* advance the kernel's time tracking system */ | 125 | /* advance the kernel's time tracking system */ |
117 | profile_tick(CPU_PROFILING); | ||
118 | do_timer(1); | 126 | do_timer(1); |
119 | } | 127 | } |
120 | 128 | ||
121 | write_sequnlock(&xtime_lock); | 129 | write_sequnlock(&xtime_lock); |
122 | 130 | ||
123 | update_process_times(user_mode(get_irq_regs())); | 131 | ret = local_timer_interrupt(); |
124 | 132 | #ifdef CONFIG_SMP | |
125 | return IRQ_HANDLED; | 133 | send_IPI_allbutself(LOCAL_TIMER_IPI); |
134 | #endif | ||
135 | return ret; | ||
126 | } | 136 | } |
127 | 137 | ||
128 | /* | 138 | /* |
@@ -148,7 +158,7 @@ void __init time_init(void) | |||
148 | /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */ | 158 | /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */ |
149 | setup_irq(TMJCIRQ, &timer_irq); | 159 | setup_irq(TMJCIRQ, &timer_irq); |
150 | 160 | ||
151 | set_intr_level(TMJCIRQ, TMJCICR_LEVEL); | 161 | set_intr_level(TMJCIRQ, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL)); |
152 | 162 | ||
153 | startup_jiffies_counter(); | 163 | startup_jiffies_counter(); |
154 | 164 | ||
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index 716a221df2f9..c924a1dd3323 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c | |||
@@ -45,8 +45,13 @@ | |||
45 | #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" | 45 | #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef CONFIG_SMP | ||
49 | struct pt_regs *___frame[NR_CPUS]; /* current frame pointer */ | ||
50 | EXPORT_SYMBOL(___frame); | ||
51 | #else /* CONFIG_SMP */ | ||
48 | struct pt_regs *__frame; /* current frame pointer */ | 52 | struct pt_regs *__frame; /* current frame pointer */ |
49 | EXPORT_SYMBOL(__frame); | 53 | EXPORT_SYMBOL(__frame); |
54 | #endif /* CONFIG_SMP */ | ||
50 | 55 | ||
51 | int kstack_depth_to_print = 24; | 56 | int kstack_depth_to_print = 24; |
52 | 57 | ||
@@ -221,11 +226,14 @@ void show_registers_only(struct pt_regs *regs) | |||
221 | printk(KERN_EMERG "threadinfo=%p task=%p)\n", | 226 | printk(KERN_EMERG "threadinfo=%p task=%p)\n", |
222 | current_thread_info(), current); | 227 | current_thread_info(), current); |
223 | 228 | ||
224 | if ((unsigned long) current >= 0x90000000UL && | 229 | if ((unsigned long) current >= PAGE_OFFSET && |
225 | (unsigned long) current < 0x94000000UL) | 230 | (unsigned long) current < (unsigned long)high_memory) |
226 | printk(KERN_EMERG "Process %s (pid: %d)\n", | 231 | printk(KERN_EMERG "Process %s (pid: %d)\n", |
227 | current->comm, current->pid); | 232 | current->comm, current->pid); |
228 | 233 | ||
234 | #ifdef CONFIG_SMP | ||
235 | printk(KERN_EMERG "CPUID: %08x\n", CPUID); | ||
236 | #endif | ||
229 | printk(KERN_EMERG "CPUP: %04hx\n", CPUP); | 237 | printk(KERN_EMERG "CPUP: %04hx\n", CPUP); |
230 | printk(KERN_EMERG "TBR: %08x\n", TBR); | 238 | printk(KERN_EMERG "TBR: %08x\n", TBR); |
231 | printk(KERN_EMERG "DEAR: %08x\n", DEAR); | 239 | printk(KERN_EMERG "DEAR: %08x\n", DEAR); |
@@ -521,8 +529,12 @@ void __init set_intr_stub(enum exception_code code, void *handler) | |||
521 | { | 529 | { |
522 | unsigned long addr; | 530 | unsigned long addr; |
523 | u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); | 531 | u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); |
532 | unsigned long flags; | ||
524 | 533 | ||
525 | addr = (unsigned long) handler - (unsigned long) vector; | 534 | addr = (unsigned long) handler - (unsigned long) vector; |
535 | |||
536 | flags = arch_local_cli_save(); | ||
537 | |||
526 | vector[0] = 0xdc; /* JMP handler */ | 538 | vector[0] = 0xdc; /* JMP handler */ |
527 | vector[1] = addr; | 539 | vector[1] = addr; |
528 | vector[2] = addr >> 8; | 540 | vector[2] = addr >> 8; |
@@ -532,6 +544,8 @@ void __init set_intr_stub(enum exception_code code, void *handler) | |||
532 | vector[6] = 0xcb; | 544 | vector[6] = 0xcb; |
533 | vector[7] = 0xcb; | 545 | vector[7] = 0xcb; |
534 | 546 | ||
547 | arch_local_irq_restore(flags); | ||
548 | |||
535 | #ifndef CONFIG_MN10300_CACHE_SNOOP | 549 | #ifndef CONFIG_MN10300_CACHE_SNOOP |
536 | mn10300_dcache_flush_inv(); | 550 | mn10300_dcache_flush_inv(); |
537 | mn10300_icache_inv(); | 551 | mn10300_icache_inv(); |
diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c index fdf6f710f94e..8e7ceb8ba33d 100644 --- a/arch/mn10300/lib/delay.c +++ b/arch/mn10300/lib/delay.c | |||
@@ -38,14 +38,14 @@ EXPORT_SYMBOL(__delay); | |||
38 | */ | 38 | */ |
39 | void __udelay(unsigned long usecs) | 39 | void __udelay(unsigned long usecs) |
40 | { | 40 | { |
41 | signed long ioclk, stop; | 41 | unsigned long start, stop, cnt; |
42 | 42 | ||
43 | /* usecs * CLK / 1E6 */ | 43 | /* usecs * CLK / 1E6 */ |
44 | stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000); | 44 | stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000); |
45 | stop = TMTSCBC - stop; | 45 | start = TMTSCBC; |
46 | 46 | ||
47 | do { | 47 | do { |
48 | ioclk = TMTSCBC; | 48 | cnt = start - TMTSCBC; |
49 | } while (stop < ioclk); | 49 | } while (cnt < stop); |
50 | } | 50 | } |
51 | EXPORT_SYMBOL(__udelay); | 51 | EXPORT_SYMBOL(__udelay); |
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 906e4c8f9ab1..59c3da49d9d9 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c | |||
@@ -39,10 +39,6 @@ void bust_spinlocks(int yes) | |||
39 | { | 39 | { |
40 | if (yes) { | 40 | if (yes) { |
41 | oops_in_progress = 1; | 41 | oops_in_progress = 1; |
42 | #ifdef CONFIG_SMP | ||
43 | /* Many serial drivers do __global_cli() */ | ||
44 | global_irq_lock = 0; | ||
45 | #endif | ||
46 | } else { | 42 | } else { |
47 | int loglevel_save = console_loglevel; | 43 | int loglevel_save = console_loglevel; |
48 | #ifdef CONFIG_VT | 44 | #ifdef CONFIG_VT |
@@ -334,10 +330,10 @@ no_context: | |||
334 | */ | 330 | */ |
335 | out_of_memory: | 331 | out_of_memory: |
336 | up_read(&mm->mmap_sem); | 332 | up_read(&mm->mmap_sem); |
337 | if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR) | 333 | printk(KERN_ALERT "VM: killing process %s\n", tsk->comm); |
338 | goto no_context; | 334 | if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) |
339 | pagefault_out_of_memory(); | 335 | do_exit(SIGKILL); |
340 | return; | 336 | goto no_context; |
341 | 337 | ||
342 | do_sigbus: | 338 | do_sigbus: |
343 | up_read(&mm->mmap_sem); | 339 | up_read(&mm->mmap_sem); |
diff --git a/arch/mn10300/proc-mn103e010/include/proc/clock.h b/arch/mn10300/proc-mn103e010/include/proc/clock.h index aa23e147d620..704a819f1f4b 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/clock.h +++ b/arch/mn10300/proc-mn103e010/include/proc/clock.h | |||
@@ -13,6 +13,4 @@ | |||
13 | 13 | ||
14 | #include <unit/clock.h> | 14 | #include <unit/clock.h> |
15 | 15 | ||
16 | #define MN10300_WDCLK MN10300_IOCLK | ||
17 | |||
18 | #endif /* _ASM_PROC_CLOCK_H */ | 16 | #endif /* _ASM_PROC_CLOCK_H */ |
diff --git a/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h new file mode 100644 index 000000000000..f537801a44ba --- /dev/null +++ b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef _ASM_PROC_INTCTL_REGS_H | ||
2 | #define _ASM_PROC_INTCTL_REGS_H | ||
3 | |||
4 | #ifndef _ASM_INTCTL_REGS_H | ||
5 | # error "please don't include this file directly" | ||
6 | #endif | ||
7 | |||
8 | /* intr acceptance group reg */ | ||
9 | #define IAGR __SYSREG(0xd4000100, u16) | ||
10 | |||
11 | /* group number register */ | ||
12 | #define IAGR_GN 0x00fc | ||
13 | |||
14 | #define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3) | ||
15 | |||
16 | #define __SET_XIRQ_TRIGGER(X, Y, Z) \ | ||
17 | ({ \ | ||
18 | typeof(Z) x = (Z); \ | ||
19 | x &= ~(3 << ((X) * 2)); \ | ||
20 | x |= ((Y) & 3) << ((X) * 2); \ | ||
21 | (Z) = x; \ | ||
22 | }) | ||
23 | |||
24 | /* external pin intr spec reg */ | ||
25 | #define EXTMD __SYSREG(0xd4000200, u16) | ||
26 | #define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD) | ||
27 | #define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD) | ||
28 | |||
29 | #endif /* _ASM_PROC_INTCTL_REGS_H */ | ||
diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c index 0cee7878bee9..27b97980dca4 100644 --- a/arch/mn10300/proc-mn103e010/proc-init.c +++ b/arch/mn10300/proc-mn103e010/proc-init.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <asm/fpu.h> | 12 | #include <asm/fpu.h> |
13 | #include <asm/rtc.h> | 13 | #include <asm/rtc.h> |
14 | #include <asm/busctl-regs.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * initialise the on-silicon processor peripherals | 17 | * initialise the on-silicon processor peripherals |
@@ -75,3 +76,37 @@ asmlinkage void __init processor_init(void) | |||
75 | 76 | ||
76 | calibrate_clock(); | 77 | calibrate_clock(); |
77 | } | 78 | } |
79 | |||
80 | /* | ||
81 | * determine the memory size and base from the memory controller regs | ||
82 | */ | ||
83 | void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size) | ||
84 | { | ||
85 | unsigned long base, size; | ||
86 | |||
87 | *mem_base = 0; | ||
88 | *mem_size = 0; | ||
89 | |||
90 | base = SDBASE(0); | ||
91 | if (base & SDBASE_CE) { | ||
92 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
93 | size = ~size + 1; | ||
94 | base &= SDBASE_CBA; | ||
95 | |||
96 | printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); | ||
97 | *mem_size += size; | ||
98 | *mem_base = base; | ||
99 | } | ||
100 | |||
101 | base = SDBASE(1); | ||
102 | if (base & SDBASE_CE) { | ||
103 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
104 | size = ~size + 1; | ||
105 | base &= SDBASE_CBA; | ||
106 | |||
107 | printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); | ||
108 | *mem_size += size; | ||
109 | if (*mem_base == 0) | ||
110 | *mem_base = base; | ||
111 | } | ||
112 | } | ||
diff --git a/arch/mn10300/proc-mn2ws0050/Makefile b/arch/mn10300/proc-mn2ws0050/Makefile new file mode 100644 index 000000000000..d4ca13309a85 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | obj-y := proc-init.o | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h new file mode 100644 index 000000000000..cafd7b5b55b4 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* Cache specification | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
7 | * Modifications: | ||
8 | * 13-Nov-2006 MEI Add L1_CACHE_SHIFT_MAX definition. | ||
9 | * 29-Jul-2008 MEI Add define for MN10300_HAS_AREAPURGE_REG. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | #ifndef _ASM_PROC_CACHE_H | ||
17 | #define _ASM_PROC_CACHE_H | ||
18 | |||
19 | /* | ||
20 | * L1 cache | ||
21 | */ | ||
22 | #define L1_CACHE_NWAYS 4 /* number of ways in caches */ | ||
23 | #define L1_CACHE_NENTRIES 128 /* number of entries in each way */ | ||
24 | #define L1_CACHE_BYTES 32 /* bytes per entry */ | ||
25 | #define L1_CACHE_SHIFT 5 /* shift for bytes per entry */ | ||
26 | #define L1_CACHE_WAYDISP 0x1000 /* distance from one way to the next */ | ||
27 | |||
28 | #define L1_CACHE_TAG_VALID 0x00000001 /* cache tag valid bit */ | ||
29 | #define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ | ||
30 | #define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */ | ||
31 | #define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ | ||
32 | |||
33 | /* | ||
34 | * specification of the interval between interrupt checking intervals whilst | ||
35 | * managing the cache with the interrupts disabled | ||
36 | */ | ||
37 | #define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4 | ||
38 | |||
39 | /* | ||
40 | * The size of range at which it becomes more economical to just flush the | ||
41 | * whole cache rather than trying to flush the specified range. | ||
42 | */ | ||
43 | #define MN10300_DCACHE_FLUSH_BORDER \ | ||
44 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
45 | #define MN10300_DCACHE_FLUSH_INV_BORDER \ | ||
46 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
47 | |||
48 | #endif /* _ASM_PROC_CACHE_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/clock.h b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h new file mode 100644 index 000000000000..fe4c0a4a53a2 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* clock.h: proc-specific clocks | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
7 | * Modifications: | ||
8 | * 23-Feb-2007 MEI Delete define for watchdog timer. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | #ifndef _ASM_PROC_CLOCK_H | ||
16 | #define _ASM_PROC_CLOCK_H | ||
17 | |||
18 | #include <unit/clock.h> | ||
19 | |||
20 | #endif /* _ASM_PROC_CLOCK_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h new file mode 100644 index 000000000000..4c4319e241d1 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* MN2WS0050 on-board DMA controller registers | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _ASM_PROC_DMACTL_REGS_H | ||
12 | #define _ASM_PROC_DMACTL_REGS_H | ||
13 | |||
14 | #include <asm/cpu-regs.h> | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | |||
18 | /* DMA registers */ | ||
19 | #define DMxCTR(N) __SYSREG(0xd4005000+(N*0x100), u32) /* control reg */ | ||
20 | #define DMxCTR_BG 0x0000001f /* transfer request source */ | ||
21 | #define DMxCTR_BG_SOFT 0x00000000 /* - software source */ | ||
22 | #define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */ | ||
23 | #define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */ | ||
24 | #define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */ | ||
25 | #define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */ | ||
26 | #define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */ | ||
27 | #define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */ | ||
28 | #define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */ | ||
29 | #define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */ | ||
30 | #define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */ | ||
31 | #define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */ | ||
32 | #define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */ | ||
33 | #define DMxCTR_BG_RYBY 0x0000000d /* - NAND Flash RY/BY request source */ | ||
34 | #define DMxCTR_BG_RMC 0x0000000e /* - remote controller output */ | ||
35 | #define DMxCTR_BG_XIRQ12 0x00000011 /* - XIRQ12 pin interrupt source */ | ||
36 | #define DMxCTR_BG_XIRQ13 0x00000012 /* - XIRQ13 pin interrupt source */ | ||
37 | #define DMxCTR_BG_TCK 0x00000014 /* - tick timer underflow */ | ||
38 | #define DMxCTR_BG_SC4TX 0x00000019 /* - serial port4 transmission */ | ||
39 | #define DMxCTR_BG_SC4RX 0x0000001a /* - serial port4 reception */ | ||
40 | #define DMxCTR_BG_SC5TX 0x0000001b /* - serial port5 transmission */ | ||
41 | #define DMxCTR_BG_SC5RX 0x0000001c /* - serial port5 reception */ | ||
42 | #define DMxCTR_BG_SC6TX 0x0000001d /* - serial port6 transmission */ | ||
43 | #define DMxCTR_BG_SC6RX 0x0000001e /* - serial port6 reception */ | ||
44 | #define DMxCTR_BG_TMSUFLOW 0x0000001f /* - timestamp timer underflow */ | ||
45 | #define DMxCTR_SAM 0x00000060 /* DMA transfer src addr mode */ | ||
46 | #define DMxCTR_SAM_INCR 0x00000000 /* - increment */ | ||
47 | #define DMxCTR_SAM_DECR 0x00000020 /* - decrement */ | ||
48 | #define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */ | ||
49 | #define DMxCTR_DAM 0x00000300 /* DMA transfer dest addr mode */ | ||
50 | #define DMxCTR_DAM_INCR 0x00000000 /* - increment */ | ||
51 | #define DMxCTR_DAM_DECR 0x00000100 /* - decrement */ | ||
52 | #define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */ | ||
53 | #define DMxCTR_UT 0x00006000 /* DMA transfer unit */ | ||
54 | #define DMxCTR_UT_1 0x00000000 /* - 1 byte */ | ||
55 | #define DMxCTR_UT_2 0x00002000 /* - 2 byte */ | ||
56 | #define DMxCTR_UT_4 0x00004000 /* - 4 byte */ | ||
57 | #define DMxCTR_UT_16 0x00006000 /* - 16 byte */ | ||
58 | #define DMxCTR_RRE 0x00008000 /* DMA round robin enable */ | ||
59 | #define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */ | ||
60 | #define DMxCTR_RQM 0x00060000 /* external request input source mode */ | ||
61 | #define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */ | ||
62 | #define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */ | ||
63 | #define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */ | ||
64 | #define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */ | ||
65 | #define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */ | ||
66 | #define DMxCTR_PERR 0x40000000 /* DMA transfer parameter error flag */ | ||
67 | #define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */ | ||
68 | |||
69 | #define DMxSRC(N) __SYSREG(0xd4005004+(N*0x100), u32) /* control reg */ | ||
70 | |||
71 | #define DMxDST(N) __SYSREG(0xd4005008+(N*0x100), u32) /* source addr reg */ | ||
72 | |||
73 | #define DMxSIZ(N) __SYSREG(0xd400500c+(N*0x100), u32) /* dest addr reg */ | ||
74 | #define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */ | ||
75 | |||
76 | #define DMxCYC(N) __SYSREG(0xd4005010+(N*0x100), u32) /* intermittent size reg */ | ||
77 | #define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */ | ||
78 | |||
79 | #define DM0IRQ 16 /* DMA channel 0 complete IRQ */ | ||
80 | #define DM1IRQ 17 /* DMA channel 1 complete IRQ */ | ||
81 | #define DM2IRQ 18 /* DMA channel 2 complete IRQ */ | ||
82 | #define DM3IRQ 19 /* DMA channel 3 complete IRQ */ | ||
83 | |||
84 | #define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */ | ||
85 | #define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */ | ||
86 | #define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */ | ||
87 | #define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */ | ||
88 | |||
89 | #ifndef __ASSEMBLY__ | ||
90 | |||
91 | struct mn10300_dmactl_regs { | ||
92 | u32 ctr; | ||
93 | const void *src; | ||
94 | void *dst; | ||
95 | u32 siz; | ||
96 | u32 cyc; | ||
97 | } __attribute__((aligned(0x100))); | ||
98 | |||
99 | #endif /* __ASSEMBLY__ */ | ||
100 | |||
101 | #endif /* __KERNEL__ */ | ||
102 | |||
103 | #endif /* _ASM_PROC_DMACTL_REGS_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h new file mode 100644 index 000000000000..a1e977273d19 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef _ASM_PROC_INTCTL_REGS_H | ||
2 | #define _ASM_PROC_INTCTL_REGS_H | ||
3 | |||
4 | #ifndef _ASM_INTCTL_REGS_H | ||
5 | # error "please don't include this file directly" | ||
6 | #endif | ||
7 | |||
8 | /* intr acceptance group reg */ | ||
9 | #define IAGR __SYSREG(0xd4000100, u16) | ||
10 | |||
11 | /* group number register */ | ||
12 | #define IAGR_GN 0x003fc | ||
13 | |||
14 | #define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3) | ||
15 | |||
16 | #define __SET_XIRQ_TRIGGER(X, Y, Z) \ | ||
17 | ({ \ | ||
18 | typeof(Z) x = (Z); \ | ||
19 | x &= ~(3 << ((X) * 2)); \ | ||
20 | x |= ((Y) & 3) << ((X) * 2); \ | ||
21 | (Z) = x; \ | ||
22 | }) | ||
23 | |||
24 | /* external pin intr spec reg */ | ||
25 | #define EXTMD0 __SYSREG(0xd4000200, u32) | ||
26 | #define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD0) | ||
27 | #define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD0) | ||
28 | |||
29 | #endif /* _ASM_PROC_INTCTL_REGS_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/irq.h b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h new file mode 100644 index 000000000000..37777a85ab6f --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* MN2WS0050 on-board interrupt controller registers | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
7 | * Modifications: | ||
8 | * 13-Nov-2006 MEI Define extended IRQ number for SMP support. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef _PROC_IRQ_H | ||
17 | #define _PROC_IRQ_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #define GxICR_NUM_IRQS 163 | ||
22 | #ifdef CONFIG_SMP | ||
23 | #define GxICR_NUM_EXT_IRQS 197 | ||
24 | #endif /* CONFIG_SMP */ | ||
25 | |||
26 | #define GxICR_NUM_XIRQS 16 | ||
27 | |||
28 | #define XIRQ0 34 | ||
29 | #define XIRQ1 35 | ||
30 | #define XIRQ2 36 | ||
31 | #define XIRQ3 37 | ||
32 | #define XIRQ4 38 | ||
33 | #define XIRQ5 39 | ||
34 | #define XIRQ6 40 | ||
35 | #define XIRQ7 41 | ||
36 | #define XIRQ8 42 | ||
37 | #define XIRQ9 43 | ||
38 | #define XIRQ10 44 | ||
39 | #define XIRQ11 45 | ||
40 | #define XIRQ12 46 | ||
41 | #define XIRQ13 47 | ||
42 | #define XIRQ14 48 | ||
43 | #define XIRQ15 49 | ||
44 | |||
45 | #define XIRQ2IRQ(num) (XIRQ0 + num) | ||
46 | |||
47 | #endif /* __KERNEL__ */ | ||
48 | |||
49 | #endif /* _PROC_IRQ_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h new file mode 100644 index 000000000000..84448f3828b3 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h | |||
@@ -0,0 +1,120 @@ | |||
1 | /* NAND flash interface register definitions | ||
2 | * | ||
3 | * Copyright (C) 2008-2009 Panasonic Corporation | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef _PROC_NAND_REGS_H_ | ||
17 | #define _PROC_NAND_REGS_H_ | ||
18 | |||
19 | /* command register */ | ||
20 | #define FCOMMAND_0 __SYSREG(0xd8f00000, u8) /* fcommand[24:31] */ | ||
21 | #define FCOMMAND_1 __SYSREG(0xd8f00001, u8) /* fcommand[16:23] */ | ||
22 | #define FCOMMAND_2 __SYSREG(0xd8f00002, u8) /* fcommand[8:15] */ | ||
23 | #define FCOMMAND_3 __SYSREG(0xd8f00003, u8) /* fcommand[0:7] */ | ||
24 | |||
25 | /* for dma 16 byte trans, use FCOMMAND2 register */ | ||
26 | #define FCOMMAND2_0 __SYSREG(0xd8f00110, u8) /* fcommand2[24:31] */ | ||
27 | #define FCOMMAND2_1 __SYSREG(0xd8f00111, u8) /* fcommand2[16:23] */ | ||
28 | #define FCOMMAND2_2 __SYSREG(0xd8f00112, u8) /* fcommand2[8:15] */ | ||
29 | #define FCOMMAND2_3 __SYSREG(0xd8f00113, u8) /* fcommand2[0:7] */ | ||
30 | |||
31 | #define FCOMMAND_FIEN 0x80 /* nand flash I/F enable */ | ||
32 | #define FCOMMAND_BW_8BIT 0x00 /* 8bit bus width */ | ||
33 | #define FCOMMAND_BW_16BIT 0x40 /* 16bit bus width */ | ||
34 | #define FCOMMAND_BLOCKSZ_SMALL 0x00 /* small block */ | ||
35 | #define FCOMMAND_BLOCKSZ_LARGE 0x20 /* large block */ | ||
36 | #define FCOMMAND_DMASTART 0x10 /* dma start */ | ||
37 | #define FCOMMAND_RYBY 0x08 /* ready/busy flag */ | ||
38 | #define FCOMMAND_RYBYINTMSK 0x04 /* mask ready/busy interrupt */ | ||
39 | #define FCOMMAND_XFWP 0x02 /* write protect enable */ | ||
40 | #define FCOMMAND_XFCE 0x01 /* flash device disable */ | ||
41 | #define FCOMMAND_SEQKILL 0x10 /* stop seq-read */ | ||
42 | #define FCOMMAND_ANUM 0x07 /* address cycle */ | ||
43 | #define FCOMMAND_ANUM_NONE 0x00 /* address cycle none */ | ||
44 | #define FCOMMAND_ANUM_1CYC 0x01 /* address cycle 1cycle */ | ||
45 | #define FCOMMAND_ANUM_2CYC 0x02 /* address cycle 2cycle */ | ||
46 | #define FCOMMAND_ANUM_3CYC 0x03 /* address cycle 3cycle */ | ||
47 | #define FCOMMAND_ANUM_4CYC 0x04 /* address cycle 4cycle */ | ||
48 | #define FCOMMAND_ANUM_5CYC 0x05 /* address cycle 5cycle */ | ||
49 | #define FCOMMAND_FCMD_READ0 0x00 /* read1 command */ | ||
50 | #define FCOMMAND_FCMD_SEQIN 0x80 /* page program 1st command */ | ||
51 | #define FCOMMAND_FCMD_PAGEPROG 0x10 /* page program 2nd command */ | ||
52 | #define FCOMMAND_FCMD_RESET 0xff /* reset command */ | ||
53 | #define FCOMMAND_FCMD_ERASE1 0x60 /* erase 1st command */ | ||
54 | #define FCOMMAND_FCMD_ERASE2 0xd0 /* erase 2nd command */ | ||
55 | #define FCOMMAND_FCMD_STATUS 0x70 /* read status command */ | ||
56 | #define FCOMMAND_FCMD_READID 0x90 /* read id command */ | ||
57 | #define FCOMMAND_FCMD_READOOB 0x50 /* read3 command */ | ||
58 | /* address register */ | ||
59 | #define FADD __SYSREG(0xd8f00004, u32) | ||
60 | /* address register 2 */ | ||
61 | #define FADD2 __SYSREG(0xd8f00008, u32) | ||
62 | /* error judgement register */ | ||
63 | #define FJUDGE __SYSREG(0xd8f0000c, u32) | ||
64 | #define FJUDGE_NOERR 0x0 /* no error */ | ||
65 | #define FJUDGE_1BITERR 0x1 /* 1bit error in data area */ | ||
66 | #define FJUDGE_PARITYERR 0x2 /* parity error */ | ||
67 | #define FJUDGE_UNCORRECTABLE 0x3 /* uncorrectable error */ | ||
68 | #define FJUDGE_ERRJDG_MSK 0x3 /* mask of judgement result */ | ||
69 | /* 1st ECC store register */ | ||
70 | #define FECC11 __SYSREG(0xd8f00010, u32) | ||
71 | /* 2nd ECC store register */ | ||
72 | #define FECC12 __SYSREG(0xd8f00014, u32) | ||
73 | /* 3rd ECC store register */ | ||
74 | #define FECC21 __SYSREG(0xd8f00018, u32) | ||
75 | /* 4th ECC store register */ | ||
76 | #define FECC22 __SYSREG(0xd8f0001c, u32) | ||
77 | /* 5th ECC store register */ | ||
78 | #define FECC31 __SYSREG(0xd8f00020, u32) | ||
79 | /* 6th ECC store register */ | ||
80 | #define FECC32 __SYSREG(0xd8f00024, u32) | ||
81 | /* 7th ECC store register */ | ||
82 | #define FECC41 __SYSREG(0xd8f00028, u32) | ||
83 | /* 8th ECC store register */ | ||
84 | #define FECC42 __SYSREG(0xd8f0002c, u32) | ||
85 | /* data register */ | ||
86 | #define FDATA __SYSREG(0xd8f00030, u32) | ||
87 | /* access pulse register */ | ||
88 | #define FPWS __SYSREG(0xd8f00100, u32) | ||
89 | #define FPWS_PWS1W_2CLK 0x00000000 /* write pulse width 1clock */ | ||
90 | #define FPWS_PWS1W_3CLK 0x01000000 /* write pulse width 2clock */ | ||
91 | #define FPWS_PWS1W_4CLK 0x02000000 /* write pulse width 4clock */ | ||
92 | #define FPWS_PWS1W_5CLK 0x03000000 /* write pulse width 5clock */ | ||
93 | #define FPWS_PWS1W_6CLK 0x04000000 /* write pulse width 6clock */ | ||
94 | #define FPWS_PWS1W_7CLK 0x05000000 /* write pulse width 7clock */ | ||
95 | #define FPWS_PWS1W_8CLK 0x06000000 /* write pulse width 8clock */ | ||
96 | #define FPWS_PWS1R_3CLK 0x00010000 /* read pulse width 3clock */ | ||
97 | #define FPWS_PWS1R_4CLK 0x00020000 /* read pulse width 4clock */ | ||
98 | #define FPWS_PWS1R_5CLK 0x00030000 /* read pulse width 5clock */ | ||
99 | #define FPWS_PWS1R_6CLK 0x00040000 /* read pulse width 6clock */ | ||
100 | #define FPWS_PWS1R_7CLK 0x00050000 /* read pulse width 7clock */ | ||
101 | #define FPWS_PWS1R_8CLK 0x00060000 /* read pulse width 8clock */ | ||
102 | #define FPWS_PWS2W_2CLK 0x00000100 /* write pulse interval 2clock */ | ||
103 | #define FPWS_PWS2W_3CLK 0x00000200 /* write pulse interval 3clock */ | ||
104 | #define FPWS_PWS2W_4CLK 0x00000300 /* write pulse interval 4clock */ | ||
105 | #define FPWS_PWS2W_5CLK 0x00000400 /* write pulse interval 5clock */ | ||
106 | #define FPWS_PWS2W_6CLK 0x00000500 /* write pulse interval 6clock */ | ||
107 | #define FPWS_PWS2R_2CLK 0x00000001 /* read pulse interval 2clock */ | ||
108 | #define FPWS_PWS2R_3CLK 0x00000002 /* read pulse interval 3clock */ | ||
109 | #define FPWS_PWS2R_4CLK 0x00000003 /* read pulse interval 4clock */ | ||
110 | #define FPWS_PWS2R_5CLK 0x00000004 /* read pulse interval 5clock */ | ||
111 | #define FPWS_PWS2R_6CLK 0x00000005 /* read pulse interval 6clock */ | ||
112 | /* command register 2 */ | ||
113 | #define FCOMMAND2 __SYSREG(0xd8f00110, u32) | ||
114 | /* transfer frequency register */ | ||
115 | #define FNUM __SYSREG(0xd8f00114, u32) | ||
116 | #define FSDATA_ADDR 0xd8f00400 | ||
117 | /* active data register */ | ||
118 | #define FSDATA __SYSREG(FSDATA_ADDR, u32) | ||
119 | |||
120 | #endif /* _PROC_NAND_REGS_H_ */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/proc.h b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h new file mode 100644 index 000000000000..90d5cadd05bd --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* proc.h: MN2WS0050 processor description | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_PROC_PROC_H | ||
13 | #define _ASM_PROC_PROC_H | ||
14 | |||
15 | #define PROCESSOR_VENDOR_NAME "Panasonic" | ||
16 | #define PROCESSOR_MODEL_NAME "mn2ws0050" | ||
17 | |||
18 | #endif /* _ASM_PROC_PROC_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h new file mode 100644 index 000000000000..22f277fbb4de --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* MN10300/AM33v2 Microcontroller SMP registers | ||
2 | * | ||
3 | * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd. | ||
4 | * All Rights Reserved. | ||
5 | * Created: | ||
6 | * 13-Nov-2006 MEI Add extended cache and atomic operation register | ||
7 | * for SMP support. | ||
8 | * 23-Feb-2007 MEI Add define for gdbstub SMP. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef _ASM_PROC_SMP_REGS_H | ||
17 | #define _ASM_PROC_SMP_REGS_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | #include <linux/types.h> | ||
23 | #endif | ||
24 | #include <asm/cpu-regs.h> | ||
25 | |||
26 | /* | ||
27 | * Reference to the interrupt controllers of other CPUs | ||
28 | */ | ||
29 | #define CROSS_ICR_CPU_SHIFT 16 | ||
30 | |||
31 | #define CROSS_GxICR(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \ | ||
32 | ((X) >= 64 && (X) < 192) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u16) | ||
33 | #define CROSS_GxICR_u8(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \ | ||
34 | (((X) >= 64) && ((X) < 192)) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u8) | ||
35 | |||
36 | /* CPU ID register */ | ||
37 | #define CPUID __SYSREGC(0xc0000054, u32) | ||
38 | #define CPUID_MASK 0x00000007 /* CPU ID mask */ | ||
39 | |||
40 | /* extended cache control register */ | ||
41 | #define ECHCTR __SYSREG(0xc0000c20, u32) | ||
42 | #define ECHCTR_IBCM 0x00000001 /* instruction cache broad cast mask */ | ||
43 | #define ECHCTR_DBCM 0x00000002 /* data cache broad cast mask */ | ||
44 | #define ECHCTR_ISPM 0x00000004 /* instruction cache snoop mask */ | ||
45 | #define ECHCTR_DSPM 0x00000008 /* data cache snoop mask */ | ||
46 | |||
47 | #define NMIAGR __SYSREG(0xd400013c, u16) | ||
48 | #define NMIAGR_GN 0x03fc | ||
49 | |||
50 | #endif /* __KERNEL__ */ | ||
51 | #endif /* _ASM_PROC_SMP_REGS_H */ | ||
diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c new file mode 100644 index 000000000000..c58249b9525a --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/proc-init.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* MN2WS0050 processor initialisation | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | |||
17 | #include <asm/processor.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/uaccess.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/atomic.h> | ||
22 | #include <asm/smp.h> | ||
23 | #include <asm/pgalloc.h> | ||
24 | #include <asm/busctl-regs.h> | ||
25 | #include <unit/timex.h> | ||
26 | #include <asm/fpu.h> | ||
27 | #include <asm/rtc.h> | ||
28 | |||
29 | #define MEMCONF __SYSREGC(0xdf800400, u32) | ||
30 | |||
31 | /* | ||
32 | * initialise the on-silicon processor peripherals | ||
33 | */ | ||
34 | asmlinkage void __init processor_init(void) | ||
35 | { | ||
36 | int loop; | ||
37 | |||
38 | /* set up the exception table first */ | ||
39 | for (loop = 0x000; loop < 0x400; loop += 8) | ||
40 | __set_intr_stub(loop, __common_exception); | ||
41 | |||
42 | __set_intr_stub(EXCEP_ITLBMISS, itlb_miss); | ||
43 | __set_intr_stub(EXCEP_DTLBMISS, dtlb_miss); | ||
44 | __set_intr_stub(EXCEP_IAERROR, itlb_aerror); | ||
45 | __set_intr_stub(EXCEP_DAERROR, dtlb_aerror); | ||
46 | __set_intr_stub(EXCEP_BUSERROR, raw_bus_error); | ||
47 | __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault); | ||
48 | __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled); | ||
49 | __set_intr_stub(EXCEP_SYSCALL0, system_call); | ||
50 | |||
51 | __set_intr_stub(EXCEP_NMI, nmi_handler); | ||
52 | __set_intr_stub(EXCEP_WDT, nmi_handler); | ||
53 | __set_intr_stub(EXCEP_IRQ_LEVEL0, irq_handler); | ||
54 | __set_intr_stub(EXCEP_IRQ_LEVEL1, irq_handler); | ||
55 | __set_intr_stub(EXCEP_IRQ_LEVEL2, irq_handler); | ||
56 | __set_intr_stub(EXCEP_IRQ_LEVEL3, irq_handler); | ||
57 | __set_intr_stub(EXCEP_IRQ_LEVEL4, irq_handler); | ||
58 | __set_intr_stub(EXCEP_IRQ_LEVEL5, irq_handler); | ||
59 | __set_intr_stub(EXCEP_IRQ_LEVEL6, irq_handler); | ||
60 | |||
61 | IVAR0 = EXCEP_IRQ_LEVEL0; | ||
62 | IVAR1 = EXCEP_IRQ_LEVEL1; | ||
63 | IVAR2 = EXCEP_IRQ_LEVEL2; | ||
64 | IVAR3 = EXCEP_IRQ_LEVEL3; | ||
65 | IVAR4 = EXCEP_IRQ_LEVEL4; | ||
66 | IVAR5 = EXCEP_IRQ_LEVEL5; | ||
67 | IVAR6 = EXCEP_IRQ_LEVEL6; | ||
68 | |||
69 | #ifndef CONFIG_MN10300_HAS_CACHE_SNOOP | ||
70 | mn10300_dcache_flush_inv(); | ||
71 | mn10300_icache_inv(); | ||
72 | #endif | ||
73 | |||
74 | /* disable all interrupts and set to priority 6 (lowest) */ | ||
75 | #ifdef CONFIG_SMP | ||
76 | for (loop = 0; loop < GxICR_NUM_IRQS; loop++) | ||
77 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | ||
78 | #else /* !CONFIG_SMP */ | ||
79 | for (loop = 0; loop < NR_IRQS; loop++) | ||
80 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | ||
81 | #endif /* !CONFIG_SMP */ | ||
82 | |||
83 | /* clear the timers */ | ||
84 | TM0MD = 0; | ||
85 | TM1MD = 0; | ||
86 | TM2MD = 0; | ||
87 | TM3MD = 0; | ||
88 | TM4MD = 0; | ||
89 | TM5MD = 0; | ||
90 | TM6MD = 0; | ||
91 | TM6MDA = 0; | ||
92 | TM6MDB = 0; | ||
93 | TM7MD = 0; | ||
94 | TM8MD = 0; | ||
95 | TM9MD = 0; | ||
96 | TM10MD = 0; | ||
97 | TM11MD = 0; | ||
98 | TM12MD = 0; | ||
99 | TM13MD = 0; | ||
100 | TM14MD = 0; | ||
101 | TM15MD = 0; | ||
102 | |||
103 | calibrate_clock(); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * determine the memory size and base from the memory controller regs | ||
108 | */ | ||
109 | void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size) | ||
110 | { | ||
111 | unsigned long memconf = MEMCONF; | ||
112 | unsigned long size = 0; /* order: MByte */ | ||
113 | |||
114 | *mem_base = 0x90000000; /* fixed address */ | ||
115 | |||
116 | switch (memconf & 0x00000003) { | ||
117 | case 0x01: | ||
118 | size = 256 / 8; /* 256 Mbit per chip */ | ||
119 | break; | ||
120 | case 0x02: | ||
121 | size = 512 / 8; /* 512 Mbit per chip */ | ||
122 | break; | ||
123 | case 0x03: | ||
124 | size = 1024 / 8; /* 1 Gbit per chip */ | ||
125 | break; | ||
126 | default: | ||
127 | panic("Invalid SDRAM size"); | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | printk(KERN_INFO "DDR2-SDRAM: %luMB x 2 @%08lx\n", size, *mem_base); | ||
132 | |||
133 | *mem_size = (size * 2) << 20; | ||
134 | } | ||
diff --git a/arch/mn10300/unit-asb2303/include/unit/clock.h b/arch/mn10300/unit-asb2303/include/unit/clock.h index 2a0bf79ab968..0316907a012e 100644 --- a/arch/mn10300/unit-asb2303/include/unit/clock.h +++ b/arch/mn10300/unit-asb2303/include/unit/clock.h | |||
@@ -14,32 +14,11 @@ | |||
14 | 14 | ||
15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ |
16 | 16 | ||
17 | #ifdef CONFIG_MN10300_RTC | ||
18 | |||
19 | extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */ | ||
20 | extern unsigned long mn10300_iobclk; | ||
21 | extern unsigned long mn10300_tsc_per_HZ; | ||
22 | |||
23 | #define MN10300_IOCLK mn10300_ioclk | ||
24 | /* If this processors has a another clock, uncomment the below. */ | ||
25 | /* #define MN10300_IOBCLK mn10300_iobclk */ | ||
26 | |||
27 | #else /* !CONFIG_MN10300_RTC */ | ||
28 | |||
29 | #define MN10300_IOCLK 33333333UL | 17 | #define MN10300_IOCLK 33333333UL |
30 | /* #define MN10300_IOBCLK 66666666UL */ | 18 | /* #define MN10300_IOBCLK 66666666UL */ |
31 | 19 | ||
32 | #endif /* !CONFIG_MN10300_RTC */ | ||
33 | |||
34 | #define MN10300_JCCLK MN10300_IOCLK | ||
35 | #define MN10300_TSCCLK MN10300_IOCLK | ||
36 | |||
37 | #ifdef CONFIG_MN10300_RTC | ||
38 | #define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ | ||
39 | #else /* !CONFIG_MN10300_RTC */ | ||
40 | #define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ) | ||
41 | #endif /* !CONFIG_MN10300_RTC */ | ||
42 | |||
43 | #endif /* !__ASSEMBLY__ */ | 20 | #endif /* !__ASSEMBLY__ */ |
44 | 21 | ||
22 | #define MN10300_WDCLK MN10300_IOCLK | ||
23 | |||
45 | #endif /* _ASM_UNIT_CLOCK_H */ | 24 | #endif /* _ASM_UNIT_CLOCK_H */ |
diff --git a/arch/mn10300/unit-asb2303/include/unit/serial.h b/arch/mn10300/unit-asb2303/include/unit/serial.h index 047566cd2e36..991e356bac5f 100644 --- a/arch/mn10300/unit-asb2303/include/unit/serial.h +++ b/arch/mn10300/unit-asb2303/include/unit/serial.h | |||
@@ -22,6 +22,11 @@ | |||
22 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 22 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * The ASB2303 has an 18.432 MHz clock the UART | ||
26 | */ | ||
27 | #define BASE_BAUD (18432000 / 16) | ||
28 | |||
29 | /* | ||
25 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports | 30 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports |
26 | */ | 31 | */ |
27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 32 | #ifndef CONFIG_GDBSTUB_ON_TTYSx |
diff --git a/arch/mn10300/unit-asb2303/include/unit/timex.h b/arch/mn10300/unit-asb2303/include/unit/timex.h index 88cd96bb2527..d1b8dafe7d7d 100644 --- a/arch/mn10300/unit-asb2303/include/unit/timex.h +++ b/arch/mn10300/unit-asb2303/include/unit/timex.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* ASB2303-specific timer specifcations | 1 | /* ASB2303-specific timer specifications |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <asm/timer-regs.h> | 18 | #include <asm/timer-regs.h> |
19 | #include <unit/clock.h> | 19 | #include <unit/clock.h> |
20 | #include <asm/param.h> | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * jiffies counter specifications | 23 | * jiffies counter specifications |
@@ -29,32 +30,43 @@ | |||
29 | #define TMJCBR TM01BR | 30 | #define TMJCBR TM01BR |
30 | #define TMJCIRQ TM1IRQ | 31 | #define TMJCIRQ TM1IRQ |
31 | #define TMJCICR TM1ICR | 32 | #define TMJCICR TM1ICR |
32 | #define TMJCICR_LEVEL GxICR_LEVEL_5 | ||
33 | 33 | ||
34 | #ifndef __ASSEMBLY__ | 34 | #ifndef __ASSEMBLY__ |
35 | 35 | ||
36 | #define MN10300_SRC_IOCLK MN10300_IOCLK | ||
37 | |||
38 | #ifndef HZ | ||
39 | # error HZ undeclared. | ||
40 | #endif /* !HZ */ | ||
41 | /* use as little prescaling as possible to avoid losing accuracy */ | ||
42 | #if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
43 | # define IOCLK_PRESCALE 1 | ||
44 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK | ||
45 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK | ||
46 | #elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
47 | # define IOCLK_PRESCALE 8 | ||
48 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8 | ||
49 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8 | ||
50 | #elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
51 | # define IOCLK_PRESCALE 32 | ||
52 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32 | ||
53 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32 | ||
54 | #else | ||
55 | # error You lose. | ||
56 | #endif | ||
57 | |||
58 | #define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE) | ||
59 | #define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE) | ||
60 | |||
61 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | ||
62 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | ||
63 | |||
36 | static inline void startup_jiffies_counter(void) | 64 | static inline void startup_jiffies_counter(void) |
37 | { | 65 | { |
38 | unsigned rate; | ||
39 | u16 md, t16; | 66 | u16 md, t16; |
40 | 67 | ||
41 | /* use as little prescaling as possible to avoid losing accuracy */ | 68 | md = JC_TIMER_CLKSRC; |
42 | md = TM0MD_SRC_IOCLK; | 69 | TMJCBR = MN10300_JC_PER_HZ - 1; |
43 | rate = MN10300_JCCLK / HZ; | ||
44 | |||
45 | if (rate > TMJCBR_MAX) { | ||
46 | md = TM0MD_SRC_IOCLK_8; | ||
47 | rate = MN10300_JCCLK / 8 / HZ; | ||
48 | |||
49 | if (rate > TMJCBR_MAX) { | ||
50 | md = TM0MD_SRC_IOCLK_32; | ||
51 | rate = MN10300_JCCLK / 32 / HZ; | ||
52 | |||
53 | BUG_ON(rate > TMJCBR_MAX); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | TMJCBR = rate - 1; | ||
58 | t16 = TMJCBR; | 70 | t16 = TMJCBR; |
59 | 71 | ||
60 | TMJCMD = | 72 | TMJCMD = |
@@ -93,29 +105,39 @@ static inline void shutdown_jiffies_counter(void) | |||
93 | 105 | ||
94 | static inline void startup_timestamp_counter(void) | 106 | static inline void startup_timestamp_counter(void) |
95 | { | 107 | { |
108 | u32 t32; | ||
109 | |||
96 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 110 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time |
97 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 111 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate |
98 | */ | 112 | */ |
99 | TM45BR = TMTSCBR_MAX; | 113 | TM45BR = TMTSCBR_MAX; |
114 | t32 = TM45BR; | ||
100 | 115 | ||
101 | TM4MD = TM4MD_SRC_IOCLK; | 116 | TM4MD = TSC_TIMER_CLKSRC; |
102 | TM4MD |= TM4MD_INIT_COUNTER; | 117 | TM4MD |= TM4MD_INIT_COUNTER; |
103 | TM4MD &= ~TM4MD_INIT_COUNTER; | 118 | TM4MD &= ~TM4MD_INIT_COUNTER; |
104 | TM4ICR = 0; | 119 | TM4ICR = 0; |
120 | t32 = TM4ICR; | ||
105 | 121 | ||
106 | TM5MD = TM5MD_SRC_TM4CASCADE; | 122 | TM5MD = TM5MD_SRC_TM4CASCADE; |
107 | TM5MD |= TM5MD_INIT_COUNTER; | 123 | TM5MD |= TM5MD_INIT_COUNTER; |
108 | TM5MD &= ~TM5MD_INIT_COUNTER; | 124 | TM5MD &= ~TM5MD_INIT_COUNTER; |
109 | TM5ICR = 0; | 125 | TM5ICR = 0; |
126 | t32 = TM5ICR; | ||
110 | 127 | ||
111 | TM5MD |= TM5MD_COUNT_ENABLE; | 128 | TM5MD |= TM5MD_COUNT_ENABLE; |
112 | TM4MD |= TM4MD_COUNT_ENABLE; | 129 | TM4MD |= TM4MD_COUNT_ENABLE; |
130 | t32 = TM5MD; | ||
131 | t32 = TM4MD; | ||
113 | } | 132 | } |
114 | 133 | ||
115 | static inline void shutdown_timestamp_counter(void) | 134 | static inline void shutdown_timestamp_counter(void) |
116 | { | 135 | { |
136 | u8 t8; | ||
117 | TM4MD = 0; | 137 | TM4MD = 0; |
118 | TM5MD = 0; | 138 | TM5MD = 0; |
139 | t8 = TM4MD; | ||
140 | t8 = TM5MD; | ||
119 | } | 141 | } |
120 | 142 | ||
121 | /* | 143 | /* |
diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c index 70e8cb4ea266..834a76aa551a 100644 --- a/arch/mn10300/unit-asb2303/unit-init.c +++ b/arch/mn10300/unit-asb2303/unit-init.c | |||
@@ -31,6 +31,14 @@ asmlinkage void __init unit_init(void) | |||
31 | SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL); | 31 | SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL); |
32 | SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL); | 32 | SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL); |
33 | SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL); | 33 | SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL); |
34 | |||
35 | #ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL | ||
36 | set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL)); | ||
37 | #endif | ||
38 | |||
39 | #ifdef CONFIG_ETHERNET_IRQ_LEVEL | ||
40 | set_intr_level(XIRQ3, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL)); | ||
41 | #endif | ||
34 | } | 42 | } |
35 | 43 | ||
36 | /* | 44 | /* |
@@ -51,7 +59,7 @@ void __init unit_init_IRQ(void) | |||
51 | switch (GET_XIRQ_TRIGGER(extnum)) { | 59 | switch (GET_XIRQ_TRIGGER(extnum)) { |
52 | case XIRQ_TRIGGER_HILEVEL: | 60 | case XIRQ_TRIGGER_HILEVEL: |
53 | case XIRQ_TRIGGER_LOWLEVEL: | 61 | case XIRQ_TRIGGER_LOWLEVEL: |
54 | set_intr_postackable(XIRQ2IRQ(extnum)); | 62 | mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum)); |
55 | break; | 63 | break; |
56 | default: | 64 | default: |
57 | break; | 65 | break; |
diff --git a/arch/mn10300/unit-asb2305/include/unit/clock.h b/arch/mn10300/unit-asb2305/include/unit/clock.h index 67be3f2eb18e..29e3425431cf 100644 --- a/arch/mn10300/unit-asb2305/include/unit/clock.h +++ b/arch/mn10300/unit-asb2305/include/unit/clock.h | |||
@@ -14,32 +14,11 @@ | |||
14 | 14 | ||
15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ |
16 | 16 | ||
17 | #ifdef CONFIG_MN10300_RTC | ||
18 | |||
19 | extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */ | ||
20 | extern unsigned long mn10300_iobclk; | ||
21 | extern unsigned long mn10300_tsc_per_HZ; | ||
22 | |||
23 | #define MN10300_IOCLK mn10300_ioclk | ||
24 | /* If this processors has a another clock, uncomment the below. */ | ||
25 | /* #define MN10300_IOBCLK mn10300_iobclk */ | ||
26 | |||
27 | #else /* !CONFIG_MN10300_RTC */ | ||
28 | |||
29 | #define MN10300_IOCLK 33333333UL | 17 | #define MN10300_IOCLK 33333333UL |
30 | /* #define MN10300_IOBCLK 66666666UL */ | 18 | /* #define MN10300_IOBCLK 66666666UL */ |
31 | 19 | ||
32 | #endif /* !CONFIG_MN10300_RTC */ | ||
33 | |||
34 | #define MN10300_JCCLK MN10300_IOCLK | ||
35 | #define MN10300_TSCCLK MN10300_IOCLK | ||
36 | |||
37 | #ifdef CONFIG_MN10300_RTC | ||
38 | #define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ | ||
39 | #else /* !CONFIG_MN10300_RTC */ | ||
40 | #define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ) | ||
41 | #endif /* !CONFIG_MN10300_RTC */ | ||
42 | |||
43 | #endif /* !__ASSEMBLY__ */ | 20 | #endif /* !__ASSEMBLY__ */ |
44 | 21 | ||
22 | #define MN10300_WDCLK MN10300_IOCLK | ||
23 | |||
45 | #endif /* _ASM_UNIT_CLOCK_H */ | 24 | #endif /* _ASM_UNIT_CLOCK_H */ |
diff --git a/arch/mn10300/unit-asb2305/include/unit/serial.h b/arch/mn10300/unit-asb2305/include/unit/serial.h index 8086cc092cec..88c08219315f 100644 --- a/arch/mn10300/unit-asb2305/include/unit/serial.h +++ b/arch/mn10300/unit-asb2305/include/unit/serial.h | |||
@@ -21,6 +21,11 @@ | |||
21 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 21 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * The ASB2305 has an 18.432 MHz clock the UART | ||
25 | */ | ||
26 | #define BASE_BAUD (18432000 / 16) | ||
27 | |||
28 | /* | ||
24 | * dispose of the /dev/ttyS0 serial port | 29 | * dispose of the /dev/ttyS0 serial port |
25 | */ | 30 | */ |
26 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 31 | #ifndef CONFIG_GDBSTUB_ON_TTYSx |
diff --git a/arch/mn10300/unit-asb2305/include/unit/timex.h b/arch/mn10300/unit-asb2305/include/unit/timex.h index 0860186eedb2..cd8bc14e3ca3 100644 --- a/arch/mn10300/unit-asb2305/include/unit/timex.h +++ b/arch/mn10300/unit-asb2305/include/unit/timex.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* ASB2305 timer specifcations | 1 | /* ASB2305-specific timer specifications |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <asm/timer-regs.h> | 18 | #include <asm/timer-regs.h> |
19 | #include <unit/clock.h> | 19 | #include <unit/clock.h> |
20 | #include <asm/param.h> | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * jiffies counter specifications | 23 | * jiffies counter specifications |
@@ -29,32 +30,43 @@ | |||
29 | #define TMJCBR TM01BR | 30 | #define TMJCBR TM01BR |
30 | #define TMJCIRQ TM1IRQ | 31 | #define TMJCIRQ TM1IRQ |
31 | #define TMJCICR TM1ICR | 32 | #define TMJCICR TM1ICR |
32 | #define TMJCICR_LEVEL GxICR_LEVEL_5 | ||
33 | 33 | ||
34 | #ifndef __ASSEMBLY__ | 34 | #ifndef __ASSEMBLY__ |
35 | 35 | ||
36 | #define MN10300_SRC_IOCLK MN10300_IOCLK | ||
37 | |||
38 | #ifndef HZ | ||
39 | # error HZ undeclared. | ||
40 | #endif /* !HZ */ | ||
41 | /* use as little prescaling as possible to avoid losing accuracy */ | ||
42 | #if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
43 | # define IOCLK_PRESCALE 1 | ||
44 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK | ||
45 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK | ||
46 | #elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
47 | # define IOCLK_PRESCALE 8 | ||
48 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8 | ||
49 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8 | ||
50 | #elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX | ||
51 | # define IOCLK_PRESCALE 32 | ||
52 | # define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32 | ||
53 | # define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32 | ||
54 | #else | ||
55 | # error You lose. | ||
56 | #endif | ||
57 | |||
58 | #define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE) | ||
59 | #define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE) | ||
60 | |||
61 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | ||
62 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | ||
63 | |||
36 | static inline void startup_jiffies_counter(void) | 64 | static inline void startup_jiffies_counter(void) |
37 | { | 65 | { |
38 | unsigned rate; | ||
39 | u16 md, t16; | 66 | u16 md, t16; |
40 | 67 | ||
41 | /* use as little prescaling as possible to avoid losing accuracy */ | 68 | md = JC_TIMER_CLKSRC; |
42 | md = TM0MD_SRC_IOCLK; | 69 | TMJCBR = MN10300_JC_PER_HZ - 1; |
43 | rate = MN10300_JCCLK / HZ; | ||
44 | |||
45 | if (rate > TMJCBR_MAX) { | ||
46 | md = TM0MD_SRC_IOCLK_8; | ||
47 | rate = MN10300_JCCLK / 8 / HZ; | ||
48 | |||
49 | if (rate > TMJCBR_MAX) { | ||
50 | md = TM0MD_SRC_IOCLK_32; | ||
51 | rate = MN10300_JCCLK / 32 / HZ; | ||
52 | |||
53 | BUG_ON(rate > TMJCBR_MAX); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | TMJCBR = rate - 1; | ||
58 | t16 = TMJCBR; | 70 | t16 = TMJCBR; |
59 | 71 | ||
60 | TMJCMD = | 72 | TMJCMD = |
@@ -93,29 +105,39 @@ static inline void shutdown_jiffies_counter(void) | |||
93 | 105 | ||
94 | static inline void startup_timestamp_counter(void) | 106 | static inline void startup_timestamp_counter(void) |
95 | { | 107 | { |
108 | u32 t32; | ||
109 | |||
96 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 110 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time |
97 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 111 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate |
98 | */ | 112 | */ |
99 | TM45BR = TMTSCBR_MAX; | 113 | TM45BR = TMTSCBR_MAX; |
114 | t32 = TM45BR; | ||
100 | 115 | ||
101 | TM4MD = TM4MD_SRC_IOCLK; | 116 | TM4MD = TSC_TIMER_CLKSRC; |
102 | TM4MD |= TM4MD_INIT_COUNTER; | 117 | TM4MD |= TM4MD_INIT_COUNTER; |
103 | TM4MD &= ~TM4MD_INIT_COUNTER; | 118 | TM4MD &= ~TM4MD_INIT_COUNTER; |
104 | TM4ICR = 0; | 119 | TM4ICR = 0; |
120 | t32 = TM4ICR; | ||
105 | 121 | ||
106 | TM5MD = TM5MD_SRC_TM4CASCADE; | 122 | TM5MD = TM5MD_SRC_TM4CASCADE; |
107 | TM5MD |= TM5MD_INIT_COUNTER; | 123 | TM5MD |= TM5MD_INIT_COUNTER; |
108 | TM5MD &= ~TM5MD_INIT_COUNTER; | 124 | TM5MD &= ~TM5MD_INIT_COUNTER; |
109 | TM5ICR = 0; | 125 | TM5ICR = 0; |
126 | t32 = TM5ICR; | ||
110 | 127 | ||
111 | TM5MD |= TM5MD_COUNT_ENABLE; | 128 | TM5MD |= TM5MD_COUNT_ENABLE; |
112 | TM4MD |= TM4MD_COUNT_ENABLE; | 129 | TM4MD |= TM4MD_COUNT_ENABLE; |
130 | t32 = TM5MD; | ||
131 | t32 = TM4MD; | ||
113 | } | 132 | } |
114 | 133 | ||
115 | static inline void shutdown_timestamp_counter(void) | 134 | static inline void shutdown_timestamp_counter(void) |
116 | { | 135 | { |
136 | u8 t8; | ||
117 | TM4MD = 0; | 137 | TM4MD = 0; |
118 | TM5MD = 0; | 138 | TM5MD = 0; |
139 | t8 = TM4MD; | ||
140 | t8 = TM5MD; | ||
119 | } | 141 | } |
120 | 142 | ||
121 | /* | 143 | /* |
@@ -126,7 +148,7 @@ typedef unsigned long cycles_t; | |||
126 | 148 | ||
127 | static inline cycles_t read_timestamp_counter(void) | 149 | static inline cycles_t read_timestamp_counter(void) |
128 | { | 150 | { |
129 | return (cycles_t) TMTSCBC; | 151 | return (cycles_t)TMTSCBC; |
130 | } | 152 | } |
131 | 153 | ||
132 | #endif /* !__ASSEMBLY__ */ | 154 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 6d8720a0a599..a4954fe82094 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c | |||
@@ -503,7 +503,7 @@ asmlinkage void __init unit_pci_init(void) | |||
503 | struct pci_ops *o = &pci_direct_ampci; | 503 | struct pci_ops *o = &pci_direct_ampci; |
504 | u32 x; | 504 | u32 x; |
505 | 505 | ||
506 | set_intr_level(XIRQ1, GxICR_LEVEL_3); | 506 | set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL)); |
507 | 507 | ||
508 | memset(&bus, 0, sizeof(bus)); | 508 | memset(&bus, 0, sizeof(bus)); |
509 | 509 | ||
diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c index a76c8e0ab90f..e1becd6b7571 100644 --- a/arch/mn10300/unit-asb2305/unit-init.c +++ b/arch/mn10300/unit-asb2305/unit-init.c | |||
@@ -26,8 +26,10 @@ asmlinkage void __init unit_init(void) | |||
26 | { | 26 | { |
27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx |
28 | /* set the 16550 interrupt line to level 3 if not being used for GDB */ | 28 | /* set the 16550 interrupt line to level 3 if not being used for GDB */ |
29 | set_intr_level(XIRQ0, GxICR_LEVEL_3); | 29 | #ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL |
30 | set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL)); | ||
30 | #endif | 31 | #endif |
32 | #endif /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
31 | } | 33 | } |
32 | 34 | ||
33 | /* | 35 | /* |
@@ -51,7 +53,7 @@ void __init unit_init_IRQ(void) | |||
51 | switch (GET_XIRQ_TRIGGER(extnum)) { | 53 | switch (GET_XIRQ_TRIGGER(extnum)) { |
52 | case XIRQ_TRIGGER_HILEVEL: | 54 | case XIRQ_TRIGGER_HILEVEL: |
53 | case XIRQ_TRIGGER_LOWLEVEL: | 55 | case XIRQ_TRIGGER_LOWLEVEL: |
54 | set_intr_postackable(XIRQ2IRQ(extnum)); | 56 | mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum)); |
55 | break; | 57 | break; |
56 | default: | 58 | default: |
57 | break; | 59 | break; |
diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile new file mode 100644 index 000000000000..6dd27d65877a --- /dev/null +++ b/arch/mn10300/unit-asb2364/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | # Note 2! The CFLAGS definitions are now in the main makefile... | ||
9 | |||
10 | obj-y := unit-init.o leds.o | ||
diff --git a/arch/mn10300/unit-asb2364/include/unit/clock.h b/arch/mn10300/unit-asb2364/include/unit/clock.h new file mode 100644 index 000000000000..d34ac9a7508b --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/clock.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* clock.h: unit-specific clocks | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
7 | * Modifications: | ||
8 | * 23-Feb-2007 MEI Add define for watchdog timer. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef _ASM_UNIT_CLOCK_H | ||
17 | #define _ASM_UNIT_CLOCK_H | ||
18 | |||
19 | #ifndef __ASSEMBLY__ | ||
20 | |||
21 | #define MN10300_IOCLK 100000000UL /* for DDR800 */ | ||
22 | /*#define MN10300_IOCLK 83333333UL */ /* for DDR667 */ | ||
23 | #define MN10300_IOBCLK MN10300_IOCLK /* IOBCLK is equal to IOCLK */ | ||
24 | |||
25 | #endif /* !__ASSEMBLY__ */ | ||
26 | |||
27 | #define MN10300_WDCLK 27000000UL | ||
28 | |||
29 | #endif /* _ASM_UNIT_CLOCK_H */ | ||
diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h new file mode 100644 index 000000000000..a039a50c91db --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* ASB2364 FPGA registers | ||
2 | */ | ||
3 | |||
4 | #ifndef _ASM_UNIT_FPGA_REGS_H | ||
5 | #define _ASM_UNIT_FPGA_REGS_H | ||
6 | |||
7 | #include <asm/cpu-regs.h> | ||
8 | |||
9 | #ifdef __KERNEL__ | ||
10 | |||
11 | #define ASB2364_FPGA_REG_RESET_LAN __SYSREG(0xa9001300, u16) | ||
12 | #define ASB2364_FPGA_REG_RESET_UART __SYSREG(0xa9001304, u16) | ||
13 | #define ASB2364_FPGA_REG_RESET_I2C __SYSREG(0xa9001308, u16) | ||
14 | #define ASB2364_FPGA_REG_RESET_USB __SYSREG(0xa900130c, u16) | ||
15 | #define ASB2364_FPGA_REG_RESET_AV __SYSREG(0xa9001310, u16) | ||
16 | |||
17 | #define ASB2364_FPGA_REG_IRQ_LAN __SYSREG(0xa9001510, u16) | ||
18 | #define ASB2364_FPGA_REG_IRQ_UART __SYSREG(0xa9001514, u16) | ||
19 | #define ASB2364_FPGA_REG_IRQ_I2C __SYSREG(0xa9001518, u16) | ||
20 | #define ASB2364_FPGA_REG_IRQ_USB __SYSREG(0xa900151c, u16) | ||
21 | #define ASB2364_FPGA_REG_IRQ_FPGA __SYSREG(0xa9001524, u16) | ||
22 | |||
23 | #define ASB2364_FPGA_REG_MASK_LAN __SYSREG(0xa9001590, u16) | ||
24 | #define ASB2364_FPGA_REG_MASK_UART __SYSREG(0xa9001594, u16) | ||
25 | #define ASB2364_FPGA_REG_MASK_I2C __SYSREG(0xa9001598, u16) | ||
26 | #define ASB2364_FPGA_REG_MASK_USB __SYSREG(0xa900159c, u16) | ||
27 | #define ASB2364_FPGA_REG_MASK_FPGA __SYSREG(0xa90015a4, u16) | ||
28 | |||
29 | #define ASB2364_FPGA_REG_CPLD5_SET1 __SYSREG(0xa9002500, u16) | ||
30 | #define ASB2364_FPGA_REG_CPLD5_SET2 __SYSREG(0xa9002504, u16) | ||
31 | #define ASB2364_FPGA_REG_CPLD6_SET1 __SYSREG(0xa9002600, u16) | ||
32 | #define ASB2364_FPGA_REG_CPLD6_SET2 __SYSREG(0xa9002604, u16) | ||
33 | #define ASB2364_FPGA_REG_CPLD7_SET1 __SYSREG(0xa9002700, u16) | ||
34 | #define ASB2364_FPGA_REG_CPLD7_SET2 __SYSREG(0xa9002704, u16) | ||
35 | #define ASB2364_FPGA_REG_CPLD8_SET1 __SYSREG(0xa9002800, u16) | ||
36 | #define ASB2364_FPGA_REG_CPLD8_SET2 __SYSREG(0xa9002804, u16) | ||
37 | #define ASB2364_FPGA_REG_CPLD9_SET1 __SYSREG(0xa9002900, u16) | ||
38 | #define ASB2364_FPGA_REG_CPLD9_SET2 __SYSREG(0xa9002904, u16) | ||
39 | #define ASB2364_FPGA_REG_CPLD10_SET1 __SYSREG(0xa9002a00, u16) | ||
40 | #define ASB2364_FPGA_REG_CPLD10_SET2 __SYSREG(0xa9002a04, u16) | ||
41 | |||
42 | #define SyncExBus() \ | ||
43 | do { \ | ||
44 | unsigned short w; \ | ||
45 | w = *(volatile short *)0xa9000000; \ | ||
46 | } while (0) | ||
47 | |||
48 | #endif /* __KERNEL__ */ | ||
49 | |||
50 | #endif /* _ASM_UNIT_FPGA_REGS_H */ | ||
diff --git a/arch/mn10300/unit-asb2364/include/unit/leds.h b/arch/mn10300/unit-asb2364/include/unit/leds.h new file mode 100644 index 000000000000..03a3933ad323 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/leds.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* Unit-specific leds | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_UNIT_LEDS_H | ||
13 | #define _ASM_UNIT_LEDS_H | ||
14 | |||
15 | #include <asm/pio-regs.h> | ||
16 | #include <asm/cpu-regs.h> | ||
17 | #include <asm/exceptions.h> | ||
18 | |||
19 | #define MN10300_USE_7SEGLEDS 0 | ||
20 | |||
21 | #define ASB2364_7SEGLEDS __SYSREG(0xA9001630, u32) | ||
22 | |||
23 | /* | ||
24 | * use the 7-segment LEDs to indicate states | ||
25 | */ | ||
26 | |||
27 | #if MN10300_USE_7SEGLEDS | ||
28 | /* flip the 7-segment LEDs between "Gdb-" and "----" */ | ||
29 | #define mn10300_set_gdbleds(ONOFF) \ | ||
30 | do { \ | ||
31 | ASB2364_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f; \ | ||
32 | } while (0) | ||
33 | #else | ||
34 | #define mn10300_set_gdbleds(ONOFF) do {} while (0) | ||
35 | #endif | ||
36 | |||
37 | #if MN10300_USE_7SEGLEDS | ||
38 | /* indicate double-fault by displaying "db-f" on the LEDs */ | ||
39 | #define mn10300_set_dbfleds \ | ||
40 | mov 0x43077f1d,d0 ; \ | ||
41 | mov d0,(ASB2364_7SEGLEDS) | ||
42 | #else | ||
43 | #define mn10300_set_dbfleds | ||
44 | #endif | ||
45 | |||
46 | #ifndef __ASSEMBLY__ | ||
47 | extern void peripheral_leds_display_exception(enum exception_code); | ||
48 | extern void peripheral_leds_led_chase(void); | ||
49 | extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int); | ||
50 | extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int); | ||
51 | extern void debug_to_serial(const char *, int); | ||
52 | #endif /* __ASSEMBLY__ */ | ||
53 | |||
54 | #endif /* _ASM_UNIT_LEDS_H */ | ||
diff --git a/arch/mn10300/unit-asb2364/include/unit/serial.h b/arch/mn10300/unit-asb2364/include/unit/serial.h new file mode 100644 index 000000000000..7f048bbfdfd7 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/serial.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* Unit-specific 8250 serial ports | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_UNIT_SERIAL_H | ||
13 | #define _ASM_UNIT_SERIAL_H | ||
14 | |||
15 | #include <asm/cpu-regs.h> | ||
16 | #include <proc/irq.h> | ||
17 | #include <unit/fpga-regs.h> | ||
18 | #include <linux/serial_reg.h> | ||
19 | |||
20 | #define SERIAL_PORT0_BASE_ADDRESS 0xA8200000 | ||
21 | |||
22 | #define SERIAL_IRQ XIRQ1 /* single serial (TL16C550C) (Lo) */ | ||
23 | |||
24 | /* | ||
25 | * The ASB2364 has an 12.288 MHz clock | ||
26 | * for your UART. | ||
27 | * | ||
28 | * It'd be nice if someone built a serial card with a 24.576 MHz | ||
29 | * clock, since the 16550A is capable of handling a top speed of 1.5 | ||
30 | * megabits/second; but this requires the faster clock. | ||
31 | */ | ||
32 | #define BASE_BAUD (12288000 / 16) | ||
33 | |||
34 | /* | ||
35 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports | ||
36 | */ | ||
37 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | ||
38 | |||
39 | #define SERIAL_PORT_DFNS \ | ||
40 | { \ | ||
41 | .baud_base = BASE_BAUD, \ | ||
42 | .irq = SERIAL_IRQ, \ | ||
43 | .flags = STD_COM_FLAGS, \ | ||
44 | .iomem_base = (u8 *) SERIAL_PORT0_BASE_ADDRESS, \ | ||
45 | .iomem_reg_shift = 1, \ | ||
46 | .io_type = SERIAL_IO_MEM, \ | ||
47 | }, | ||
48 | |||
49 | #ifndef __ASSEMBLY__ | ||
50 | |||
51 | static inline void __debug_to_serial(const char *p, int n) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | #endif /* !__ASSEMBLY__ */ | ||
56 | |||
57 | #else /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
58 | |||
59 | #define SERIAL_PORT_DFNS /* stolen by gdb-stub */ | ||
60 | |||
61 | #if defined(CONFIG_GDBSTUB_ON_TTYS0) | ||
62 | #define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 4, u8) | ||
63 | #define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 4, u8) | ||
64 | #define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8) | ||
65 | #define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8) | ||
66 | #define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8) | ||
67 | #define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8) | ||
68 | #define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8) | ||
69 | #define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8) | ||
70 | #define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8) | ||
71 | #define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8) | ||
72 | #define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8) | ||
73 | #define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8) | ||
74 | #define GDBPORT_SERIAL_IRQ SERIAL_IRQ | ||
75 | |||
76 | #elif defined(CONFIG_GDBSTUB_ON_TTYS1) | ||
77 | #error The ASB2364 does not have a /dev/ttyS1 | ||
78 | #endif | ||
79 | |||
80 | #ifndef __ASSEMBLY__ | ||
81 | |||
82 | static inline void __debug_to_serial(const char *p, int n) | ||
83 | { | ||
84 | char ch; | ||
85 | |||
86 | #define LSR_WAIT_FOR(STATE) \ | ||
87 | do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE)) | ||
88 | #define FLOWCTL_QUERY(LINE) \ | ||
89 | ({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; }) | ||
90 | #define FLOWCTL_WAIT_FOR(LINE) \ | ||
91 | do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE)) | ||
92 | #define FLOWCTL_CLEAR(LINE) \ | ||
93 | do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0) | ||
94 | #define FLOWCTL_SET(LINE) \ | ||
95 | do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0) | ||
96 | |||
97 | FLOWCTL_SET(DTR); | ||
98 | |||
99 | for (; n > 0; n--) { | ||
100 | LSR_WAIT_FOR(THRE); | ||
101 | FLOWCTL_WAIT_FOR(CTS); | ||
102 | |||
103 | ch = *p++; | ||
104 | if (ch == 0x0a) { | ||
105 | GDBPORT_SERIAL_TX = 0x0d; | ||
106 | LSR_WAIT_FOR(THRE); | ||
107 | FLOWCTL_WAIT_FOR(CTS); | ||
108 | } | ||
109 | GDBPORT_SERIAL_TX = ch; | ||
110 | } | ||
111 | |||
112 | FLOWCTL_CLEAR(DTR); | ||
113 | } | ||
114 | |||
115 | #endif /* !__ASSEMBLY__ */ | ||
116 | |||
117 | #endif /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
118 | |||
119 | #define SERIAL_INITIALIZE \ | ||
120 | do { \ | ||
121 | /* release reset */ \ | ||
122 | ASB2364_FPGA_REG_RESET_UART = 0x0001; \ | ||
123 | SyncExBus(); \ | ||
124 | } while (0) | ||
125 | |||
126 | #define SERIAL_CHECK_INTERRUPT \ | ||
127 | do { \ | ||
128 | if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) { \ | ||
129 | return IRQ_NONE; \ | ||
130 | } \ | ||
131 | } while (0) | ||
132 | |||
133 | #define SERIAL_CLEAR_INTERRUPT \ | ||
134 | do { \ | ||
135 | ASB2364_FPGA_REG_IRQ_UART = 0x0001; \ | ||
136 | SyncExBus(); \ | ||
137 | } while (0) | ||
138 | |||
139 | #define SERIAL_SET_INT_MASK \ | ||
140 | do { \ | ||
141 | ASB2364_FPGA_REG_MASK_UART = 0x0001; \ | ||
142 | SyncExBus(); \ | ||
143 | } while (0) | ||
144 | |||
145 | #define SERIAL_CLEAR_INT_MASK \ | ||
146 | do { \ | ||
147 | ASB2364_FPGA_REG_MASK_UART = 0x0000; \ | ||
148 | SyncExBus(); \ | ||
149 | } while (0) | ||
150 | |||
151 | #endif /* _ASM_UNIT_SERIAL_H */ | ||
diff --git a/arch/mn10300/unit-asb2364/include/unit/timex.h b/arch/mn10300/unit-asb2364/include/unit/timex.h new file mode 100644 index 000000000000..b5223f705ef8 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/timex.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* timex.h: MN2WS0038 architecture timer specifications | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef _ASM_UNIT_TIMEX_H | ||
12 | #define _ASM_UNIT_TIMEX_H | ||
13 | |||
14 | #ifndef __ASSEMBLY__ | ||
15 | #include <linux/irq.h> | ||
16 | #endif /* __ASSEMBLY__ */ | ||
17 | |||
18 | #include <asm/timer-regs.h> | ||
19 | #include <unit/clock.h> | ||
20 | #include <asm/param.h> | ||
21 | |||
22 | /* | ||
23 | * jiffies counter specifications | ||
24 | */ | ||
25 | |||
26 | #define TMJCBR_MAX 0xffffff /* 24bit */ | ||
27 | #define TMJCBC TMTBC | ||
28 | |||
29 | #define TMJCMD TMTMD | ||
30 | #define TMJCBR TMTBR | ||
31 | #define TMJCIRQ TMTIRQ | ||
32 | #define TMJCICR TMTICR | ||
33 | |||
34 | #ifndef __ASSEMBLY__ | ||
35 | |||
36 | #define MN10300_SRC_IOBCLK MN10300_IOBCLK | ||
37 | |||
38 | #ifndef HZ | ||
39 | # error HZ undeclared. | ||
40 | #endif /* !HZ */ | ||
41 | |||
42 | #define MN10300_JCCLK (MN10300_SRC_IOBCLK) | ||
43 | #define MN10300_TSCCLK (MN10300_SRC_IOBCLK) | ||
44 | |||
45 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | ||
46 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | ||
47 | |||
48 | /* Check bit width of MTM interval value that sets base register */ | ||
49 | #if (MN10300_JC_PER_HZ - 1) > TMJCBR_MAX | ||
50 | # error MTM tick timer interval value is overflow. | ||
51 | #endif | ||
52 | |||
53 | |||
54 | static inline void startup_jiffies_counter(void) | ||
55 | { | ||
56 | u32 sync; | ||
57 | |||
58 | TMJCBR = MN10300_JC_PER_HZ - 1; | ||
59 | sync = TMJCBR; | ||
60 | |||
61 | TMJCMD = TMTMD_TMTLDE; | ||
62 | TMJCMD = TMTMD_TMTCNE; | ||
63 | sync = TMJCMD; | ||
64 | |||
65 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | ||
66 | sync = TMJCICR; | ||
67 | } | ||
68 | |||
69 | static inline void shutdown_jiffies_counter(void) | ||
70 | { | ||
71 | } | ||
72 | |||
73 | #endif /* !__ASSEMBLY__ */ | ||
74 | |||
75 | |||
76 | /* | ||
77 | * timestamp counter specifications | ||
78 | */ | ||
79 | |||
80 | #define TMTSCBR_MAX 0xffffffff | ||
81 | #define TMTSCMD TMSMD | ||
82 | #define TMTSCBR TMSBR | ||
83 | #define TMTSCBC TMSBC | ||
84 | #define TMTSCICR TMSICR | ||
85 | |||
86 | #ifndef __ASSEMBLY__ | ||
87 | |||
88 | static inline void startup_timestamp_counter(void) | ||
89 | { | ||
90 | u32 sync; | ||
91 | |||
92 | /* set up TMS(Timestamp) 32bit timer register to count real time | ||
93 | * - count down from 4Gig-1 to 0 and wrap at IOBCLK rate | ||
94 | */ | ||
95 | |||
96 | TMTSCBR = TMTSCBR_MAX; | ||
97 | sync = TMTSCBR; | ||
98 | |||
99 | TMTSCICR = 0; | ||
100 | sync = TMTSCICR; | ||
101 | |||
102 | TMTSCMD = TMTMD_TMTLDE; | ||
103 | TMTSCMD = TMTMD_TMTCNE; | ||
104 | sync = TMTSCMD; | ||
105 | } | ||
106 | |||
107 | static inline void shutdown_timestamp_counter(void) | ||
108 | { | ||
109 | TMTSCMD = 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * we use a cascaded pair of 16-bit down-counting timers to count I/O | ||
114 | * clock cycles for the purposes of time keeping | ||
115 | */ | ||
116 | typedef unsigned long cycles_t; | ||
117 | |||
118 | static inline cycles_t read_timestamp_counter(void) | ||
119 | { | ||
120 | return (cycles_t)TMTSCBC; | ||
121 | } | ||
122 | |||
123 | #endif /* !__ASSEMBLY__ */ | ||
124 | |||
125 | #endif /* _ASM_UNIT_TIMEX_H */ | ||
diff --git a/arch/mn10300/unit-asb2364/leds.c b/arch/mn10300/unit-asb2364/leds.c new file mode 100644 index 000000000000..1ff830c372b3 --- /dev/null +++ b/arch/mn10300/unit-asb2364/leds.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* leds.c: ASB2364 peripheral 7seg LEDs x4 support | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | #include <asm/processor.h> | ||
18 | #include <asm/intctl-regs.h> | ||
19 | #include <asm/rtc-regs.h> | ||
20 | #include <unit/leds.h> | ||
21 | |||
22 | #if MN10300_USE_7SEGLEDS | ||
23 | static const u8 asb2364_led_hex_tbl[16] = { | ||
24 | 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0, | ||
25 | 0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c | ||
26 | }; | ||
27 | |||
28 | static const u32 asb2364_led_chase_tbl[6] = { | ||
29 | ~0x02020202, /* top - segA */ | ||
30 | ~0x04040404, /* right top - segB */ | ||
31 | ~0x08080808, /* right bottom - segC */ | ||
32 | ~0x10101010, /* bottom - segD */ | ||
33 | ~0x20202020, /* left bottom - segE */ | ||
34 | ~0x40404040, /* left top - segF */ | ||
35 | }; | ||
36 | |||
37 | static unsigned asb2364_led_chase; | ||
38 | |||
39 | void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) | ||
40 | { | ||
41 | u32 leds; | ||
42 | |||
43 | leds = asb2364_led_hex_tbl[(val/1000) % 10]; | ||
44 | leds <<= 8; | ||
45 | leds |= asb2364_led_hex_tbl[(val/100) % 10]; | ||
46 | leds <<= 8; | ||
47 | leds |= asb2364_led_hex_tbl[(val/10) % 10]; | ||
48 | leds <<= 8; | ||
49 | leds |= asb2364_led_hex_tbl[val % 10]; | ||
50 | leds |= points^0x01010101; | ||
51 | |||
52 | ASB2364_7SEGLEDS = leds; | ||
53 | } | ||
54 | |||
55 | void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) | ||
56 | { | ||
57 | u32 leds; | ||
58 | |||
59 | leds = asb2364_led_hex_tbl[(val/1000) % 10]; | ||
60 | leds <<= 8; | ||
61 | leds |= asb2364_led_hex_tbl[(val/100) % 10]; | ||
62 | leds <<= 8; | ||
63 | leds |= asb2364_led_hex_tbl[(val/10) % 10]; | ||
64 | leds <<= 8; | ||
65 | leds |= asb2364_led_hex_tbl[val % 10]; | ||
66 | leds |= points^0x01010101; | ||
67 | |||
68 | ASB2364_7SEGLEDS = leds; | ||
69 | } | ||
70 | |||
71 | /* display triple horizontal bar and exception code */ | ||
72 | void peripheral_leds_display_exception(enum exception_code code) | ||
73 | { | ||
74 | u32 leds; | ||
75 | |||
76 | leds = asb2364_led_hex_tbl[(code/0x100) % 0x10]; | ||
77 | leds <<= 8; | ||
78 | leds |= asb2364_led_hex_tbl[(code/0x10) % 0x10]; | ||
79 | leds <<= 8; | ||
80 | leds |= asb2364_led_hex_tbl[code % 0x10]; | ||
81 | leds |= 0x6d010101; | ||
82 | |||
83 | ASB2364_7SEGLEDS = leds; | ||
84 | } | ||
85 | |||
86 | void peripheral_leds_led_chase(void) | ||
87 | { | ||
88 | ASB2364_7SEGLEDS = asb2364_led_chase_tbl[asb2364_led_chase]; | ||
89 | asb2364_led_chase++; | ||
90 | if (asb2364_led_chase >= 6) | ||
91 | asb2364_led_chase = 0; | ||
92 | } | ||
93 | #else /* MN10300_USE_7SEGLEDS */ | ||
94 | void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { } | ||
95 | void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { } | ||
96 | void peripheral_leds_display_exception(enum exception_code code) { } | ||
97 | void peripheral_leds_led_chase(void) { } | ||
98 | #endif /* MN10300_USE_7SEGLEDS */ | ||
diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c new file mode 100644 index 000000000000..a3fc09b43f84 --- /dev/null +++ b/arch/mn10300/unit-asb2364/unit-init.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* ASB2364 initialisation | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/delay.h> | ||
17 | |||
18 | #include <asm/io.h> | ||
19 | #include <asm/setup.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/intctl-regs.h> | ||
23 | |||
24 | /* | ||
25 | * initialise some of the unit hardware before gdbstub is set up | ||
26 | */ | ||
27 | asmlinkage void __init unit_init(void) | ||
28 | { | ||
29 | /* set up the external interrupts */ | ||
30 | |||
31 | /* XIRQ[0]: NAND RXBY */ | ||
32 | /* SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_LOWLEVEL); */ | ||
33 | |||
34 | /* XIRQ[1]: LAN, UART, I2C, USB, PCI, FPGA */ | ||
35 | SET_XIRQ_TRIGGER(1, XIRQ_TRIGGER_LOWLEVEL); | ||
36 | |||
37 | /* XIRQ[2]: Extend Slot 1-9 */ | ||
38 | /* SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL); */ | ||
39 | |||
40 | #if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL) && \ | ||
41 | defined(CONFIG_ETHERNET_IRQ_LEVEL) && \ | ||
42 | (CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL) | ||
43 | # error CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL | ||
44 | #endif | ||
45 | |||
46 | #if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL) | ||
47 | set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL)); | ||
48 | #elif defined(CONFIG_ETHERNET_IRQ_LEVEL) | ||
49 | set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL)); | ||
50 | #endif | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * initialise the rest of the unit hardware after gdbstub is ready | ||
55 | */ | ||
56 | asmlinkage void __init unit_setup(void) | ||
57 | { | ||
58 | |||
59 | } | ||
60 | |||
61 | /* | ||
62 | * initialise the external interrupts used by a unit of this type | ||
63 | */ | ||
64 | void __init unit_init_IRQ(void) | ||
65 | { | ||
66 | unsigned int extnum; | ||
67 | |||
68 | for (extnum = 0 ; extnum < NR_XIRQS ; extnum++) { | ||
69 | switch (GET_XIRQ_TRIGGER(extnum)) { | ||
70 | /* LEVEL triggered interrupts should be made | ||
71 | * post-ACK'able as they hold their lines until | ||
72 | * serviced | ||
73 | */ | ||
74 | case XIRQ_TRIGGER_HILEVEL: | ||
75 | case XIRQ_TRIGGER_LOWLEVEL: | ||
76 | mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum)); | ||
77 | break; | ||
78 | default: | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | #define IRQCTL __SYSREG(0xd5000090, u32) | ||
84 | IRQCTL |= 0x02; | ||
85 | } | ||