aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300')
-rw-r--r--arch/mn10300/Kconfig279
-rw-r--r--arch/mn10300/Makefile6
-rw-r--r--arch/mn10300/boot/compressed/head.S69
-rw-r--r--arch/mn10300/configs/asb2303_defconfig2
-rw-r--r--arch/mn10300/configs/asb2364_defconfig98
-rw-r--r--arch/mn10300/include/asm/atomic.h350
-rw-r--r--arch/mn10300/include/asm/bitops.h14
-rw-r--r--arch/mn10300/include/asm/cache.h14
-rw-r--r--arch/mn10300/include/asm/cacheflush.h164
-rw-r--r--arch/mn10300/include/asm/cpu-regs.h91
-rw-r--r--arch/mn10300/include/asm/dmactl-regs.h87
-rw-r--r--arch/mn10300/include/asm/elf.h12
-rw-r--r--arch/mn10300/include/asm/exceptions.h8
-rw-r--r--arch/mn10300/include/asm/fpu.h157
-rw-r--r--arch/mn10300/include/asm/frame.inc20
-rw-r--r--arch/mn10300/include/asm/gdb-stub.h2
-rw-r--r--arch/mn10300/include/asm/hardirq.h3
-rw-r--r--arch/mn10300/include/asm/highmem.h4
-rw-r--r--arch/mn10300/include/asm/intctl-regs.h37
-rw-r--r--arch/mn10300/include/asm/io.h13
-rw-r--r--arch/mn10300/include/asm/irq.h12
-rw-r--r--arch/mn10300/include/asm/irq_regs.h6
-rw-r--r--arch/mn10300/include/asm/irqflags.h111
-rw-r--r--arch/mn10300/include/asm/mmu_context.h73
-rw-r--r--arch/mn10300/include/asm/pgalloc.h1
-rw-r--r--arch/mn10300/include/asm/pgtable.h88
-rw-r--r--arch/mn10300/include/asm/processor.h66
-rw-r--r--arch/mn10300/include/asm/ptrace.h13
-rw-r--r--arch/mn10300/include/asm/reset-regs.h2
-rw-r--r--arch/mn10300/include/asm/rtc.h11
-rw-r--r--arch/mn10300/include/asm/rwlock.h125
-rw-r--r--arch/mn10300/include/asm/serial-regs.h51
-rw-r--r--arch/mn10300/include/asm/serial.h8
-rw-r--r--arch/mn10300/include/asm/smp.h91
-rw-r--r--arch/mn10300/include/asm/smsc911x.h1
-rw-r--r--arch/mn10300/include/asm/spinlock.h179
-rw-r--r--arch/mn10300/include/asm/spinlock_types.h20
-rw-r--r--arch/mn10300/include/asm/system.h73
-rw-r--r--arch/mn10300/include/asm/thread_info.h18
-rw-r--r--arch/mn10300/include/asm/timer-regs.h191
-rw-r--r--arch/mn10300/include/asm/timex.h20
-rw-r--r--arch/mn10300/include/asm/tlbflush.h174
-rw-r--r--arch/mn10300/include/asm/uaccess.h6
-rw-r--r--arch/mn10300/kernel/Makefile15
-rw-r--r--arch/mn10300/kernel/asm-offsets.c11
-rw-r--r--arch/mn10300/kernel/cevt-mn10300.c131
-rw-r--r--arch/mn10300/kernel/csrc-mn10300.c35
-rw-r--r--arch/mn10300/kernel/entry.S146
-rw-r--r--arch/mn10300/kernel/fpu-low.S265
-rw-r--r--arch/mn10300/kernel/fpu-nofpu-low.S39
-rw-r--r--arch/mn10300/kernel/fpu-nofpu.c30
-rw-r--r--arch/mn10300/kernel/fpu.c141
-rw-r--r--arch/mn10300/kernel/gdb-io-serial-low.S5
-rw-r--r--arch/mn10300/kernel/gdb-io-serial.c37
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c24
-rw-r--r--arch/mn10300/kernel/gdb-stub.c17
-rw-r--r--arch/mn10300/kernel/head.S202
-rw-r--r--arch/mn10300/kernel/internal.h25
-rw-r--r--arch/mn10300/kernel/irq.c276
-rw-r--r--arch/mn10300/kernel/kprobes.c4
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S6
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c210
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog-low.S9
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c100
-rw-r--r--arch/mn10300/kernel/process.c61
-rw-r--r--arch/mn10300/kernel/profile.c2
-rw-r--r--arch/mn10300/kernel/rtc.c41
-rw-r--r--arch/mn10300/kernel/setup.c79
-rw-r--r--arch/mn10300/kernel/signal.c20
-rw-r--r--arch/mn10300/kernel/smp-low.S97
-rw-r--r--arch/mn10300/kernel/smp.c1152
-rw-r--r--arch/mn10300/kernel/switch_to.S7
-rw-r--r--arch/mn10300/kernel/time.c112
-rw-r--r--arch/mn10300/kernel/traps.c42
-rw-r--r--arch/mn10300/lib/bitops.c4
-rw-r--r--arch/mn10300/lib/delay.c8
-rw-r--r--arch/mn10300/lib/do_csum.S49
-rw-r--r--arch/mn10300/mm/Kconfig.cache101
-rw-r--r--arch/mn10300/mm/Makefile14
-rw-r--r--arch/mn10300/mm/cache-flush-by-reg.S308
-rw-r--r--arch/mn10300/mm/cache-flush-by-tag.S251
-rw-r--r--arch/mn10300/mm/cache-flush-icache.c155
-rw-r--r--arch/mn10300/mm/cache-flush-mn10300.S192
-rw-r--r--arch/mn10300/mm/cache-inv-by-reg.S356
-rw-r--r--arch/mn10300/mm/cache-inv-by-tag.S348
-rw-r--r--arch/mn10300/mm/cache-inv-icache.c129
-rw-r--r--arch/mn10300/mm/cache-mn10300.S289
-rw-r--r--arch/mn10300/mm/cache-smp-flush.c156
-rw-r--r--arch/mn10300/mm/cache-smp-inv.c153
-rw-r--r--arch/mn10300/mm/cache-smp.c105
-rw-r--r--arch/mn10300/mm/cache-smp.h69
-rw-r--r--arch/mn10300/mm/cache.c95
-rw-r--r--arch/mn10300/mm/fault.c17
-rw-r--r--arch/mn10300/mm/init.c26
-rw-r--r--arch/mn10300/mm/misalignment.c3
-rw-r--r--arch/mn10300/mm/mmu-context.c41
-rw-r--r--arch/mn10300/mm/pgtable.c2
-rw-r--r--arch/mn10300/mm/tlb-mn10300.S59
-rw-r--r--arch/mn10300/mm/tlb-smp.c214
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/cache.h9
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/clock.h2
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h102
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h29
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/proc.h2
-rw-r--r--arch/mn10300/proc-mn103e010/proc-init.c37
-rw-r--r--arch/mn10300/proc-mn2ws0050/Makefile5
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/cache.h48
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/clock.h20
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h103
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h29
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/irq.h49
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h120
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/proc.h18
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h51
-rw-r--r--arch/mn10300/proc-mn2ws0050/proc-init.c134
-rw-r--r--arch/mn10300/unit-asb2303/include/unit/clock.h25
-rw-r--r--arch/mn10300/unit-asb2303/include/unit/serial.h5
-rw-r--r--arch/mn10300/unit-asb2303/include/unit/timex.h109
-rw-r--r--arch/mn10300/unit-asb2303/unit-init.c10
-rw-r--r--arch/mn10300/unit-asb2305/include/unit/clock.h25
-rw-r--r--arch/mn10300/unit-asb2305/include/unit/serial.h5
-rw-r--r--arch/mn10300/unit-asb2305/include/unit/timex.h109
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.c16
-rw-r--r--arch/mn10300/unit-asb2305/pci.c2
-rw-r--r--arch/mn10300/unit-asb2305/unit-init.c6
-rw-r--r--arch/mn10300/unit-asb2364/Makefile12
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/clock.h29
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/fpga-regs.h52
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/irq.h35
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/leds.h54
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/serial.h151
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/smsc911x.h171
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/timex.h159
-rw-r--r--arch/mn10300/unit-asb2364/irq-fpga.c96
-rw-r--r--arch/mn10300/unit-asb2364/leds.c98
-rw-r--r--arch/mn10300/unit-asb2364/smsc911x.c58
-rw-r--r--arch/mn10300/unit-asb2364/unit-init.c88
137 files changed, 9384 insertions, 1944 deletions
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 7c2a2f7f8dc1..365766a3d536 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -9,8 +9,19 @@ config MN10300
9 def_bool y 9 def_bool y
10 select HAVE_OPROFILE 10 select HAVE_OPROFILE
11 11
12config AM33 12config AM33_2
13 def_bool y 13 def_bool n
14
15config AM33_3
16 def_bool n
17
18config AM34_2
19 def_bool n
20 select MN10300_HAS_ATOMIC_OPS_UNIT
21 select MN10300_HAS_CACHE_SNOOP
22
23config ERRATUM_NEED_TO_RELOAD_MMUCTR
24 def_bool y if AM33_3 || AM34_2
14 25
15config MMU 26config MMU
16 def_bool y 27 def_bool y
@@ -37,7 +48,7 @@ config GENERIC_CALIBRATE_DELAY
37 def_bool y 48 def_bool y
38 49
39config GENERIC_CMOS_UPDATE 50config GENERIC_CMOS_UPDATE
40 def_bool y 51 def_bool n
41 52
42config GENERIC_FIND_NEXT_BIT 53config GENERIC_FIND_NEXT_BIT
43 def_bool y 54 def_bool y
@@ -45,6 +56,27 @@ config GENERIC_FIND_NEXT_BIT
45config GENERIC_HWEIGHT 56config GENERIC_HWEIGHT
46 def_bool y 57 def_bool y
47 58
59config GENERIC_TIME
60 def_bool y
61
62config GENERIC_CLOCKEVENTS
63 def_bool y
64
65config GENERIC_CLOCKEVENTS_BUILD
66 def_bool y
67 depends on GENERIC_CLOCKEVENTS
68
69config GENERIC_CLOCKEVENTS_BROADCAST
70 bool
71
72config CEVT_MN10300
73 def_bool y
74 depends on GENERIC_CLOCKEVENTS
75
76config CSRC_MN10300
77 def_bool y
78 depends on GENERIC_TIME
79
48config GENERIC_BUG 80config GENERIC_BUG
49 def_bool y 81 def_bool y
50 82
@@ -61,18 +93,14 @@ config GENERIC_HARDIRQS
61config HOTPLUG_CPU 93config HOTPLUG_CPU
62 def_bool n 94 def_bool n
63 95
64config HZ 96mainmenu "Panasonic MN10300/AM33 Kernel Configuration"
65 int
66 default 1000
67
68mainmenu "Matsushita MN10300/AM33 Kernel Configuration"
69 97
70source "init/Kconfig" 98source "init/Kconfig"
71 99
72source "kernel/Kconfig.freezer" 100source "kernel/Kconfig.freezer"
73 101
74 102
75menu "Matsushita MN10300 system setup" 103menu "Panasonic MN10300 system setup"
76 104
77choice 105choice
78 prompt "Unit type" 106 prompt "Unit type"
@@ -87,6 +115,10 @@ config MN10300_UNIT_ASB2303
87config MN10300_UNIT_ASB2305 115config MN10300_UNIT_ASB2305
88 bool "ASB2305" 116 bool "ASB2305"
89 117
118config MN10300_UNIT_ASB2364
119 bool "ASB2364"
120 select SMSC911X_ARCH_HOOKS if SMSC911X
121
90endchoice 122endchoice
91 123
92choice 124choice
@@ -99,57 +131,51 @@ choice
99config MN10300_PROC_MN103E010 131config MN10300_PROC_MN103E010
100 bool "MN103E010" 132 bool "MN103E010"
101 depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305 133 depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305
134 select AM33_2
135 select MN10300_PROC_HAS_TTYSM0
136 select MN10300_PROC_HAS_TTYSM1
137 select MN10300_PROC_HAS_TTYSM2
138
139config MN10300_PROC_MN2WS0050
140 bool "MN2WS0050"
141 depends on MN10300_UNIT_ASB2364
142 select AM34_2
102 select MN10300_PROC_HAS_TTYSM0 143 select MN10300_PROC_HAS_TTYSM0
103 select MN10300_PROC_HAS_TTYSM1 144 select MN10300_PROC_HAS_TTYSM1
104 select MN10300_PROC_HAS_TTYSM2 145 select MN10300_PROC_HAS_TTYSM2
105 146
106endchoice 147endchoice
107 148
108choice 149config MN10300_HAS_ATOMIC_OPS_UNIT
109 prompt "Processor core support" 150 def_bool n
110 default MN10300_CPU_AM33V2
111 help 151 help
112 This option specifies the processor core for which the kernel will be 152 This should be enabled if the processor has an atomic ops unit
113 compiled. It affects the instruction set used. 153 capable of doing LL/SC equivalent operations.
114
115config MN10300_CPU_AM33V2
116 bool "AM33v2"
117
118endchoice
119 154
120config FPU 155config FPU
121 bool "FPU present" 156 bool "FPU present"
122 default y 157 default y
123 depends on MN10300_PROC_MN103E010 158 depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
124 159
125choice 160config LAZY_SAVE_FPU
126 prompt "CPU Caching mode" 161 bool "Save FPU state lazily"
127 default MN10300_CACHE_WBACK 162 default y
163 depends on FPU && !SMP
128 help 164 help
129 This option determines the caching mode for the kernel. 165 Enable this to be lazy in the saving of the FPU state to the owning
130 166 task's thread struct. This is useful if most tasks on the system
131 Write-Back caching mode involves the all reads and writes causing 167 don't use the FPU as only those tasks that use it will pass it
132 the affected cacheline to be read into the cache first before being 168 between them, and the state needn't be saved for a task that isn't
133 operated upon. Memory is not then updated by a write until the cache 169 using it.
134 is filled and a cacheline needs to be displaced from the cache to
135 make room. Only at that point is it written back.
136
137 Write-Through caching only fetches cachelines from memory on a
138 read. Writes always get written directly to memory. If the affected
139 cacheline is also in cache, it will be updated too.
140
141 The final option is to turn of caching entirely.
142 170
143config MN10300_CACHE_WBACK 171 This can't be so easily used on SMP as the process that owns the FPU
144 bool "Write-Back" 172 state on a CPU may be currently running on another CPU, so for the
173 moment, it is disabled.
145 174
146config MN10300_CACHE_WTHRU 175source "arch/mn10300/mm/Kconfig.cache"
147 bool "Write-Through"
148 176
149config MN10300_CACHE_DISABLED 177config MN10300_TLB_USE_PIDR
150 bool "Disabled" 178 def_bool y
151
152endchoice
153 179
154menu "Memory layout options" 180menu "Memory layout options"
155 181
@@ -170,24 +196,55 @@ config KERNEL_TEXT_ADDRESS
170 196
171config KERNEL_ZIMAGE_BASE_ADDRESS 197config KERNEL_ZIMAGE_BASE_ADDRESS
172 hex "Base address of compressed vmlinux image" 198 hex "Base address of compressed vmlinux image"
173 default "0x90700000" 199 default "0x50700000"
174 200
201config BOOT_STACK_OFFSET
202 hex
203 default "0xF00" if SMP
204 default "0xFF0" if !SMP
205
206config BOOT_STACK_SIZE
207 hex
208 depends on SMP
209 default "0x100"
175endmenu 210endmenu
176 211
177config PREEMPT 212config SMP
178 bool "Preemptible Kernel" 213 bool "Symmetric multi-processing support"
179 help 214 default y
180 This option reduces the latency of the kernel when reacting to 215 depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050
181 real-time or interactive events by allowing a low priority process to 216 ---help---
182 be preempted even if it is in kernel mode executing a system call. 217 This enables support for systems with more than one CPU. If you have
183 This allows applications to run more reliably even when the system is 218 a system with only one CPU, like most personal computers, say N. If
184 under load. 219 you have a system with more than one CPU, say Y.
220
221 If you say N here, the kernel will run on single and multiprocessor
222 machines, but will use only one CPU of a multiprocessor machine. If
223 you say Y here, the kernel will run on many, but not all,
224 singleprocessor machines. On a singleprocessor machine, the kernel
225 will run faster if you say N here.
185 226
186 Say Y here if you are building a kernel for a desktop, embedded 227 See also <file:Documentation/i386/IO-APIC.txt>,
187 or real-time system. Say N if you are unsure. 228 <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
229 <http://www.tldp.org/docs.html#howto>.
230
231 If you don't know what to do here, say N.
232
233config NR_CPUS
234 int
235 depends on SMP
236 default "2"
237
238config USE_GENERIC_SMP_HELPERS
239 bool
240 depends on SMP
241 default y
242
243source "kernel/Kconfig.preempt"
188 244
189config MN10300_CURRENT_IN_E2 245config MN10300_CURRENT_IN_E2
190 bool "Hold current task address in E2 register" 246 bool "Hold current task address in E2 register"
247 depends on !SMP
191 default y 248 default y
192 help 249 help
193 This option removes the E2/R2 register from the set available to gcc 250 This option removes the E2/R2 register from the set available to gcc
@@ -209,12 +266,15 @@ config MN10300_USING_JTAG
209 suppresses the use of certain hardware debugging features, such as 266 suppresses the use of certain hardware debugging features, such as
210 single-stepping, which are taken over completely by the JTAG unit. 267 single-stepping, which are taken over completely by the JTAG unit.
211 268
269source "kernel/Kconfig.hz"
270source "kernel/time/Kconfig"
271
212config MN10300_RTC 272config MN10300_RTC
213 bool "Using MN10300 RTC" 273 bool "Using MN10300 RTC"
214 depends on MN10300_PROC_MN103E010 274 depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
275 select GENERIC_CMOS_UPDATE
215 default n 276 default n
216 help 277 help
217
218 This option enables support for the RTC, thus enabling time to be 278 This option enables support for the RTC, thus enabling time to be
219 tracked, even when system is powered down. This is available on-chip 279 tracked, even when system is powered down. This is available on-chip
220 on the MN103E010. 280 on the MN103E010.
@@ -306,14 +366,23 @@ config MN10300_TTYSM1
306 366
307choice 367choice
308 prompt "Select the timer to supply the clock for SIF1" 368 prompt "Select the timer to supply the clock for SIF1"
309 default MN10300_TTYSM0_TIMER9 369 default MN10300_TTYSM1_TIMER12 \
370 if !(AM33_2 || AM33_3)
371 default MN10300_TTYSM1_TIMER9 \
372 if AM33_2 || AM33_3
310 depends on MN10300_TTYSM1 373 depends on MN10300_TTYSM1
311 374
375config MN10300_TTYSM1_TIMER12
376 bool "Use timer 12 (16-bit)"
377 depends on !(AM33_2 || AM33_3)
378
312config MN10300_TTYSM1_TIMER9 379config MN10300_TTYSM1_TIMER9
313 bool "Use timer 9 (16-bit)" 380 bool "Use timer 9 (16-bit)"
381 depends on AM33_2 || AM33_3
314 382
315config MN10300_TTYSM1_TIMER3 383config MN10300_TTYSM1_TIMER3
316 bool "Use timer 3 (8-bit)" 384 bool "Use timer 3 (8-bit)"
385 depends on AM33_2 || AM33_3
317 386
318endchoice 387endchoice
319 388
@@ -328,17 +397,107 @@ config MN10300_TTYSM2
328 397
329choice 398choice
330 prompt "Select the timer to supply the clock for SIF2" 399 prompt "Select the timer to supply the clock for SIF2"
331 default MN10300_TTYSM0_TIMER10 400 default MN10300_TTYSM2_TIMER3 \
401 if !(AM33_2 || AM33_3)
402 default MN10300_TTYSM2_TIMER10 \
403 if AM33_2 || AM33_3
332 depends on MN10300_TTYSM2 404 depends on MN10300_TTYSM2
333 405
406config MN10300_TTYSM2_TIMER9
407 bool "Use timer 9 (16-bit)"
408 depends on !(AM33_2 || AM33_3)
409
410config MN10300_TTYSM2_TIMER1
411 bool "Use timer 1 (8-bit)"
412 depends on !(AM33_2 || AM33_3)
413
414config MN10300_TTYSM2_TIMER3
415 bool "Use timer 3 (8-bit)"
416 depends on !(AM33_2 || AM33_3)
417
334config MN10300_TTYSM2_TIMER10 418config MN10300_TTYSM2_TIMER10
335 bool "Use timer 10 (16-bit)" 419 bool "Use timer 10 (16-bit)"
420 depends on AM33_2 || AM33_3
336 421
337endchoice 422endchoice
338 423
339config MN10300_TTYSM2_CTS 424config MN10300_TTYSM2_CTS
340 bool "Enable the use of the CTS line /dev/ttySM2" 425 bool "Enable the use of the CTS line /dev/ttySM2"
341 depends on MN10300_TTYSM2 426 depends on MN10300_TTYSM2 && AM33_2
427
428endmenu
429
430menu "Interrupt request priority options"
431
432comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highest, 6 is lowest)"
433
434comment "____Non-maskable interrupt levels____"
435comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
436
437config GDBSTUB_IRQ_LEVEL
438 int "GDBSTUB interrupt priority"
439 depends on GDBSTUB
440 range 0 1 if LINUX_CLI_LEVEL = 2
441 range 0 2 if LINUX_CLI_LEVEL = 3
442 range 0 3 if LINUX_CLI_LEVEL = 4
443 range 0 4 if LINUX_CLI_LEVEL = 5
444 range 0 5 if LINUX_CLI_LEVEL = 6
445 default 0
446
447comment "The following must be set to a higher priority than local_irq_disable()"
448
449config MN10300_SERIAL_IRQ_LEVEL
450 int "MN10300 on-chip serial interrupt priority"
451 depends on MN10300_TTYSM
452 range 1 1 if LINUX_CLI_LEVEL = 2
453 range 1 2 if LINUX_CLI_LEVEL = 3
454 range 1 3 if LINUX_CLI_LEVEL = 4
455 range 1 4 if LINUX_CLI_LEVEL = 5
456 range 1 5 if LINUX_CLI_LEVEL = 6
457 default 1
458
459comment "-"
460comment "____Maskable interrupt levels____"
461
462config LINUX_CLI_LEVEL
463 int "The highest interrupt priority excluded by local_irq_disable() (2-6)"
464 range 2 6
465 default 2
466 help
467 local_irq_disable() doesn't actually disable maskable interrupts -
468 what it does is restrict the levels of interrupt which are permitted
469 (a lower level indicates a higher priority) by lowering the value in
470 EPSW.IM from 7. Any interrupt is permitted for which the level is
471 lower than EPSW.IM.
472
473 Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip
474 serial DMA interrupts are allowed to interrupt normal disabled
475 sections.
476
477comment "The following must be set to a equal to or lower priority than LINUX_CLI_LEVEL"
478
479config TIMER_IRQ_LEVEL
480 int "Kernel timer interrupt priority"
481 range LINUX_CLI_LEVEL 6
482 default 4
483
484config PCI_IRQ_LEVEL
485 int "PCI interrupt priority"
486 depends on PCI
487 range LINUX_CLI_LEVEL 6
488 default 5
489
490config ETHERNET_IRQ_LEVEL
491 int "Ethernet interrupt priority"
492 depends on SMC91X || SMC911X || SMSC911X
493 range LINUX_CLI_LEVEL 6
494 default 6
495
496config EXT_SERIAL_IRQ_LEVEL
497 int "External serial port interrupt priority"
498 depends on SERIAL_8250
499 range LINUX_CLI_LEVEL 6
500 default 6
342 501
343endmenu 502endmenu
344 503
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
36ifeq ($(CONFIG_MN10300_PROC_MN103E010),y) 36ifeq ($(CONFIG_MN10300_PROC_MN103E010),y)
37PROCESSOR := mn103e010 37PROCESSOR := mn103e010
38endif 38endif
39ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y)
40PROCESSOR := mn2ws0050
41endif
39 42
40ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y) 43ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y)
41UNIT := asb2303 44UNIT := asb2303
@@ -43,6 +46,9 @@ endif
43ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y) 46ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y)
44UNIT := asb2305 47UNIT := asb2305
45endif 48endif
49ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y)
50UNIT := asb2364
51endif
46 52
47 53
48head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o 54head-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 502e1eb56709..7b50345b9e84 100644
--- a/arch/mn10300/boot/compressed/head.S
+++ b/arch/mn10300/boot/compressed/head.S
@@ -14,10 +14,29 @@
14 14
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>
18#ifdef CONFIG_SMP
19#include <proc/smp-regs.h>
20#endif
17 21
18 .globl startup_32 22 .globl startup_32
19startup_32: 23startup_32:
20 # 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
36startup_primary:
37#endif /* CONFIG_SMP */
38
39 # first save parameters from bootloader
21 mov param_save_area,a0 40 mov param_save_area,a0
22 mov d0,(a0) 41 mov d0,(a0)
23 mov d1,(4,a0) 42 mov d1,(4,a0)
@@ -37,8 +56,15 @@ startup_32:
37 mov (a0),d0 56 mov (a0),d0
38 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy 57 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
39 lne 58 lne
40 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD,d0 # writethru dcache 59
60#ifdef CONFIG_MN10300_CACHE_ENABLED
61#ifdef CONFIG_MN10300_CACHE_WBACK
62 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
63#else
64 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
65#endif /* WBACK */
41 movhu d0,(a0) # enable 66 movhu d0,(a0) # enable
67#endif /* !ENABLED */
42 68
43 # clear the BSS area 69 # clear the BSS area
44 mov __bss_start,a0 70 mov __bss_start,a0
@@ -54,6 +80,9 @@ bssclear_end:
54 80
55 # decompress the kernel 81 # decompress the kernel
56 call decompress_kernel[],0 82 call decompress_kernel[],0
83#ifdef CONFIG_MN10300_CACHE_WBACK
84 call mn10300_dcache_flush_inv[],0
85#endif
57 86
58 # disable caches again 87 # disable caches again
59 mov CHCTR,a0 88 mov CHCTR,a0
@@ -69,10 +98,46 @@ bssclear_end:
69 mov (4,a0),d1 98 mov (4,a0),d1
70 mov (8,a0),d2 99 mov (8,a0),d2
71 100
101 # jump to the kernel proper entry point
72 mov a3,sp 102 mov a3,sp
73 mov CONFIG_KERNEL_TEXT_ADDRESS,a0 103 mov CONFIG_KERNEL_TEXT_ADDRESS,a0
74 jmp (a0) 104 jmp (a0)
75 105
106
107###############################################################################
108#
109# Cache flush routines
110#
111###############################################################################
112#ifdef CONFIG_MN10300_CACHE_WBACK
113mn10300_dcache_flush_inv:
114 movhu (CHCTR),d0
115 btst CHCTR_DCEN,d0
116 beq mn10300_dcache_flush_inv_end
117
118 mov L1_CACHE_NENTRIES,d1
119 clr a1
120
121mn10300_dcache_flush_inv_loop:
122 mov (DCACHE_PURGE_WAY0(0),a1),d0 # unconditional purge
123 mov (DCACHE_PURGE_WAY1(0),a1),d0 # unconditional purge
124 mov (DCACHE_PURGE_WAY2(0),a1),d0 # unconditional purge
125 mov (DCACHE_PURGE_WAY3(0),a1),d0 # unconditional purge
126
127 add L1_CACHE_BYTES,a1
128 add -1,d1
129 bne mn10300_dcache_flush_inv_loop
130
131mn10300_dcache_flush_inv_end:
132 ret [],0
133#endif /* CONFIG_MN10300_CACHE_WBACK */
134
135
136###############################################################################
137#
138# Data areas
139#
140###############################################################################
76 .data 141 .data
77 .align 4 142 .align 4
78param_save_area: 143param_save_area:
diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig
index d80dfcb2c902..3f749b69ca71 100644
--- a/arch/mn10300/configs/asb2303_defconfig
+++ b/arch/mn10300/configs/asb2303_defconfig
@@ -12,6 +12,8 @@ CONFIG_SLAB=y
12CONFIG_PROFILING=y 12CONFIG_PROFILING=y
13# CONFIG_BLOCK is not set 13# CONFIG_BLOCK is not set
14CONFIG_PREEMPT=y 14CONFIG_PREEMPT=y
15CONFIG_NO_HZ=y
16CONFIG_HIGH_RES_TIMERS=y
15CONFIG_MN10300_RTC=y 17CONFIG_MN10300_RTC=y
16CONFIG_MN10300_TTYSM_CONSOLE=y 18CONFIG_MN10300_TTYSM_CONSOLE=y
17CONFIG_MN10300_TTYSM0=y 19CONFIG_MN10300_TTYSM0=y
diff --git a/arch/mn10300/configs/asb2364_defconfig b/arch/mn10300/configs/asb2364_defconfig
new file mode 100644
index 000000000000..83ce2f27b12a
--- /dev/null
+++ b/arch/mn10300/configs/asb2364_defconfig
@@ -0,0 +1,98 @@
1CONFIG_EXPERIMENTAL=y
2CONFIG_SYSVIPC=y
3CONFIG_POSIX_MQUEUE=y
4CONFIG_BSD_PROCESS_ACCT=y
5CONFIG_TASKSTATS=y
6CONFIG_TASK_DELAY_ACCT=y
7CONFIG_TASK_XACCT=y
8CONFIG_TASK_IO_ACCOUNTING=y
9CONFIG_LOG_BUF_SHIFT=14
10CONFIG_CGROUPS=y
11CONFIG_CGROUP_NS=y
12CONFIG_CGROUP_FREEZER=y
13CONFIG_CGROUP_DEVICE=y
14CONFIG_CGROUP_CPUACCT=y
15CONFIG_RESOURCE_COUNTERS=y
16CONFIG_RELAY=y
17# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
18CONFIG_EMBEDDED=y
19# CONFIG_KALLSYMS is not set
20# CONFIG_VM_EVENT_COUNTERS is not set
21CONFIG_SLAB=y
22CONFIG_PROFILING=y
23CONFIG_MODULES=y
24CONFIG_MODULE_UNLOAD=y
25# CONFIG_BLOCK is not set
26CONFIG_MN10300_UNIT_ASB2364=y
27CONFIG_PREEMPT=y
28# CONFIG_MN10300_USING_JTAG is not set
29CONFIG_NO_HZ=y
30CONFIG_HIGH_RES_TIMERS=y
31CONFIG_MN10300_TTYSM_CONSOLE=y
32CONFIG_MN10300_TTYSM0=y
33CONFIG_MN10300_TTYSM0_TIMER2=y
34CONFIG_MN10300_TTYSM1=y
35CONFIG_NET=y
36CONFIG_PACKET=y
37CONFIG_UNIX=y
38CONFIG_INET=y
39CONFIG_IP_MULTICAST=y
40CONFIG_IP_PNP=y
41CONFIG_IP_PNP_BOOTP=y
42# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
43# CONFIG_INET_XFRM_MODE_TUNNEL is not set
44# CONFIG_INET_XFRM_MODE_BEET is not set
45# CONFIG_INET_LRO is not set
46# CONFIG_INET_DIAG is not set
47CONFIG_IPV6=y
48# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
49# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
50# CONFIG_INET6_XFRM_MODE_BEET is not set
51# CONFIG_FIRMWARE_IN_KERNEL is not set
52CONFIG_CONNECTOR=y
53CONFIG_MTD=y
54CONFIG_MTD_DEBUG=y
55CONFIG_MTD_PARTITIONS=y
56CONFIG_MTD_REDBOOT_PARTS=y
57CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
58CONFIG_MTD_CHAR=y
59CONFIG_MTD_CFI=y
60CONFIG_MTD_JEDECPROBE=y
61CONFIG_MTD_CFI_ADV_OPTIONS=y
62CONFIG_MTD_CFI_GEOMETRY=y
63CONFIG_MTD_CFI_I4=y
64CONFIG_MTD_CFI_AMDSTD=y
65CONFIG_MTD_PHYSMAP=y
66CONFIG_NETDEVICES=y
67CONFIG_NET_ETHERNET=y
68CONFIG_SMSC911X=y
69# CONFIG_NETDEV_1000 is not set
70# CONFIG_NETDEV_10000 is not set
71# CONFIG_INPUT_MOUSEDEV is not set
72# CONFIG_INPUT_KEYBOARD is not set
73# CONFIG_INPUT_MOUSE is not set
74# CONFIG_SERIO is not set
75# CONFIG_VT is not set
76CONFIG_SERIAL_8250=y
77CONFIG_SERIAL_8250_CONSOLE=y
78CONFIG_SERIAL_8250_EXTENDED=y
79CONFIG_SERIAL_8250_SHARE_IRQ=y
80# CONFIG_HW_RANDOM is not set
81# CONFIG_HWMON is not set
82# CONFIG_HID_SUPPORT is not set
83# CONFIG_USB_SUPPORT is not set
84CONFIG_PROC_KCORE=y
85# CONFIG_PROC_PAGE_MONITOR is not set
86CONFIG_TMPFS=y
87CONFIG_TMPFS_POSIX_ACL=y
88CONFIG_JFFS2_FS=y
89CONFIG_NFS_FS=y
90CONFIG_NFS_V3=y
91CONFIG_ROOT_NFS=y
92CONFIG_MAGIC_SYSRQ=y
93CONFIG_STRIP_ASM_SYMS=y
94CONFIG_DEBUG_KERNEL=y
95CONFIG_DETECT_HUNG_TASK=y
96# CONFIG_DEBUG_BUGVERBOSE is not set
97CONFIG_DEBUG_INFO=y
98# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h
index f0cc1f84a72f..92d2f9298e38 100644
--- a/arch/mn10300/include/asm/atomic.h
+++ b/arch/mn10300/include/asm/atomic.h
@@ -1 +1,351 @@
1/* MN10300 Atomic counter operations
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#ifndef _ASM_ATOMIC_H
12#define _ASM_ATOMIC_H
13
14#include <asm/irqflags.h>
15
16#ifndef __ASSEMBLY__
17
18#ifdef CONFIG_SMP
19#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
20static inline
21unsigned long __xchg(volatile unsigned long *m, unsigned long val)
22{
23 unsigned long status;
24 unsigned long oldval;
25
26 asm volatile(
27 "1: mov %4,(_AAR,%3) \n"
28 " mov (_ADR,%3),%1 \n"
29 " mov %5,(_ADR,%3) \n"
30 " mov (_ADR,%3),%0 \n" /* flush */
31 " mov (_ASR,%3),%0 \n"
32 " or %0,%0 \n"
33 " bne 1b \n"
34 : "=&r"(status), "=&r"(oldval), "=m"(*m)
35 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
36 : "memory", "cc");
37
38 return oldval;
39}
40
41static inline unsigned long __cmpxchg(volatile unsigned long *m,
42 unsigned long old, unsigned long new)
43{
44 unsigned long status;
45 unsigned long oldval;
46
47 asm volatile(
48 "1: mov %4,(_AAR,%3) \n"
49 " mov (_ADR,%3),%1 \n"
50 " cmp %5,%1 \n"
51 " bne 2f \n"
52 " mov %6,(_ADR,%3) \n"
53 "2: mov (_ADR,%3),%0 \n" /* flush */
54 " mov (_ASR,%3),%0 \n"
55 " or %0,%0 \n"
56 " bne 1b \n"
57 : "=&r"(status), "=&r"(oldval), "=m"(*m)
58 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
59 "r"(old), "r"(new)
60 : "memory", "cc");
61
62 return oldval;
63}
64#else /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
65#error "No SMP atomic operation support!"
66#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
67
68#else /* CONFIG_SMP */
69
70/*
71 * Emulate xchg for non-SMP MN10300
72 */
73struct __xchg_dummy { unsigned long a[100]; };
74#define __xg(x) ((struct __xchg_dummy *)(x))
75
76static inline
77unsigned long __xchg(volatile unsigned long *m, unsigned long val)
78{
79 unsigned long oldval;
80 unsigned long flags;
81
82 flags = arch_local_cli_save();
83 oldval = *m;
84 *m = val;
85 arch_local_irq_restore(flags);
86 return oldval;
87}
88
89/*
90 * Emulate cmpxchg for non-SMP MN10300
91 */
92static inline unsigned long __cmpxchg(volatile unsigned long *m,
93 unsigned long old, unsigned long new)
94{
95 unsigned long oldval;
96 unsigned long flags;
97
98 flags = arch_local_cli_save();
99 oldval = *m;
100 if (oldval == old)
101 *m = new;
102 arch_local_irq_restore(flags);
103 return oldval;
104}
105
106#endif /* CONFIG_SMP */
107
108#define xchg(ptr, v) \
109 ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \
110 (unsigned long)(v)))
111
112#define cmpxchg(ptr, o, n) \
113 ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
114 (unsigned long)(o), \
115 (unsigned long)(n)))
116
117#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
118#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
119
120#endif /* !__ASSEMBLY__ */
121
122#ifndef CONFIG_SMP
1#include <asm-generic/atomic.h> 123#include <asm-generic/atomic.h>
124#else
125
126/*
127 * Atomic operations that C can't guarantee us. Useful for
128 * resource counting etc..
129 */
130
131#define ATOMIC_INIT(i) { (i) }
132
133#ifdef __KERNEL__
134
135/**
136 * atomic_read - read atomic variable
137 * @v: pointer of type atomic_t
138 *
139 * Atomically reads the value of @v. Note that the guaranteed
140 * useful range of an atomic_t is only 24 bits.
141 */
142#define atomic_read(v) ((v)->counter)
143
144/**
145 * atomic_set - set atomic variable
146 * @v: pointer of type atomic_t
147 * @i: required value
148 *
149 * Atomically sets the value of @v to @i. Note that the guaranteed
150 * useful range of an atomic_t is only 24 bits.
151 */
152#define atomic_set(v, i) (((v)->counter) = (i))
153
154/**
155 * atomic_add_return - add integer to atomic variable
156 * @i: integer value to add
157 * @v: pointer of type atomic_t
158 *
159 * Atomically adds @i to @v and returns the result
160 * Note that the guaranteed useful range of an atomic_t is only 24 bits.
161 */
162static inline int atomic_add_return(int i, atomic_t *v)
163{
164 int retval;
165#ifdef CONFIG_SMP
166 int status;
167
168 asm volatile(
169 "1: mov %4,(_AAR,%3) \n"
170 " mov (_ADR,%3),%1 \n"
171 " add %5,%1 \n"
172 " mov %1,(_ADR,%3) \n"
173 " mov (_ADR,%3),%0 \n" /* flush */
174 " mov (_ASR,%3),%0 \n"
175 " or %0,%0 \n"
176 " bne 1b \n"
177 : "=&r"(status), "=&r"(retval), "=m"(v->counter)
178 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
179 : "memory", "cc");
180
181#else
182 unsigned long flags;
183
184 flags = arch_local_cli_save();
185 retval = v->counter;
186 retval += i;
187 v->counter = retval;
188 arch_local_irq_restore(flags);
189#endif
190 return retval;
191}
192
193/**
194 * atomic_sub_return - subtract integer from atomic variable
195 * @i: integer value to subtract
196 * @v: pointer of type atomic_t
197 *
198 * Atomically subtracts @i from @v and returns the result
199 * Note that the guaranteed useful range of an atomic_t is only 24 bits.
200 */
201static inline int atomic_sub_return(int i, atomic_t *v)
202{
203 int retval;
204#ifdef CONFIG_SMP
205 int status;
206
207 asm volatile(
208 "1: mov %4,(_AAR,%3) \n"
209 " mov (_ADR,%3),%1 \n"
210 " sub %5,%1 \n"
211 " mov %1,(_ADR,%3) \n"
212 " mov (_ADR,%3),%0 \n" /* flush */
213 " mov (_ASR,%3),%0 \n"
214 " or %0,%0 \n"
215 " bne 1b \n"
216 : "=&r"(status), "=&r"(retval), "=m"(v->counter)
217 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
218 : "memory", "cc");
219
220#else
221 unsigned long flags;
222 flags = arch_local_cli_save();
223 retval = v->counter;
224 retval -= i;
225 v->counter = retval;
226 arch_local_irq_restore(flags);
227#endif
228 return retval;
229}
230
231static inline int atomic_add_negative(int i, atomic_t *v)
232{
233 return atomic_add_return(i, v) < 0;
234}
235
236static inline void atomic_add(int i, atomic_t *v)
237{
238 atomic_add_return(i, v);
239}
240
241static inline void atomic_sub(int i, atomic_t *v)
242{
243 atomic_sub_return(i, v);
244}
245
246static inline void atomic_inc(atomic_t *v)
247{
248 atomic_add_return(1, v);
249}
250
251static inline void atomic_dec(atomic_t *v)
252{
253 atomic_sub_return(1, v);
254}
255
256#define atomic_dec_return(v) atomic_sub_return(1, (v))
257#define atomic_inc_return(v) atomic_add_return(1, (v))
258
259#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
260#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
261#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
262
263#define atomic_add_unless(v, a, u) \
264({ \
265 int c, old; \
266 c = atomic_read(v); \
267 while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
268 c = old; \
269 c != (u); \
270})
271
272#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
273
274/**
275 * atomic_clear_mask - Atomically clear bits in memory
276 * @mask: Mask of the bits to be cleared
277 * @v: pointer to word in memory
278 *
279 * Atomically clears the bits set in mask from the memory word specified.
280 */
281static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
282{
283#ifdef CONFIG_SMP
284 int status;
285
286 asm volatile(
287 "1: mov %3,(_AAR,%2) \n"
288 " mov (_ADR,%2),%0 \n"
289 " and %4,%0 \n"
290 " mov %0,(_ADR,%2) \n"
291 " mov (_ADR,%2),%0 \n" /* flush */
292 " mov (_ASR,%2),%0 \n"
293 " or %0,%0 \n"
294 " bne 1b \n"
295 : "=&r"(status), "=m"(*addr)
296 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(~mask)
297 : "memory", "cc");
298#else
299 unsigned long flags;
300
301 mask = ~mask;
302 flags = arch_local_cli_save();
303 *addr &= mask;
304 arch_local_irq_restore(flags);
305#endif
306}
307
308/**
309 * atomic_set_mask - Atomically set bits in memory
310 * @mask: Mask of the bits to be set
311 * @v: pointer to word in memory
312 *
313 * Atomically sets the bits set in mask from the memory word specified.
314 */
315static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
316{
317#ifdef CONFIG_SMP
318 int status;
319
320 asm volatile(
321 "1: mov %3,(_AAR,%2) \n"
322 " mov (_ADR,%2),%0 \n"
323 " or %4,%0 \n"
324 " mov %0,(_ADR,%2) \n"
325 " mov (_ADR,%2),%0 \n" /* flush */
326 " mov (_ASR,%2),%0 \n"
327 " or %0,%0 \n"
328 " bne 1b \n"
329 : "=&r"(status), "=m"(*addr)
330 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(mask)
331 : "memory", "cc");
332#else
333 unsigned long flags;
334
335 flags = arch_local_cli_save();
336 *addr |= mask;
337 arch_local_irq_restore(flags);
338#endif
339}
340
341/* Atomic operations are already serializing on MN10300??? */
342#define smp_mb__before_atomic_dec() barrier()
343#define smp_mb__after_atomic_dec() barrier()
344#define smp_mb__before_atomic_inc() barrier()
345#define smp_mb__after_atomic_inc() barrier()
346
347#include <asm-generic/atomic-long.h>
348
349#endif /* __KERNEL__ */
350#endif /* CONFIG_SMP */
351#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index 3f50e9661076..3b8a868188f5 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -57,7 +57,7 @@
57#define clear_bit(nr, addr) ___clear_bit((nr), (addr)) 57#define clear_bit(nr, addr) ___clear_bit((nr), (addr))
58 58
59 59
60static inline void __clear_bit(int nr, volatile void *addr) 60static inline void __clear_bit(unsigned long nr, volatile void *addr)
61{ 61{
62 unsigned int *a = (unsigned int *) addr; 62 unsigned int *a = (unsigned int *) addr;
63 int mask; 63 int mask;
@@ -70,15 +70,15 @@ static inline void __clear_bit(int nr, volatile void *addr)
70/* 70/*
71 * test bit 71 * test bit
72 */ 72 */
73static inline int test_bit(int nr, const volatile void *addr) 73static inline int test_bit(unsigned long nr, const volatile void *addr)
74{ 74{
75 return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31)); 75 return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
76} 76}
77 77
78/* 78/*
79 * change bit 79 * change bit
80 */ 80 */
81static inline void __change_bit(int nr, volatile void *addr) 81static inline void __change_bit(unsigned long nr, volatile void *addr)
82{ 82{
83 int mask; 83 int mask;
84 unsigned int *a = (unsigned int *) addr; 84 unsigned int *a = (unsigned int *) addr;
@@ -88,7 +88,7 @@ static inline void __change_bit(int nr, volatile void *addr)
88 *a ^= mask; 88 *a ^= mask;
89} 89}
90 90
91extern void change_bit(int nr, volatile void *addr); 91extern void change_bit(unsigned long nr, volatile void *addr);
92 92
93/* 93/*
94 * test and set bit 94 * test and set bit
@@ -135,7 +135,7 @@ extern void change_bit(int nr, volatile void *addr);
135/* 135/*
136 * test and change bit 136 * test and change bit
137 */ 137 */
138static inline int __test_and_change_bit(int nr, volatile void *addr) 138static inline int __test_and_change_bit(unsigned long nr, volatile void *addr)
139{ 139{
140 int mask, retval; 140 int mask, retval;
141 unsigned int *a = (unsigned int *)addr; 141 unsigned int *a = (unsigned int *)addr;
@@ -148,7 +148,7 @@ static inline int __test_and_change_bit(int nr, volatile void *addr)
148 return retval; 148 return retval;
149} 149}
150 150
151extern int test_and_change_bit(int nr, volatile void *addr); 151extern int test_and_change_bit(unsigned long nr, volatile void *addr);
152 152
153#include <asm-generic/bitops/lock.h> 153#include <asm-generic/bitops/lock.h>
154 154
diff --git a/arch/mn10300/include/asm/cache.h b/arch/mn10300/include/asm/cache.h
index 781bf613366d..f29cde2cfc91 100644
--- a/arch/mn10300/include/asm/cache.h
+++ b/arch/mn10300/include/asm/cache.h
@@ -43,14 +43,18 @@
43 43
44/* instruction cache access registers */ 44/* instruction cache access registers */
45#define ICACHE_DATA(WAY, ENTRY, OFF) \ 45#define ICACHE_DATA(WAY, ENTRY, OFF) \
46 __SYSREG(0xc8000000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10 + (OFF) * 4, u32) 46 __SYSREG(0xc8000000 + (WAY) * L1_CACHE_WAYDISP + \
47 (ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32)
47#define ICACHE_TAG(WAY, ENTRY) \ 48#define ICACHE_TAG(WAY, ENTRY) \
48 __SYSREG(0xc8100000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10, u32) 49 __SYSREG(0xc8100000 + (WAY) * L1_CACHE_WAYDISP + \
50 (ENTRY) * L1_CACHE_BYTES, u32)
49 51
50/* instruction cache access registers */ 52/* data cache access registers */
51#define DCACHE_DATA(WAY, ENTRY, OFF) \ 53#define DCACHE_DATA(WAY, ENTRY, OFF) \
52 __SYSREG(0xc8200000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10 + (OFF) * 4, u32) 54 __SYSREG(0xc8200000 + (WAY) * L1_CACHE_WAYDISP + \
55 (ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32)
53#define DCACHE_TAG(WAY, ENTRY) \ 56#define DCACHE_TAG(WAY, ENTRY) \
54 __SYSREG(0xc8300000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10, u32) 57 __SYSREG(0xc8300000 + (WAY) * L1_CACHE_WAYDISP + \
58 (ENTRY) * L1_CACHE_BYTES, u32)
55 59
56#endif /* _ASM_CACHE_H */ 60#endif /* _ASM_CACHE_H */
diff --git a/arch/mn10300/include/asm/cacheflush.h b/arch/mn10300/include/asm/cacheflush.h
index 29e692f7f030..faed90240ded 100644
--- a/arch/mn10300/include/asm/cacheflush.h
+++ b/arch/mn10300/include/asm/cacheflush.h
@@ -17,66 +17,55 @@
17#include <linux/mm.h> 17#include <linux/mm.h>
18 18
19/* 19/*
20 * virtually-indexed cache management (our cache is physically indexed) 20 * Primitive routines
21 */ 21 */
22#define flush_cache_all() do {} while (0) 22#ifdef CONFIG_MN10300_CACHE_ENABLED
23#define flush_cache_mm(mm) do {} while (0) 23extern void mn10300_local_icache_inv(void);
24#define flush_cache_dup_mm(mm) do {} while (0) 24extern void mn10300_local_icache_inv_page(unsigned long start);
25#define flush_cache_range(mm, start, end) do {} while (0) 25extern void mn10300_local_icache_inv_range(unsigned long start, unsigned long end);
26#define flush_cache_page(vma, vmaddr, pfn) do {} while (0) 26extern void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size);
27#define flush_cache_vmap(start, end) do {} while (0) 27extern void mn10300_local_dcache_inv(void);
28#define flush_cache_vunmap(start, end) do {} while (0) 28extern void mn10300_local_dcache_inv_page(unsigned long start);
29#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 29extern void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end);
30#define flush_dcache_page(page) do {} while (0) 30extern void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size);
31#define flush_dcache_mmap_lock(mapping) do {} while (0)
32#define flush_dcache_mmap_unlock(mapping) do {} while (0)
33
34/*
35 * physically-indexed cache management
36 */
37#ifndef CONFIG_MN10300_CACHE_DISABLED
38
39extern void flush_icache_range(unsigned long start, unsigned long end);
40extern void flush_icache_page(struct vm_area_struct *vma, struct page *pg);
41
42#else
43
44#define flush_icache_range(start, end) do {} while (0)
45#define flush_icache_page(vma, pg) do {} while (0)
46
47#endif
48
49#define flush_icache_user_range(vma, pg, adr, len) \
50 flush_icache_range(adr, adr + len)
51
52#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
53 do { \
54 memcpy(dst, src, len); \
55 flush_icache_page(vma, page); \
56 } while (0)
57
58#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
59 memcpy(dst, src, len)
60
61/*
62 * primitive routines
63 */
64#ifndef CONFIG_MN10300_CACHE_DISABLED
65extern void mn10300_icache_inv(void); 31extern void mn10300_icache_inv(void);
32extern void mn10300_icache_inv_page(unsigned long start);
33extern void mn10300_icache_inv_range(unsigned long start, unsigned long end);
34extern void mn10300_icache_inv_range2(unsigned long start, unsigned long size);
66extern void mn10300_dcache_inv(void); 35extern void mn10300_dcache_inv(void);
67extern void mn10300_dcache_inv_page(unsigned start); 36extern void mn10300_dcache_inv_page(unsigned long start);
68extern void mn10300_dcache_inv_range(unsigned start, unsigned end); 37extern void mn10300_dcache_inv_range(unsigned long start, unsigned long end);
69extern void mn10300_dcache_inv_range2(unsigned start, unsigned size); 38extern void mn10300_dcache_inv_range2(unsigned long start, unsigned long size);
70#ifdef CONFIG_MN10300_CACHE_WBACK 39#ifdef CONFIG_MN10300_CACHE_WBACK
40extern void mn10300_local_dcache_flush(void);
41extern void mn10300_local_dcache_flush_page(unsigned long start);
42extern void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end);
43extern void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size);
44extern void mn10300_local_dcache_flush_inv(void);
45extern void mn10300_local_dcache_flush_inv_page(unsigned long start);
46extern void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end);
47extern void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size);
71extern void mn10300_dcache_flush(void); 48extern void mn10300_dcache_flush(void);
72extern void mn10300_dcache_flush_page(unsigned start); 49extern void mn10300_dcache_flush_page(unsigned long start);
73extern void mn10300_dcache_flush_range(unsigned start, unsigned end); 50extern void mn10300_dcache_flush_range(unsigned long start, unsigned long end);
74extern void mn10300_dcache_flush_range2(unsigned start, unsigned size); 51extern void mn10300_dcache_flush_range2(unsigned long start, unsigned long size);
75extern void mn10300_dcache_flush_inv(void); 52extern void mn10300_dcache_flush_inv(void);
76extern void mn10300_dcache_flush_inv_page(unsigned start); 53extern void mn10300_dcache_flush_inv_page(unsigned long start);
77extern void mn10300_dcache_flush_inv_range(unsigned start, unsigned end); 54extern void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end);
78extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size); 55extern void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size);
79#else 56#else
57#define mn10300_local_dcache_flush() do {} while (0)
58#define mn10300_local_dcache_flush_page(start) do {} while (0)
59#define mn10300_local_dcache_flush_range(start, end) do {} while (0)
60#define mn10300_local_dcache_flush_range2(start, size) do {} while (0)
61#define mn10300_local_dcache_flush_inv() \
62 mn10300_local_dcache_inv()
63#define mn10300_local_dcache_flush_inv_page(start) \
64 mn10300_local_dcache_inv_page(start)
65#define mn10300_local_dcache_flush_inv_range(start, end) \
66 mn10300_local_dcache_inv_range(start, end)
67#define mn10300_local_dcache_flush_inv_range2(start, size) \
68 mn10300_local_dcache_inv_range2(start, size)
80#define mn10300_dcache_flush() do {} while (0) 69#define mn10300_dcache_flush() do {} while (0)
81#define mn10300_dcache_flush_page(start) do {} while (0) 70#define mn10300_dcache_flush_page(start) do {} while (0)
82#define mn10300_dcache_flush_range(start, end) do {} while (0) 71#define mn10300_dcache_flush_range(start, end) do {} while (0)
@@ -90,7 +79,26 @@ extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size);
90 mn10300_dcache_inv_range2((start), (size)) 79 mn10300_dcache_inv_range2((start), (size))
91#endif /* CONFIG_MN10300_CACHE_WBACK */ 80#endif /* CONFIG_MN10300_CACHE_WBACK */
92#else 81#else
82#define mn10300_local_icache_inv() do {} while (0)
83#define mn10300_local_icache_inv_page(start) do {} while (0)
84#define mn10300_local_icache_inv_range(start, end) do {} while (0)
85#define mn10300_local_icache_inv_range2(start, size) do {} while (0)
86#define mn10300_local_dcache_inv() do {} while (0)
87#define mn10300_local_dcache_inv_page(start) do {} while (0)
88#define mn10300_local_dcache_inv_range(start, end) do {} while (0)
89#define mn10300_local_dcache_inv_range2(start, size) do {} while (0)
90#define mn10300_local_dcache_flush() do {} while (0)
91#define mn10300_local_dcache_flush_inv_page(start) do {} while (0)
92#define mn10300_local_dcache_flush_inv() do {} while (0)
93#define mn10300_local_dcache_flush_inv_range(start, end)do {} while (0)
94#define mn10300_local_dcache_flush_inv_range2(start, size) do {} while (0)
95#define mn10300_local_dcache_flush_page(start) do {} while (0)
96#define mn10300_local_dcache_flush_range(start, end) do {} while (0)
97#define mn10300_local_dcache_flush_range2(start, size) do {} while (0)
93#define mn10300_icache_inv() do {} while (0) 98#define mn10300_icache_inv() do {} while (0)
99#define mn10300_icache_inv_page(start) do {} while (0)
100#define mn10300_icache_inv_range(start, end) do {} while (0)
101#define mn10300_icache_inv_range2(start, size) do {} while (0)
94#define mn10300_dcache_inv() do {} while (0) 102#define mn10300_dcache_inv() do {} while (0)
95#define mn10300_dcache_inv_page(start) do {} while (0) 103#define mn10300_dcache_inv_page(start) do {} while (0)
96#define mn10300_dcache_inv_range(start, end) do {} while (0) 104#define mn10300_dcache_inv_range(start, end) do {} while (0)
@@ -103,10 +111,56 @@ extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size);
103#define mn10300_dcache_flush_page(start) do {} while (0) 111#define mn10300_dcache_flush_page(start) do {} while (0)
104#define mn10300_dcache_flush_range(start, end) do {} while (0) 112#define mn10300_dcache_flush_range(start, end) do {} while (0)
105#define mn10300_dcache_flush_range2(start, size) do {} while (0) 113#define mn10300_dcache_flush_range2(start, size) do {} while (0)
106#endif /* CONFIG_MN10300_CACHE_DISABLED */ 114#endif /* CONFIG_MN10300_CACHE_ENABLED */
115
116/*
117 * Virtually-indexed cache management (our cache is physically indexed)
118 */
119#define flush_cache_all() do {} while (0)
120#define flush_cache_mm(mm) do {} while (0)
121#define flush_cache_dup_mm(mm) do {} while (0)
122#define flush_cache_range(mm, start, end) do {} while (0)
123#define flush_cache_page(vma, vmaddr, pfn) do {} while (0)
124#define flush_cache_vmap(start, end) do {} while (0)
125#define flush_cache_vunmap(start, end) do {} while (0)
126#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
127#define flush_dcache_page(page) do {} while (0)
128#define flush_dcache_mmap_lock(mapping) do {} while (0)
129#define flush_dcache_mmap_unlock(mapping) do {} while (0)
130
131/*
132 * Physically-indexed cache management
133 */
134#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE)
135extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
136extern void flush_icache_range(unsigned long start, unsigned long end);
137#elif defined(CONFIG_MN10300_CACHE_INV_ICACHE)
138static inline void flush_icache_page(struct vm_area_struct *vma,
139 struct page *page)
140{
141 mn10300_icache_inv_page(page_to_phys(page));
142}
143extern void flush_icache_range(unsigned long start, unsigned long end);
144#else
145#define flush_icache_range(start, end) do {} while (0)
146#define flush_icache_page(vma, pg) do {} while (0)
147#endif
148
149
150#define flush_icache_user_range(vma, pg, adr, len) \
151 flush_icache_range(adr, adr + len)
152
153#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
154 do { \
155 memcpy(dst, src, len); \
156 flush_icache_page(vma, page); \
157 } while (0)
158
159#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
160 memcpy(dst, src, len)
107 161
108/* 162/*
109 * internal debugging function 163 * Internal debugging function
110 */ 164 */
111#ifdef CONFIG_DEBUG_PAGEALLOC 165#ifdef CONFIG_DEBUG_PAGEALLOC
112extern void kernel_map_pages(struct page *page, int numpages, int enable); 166extern void kernel_map_pages(struct page *page, int numpages, int enable);
diff --git a/arch/mn10300/include/asm/cpu-regs.h b/arch/mn10300/include/asm/cpu-regs.h
index 757e9b5388ea..90ed4a365c97 100644
--- a/arch/mn10300/include/asm/cpu-regs.h
+++ b/arch/mn10300/include/asm/cpu-regs.h
@@ -15,7 +15,6 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#endif 16#endif
17 17
18#ifdef CONFIG_MN10300_CPU_AM33V2
19/* we tell the compiler to pretend to be AM33 so that it doesn't try and use 18/* we tell the compiler to pretend to be AM33 so that it doesn't try and use
20 * the FP regs, but tell the assembler that we're actually allowed AM33v2 19 * the FP regs, but tell the assembler that we're actually allowed AM33v2
21 * instructions */ 20 * instructions */
@@ -24,7 +23,6 @@ asm(" .am33_2\n");
24#else 23#else
25.am33_2 24.am33_2
26#endif 25#endif
27#endif
28 26
29#ifdef __KERNEL__ 27#ifdef __KERNEL__
30 28
@@ -58,6 +56,9 @@ asm(" .am33_2\n");
58#define EPSW_nAR 0x00040000 /* register bank control */ 56#define EPSW_nAR 0x00040000 /* register bank control */
59#define EPSW_ML 0x00080000 /* monitor level */ 57#define EPSW_ML 0x00080000 /* monitor level */
60#define EPSW_FE 0x00100000 /* FPU enable */ 58#define EPSW_FE 0x00100000 /* FPU enable */
59#define EPSW_IM_SHIFT 8 /* EPSW_IM_SHIFT determines the interrupt mode */
60
61#define NUM2EPSW_IM(num) ((num) << EPSW_IM_SHIFT)
61 62
62/* FPU registers */ 63/* FPU registers */
63#define FPCR_EF_I 0x00000001 /* inexact result FPU exception flag */ 64#define FPCR_EF_I 0x00000001 /* inexact result FPU exception flag */
@@ -99,9 +100,11 @@ asm(" .am33_2\n");
99#define CPUREV __SYSREGC(0xc0000050, u32) /* CPU revision register */ 100#define CPUREV __SYSREGC(0xc0000050, u32) /* CPU revision register */
100#define CPUREV_TYPE 0x0000000f /* CPU type */ 101#define CPUREV_TYPE 0x0000000f /* CPU type */
101#define CPUREV_TYPE_S 0 102#define CPUREV_TYPE_S 0
102#define CPUREV_TYPE_AM33V1 0x00000000 /* - AM33 V1 core, AM33/1.00 arch */ 103#define CPUREV_TYPE_AM33_1 0x00000000 /* - AM33-1 core, AM33/1.00 arch */
103#define CPUREV_TYPE_AM33V2 0x00000001 /* - AM33 V2 core, AM33/2.00 arch */ 104#define CPUREV_TYPE_AM33_2 0x00000001 /* - AM33-2 core, AM33/2.00 arch */
104#define CPUREV_TYPE_AM34V1 0x00000002 /* - AM34 V1 core, AM33/2.00 arch */ 105#define CPUREV_TYPE_AM34_1 0x00000002 /* - AM34-1 core, AM33/2.00 arch */
106#define CPUREV_TYPE_AM33_3 0x00000003 /* - AM33-3 core, AM33/2.00 arch */
107#define CPUREV_TYPE_AM34_2 0x00000004 /* - AM34-2 core, AM33/3.00 arch */
105#define CPUREV_REVISION 0x000000f0 /* CPU revision */ 108#define CPUREV_REVISION 0x000000f0 /* CPU revision */
106#define CPUREV_REVISION_S 4 109#define CPUREV_REVISION_S 4
107#define CPUREV_ICWAY 0x00000f00 /* number of instruction cache ways */ 110#define CPUREV_ICWAY 0x00000f00 /* number of instruction cache ways */
@@ -180,6 +183,21 @@ asm(" .am33_2\n");
180#define CHCTR_ICWMD 0x0f00 /* instruction cache way mode */ 183#define CHCTR_ICWMD 0x0f00 /* instruction cache way mode */
181#define CHCTR_DCWMD 0xf000 /* data cache way mode */ 184#define CHCTR_DCWMD 0xf000 /* data cache way mode */
182 185
186#ifdef CONFIG_AM34_2
187#define ICIVCR __SYSREG(0xc0000c00, u32) /* icache area invalidate control */
188#define ICIVCR_ICIVBSY 0x00000008 /* icache area invalidate busy */
189#define ICIVCR_ICI 0x00000001 /* icache area invalidate */
190
191#define ICIVMR __SYSREG(0xc0000c04, u32) /* icache area invalidate mask */
192
193#define DCPGCR __SYSREG(0xc0000c10, u32) /* data cache area purge control */
194#define DCPGCR_DCPGBSY 0x00000008 /* data cache area purge busy */
195#define DCPGCR_DCP 0x00000002 /* data cache area purge */
196#define DCPGCR_DCI 0x00000001 /* data cache area invalidate */
197
198#define DCPGMR __SYSREG(0xc0000c14, u32) /* data cache area purge mask */
199#endif /* CONFIG_AM34_2 */
200
183/* MMU control registers */ 201/* MMU control registers */
184#define MMUCTR __SYSREG(0xc0000090, u32) /* MMU control register */ 202#define MMUCTR __SYSREG(0xc0000090, u32) /* MMU control register */
185#define MMUCTR_IRP 0x0000003f /* instruction TLB replace pointer */ 203#define MMUCTR_IRP 0x0000003f /* instruction TLB replace pointer */
@@ -203,6 +221,9 @@ asm(" .am33_2\n");
203#define MMUCTR_DTL_LOCK0_3 0x03000000 /* - entry 0-3 locked */ 221#define MMUCTR_DTL_LOCK0_3 0x03000000 /* - entry 0-3 locked */
204#define MMUCTR_DTL_LOCK0_7 0x04000000 /* - entry 0-7 locked */ 222#define MMUCTR_DTL_LOCK0_7 0x04000000 /* - entry 0-7 locked */
205#define MMUCTR_DTL_LOCK0_15 0x05000000 /* - entry 0-15 locked */ 223#define MMUCTR_DTL_LOCK0_15 0x05000000 /* - entry 0-15 locked */
224#ifdef CONFIG_AM34_2
225#define MMUCTR_WTE 0x80000000 /* write-through cache TLB entry bit enable */
226#endif
206 227
207#define PIDR __SYSREG(0xc0000094, u16) /* PID register */ 228#define PIDR __SYSREG(0xc0000094, u16) /* PID register */
208#define PIDR_PID 0x00ff /* process identifier */ 229#define PIDR_PID 0x00ff /* process identifier */
@@ -231,14 +252,6 @@ asm(" .am33_2\n");
231#define xPTEL_PS_4Mb 0x00000c00 /* - 4Mb page */ 252#define xPTEL_PS_4Mb 0x00000c00 /* - 4Mb page */
232#define xPTEL_PPN 0xfffff006 /* physical page number */ 253#define xPTEL_PPN 0xfffff006 /* physical page number */
233 254
234#define xPTEL_V_BIT 0 /* bit numbers corresponding to above masks */
235#define xPTEL_UNUSED1_BIT 1
236#define xPTEL_UNUSED2_BIT 2
237#define xPTEL_C_BIT 3
238#define xPTEL_PV_BIT 4
239#define xPTEL_D_BIT 5
240#define xPTEL_G_BIT 9
241
242#define IPTEU __SYSREG(0xc00000a4, u32) /* instruction TLB virtual addr */ 255#define IPTEU __SYSREG(0xc00000a4, u32) /* instruction TLB virtual addr */
243#define DPTEU __SYSREG(0xc00000b4, u32) /* data TLB virtual addr */ 256#define DPTEU __SYSREG(0xc00000b4, u32) /* data TLB virtual addr */
244#define xPTEU_VPN 0xfffffc00 /* virtual page number */ 257#define xPTEU_VPN 0xfffffc00 /* virtual page number */
@@ -262,7 +275,16 @@ asm(" .am33_2\n");
262#define xPTEL2_PS_128Kb 0x00000100 /* - 128Kb page */ 275#define xPTEL2_PS_128Kb 0x00000100 /* - 128Kb page */
263#define xPTEL2_PS_1Kb 0x00000200 /* - 1Kb page */ 276#define xPTEL2_PS_1Kb 0x00000200 /* - 1Kb page */
264#define xPTEL2_PS_4Mb 0x00000300 /* - 4Mb page */ 277#define xPTEL2_PS_4Mb 0x00000300 /* - 4Mb page */
265#define xPTEL2_PPN 0xfffffc00 /* physical page number */ 278#define xPTEL2_CWT 0x00000400 /* cacheable write-through */
279#define xPTEL2_UNUSED1 0x00000800 /* unused bit (broadcast mask) */
280#define xPTEL2_PPN 0xfffff000 /* physical page number */
281
282#define xPTEL2_V_BIT 0 /* bit numbers corresponding to above masks */
283#define xPTEL2_C_BIT 1
284#define xPTEL2_PV_BIT 2
285#define xPTEL2_D_BIT 3
286#define xPTEL2_G_BIT 7
287#define xPTEL2_UNUSED1_BIT 11
266 288
267#define MMUFCR __SYSREGC(0xc000009c, u32) /* MMU exception cause */ 289#define MMUFCR __SYSREGC(0xc000009c, u32) /* MMU exception cause */
268#define MMUFCR_IFC __SYSREGC(0xc000009c, u16) /* MMU instruction excep cause */ 290#define MMUFCR_IFC __SYSREGC(0xc000009c, u16) /* MMU instruction excep cause */
@@ -285,6 +307,47 @@ asm(" .am33_2\n");
285#define MMUFCR_xFC_PR_RWK_RWU 0x01c0 /* - R/W kernel and R/W user */ 307#define MMUFCR_xFC_PR_RWK_RWU 0x01c0 /* - R/W kernel and R/W user */
286#define MMUFCR_xFC_ILLADDR 0x0200 /* illegal address excep flag */ 308#define MMUFCR_xFC_ILLADDR 0x0200 /* illegal address excep flag */
287 309
310#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
311/* atomic operation registers */
312#define AAR __SYSREG(0xc0000a00, u32) /* cacheable address */
313#define AAR2 __SYSREG(0xc0000a04, u32) /* uncacheable address */
314#define ADR __SYSREG(0xc0000a08, u32) /* data */
315#define ASR __SYSREG(0xc0000a0c, u32) /* status */
316#define AARU __SYSREG(0xd400aa00, u32) /* user address */
317#define ADRU __SYSREG(0xd400aa08, u32) /* user data */
318#define ASRU __SYSREG(0xd400aa0c, u32) /* user status */
319
320#define ASR_RW 0x00000008 /* read */
321#define ASR_BW 0x00000004 /* bus error */
322#define ASR_IW 0x00000002 /* interrupt */
323#define ASR_LW 0x00000001 /* bus lock */
324
325#define ASRU_RW ASR_RW /* read */
326#define ASRU_BW ASR_BW /* bus error */
327#define ASRU_IW ASR_IW /* interrupt */
328#define ASRU_LW ASR_LW /* bus lock */
329
330/* in inline ASM, we stick the base pointer in to a reg and use offsets from
331 * it */
332#define ATOMIC_OPS_BASE_ADDR 0xc0000a00
333#ifndef __ASSEMBLY__
334asm(
335 "_AAR = 0\n"
336 "_AAR2 = 4\n"
337 "_ADR = 8\n"
338 "_ASR = 12\n");
339#else
340#define _AAR 0
341#define _AAR2 4
342#define _ADR 8
343#define _ASR 12
344#endif
345
346/* physical page address for userspace atomic operations registers */
347#define USER_ATOMIC_OPS_PAGE_ADDR 0xd400a000
348
349#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
350
288#endif /* __KERNEL__ */ 351#endif /* __KERNEL__ */
289 352
290#endif /* _ASM_CPU_REGS_H */ 353#endif /* _ASM_CPU_REGS_H */
diff --git a/arch/mn10300/include/asm/dmactl-regs.h b/arch/mn10300/include/asm/dmactl-regs.h
index 58a199da0f4a..80337b339c90 100644
--- a/arch/mn10300/include/asm/dmactl-regs.h
+++ b/arch/mn10300/include/asm/dmactl-regs.h
@@ -11,91 +11,6 @@
11#ifndef _ASM_DMACTL_REGS_H 11#ifndef _ASM_DMACTL_REGS_H
12#define _ASM_DMACTL_REGS_H 12#define _ASM_DMACTL_REGS_H
13 13
14#include <asm/cpu-regs.h> 14#include <proc/dmactl-regs.h>
15
16#ifdef __KERNEL__
17
18/* DMA registers */
19#define DMxCTR(N) __SYSREG(0xd2000000 + ((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_AFE 0x0000000d /* - analogue front-end interrupt source */
34#define DMxCTR_BG_ADC 0x0000000e /* - A/D conversion end interrupt source */
35#define DMxCTR_BG_IRDA 0x0000000f /* - IrDA interrupt source */
36#define DMxCTR_BG_RTC 0x00000010 /* - RTC interrupt source */
37#define DMxCTR_BG_XIRQ0 0x00000011 /* - XIRQ0 pin interrupt source */
38#define DMxCTR_BG_XIRQ1 0x00000012 /* - XIRQ1 pin interrupt source */
39#define DMxCTR_BG_XDMR0 0x00000013 /* - external request 0 source (XDMR0 pin) */
40#define DMxCTR_BG_XDMR1 0x00000014 /* - external request 1 source (XDMR1 pin) */
41#define DMxCTR_SAM 0x000000e0 /* DMA transfer src addr mode */
42#define DMxCTR_SAM_INCR 0x00000000 /* - increment */
43#define DMxCTR_SAM_DECR 0x00000020 /* - decrement */
44#define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */
45#define DMxCTR_DAM 0x00000000 /* DMA transfer dest addr mode */
46#define DMxCTR_DAM_INCR 0x00000000 /* - increment */
47#define DMxCTR_DAM_DECR 0x00000100 /* - decrement */
48#define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */
49#define DMxCTR_TM 0x00001800 /* DMA transfer mode */
50#define DMxCTR_TM_BATCH 0x00000000 /* - batch transfer */
51#define DMxCTR_TM_INTERM 0x00001000 /* - intermittent transfer */
52#define DMxCTR_UT 0x00006000 /* DMA transfer unit */
53#define DMxCTR_UT_1 0x00000000 /* - 1 byte */
54#define DMxCTR_UT_2 0x00002000 /* - 2 byte */
55#define DMxCTR_UT_4 0x00004000 /* - 4 byte */
56#define DMxCTR_UT_16 0x00006000 /* - 16 byte */
57#define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */
58#define DMxCTR_RQM 0x00060000 /* external request input source mode */
59#define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */
60#define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */
61#define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */
62#define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */
63#define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */
64#define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */
65
66#define DMxSRC(N) __SYSREG(0xd2000004 + ((N) * 0x100), u32) /* control reg */
67
68#define DMxDST(N) __SYSREG(0xd2000008 + ((N) * 0x100), u32) /* src addr reg */
69
70#define DMxSIZ(N) __SYSREG(0xd200000c + ((N) * 0x100), u32) /* dest addr reg */
71#define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */
72
73#define DMxCYC(N) __SYSREG(0xd2000010 + ((N) * 0x100), u32) /* intermittent
74 * size reg */
75#define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */
76
77#define DM0IRQ 16 /* DMA channel 0 complete IRQ */
78#define DM1IRQ 17 /* DMA channel 1 complete IRQ */
79#define DM2IRQ 18 /* DMA channel 2 complete IRQ */
80#define DM3IRQ 19 /* DMA channel 3 complete IRQ */
81
82#define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */
83#define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */
84#define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */
85#define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */
86
87#ifndef __ASSEMBLY__
88
89struct mn10300_dmactl_regs {
90 u32 ctr;
91 const void *src;
92 void *dst;
93 u32 siz;
94 u32 cyc;
95} __attribute__((aligned(0x100)));
96
97#endif /* __ASSEMBLY__ */
98
99#endif /* __KERNEL__ */
100 15
101#endif /* _ASM_DMACTL_REGS_H */ 16#endif /* _ASM_DMACTL_REGS_H */
diff --git a/arch/mn10300/include/asm/elf.h b/arch/mn10300/include/asm/elf.h
index e5fa97cd9a14..8157c9267f42 100644
--- a/arch/mn10300/include/asm/elf.h
+++ b/arch/mn10300/include/asm/elf.h
@@ -32,6 +32,12 @@
32#define R_MN10300_ALIGN 34 /* Alignment requirement. */ 32#define R_MN10300_ALIGN 34 /* Alignment requirement. */
33 33
34/* 34/*
35 * AM33/AM34 HW Capabilities
36 */
37#define HWCAP_MN10300_ATOMIC_OP_UNIT 1 /* Has AM34 Atomic Operations */
38
39
40/*
35 * ELF register definitions.. 41 * ELF register definitions..
36 */ 42 */
37typedef unsigned long elf_greg_t; 43typedef unsigned long elf_greg_t;
@@ -47,8 +53,6 @@ typedef struct {
47 u_int32_t fpcr; 53 u_int32_t fpcr;
48} elf_fpregset_t; 54} elf_fpregset_t;
49 55
50extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
51
52/* 56/*
53 * This is used to ensure we don't load something for the wrong architecture 57 * This is used to ensure we don't load something for the wrong architecture
54 */ 58 */
@@ -130,7 +134,11 @@ do { \
130 * instruction set this CPU supports. This could be done in user space, 134 * instruction set this CPU supports. This could be done in user space,
131 * but it's not easy, and we've already done it here. 135 * but it's not easy, and we've already done it here.
132 */ 136 */
137#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
138#define ELF_HWCAP (HWCAP_MN10300_ATOMIC_OP_UNIT)
139#else
133#define ELF_HWCAP (0) 140#define ELF_HWCAP (0)
141#endif
134 142
135/* 143/*
136 * This yields a string that ld.so will use to load implementation 144 * This yields a string that ld.so will use to load implementation
diff --git a/arch/mn10300/include/asm/exceptions.h b/arch/mn10300/include/asm/exceptions.h
index fa16466ef3f9..ca3e20508c77 100644
--- a/arch/mn10300/include/asm/exceptions.h
+++ b/arch/mn10300/include/asm/exceptions.h
@@ -15,8 +15,8 @@
15 15
16/* 16/*
17 * define the breakpoint instruction opcode to use 17 * define the breakpoint instruction opcode to use
18 * - note that the JTAG unit steals 0xFF, so we want to avoid that if we can 18 * - note that the JTAG unit steals 0xFF, so you can't use JTAG and GDBSTUB at
19 * (can use 0xF7) 19 * the same time.
20 */ 20 */
21#define GDBSTUB_BKPT 0xFF 21#define GDBSTUB_BKPT 0xFF
22 22
@@ -90,7 +90,6 @@ enum exception_code {
90 90
91extern void __set_intr_stub(enum exception_code code, void *handler); 91extern void __set_intr_stub(enum exception_code code, void *handler);
92extern void set_intr_stub(enum exception_code code, void *handler); 92extern void set_intr_stub(enum exception_code code, void *handler);
93extern void set_jtag_stub(enum exception_code code, void *handler);
94 93
95struct pt_regs; 94struct pt_regs;
96 95
@@ -102,7 +101,6 @@ extern asmlinkage void dtlb_aerror(void);
102extern asmlinkage void raw_bus_error(void); 101extern asmlinkage void raw_bus_error(void);
103extern asmlinkage void double_fault(void); 102extern asmlinkage void double_fault(void);
104extern asmlinkage int system_call(struct pt_regs *); 103extern asmlinkage int system_call(struct pt_regs *);
105extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
106extern asmlinkage void nmi(struct pt_regs *, enum exception_code); 104extern asmlinkage void nmi(struct pt_regs *, enum exception_code);
107extern asmlinkage void uninitialised_exception(struct pt_regs *, 105extern asmlinkage void uninitialised_exception(struct pt_regs *,
108 enum exception_code); 106 enum exception_code);
@@ -116,6 +114,8 @@ extern void die(const char *, struct pt_regs *, enum exception_code)
116 114
117extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code); 115extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code);
118 116
117#define NUM2EXCEP_IRQ_LEVEL(num) (EXCEP_IRQ_LEVEL0 + (num) * 8)
118
119#endif /* __ASSEMBLY__ */ 119#endif /* __ASSEMBLY__ */
120 120
121#endif /* _ASM_EXCEPTIONS_H */ 121#endif /* _ASM_EXCEPTIONS_H */
diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h
index 64a2b83a7a6a..b7625de8eade 100644
--- a/arch/mn10300/include/asm/fpu.h
+++ b/arch/mn10300/include/asm/fpu.h
@@ -12,74 +12,125 @@
12#ifndef _ASM_FPU_H 12#ifndef _ASM_FPU_H
13#define _ASM_FPU_H 13#define _ASM_FPU_H
14 14
15#include <asm/processor.h> 15#ifndef __ASSEMBLY__
16
17#include <linux/sched.h>
18#include <asm/exceptions.h>
16#include <asm/sigcontext.h> 19#include <asm/sigcontext.h>
17#include <asm/user.h>
18 20
19#ifdef __KERNEL__ 21#ifdef __KERNEL__
20 22
21/* the task that owns the FPU state */ 23extern asmlinkage void fpu_disabled(void);
24
25#ifdef CONFIG_FPU
26
27#ifdef CONFIG_LAZY_SAVE_FPU
28/* the task that currently owns the FPU state */
22extern struct task_struct *fpu_state_owner; 29extern struct task_struct *fpu_state_owner;
30#endif
23 31
24#define set_using_fpu(tsk) \ 32#if (THREAD_USING_FPU & ~0xff)
25do { \ 33#error THREAD_USING_FPU must be smaller than 0x100.
26 (tsk)->thread.fpu_flags |= THREAD_USING_FPU; \ 34#endif
27} while (0)
28 35
29#define clear_using_fpu(tsk) \ 36static inline void set_using_fpu(struct task_struct *tsk)
30do { \ 37{
31 (tsk)->thread.fpu_flags &= ~THREAD_USING_FPU; \ 38 asm volatile(
32} while (0) 39 "bset %0,(0,%1)"
40 :
41 : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
42 : "memory", "cc");
43}
33 44
34#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU) 45static inline void clear_using_fpu(struct task_struct *tsk)
46{
47 asm volatile(
48 "bclr %0,(0,%1)"
49 :
50 : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
51 : "memory", "cc");
52}
35 53
36#define unlazy_fpu(tsk) \ 54#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
37do { \
38 preempt_disable(); \
39 if (fpu_state_owner == (tsk)) \
40 fpu_save(&tsk->thread.fpu_state); \
41 preempt_enable(); \
42} while (0)
43
44#define exit_fpu() \
45do { \
46 struct task_struct *__tsk = current; \
47 preempt_disable(); \
48 if (fpu_state_owner == __tsk) \
49 fpu_state_owner = NULL; \
50 preempt_enable(); \
51} while (0)
52
53#define flush_fpu() \
54do { \
55 struct task_struct *__tsk = current; \
56 preempt_disable(); \
57 if (fpu_state_owner == __tsk) { \
58 fpu_state_owner = NULL; \
59 __tsk->thread.uregs->epsw &= ~EPSW_FE; \
60 } \
61 preempt_enable(); \
62 clear_using_fpu(__tsk); \
63} while (0)
64 55
65extern asmlinkage void fpu_init_state(void);
66extern asmlinkage void fpu_kill_state(struct task_struct *); 56extern asmlinkage void fpu_kill_state(struct task_struct *);
67extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code);
68extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); 57extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
69 58extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
70#ifdef CONFIG_FPU 59extern asmlinkage void fpu_init_state(void);
71extern asmlinkage void fpu_save(struct fpu_state_struct *); 60extern asmlinkage void fpu_save(struct fpu_state_struct *);
72extern asmlinkage void fpu_restore(struct fpu_state_struct *);
73#else
74#define fpu_save(a)
75#define fpu_restore(a)
76#endif /* CONFIG_FPU */
77
78/*
79 * signal frame handlers
80 */
81extern int fpu_setup_sigcontext(struct fpucontext *buf); 61extern int fpu_setup_sigcontext(struct fpucontext *buf);
82extern int fpu_restore_sigcontext(struct fpucontext *buf); 62extern int fpu_restore_sigcontext(struct fpucontext *buf);
83 63
64static inline void unlazy_fpu(struct task_struct *tsk)
65{
66 preempt_disable();
67#ifndef CONFIG_LAZY_SAVE_FPU
68 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
69 fpu_save(&tsk->thread.fpu_state);
70 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
71 tsk->thread.uregs->epsw &= ~EPSW_FE;
72 }
73#else
74 if (fpu_state_owner == tsk)
75 fpu_save(&tsk->thread.fpu_state);
76#endif
77 preempt_enable();
78}
79
80static inline void exit_fpu(void)
81{
82#ifdef CONFIG_LAZY_SAVE_FPU
83 struct task_struct *tsk = current;
84
85 preempt_disable();
86 if (fpu_state_owner == tsk)
87 fpu_state_owner = NULL;
88 preempt_enable();
89#endif
90}
91
92static inline void flush_fpu(void)
93{
94 struct task_struct *tsk = current;
95
96 preempt_disable();
97#ifndef CONFIG_LAZY_SAVE_FPU
98 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
99 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
100 tsk->thread.uregs->epsw &= ~EPSW_FE;
101 }
102#else
103 if (fpu_state_owner == tsk) {
104 fpu_state_owner = NULL;
105 tsk->thread.uregs->epsw &= ~EPSW_FE;
106 }
107#endif
108 preempt_enable();
109 clear_using_fpu(tsk);
110}
111
112#else /* CONFIG_FPU */
113
114extern asmlinkage
115void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
116#define fpu_invalid_op unexpected_fpu_exception
117#define fpu_exception unexpected_fpu_exception
118
119struct task_struct;
120struct fpu_state_struct;
121static inline bool is_using_fpu(struct task_struct *tsk) { return false; }
122static inline void set_using_fpu(struct task_struct *tsk) {}
123static inline void clear_using_fpu(struct task_struct *tsk) {}
124static inline void fpu_init_state(void) {}
125static inline void fpu_save(struct fpu_state_struct *s) {}
126static inline void fpu_kill_state(struct task_struct *tsk) {}
127static inline void unlazy_fpu(struct task_struct *tsk) {}
128static inline void exit_fpu(void) {}
129static inline void flush_fpu(void) {}
130static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
131static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
132#endif /* CONFIG_FPU */
133
84#endif /* __KERNEL__ */ 134#endif /* __KERNEL__ */
135#endif /* !__ASSEMBLY__ */
85#endif /* _ASM_FPU_H */ 136#endif /* _ASM_FPU_H */
diff --git a/arch/mn10300/include/asm/frame.inc b/arch/mn10300/include/asm/frame.inc
index 5b1949bdf039..2ee58e3eb6b3 100644
--- a/arch/mn10300/include/asm/frame.inc
+++ b/arch/mn10300/include/asm/frame.inc
@@ -18,6 +18,7 @@
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#include <asm/thread_info.h>
21 22
22#define pi break 23#define pi break
23 24
@@ -37,11 +38,15 @@
37 movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp) 38 movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
38 mov sp,fp # FRAME pointer in A3 39 mov sp,fp # FRAME pointer in A3
39 add -12,sp # allow for calls to be made 40 add -12,sp # allow for calls to be made
40 mov (__frame),a1
41 mov a1,(REG_NEXT,fp)
42 mov fp,(__frame)
43 41
44 and ~EPSW_FE,epsw # disable the FPU inside the kernel 42 # push the exception frame onto the front of the list
43 GET_THREAD_INFO a1
44 mov (TI_frame,a1),a0
45 mov a0,(REG_NEXT,fp)
46 mov fp,(TI_frame,a1)
47
48 # disable the FPU inside the kernel
49 and ~EPSW_FE,epsw
45 50
46 # we may be holding current in E2 51 # we may be holding current in E2
47#ifdef CONFIG_MN10300_CURRENT_IN_E2 52#ifdef CONFIG_MN10300_CURRENT_IN_E2
@@ -57,10 +62,11 @@
57.macro RESTORE_ALL 62.macro RESTORE_ALL
58 # peel back the stack to the calling frame 63 # peel back the stack to the calling frame
59 # - this permits execve() to discard extra frames due to kernel syscalls 64 # - this permits execve() to discard extra frames due to kernel syscalls
60 mov (__frame),fp 65 GET_THREAD_INFO a0
66 mov (TI_frame,a0),fp
61 mov fp,sp 67 mov fp,sp
62 mov (REG_NEXT,fp),d0 # userspace has regs->next == 0 68 mov (REG_NEXT,fp),d0
63 mov d0,(__frame) 69 mov d0,(TI_frame,a0) # userspace has regs->next == 0
64 70
65#ifndef CONFIG_MN10300_USING_JTAG 71#ifndef CONFIG_MN10300_USING_JTAG
66 mov (REG_EPSW,fp),d0 72 mov (REG_EPSW,fp),d0
diff --git a/arch/mn10300/include/asm/gdb-stub.h b/arch/mn10300/include/asm/gdb-stub.h
index 41ed26763964..f5495ad82b77 100644
--- a/arch/mn10300/include/asm/gdb-stub.h
+++ b/arch/mn10300/include/asm/gdb-stub.h
@@ -110,7 +110,7 @@ extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code);
110extern asmlinkage void __gdbstub_bug_trap(void); 110extern asmlinkage void __gdbstub_bug_trap(void);
111extern asmlinkage void __gdbstub_pause(void); 111extern asmlinkage void __gdbstub_pause(void);
112 112
113#ifndef CONFIG_MN10300_CACHE_DISABLED 113#ifdef CONFIG_MN10300_CACHE_ENABLED
114extern asmlinkage void gdbstub_purge_cache(void); 114extern asmlinkage void gdbstub_purge_cache(void);
115#else 115#else
116#define gdbstub_purge_cache() do {} while (0) 116#define gdbstub_purge_cache() do {} while (0)
diff --git a/arch/mn10300/include/asm/hardirq.h b/arch/mn10300/include/asm/hardirq.h
index 54d950117674..0000d650b55f 100644
--- a/arch/mn10300/include/asm/hardirq.h
+++ b/arch/mn10300/include/asm/hardirq.h
@@ -19,9 +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 */
20typedef struct { 20typedef struct {
21 unsigned int __softirq_pending; 21 unsigned int __softirq_pending;
22 unsigned long idle_timestamp; 22#ifdef CONFIG_MN10300_WD_TIMER
23 unsigned int __nmi_count; /* arch dependent */ 23 unsigned int __nmi_count; /* arch dependent */
24 unsigned int __irq_count; /* arch dependent */ 24 unsigned int __irq_count; /* arch dependent */
25#endif
25} ____cacheline_aligned irq_cpustat_t; 26} ____cacheline_aligned irq_cpustat_t;
26 27
27#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/highmem.h b/arch/mn10300/include/asm/highmem.h
index e2155e686451..bfe2d88604d9 100644
--- a/arch/mn10300/include/asm/highmem.h
+++ b/arch/mn10300/include/asm/highmem.h
@@ -87,7 +87,7 @@ static inline unsigned long __kmap_atomic(struct page *page)
87 BUG(); 87 BUG();
88#endif 88#endif
89 set_pte(kmap_pte - idx, mk_pte(page, kmap_prot)); 89 set_pte(kmap_pte - idx, mk_pte(page, kmap_prot));
90 __flush_tlb_one(vaddr); 90 local_flush_tlb_one(vaddr);
91 91
92 return vaddr; 92 return vaddr;
93} 93}
@@ -116,7 +116,7 @@ static inline void __kunmap_atomic(unsigned long vaddr)
116 * this pte without first remap it 116 * this pte without first remap it
117 */ 117 */
118 pte_clear(kmap_pte - idx); 118 pte_clear(kmap_pte - idx);
119 __flush_tlb_one(vaddr); 119 local_flush_tlb_one(vaddr);
120 } 120 }
121#endif 121#endif
122 122
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>
30do { \
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__
64extern void set_intr_level(int irq, u16 level); 62extern void set_intr_level(int irq, u16 level);
65extern void set_intr_postackable(int irq); 63extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
64extern void mn10300_intc_clear(unsigned int irq);
65extern void mn10300_intc_set(unsigned int irq);
66extern void mn10300_intc_enable(unsigned int irq);
67extern void mn10300_intc_disable(unsigned int irq);
68extern 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/io.h b/arch/mn10300/include/asm/io.h
index c1a4119e6497..787255da744e 100644
--- a/arch/mn10300/include/asm/io.h
+++ b/arch/mn10300/include/asm/io.h
@@ -206,6 +206,19 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
206#define iowrite32_rep(p, src, count) \ 206#define iowrite32_rep(p, src, count) \
207 outsl((unsigned long) (p), (src), (count)) 207 outsl((unsigned long) (p), (src), (count))
208 208
209#define readsb(p, dst, count) \
210 insb((unsigned long) (p), (dst), (count))
211#define readsw(p, dst, count) \
212 insw((unsigned long) (p), (dst), (count))
213#define readsl(p, dst, count) \
214 insl((unsigned long) (p), (dst), (count))
215
216#define writesb(p, src, count) \
217 outsb((unsigned long) (p), (src), (count))
218#define writesw(p, src, count) \
219 outsw((unsigned long) (p), (src), (count))
220#define writesl(p, src, count) \
221 outsl((unsigned long) (p), (src), (count))
209 222
210#define IO_SPACE_LIMIT 0xffffffff 223#define IO_SPACE_LIMIT 0xffffffff
211 224
diff --git a/arch/mn10300/include/asm/irq.h b/arch/mn10300/include/asm/irq.h
index 25c045d16d1c..1a73fb3f60c6 100644
--- a/arch/mn10300/include/asm/irq.h
+++ b/arch/mn10300/include/asm/irq.h
@@ -21,8 +21,16 @@
21/* this number is used when no interrupt has been assigned */ 21/* this number is used when no interrupt has been assigned */
22#define NO_IRQ INT_MAX 22#define NO_IRQ INT_MAX
23 23
24/* hardware irq numbers */ 24/*
25#define NR_IRQS GxICR_NUM_IRQS 25 * hardware irq numbers
26 * - the ASB2364 has an FPGA with an IRQ multiplexer on it
27 */
28#ifdef CONFIG_MN10300_UNIT_ASB2364
29#include <unit/irq.h>
30#else
31#define NR_CPU_IRQS GxICR_NUM_IRQS
32#define NR_IRQS NR_CPU_IRQS
33#endif
26 34
27/* external hardware irq numbers */ 35/* external hardware irq numbers */
28#define NR_XIRQS GxICR_NUM_XIRQS 36#define NR_XIRQS GxICR_NUM_XIRQS
diff --git a/arch/mn10300/include/asm/irq_regs.h b/arch/mn10300/include/asm/irq_regs.h
index a848cd232eb4..97d0cb5af807 100644
--- a/arch/mn10300/include/asm/irq_regs.h
+++ b/arch/mn10300/include/asm/irq_regs.h
@@ -18,7 +18,11 @@
18#define ARCH_HAS_OWN_IRQ_REGS 18#define ARCH_HAS_OWN_IRQ_REGS
19 19
20#ifndef __ASSEMBLY__ 20#ifndef __ASSEMBLY__
21#define get_irq_regs() (__frame) 21static inline __attribute__((const))
22struct pt_regs *get_irq_regs(void)
23{
24 return current_frame();
25}
22#endif 26#endif
23 27
24#endif /* _ASM_IRQ_REGS_H */ 28#endif /* _ASM_IRQ_REGS_H */
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h
index 5e529a117cb2..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
@@ -23,11 +26,7 @@
23 * - level 6 - timer interrupt 26 * - level 6 - timer interrupt
24 * - "enabled": run in IM7 27 * - "enabled": run in IM7
25 */ 28 */
26#ifdef CONFIG_MN10300_TTYSM 29#define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
27#define MN10300_CLI_LEVEL EPSW_IM_2
28#else
29#define MN10300_CLI_LEVEL EPSW_IM_1
30#endif
31 30
32#ifndef __ASSEMBLY__ 31#ifndef __ASSEMBLY__
33 32
@@ -64,11 +63,12 @@ static inline unsigned long arch_local_irq_save(void)
64/* 63/*
65 * we make sure arch_irq_enable() doesn't cause priority inversion 64 * we make sure arch_irq_enable() doesn't cause priority inversion
66 */ 65 */
67extern unsigned long __mn10300_irq_enabled_epsw; 66extern unsigned long __mn10300_irq_enabled_epsw[];
68 67
69static inline void arch_local_irq_enable(void) 68static inline void arch_local_irq_enable(void)
70{ 69{
71 unsigned long tmp; 70 unsigned long tmp;
71 int cpu = raw_smp_processor_id();
72 72
73 asm volatile( 73 asm volatile(
74 " mov epsw,%0 \n" 74 " mov epsw,%0 \n"
@@ -76,8 +76,8 @@ static inline void arch_local_irq_enable(void)
76 " or %2,%0 \n" 76 " or %2,%0 \n"
77 " mov %0,epsw \n" 77 " mov %0,epsw \n"
78 : "=&d"(tmp) 78 : "=&d"(tmp)
79 : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw) 79 : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
80 : "memory"); 80 : "memory", "cc");
81} 81}
82 82
83static inline void arch_local_irq_restore(unsigned long flags) 83static inline void arch_local_irq_restore(unsigned long flags)
@@ -94,7 +94,7 @@ static inline void arch_local_irq_restore(unsigned long flags)
94 94
95static inline bool arch_irqs_disabled_flags(unsigned long flags) 95static inline bool arch_irqs_disabled_flags(unsigned long flags)
96{ 96{
97 return (flags & EPSW_IM) <= MN10300_CLI_LEVEL; 97 return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
98} 98}
99 99
100static inline bool arch_irqs_disabled(void) 100static inline bool arch_irqs_disabled(void)
@@ -109,6 +109,9 @@ static inline bool arch_irqs_disabled(void)
109 */ 109 */
110static inline void arch_safe_halt(void) 110static inline void arch_safe_halt(void)
111{ 111{
112#ifdef CONFIG_SMP
113 arch_local_irq_enable();
114#else
112 asm volatile( 115 asm volatile(
113 " or %0,epsw \n" 116 " or %0,epsw \n"
114 " nop \n" 117 " nop \n"
@@ -117,7 +120,97 @@ static inline void arch_safe_halt(void)
117 : 120 :
118 : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP) 121 : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
119 : "cc"); 122 : "cc");
123#endif
120} 124}
121 125
126#define __sleep_cpu() \
127do { \
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
138static inline void arch_local_cli(void)
139{
140 asm volatile(
141 " and %0,epsw \n"
142 " nop \n"
143 " nop \n"
144 " nop \n"
145 :
146 : "i"(~EPSW_IE)
147 : "memory"
148 );
149}
150
151static inline unsigned long arch_local_cli_save(void)
152{
153 unsigned long flags = arch_local_save_flags();
154 arch_local_cli();
155 return flags;
156}
157
158static inline void arch_local_sti(void)
159{
160 asm volatile(
161 " or %0,epsw \n"
162 :
163 : "i"(EPSW_IE)
164 : "memory");
165}
166
167static inline void arch_local_change_intr_mask_level(unsigned long level)
168{
169 asm volatile(
170 " and %0,epsw \n"
171 " or %1,epsw \n"
172 :
173 : "i"(~EPSW_IM), "i"(EPSW_IE | level)
174 : "cc", "memory");
175}
176
177#else /* !__ASSEMBLY__ */
178
179#define LOCAL_SAVE_FLAGS(reg) \
180 mov epsw,reg
181
182#define LOCAL_IRQ_DISABLE \
183 and ~EPSW_IM,epsw; \
184 or EPSW_IE|MN10300_CLI_LEVEL,epsw; \
185 nop; \
186 nop; \
187 nop
188
189#define LOCAL_IRQ_ENABLE \
190 or EPSW_IE|EPSW_IM_7,epsw
191
192#define LOCAL_IRQ_RESTORE(reg) \
193 mov reg,epsw
194
195#define LOCAL_CLI_SAVE(reg) \
196 mov epsw,reg; \
197 and ~EPSW_IE,epsw; \
198 nop; \
199 nop; \
200 nop
201
202#define LOCAL_CLI \
203 and ~EPSW_IE,epsw; \
204 nop; \
205 nop; \
206 nop
207
208#define LOCAL_STI \
209 or EPSW_IE,epsw
210
211#define LOCAL_CHANGE_INTR_MASK_LEVEL(level) \
212 and ~EPSW_IM,epsw; \
213 or EPSW_IE|(level),epsw
214
122#endif /* __ASSEMBLY__ */ 215#endif /* __ASSEMBLY__ */
123#endif /* _ASM_IRQFLAGS_H */ 216#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h
index cb294c244de3..c8f6c82672ad 100644
--- a/arch/mn10300/include/asm/mmu_context.h
+++ b/arch/mn10300/include/asm/mmu_context.h
@@ -27,28 +27,38 @@
27#include <asm/tlbflush.h> 27#include <asm/tlbflush.h>
28#include <asm-generic/mm_hooks.h> 28#include <asm-generic/mm_hooks.h>
29 29
30#define MMU_CONTEXT_TLBPID_NR 256
30#define MMU_CONTEXT_TLBPID_MASK 0x000000ffUL 31#define MMU_CONTEXT_TLBPID_MASK 0x000000ffUL
31#define MMU_CONTEXT_VERSION_MASK 0xffffff00UL 32#define MMU_CONTEXT_VERSION_MASK 0xffffff00UL
32#define MMU_CONTEXT_FIRST_VERSION 0x00000100UL 33#define MMU_CONTEXT_FIRST_VERSION 0x00000100UL
33#define MMU_NO_CONTEXT 0x00000000UL 34#define MMU_NO_CONTEXT 0x00000000UL
34 35#define MMU_CONTEXT_TLBPID_LOCK_NR 0
35extern unsigned long mmu_context_cache[NR_CPUS];
36#define mm_context(mm) (mm->context.tlbpid[smp_processor_id()])
37 36
38#define enter_lazy_tlb(mm, tsk) do {} while (0) 37#define enter_lazy_tlb(mm, tsk) do {} while (0)
39 38
39static inline void cpu_ran_vm(int cpu, struct mm_struct *mm)
40{
40#ifdef CONFIG_SMP 41#ifdef CONFIG_SMP
41#define cpu_ran_vm(cpu, mm) \ 42 cpumask_set_cpu(cpu, mm_cpumask(mm));
42 cpumask_set_cpu((cpu), mm_cpumask(mm)) 43#endif
43#define cpu_maybe_ran_vm(cpu, mm) \ 44}
44 cpumask_test_and_set_cpu((cpu), mm_cpumask(mm)) 45
46static inline bool cpu_maybe_ran_vm(int cpu, struct mm_struct *mm)
47{
48#ifdef CONFIG_SMP
49 return cpumask_test_and_set_cpu(cpu, mm_cpumask(mm));
45#else 50#else
46#define cpu_ran_vm(cpu, mm) do {} while (0) 51 return true;
47#define cpu_maybe_ran_vm(cpu, mm) true 52#endif
48#endif /* CONFIG_SMP */ 53}
49 54
50/* 55#ifdef CONFIG_MN10300_TLB_USE_PIDR
51 * allocate an MMU context 56extern unsigned long mmu_context_cache[NR_CPUS];
57#define mm_context(mm) (mm->context.tlbpid[smp_processor_id()])
58
59/**
60 * allocate_mmu_context - Allocate storage for the arch-specific MMU data
61 * @mm: The userspace VM context being set up
52 */ 62 */
53static inline unsigned long allocate_mmu_context(struct mm_struct *mm) 63static inline unsigned long allocate_mmu_context(struct mm_struct *mm)
54{ 64{
@@ -58,7 +68,7 @@ static inline unsigned long allocate_mmu_context(struct mm_struct *mm)
58 if (!(mc & MMU_CONTEXT_TLBPID_MASK)) { 68 if (!(mc & MMU_CONTEXT_TLBPID_MASK)) {
59 /* we exhausted the TLB PIDs of this version on this CPU, so we 69 /* we exhausted the TLB PIDs of this version on this CPU, so we
60 * flush this CPU's TLB in its entirety and start new cycle */ 70 * flush this CPU's TLB in its entirety and start new cycle */
61 flush_tlb_all(); 71 local_flush_tlb_all();
62 72
63 /* fix the TLB version if needed (we avoid version #0 so as to 73 /* fix the TLB version if needed (we avoid version #0 so as to
64 * distingush MMU_NO_CONTEXT) */ 74 * distingush MMU_NO_CONTEXT) */
@@ -101,22 +111,34 @@ static inline int init_new_context(struct task_struct *tsk,
101} 111}
102 112
103/* 113/*
104 * destroy context related info for an mm_struct that is about to be put to
105 * rest
106 */
107#define destroy_context(mm) do { } while (0)
108
109/*
110 * after we have set current->mm to a new value, this activates the context for 114 * after we have set current->mm to a new value, this activates the context for
111 * the new mm so we see the new mappings. 115 * the new mm so we see the new mappings.
112 */ 116 */
113static inline void activate_context(struct mm_struct *mm, int cpu) 117static inline void activate_context(struct mm_struct *mm)
114{ 118{
115 PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK; 119 PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK;
116} 120}
121#else /* CONFIG_MN10300_TLB_USE_PIDR */
117 122
118/* 123#define init_new_context(tsk, mm) (0)
119 * change between virtual memory sets 124#define activate_context(mm) local_flush_tlb()
125
126#endif /* CONFIG_MN10300_TLB_USE_PIDR */
127
128/**
129 * destroy_context - Destroy mm context information
130 * @mm: The MM being destroyed.
131 *
132 * Destroy context related info for an mm_struct that is about to be put to
133 * rest
134 */
135#define destroy_context(mm) do {} while (0)
136
137/**
138 * switch_mm - Change between userspace virtual memory contexts
139 * @prev: The outgoing MM context.
140 * @next: The incoming MM context.
141 * @tsk: The incoming task.
120 */ 142 */
121static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 143static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
122 struct task_struct *tsk) 144 struct task_struct *tsk)
@@ -124,11 +146,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
124 int cpu = smp_processor_id(); 146 int cpu = smp_processor_id();
125 147
126 if (prev != next) { 148 if (prev != next) {
149#ifdef CONFIG_SMP
150 per_cpu(cpu_tlbstate, cpu).active_mm = next;
151#endif
127 cpu_ran_vm(cpu, next); 152 cpu_ran_vm(cpu, next);
128 activate_context(next, cpu);
129 PTBR = (unsigned long) next->pgd; 153 PTBR = (unsigned long) next->pgd;
130 } else if (!cpu_maybe_ran_vm(cpu, next)) { 154 activate_context(next);
131 activate_context(next, cpu);
132 } 155 }
133} 156}
134 157
diff --git a/arch/mn10300/include/asm/pgalloc.h b/arch/mn10300/include/asm/pgalloc.h
index a19f11327cd8..146bacf193ea 100644
--- a/arch/mn10300/include/asm/pgalloc.h
+++ b/arch/mn10300/include/asm/pgalloc.h
@@ -11,7 +11,6 @@
11#ifndef _ASM_PGALLOC_H 11#ifndef _ASM_PGALLOC_H
12#define _ASM_PGALLOC_H 12#define _ASM_PGALLOC_H
13 13
14#include <asm/processor.h>
15#include <asm/page.h> 14#include <asm/page.h>
16#include <linux/threads.h> 15#include <linux/threads.h>
17#include <linux/mm.h> /* for struct page */ 16#include <linux/mm.h> /* for struct page */
diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h
index b049a8bd1577..a1e894b5f65b 100644
--- a/arch/mn10300/include/asm/pgtable.h
+++ b/arch/mn10300/include/asm/pgtable.h
@@ -90,46 +90,58 @@ 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__
98extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; 104extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE];
99#endif 105#endif
100 106
101/* IPTEL/DPTEL bit assignments */ 107/* IPTEL2/DPTEL2 bit assignments */
102#define _PAGE_BIT_VALID xPTEL_V_BIT 108#define _PAGE_BIT_VALID xPTEL2_V_BIT
103#define _PAGE_BIT_ACCESSED xPTEL_UNUSED1_BIT /* mustn't be loaded into IPTEL/DPTEL */ 109#define _PAGE_BIT_CACHE xPTEL2_C_BIT
104#define _PAGE_BIT_NX xPTEL_UNUSED2_BIT /* mustn't be loaded into IPTEL/DPTEL */ 110#define _PAGE_BIT_PRESENT xPTEL2_PV_BIT
105#define _PAGE_BIT_CACHE xPTEL_C_BIT 111#define _PAGE_BIT_DIRTY xPTEL2_D_BIT
106#define _PAGE_BIT_PRESENT xPTEL_PV_BIT 112#define _PAGE_BIT_GLOBAL xPTEL2_G_BIT
107#define _PAGE_BIT_DIRTY xPTEL_D_BIT 113#define _PAGE_BIT_ACCESSED xPTEL2_UNUSED1_BIT /* mustn't be loaded into IPTEL2/DPTEL2 */
108#define _PAGE_BIT_GLOBAL xPTEL_G_BIT 114
109 115#define _PAGE_VALID xPTEL2_V
110#define _PAGE_VALID xPTEL_V 116#define _PAGE_CACHE xPTEL2_C
111#define _PAGE_ACCESSED xPTEL_UNUSED1 117#define _PAGE_PRESENT xPTEL2_PV
112#define _PAGE_NX xPTEL_UNUSED2 /* no-execute bit */ 118#define _PAGE_DIRTY xPTEL2_D
113#define _PAGE_CACHE xPTEL_C 119#define _PAGE_PROT xPTEL2_PR
114#define _PAGE_PRESENT xPTEL_PV 120#define _PAGE_PROT_RKNU xPTEL2_PR_ROK
115#define _PAGE_DIRTY xPTEL_D 121#define _PAGE_PROT_WKNU xPTEL2_PR_RWK
116#define _PAGE_PROT xPTEL_PR 122#define _PAGE_PROT_RKRU xPTEL2_PR_ROK_ROU
117#define _PAGE_PROT_RKNU xPTEL_PR_ROK 123#define _PAGE_PROT_WKRU xPTEL2_PR_RWK_ROU
118#define _PAGE_PROT_WKNU xPTEL_PR_RWK 124#define _PAGE_PROT_WKWU xPTEL2_PR_RWK_RWU
119#define _PAGE_PROT_RKRU xPTEL_PR_ROK_ROU 125#define _PAGE_GLOBAL xPTEL2_G
120#define _PAGE_PROT_WKRU xPTEL_PR_RWK_ROU 126#define _PAGE_PS_MASK xPTEL2_PS
121#define _PAGE_PROT_WKWU xPTEL_PR_RWK_RWU 127#define _PAGE_PS_4Kb xPTEL2_PS_4Kb
122#define _PAGE_GLOBAL xPTEL_G 128#define _PAGE_PS_128Kb xPTEL2_PS_128Kb
123#define _PAGE_PSE xPTEL_PS_4Mb /* 4MB page */ 129#define _PAGE_PS_1Kb xPTEL2_PS_1Kb
124 130#define _PAGE_PS_4Mb xPTEL2_PS_4Mb
125#define _PAGE_FILE xPTEL_UNUSED1_BIT /* set:pagecache unset:swap */ 131#define _PAGE_PSE xPTEL2_PS_4Mb /* 4MB page */
126 132#define _PAGE_CACHE_WT xPTEL2_CWT
127#define __PAGE_PROT_UWAUX 0x040 133#define _PAGE_ACCESSED xPTEL2_UNUSED1
128#define __PAGE_PROT_USER 0x080 134#define _PAGE_NX 0 /* no-execute bit */
129#define __PAGE_PROT_WRITE 0x100 135
136/* If _PAGE_VALID is clear, we use these: */
137#define _PAGE_FILE xPTEL2_C /* set:pagecache unset:swap */
138#define _PAGE_PROTNONE 0x000 /* If not present */
139
140#define __PAGE_PROT_UWAUX 0x010
141#define __PAGE_PROT_USER 0x020
142#define __PAGE_PROT_WRITE 0x040
130 143
131#define _PAGE_PRESENTV (_PAGE_PRESENT|_PAGE_VALID) 144#define _PAGE_PRESENTV (_PAGE_PRESENT|_PAGE_VALID)
132#define _PAGE_PROTNONE 0x000 /* If not present */
133 145
134#ifndef __ASSEMBLY__ 146#ifndef __ASSEMBLY__
135 147
@@ -170,6 +182,9 @@ extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE];
170#define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE) 182#define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE)
171#define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC) 183#define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC)
172 184
185#define __PAGE_USERIO (__PAGE_KERNEL_BASE | _PAGE_PROT_WKWU | _PAGE_NX)
186#define PAGE_USERIO __pgprot(__PAGE_USERIO)
187
173/* 188/*
174 * Whilst the MN10300 can do page protection for execute (given separate data 189 * Whilst the MN10300 can do page protection for execute (given separate data
175 * and insn TLBs), we are not supporting it at the moment. Write permission, 190 * and insn TLBs), we are not supporting it at the moment. Write permission,
@@ -323,11 +338,7 @@ static inline int pte_exec_kernel(pte_t pte)
323 return 1; 338 return 1;
324} 339}
325 340
326/* 341#define PTE_FILE_MAX_BITS 30
327 * Bits 0 and 1 are taken, split up the 29 bits of offset
328 * into this range:
329 */
330#define PTE_FILE_MAX_BITS 29
331 342
332#define pte_to_pgoff(pte) (pte_val(pte) >> 2) 343#define pte_to_pgoff(pte) (pte_val(pte) >> 2)
333#define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) 344#define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE)
@@ -373,8 +384,13 @@ static inline void ptep_mkdirty(pte_t *ptep)
373 * Macro to mark a page protection value as "uncacheable". On processors which 384 * Macro to mark a page protection value as "uncacheable". On processors which
374 * do not support it, this is a no-op. 385 * do not support it, this is a no-op.
375 */ 386 */
376#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE) 387#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHE)
377 388
389/*
390 * Macro to mark a page protection value as "Write-Through".
391 * On processors which do not support it, this is a no-op.
392 */
393#define pgprot_through(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE_WT)
378 394
379/* 395/*
380 * Conversion functions: convert a page and protection to a page entry, 396 * 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 f7d4b0d285e8..4c1b5cc14c19 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -13,10 +13,13 @@
13#ifndef _ASM_PROCESSOR_H 13#ifndef _ASM_PROCESSOR_H
14#define _ASM_PROCESSOR_H 14#define _ASM_PROCESSOR_H
15 15
16#include <linux/threads.h>
17#include <linux/thread_info.h>
16#include <asm/page.h> 18#include <asm/page.h>
17#include <asm/ptrace.h> 19#include <asm/ptrace.h>
18#include <asm/cpu-regs.h> 20#include <asm/cpu-regs.h>
19#include <linux/threads.h> 21#include <asm/uaccess.h>
22#include <asm/current.h>
20 23
21/* Forward declaration, a strange C thing */ 24/* Forward declaration, a strange C thing */
22struct task_struct; 25struct task_struct;
@@ -33,6 +36,8 @@ struct mm_struct;
33 __pc; \ 36 __pc; \
34}) 37})
35 38
39extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size);
40
36extern void show_registers(struct pt_regs *regs); 41extern void show_registers(struct pt_regs *regs);
37 42
38/* 43/*
@@ -43,17 +48,22 @@ extern void show_registers(struct pt_regs *regs);
43 48
44struct mn10300_cpuinfo { 49struct mn10300_cpuinfo {
45 int type; 50 int type;
46 unsigned long loops_per_sec; 51 unsigned long loops_per_jiffy;
47 char hard_math; 52 char hard_math;
48 unsigned long *pgd_quick;
49 unsigned long *pte_quick;
50 unsigned long pgtable_cache_sz;
51}; 53};
52 54
53extern struct mn10300_cpuinfo boot_cpu_data; 55extern struct mn10300_cpuinfo boot_cpu_data;
54 56
57#ifdef CONFIG_SMP
58#if CONFIG_NR_CPUS < 2 || CONFIG_NR_CPUS > 8
59# error Sorry, NR_CPUS should be 2 to 8
60#endif
61extern struct mn10300_cpuinfo cpu_data[];
62#define current_cpu_data cpu_data[smp_processor_id()]
63#else /* CONFIG_SMP */
55#define cpu_data &boot_cpu_data 64#define cpu_data &boot_cpu_data
56#define current_cpu_data boot_cpu_data 65#define current_cpu_data boot_cpu_data
66#endif /* CONFIG_SMP */
57 67
58extern void identify_cpu(struct mn10300_cpuinfo *); 68extern void identify_cpu(struct mn10300_cpuinfo *);
59extern void print_cpu_info(struct mn10300_cpuinfo *); 69extern void print_cpu_info(struct mn10300_cpuinfo *);
@@ -76,10 +86,6 @@ extern void dodgy_tsc(void);
76 */ 86 */
77#define TASK_UNMAPPED_BASE 0x30000000 87#define TASK_UNMAPPED_BASE 0x30000000
78 88
79typedef struct {
80 unsigned long seg;
81} mm_segment_t;
82
83struct fpu_state_struct { 89struct fpu_state_struct {
84 unsigned long fs[32]; /* fpu registers */ 90 unsigned long fs[32]; /* fpu registers */
85 unsigned long fpcr; /* fpu control register */ 91 unsigned long fpcr; /* fpu control register */
@@ -92,20 +98,19 @@ struct thread_struct {
92 unsigned long a3; /* kernel FP */ 98 unsigned long a3; /* kernel FP */
93 unsigned long wchan; 99 unsigned long wchan;
94 unsigned long usp; 100 unsigned long usp;
95 struct pt_regs *__frame;
96 unsigned long fpu_flags; 101 unsigned long fpu_flags;
97#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */ 102#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
103#define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */
98 struct fpu_state_struct fpu_state; 104 struct fpu_state_struct fpu_state;
99}; 105};
100 106
101#define INIT_THREAD \ 107#define INIT_THREAD \
102{ \ 108{ \
103 .uregs = init_uregs, \ 109 .uregs = init_uregs, \
104 .pc = 0, \ 110 .pc = 0, \
105 .sp = 0, \ 111 .sp = 0, \
106 .a3 = 0, \ 112 .a3 = 0, \
107 .wchan = 0, \ 113 .wchan = 0, \
108 .__frame = NULL, \
109} 114}
110 115
111#define INIT_MMAP \ 116#define INIT_MMAP \
@@ -117,13 +122,20 @@ struct thread_struct {
117 * - need to discard the frame stacked by the kernel thread invoking the execve 122 * - need to discard the frame stacked by the kernel thread invoking the execve
118 * syscall (see RESTORE_ALL macro) 123 * syscall (see RESTORE_ALL macro)
119 */ 124 */
120#define start_thread(regs, new_pc, new_sp) do { \ 125static inline void start_thread(struct pt_regs *regs,
121 set_fs(USER_DS); \ 126 unsigned long new_pc, unsigned long new_sp)
122 __frame = current->thread.uregs; \ 127{
123 __frame->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; \ 128 struct thread_info *ti = current_thread_info();
124 __frame->pc = new_pc; \ 129 struct pt_regs *frame0;
125 __frame->sp = new_sp; \ 130 set_fs(USER_DS);
126} while (0) 131
132 frame0 = thread_info_to_uregs(ti);
133 frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
134 frame0->pc = new_pc;
135 frame0->sp = new_sp;
136 ti->frame = frame0;
137}
138
127 139
128/* Free all resources held by a thread. */ 140/* Free all resources held by a thread. */
129extern void release_thread(struct task_struct *); 141extern void release_thread(struct task_struct *);
@@ -157,7 +169,7 @@ unsigned long get_wchan(struct task_struct *p);
157 169
158static inline void prefetch(const void *x) 170static inline void prefetch(const void *x)
159{ 171{
160#ifndef CONFIG_MN10300_CACHE_DISABLED 172#ifdef CONFIG_MN10300_CACHE_ENABLED
161#ifdef CONFIG_MN10300_PROC_MN103E010 173#ifdef CONFIG_MN10300_PROC_MN103E010
162 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); 174 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
163#else 175#else
@@ -168,7 +180,7 @@ static inline void prefetch(const void *x)
168 180
169static inline void prefetchw(const void *x) 181static inline void prefetchw(const void *x)
170{ 182{
171#ifndef CONFIG_MN10300_CACHE_DISABLED 183#ifdef CONFIG_MN10300_CACHE_ENABLED
172#ifdef CONFIG_MN10300_PROC_MN103E010 184#ifdef CONFIG_MN10300_PROC_MN103E010
173 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); 185 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
174#else 186#else
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
index 7c2e911052b6..b6961811d445 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,7 @@ 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
91extern struct pt_regs *__frame; /* current frame pointer */
92
93#if !defined(__ASSEMBLY__)
94struct task_struct;
95 88
96#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) 89#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
97#define instruction_pointer(regs) ((regs)->pc) 90#define instruction_pointer(regs) ((regs)->pc)
@@ -100,9 +93,7 @@ extern void show_regs(struct pt_regs *);
100 93
101#define arch_has_single_step() (1) 94#define arch_has_single_step() (1)
102 95
103#endif /* !__ASSEMBLY */
104
105#define profile_pc(regs) ((regs)->pc) 96#define profile_pc(regs) ((regs)->pc)
106 97
107#endif /* __KERNEL__ */ 98#endif /* __KERNEL__ */
108#endif /* _ASM_PTRACE_H */ 99#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
53extern unsigned int watchdog_alert_counter; 53extern unsigned int watchdog_alert_counter[];
54 54
55extern void watchdog_go(void); 55extern void watchdog_go(void);
56extern asmlinkage void watchdog_handler(void); 56extern 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
18extern void check_rtc_time(void);
19extern void __init calibrate_clock(void); 18extern void __init calibrate_clock(void);
20extern unsigned long __init get_initial_rtc_time(void);
21 19
22#else /* !CONFIG_MN10300_RTC */ 20#else /* !CONFIG_MN10300_RTC */
23 21
24static inline void check_rtc_time(void)
25{
26}
27
28static inline void calibrate_clock(void) 22static inline void calibrate_clock(void)
29{ 23{
30} 24}
31 25
32static 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
27typedef 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..a3930e43a958 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,85 @@
11#ifndef _ASM_SMP_H 21#ifndef _ASM_SMP_H
12#define _ASM_SMP_H 22#define _ASM_SMP_H
13 23
14#ifdef CONFIG_SMP 24#ifndef __ASSEMBLY__
15#error SMP not yet supported for MN10300 25#include <linux/threads.h>
26#include <linux/cpumask.h>
16#endif 27#endif
17 28
29#ifdef CONFIG_SMP
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)
18#endif 68#endif
69
70static inline int cpu_logical_map(int cpu)
71{
72 return cpu;
73}
74
75static inline int cpu_number_map(int cpu)
76{
77 return cpu;
78}
79
80
81extern cpumask_t cpu_boot_map;
82
83extern void smp_init_cpus(void);
84extern void smp_cache_interrupt(void);
85extern void send_IPI_allbutself(int irq);
86extern int smp_nmi_call_function(smp_call_func_t func, void *info, int wait);
87
88extern void arch_send_call_function_single_ipi(int cpu);
89extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
90
91#ifdef CONFIG_HOTPLUG_CPU
92extern int __cpu_disable(void);
93extern void __cpu_die(unsigned int cpu);
94#endif /* CONFIG_HOTPLUG_CPU */
95
96#endif /* __ASSEMBLY__ */
97#else /* CONFIG_SMP */
98#ifndef __ASSEMBLY__
99
100static inline void smp_init_cpus(void) {}
101
102#endif /* __ASSEMBLY__ */
103#endif /* CONFIG_SMP */
104
105#endif /* _ASM_SMP_H */
diff --git a/arch/mn10300/include/asm/smsc911x.h b/arch/mn10300/include/asm/smsc911x.h
new file mode 100644
index 000000000000..2fcd1080322b
--- /dev/null
+++ b/arch/mn10300/include/asm/smsc911x.h
@@ -0,0 +1 @@
#include <unit/smsc911x.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
28static 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
37static 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
54static 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
64static 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 */
116static 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
129static 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
142static 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
154static 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
166static 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
176static 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
8typedef struct arch_spinlock {
9 unsigned int slock;
10} arch_spinlock_t;
11
12#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
13
14typedef 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 9f7c7e17c01e..8ff3e5aaca41 100644
--- a/arch/mn10300/include/asm/system.h
+++ b/arch/mn10300/include/asm/system.h
@@ -12,12 +12,29 @@
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__
18 19
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/irqflags.h> 21#include <linux/irqflags.h>
22#include <asm/atomic.h>
23
24#if !defined(CONFIG_LAZY_SAVE_FPU)
25struct fpu_state_struct;
26extern asmlinkage void fpu_save(struct fpu_state_struct *);
27#define switch_fpu(prev, next) \
28 do { \
29 if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) { \
30 (prev)->thread.fpu_flags &= ~THREAD_HAS_FPU; \
31 (prev)->thread.uregs->epsw &= ~EPSW_FE; \
32 fpu_save(&(prev)->thread.fpu_state); \
33 } \
34 } while (0)
35#else
36#define switch_fpu(prev, next) do {} while (0)
37#endif
21 38
22struct task_struct; 39struct task_struct;
23struct thread_struct; 40struct thread_struct;
@@ -30,6 +47,7 @@ struct task_struct *__switch_to(struct thread_struct *prev,
30/* context switching is now performed out-of-line in switch_to.S */ 47/* context switching is now performed out-of-line in switch_to.S */
31#define switch_to(prev, next, last) \ 48#define switch_to(prev, next, last) \
32do { \ 49do { \
50 switch_fpu(prev, next); \
33 current->thread.wchan = (u_long) __builtin_return_address(0); \ 51 current->thread.wchan = (u_long) __builtin_return_address(0); \
34 (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \ 52 (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
35 mb(); \ 53 mb(); \
@@ -40,8 +58,6 @@ do { \
40 58
41#define nop() asm volatile ("nop") 59#define nop() asm volatile ("nop")
42 60
43#endif /* !__ASSEMBLY__ */
44
45/* 61/*
46 * Force strict CPU ordering. 62 * Force strict CPU ordering.
47 * 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
@@ -68,64 +84,19 @@ do { \
68#define smp_mb() mb() 84#define smp_mb() mb()
69#define smp_rmb() rmb() 85#define smp_rmb() rmb()
70#define smp_wmb() wmb() 86#define smp_wmb() wmb()
71#else 87#define set_mb(var, value) do { xchg(&var, value); } while (0)
88#else /* CONFIG_SMP */
72#define smp_mb() barrier() 89#define smp_mb() barrier()
73#define smp_rmb() barrier() 90#define smp_rmb() barrier()
74#define smp_wmb() barrier() 91#define smp_wmb() barrier()
75#endif
76
77#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
78#define set_wmb(var, value) do { var = value; wmb(); } while (0) 95#define set_wmb(var, value) do { var = value; wmb(); } while (0)
79 96
80#define read_barrier_depends() do {} while (0) 97#define read_barrier_depends() do {} while (0)
81#define smp_read_barrier_depends() do {} while (0) 98#define smp_read_barrier_depends() do {} while (0)
82 99
83/*****************************************************************************/
84/*
85 * MN10300 doesn't actually have an exchange instruction
86 */
87#ifndef __ASSEMBLY__
88
89struct __xchg_dummy { unsigned long a[100]; };
90#define __xg(x) ((struct __xchg_dummy *)(x))
91
92static inline
93unsigned long __xchg(volatile unsigned long *m, unsigned long val)
94{
95 unsigned long retval;
96 unsigned long flags;
97
98 local_irq_save(flags);
99 retval = *m;
100 *m = val;
101 local_irq_restore(flags);
102 return retval;
103}
104
105#define xchg(ptr, v) \
106 ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \
107 (unsigned long)(v)))
108
109static inline unsigned long __cmpxchg(volatile unsigned long *m,
110 unsigned long old, unsigned long new)
111{
112 unsigned long retval;
113 unsigned long flags;
114
115 local_irq_save(flags);
116 retval = *m;
117 if (retval == old)
118 *m = new;
119 local_irq_restore(flags);
120 return retval;
121}
122
123#define cmpxchg(ptr, o, n) \
124 ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
125 (unsigned long)(o), \
126 (unsigned long)(n)))
127
128#endif /* !__ASSEMBLY__ */ 100#endif /* !__ASSEMBLY__ */
129
130#endif /* __KERNEL__ */ 101#endif /* __KERNEL__ */
131#endif /* _ASM_SYSTEM_H */ 102#endif /* _ASM_SYSTEM_H */
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
index 2001cb657a95..aa07a4a5d794 100644
--- a/arch/mn10300/include/asm/thread_info.h
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -16,10 +16,6 @@
16 16
17#include <asm/page.h> 17#include <asm/page.h>
18 18
19#ifndef __ASSEMBLY__
20#include <asm/processor.h>
21#endif
22
23#define PREEMPT_ACTIVE 0x10000000 19#define PREEMPT_ACTIVE 0x10000000
24 20
25#ifdef CONFIG_4KSTACKS 21#ifdef CONFIG_4KSTACKS
@@ -38,10 +34,14 @@
38 * must also be changed 34 * must also be changed
39 */ 35 */
40#ifndef __ASSEMBLY__ 36#ifndef __ASSEMBLY__
37typedef struct {
38 unsigned long seg;
39} mm_segment_t;
41 40
42struct thread_info { 41struct thread_info {
43 struct task_struct *task; /* main task structure */ 42 struct task_struct *task; /* main task structure */
44 struct exec_domain *exec_domain; /* execution domain */ 43 struct exec_domain *exec_domain; /* execution domain */
44 struct pt_regs *frame; /* current exception frame */
45 unsigned long flags; /* low level flags */ 45 unsigned long flags; /* low level flags */
46 __u32 cpu; /* current CPU */ 46 __u32 cpu; /* current CPU */
47 __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ 47 __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
@@ -55,6 +55,10 @@ struct thread_info {
55 __u8 supervisor_stack[0]; 55 __u8 supervisor_stack[0];
56}; 56};
57 57
58#define thread_info_to_uregs(ti) \
59 ((struct pt_regs *) \
60 ((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs)))
61
58#else /* !__ASSEMBLY__ */ 62#else /* !__ASSEMBLY__ */
59 63
60#ifndef __ASM_OFFSETS_H__ 64#ifndef __ASM_OFFSETS_H__
@@ -102,6 +106,12 @@ struct thread_info *current_thread_info(void)
102 return ti; 106 return ti;
103} 107}
104 108
109static inline __attribute__((const))
110struct pt_regs *current_frame(void)
111{
112 return current_thread_info()->frame;
113}
114
105/* how to get the current stack pointer from C */ 115/* how to get the current stack pointer from C */
106static inline unsigned long current_stack_pointer(void) 116static inline unsigned long current_stack_pointer(void)
107{ 117{
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..bd4e90dfe6c2 100644
--- a/arch/mn10300/include/asm/timex.h
+++ b/arch/mn10300/include/asm/timex.h
@@ -16,18 +16,30 @@
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
22extern cycles_t cacheflush_time;
23 20
24#ifdef __KERNEL__ 21#ifdef __KERNEL__
25 22
23extern cycles_t cacheflush_time;
24
26static inline cycles_t get_cycles(void) 25static inline cycles_t get_cycles(void)
27{ 26{
28 return read_timestamp_counter(); 27 return read_timestamp_counter();
29} 28}
30 29
30extern int init_clockevents(void);
31extern int init_clocksource(void);
32
33static inline void setup_jiffies_interrupt(int irq,
34 struct irqaction *action)
35{
36 u16 tmp;
37 setup_irq(irq, action);
38 set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
39 GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
40 tmp = GxICR(irq);
41}
42
31#endif /* __KERNEL__ */ 43#endif /* __KERNEL__ */
32 44
33#endif /* _ASM_TIMEX_H */ 45#endif /* _ASM_TIMEX_H */
diff --git a/arch/mn10300/include/asm/tlbflush.h b/arch/mn10300/include/asm/tlbflush.h
index 1a7e29281c5d..efddd6e1adea 100644
--- a/arch/mn10300/include/asm/tlbflush.h
+++ b/arch/mn10300/include/asm/tlbflush.h
@@ -11,24 +11,78 @@
11#ifndef _ASM_TLBFLUSH_H 11#ifndef _ASM_TLBFLUSH_H
12#define _ASM_TLBFLUSH_H 12#define _ASM_TLBFLUSH_H
13 13
14#include <linux/mm.h>
14#include <asm/processor.h> 15#include <asm/processor.h>
15 16
16#define __flush_tlb() \ 17struct tlb_state {
17do { \ 18 struct mm_struct *active_mm;
18 int w; \ 19 int state;
19 __asm__ __volatile__ \ 20};
20 (" mov %1,%0 \n" \ 21DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
21 " or %2,%0 \n" \
22 " mov %0,%1 \n" \
23 : "=d"(w) \
24 : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV) \
25 : "cc", "memory" \
26 ); \
27} while (0)
28 22
29#define __flush_tlb_all() __flush_tlb() 23/**
30#define __flush_tlb_one(addr) __flush_tlb() 24 * local_flush_tlb - Flush the current MM's entries from the local CPU's TLBs
25 */
26static inline void local_flush_tlb(void)
27{
28 int w;
29 asm volatile(
30 " mov %1,%0 \n"
31 " or %2,%0 \n"
32 " mov %0,%1 \n"
33 : "=d"(w)
34 : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV)
35 : "cc", "memory");
36}
37
38/**
39 * local_flush_tlb_all - Flush all entries from the local CPU's TLBs
40 */
41static inline void local_flush_tlb_all(void)
42{
43 local_flush_tlb();
44}
31 45
46/**
47 * local_flush_tlb_one - Flush one entry from the local CPU's TLBs
48 */
49static inline void local_flush_tlb_one(unsigned long addr)
50{
51 local_flush_tlb();
52}
53
54/**
55 * local_flush_tlb_page - Flush a page's entry from the local CPU's TLBs
56 * @mm: The MM to flush for
57 * @addr: The address of the target page in RAM (not its page struct)
58 */
59static inline
60void local_flush_tlb_page(struct mm_struct *mm, unsigned long addr)
61{
62 unsigned long pteu, flags, cnx;
63
64 addr &= PAGE_MASK;
65
66 local_irq_save(flags);
67
68 cnx = 1;
69#ifdef CONFIG_MN10300_TLB_USE_PIDR
70 cnx = mm->context.tlbpid[smp_processor_id()];
71#endif
72 if (cnx) {
73 pteu = addr;
74#ifdef CONFIG_MN10300_TLB_USE_PIDR
75 pteu |= cnx & xPTEU_PID;
76#endif
77 IPTEU = pteu;
78 DPTEU = pteu;
79 if (IPTEL & xPTEL_V)
80 IPTEL = 0;
81 if (DPTEL & xPTEL_V)
82 DPTEL = 0;
83 }
84 local_irq_restore(flags);
85}
32 86
33/* 87/*
34 * TLB flushing: 88 * TLB flushing:
@@ -40,41 +94,61 @@ do { \
40 * - flush_tlb_range(mm, start, end) flushes a range of pages 94 * - flush_tlb_range(mm, start, end) flushes a range of pages
41 * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables 95 * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
42 */ 96 */
43#define flush_tlb_all() \ 97#ifdef CONFIG_SMP
44do { \ 98
45 preempt_disable(); \ 99#include <asm/smp.h>
46 __flush_tlb_all(); \ 100
47 preempt_enable(); \ 101extern void flush_tlb_all(void);
48} while (0) 102extern void flush_tlb_current_task(void);
49 103extern void flush_tlb_mm(struct mm_struct *);
50#define flush_tlb_mm(mm) \ 104extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
51do { \ 105
52 preempt_disable(); \ 106#define flush_tlb() flush_tlb_current_task()
53 __flush_tlb_all(); \ 107
54 preempt_enable(); \ 108static inline void flush_tlb_range(struct vm_area_struct *vma,
55} while (0) 109 unsigned long start, unsigned long end)
56 110{
57#define flush_tlb_range(vma, start, end) \ 111 flush_tlb_mm(vma->vm_mm);
58do { \ 112}
59 unsigned long __s __attribute__((unused)) = (start); \ 113
60 unsigned long __e __attribute__((unused)) = (end); \ 114#else /* CONFIG_SMP */
61 preempt_disable(); \ 115
62 __flush_tlb_all(); \ 116static inline void flush_tlb_all(void)
63 preempt_enable(); \ 117{
64} while (0) 118 preempt_disable();
65 119 local_flush_tlb_all();
66 120 preempt_enable();
67#define __flush_tlb_global() flush_tlb_all() 121}
68#define flush_tlb() flush_tlb_all() 122
69#define flush_tlb_kernel_range(start, end) \ 123static inline void flush_tlb_mm(struct mm_struct *mm)
70do { \ 124{
71 unsigned long __s __attribute__((unused)) = (start); \ 125 preempt_disable();
72 unsigned long __e __attribute__((unused)) = (end); \ 126 local_flush_tlb_all();
73 flush_tlb_all(); \ 127 preempt_enable();
74} while (0) 128}
75 129
76extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); 130static inline void flush_tlb_range(struct vm_area_struct *vma,
77 131 unsigned long start, unsigned long end)
78#define flush_tlb_pgtables(mm, start, end) do {} while (0) 132{
133 preempt_disable();
134 local_flush_tlb_all();
135 preempt_enable();
136}
137
138#define flush_tlb_page(vma, addr) local_flush_tlb_page((vma)->vm_mm, addr)
139#define flush_tlb() flush_tlb_all()
140
141#endif /* CONFIG_SMP */
142
143static inline void flush_tlb_kernel_range(unsigned long start,
144 unsigned long end)
145{
146 flush_tlb_all();
147}
148
149static inline void flush_tlb_pgtables(struct mm_struct *mm,
150 unsigned long start, unsigned long end)
151{
152}
79 153
80#endif /* _ASM_TLBFLUSH_H */ 154#endif /* _ASM_TLBFLUSH_H */
diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h
index 197a7af3dd8a..679dee0bbd08 100644
--- a/arch/mn10300/include/asm/uaccess.h
+++ b/arch/mn10300/include/asm/uaccess.h
@@ -14,9 +14,8 @@
14/* 14/*
15 * User space memory access functions 15 * User space memory access functions
16 */ 16 */
17#include <linux/sched.h> 17#include <linux/thread_info.h>
18#include <asm/page.h> 18#include <asm/page.h>
19#include <asm/pgtable.h>
20#include <asm/errno.h> 19#include <asm/errno.h>
21 20
22#define VERIFY_READ 0 21#define VERIFY_READ 0
@@ -29,7 +28,6 @@
29 * 28 *
30 * For historical reasons, these macros are grossly misnamed. 29 * For historical reasons, these macros are grossly misnamed.
31 */ 30 */
32
33#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 31#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
34 32
35#define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF) 33#define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF)
@@ -377,7 +375,7 @@ unsigned long __generic_copy_to_user_nocheck(void *to, const void *from,
377 375
378 376
379#if 0 377#if 0
380#error don't use - these macros don't increment to & from pointers 378#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. */ 379/* Optimize just a little bit when we know the size of the move. */
382#define __constant_copy_user(to, from, size) \ 380#define __constant_copy_user(to, from, size) \
383do { \ 381do { \
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index 23f2ab67574c..8f5f1e81baf5 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -3,13 +3,16 @@
3# 3#
4extra-y := head.o init_task.o vmlinux.lds 4extra-y := head.o init_task.o vmlinux.lds
5 5
6obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \ 6fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
7fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
8
9obj-y := process.o signal.o entry.o traps.o irq.o \
7 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 \
8 switch_to.o mn10300_ksyms.o kernel_execve.o 11 switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
9 12
10obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o 13obj-$(CONFIG_SMP) += smp.o smp-low.o
11 14
12obj-$(CONFIG_FPU) += fpu-low.o 15obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
13 16
14obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ 17obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
15 mn10300-debug.o 18 mn10300-debug.o
@@ -17,7 +20,7 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
17obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o 20obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
18obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o 21obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
19 22
20ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y) 23ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
21obj-$(CONFIG_GDBSTUB) += gdb-cache.o 24obj-$(CONFIG_GDBSTUB) += gdb-cache.o
22endif 25endif
23 26
@@ -25,3 +28,5 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o
25obj-$(CONFIG_PROFILE) += profile.o profile-low.o 28obj-$(CONFIG_PROFILE) += profile.o profile-low.o
26obj-$(CONFIG_MODULES) += module.o 29obj-$(CONFIG_MODULES) += module.o
27obj-$(CONFIG_KPROBES) += kprobes.o 30obj-$(CONFIG_KPROBES) += kprobes.o
31obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o
32obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 02dc7e461fef..96f24fab7de6 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -23,6 +23,7 @@ void foo(void)
23 23
24 OFFSET(TI_task, thread_info, task); 24 OFFSET(TI_task, thread_info, task);
25 OFFSET(TI_exec_domain, thread_info, exec_domain); 25 OFFSET(TI_exec_domain, thread_info, exec_domain);
26 OFFSET(TI_frame, thread_info, frame);
26 OFFSET(TI_flags, thread_info, flags); 27 OFFSET(TI_flags, thread_info, flags);
27 OFFSET(TI_cpu, thread_info, cpu); 28 OFFSET(TI_cpu, thread_info, cpu);
28 OFFSET(TI_preempt_count, thread_info, preempt_count); 29 OFFSET(TI_preempt_count, thread_info, preempt_count);
@@ -66,7 +67,15 @@ void foo(void)
66 OFFSET(THREAD_SP, thread_struct, sp); 67 OFFSET(THREAD_SP, thread_struct, sp);
67 OFFSET(THREAD_A3, thread_struct, a3); 68 OFFSET(THREAD_A3, thread_struct, a3);
68 OFFSET(THREAD_USP, thread_struct, usp); 69 OFFSET(THREAD_USP, thread_struct, usp);
69 OFFSET(THREAD_FRAME, thread_struct, __frame); 70#ifdef CONFIG_FPU
71 OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
72 OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);
73 DEFINE(__THREAD_USING_FPU, THREAD_USING_FPU);
74 DEFINE(__THREAD_HAS_FPU, THREAD_HAS_FPU);
75#endif /* CONFIG_FPU */
76 BLANK();
77
78 OFFSET(TASK_THREAD, task_struct, thread);
70 BLANK(); 79 BLANK();
71 80
72 DEFINE(CLONE_VM_asm, CLONE_VM); 81 DEFINE(CLONE_VM_asm, CLONE_VM);
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c
new file mode 100644
index 000000000000..d4cb535bf786
--- /dev/null
+++ b/arch/mn10300/kernel/cevt-mn10300.c
@@ -0,0 +1,131 @@
1/* MN10300 clockevents
2 *
3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/clockchips.h>
12#include <linux/interrupt.h>
13#include <linux/percpu.h>
14#include <linux/smp.h>
15#include <asm/timex.h>
16#include "internal.h"
17
18#ifdef CONFIG_SMP
19#if (CONFIG_NR_CPUS > 2) && !defined(CONFIG_GEENERIC_CLOCKEVENTS_BROADCAST)
20#error "This doesn't scale well! Need per-core local timers."
21#endif
22#else /* CONFIG_SMP */
23#define stop_jiffies_counter1()
24#define reload_jiffies_counter1(x)
25#define TMJC1IRQ TMJCIRQ
26#endif
27
28
29static int next_event(unsigned long delta,
30 struct clock_event_device *evt)
31{
32 unsigned int cpu = smp_processor_id();
33
34 if (cpu == 0) {
35 stop_jiffies_counter();
36 reload_jiffies_counter(delta - 1);
37 } else {
38 stop_jiffies_counter1();
39 reload_jiffies_counter1(delta - 1);
40 }
41 return 0;
42}
43
44static void set_clock_mode(enum clock_event_mode mode,
45 struct clock_event_device *evt)
46{
47 /* Nothing to do ... */
48}
49
50static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device);
51static DEFINE_PER_CPU(struct irqaction, timer_irq);
52
53static irqreturn_t timer_interrupt(int irq, void *dev_id)
54{
55 struct clock_event_device *cd;
56 unsigned int cpu = smp_processor_id();
57
58 if (cpu == 0)
59 stop_jiffies_counter();
60 else
61 stop_jiffies_counter1();
62
63 cd = &per_cpu(mn10300_clockevent_device, cpu);
64 cd->event_handler(cd);
65
66 return IRQ_HANDLED;
67}
68
69static void event_handler(struct clock_event_device *dev)
70{
71}
72
73int __init init_clockevents(void)
74{
75 struct clock_event_device *cd;
76 struct irqaction *iact;
77 unsigned int cpu = smp_processor_id();
78
79 cd = &per_cpu(mn10300_clockevent_device, cpu);
80
81 if (cpu == 0) {
82 stop_jiffies_counter();
83 cd->irq = TMJCIRQ;
84 } else {
85 stop_jiffies_counter1();
86 cd->irq = TMJC1IRQ;
87 }
88
89 cd->name = "Timestamp";
90 cd->features = CLOCK_EVT_FEAT_ONESHOT;
91
92 /* Calculate the min / max delta */
93 clockevent_set_clock(cd, MN10300_JCCLK);
94
95 cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd);
96 cd->min_delta_ns = clockevent_delta2ns(100, cd);
97
98 cd->rating = 200;
99 cd->cpumask = cpumask_of(smp_processor_id());
100 cd->set_mode = set_clock_mode;
101 cd->event_handler = event_handler;
102 cd->set_next_event = next_event;
103
104 iact = &per_cpu(timer_irq, cpu);
105 iact->flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER;
106 iact->handler = timer_interrupt;
107
108 clockevents_register_device(cd);
109
110#if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
111 /* setup timer irq affinity so it only runs on this cpu */
112 {
113 struct irq_desc *desc;
114 desc = irq_to_desc(cd->irq);
115 cpumask_copy(desc->affinity, cpumask_of(cpu));
116 iact->flags |= IRQF_NOBALANCING;
117 }
118#endif
119
120 if (cpu == 0) {
121 reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
122 iact->name = "CPU0 Timer";
123 } else {
124 reload_jiffies_counter1(MN10300_JC_PER_HZ - 1);
125 iact->name = "CPU1 Timer";
126 }
127
128 setup_jiffies_interrupt(cd->irq, iact);
129
130 return 0;
131}
diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c
new file mode 100644
index 000000000000..ba2f0c4d6e01
--- /dev/null
+++ b/arch/mn10300/kernel/csrc-mn10300.c
@@ -0,0 +1,35 @@
1/* MN10300 clocksource
2 *
3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/clocksource.h>
12#include <linux/init.h>
13#include <asm/timex.h>
14#include "internal.h"
15
16static cycle_t mn10300_read(struct clocksource *cs)
17{
18 return read_timestamp_counter();
19}
20
21static struct clocksource clocksource_mn10300 = {
22 .name = "TSC",
23 .rating = 200,
24 .read = mn10300_read,
25 .mask = CLOCKSOURCE_MASK(32),
26 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
27};
28
29int __init init_clocksource(void)
30{
31 startup_timestamp_counter();
32 clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK);
33 clocksource_register(&clocksource_mn10300);
34 return 0;
35}
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 3d394b4eefba..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:
88syscall_exit: 80syscall_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:
105syscall_exit_work: 97syscall_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:
168ENTRY(resume_userspace) 160ENTRY(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
180ENTRY(resume_kernel) 172ENTRY(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
@@ -216,31 +208,6 @@ ENTRY(irq_handler)
216 208
217############################################################################### 209###############################################################################
218# 210#
219# Monitor Signal handler entry point
220#
221###############################################################################
222ENTRY(monitor_signal)
223 movbu (0xae000001),d1
224 cmp 1,d1
225 beq monsignal
226 ret [],0
227
228monsignal:
229 or EPSW_NMID,epsw
230 mov d0,a0
231 mov a0,sp
232 mov (REG_EPSW,fp),d1
233 and ~EPSW_nSL,d1
234 mov d1,(REG_EPSW,fp)
235 movm (sp),[d2,d3,a2,a3,exreg0,exreg1,exother]
236 mov (sp),a1
237 mov a1,usp
238 movm (sp),[other]
239 add 4,sp
240here: jmp 0x8e000008-here+0x8e000008
241
242###############################################################################
243#
244# Double Fault handler entry point 211# Double Fault handler entry point
245# - note that there will not be a stack, D0/A0 will hold EPSW/PC as were 212# - note that there will not be a stack, D0/A0 will hold EPSW/PC as were
246# 213#
@@ -276,6 +243,10 @@ double_fault_loop:
276ENTRY(raw_bus_error) 243ENTRY(raw_bus_error)
277 add -4,sp 244 add -4,sp
278 mov d0,(sp) 245 mov d0,(sp)
246#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
247 mov (MMUCTR),d0
248 mov d0,(MMUCTR)
249#endif
279 mov (BCBERR),d0 # what 250 mov (BCBERR),d0 # what
280 btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error 251 btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error
281 beq __common_exception_aux # it wasn't 252 beq __common_exception_aux # it wasn't
@@ -302,11 +273,88 @@ ENTRY(nmi_handler)
302 add -4,sp 273 add -4,sp
303 mov d0,(sp) 274 mov d0,(sp)
304 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
2985:
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
3364:
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
3433:
344#endif /* CONFIG_GDBSTUB */
345 mov (sp),d0 # restore TBR to d0
346 add 4,sp
347#endif /* CONFIG_SMP */
348
305 bra __common_exception_nonmi 349 bra __common_exception_nonmi
306 350
307ENTRY(__common_exception) 351ENTRY(__common_exception)
308 add -4,sp 352 add -4,sp
309 mov d0,(sp) 353 mov d0,(sp)
354#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
355 mov (MMUCTR),d0
356 mov d0,(MMUCTR)
357#endif
310 358
311__common_exception_aux: 359__common_exception_aux:
312 mov (TBR),d0 360 mov (TBR),d0
@@ -331,15 +379,21 @@ __common_exception_nonmi:
331 mov d0,(REG_ORIG_D0,fp) 379 mov d0,(REG_ORIG_D0,fp)
332 380
333#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 */
334 btst 0x01,(gdbstub_busy) 387 btst 0x01,(gdbstub_busy)
335 beq 2f 388 beq 2f
389#endif /* CONFIG_SMP */
336 and ~EPSW_IE,epsw 390 and ~EPSW_IE,epsw
337 mov fp,d0 391 mov fp,d0
338 mov a2,d1 392 mov a2,d1
339 call gdbstub_exception[],0 # gdbstub itself caused an exception 393 call gdbstub_exception[],0 # gdbstub itself caused an exception
340 bra restore_all 394 bra restore_all
3412: 3952:
342#endif 396#endif /* CONFIG_GDBSTUB */
343 397
344 mov fp,d0 # arg 0: stacked register file 398 mov fp,d0 # arg 0: stacked register file
345 mov a2,d1 # arg 1: exception number 399 mov a2,d1 # arg 1: exception number
@@ -374,11 +428,7 @@ ENTRY(set_excp_vector)
374 add exception_table,d0 428 add exception_table,d0
375 mov d1,(d0) 429 mov d1,(d0)
376 mov 4,d1 430 mov 4,d1
377#if defined(CONFIG_MN10300_CACHE_WBACK)
378 jmp mn10300_dcache_flush_inv_range2
379#else
380 ret [],0 431 ret [],0
381#endif
382 432
383############################################################################### 433###############################################################################
384# 434#
diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S
index 96cfd47e68d5..78df25cfae29 100644
--- a/arch/mn10300/kernel/fpu-low.S
+++ b/arch/mn10300/kernel/fpu-low.S
@@ -8,25 +8,14 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
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#include <linux/linkage.h>
11#include <asm/cpu-regs.h> 12#include <asm/cpu-regs.h>
13#include <asm/smp.h>
14#include <asm/thread_info.h>
15#include <asm/asm-offsets.h>
16#include <asm/frame.inc>
12 17
13############################################################################### 18.macro FPU_INIT_STATE_ALL
14#
15# void fpu_init_state(void)
16# - initialise the FPU
17#
18###############################################################################
19 .globl fpu_init_state
20 .type fpu_init_state,@function
21fpu_init_state:
22 mov epsw,d0
23 or EPSW_FE,epsw
24
25#ifdef CONFIG_MN10300_PROC_MN103E010
26 nop
27 nop
28 nop
29#endif
30 fmov 0,fs0 19 fmov 0,fs0
31 fmov fs0,fs1 20 fmov fs0,fs1
32 fmov fs0,fs2 21 fmov fs0,fs2
@@ -60,7 +49,100 @@ fpu_init_state:
60 fmov fs0,fs30 49 fmov fs0,fs30
61 fmov fs0,fs31 50 fmov fs0,fs31
62 fmov FPCR_INIT,fpcr 51 fmov FPCR_INIT,fpcr
52.endm
53
54.macro FPU_SAVE_ALL areg,dreg
55 fmov fs0,(\areg+)
56 fmov fs1,(\areg+)
57 fmov fs2,(\areg+)
58 fmov fs3,(\areg+)
59 fmov fs4,(\areg+)
60 fmov fs5,(\areg+)
61 fmov fs6,(\areg+)
62 fmov fs7,(\areg+)
63 fmov fs8,(\areg+)
64 fmov fs9,(\areg+)
65 fmov fs10,(\areg+)
66 fmov fs11,(\areg+)
67 fmov fs12,(\areg+)
68 fmov fs13,(\areg+)
69 fmov fs14,(\areg+)
70 fmov fs15,(\areg+)
71 fmov fs16,(\areg+)
72 fmov fs17,(\areg+)
73 fmov fs18,(\areg+)
74 fmov fs19,(\areg+)
75 fmov fs20,(\areg+)
76 fmov fs21,(\areg+)
77 fmov fs22,(\areg+)
78 fmov fs23,(\areg+)
79 fmov fs24,(\areg+)
80 fmov fs25,(\areg+)
81 fmov fs26,(\areg+)
82 fmov fs27,(\areg+)
83 fmov fs28,(\areg+)
84 fmov fs29,(\areg+)
85 fmov fs30,(\areg+)
86 fmov fs31,(\areg+)
87 fmov fpcr,\dreg
88 mov \dreg,(\areg)
89.endm
90
91.macro FPU_RESTORE_ALL areg,dreg
92 fmov (\areg+),fs0
93 fmov (\areg+),fs1
94 fmov (\areg+),fs2
95 fmov (\areg+),fs3
96 fmov (\areg+),fs4
97 fmov (\areg+),fs5
98 fmov (\areg+),fs6
99 fmov (\areg+),fs7
100 fmov (\areg+),fs8
101 fmov (\areg+),fs9
102 fmov (\areg+),fs10
103 fmov (\areg+),fs11
104 fmov (\areg+),fs12
105 fmov (\areg+),fs13
106 fmov (\areg+),fs14
107 fmov (\areg+),fs15
108 fmov (\areg+),fs16
109 fmov (\areg+),fs17
110 fmov (\areg+),fs18
111 fmov (\areg+),fs19
112 fmov (\areg+),fs20
113 fmov (\areg+),fs21
114 fmov (\areg+),fs22
115 fmov (\areg+),fs23
116 fmov (\areg+),fs24
117 fmov (\areg+),fs25
118 fmov (\areg+),fs26
119 fmov (\areg+),fs27
120 fmov (\areg+),fs28
121 fmov (\areg+),fs29
122 fmov (\areg+),fs30
123 fmov (\areg+),fs31
124 mov (\areg),\dreg
125 fmov \dreg,fpcr
126.endm
63 127
128###############################################################################
129#
130# void fpu_init_state(void)
131# - initialise the FPU
132#
133###############################################################################
134 .globl fpu_init_state
135 .type fpu_init_state,@function
136fpu_init_state:
137 mov epsw,d0
138 or EPSW_FE,epsw
139
140#ifdef CONFIG_MN10300_PROC_MN103E010
141 nop
142 nop
143 nop
144#endif
145 FPU_INIT_STATE_ALL
64#ifdef CONFIG_MN10300_PROC_MN103E010 146#ifdef CONFIG_MN10300_PROC_MN103E010
65 nop 147 nop
66 nop 148 nop
@@ -89,40 +171,7 @@ fpu_save:
89 nop 171 nop
90#endif 172#endif
91 mov d0,a0 173 mov d0,a0
92 fmov fs0,(a0+) 174 FPU_SAVE_ALL a0,d0
93 fmov fs1,(a0+)
94 fmov fs2,(a0+)
95 fmov fs3,(a0+)
96 fmov fs4,(a0+)
97 fmov fs5,(a0+)
98 fmov fs6,(a0+)
99 fmov fs7,(a0+)
100 fmov fs8,(a0+)
101 fmov fs9,(a0+)
102 fmov fs10,(a0+)
103 fmov fs11,(a0+)
104 fmov fs12,(a0+)
105 fmov fs13,(a0+)
106 fmov fs14,(a0+)
107 fmov fs15,(a0+)
108 fmov fs16,(a0+)
109 fmov fs17,(a0+)
110 fmov fs18,(a0+)
111 fmov fs19,(a0+)
112 fmov fs20,(a0+)
113 fmov fs21,(a0+)
114 fmov fs22,(a0+)
115 fmov fs23,(a0+)
116 fmov fs24,(a0+)
117 fmov fs25,(a0+)
118 fmov fs26,(a0+)
119 fmov fs27,(a0+)
120 fmov fs28,(a0+)
121 fmov fs29,(a0+)
122 fmov fs30,(a0+)
123 fmov fs31,(a0+)
124 fmov fpcr,d0
125 mov d0,(a0)
126#ifdef CONFIG_MN10300_PROC_MN103E010 175#ifdef CONFIG_MN10300_PROC_MN103E010
127 nop 176 nop
128 nop 177 nop
@@ -135,63 +184,75 @@ fpu_save:
135 184
136############################################################################### 185###############################################################################
137# 186#
138# void fpu_restore(struct fpu_state_struct *) 187# void fpu_disabled(void)
139# - restore the fpu state 188# - handle an exception due to the FPU being disabled
140# - note that an FPU Operational exception might occur during this process 189# when CONFIG_FPU is enabled
141# 190#
142############################################################################### 191###############################################################################
143 .globl fpu_restore 192 .type fpu_disabled,@function
144 .type fpu_restore,@function 193 .globl fpu_disabled
145fpu_restore: 194fpu_disabled:
146 mov epsw,d1 195 or EPSW_nAR|EPSW_FE,epsw
147 or EPSW_FE,epsw /* enable the FPU so we can access it */
148
149#ifdef CONFIG_MN10300_PROC_MN103E010
150 nop 196 nop
151 nop 197 nop
152#endif
153 mov d0,a0
154 fmov (a0+),fs0
155 fmov (a0+),fs1
156 fmov (a0+),fs2
157 fmov (a0+),fs3
158 fmov (a0+),fs4
159 fmov (a0+),fs5
160 fmov (a0+),fs6
161 fmov (a0+),fs7
162 fmov (a0+),fs8
163 fmov (a0+),fs9
164 fmov (a0+),fs10
165 fmov (a0+),fs11
166 fmov (a0+),fs12
167 fmov (a0+),fs13
168 fmov (a0+),fs14
169 fmov (a0+),fs15
170 fmov (a0+),fs16
171 fmov (a0+),fs17
172 fmov (a0+),fs18
173 fmov (a0+),fs19
174 fmov (a0+),fs20
175 fmov (a0+),fs21
176 fmov (a0+),fs22
177 fmov (a0+),fs23
178 fmov (a0+),fs24
179 fmov (a0+),fs25
180 fmov (a0+),fs26
181 fmov (a0+),fs27
182 fmov (a0+),fs28
183 fmov (a0+),fs29
184 fmov (a0+),fs30
185 fmov (a0+),fs31
186 mov (a0),d0
187 fmov d0,fpcr
188#ifdef CONFIG_MN10300_PROC_MN103E010
189 nop 198 nop
199
200 mov sp,a1
201 mov (a1),d1 /* get epsw of user context */
202 and ~(THREAD_SIZE-1),a1 /* a1: (thread_info *ti) */
203 mov (TI_task,a1),a2 /* a2: (task_struct *tsk) */
204 btst EPSW_nSL,d1
205 beq fpu_used_in_kernel
206
207 or EPSW_FE,d1
208 mov d1,(sp)
209 mov (TASK_THREAD+THREAD_FPU_FLAGS,a2),d1
210#ifndef CONFIG_LAZY_SAVE_FPU
211 or __THREAD_HAS_FPU,d1
212 mov d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2)
213#else /* !CONFIG_LAZY_SAVE_FPU */
214 mov (fpu_state_owner),a0
215 cmp 0,a0
216 beq fpu_regs_save_end
217
218 mov (TASK_THREAD+THREAD_UREGS,a0),a1
219 add TASK_THREAD+THREAD_FPU_STATE,a0
220 FPU_SAVE_ALL a0,d0
221
222 mov (REG_EPSW,a1),d0
223 and ~EPSW_FE,d0
224 mov d0,(REG_EPSW,a1)
225
226fpu_regs_save_end:
227 mov a2,(fpu_state_owner)
228#endif /* !CONFIG_LAZY_SAVE_FPU */
229
230 btst __THREAD_USING_FPU,d1
231 beq fpu_regs_init
232 add TASK_THREAD+THREAD_FPU_STATE,a2
233 FPU_RESTORE_ALL a2,d0
234 rti
235
236fpu_regs_init:
237 FPU_INIT_STATE_ALL
238 add TASK_THREAD+THREAD_FPU_FLAGS,a2
239 bset __THREAD_USING_FPU,(0,a2)
240 rti
241
242fpu_used_in_kernel:
243 and ~(EPSW_nAR|EPSW_FE),epsw
190 nop 244 nop
191 nop 245 nop
192#endif
193 246
194 mov d1,epsw 247 add -4,sp
195 ret [],0 248 SAVE_ALL
249 mov -1,d0
250 mov d0,(REG_ORIG_D0,fp)
251
252 and ~EPSW_NMID,epsw
253
254 mov fp,d0
255 call fpu_disabled_in_kernel[],0
256 jmp ret_from_exception
196 257
197 .size fpu_restore,.-fpu_restore 258 .size fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu-low.S b/arch/mn10300/kernel/fpu-nofpu-low.S
new file mode 100644
index 000000000000..7ea087a549f4
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu-low.S
@@ -0,0 +1,39 @@
1/* MN10300 Low level FPU management operations
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/linkage.h>
12#include <asm/cpu-regs.h>
13#include <asm/smp.h>
14#include <asm/thread_info.h>
15#include <asm/asm-offsets.h>
16#include <asm/frame.inc>
17
18###############################################################################
19#
20# void fpu_disabled(void)
21# - handle an exception due to the FPU being disabled
22# when CONFIG_FPU is disabled
23#
24###############################################################################
25 .type fpu_disabled,@function
26 .globl fpu_disabled
27fpu_disabled:
28 add -4,sp
29 SAVE_ALL
30 mov -1,d0
31 mov d0,(REG_ORIG_D0,fp)
32
33 and ~EPSW_NMID,epsw
34
35 mov fp,d0
36 call unexpected_fpu_exception[],0
37 jmp ret_from_exception
38
39 .size fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu.c b/arch/mn10300/kernel/fpu-nofpu.c
new file mode 100644
index 000000000000..31c765b92c5d
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu.c
@@ -0,0 +1,30 @@
1/* MN10300 FPU management
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/fpu.h>
12
13/*
14 * handle an FPU operational exception
15 * - there's a possibility that if the FPU is asynchronous, the signal might
16 * be meant for a process other than the current one
17 */
18asmlinkage
19void unexpected_fpu_exception(struct pt_regs *regs, enum exception_code code)
20{
21 panic("An FPU exception was received, but there's no FPU enabled.");
22}
23
24/*
25 * fill in the FPU structure for a core dump
26 */
27int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
28{
29 return 0; /* not valid */
30}
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
index e705f25ad5ff..5f9c3fa19a85 100644
--- a/arch/mn10300/kernel/fpu.c
+++ b/arch/mn10300/kernel/fpu.c
@@ -12,56 +12,19 @@
12#include <asm/fpu.h> 12#include <asm/fpu.h>
13#include <asm/elf.h> 13#include <asm/elf.h>
14#include <asm/exceptions.h> 14#include <asm/exceptions.h>
15#include <asm/system.h>
15 16
17#ifdef CONFIG_LAZY_SAVE_FPU
16struct task_struct *fpu_state_owner; 18struct task_struct *fpu_state_owner;
19#endif
17 20
18/* 21/*
19 * handle an exception due to the FPU being disabled 22 * error functions in FPU disabled exception
20 */ 23 */
21asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code) 24asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs)
22{ 25{
23 struct task_struct *tsk = current; 26 die_if_no_fixup("An FPU Disabled exception happened in kernel space\n",
24 27 regs, EXCEP_FPU_DISABLED);
25 if (!user_mode(regs))
26 die_if_no_fixup("An FPU Disabled exception happened in"
27 " kernel space\n",
28 regs, code);
29
30#ifdef CONFIG_FPU
31 preempt_disable();
32
33 /* transfer the last process's FPU state to memory */
34 if (fpu_state_owner) {
35 fpu_save(&fpu_state_owner->thread.fpu_state);
36 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
37 }
38
39 /* the current process now owns the FPU state */
40 fpu_state_owner = tsk;
41 regs->epsw |= EPSW_FE;
42
43 /* load the FPU with the current process's FPU state or invent a new
44 * clean one if the process doesn't have one */
45 if (is_using_fpu(tsk)) {
46 fpu_restore(&tsk->thread.fpu_state);
47 } else {
48 fpu_init_state();
49 set_using_fpu(tsk);
50 }
51
52 preempt_enable();
53#else
54 {
55 siginfo_t info;
56
57 info.si_signo = SIGFPE;
58 info.si_errno = 0;
59 info.si_addr = (void *) tsk->thread.uregs->pc;
60 info.si_code = FPE_FLTINV;
61
62 force_sig_info(SIGFPE, &info, tsk);
63 }
64#endif /* CONFIG_FPU */
65} 28}
66 29
67/* 30/*
@@ -71,15 +34,16 @@ asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
71 */ 34 */
72asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) 35asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
73{ 36{
74 struct task_struct *tsk = fpu_state_owner; 37 struct task_struct *tsk = current;
75 siginfo_t info; 38 siginfo_t info;
39 u32 fpcr;
76 40
77 if (!user_mode(regs)) 41 if (!user_mode(regs))
78 die_if_no_fixup("An FPU Operation exception happened in" 42 die_if_no_fixup("An FPU Operation exception happened in"
79 " kernel space\n", 43 " kernel space\n",
80 regs, code); 44 regs, code);
81 45
82 if (!tsk) 46 if (!is_using_fpu(tsk))
83 die_if_no_fixup("An FPU Operation exception happened," 47 die_if_no_fixup("An FPU Operation exception happened,"
84 " but the FPU is not in use", 48 " but the FPU is not in use",
85 regs, code); 49 regs, code);
@@ -89,48 +53,45 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
89 info.si_addr = (void *) tsk->thread.uregs->pc; 53 info.si_addr = (void *) tsk->thread.uregs->pc;
90 info.si_code = FPE_FLTINV; 54 info.si_code = FPE_FLTINV;
91 55
92#ifdef CONFIG_FPU 56 unlazy_fpu(tsk);
93 {
94 u32 fpcr;
95 57
96 /* get FPCR (we need to enable the FPU whilst we do this) */ 58 fpcr = tsk->thread.fpu_state.fpcr;
97 asm volatile(" or %1,epsw \n" 59
98#ifdef CONFIG_MN10300_PROC_MN103E010 60 if (fpcr & FPCR_EC_Z)
99 " nop \n" 61 info.si_code = FPE_FLTDIV;
100 " nop \n" 62 else if (fpcr & FPCR_EC_O)
101 " nop \n" 63 info.si_code = FPE_FLTOVF;
102#endif 64 else if (fpcr & FPCR_EC_U)
103 " fmov fpcr,%0 \n" 65 info.si_code = FPE_FLTUND;
104#ifdef CONFIG_MN10300_PROC_MN103E010 66 else if (fpcr & FPCR_EC_I)
105 " nop \n" 67 info.si_code = FPE_FLTRES;
106 " nop \n"
107 " nop \n"
108#endif
109 " and %2,epsw \n"
110 : "=&d"(fpcr)
111 : "i"(EPSW_FE), "i"(~EPSW_FE)
112 );
113
114 if (fpcr & FPCR_EC_Z)
115 info.si_code = FPE_FLTDIV;
116 else if (fpcr & FPCR_EC_O)
117 info.si_code = FPE_FLTOVF;
118 else if (fpcr & FPCR_EC_U)
119 info.si_code = FPE_FLTUND;
120 else if (fpcr & FPCR_EC_I)
121 info.si_code = FPE_FLTRES;
122 }
123#endif
124 68
125 force_sig_info(SIGFPE, &info, tsk); 69 force_sig_info(SIGFPE, &info, tsk);
126} 70}
127 71
128/* 72/*
73 * handle an FPU invalid_op exception
74 * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
75 */
76asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
77{
78 siginfo_t info;
79
80 if (!user_mode(regs))
81 die_if_no_fixup("FPU invalid opcode", regs, code);
82
83 info.si_signo = SIGILL;
84 info.si_errno = 0;
85 info.si_code = ILL_COPROC;
86 info.si_addr = (void *) regs->pc;
87 force_sig_info(info.si_signo, &info, current);
88}
89
90/*
129 * save the FPU state to a signal context 91 * save the FPU state to a signal context
130 */ 92 */
131int fpu_setup_sigcontext(struct fpucontext *fpucontext) 93int fpu_setup_sigcontext(struct fpucontext *fpucontext)
132{ 94{
133#ifdef CONFIG_FPU
134 struct task_struct *tsk = current; 95 struct task_struct *tsk = current;
135 96
136 if (!is_using_fpu(tsk)) 97 if (!is_using_fpu(tsk))
@@ -142,11 +103,19 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
142 */ 103 */
143 preempt_disable(); 104 preempt_disable();
144 105
106#ifndef CONFIG_LAZY_SAVE_FPU
107 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
108 fpu_save(&tsk->thread.fpu_state);
109 tsk->thread.uregs->epsw &= ~EPSW_FE;
110 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
111 }
112#else /* !CONFIG_LAZY_SAVE_FPU */
145 if (fpu_state_owner == tsk) { 113 if (fpu_state_owner == tsk) {
146 fpu_save(&tsk->thread.fpu_state); 114 fpu_save(&tsk->thread.fpu_state);
147 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; 115 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
148 fpu_state_owner = NULL; 116 fpu_state_owner = NULL;
149 } 117 }
118#endif /* !CONFIG_LAZY_SAVE_FPU */
150 119
151 preempt_enable(); 120 preempt_enable();
152 121
@@ -161,9 +130,6 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
161 return -1; 130 return -1;
162 131
163 return 1; 132 return 1;
164#else
165 return 0;
166#endif
167} 133}
168 134
169/* 135/*
@@ -171,17 +137,23 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
171 */ 137 */
172void fpu_kill_state(struct task_struct *tsk) 138void fpu_kill_state(struct task_struct *tsk)
173{ 139{
174#ifdef CONFIG_FPU
175 /* disown anything left in the FPU */ 140 /* disown anything left in the FPU */
176 preempt_disable(); 141 preempt_disable();
177 142
143#ifndef CONFIG_LAZY_SAVE_FPU
144 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
145 tsk->thread.uregs->epsw &= ~EPSW_FE;
146 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
147 }
148#else /* !CONFIG_LAZY_SAVE_FPU */
178 if (fpu_state_owner == tsk) { 149 if (fpu_state_owner == tsk) {
179 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; 150 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
180 fpu_state_owner = NULL; 151 fpu_state_owner = NULL;
181 } 152 }
153#endif /* !CONFIG_LAZY_SAVE_FPU */
182 154
183 preempt_enable(); 155 preempt_enable();
184#endif 156
185 /* we no longer have a valid current FPU state */ 157 /* we no longer have a valid current FPU state */
186 clear_using_fpu(tsk); 158 clear_using_fpu(tsk);
187} 159}
@@ -195,8 +167,7 @@ int fpu_restore_sigcontext(struct fpucontext *fpucontext)
195 int ret; 167 int ret;
196 168
197 /* load up the old FPU state */ 169 /* load up the old FPU state */
198 ret = copy_from_user(&tsk->thread.fpu_state, 170 ret = copy_from_user(&tsk->thread.fpu_state, fpucontext,
199 fpucontext,
200 min(sizeof(struct fpu_state_struct), 171 min(sizeof(struct fpu_state_struct),
201 sizeof(struct fpucontext))); 172 sizeof(struct fpucontext)));
202 if (!ret) 173 if (!ret)
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
71gdbstub_io_rx_enter: 72gdbstub_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
441static int __gdbstub_mark_bp(u8 *addr, int ix) 441static 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 14f27f3bfaf4..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
54loop_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
@@ -61,18 +106,18 @@ _start:
61 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy 106 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
62 lne 107 lne
63 108
64#ifndef CONFIG_MN10300_CACHE_DISABLED 109#ifdef CONFIG_MN10300_CACHE_ENABLED
65#ifdef CONFIG_MN10300_CACHE_WBACK 110#ifdef CONFIG_MN10300_CACHE_WBACK
66#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC 111#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
67 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 112 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
68#else 113#else
69 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 114 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
70#endif /* CACHE_DISABLED */ 115#endif /* NOWRALLOC */
71#else 116#else
72 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 117 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
73#endif /* WBACK */ 118#endif /* WBACK */
74 movhu d0,(a0) # enable 119 movhu d0,(a0) # enable
75#endif /* NOWRALLOC */ 120#endif /* ENABLED */
76 121
77 # turn on RTS on the debug serial port if applicable 122 # turn on RTS on the debug serial port if applicable
78#ifdef CONFIG_MN10300_UNIT_ASB2305 123#ifdef CONFIG_MN10300_UNIT_ASB2305
@@ -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
263loop_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
275wait_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
2861:
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
311startup_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
401secondary_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###############################################################################
221ENTRY(__head_end) 415ENTRY(__head_end)
222 416
223/* 417/*
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
index eee2eee86267..6a064ab5af07 100644
--- a/arch/mn10300/kernel/internal.h
+++ b/arch/mn10300/kernel/internal.h
@@ -9,6 +9,9 @@
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
12struct clocksource;
13struct clock_event_device;
14
12/* 15/*
13 * kthread.S 16 * kthread.S
14 */ 17 */
@@ -18,3 +21,25 @@ extern int kernel_thread_helper(int);
18 * entry.S 21 * entry.S
19 */ 22 */
20extern void ret_from_fork(struct task_struct *) __attribute__((noreturn)); 23extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
24
25/*
26 * smp-low.S
27 */
28#ifdef CONFIG_SMP
29extern void mn10300_low_ipi_handler(void);
30#endif
31
32/*
33 * time.c
34 */
35extern irqreturn_t local_timer_interrupt(void);
36
37/*
38 * time.c
39 */
40#ifdef CONFIG_CEVT_MN10300
41extern void clockevent_set_clock(struct clock_event_device *, unsigned int);
42#endif
43#ifdef CONFIG_CSRC_MN10300
44extern void clocksource_set_clock(struct clocksource *, unsigned int);
45#endif
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index e2d5ed891f37..c2e44597c22b 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -12,11 +12,26 @@
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
17unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7; 19unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = {
20 [0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7
21};
18EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); 22EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
19 23
24#ifdef CONFIG_SMP
25static char irq_affinity_online[NR_IRQS] = {
26 [0 ... NR_IRQS - 1] = 0
27};
28
29#define NR_IRQ_WORDS ((NR_IRQS + 31) / 32)
30static unsigned long irq_affinity_request[NR_IRQ_WORDS] = {
31 [0 ... NR_IRQ_WORDS - 1] = 0
32};
33#endif /* CONFIG_SMP */
34
20atomic_t irq_err_count; 35atomic_t irq_err_count;
21 36
22/* 37/*
@@ -24,30 +39,67 @@ atomic_t irq_err_count;
24 */ 39 */
25static void mn10300_cpupic_ack(unsigned int irq) 40static void mn10300_cpupic_ack(unsigned int irq)
26{ 41{
42 unsigned long flags;
27 u16 tmp; 43 u16 tmp;
28 *(volatile u8 *) &GxICR(irq) = GxICR_DETECT; 44
45 flags = arch_local_cli_save();
46 GxICR_u8(irq) = GxICR_DETECT;
29 tmp = GxICR(irq); 47 tmp = GxICR(irq);
48 arch_local_irq_restore(flags);
30} 49}
31 50
32static void mn10300_cpupic_mask(unsigned int irq) 51static void __mask_and_set_icr(unsigned int irq,
52 unsigned int mask, unsigned int set)
33{ 53{
34 u16 tmp = GxICR(irq); 54 unsigned long flags;
35 GxICR(irq) = (tmp & GxICR_LEVEL); 55 u16 tmp;
56
57 flags = arch_local_cli_save();
58 tmp = GxICR(irq);
59 GxICR(irq) = (tmp & mask) | set;
36 tmp = GxICR(irq); 60 tmp = GxICR(irq);
61 arch_local_irq_restore(flags);
62}
63
64static void mn10300_cpupic_mask(unsigned int irq)
65{
66 __mask_and_set_icr(irq, GxICR_LEVEL, 0);
37} 67}
38 68
39static void mn10300_cpupic_mask_ack(unsigned int irq) 69static void mn10300_cpupic_mask_ack(unsigned int irq)
40{ 70{
41 u16 tmp = GxICR(irq); 71#ifdef CONFIG_SMP
42 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; 72 unsigned long flags;
43 tmp = GxICR(irq); 73 u16 tmp;
74
75 flags = arch_local_cli_save();
76
77 if (!test_and_clear_bit(irq, irq_affinity_request)) {
78 tmp = GxICR(irq);
79 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
80 tmp = GxICR(irq);
81 } else {
82 u16 tmp2;
83 tmp = GxICR(irq);
84 GxICR(irq) = (tmp & GxICR_LEVEL);
85 tmp2 = GxICR(irq);
86
87 irq_affinity_online[irq] =
88 any_online_cpu(*irq_desc[irq].affinity);
89 CROSS_GxICR(irq, irq_affinity_online[irq]) =
90 (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
91 tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
92 }
93
94 arch_local_irq_restore(flags);
95#else /* CONFIG_SMP */
96 __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_DETECT);
97#endif /* CONFIG_SMP */
44} 98}
45 99
46static void mn10300_cpupic_unmask(unsigned int irq) 100static void mn10300_cpupic_unmask(unsigned int irq)
47{ 101{
48 u16 tmp = GxICR(irq); 102 __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
49 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
50 tmp = GxICR(irq);
51} 103}
52 104
53static void mn10300_cpupic_unmask_clear(unsigned int irq) 105static void mn10300_cpupic_unmask_clear(unsigned int irq)
@@ -56,11 +108,89 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
56 * device has ceased to assert its interrupt line and the interrupt 108 * device has ceased to assert its interrupt line and the interrupt
57 * channel has been disabled in the PIC, so for level-triggered 109 * channel has been disabled in the PIC, so for level-triggered
58 * interrupts we need to clear the request bit when we re-enable */ 110 * interrupts we need to clear the request bit when we re-enable */
59 u16 tmp = GxICR(irq); 111#ifdef CONFIG_SMP
60 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; 112 unsigned long flags;
61 tmp = GxICR(irq); 113 u16 tmp;
114
115 flags = arch_local_cli_save();
116
117 if (!test_and_clear_bit(irq, irq_affinity_request)) {
118 tmp = GxICR(irq);
119 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
120 tmp = GxICR(irq);
121 } else {
122 tmp = GxICR(irq);
123
124 irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
125 CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
126 tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
127 }
128
129 arch_local_irq_restore(flags);
130#else /* CONFIG_SMP */
131 __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE | GxICR_DETECT);
132#endif /* CONFIG_SMP */
62} 133}
63 134
135#ifdef CONFIG_SMP
136static int
137mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
138{
139 unsigned long flags;
140 int err;
141
142 flags = arch_local_cli_save();
143
144 /* check irq no */
145 switch (irq) {
146 case TMJCIRQ:
147 case RESCHEDULE_IPI:
148 case CALL_FUNC_SINGLE_IPI:
149 case LOCAL_TIMER_IPI:
150 case FLUSH_CACHE_IPI:
151 case CALL_FUNCTION_NMI_IPI:
152 case GDB_NMI_IPI:
153#ifdef CONFIG_MN10300_TTYSM0
154 case SC0RXIRQ:
155 case SC0TXIRQ:
156#ifdef CONFIG_MN10300_TTYSM0_TIMER8
157 case TM8IRQ:
158#elif CONFIG_MN10300_TTYSM0_TIMER2
159 case TM2IRQ:
160#endif /* CONFIG_MN10300_TTYSM0_TIMER8 */
161#endif /* CONFIG_MN10300_TTYSM0 */
162
163#ifdef CONFIG_MN10300_TTYSM1
164 case SC1RXIRQ:
165 case SC1TXIRQ:
166#ifdef CONFIG_MN10300_TTYSM1_TIMER12
167 case TM12IRQ:
168#elif CONFIG_MN10300_TTYSM1_TIMER9
169 case TM9IRQ:
170#elif CONFIG_MN10300_TTYSM1_TIMER3
171 case TM3IRQ:
172#endif /* CONFIG_MN10300_TTYSM1_TIMER12 */
173#endif /* CONFIG_MN10300_TTYSM1 */
174
175#ifdef CONFIG_MN10300_TTYSM2
176 case SC2RXIRQ:
177 case SC2TXIRQ:
178 case TM10IRQ:
179#endif /* CONFIG_MN10300_TTYSM2 */
180 err = -1;
181 break;
182
183 default:
184 set_bit(irq, irq_affinity_request);
185 err = 0;
186 break;
187 }
188
189 arch_local_irq_restore(flags);
190 return err;
191}
192#endif /* CONFIG_SMP */
193
64/* 194/*
65 * MN10300 PIC level-triggered IRQ handling. 195 * MN10300 PIC level-triggered IRQ handling.
66 * 196 *
@@ -79,6 +209,9 @@ static struct irq_chip mn10300_cpu_pic_level = {
79 .mask = mn10300_cpupic_mask, 209 .mask = mn10300_cpupic_mask,
80 .mask_ack = mn10300_cpupic_mask, 210 .mask_ack = mn10300_cpupic_mask,
81 .unmask = mn10300_cpupic_unmask_clear, 211 .unmask = mn10300_cpupic_unmask_clear,
212#ifdef CONFIG_SMP
213 .set_affinity = mn10300_cpupic_setaffinity,
214#endif
82}; 215};
83 216
84/* 217/*
@@ -94,6 +227,9 @@ static struct irq_chip mn10300_cpu_pic_edge = {
94 .mask = mn10300_cpupic_mask, 227 .mask = mn10300_cpupic_mask,
95 .mask_ack = mn10300_cpupic_mask_ack, 228 .mask_ack = mn10300_cpupic_mask_ack,
96 .unmask = mn10300_cpupic_unmask, 229 .unmask = mn10300_cpupic_unmask,
230#ifdef CONFIG_SMP
231 .set_affinity = mn10300_cpupic_setaffinity,
232#endif
97}; 233};
98 234
99/* 235/*
@@ -111,14 +247,34 @@ void ack_bad_irq(int irq)
111 */ 247 */
112void set_intr_level(int irq, u16 level) 248void set_intr_level(int irq, u16 level)
113{ 249{
114 u16 tmp; 250 BUG_ON(in_interrupt());
115 251
116 if (in_interrupt()) 252 __mask_and_set_icr(irq, GxICR_ENABLE, level);
117 BUG(); 253}
118 254
119 tmp = GxICR(irq); 255void mn10300_intc_set_level(unsigned int irq, unsigned int level)
120 GxICR(irq) = (tmp & GxICR_ENABLE) | level; 256{
121 tmp = GxICR(irq); 257 set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
258}
259
260void mn10300_intc_clear(unsigned int irq)
261{
262 __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
263}
264
265void mn10300_intc_set(unsigned int irq)
266{
267 __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
268}
269
270void mn10300_intc_enable(unsigned int irq)
271{
272 mn10300_cpupic_unmask(irq);
273}
274
275void mn10300_intc_disable(unsigned int irq)
276{
277 mn10300_cpupic_mask(irq);
122} 278}
123 279
124/* 280/*
@@ -126,7 +282,7 @@ void set_intr_level(int irq, u16 level)
126 * than before 282 * than before
127 * - see Documentation/mn10300/features.txt 283 * - see Documentation/mn10300/features.txt
128 */ 284 */
129void set_intr_postackable(int irq) 285void mn10300_set_lateack_irq_type(int irq)
130{ 286{
131 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, 287 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
132 handle_level_irq); 288 handle_level_irq);
@@ -147,6 +303,7 @@ void __init init_IRQ(void)
147 * interrupts */ 303 * interrupts */
148 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, 304 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
149 handle_level_irq); 305 handle_level_irq);
306
150 unit_init_IRQ(); 307 unit_init_IRQ();
151} 308}
152 309
@@ -156,20 +313,22 @@ void __init init_IRQ(void)
156asmlinkage void do_IRQ(void) 313asmlinkage void do_IRQ(void)
157{ 314{
158 unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw; 315 unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
316 unsigned int cpu_id = smp_processor_id();
159 int irq; 317 int irq;
160 318
161 sp = current_stack_pointer(); 319 sp = current_stack_pointer();
162 if (sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN) 320 BUG_ON(sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN);
163 BUG();
164 321
165 /* make sure local_irq_enable() doesn't muck up the interrupt priority 322 /* make sure local_irq_enable() doesn't muck up the interrupt priority
166 * setting in EPSW */ 323 * setting in EPSW */
167 old_irq_enabled_epsw = __mn10300_irq_enabled_epsw; 324 old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id];
168 local_save_flags(epsw); 325 local_save_flags(epsw);
169 __mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw); 326 __mn10300_irq_enabled_epsw[cpu_id] = EPSW_IE | (EPSW_IM & epsw);
170 irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL; 327 irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
171 328
172 __IRQ_STAT(smp_processor_id(), __irq_count)++; 329#ifdef CONFIG_MN10300_WD_TIMER
330 __IRQ_STAT(cpu_id, __irq_count)++;
331#endif
173 332
174 irq_enter(); 333 irq_enter();
175 334
@@ -189,7 +348,7 @@ asmlinkage void do_IRQ(void)
189 local_irq_restore(epsw); 348 local_irq_restore(epsw);
190 } 349 }
191 350
192 __mn10300_irq_enabled_epsw = old_irq_enabled_epsw; 351 __mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw;
193 352
194 irq_exit(); 353 irq_exit();
195} 354}
@@ -222,9 +381,16 @@ int show_interrupts(struct seq_file *p, void *v)
222 seq_printf(p, "%3d: ", i); 381 seq_printf(p, "%3d: ", i);
223 for_each_present_cpu(cpu) 382 for_each_present_cpu(cpu)
224 seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); 383 seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
225 seq_printf(p, " %14s.%u", irq_desc[i].chip->name, 384
226 (GxICR(i) & GxICR_LEVEL) >> 385 if (i < NR_CPU_IRQS)
227 GxICR_LEVEL_SHIFT); 386 seq_printf(p, " %14s.%u",
387 irq_desc[i].chip->name,
388 (GxICR(i) & GxICR_LEVEL) >>
389 GxICR_LEVEL_SHIFT);
390 else
391 seq_printf(p, " %14s",
392 irq_desc[i].chip->name);
393
228 seq_printf(p, " %s", action->name); 394 seq_printf(p, " %s", action->name);
229 395
230 for (action = action->next; 396 for (action = action->next;
@@ -240,11 +406,13 @@ int show_interrupts(struct seq_file *p, void *v)
240 406
241 /* polish off with NMI and error counters */ 407 /* polish off with NMI and error counters */
242 case NR_IRQS: 408 case NR_IRQS:
409#ifdef CONFIG_MN10300_WD_TIMER
243 seq_printf(p, "NMI: "); 410 seq_printf(p, "NMI: ");
244 for (j = 0; j < NR_CPUS; j++) 411 for (j = 0; j < NR_CPUS; j++)
245 if (cpu_online(j)) 412 if (cpu_online(j))
246 seq_printf(p, "%10u ", nmi_count(j)); 413 seq_printf(p, "%10u ", nmi_count(j));
247 seq_putc(p, '\n'); 414 seq_putc(p, '\n');
415#endif
248 416
249 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 417 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
250 break; 418 break;
@@ -252,3 +420,51 @@ int show_interrupts(struct seq_file *p, void *v)
252 420
253 return 0; 421 return 0;
254} 422}
423
424#ifdef CONFIG_HOTPLUG_CPU
425void migrate_irqs(void)
426{
427 irq_desc_t *desc;
428 int irq;
429 unsigned int self, new;
430 unsigned long flags;
431
432 self = smp_processor_id();
433 for (irq = 0; irq < NR_IRQS; irq++) {
434 desc = irq_desc + irq;
435
436 if (desc->status == IRQ_PER_CPU)
437 continue;
438
439 if (cpu_isset(self, irq_desc[irq].affinity) &&
440 !cpus_intersects(irq_affinity[irq], cpu_online_map)) {
441 int cpu_id;
442 cpu_id = first_cpu(cpu_online_map);
443 cpu_set(cpu_id, irq_desc[irq].affinity);
444 }
445 /* We need to operate irq_affinity_online atomically. */
446 arch_local_cli_save(flags);
447 if (irq_affinity_online[irq] == self) {
448 u16 x, tmp;
449
450 x = GxICR(irq);
451 GxICR(irq) = x & GxICR_LEVEL;
452 tmp = GxICR(irq);
453
454 new = any_online_cpu(irq_desc[irq].affinity);
455 irq_affinity_online[irq] = new;
456
457 CROSS_GxICR(irq, new) =
458 (x & GxICR_LEVEL) | GxICR_DETECT;
459 tmp = CROSS_GxICR(irq, new);
460
461 x &= GxICR_LEVEL | GxICR_ENABLE;
462 if (GxICR(irq) & GxICR_REQUEST) {
463 x |= GxICR_REQUEST | GxICR_DETECT;
464 CROSS_GxICR(irq, new) = x;
465 tmp = CROSS_GxICR(irq, new);
466 }
467 arch_local_irq_restore(flags);
468 }
469}
470#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c
index 67e6389d625a..0311a7fcea16 100644
--- a/arch/mn10300/kernel/kprobes.c
+++ b/arch/mn10300/kernel/kprobes.c
@@ -377,8 +377,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
377 377
378void __kprobes arch_disarm_kprobe(struct kprobe *p) 378void __kprobes arch_disarm_kprobe(struct kprobe *p)
379{ 379{
380#ifndef CONFIG_MN10300_CACHE_SNOOP
380 mn10300_dcache_flush(); 381 mn10300_dcache_flush();
381 mn10300_icache_inv(); 382 mn10300_icache_inv();
383#endif
382} 384}
383 385
384void arch_remove_kprobe(struct kprobe *p) 386void arch_remove_kprobe(struct kprobe *p)
@@ -390,8 +392,10 @@ void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
390{ 392{
391 *p->addr = p->opcode; 393 *p->addr = p->opcode;
392 regs->pc = (unsigned long) p->addr; 394 regs->pc = (unsigned long) p->addr;
395#ifndef CONFIG_MN10300_CACHE_SNOOP
393 mn10300_dcache_flush(); 396 mn10300_dcache_flush();
394 mn10300_icache_inv(); 397 mn10300_icache_inv();
398#endif
395} 399}
396 400
397static inline 401static inline
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
41ENTRY(mn10300_serial_vdma_interrupt) 41ENTRY(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
166mnsc_vdma_tx_empty: 166mnsc_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 */
323static void mn10300_serial_mask_ack(unsigned int irq) 376static 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
330static void mn10300_serial_nop(unsigned int irq) 387static void mn10300_serial_nop(unsigned int irq)
@@ -348,23 +405,36 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
348 405
349static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) 406static 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
356static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) 417static 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
363static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) 429static 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)
650static void mn10300_serial_set_mctrl(struct uart_port *_port, 720static 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 */
877static void mn10300_serial_shutdown(struct uart_port *_port) 954static 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
956try_alternative: 1093try_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
54touch_nmi_watchdog: 55touch_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..c5e12bfd9fcd 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -30,7 +30,7 @@
30static DEFINE_SPINLOCK(watchdog_print_lock); 30static DEFINE_SPINLOCK(watchdog_print_lock);
31static unsigned int watchdog; 31static unsigned int watchdog;
32static unsigned int watchdog_hz = 1; 32static unsigned int watchdog_hz = 1;
33unsigned int watchdog_alert_counter; 33unsigned int watchdog_alert_counter[NR_CPUS];
34 34
35EXPORT_SYMBOL(touch_nmi_watchdog); 35EXPORT_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
122static void watchdog_dump_register(void *dummy)
123{
124 printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
125 show_registers(current_frame());
126}
127#endif
128
124asmlinkage 129asmlinkage
125void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) 130void 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 f48373e2bc1c..0d0f8049a17b 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)
57void (*pm_power_off)(void); 57void (*pm_power_off)(void);
58EXPORT_SYMBOL(pm_power_off); 58EXPORT_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 */
79static 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 */
78void cpu_idle(void) 108void 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,10 +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;
91 122#endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
92 irq_stat[cpu].idle_timestamp = jiffies; 123 }
93 idle(); 124 idle();
94 } 125 }
95 126
@@ -197,6 +228,7 @@ int copy_thread(unsigned long clone_flags,
197 unsigned long c_usp, unsigned long ustk_size, 228 unsigned long c_usp, unsigned long ustk_size,
198 struct task_struct *p, struct pt_regs *kregs) 229 struct task_struct *p, struct pt_regs *kregs)
199{ 230{
231 struct thread_info *ti = task_thread_info(p);
200 struct pt_regs *c_uregs, *c_kregs, *uregs; 232 struct pt_regs *c_uregs, *c_kregs, *uregs;
201 unsigned long c_ksp; 233 unsigned long c_ksp;
202 234
@@ -217,7 +249,7 @@ int copy_thread(unsigned long clone_flags,
217 249
218 /* the new TLS pointer is passed in as arg #5 to sys_clone() */ 250 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
219 if (clone_flags & CLONE_SETTLS) 251 if (clone_flags & CLONE_SETTLS)
220 c_uregs->e2 = __frame->d3; 252 c_uregs->e2 = current_frame()->d3;
221 253
222 /* set up the return kernel frame if called from kernel_thread() */ 254 /* set up the return kernel frame if called from kernel_thread() */
223 c_kregs = c_uregs; 255 c_kregs = c_uregs;
@@ -235,7 +267,7 @@ int copy_thread(unsigned long clone_flags,
235 } 267 }
236 268
237 /* set up things up so the scheduler can start the new task */ 269 /* set up things up so the scheduler can start the new task */
238 p->thread.__frame = c_kregs; 270 ti->frame = c_kregs;
239 p->thread.a3 = (unsigned long) c_kregs; 271 p->thread.a3 = (unsigned long) c_kregs;
240 p->thread.sp = c_ksp; 272 p->thread.sp = c_ksp;
241 p->thread.pc = (unsigned long) ret_from_fork; 273 p->thread.pc = (unsigned long) ret_from_fork;
@@ -247,25 +279,26 @@ int copy_thread(unsigned long clone_flags,
247 279
248/* 280/*
249 * clone a process 281 * clone a process
250 * - tlsptr is retrieved by copy_thread() from __frame->d3 282 * - tlsptr is retrieved by copy_thread() from current_frame()->d3
251 */ 283 */
252asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, 284asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
253 int __user *parent_tidptr, int __user *child_tidptr, 285 int __user *parent_tidptr, int __user *child_tidptr,
254 int __user *tlsptr) 286 int __user *tlsptr)
255{ 287{
256 return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0, 288 return do_fork(clone_flags, newsp ?: current_frame()->sp,
257 parent_tidptr, child_tidptr); 289 current_frame(), 0, parent_tidptr, child_tidptr);
258} 290}
259 291
260asmlinkage long sys_fork(void) 292asmlinkage long sys_fork(void)
261{ 293{
262 return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL); 294 return do_fork(SIGCHLD, current_frame()->sp,
295 current_frame(), 0, NULL, NULL);
263} 296}
264 297
265asmlinkage long sys_vfork(void) 298asmlinkage long sys_vfork(void)
266{ 299{
267 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame, 300 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
268 0, NULL, NULL); 301 current_frame(), 0, NULL, NULL);
269} 302}
270 303
271asmlinkage long sys_execve(const char __user *name, 304asmlinkage long sys_execve(const char __user *name,
@@ -279,7 +312,7 @@ asmlinkage long sys_execve(const char __user *name,
279 error = PTR_ERR(filename); 312 error = PTR_ERR(filename);
280 if (IS_ERR(filename)) 313 if (IS_ERR(filename))
281 return error; 314 return error;
282 error = do_execve(filename, argv, envp, __frame); 315 error = do_execve(filename, argv, envp, current_frame());
283 putname(filename); 316 putname(filename);
284 return error; 317 return error;
285} 318}
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 @@
20DEFINE_SPINLOCK(rtc_lock); 20DEFINE_SPINLOCK(rtc_lock);
21EXPORT_SYMBOL(rtc_lock); 21EXPORT_SYMBOL(rtc_lock);
22 22
23/* time for RTC to update itself in ioclks */ 23/*
24static unsigned long mn10300_rtc_update_period; 24 * Read the current RTC time
25 25 */
26void read_persistent_clock(struct timespec *ts) 26void 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 */
116void __init calibrate_clock(void) 120void __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..9e7a3209a3e1 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;
64struct thread_info *__current_ti = &init_thread_union.thread_info; 64struct thread_info *__current_ti = &init_thread_union.thread_info;
65struct task_struct *__current = &init_task; 65struct task_struct *__current = &init_task;
66 66
67#define mn10300_known_cpus 3 67#define mn10300_known_cpus 5
68static const char *const mn10300_cputypes[] = { 68static 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,57 +182,55 @@ void __init setup_arch(char **cmdline_p)
179void __init cpu_init(void) 182void __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)
186 type = mn10300_known_cpus; 188 type = mn10300_known_cpus;
187 189
188 printk(KERN_INFO "Matsushita %s, rev %ld\n", 190 printk(KERN_INFO "Panasonic %s, rev %ld\n",
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); 200static 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); 202static 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
212subsys_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 */
228static int show_cpuinfo(struct seq_file *m, void *v) 217static 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 : " PROCESSOR_VENDOR_NAME "\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/signal.c b/arch/mn10300/kernel/signal.c
index d4de05ab7864..690f4e9507d7 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -91,7 +91,7 @@ asmlinkage long sys_sigaction(int sig,
91 */ 91 */
92asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss) 92asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
93{ 93{
94 return do_sigaltstack(uss, uoss, __frame->sp); 94 return do_sigaltstack(uss, uoss, current_frame()->sp);
95} 95}
96 96
97/* 97/*
@@ -156,10 +156,11 @@ badframe:
156 */ 156 */
157asmlinkage long sys_sigreturn(void) 157asmlinkage long sys_sigreturn(void)
158{ 158{
159 struct sigframe __user *frame = (struct sigframe __user *) __frame->sp; 159 struct sigframe __user *frame;
160 sigset_t set; 160 sigset_t set;
161 long d0; 161 long d0;
162 162
163 frame = (struct sigframe __user *) current_frame()->sp;
163 if (verify_area(VERIFY_READ, frame, sizeof(*frame))) 164 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
164 goto badframe; 165 goto badframe;
165 if (__get_user(set.sig[0], &frame->sc.oldmask)) 166 if (__get_user(set.sig[0], &frame->sc.oldmask))
@@ -176,7 +177,7 @@ asmlinkage long sys_sigreturn(void)
176 recalc_sigpending(); 177 recalc_sigpending();
177 spin_unlock_irq(&current->sighand->siglock); 178 spin_unlock_irq(&current->sighand->siglock);
178 179
179 if (restore_sigcontext(__frame, &frame->sc, &d0)) 180 if (restore_sigcontext(current_frame(), &frame->sc, &d0))
180 goto badframe; 181 goto badframe;
181 182
182 return d0; 183 return d0;
@@ -191,11 +192,11 @@ badframe:
191 */ 192 */
192asmlinkage long sys_rt_sigreturn(void) 193asmlinkage long sys_rt_sigreturn(void)
193{ 194{
194 struct rt_sigframe __user *frame = 195 struct rt_sigframe __user *frame;
195 (struct rt_sigframe __user *) __frame->sp;
196 sigset_t set; 196 sigset_t set;
197 unsigned long d0; 197 long d0;
198 198
199 frame = (struct rt_sigframe __user *) current_frame()->sp;
199 if (verify_area(VERIFY_READ, frame, sizeof(*frame))) 200 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
200 goto badframe; 201 goto badframe;
201 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 202 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -207,10 +208,11 @@ asmlinkage long sys_rt_sigreturn(void)
207 recalc_sigpending(); 208 recalc_sigpending();
208 spin_unlock_irq(&current->sighand->siglock); 209 spin_unlock_irq(&current->sighand->siglock);
209 210
210 if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0)) 211 if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
211 goto badframe; 212 goto badframe;
212 213
213 if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT) 214 if (do_sigaltstack(&frame->uc.uc_stack, NULL, current_frame()->sp) ==
215 -EFAULT)
214 goto badframe; 216 goto badframe;
215 217
216 return d0; 218 return d0;
@@ -572,7 +574,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
572 574
573 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 575 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
574 clear_thread_flag(TIF_NOTIFY_RESUME); 576 clear_thread_flag(TIF_NOTIFY_RESUME);
575 tracehook_notify_resume(__frame); 577 tracehook_notify_resume(current_frame());
576 if (current->replacement_session_keyring) 578 if (current->replacement_session_keyring)
577 key_replace_session_keyring(); 579 key_replace_session_keyring();
578 } 580 }
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
31mn10300_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
58mn10300_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###############################################################################
78mn10300_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
97end:
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
new file mode 100644
index 000000000000..0dcd1c686ba8
--- /dev/null
+++ b/arch/mn10300/kernel/smp.c
@@ -0,0 +1,1152 @@
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
45static unsigned long sleep_mode[NR_CPUS];
46
47static void run_sleep_cpu(unsigned int cpu);
48static 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 */
68struct 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
78static DEFINE_SPINLOCK(smp_nmi_call_lock);
79static struct nmi_call_data_struct *nmi_call_data;
80
81/*
82 * Data structures and variables
83 */
84static cpumask_t cpu_callin_map; /* Bitmask of callin CPUs */
85static cpumask_t cpu_callout_map; /* Bitmask of callout CPUs */
86cpumask_t cpu_boot_map; /* Bitmask of boot APs */
87unsigned long start_stack[NR_CPUS - 1];
88
89/*
90 * Per CPU parameters
91 */
92struct mn10300_cpuinfo cpu_data[NR_CPUS] __cacheline_aligned;
93
94static int cpucount; /* The count of boot CPUs */
95static cpumask_t smp_commenced_mask;
96cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
97
98/*
99 * Function Prototypes
100 */
101static int do_boot_cpu(int);
102static void smp_show_cpu_info(int cpu_id);
103static void smp_callin(void);
104static void smp_online(void);
105static void smp_store_cpu_info(int);
106static void smp_cpu_init(void);
107static void smp_tune_scheduling(void);
108static void send_IPI_mask(const cpumask_t *cpumask, int irq);
109static void init_ipi(void);
110
111/*
112 * IPI Initialization interrupt definitions
113 */
114static void mn10300_ipi_disable(unsigned int irq);
115static void mn10300_ipi_enable(unsigned int irq);
116static void mn10300_ipi_ack(unsigned int irq);
117static void mn10300_ipi_nop(unsigned int irq);
118
119static 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
127static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
128static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id);
129
130static struct irqaction reschedule_ipi = {
131 .handler = smp_reschedule_interrupt,
132 .name = "smp reschedule IPI"
133};
134static struct irqaction call_function_ipi = {
135 .handler = smp_call_function_interrupt,
136 .name = "smp call function IPI"
137};
138
139#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
140static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
141static struct irqaction local_timer_ipi = {
142 .handler = smp_ipi_timer_interrupt,
143 .flags = IRQF_DISABLED,
144 .name = "smp local timer IPI"
145};
146#endif
147
148/**
149 * init_ipi - Initialise the IPI mechanism
150 */
151static void init_ipi(void)
152{
153 unsigned long flags;
154 u16 tmp16;
155
156 /* set up the reschedule IPI */
157 set_irq_chip_and_handler(RESCHEDULE_IPI,
158 &mn10300_ipi_type, handle_percpu_irq);
159 setup_irq(RESCHEDULE_IPI, &reschedule_ipi);
160 set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV);
161 mn10300_ipi_enable(RESCHEDULE_IPI);
162
163 /* set up the call function IPI */
164 set_irq_chip_and_handler(CALL_FUNC_SINGLE_IPI,
165 &mn10300_ipi_type, handle_percpu_irq);
166 setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi);
167 set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV);
168 mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
169
170 /* set up the local timer IPI */
171#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
172 defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
173 set_irq_chip_and_handler(LOCAL_TIMER_IPI,
174 &mn10300_ipi_type, handle_percpu_irq);
175 setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi);
176 set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV);
177 mn10300_ipi_enable(LOCAL_TIMER_IPI);
178#endif
179
180#ifdef CONFIG_MN10300_CACHE_ENABLED
181 /* set up the cache flush IPI */
182 flags = arch_local_cli_save();
183 __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV),
184 mn10300_low_ipi_handler);
185 GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT;
186 mn10300_ipi_enable(FLUSH_CACHE_IPI);
187 arch_local_irq_restore(flags);
188#endif
189
190 /* set up the NMI call function IPI */
191 flags = arch_local_cli_save();
192 GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
193 tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
194 arch_local_irq_restore(flags);
195
196 /* set up the SMP boot IPI */
197 flags = arch_local_cli_save();
198 __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV),
199 mn10300_low_ipi_handler);
200 arch_local_irq_restore(flags);
201}
202
203/**
204 * mn10300_ipi_shutdown - Shut down handling of an IPI
205 * @irq: The IPI to be shut down.
206 */
207static void mn10300_ipi_shutdown(unsigned int irq)
208{
209 unsigned long flags;
210 u16 tmp;
211
212 flags = arch_local_cli_save();
213
214 tmp = GxICR(irq);
215 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
216 tmp = GxICR(irq);
217
218 arch_local_irq_restore(flags);
219}
220
221/**
222 * mn10300_ipi_enable - Enable an IPI
223 * @irq: The IPI to be enabled.
224 */
225static void mn10300_ipi_enable(unsigned int irq)
226{
227 unsigned long flags;
228 u16 tmp;
229
230 flags = arch_local_cli_save();
231
232 tmp = GxICR(irq);
233 GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
234 tmp = GxICR(irq);
235
236 arch_local_irq_restore(flags);
237}
238
239/**
240 * mn10300_ipi_disable - Disable an IPI
241 * @irq: The IPI to be disabled.
242 */
243static void mn10300_ipi_disable(unsigned int irq)
244{
245 unsigned long flags;
246 u16 tmp;
247
248 flags = arch_local_cli_save();
249
250 tmp = GxICR(irq);
251 GxICR(irq) = tmp & GxICR_LEVEL;
252 tmp = GxICR(irq);
253
254 arch_local_irq_restore(flags);
255}
256
257/**
258 * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC
259 * @irq: The IPI to be acknowledged.
260 *
261 * Clear the interrupt detection flag for the IPI on the appropriate interrupt
262 * channel in the PIC.
263 */
264static void mn10300_ipi_ack(unsigned int irq)
265{
266 unsigned long flags;
267 u16 tmp;
268
269 flags = arch_local_cli_save();
270 GxICR_u8(irq) = GxICR_DETECT;
271 tmp = GxICR(irq);
272 arch_local_irq_restore(flags);
273}
274
275/**
276 * mn10300_ipi_nop - Dummy IPI action
277 * @irq: The IPI to be acted upon.
278 */
279static void mn10300_ipi_nop(unsigned int irq)
280{
281}
282
283/**
284 * send_IPI_mask - Send IPIs to all CPUs in list
285 * @cpumask: The list of CPUs to target.
286 * @irq: The IPI request to be sent.
287 *
288 * Send the specified IPI to all the CPUs in the list, not waiting for them to
289 * finish before returning. The caller is responsible for synchronisation if
290 * that is needed.
291 */
292static void send_IPI_mask(const cpumask_t *cpumask, int irq)
293{
294 int i;
295 u16 tmp;
296
297 for (i = 0; i < NR_CPUS; i++) {
298 if (cpu_isset(i, *cpumask)) {
299 /* send IPI */
300 tmp = CROSS_GxICR(irq, i);
301 CROSS_GxICR(irq, i) =
302 tmp | GxICR_REQUEST | GxICR_DETECT;
303 tmp = CROSS_GxICR(irq, i); /* flush write buffer */
304 }
305 }
306}
307
308/**
309 * send_IPI_self - Send an IPI to this CPU.
310 * @irq: The IPI request to be sent.
311 *
312 * Send the specified IPI to the current CPU.
313 */
314void send_IPI_self(int irq)
315{
316 send_IPI_mask(cpumask_of(smp_processor_id()), irq);
317}
318
319/**
320 * send_IPI_allbutself - Send IPIs to all the other CPUs.
321 * @irq: The IPI request to be sent.
322 *
323 * Send the specified IPI to all CPUs in the system barring the current one,
324 * not waiting for them to finish before returning. The caller is responsible
325 * for synchronisation if that is needed.
326 */
327void send_IPI_allbutself(int irq)
328{
329 cpumask_t cpumask;
330
331 cpumask = cpu_online_map;
332 cpu_clear(smp_processor_id(), cpumask);
333 send_IPI_mask(&cpumask, irq);
334}
335
336void arch_send_call_function_ipi_mask(const struct cpumask *mask)
337{
338 BUG();
339 /*send_IPI_mask(mask, CALL_FUNCTION_IPI);*/
340}
341
342void arch_send_call_function_single_ipi(int cpu)
343{
344 send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_IPI);
345}
346
347/**
348 * smp_send_reschedule - Send reschedule IPI to a CPU
349 * @cpu: The CPU to target.
350 */
351void smp_send_reschedule(int cpu)
352{
353 send_IPI_mask(cpumask_of(cpu), RESCHEDULE_IPI);
354}
355
356/**
357 * smp_nmi_call_function - Send a call function NMI IPI to all CPUs
358 * @func: The function to ask to be run.
359 * @info: The context data to pass to that function.
360 * @wait: If true, wait (atomically) until function is run on all CPUs.
361 *
362 * Send a non-maskable request to all CPUs in the system, requesting them to
363 * run the specified function with the given context data, and, potentially, to
364 * wait for completion of that function on all CPUs.
365 *
366 * Returns 0 if successful, -ETIMEDOUT if we were asked to wait, but hit the
367 * timeout.
368 */
369int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
370{
371 struct nmi_call_data_struct data;
372 unsigned long flags;
373 unsigned int cnt;
374 int cpus, ret = 0;
375
376 cpus = num_online_cpus() - 1;
377 if (cpus < 1)
378 return 0;
379
380 data.func = func;
381 data.info = info;
382 data.started = cpu_online_map;
383 cpu_clear(smp_processor_id(), data.started);
384 data.wait = wait;
385 if (wait)
386 data.finished = data.started;
387
388 spin_lock_irqsave(&smp_nmi_call_lock, flags);
389 nmi_call_data = &data;
390 smp_mb();
391
392 /* Send a message to all other CPUs and wait for them to respond */
393 send_IPI_allbutself(CALL_FUNCTION_NMI_IPI);
394
395 /* Wait for response */
396 if (CALL_FUNCTION_NMI_IPI_TIMEOUT > 0) {
397 for (cnt = 0;
398 cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
399 !cpus_empty(data.started);
400 cnt++)
401 mdelay(1);
402
403 if (wait && cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT) {
404 for (cnt = 0;
405 cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
406 !cpus_empty(data.finished);
407 cnt++)
408 mdelay(1);
409 }
410
411 if (cnt >= CALL_FUNCTION_NMI_IPI_TIMEOUT)
412 ret = -ETIMEDOUT;
413
414 } else {
415 /* If timeout value is zero, wait until cpumask has been
416 * cleared */
417 while (!cpus_empty(data.started))
418 barrier();
419 if (wait)
420 while (!cpus_empty(data.finished))
421 barrier();
422 }
423
424 spin_unlock_irqrestore(&smp_nmi_call_lock, flags);
425 return ret;
426}
427
428/**
429 * stop_this_cpu - Callback to stop a CPU.
430 * @unused: Callback context (ignored).
431 */
432void stop_this_cpu(void *unused)
433{
434 static volatile int stopflag;
435 unsigned long flags;
436
437#ifdef CONFIG_GDBSTUB
438 /* In case of single stepping smp_send_stop by other CPU,
439 * clear procindebug to avoid deadlock.
440 */
441 atomic_set(&procindebug[smp_processor_id()], 0);
442#endif /* CONFIG_GDBSTUB */
443
444 flags = arch_local_cli_save();
445 cpu_clear(smp_processor_id(), cpu_online_map);
446
447 while (!stopflag)
448 cpu_relax();
449
450 cpu_set(smp_processor_id(), cpu_online_map);
451 arch_local_irq_restore(flags);
452}
453
454/**
455 * smp_send_stop - Send a stop request to all CPUs.
456 */
457void smp_send_stop(void)
458{
459 smp_nmi_call_function(stop_this_cpu, NULL, 0);
460}
461
462/**
463 * smp_reschedule_interrupt - Reschedule IPI handler
464 * @irq: The interrupt number.
465 * @dev_id: The device ID.
466 *
467 * We need do nothing here, since the scheduling will be effected on our way
468 * back through entry.S.
469 *
470 * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
471 */
472static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
473{
474 /* do nothing */
475 return IRQ_HANDLED;
476}
477
478/**
479 * smp_call_function_interrupt - Call function IPI handler
480 * @irq: The interrupt number.
481 * @dev_id: The device ID.
482 *
483 * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
484 */
485static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
486{
487 /* generic_smp_call_function_interrupt(); */
488 generic_smp_call_function_single_interrupt();
489 return IRQ_HANDLED;
490}
491
492/**
493 * smp_nmi_call_function_interrupt - Non-maskable call function IPI handler
494 */
495void smp_nmi_call_function_interrupt(void)
496{
497 smp_call_func_t func = nmi_call_data->func;
498 void *info = nmi_call_data->info;
499 int wait = nmi_call_data->wait;
500
501 /* Notify the initiating CPU that I've grabbed the data and am about to
502 * execute the function
503 */
504 smp_mb();
505 cpu_clear(smp_processor_id(), nmi_call_data->started);
506 (*func)(info);
507
508 if (wait) {
509 smp_mb();
510 cpu_clear(smp_processor_id(), nmi_call_data->finished);
511 }
512}
513
514#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
515 defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
516/**
517 * smp_ipi_timer_interrupt - Local timer IPI handler
518 * @irq: The interrupt number.
519 * @dev_id: The device ID.
520 *
521 * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
522 */
523static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id)
524{
525 return local_timer_interrupt();
526}
527#endif
528
529void __init smp_init_cpus(void)
530{
531 int i;
532 for (i = 0; i < NR_CPUS; i++) {
533 set_cpu_possible(i, true);
534 set_cpu_present(i, true);
535 }
536}
537
538/**
539 * smp_cpu_init - Initialise AP in start_secondary.
540 *
541 * For this Application Processor, set up init_mm, initialise FPU and set
542 * interrupt level 0-6 setting.
543 */
544static void __init smp_cpu_init(void)
545{
546 unsigned long flags;
547 int cpu_id = smp_processor_id();
548 u16 tmp16;
549
550 if (test_and_set_bit(cpu_id, &cpu_initialized)) {
551 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
552 for (;;)
553 local_irq_enable();
554 }
555 printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);
556
557 atomic_inc(&init_mm.mm_count);
558 current->active_mm = &init_mm;
559 BUG_ON(current->mm);
560
561 enter_lazy_tlb(&init_mm, current);
562
563 /* Force FPU initialization */
564 clear_using_fpu(current);
565
566 GxICR(CALL_FUNC_SINGLE_IPI) = CALL_FUNCTION_GxICR_LV | GxICR_DETECT;
567 mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
568
569 GxICR(LOCAL_TIMER_IPI) = LOCAL_TIMER_GxICR_LV | GxICR_DETECT;
570 mn10300_ipi_enable(LOCAL_TIMER_IPI);
571
572 GxICR(RESCHEDULE_IPI) = RESCHEDULE_GxICR_LV | GxICR_DETECT;
573 mn10300_ipi_enable(RESCHEDULE_IPI);
574
575#ifdef CONFIG_MN10300_CACHE_ENABLED
576 GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT;
577 mn10300_ipi_enable(FLUSH_CACHE_IPI);
578#endif
579
580 mn10300_ipi_shutdown(SMP_BOOT_IRQ);
581
582 /* Set up the non-maskable call function IPI */
583 flags = arch_local_cli_save();
584 GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
585 tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
586 arch_local_irq_restore(flags);
587}
588
589/**
590 * smp_prepare_cpu_init - Initialise CPU in startup_secondary
591 *
592 * Set interrupt level 0-6 setting and init ICR of gdbstub.
593 */
594void smp_prepare_cpu_init(void)
595{
596 int loop;
597
598 /* Set the interrupt vector registers */
599 IVAR0 = EXCEP_IRQ_LEVEL0;
600 IVAR1 = EXCEP_IRQ_LEVEL1;
601 IVAR2 = EXCEP_IRQ_LEVEL2;
602 IVAR3 = EXCEP_IRQ_LEVEL3;
603 IVAR4 = EXCEP_IRQ_LEVEL4;
604 IVAR5 = EXCEP_IRQ_LEVEL5;
605 IVAR6 = EXCEP_IRQ_LEVEL6;
606
607 /* Disable all interrupts and set to priority 6 (lowest) */
608 for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
609 GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
610
611#ifdef CONFIG_GDBSTUB
612 /* initialise GDB-stub */
613 do {
614 unsigned long flags;
615 u16 tmp16;
616
617 flags = arch_local_cli_save();
618 GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
619 tmp16 = GxICR(GDB_NMI_IPI);
620 arch_local_irq_restore(flags);
621 } while (0);
622#endif
623}
624
625/**
626 * start_secondary - Activate a secondary CPU (AP)
627 * @unused: Thread parameter (ignored).
628 */
629int __init start_secondary(void *unused)
630{
631 smp_cpu_init();
632 smp_callin();
633 while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
634 cpu_relax();
635
636 local_flush_tlb();
637 preempt_disable();
638 smp_online();
639
640#ifdef CONFIG_GENERIC_CLOCKEVENTS
641 init_clockevents();
642#endif
643 cpu_idle();
644 return 0;
645}
646
647/**
648 * smp_prepare_cpus - Boot up secondary CPUs (APs)
649 * @max_cpus: Maximum number of CPUs to boot.
650 *
651 * Call do_boot_cpu, and boot up APs.
652 */
653void __init smp_prepare_cpus(unsigned int max_cpus)
654{
655 int phy_id;
656
657 /* Setup boot CPU information */
658 smp_store_cpu_info(0);
659 smp_tune_scheduling();
660
661 init_ipi();
662
663 /* If SMP should be disabled, then finish */
664 if (max_cpus == 0) {
665 printk(KERN_INFO "SMP mode deactivated.\n");
666 goto smp_done;
667 }
668
669 /* Boot secondary CPUs (for which phy_id > 0) */
670 for (phy_id = 0; phy_id < NR_CPUS; phy_id++) {
671 /* Don't boot primary CPU */
672 if (max_cpus <= cpucount + 1)
673 continue;
674 if (phy_id != 0)
675 do_boot_cpu(phy_id);
676 set_cpu_possible(phy_id, true);
677 smp_show_cpu_info(phy_id);
678 }
679
680smp_done:
681 Dprintk("Boot done.\n");
682}
683
684/**
685 * smp_store_cpu_info - Save a CPU's information
686 * @cpu: The CPU to save for.
687 *
688 * Save boot_cpu_data and jiffy for the specified CPU.
689 */
690static void __init smp_store_cpu_info(int cpu)
691{
692 struct mn10300_cpuinfo *ci = &cpu_data[cpu];
693
694 *ci = boot_cpu_data;
695 ci->loops_per_jiffy = loops_per_jiffy;
696 ci->type = CPUREV;
697}
698
699/**
700 * smp_tune_scheduling - Set time slice value
701 *
702 * Nothing to do here.
703 */
704static void __init smp_tune_scheduling(void)
705{
706}
707
708/**
709 * do_boot_cpu: Boot up one CPU
710 * @phy_id: Physical ID of CPU to boot.
711 *
712 * Send an IPI to a secondary CPU to boot it. Returns 0 on success, 1
713 * otherwise.
714 */
715static int __init do_boot_cpu(int phy_id)
716{
717 struct task_struct *idle;
718 unsigned long send_status, callin_status;
719 int timeout, cpu_id;
720
721 send_status = GxICR_REQUEST;
722 callin_status = 0;
723 timeout = 0;
724 cpu_id = phy_id;
725
726 cpucount++;
727
728 /* Create idle thread for this CPU */
729 idle = fork_idle(cpu_id);
730 if (IS_ERR(idle))
731 panic("Failed fork for CPU#%d.", cpu_id);
732
733 idle->thread.pc = (unsigned long)start_secondary;
734
735 printk(KERN_NOTICE "Booting CPU#%d\n", cpu_id);
736 start_stack[cpu_id - 1] = idle->thread.sp;
737
738 task_thread_info(idle)->cpu = cpu_id;
739
740 /* Send boot IPI to AP */
741 send_IPI_mask(cpumask_of(phy_id), SMP_BOOT_IRQ);
742
743 Dprintk("Waiting for send to finish...\n");
744
745 /* Wait for AP's IPI receive in 100[ms] */
746 do {
747 udelay(1000);
748 send_status =
749 CROSS_GxICR(SMP_BOOT_IRQ, phy_id) & GxICR_REQUEST;
750 } while (send_status == GxICR_REQUEST && timeout++ < 100);
751
752 Dprintk("Waiting for cpu_callin_map.\n");
753
754 if (send_status == 0) {
755 /* Allow AP to start initializing */
756 cpu_set(cpu_id, cpu_callout_map);
757
758 /* Wait for setting cpu_callin_map */
759 timeout = 0;
760 do {
761 udelay(1000);
762 callin_status = cpu_isset(cpu_id, cpu_callin_map);
763 } while (callin_status == 0 && timeout++ < 5000);
764
765 if (callin_status == 0)
766 Dprintk("Not responding.\n");
767 } else {
768 printk(KERN_WARNING "IPI not delivered.\n");
769 }
770
771 if (send_status == GxICR_REQUEST || callin_status == 0) {
772 cpu_clear(cpu_id, cpu_callout_map);
773 cpu_clear(cpu_id, cpu_callin_map);
774 cpu_clear(cpu_id, cpu_initialized);
775 cpucount--;
776 return 1;
777 }
778 return 0;
779}
780
781/**
782 * smp_show_cpu_info - Show SMP CPU information
783 * @cpu: The CPU of interest.
784 */
785static void __init smp_show_cpu_info(int cpu)
786{
787 struct mn10300_cpuinfo *ci = &cpu_data[cpu];
788
789 printk(KERN_INFO
790 "CPU#%d : ioclk speed: %lu.%02luMHz : bogomips : %lu.%02lu\n",
791 cpu,
792 MN10300_IOCLK / 1000000,
793 (MN10300_IOCLK / 10000) % 100,
794 ci->loops_per_jiffy / (500000 / HZ),
795 (ci->loops_per_jiffy / (5000 / HZ)) % 100);
796}
797
798/**
799 * smp_callin - Set cpu_callin_map of the current CPU ID
800 */
801static void __init smp_callin(void)
802{
803 unsigned long timeout;
804 int cpu;
805
806 cpu = smp_processor_id();
807 timeout = jiffies + (2 * HZ);
808
809 if (cpu_isset(cpu, cpu_callin_map)) {
810 printk(KERN_ERR "CPU#%d already present.\n", cpu);
811 BUG();
812 }
813 Dprintk("CPU#%d waiting for CALLOUT\n", cpu);
814
815 /* Wait for AP startup 2s total */
816 while (time_before(jiffies, timeout)) {
817 if (cpu_isset(cpu, cpu_callout_map))
818 break;
819 cpu_relax();
820 }
821
822 if (!time_before(jiffies, timeout)) {
823 printk(KERN_ERR
824 "BUG: CPU#%d started up but did not get a callout!\n",
825 cpu);
826 BUG();
827 }
828
829#ifdef CONFIG_CALIBRATE_DELAY
830 calibrate_delay(); /* Get our bogomips */
831#endif
832
833 /* Save our processor parameters */
834 smp_store_cpu_info(cpu);
835
836 /* Allow the boot processor to continue */
837 cpu_set(cpu, cpu_callin_map);
838}
839
840/**
841 * smp_online - Set cpu_online_map
842 */
843static void __init smp_online(void)
844{
845 int cpu;
846
847 cpu = smp_processor_id();
848
849 local_irq_enable();
850
851 cpu_set(cpu, cpu_online_map);
852 smp_wmb();
853}
854
855/**
856 * smp_cpus_done -
857 * @max_cpus: Maximum CPU count.
858 *
859 * Do nothing.
860 */
861void __init smp_cpus_done(unsigned int max_cpus)
862{
863}
864
865/*
866 * smp_prepare_boot_cpu - Set up stuff for the boot processor.
867 *
868 * Set up the cpu_online_map, cpu_callout_map and cpu_callin_map of the boot
869 * processor (CPU 0).
870 */
871void __devinit smp_prepare_boot_cpu(void)
872{
873 cpu_set(0, cpu_callout_map);
874 cpu_set(0, cpu_callin_map);
875 current_thread_info()->cpu = 0;
876}
877
878/*
879 * initialize_secondary - Initialise a secondary CPU (Application Processor).
880 *
881 * Set SP register and jump to thread's PC address.
882 */
883void initialize_secondary(void)
884{
885 asm volatile (
886 "mov %0,sp \n"
887 "jmp (%1) \n"
888 :
889 : "a"(current->thread.sp), "a"(current->thread.pc));
890}
891
892/**
893 * __cpu_up - Set smp_commenced_mask for the nominated CPU
894 * @cpu: The target CPU.
895 */
896int __devinit __cpu_up(unsigned int cpu)
897{
898 int timeout;
899
900#ifdef CONFIG_HOTPLUG_CPU
901 if (num_online_cpus() == 1)
902 disable_hlt();
903 if (sleep_mode[cpu])
904 run_wakeup_cpu(cpu);
905#endif /* CONFIG_HOTPLUG_CPU */
906
907 cpu_set(cpu, smp_commenced_mask);
908
909 /* Wait 5s total for a response */
910 for (timeout = 0 ; timeout < 5000 ; timeout++) {
911 if (cpu_isset(cpu, cpu_online_map))
912 break;
913 udelay(1000);
914 }
915
916 BUG_ON(!cpu_isset(cpu, cpu_online_map));
917 return 0;
918}
919
920/**
921 * setup_profiling_timer - Set up the profiling timer
922 * @multiplier - The frequency multiplier to use
923 *
924 * The frequency of the profiling timer can be changed by writing a multiplier
925 * value into /proc/profile.
926 */
927int setup_profiling_timer(unsigned int multiplier)
928{
929 return -EINVAL;
930}
931
932/*
933 * CPU hotplug routines
934 */
935#ifdef CONFIG_HOTPLUG_CPU
936
937static DEFINE_PER_CPU(struct cpu, cpu_devices);
938
939static int __init topology_init(void)
940{
941 int cpu, ret;
942
943 for_each_cpu(cpu) {
944 ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
945 if (ret)
946 printk(KERN_WARNING
947 "topology_init: register_cpu %d failed (%d)\n",
948 cpu, ret);
949 }
950 return 0;
951}
952
953subsys_initcall(topology_init);
954
955int __cpu_disable(void)
956{
957 int cpu = smp_processor_id();
958 if (cpu == 0)
959 return -EBUSY;
960
961 migrate_irqs();
962 cpu_clear(cpu, current->active_mm->cpu_vm_mask);
963 return 0;
964}
965
966void __cpu_die(unsigned int cpu)
967{
968 run_sleep_cpu(cpu);
969
970 if (num_online_cpus() == 1)
971 enable_hlt();
972}
973
974#ifdef CONFIG_MN10300_CACHE_ENABLED
975static inline void hotplug_cpu_disable_cache(void)
976{
977 int tmp;
978 asm volatile(
979 " movhu (%1),%0 \n"
980 " and %2,%0 \n"
981 " movhu %0,(%1) \n"
982 "1: movhu (%1),%0 \n"
983 " btst %3,%0 \n"
984 " bne 1b \n"
985 : "=&r"(tmp)
986 : "a"(&CHCTR),
987 "i"(~(CHCTR_ICEN | CHCTR_DCEN)),
988 "i"(CHCTR_ICBUSY | CHCTR_DCBUSY)
989 : "memory", "cc");
990}
991
992static inline void hotplug_cpu_enable_cache(void)
993{
994 int tmp;
995 asm volatile(
996 "movhu (%1),%0 \n"
997 "or %2,%0 \n"
998 "movhu %0,(%1) \n"
999 : "=&r"(tmp)
1000 : "a"(&CHCTR),
1001 "i"(CHCTR_ICEN | CHCTR_DCEN)
1002 : "memory", "cc");
1003}
1004
1005static inline void hotplug_cpu_invalidate_cache(void)
1006{
1007 int tmp;
1008 asm volatile (
1009 "movhu (%1),%0 \n"
1010 "or %2,%0 \n"
1011 "movhu %0,(%1) \n"
1012 : "=&r"(tmp)
1013 : "a"(&CHCTR),
1014 "i"(CHCTR_ICINV | CHCTR_DCINV)
1015 : "cc");
1016}
1017
1018#else /* CONFIG_MN10300_CACHE_ENABLED */
1019#define hotplug_cpu_disable_cache() do {} while (0)
1020#define hotplug_cpu_enable_cache() do {} while (0)
1021#define hotplug_cpu_invalidate_cache() do {} while (0)
1022#endif /* CONFIG_MN10300_CACHE_ENABLED */
1023
1024/**
1025 * hotplug_cpu_nmi_call_function - Call a function on other CPUs for hotplug
1026 * @cpumask: List of target CPUs.
1027 * @func: The function to call on those CPUs.
1028 * @info: The context data for the function to be called.
1029 * @wait: Whether to wait for the calls to complete.
1030 *
1031 * Non-maskably call a function on another CPU for hotplug purposes.
1032 *
1033 * This function must be called with maskable interrupts disabled.
1034 */
1035static int hotplug_cpu_nmi_call_function(cpumask_t cpumask,
1036 smp_call_func_t func, void *info,
1037 int wait)
1038{
1039 /*
1040 * The address and the size of nmi_call_func_mask_data
1041 * need to be aligned on L1_CACHE_BYTES.
1042 */
1043 static struct nmi_call_data_struct nmi_call_func_mask_data
1044 __cacheline_aligned;
1045 unsigned long start, end;
1046
1047 start = (unsigned long)&nmi_call_func_mask_data;
1048 end = start + sizeof(struct nmi_call_data_struct);
1049
1050 nmi_call_func_mask_data.func = func;
1051 nmi_call_func_mask_data.info = info;
1052 nmi_call_func_mask_data.started = cpumask;
1053 nmi_call_func_mask_data.wait = wait;
1054 if (wait)
1055 nmi_call_func_mask_data.finished = cpumask;
1056
1057 spin_lock(&smp_nmi_call_lock);
1058 nmi_call_data = &nmi_call_func_mask_data;
1059 mn10300_local_dcache_flush_range(start, end);
1060 smp_wmb();
1061
1062 send_IPI_mask(cpumask, CALL_FUNCTION_NMI_IPI);
1063
1064 do {
1065 mn10300_local_dcache_inv_range(start, end);
1066 barrier();
1067 } while (!cpus_empty(nmi_call_func_mask_data.started));
1068
1069 if (wait) {
1070 do {
1071 mn10300_local_dcache_inv_range(start, end);
1072 barrier();
1073 } while (!cpus_empty(nmi_call_func_mask_data.finished));
1074 }
1075
1076 spin_unlock(&smp_nmi_call_lock);
1077 return 0;
1078}
1079
1080static void restart_wakeup_cpu(void)
1081{
1082 unsigned int cpu = smp_processor_id();
1083
1084 cpu_set(cpu, cpu_callin_map);
1085 local_flush_tlb();
1086 cpu_set(cpu, cpu_online_map);
1087 smp_wmb();
1088}
1089
1090static void prepare_sleep_cpu(void *unused)
1091{
1092 sleep_mode[smp_processor_id()] = 1;
1093 smp_mb();
1094 mn10300_local_dcache_flush_inv();
1095 hotplug_cpu_disable_cache();
1096 hotplug_cpu_invalidate_cache();
1097}
1098
1099/* when this function called, IE=0, NMID=0. */
1100static void sleep_cpu(void *unused)
1101{
1102 unsigned int cpu_id = smp_processor_id();
1103 /*
1104 * CALL_FUNCTION_NMI_IPI for wakeup_cpu() shall not be requested,
1105 * before this cpu goes in SLEEP mode.
1106 */
1107 do {
1108 smp_mb();
1109 __sleep_cpu();
1110 } while (sleep_mode[cpu_id]);
1111 restart_wakeup_cpu();
1112}
1113
1114static void run_sleep_cpu(unsigned int cpu)
1115{
1116 unsigned long flags;
1117 cpumask_t cpumask = cpumask_of(cpu);
1118
1119 flags = arch_local_cli_save();
1120 hotplug_cpu_nmi_call_function(cpumask, prepare_sleep_cpu, NULL, 1);
1121 hotplug_cpu_nmi_call_function(cpumask, sleep_cpu, NULL, 0);
1122 udelay(1); /* delay for the cpu to sleep. */
1123 arch_local_irq_restore(flags);
1124}
1125
1126static void wakeup_cpu(void)
1127{
1128 hotplug_cpu_invalidate_cache();
1129 hotplug_cpu_enable_cache();
1130 smp_mb();
1131 sleep_mode[smp_processor_id()] = 0;
1132}
1133
1134static void run_wakeup_cpu(unsigned int cpu)
1135{
1136 unsigned long flags;
1137
1138 flags = arch_local_cli_save();
1139#if NR_CPUS == 2
1140 mn10300_local_dcache_flush_inv();
1141#else
1142 /*
1143 * Before waking up the cpu,
1144 * all online cpus should stop and flush D-Cache for global data.
1145 */
1146#error not support NR_CPUS > 2, when CONFIG_HOTPLUG_CPU=y.
1147#endif
1148 hotplug_cpu_nmi_call_function(cpumask_of(cpu), wakeup_cpu, NULL, 1);
1149 arch_local_irq_restore(flags);
1150}
1151
1152#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
index 630aad71b946..9074d0fb8788 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,8 +38,6 @@ ENTRY(__switch_to)
35 mov d1,a1 38 mov d1,a1
36 39
37 # save prev context 40 # save prev context
38 mov (__frame),d0
39 mov d0,(THREAD_FRAME,a0)
40 mov __switch_back,d0 41 mov __switch_back,d0
41 mov d0,(THREAD_PC,a0) 42 mov d0,(THREAD_PC,a0)
42 mov sp,a2 43 mov sp,a2
@@ -58,8 +59,6 @@ ENTRY(__switch_to)
58 mov a2,e2 59 mov a2,e2
59#endif 60#endif
60 61
61 mov (THREAD_FRAME,a1),a2
62 mov a2,(__frame)
63 mov (THREAD_PC,a1),a2 62 mov (THREAD_PC,a1),a2
64 mov d2,d0 # for ret_from_fork 63 mov d2,d0 # for ret_from_fork
65 mov d0,a0 # for __switch_to 64 mov d0,a0 # for __switch_to
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c
index 8f7f6d22783d..f860a340acc9 100644
--- a/arch/mn10300/kernel/time.c
+++ b/arch/mn10300/kernel/time.c
@@ -17,29 +17,18 @@
17#include <linux/smp.h> 17#include <linux/smp.h>
18#include <linux/profile.h> 18#include <linux/profile.h>
19#include <linux/cnt32_to_63.h> 19#include <linux/cnt32_to_63.h>
20#include <linux/clocksource.h>
21#include <linux/clockchips.h>
20#include <asm/irq.h> 22#include <asm/irq.h>
21#include <asm/div64.h> 23#include <asm/div64.h>
22#include <asm/processor.h> 24#include <asm/processor.h>
23#include <asm/intctl-regs.h> 25#include <asm/intctl-regs.h>
24#include <asm/rtc.h> 26#include <asm/rtc.h>
25 27#include "internal.h"
26#ifdef CONFIG_MN10300_RTC
27unsigned long mn10300_ioclk; /* system I/O clock frequency */
28unsigned long mn10300_iobclk; /* system I/O clock frequency */
29unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */
30#endif /* CONFIG_MN10300_RTC */
31 28
32static unsigned long mn10300_last_tsc; /* time-stamp counter at last time 29static unsigned long mn10300_last_tsc; /* time-stamp counter at last time
33 * interrupt occurred */ 30 * interrupt occurred */
34 31
35static irqreturn_t timer_interrupt(int irq, void *dev_id);
36
37static struct irqaction timer_irq = {
38 .handler = timer_interrupt,
39 .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
40 .name = "timer",
41};
42
43static unsigned long sched_clock_multiplier; 32static unsigned long sched_clock_multiplier;
44 33
45/* 34/*
@@ -54,9 +43,12 @@ unsigned long long sched_clock(void)
54 unsigned long tsc, tmp; 43 unsigned long tsc, tmp;
55 unsigned product[3]; /* 96-bit intermediate value */ 44 unsigned product[3]; /* 96-bit intermediate value */
56 45
46 /* cnt32_to_63() is not safe with preemption */
47 preempt_disable();
48
57 /* read the TSC value 49 /* read the TSC value
58 */ 50 */
59 tsc = 0 - get_cycles(); /* get_cycles() counts down */ 51 tsc = get_cycles();
60 52
61 /* expand to 64-bits. 53 /* expand to 64-bits.
62 * - sched_clock() must be called once a minute or better or the 54 * - sched_clock() must be called once a minute or better or the
@@ -64,6 +56,8 @@ unsigned long long sched_clock(void)
64 */ 56 */
65 tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; 57 tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
66 58
59 preempt_enable();
60
67 /* scale the 64-bit TSC value to a nanosecond value via a 96-bit 61 /* scale the 64-bit TSC value to a nanosecond value via a 96-bit
68 * intermediate 62 * intermediate
69 */ 63 */
@@ -90,6 +84,20 @@ static void __init mn10300_sched_clock_init(void)
90 __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); 84 __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK);
91} 85}
92 86
87/**
88 * local_timer_interrupt - Local timer interrupt handler
89 *
90 * Handle local timer interrupts for this CPU. They may have been propagated
91 * to this CPU from the CPU that actually gets them by way of an IPI.
92 */
93irqreturn_t local_timer_interrupt(void)
94{
95 profile_tick(CPU_PROFILING);
96 update_process_times(user_mode(get_irq_regs()));
97 return IRQ_HANDLED;
98}
99
100#ifndef CONFIG_GENERIC_TIME
93/* 101/*
94 * advance the kernel's time keeping clocks (xtime and jiffies) 102 * advance the kernel's time keeping clocks (xtime and jiffies)
95 * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time 103 * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
@@ -98,27 +106,73 @@ static void __init mn10300_sched_clock_init(void)
98static irqreturn_t timer_interrupt(int irq, void *dev_id) 106static irqreturn_t timer_interrupt(int irq, void *dev_id)
99{ 107{
100 unsigned tsc, elapse; 108 unsigned tsc, elapse;
109 irqreturn_t ret;
101 110
102 write_seqlock(&xtime_lock); 111 write_seqlock(&xtime_lock);
103 112
104 while (tsc = get_cycles(), 113 while (tsc = get_cycles(),
105 elapse = mn10300_last_tsc - tsc, /* time elapsed since last 114 elapse = tsc - mn10300_last_tsc, /* time elapsed since last
106 * tick */ 115 * tick */
107 elapse > MN10300_TSC_PER_HZ 116 elapse > MN10300_TSC_PER_HZ
108 ) { 117 ) {
109 mn10300_last_tsc -= MN10300_TSC_PER_HZ; 118 mn10300_last_tsc += MN10300_TSC_PER_HZ;
110 119
111 /* advance the kernel's time tracking system */ 120 /* advance the kernel's time tracking system */
112 profile_tick(CPU_PROFILING);
113 do_timer(1); 121 do_timer(1);
114 } 122 }
115 123
116 write_sequnlock(&xtime_lock); 124 write_sequnlock(&xtime_lock);
117 125
118 update_process_times(user_mode(get_irq_regs())); 126 ret = local_timer_interrupt();
127#ifdef CONFIG_SMP
128 send_IPI_allbutself(LOCAL_TIMER_IPI);
129#endif
130 return ret;
131}
119 132
120 return IRQ_HANDLED; 133static struct irqaction timer_irq = {
134 .handler = timer_interrupt,
135 .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
136 .name = "timer",
137};
138#endif /* CONFIG_GENERIC_TIME */
139
140#ifdef CONFIG_CSRC_MN10300
141void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
142{
143 u64 temp;
144 u32 shift;
145
146 /* Find a shift value */
147 for (shift = 32; shift > 0; shift--) {
148 temp = (u64) NSEC_PER_SEC << shift;
149 do_div(temp, clock);
150 if ((temp >> 32) == 0)
151 break;
152 }
153 cs->shift = shift;
154 cs->mult = (u32) temp;
121} 155}
156#endif
157
158#if CONFIG_CEVT_MN10300
159void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
160 unsigned int clock)
161{
162 u64 temp;
163 u32 shift;
164
165 /* Find a shift value */
166 for (shift = 32; shift > 0; shift--) {
167 temp = (u64) clock << shift;
168 do_div(temp, NSEC_PER_SEC);
169 if ((temp >> 32) == 0)
170 break;
171 }
172 cd->shift = shift;
173 cd->mult = (u32) temp;
174}
175#endif
122 176
123/* 177/*
124 * initialise the various timers used by the main part of the kernel 178 * initialise the various timers used by the main part of the kernel
@@ -131,21 +185,25 @@ void __init time_init(void)
131 */ 185 */
132 TMPSCNT |= TMPSCNT_ENABLE; 186 TMPSCNT |= TMPSCNT_ENABLE;
133 187
188#ifdef CONFIG_GENERIC_TIME
189 init_clocksource();
190#else
134 startup_timestamp_counter(); 191 startup_timestamp_counter();
192#endif
135 193
136 printk(KERN_INFO 194 printk(KERN_INFO
137 "timestamp counter I/O clock running at %lu.%02lu" 195 "timestamp counter I/O clock running at %lu.%02lu"
138 " (calibrated against RTC)\n", 196 " (calibrated against RTC)\n",
139 MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); 197 MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100);
140 198
141 mn10300_last_tsc = TMTSCBC; 199 mn10300_last_tsc = read_timestamp_counter();
142
143 /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */
144 setup_irq(TMJCIRQ, &timer_irq);
145 200
146 set_intr_level(TMJCIRQ, TMJCICR_LEVEL); 201#ifdef CONFIG_GENERIC_CLOCKEVENTS
147 202 init_clockevents();
148 startup_jiffies_counter(); 203#else
204 reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
205 setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL);
206#endif
149 207
150#ifdef CONFIG_MN10300_WD_TIMER 208#ifdef CONFIG_MN10300_WD_TIMER
151 /* start the watchdog timer */ 209 /* start the watchdog timer */
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index 91365adba4f5..b90c3f160c77 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -45,9 +45,6 @@
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
48struct pt_regs *__frame; /* current frame pointer */
49EXPORT_SYMBOL(__frame);
50
51int kstack_depth_to_print = 24; 48int kstack_depth_to_print = 24;
52 49
53spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); 50spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
@@ -101,7 +98,6 @@ DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC);
101DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); 98DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
102DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); 99DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
103DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); 100DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
104DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
105 101
106DO_ERROR(SIGTRAP, 102DO_ERROR(SIGTRAP,
107#ifndef CONFIG_MN10300_USING_JTAG 103#ifndef CONFIG_MN10300_USING_JTAG
@@ -222,11 +218,14 @@ void show_registers_only(struct pt_regs *regs)
222 printk(KERN_EMERG "threadinfo=%p task=%p)\n", 218 printk(KERN_EMERG "threadinfo=%p task=%p)\n",
223 current_thread_info(), current); 219 current_thread_info(), current);
224 220
225 if ((unsigned long) current >= 0x90000000UL && 221 if ((unsigned long) current >= PAGE_OFFSET &&
226 (unsigned long) current < 0x94000000UL) 222 (unsigned long) current < (unsigned long)high_memory)
227 printk(KERN_EMERG "Process %s (pid: %d)\n", 223 printk(KERN_EMERG "Process %s (pid: %d)\n",
228 current->comm, current->pid); 224 current->comm, current->pid);
229 225
226#ifdef CONFIG_SMP
227 printk(KERN_EMERG "CPUID: %08x\n", CPUID);
228#endif
230 printk(KERN_EMERG "CPUP: %04hx\n", CPUP); 229 printk(KERN_EMERG "CPUP: %04hx\n", CPUP);
231 printk(KERN_EMERG "TBR: %08x\n", TBR); 230 printk(KERN_EMERG "TBR: %08x\n", TBR);
232 printk(KERN_EMERG "DEAR: %08x\n", DEAR); 231 printk(KERN_EMERG "DEAR: %08x\n", DEAR);
@@ -522,8 +521,12 @@ void __init set_intr_stub(enum exception_code code, void *handler)
522{ 521{
523 unsigned long addr; 522 unsigned long addr;
524 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); 523 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
524 unsigned long flags;
525 525
526 addr = (unsigned long) handler - (unsigned long) vector; 526 addr = (unsigned long) handler - (unsigned long) vector;
527
528 flags = arch_local_cli_save();
529
527 vector[0] = 0xdc; /* JMP handler */ 530 vector[0] = 0xdc; /* JMP handler */
528 vector[1] = addr; 531 vector[1] = addr;
529 vector[2] = addr >> 8; 532 vector[2] = addr >> 8;
@@ -533,30 +536,12 @@ void __init set_intr_stub(enum exception_code code, void *handler)
533 vector[6] = 0xcb; 536 vector[6] = 0xcb;
534 vector[7] = 0xcb; 537 vector[7] = 0xcb;
535 538
536 mn10300_dcache_flush_inv(); 539 arch_local_irq_restore(flags);
537 mn10300_icache_inv();
538}
539
540/*
541 * set an interrupt stub to invoke the JTAG unit and then jump to a handler
542 */
543void __init set_jtag_stub(enum exception_code code, void *handler)
544{
545 unsigned long addr;
546 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
547
548 addr = (unsigned long) handler - ((unsigned long) vector + 1);
549 vector[0] = 0xff; /* PI to jump into JTAG debugger */
550 vector[1] = 0xdc; /* jmp handler */
551 vector[2] = addr;
552 vector[3] = addr >> 8;
553 vector[4] = addr >> 16;
554 vector[5] = addr >> 24;
555 vector[6] = 0xcb;
556 vector[7] = 0xcb;
557 540
541#ifndef CONFIG_MN10300_CACHE_SNOOP
558 mn10300_dcache_flush_inv(); 542 mn10300_dcache_flush_inv();
559 flush_icache_range((unsigned long) vector, (unsigned long) vector + 8); 543 mn10300_icache_inv();
544#endif
560} 545}
561 546
562/* 547/*
@@ -581,7 +566,6 @@ void __init trap_init(void)
581 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); 566 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
582 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); 567 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
583 set_excp_vector(EXCEP_DATINSACC, insn_acc_error); 568 set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
584 set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
585 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); 569 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
586 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); 570 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
587 571
diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c
index 440a7dcbf87b..a66c6cdaf442 100644
--- a/arch/mn10300/lib/bitops.c
+++ b/arch/mn10300/lib/bitops.c
@@ -15,7 +15,7 @@
15/* 15/*
16 * try flipping a bit using BSET and BCLR 16 * try flipping a bit using BSET and BCLR
17 */ 17 */
18void change_bit(int nr, volatile void *addr) 18void change_bit(unsigned long nr, volatile void *addr)
19{ 19{
20 if (test_bit(nr, addr)) 20 if (test_bit(nr, addr))
21 goto try_clear_bit; 21 goto try_clear_bit;
@@ -34,7 +34,7 @@ try_clear_bit:
34/* 34/*
35 * try flipping a bit using BSET and BCLR and returning the old value 35 * try flipping a bit using BSET and BCLR and returning the old value
36 */ 36 */
37int test_and_change_bit(int nr, volatile void *addr) 37int test_and_change_bit(unsigned long nr, volatile void *addr)
38{ 38{
39 if (test_bit(nr, addr)) 39 if (test_bit(nr, addr))
40 goto try_clear_bit; 40 goto try_clear_bit;
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 */
39void __udelay(unsigned long usecs) 39void __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}
51EXPORT_SYMBOL(__udelay); 51EXPORT_SYMBOL(__udelay);
diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S
index e138994e1667..1d27bba0cd8f 100644
--- a/arch/mn10300/lib/do_csum.S
+++ b/arch/mn10300/lib/do_csum.S
@@ -10,26 +10,25 @@
10 */ 10 */
11#include <asm/cache.h> 11#include <asm/cache.h>
12 12
13 .section .text 13 .section .text
14 .balign L1_CACHE_BYTES 14 .balign L1_CACHE_BYTES
15 15
16############################################################################### 16###############################################################################
17# 17#
18# unsigned int do_csum(const unsigned char *buff, size_t len) 18# unsigned int do_csum(const unsigned char *buff, int len)
19# 19#
20############################################################################### 20###############################################################################
21 .globl do_csum 21 .globl do_csum
22 .type do_csum,@function 22 .type do_csum,@function
23do_csum: 23do_csum:
24 movm [d2,d3],(sp) 24 movm [d2,d3],(sp)
25 mov d0,(12,sp)
26 mov d1,(16,sp)
27 mov d1,d2 # count 25 mov d1,d2 # count
28 mov d0,a0 # buff 26 mov d0,a0 # buff
27 mov a0,a1
29 clr d1 # accumulator 28 clr d1 # accumulator
30 29
31 cmp +0,d2 30 cmp +0,d2
32 beq do_csum_done # return if zero-length buffer 31 ble do_csum_done # check for zero length or negative
33 32
34 # 4-byte align the buffer pointer 33 # 4-byte align the buffer pointer
35 btst +3,a0 34 btst +3,a0
@@ -41,17 +40,15 @@ do_csum:
41 inc a0 40 inc a0
42 asl +8,d0 41 asl +8,d0
43 add d0,d1 42 add d0,d1
44 addc +0,d1
45 add -1,d2 43 add -1,d2
46do_csum_addr_not_odd:
47 44
45do_csum_addr_not_odd:
48 cmp +2,d2 46 cmp +2,d2
49 bcs do_csum_fewer_than_4 47 bcs do_csum_fewer_than_4
50 btst +2,a0 48 btst +2,a0
51 beq do_csum_now_4b_aligned 49 beq do_csum_now_4b_aligned
52 movhu (a0+),d0 50 movhu (a0+),d0
53 add d0,d1 51 add d0,d1
54 addc +0,d1
55 add -2,d2 52 add -2,d2
56 cmp +4,d2 53 cmp +4,d2
57 bcs do_csum_fewer_than_4 54 bcs do_csum_fewer_than_4
@@ -66,20 +63,20 @@ do_csum_now_4b_aligned:
66 63
67do_csum_loop: 64do_csum_loop:
68 mov (a0+),d0 65 mov (a0+),d0
69 add d0,d1
70 mov (a0+),e0 66 mov (a0+),e0
71 addc e0,d1
72 mov (a0+),e1 67 mov (a0+),e1
73 addc e1,d1
74 mov (a0+),e3 68 mov (a0+),e3
69 add d0,d1
70 addc e0,d1
71 addc e1,d1
75 addc e3,d1 72 addc e3,d1
76 mov (a0+),d0 73 mov (a0+),d0
77 addc d0,d1
78 mov (a0+),e0 74 mov (a0+),e0
79 addc e0,d1
80 mov (a0+),e1 75 mov (a0+),e1
81 addc e1,d1
82 mov (a0+),e3 76 mov (a0+),e3
77 addc d0,d1
78 addc e0,d1
79 addc e1,d1
83 addc e3,d1 80 addc e3,d1
84 addc +0,d1 81 addc +0,d1
85 82
@@ -94,12 +91,12 @@ do_csum_remainder:
94 cmp +16,d2 91 cmp +16,d2
95 bcs do_csum_fewer_than_16 92 bcs do_csum_fewer_than_16
96 mov (a0+),d0 93 mov (a0+),d0
97 add d0,d1
98 mov (a0+),e0 94 mov (a0+),e0
99 addc e0,d1
100 mov (a0+),e1 95 mov (a0+),e1
101 addc e1,d1
102 mov (a0+),e3 96 mov (a0+),e3
97 add d0,d1
98 addc e0,d1
99 addc e1,d1
103 addc e3,d1 100 addc e3,d1
104 addc +0,d1 101 addc +0,d1
105 add -16,d2 102 add -16,d2
@@ -131,9 +128,9 @@ do_csum_fewer_than_4:
131 xor_cmp d0,d0,+2,d2 128 xor_cmp d0,d0,+2,d2
132 bcs do_csum_fewer_than_2 129 bcs do_csum_fewer_than_2
133 movhu (a0+),d0 130 movhu (a0+),d0
134do_csum_fewer_than_2:
135 and +1,d2 131 and +1,d2
136 beq do_csum_add_last_bit 132 beq do_csum_add_last_bit
133do_csum_fewer_than_2:
137 movbu (a0),d3 134 movbu (a0),d3
138 add d3,d0 135 add d3,d0
139do_csum_add_last_bit: 136do_csum_add_last_bit:
@@ -142,21 +139,19 @@ do_csum_add_last_bit:
142 139
143do_csum_done: 140do_csum_done:
144 # compress the checksum down to 16 bits 141 # compress the checksum down to 16 bits
145 mov +0xffff0000,d2 142 mov +0xffff0000,d0
146 and d1,d2 143 and d1,d0
147 asl +16,d1 144 asl +16,d1
148 add d2,d1,d0 145 add d1,d0
149 addc +0xffff,d0 146 addc +0xffff,d0
150 lsr +16,d0 147 lsr +16,d0
151 148
152 # flip the halves of the word result if the buffer was oddly aligned 149 # flip the halves of the word result if the buffer was oddly aligned
153 mov (12,sp),d1 150 and +1,a1
154 and +1,d1
155 beq do_csum_not_oddly_aligned 151 beq do_csum_not_oddly_aligned
156 swaph d0,d0 # exchange bits 15:8 with 7:0 152 swaph d0,d0 # exchange bits 15:8 with 7:0
157 153
158do_csum_not_oddly_aligned: 154do_csum_not_oddly_aligned:
159 ret [d2,d3],8 155 ret [d2,d3],8
160 156
161do_csum_end: 157 .size do_csum, .-do_csum
162 .size do_csum, do_csum_end-do_csum
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache
new file mode 100644
index 000000000000..c4fd923a55a0
--- /dev/null
+++ b/arch/mn10300/mm/Kconfig.cache
@@ -0,0 +1,101 @@
1#
2# MN10300 CPU cache options
3#
4
5choice
6 prompt "CPU Caching mode"
7 default MN10300_CACHE_WBACK
8 help
9 This option determines the caching mode for the kernel.
10
11 Write-Back caching mode involves the all reads and writes causing
12 the affected cacheline to be read into the cache first before being
13 operated upon. Memory is not then updated by a write until the cache
14 is filled and a cacheline needs to be displaced from the cache to
15 make room. Only at that point is it written back.
16
17 Write-Through caching only fetches cachelines from memory on a
18 read. Writes always get written directly to memory. If the affected
19 cacheline is also in cache, it will be updated too.
20
21 The final option is to turn of caching entirely.
22
23config MN10300_CACHE_WBACK
24 bool "Write-Back"
25 help
26 The dcache operates in delayed write-back mode. It must be manually
27 flushed if writes are made that subsequently need to be executed or
28 to be DMA'd by a device.
29
30config MN10300_CACHE_WTHRU
31 bool "Write-Through"
32 help
33 The dcache operates in immediate write-through mode. Writes are
34 committed to RAM immediately in addition to being stored in the
35 cache. This means that the written data is immediately available for
36 execution or DMA.
37
38 This is not available for use with an SMP kernel if cache flushing
39 and invalidation by automatic purge register is not selected.
40
41config MN10300_CACHE_DISABLED
42 bool "Disabled"
43 help
44 The icache and dcache are disabled.
45
46endchoice
47
48config MN10300_CACHE_ENABLED
49 def_bool y if !MN10300_CACHE_DISABLED
50
51
52choice
53 prompt "CPU cache flush/invalidate method"
54 default MN10300_CACHE_MANAGE_BY_TAG if !AM34_2
55 default MN10300_CACHE_MANAGE_BY_REG if AM34_2
56 depends on MN10300_CACHE_ENABLED
57 help
58 This determines the method by which CPU cache flushing and
59 invalidation is performed.
60
61config MN10300_CACHE_MANAGE_BY_TAG
62 bool "Use the cache tag registers directly"
63 depends on !(SMP && MN10300_CACHE_WTHRU)
64
65config MN10300_CACHE_MANAGE_BY_REG
66 bool "Flush areas by way of automatic purge registers (AM34 only)"
67 depends on AM34_2
68
69endchoice
70
71config MN10300_CACHE_INV_BY_TAG
72 def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED
73
74config MN10300_CACHE_INV_BY_REG
75 def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED
76
77config MN10300_CACHE_FLUSH_BY_TAG
78 def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK
79
80config MN10300_CACHE_FLUSH_BY_REG
81 def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK
82
83
84config MN10300_HAS_CACHE_SNOOP
85 def_bool n
86
87config MN10300_CACHE_SNOOP
88 bool "Use CPU Cache Snooping"
89 depends on MN10300_CACHE_ENABLED && MN10300_HAS_CACHE_SNOOP
90 default y
91
92config MN10300_CACHE_FLUSH_ICACHE
93 def_bool y if MN10300_CACHE_WBACK && !MN10300_CACHE_SNOOP
94 help
95 Set if we need the dcache flushing before the icache is invalidated.
96
97config MN10300_CACHE_INV_ICACHE
98 def_bool y if MN10300_CACHE_WTHRU && !MN10300_CACHE_SNOOP
99 help
100 Set if we need the icache to be invalidated, even if the dcache is in
101 write-through mode and doesn't need flushing.
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
index 1557277fbc5c..203fee23f7d7 100644
--- a/arch/mn10300/mm/Makefile
+++ b/arch/mn10300/mm/Makefile
@@ -2,11 +2,21 @@
2# Makefile for the MN10300-specific memory management code 2# Makefile for the MN10300-specific memory management code
3# 3#
4 4
5cacheflush-y := cache.o cache-mn10300.o 5cache-smp-wback-$(CONFIG_MN10300_CACHE_WBACK) := cache-smp-flush.o
6cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o 6
7cacheflush-y := cache.o
8cacheflush-$(CONFIG_SMP) += cache-smp.o cache-smp-inv.o $(cache-smp-wback-y)
9cacheflush-$(CONFIG_MN10300_CACHE_INV_ICACHE) += cache-inv-icache.o
10cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_ICACHE) += cache-flush-icache.o
11cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o
12cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
13cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
14cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
7 15
8cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o 16cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
9 17
10obj-y := \ 18obj-y := \
11 init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \ 19 init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
12 misalignment.o dma-alloc.o $(cacheflush-y) 20 misalignment.o dma-alloc.o $(cacheflush-y)
21
22obj-$(CONFIG_SMP) += tlb-smp.o
diff --git a/arch/mn10300/mm/cache-flush-by-reg.S b/arch/mn10300/mm/cache-flush-by-reg.S
new file mode 100644
index 000000000000..1dcae0211671
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-by-reg.S
@@ -0,0 +1,308 @@
1/* MN10300 CPU core caching routines, using indirect regs on cache controller
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <asm/smp.h>
15#include <asm/page.h>
16#include <asm/cache.h>
17#include <asm/irqflags.h>
18
19 .am33_2
20
21#ifndef CONFIG_SMP
22 .globl mn10300_dcache_flush
23 .globl mn10300_dcache_flush_page
24 .globl mn10300_dcache_flush_range
25 .globl mn10300_dcache_flush_range2
26 .globl mn10300_dcache_flush_inv
27 .globl mn10300_dcache_flush_inv_page
28 .globl mn10300_dcache_flush_inv_range
29 .globl mn10300_dcache_flush_inv_range2
30
31mn10300_dcache_flush = mn10300_local_dcache_flush
32mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
33mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
34mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
35mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
36mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
37mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
38mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2
39
40#endif /* !CONFIG_SMP */
41
42###############################################################################
43#
44# void mn10300_local_dcache_flush(void)
45# Flush the entire data cache back to RAM
46#
47###############################################################################
48 ALIGN
49 .globl mn10300_local_dcache_flush
50 .type mn10300_local_dcache_flush,@function
51mn10300_local_dcache_flush:
52 movhu (CHCTR),d0
53 btst CHCTR_DCEN,d0
54 beq mn10300_local_dcache_flush_end
55
56 mov DCPGCR,a0
57
58 LOCAL_CLI_SAVE(d1)
59
60 # wait for busy bit of area purge
61 setlb
62 mov (a0),d0
63 btst DCPGCR_DCPGBSY,d0
64 lne
65
66 # set mask
67 clr d0
68 mov d0,(DCPGMR)
69
70 # area purge
71 #
72 # DCPGCR = DCPGCR_DCP
73 #
74 mov DCPGCR_DCP,d0
75 mov d0,(a0)
76
77 # wait for busy bit of area purge
78 setlb
79 mov (a0),d0
80 btst DCPGCR_DCPGBSY,d0
81 lne
82
83 LOCAL_IRQ_RESTORE(d1)
84
85mn10300_local_dcache_flush_end:
86 ret [],0
87 .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
88
89###############################################################################
90#
91# void mn10300_local_dcache_flush_page(unsigned long start)
92# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
93# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
94# Flush a range of addresses on a page in the dcache
95#
96###############################################################################
97 ALIGN
98 .globl mn10300_local_dcache_flush_page
99 .globl mn10300_local_dcache_flush_range
100 .globl mn10300_local_dcache_flush_range2
101 .type mn10300_local_dcache_flush_page,@function
102 .type mn10300_local_dcache_flush_range,@function
103 .type mn10300_local_dcache_flush_range2,@function
104mn10300_local_dcache_flush_page:
105 and ~(PAGE_SIZE-1),d0
106 mov PAGE_SIZE,d1
107mn10300_local_dcache_flush_range2:
108 add d0,d1
109mn10300_local_dcache_flush_range:
110 movm [d2,d3,a2],(sp)
111
112 movhu (CHCTR),d2
113 btst CHCTR_DCEN,d2
114 beq mn10300_local_dcache_flush_range_end
115
116 # calculate alignsize
117 #
118 # alignsize = L1_CACHE_BYTES;
119 # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1)
120 # alignsize <<= 1;
121 # d2 = alignsize;
122 #
123 mov L1_CACHE_BYTES,d2
124 sub d0,d1,d3
125 add -1,d3
126 lsr L1_CACHE_SHIFT,d3
127 beq 2f
1281:
129 add d2,d2
130 lsr 1,d3
131 bne 1b
1322:
133 mov d1,a1 # a1 = end
134
135 LOCAL_CLI_SAVE(d3)
136 mov DCPGCR,a0
137
138 # wait for busy bit of area purge
139 setlb
140 mov (a0),d1
141 btst DCPGCR_DCPGBSY,d1
142 lne
143
144 # determine the mask
145 mov d2,d1
146 add -1,d1
147 not d1 # d1 = mask = ~(alignsize-1)
148 mov d1,(DCPGMR)
149
150 and d1,d0,a2 # a2 = mask & start
151
152dcpgloop:
153 # area purge
154 mov a2,d0
155 or DCPGCR_DCP,d0
156 mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP
157
158 # wait for busy bit of area purge
159 setlb
160 mov (a0),d1
161 btst DCPGCR_DCPGBSY,d1
162 lne
163
164 # check purge of end address
165 add d2,a2 # a2 += alignsize
166 cmp a1,a2 # if (a2 < end) goto dcpgloop
167 bns dcpgloop
168
169 LOCAL_IRQ_RESTORE(d3)
170
171mn10300_local_dcache_flush_range_end:
172 ret [d2,d3,a2],12
173
174 .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
175 .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
176 .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
177
178###############################################################################
179#
180# void mn10300_local_dcache_flush_inv(void)
181# Flush the entire data cache and invalidate all entries
182#
183###############################################################################
184 ALIGN
185 .globl mn10300_local_dcache_flush_inv
186 .type mn10300_local_dcache_flush_inv,@function
187mn10300_local_dcache_flush_inv:
188 movhu (CHCTR),d0
189 btst CHCTR_DCEN,d0
190 beq mn10300_local_dcache_flush_inv_end
191
192 mov DCPGCR,a0
193
194 LOCAL_CLI_SAVE(d1)
195
196 # wait for busy bit of area purge & invalidate
197 setlb
198 mov (a0),d0
199 btst DCPGCR_DCPGBSY,d0
200 lne
201
202 # set the mask to cover everything
203 clr d0
204 mov d0,(DCPGMR)
205
206 # area purge & invalidate
207 mov DCPGCR_DCP|DCPGCR_DCI,d0
208 mov d0,(a0)
209
210 # wait for busy bit of area purge & invalidate
211 setlb
212 mov (a0),d0
213 btst DCPGCR_DCPGBSY,d0
214 lne
215
216 LOCAL_IRQ_RESTORE(d1)
217
218mn10300_local_dcache_flush_inv_end:
219 ret [],0
220 .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
221
222###############################################################################
223#
224# void mn10300_local_dcache_flush_inv_page(unsigned long start)
225# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
226# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
227# Flush and invalidate a range of addresses on a page in the dcache
228#
229###############################################################################
230 ALIGN
231 .globl mn10300_local_dcache_flush_inv_page
232 .globl mn10300_local_dcache_flush_inv_range
233 .globl mn10300_local_dcache_flush_inv_range2
234 .type mn10300_local_dcache_flush_inv_page,@function
235 .type mn10300_local_dcache_flush_inv_range,@function
236 .type mn10300_local_dcache_flush_inv_range2,@function
237mn10300_local_dcache_flush_inv_page:
238 and ~(PAGE_SIZE-1),d0
239 mov PAGE_SIZE,d1
240mn10300_local_dcache_flush_inv_range2:
241 add d0,d1
242mn10300_local_dcache_flush_inv_range:
243 movm [d2,d3,a2],(sp)
244
245 movhu (CHCTR),d2
246 btst CHCTR_DCEN,d2
247 beq mn10300_local_dcache_flush_inv_range_end
248
249 # calculate alignsize
250 #
251 # alignsize = L1_CACHE_BYTES;
252 # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
253 # alignsize <<= 1;
254 # d2 = alignsize
255 #
256 mov L1_CACHE_BYTES,d2
257 sub d0,d1,d3
258 add -1,d3
259 lsr L1_CACHE_SHIFT,d3
260 beq 2f
2611:
262 add d2,d2
263 lsr 1,d3
264 bne 1b
2652:
266 mov d1,a1 # a1 = end
267
268 LOCAL_CLI_SAVE(d3)
269 mov DCPGCR,a0
270
271 # wait for busy bit of area purge & invalidate
272 setlb
273 mov (a0),d1
274 btst DCPGCR_DCPGBSY,d1
275 lne
276
277 # set the mask
278 mov d2,d1
279 add -1,d1
280 not d1 # d1 = mask = ~(alignsize-1)
281 mov d1,(DCPGMR)
282
283 and d1,d0,a2 # a2 = mask & start
284
285dcpgivloop:
286 # area purge & invalidate
287 mov a2,d0
288 or DCPGCR_DCP|DCPGCR_DCI,d0
289 mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
290
291 # wait for busy bit of area purge & invalidate
292 setlb
293 mov (a0),d1
294 btst DCPGCR_DCPGBSY,d1
295 lne
296
297 # check purge & invalidate of end address
298 add d2,a2 # a2 += alignsize
299 cmp a1,a2 # if (a2 < end) goto dcpgivloop
300 bns dcpgivloop
301
302 LOCAL_IRQ_RESTORE(d3)
303
304mn10300_local_dcache_flush_inv_range_end:
305 ret [d2,d3,a2],12
306 .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
307 .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
308 .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S
new file mode 100644
index 000000000000..5cd6a27dd63e
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-by-tag.S
@@ -0,0 +1,251 @@
1/* MN10300 CPU core caching routines, using direct tag flushing
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <asm/smp.h>
15#include <asm/page.h>
16#include <asm/cache.h>
17#include <asm/irqflags.h>
18
19 .am33_2
20
21#ifndef CONFIG_SMP
22 .globl mn10300_dcache_flush
23 .globl mn10300_dcache_flush_page
24 .globl mn10300_dcache_flush_range
25 .globl mn10300_dcache_flush_range2
26 .globl mn10300_dcache_flush_inv
27 .globl mn10300_dcache_flush_inv_page
28 .globl mn10300_dcache_flush_inv_range
29 .globl mn10300_dcache_flush_inv_range2
30
31mn10300_dcache_flush = mn10300_local_dcache_flush
32mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
33mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
34mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
35mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
36mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
37mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
38mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2
39
40#endif /* !CONFIG_SMP */
41
42###############################################################################
43#
44# void mn10300_local_dcache_flush(void)
45# Flush the entire data cache back to RAM
46#
47###############################################################################
48 ALIGN
49 .globl mn10300_local_dcache_flush
50 .type mn10300_local_dcache_flush,@function
51mn10300_local_dcache_flush:
52 movhu (CHCTR),d0
53 btst CHCTR_DCEN,d0
54 beq mn10300_local_dcache_flush_end
55
56 # read the addresses tagged in the cache's tag RAM and attempt to flush
57 # those addresses specifically
58 # - we rely on the hardware to filter out invalid tag entry addresses
59 mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
60 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
61 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
62
63mn10300_local_dcache_flush_loop:
64 mov (a0),d0
65 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
66 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
67 # cache
68 mov d0,(a1) # conditional purge
69
70 add L1_CACHE_BYTES,a0
71 add L1_CACHE_BYTES,a1
72 add -1,d1
73 bne mn10300_local_dcache_flush_loop
74
75mn10300_local_dcache_flush_end:
76 ret [],0
77 .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
78
79###############################################################################
80#
81# void mn10300_local_dcache_flush_page(unsigned long start)
82# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
83# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
84# Flush a range of addresses on a page in the dcache
85#
86###############################################################################
87 ALIGN
88 .globl mn10300_local_dcache_flush_page
89 .globl mn10300_local_dcache_flush_range
90 .globl mn10300_local_dcache_flush_range2
91 .type mn10300_local_dcache_flush_page,@function
92 .type mn10300_local_dcache_flush_range,@function
93 .type mn10300_local_dcache_flush_range2,@function
94mn10300_local_dcache_flush_page:
95 and ~(PAGE_SIZE-1),d0
96 mov PAGE_SIZE,d1
97mn10300_local_dcache_flush_range2:
98 add d0,d1
99mn10300_local_dcache_flush_range:
100 movm [d2],(sp)
101
102 movhu (CHCTR),d2
103 btst CHCTR_DCEN,d2
104 beq mn10300_local_dcache_flush_range_end
105
106 sub d0,d1,a0
107 cmp MN10300_DCACHE_FLUSH_BORDER,a0
108 ble 1f
109
110 movm (sp),[d2]
111 bra mn10300_local_dcache_flush
1121:
113
114 # round start addr down
115 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
116 mov d0,a1
117
118 add L1_CACHE_BYTES,d1 # round end addr up
119 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
120
121 # write a request to flush all instances of an address from the cache
122 mov DCACHE_PURGE(0,0),a0
123 mov a1,d0
124 and L1_CACHE_TAG_ENTRY,d0
125 add d0,a0 # starting dcache purge control
126 # reg address
127
128 sub a1,d1
129 lsr L1_CACHE_SHIFT,d1 # total number of entries to
130 # examine
131
132 or L1_CACHE_TAG_VALID,a1 # retain valid entries in the
133 # cache
134
135mn10300_local_dcache_flush_range_loop:
136 mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
137 # all ways
138
139 add L1_CACHE_BYTES,a0
140 add L1_CACHE_BYTES,a1
141 and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
142 add -1,d1
143 bne mn10300_local_dcache_flush_range_loop
144
145mn10300_local_dcache_flush_range_end:
146 ret [d2],4
147
148 .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
149 .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
150 .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
151
152###############################################################################
153#
154# void mn10300_local_dcache_flush_inv(void)
155# Flush the entire data cache and invalidate all entries
156#
157###############################################################################
158 ALIGN
159 .globl mn10300_local_dcache_flush_inv
160 .type mn10300_local_dcache_flush_inv,@function
161mn10300_local_dcache_flush_inv:
162 movhu (CHCTR),d0
163 btst CHCTR_DCEN,d0
164 beq mn10300_local_dcache_flush_inv_end
165
166 mov L1_CACHE_NENTRIES,d1
167 clr a1
168
169mn10300_local_dcache_flush_inv_loop:
170 mov (DCACHE_PURGE_WAY0(0),a1),d0 # unconditional purge
171 mov (DCACHE_PURGE_WAY1(0),a1),d0 # unconditional purge
172 mov (DCACHE_PURGE_WAY2(0),a1),d0 # unconditional purge
173 mov (DCACHE_PURGE_WAY3(0),a1),d0 # unconditional purge
174
175 add L1_CACHE_BYTES,a1
176 add -1,d1
177 bne mn10300_local_dcache_flush_inv_loop
178
179mn10300_local_dcache_flush_inv_end:
180 ret [],0
181 .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
182
183###############################################################################
184#
185# void mn10300_local_dcache_flush_inv_page(unsigned long start)
186# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
187# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
188# Flush and invalidate a range of addresses on a page in the dcache
189#
190###############################################################################
191 ALIGN
192 .globl mn10300_local_dcache_flush_inv_page
193 .globl mn10300_local_dcache_flush_inv_range
194 .globl mn10300_local_dcache_flush_inv_range2
195 .type mn10300_local_dcache_flush_inv_page,@function
196 .type mn10300_local_dcache_flush_inv_range,@function
197 .type mn10300_local_dcache_flush_inv_range2,@function
198mn10300_local_dcache_flush_inv_page:
199 and ~(PAGE_SIZE-1),d0
200 mov PAGE_SIZE,d1
201mn10300_local_dcache_flush_inv_range2:
202 add d0,d1
203mn10300_local_dcache_flush_inv_range:
204 movm [d2],(sp)
205
206 movhu (CHCTR),d2
207 btst CHCTR_DCEN,d2
208 beq mn10300_local_dcache_flush_inv_range_end
209
210 sub d0,d1,a0
211 cmp MN10300_DCACHE_FLUSH_INV_BORDER,a0
212 ble 1f
213
214 movm (sp),[d2]
215 bra mn10300_local_dcache_flush_inv
2161:
217
218 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
219 # addr down
220 mov d0,a1
221
222 add L1_CACHE_BYTES,d1 # round end addr up
223 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
224
225 # write a request to flush and invalidate all instances of an address
226 # from the cache
227 mov DCACHE_PURGE(0,0),a0
228 mov a1,d0
229 and L1_CACHE_TAG_ENTRY,d0
230 add d0,a0 # starting dcache purge control
231 # reg address
232
233 sub a1,d1
234 lsr L1_CACHE_SHIFT,d1 # total number of entries to
235 # examine
236
237mn10300_local_dcache_flush_inv_range_loop:
238 mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
239 # in all ways
240
241 add L1_CACHE_BYTES,a0
242 add L1_CACHE_BYTES,a1
243 and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
244 add -1,d1
245 bne mn10300_local_dcache_flush_inv_range_loop
246
247mn10300_local_dcache_flush_inv_range_end:
248 ret [d2],4
249 .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
250 .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
251 .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c
new file mode 100644
index 000000000000..fdb1a9db20f0
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-icache.c
@@ -0,0 +1,155 @@
1/* Flush dcache and invalidate icache when the dcache is in writeback mode
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/mm.h>
13#include <asm/cacheflush.h>
14#include <asm/smp.h>
15#include "cache-smp.h"
16
17/**
18 * flush_icache_page - Flush a page from the dcache and invalidate the icache
19 * @vma: The VMA the page is part of.
20 * @page: The page to be flushed.
21 *
22 * Write a page back from the dcache and invalidate the icache so that we can
23 * run code from it that we've just written into it
24 */
25void flush_icache_page(struct vm_area_struct *vma, struct page *page)
26{
27 unsigned long start = page_to_phys(page);
28 unsigned long flags;
29
30 flags = smp_lock_cache();
31
32 mn10300_local_dcache_flush_page(start);
33 mn10300_local_icache_inv_page(start);
34
35 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE);
36 smp_unlock_cache(flags);
37}
38EXPORT_SYMBOL(flush_icache_page);
39
40/**
41 * flush_icache_page_range - Flush dcache and invalidate icache for part of a
42 * single page
43 * @start: The starting virtual address of the page part.
44 * @end: The ending virtual address of the page part.
45 *
46 * Flush the dcache and invalidate the icache for part of a single page, as
47 * determined by the virtual addresses given. The page must be in the paged
48 * area.
49 */
50static void flush_icache_page_range(unsigned long start, unsigned long end)
51{
52 unsigned long addr, size, off;
53 struct page *page;
54 pgd_t *pgd;
55 pud_t *pud;
56 pmd_t *pmd;
57 pte_t *ppte, pte;
58
59 /* work out how much of the page to flush */
60 off = start & ~PAGE_MASK;
61 size = end - start;
62
63 /* get the physical address the page is mapped to from the page
64 * tables */
65 pgd = pgd_offset(current->mm, start);
66 if (!pgd || !pgd_val(*pgd))
67 return;
68
69 pud = pud_offset(pgd, start);
70 if (!pud || !pud_val(*pud))
71 return;
72
73 pmd = pmd_offset(pud, start);
74 if (!pmd || !pmd_val(*pmd))
75 return;
76
77 ppte = pte_offset_map(pmd, start);
78 if (!ppte)
79 return;
80 pte = *ppte;
81 pte_unmap(ppte);
82
83 if (pte_none(pte))
84 return;
85
86 page = pte_page(pte);
87 if (!page)
88 return;
89
90 addr = page_to_phys(page);
91
92 /* flush the dcache and invalidate the icache coverage on that
93 * region */
94 mn10300_local_dcache_flush_range2(addr + off, size);
95 mn10300_local_icache_inv_range2(addr + off, size);
96 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end);
97}
98
99/**
100 * flush_icache_range - Globally flush dcache and invalidate icache for region
101 * @start: The starting virtual address of the region.
102 * @end: The ending virtual address of the region.
103 *
104 * This is used by the kernel to globally flush some code it has just written
105 * from the dcache back to RAM and then to globally invalidate the icache over
106 * that region so that that code can be run on all CPUs in the system.
107 */
108void flush_icache_range(unsigned long start, unsigned long end)
109{
110 unsigned long start_page, end_page;
111 unsigned long flags;
112
113 flags = smp_lock_cache();
114
115 if (end > 0x80000000UL) {
116 /* addresses above 0xa0000000 do not go through the cache */
117 if (end > 0xa0000000UL) {
118 end = 0xa0000000UL;
119 if (start >= end)
120 goto done;
121 }
122
123 /* kernel addresses between 0x80000000 and 0x9fffffff do not
124 * require page tables, so we just map such addresses
125 * directly */
126 start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
127 mn10300_local_dcache_flush_range(start_page, end);
128 mn10300_local_icache_inv_range(start_page, end);
129 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end);
130 if (start_page == start)
131 goto done;
132 end = start_page;
133 }
134
135 start_page = start & PAGE_MASK;
136 end_page = (end - 1) & PAGE_MASK;
137
138 if (start_page == end_page) {
139 /* the first and last bytes are on the same page */
140 flush_icache_page_range(start, end);
141 } else if (start_page + 1 == end_page) {
142 /* split over two virtually contiguous pages */
143 flush_icache_page_range(start, end_page);
144 flush_icache_page_range(end_page, end);
145 } else {
146 /* more than 2 pages; just flush the entire cache */
147 mn10300_dcache_flush();
148 mn10300_icache_inv();
149 smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0);
150 }
151
152done:
153 smp_unlock_cache(flags);
154}
155EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-flush-mn10300.S b/arch/mn10300/mm/cache-flush-mn10300.S
deleted file mode 100644
index c8ed1cbac107..000000000000
--- a/arch/mn10300/mm/cache-flush-mn10300.S
+++ /dev/null
@@ -1,192 +0,0 @@
1/* MN10300 CPU core caching routines
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <asm/smp.h>
15#include <asm/page.h>
16#include <asm/cache.h>
17
18 .am33_2
19 .globl mn10300_dcache_flush
20 .globl mn10300_dcache_flush_page
21 .globl mn10300_dcache_flush_range
22 .globl mn10300_dcache_flush_range2
23 .globl mn10300_dcache_flush_inv
24 .globl mn10300_dcache_flush_inv_page
25 .globl mn10300_dcache_flush_inv_range
26 .globl mn10300_dcache_flush_inv_range2
27
28###############################################################################
29#
30# void mn10300_dcache_flush(void)
31# Flush the entire data cache back to RAM
32#
33###############################################################################
34 ALIGN
35mn10300_dcache_flush:
36 movhu (CHCTR),d0
37 btst CHCTR_DCEN,d0
38 beq mn10300_dcache_flush_end
39
40 # read the addresses tagged in the cache's tag RAM and attempt to flush
41 # those addresses specifically
42 # - we rely on the hardware to filter out invalid tag entry addresses
43 mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
44 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
45 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
46
47mn10300_dcache_flush_loop:
48 mov (a0),d0
49 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
50 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
51 # cache
52 mov d0,(a1) # conditional purge
53
54mn10300_dcache_flush_skip:
55 add L1_CACHE_BYTES,a0
56 add L1_CACHE_BYTES,a1
57 add -1,d1
58 bne mn10300_dcache_flush_loop
59
60mn10300_dcache_flush_end:
61 ret [],0
62
63###############################################################################
64#
65# void mn10300_dcache_flush_page(unsigned start)
66# void mn10300_dcache_flush_range(unsigned start, unsigned end)
67# void mn10300_dcache_flush_range2(unsigned start, unsigned size)
68# Flush a range of addresses on a page in the dcache
69#
70###############################################################################
71 ALIGN
72mn10300_dcache_flush_page:
73 mov PAGE_SIZE,d1
74mn10300_dcache_flush_range2:
75 add d0,d1
76mn10300_dcache_flush_range:
77 movm [d2,d3],(sp)
78
79 movhu (CHCTR),d2
80 btst CHCTR_DCEN,d2
81 beq mn10300_dcache_flush_range_end
82
83 # round start addr down
84 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
85 mov d0,a1
86
87 add L1_CACHE_BYTES,d1 # round end addr up
88 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
89
90 # write a request to flush all instances of an address from the cache
91 mov DCACHE_PURGE(0,0),a0
92 mov a1,d0
93 and L1_CACHE_TAG_ENTRY,d0
94 add d0,a0 # starting dcache purge control
95 # reg address
96
97 sub a1,d1
98 lsr L1_CACHE_SHIFT,d1 # total number of entries to
99 # examine
100
101 or L1_CACHE_TAG_VALID,a1 # retain valid entries in the
102 # cache
103
104mn10300_dcache_flush_range_loop:
105 mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
106 # all ways
107
108 add L1_CACHE_BYTES,a0
109 add L1_CACHE_BYTES,a1
110 and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
111 add -1,d1
112 bne mn10300_dcache_flush_range_loop
113
114mn10300_dcache_flush_range_end:
115 ret [d2,d3],8
116
117###############################################################################
118#
119# void mn10300_dcache_flush_inv(void)
120# Flush the entire data cache and invalidate all entries
121#
122###############################################################################
123 ALIGN
124mn10300_dcache_flush_inv:
125 movhu (CHCTR),d0
126 btst CHCTR_DCEN,d0
127 beq mn10300_dcache_flush_inv_end
128
129 # hit each line in the dcache with an unconditional purge
130 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
131 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
132
133mn10300_dcache_flush_inv_loop:
134 mov (a1),d0 # unconditional purge
135
136 add L1_CACHE_BYTES,a1
137 add -1,d1
138 bne mn10300_dcache_flush_inv_loop
139
140mn10300_dcache_flush_inv_end:
141 ret [],0
142
143###############################################################################
144#
145# void mn10300_dcache_flush_inv_page(unsigned start)
146# void mn10300_dcache_flush_inv_range(unsigned start, unsigned end)
147# void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size)
148# Flush and invalidate a range of addresses on a page in the dcache
149#
150###############################################################################
151 ALIGN
152mn10300_dcache_flush_inv_page:
153 mov PAGE_SIZE,d1
154mn10300_dcache_flush_inv_range2:
155 add d0,d1
156mn10300_dcache_flush_inv_range:
157 movm [d2,d3],(sp)
158 movhu (CHCTR),d2
159 btst CHCTR_DCEN,d2
160 beq mn10300_dcache_flush_inv_range_end
161
162 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
163 # addr down
164 mov d0,a1
165
166 add L1_CACHE_BYTES,d1 # round end addr up
167 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
168
169 # write a request to flush and invalidate all instances of an address
170 # from the cache
171 mov DCACHE_PURGE(0,0),a0
172 mov a1,d0
173 and L1_CACHE_TAG_ENTRY,d0
174 add d0,a0 # starting dcache purge control
175 # reg address
176
177 sub a1,d1
178 lsr L1_CACHE_SHIFT,d1 # total number of entries to
179 # examine
180
181mn10300_dcache_flush_inv_range_loop:
182 mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
183 # in all ways
184
185 add L1_CACHE_BYTES,a0
186 add L1_CACHE_BYTES,a1
187 and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
188 add -1,d1
189 bne mn10300_dcache_flush_inv_range_loop
190
191mn10300_dcache_flush_inv_range_end:
192 ret [d2,d3],8
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S
new file mode 100644
index 000000000000..c8950861ed77
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-by-reg.S
@@ -0,0 +1,356 @@
1/* MN10300 CPU cache invalidation routines, using automatic purge registers
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18
19#define mn10300_local_dcache_inv_range_intr_interval \
20 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
21
22#if mn10300_local_dcache_inv_range_intr_interval > 0xff
23#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
24#endif
25
26 .am33_2
27
28#ifndef CONFIG_SMP
29 .globl mn10300_icache_inv
30 .globl mn10300_icache_inv_page
31 .globl mn10300_icache_inv_range
32 .globl mn10300_icache_inv_range2
33 .globl mn10300_dcache_inv
34 .globl mn10300_dcache_inv_page
35 .globl mn10300_dcache_inv_range
36 .globl mn10300_dcache_inv_range2
37
38mn10300_icache_inv = mn10300_local_icache_inv
39mn10300_icache_inv_page = mn10300_local_icache_inv_page
40mn10300_icache_inv_range = mn10300_local_icache_inv_range
41mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
42mn10300_dcache_inv = mn10300_local_dcache_inv
43mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
44mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
45mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
46
47#endif /* !CONFIG_SMP */
48
49###############################################################################
50#
51# void mn10300_local_icache_inv(void)
52# Invalidate the entire icache
53#
54###############################################################################
55 ALIGN
56 .globl mn10300_local_icache_inv
57 .type mn10300_local_icache_inv,@function
58mn10300_local_icache_inv:
59 mov CHCTR,a0
60
61 movhu (a0),d0
62 btst CHCTR_ICEN,d0
63 beq mn10300_local_icache_inv_end
64
65 # invalidate
66 or CHCTR_ICINV,d0
67 movhu d0,(a0)
68 movhu (a0),d0
69
70mn10300_local_icache_inv_end:
71 ret [],0
72 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
73
74###############################################################################
75#
76# void mn10300_local_dcache_inv(void)
77# Invalidate the entire dcache
78#
79###############################################################################
80 ALIGN
81 .globl mn10300_local_dcache_inv
82 .type mn10300_local_dcache_inv,@function
83mn10300_local_dcache_inv:
84 mov CHCTR,a0
85
86 movhu (a0),d0
87 btst CHCTR_DCEN,d0
88 beq mn10300_local_dcache_inv_end
89
90 # invalidate
91 or CHCTR_DCINV,d0
92 movhu d0,(a0)
93 movhu (a0),d0
94
95mn10300_local_dcache_inv_end:
96 ret [],0
97 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
98
99###############################################################################
100#
101# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
102# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
103# void mn10300_local_dcache_inv_page(unsigned long start)
104# Invalidate a range of addresses on a page in the dcache
105#
106###############################################################################
107 ALIGN
108 .globl mn10300_local_dcache_inv_page
109 .globl mn10300_local_dcache_inv_range
110 .globl mn10300_local_dcache_inv_range2
111 .type mn10300_local_dcache_inv_page,@function
112 .type mn10300_local_dcache_inv_range,@function
113 .type mn10300_local_dcache_inv_range2,@function
114mn10300_local_dcache_inv_page:
115 and ~(PAGE_SIZE-1),d0
116 mov PAGE_SIZE,d1
117mn10300_local_dcache_inv_range2:
118 add d0,d1
119mn10300_local_dcache_inv_range:
120 # If we are in writeback mode we check the start and end alignments,
121 # and if they're not cacheline-aligned, we must flush any bits outside
122 # the range that share cachelines with stuff inside the range
123#ifdef CONFIG_MN10300_CACHE_WBACK
124 btst ~(L1_CACHE_BYTES-1),d0
125 bne 1f
126 btst ~(L1_CACHE_BYTES-1),d1
127 beq 2f
1281:
129 bra mn10300_local_dcache_flush_inv_range
1302:
131#endif /* CONFIG_MN10300_CACHE_WBACK */
132
133 movm [d2,d3,a2],(sp)
134
135 mov CHCTR,a0
136 movhu (a0),d2
137 btst CHCTR_DCEN,d2
138 beq mn10300_local_dcache_inv_range_end
139
140 # round the addresses out to be full cachelines, unless we're in
141 # writeback mode, in which case we would be in flush and invalidate by
142 # now
143#ifndef CONFIG_MN10300_CACHE_WBACK
144 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
145 # addr down
146
147 mov L1_CACHE_BYTES-1,d2
148 add d2,d1
149 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 # round end addr up
150#endif /* !CONFIG_MN10300_CACHE_WBACK */
151
152 sub d0,d1,d2 # calculate the total size
153 mov d0,a2 # A2 = start address
154 mov d1,a1 # A1 = end address
155
156 LOCAL_CLI_SAVE(d3)
157
158 mov DCPGCR,a0 # make sure the purger isn't busy
159 setlb
160 mov (a0),d0
161 btst DCPGCR_DCPGBSY,d0
162 lne
163
164 # skip initial address alignment calculation if address is zero
165 mov d2,d1
166 cmp 0,a2
167 beq 1f
168
169dcivloop:
170 /* calculate alignsize
171 *
172 * alignsize = L1_CACHE_BYTES;
173 * while (! start & alignsize) {
174 * alignsize <<=1;
175 * }
176 * d1 = alignsize;
177 */
178 mov L1_CACHE_BYTES,d1
179 lsr 1,d1
180 setlb
181 add d1,d1
182 mov d1,d0
183 and a2,d0
184 leq
185
1861:
187 /* calculate invsize
188 *
189 * if (totalsize > alignsize) {
190 * invsize = alignsize;
191 * } else {
192 * invsize = totalsize;
193 * tmp = 0x80000000;
194 * while (! invsize & tmp) {
195 * tmp >>= 1;
196 * }
197 * invsize = tmp;
198 * }
199 * d1 = invsize
200 */
201 cmp d2,d1
202 bns 2f
203 mov d2,d1
204
205 mov 0x80000000,d0 # start from 31bit=1
206 setlb
207 lsr 1,d0
208 mov d0,e0
209 and d1,e0
210 leq
211 mov d0,d1
212
2132:
214 /* set mask
215 *
216 * mask = ~(invsize-1);
217 * DCPGMR = mask;
218 */
219 mov d1,d0
220 add -1,d0
221 not d0
222 mov d0,(DCPGMR)
223
224 # invalidate area
225 mov a2,d0
226 or DCPGCR_DCI,d0
227 mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCI
228
229 setlb # wait for the purge to complete
230 mov (a0),d0
231 btst DCPGCR_DCPGBSY,d0
232 lne
233
234 sub d1,d2 # decrease size remaining
235 add d1,a2 # increase next start address
236
237 /* check invalidating of end address
238 *
239 * a2 = a2 + invsize
240 * if (a2 < end) {
241 * goto dcivloop;
242 * } */
243 cmp a1,a2
244 bns dcivloop
245
246 LOCAL_IRQ_RESTORE(d3)
247
248mn10300_local_dcache_inv_range_end:
249 ret [d2,d3,a2],12
250 .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
251 .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
252 .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
253
254###############################################################################
255#
256# void mn10300_local_icache_inv_page(unsigned long start)
257# void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size)
258# void mn10300_local_icache_inv_range(unsigned long start, unsigned long end)
259# Invalidate a range of addresses on a page in the icache
260#
261###############################################################################
262 ALIGN
263 .globl mn10300_local_icache_inv_page
264 .globl mn10300_local_icache_inv_range
265 .globl mn10300_local_icache_inv_range2
266 .type mn10300_local_icache_inv_page,@function
267 .type mn10300_local_icache_inv_range,@function
268 .type mn10300_local_icache_inv_range2,@function
269mn10300_local_icache_inv_page:
270 and ~(PAGE_SIZE-1),d0
271 mov PAGE_SIZE,d1
272mn10300_local_icache_inv_range2:
273 add d0,d1
274mn10300_local_icache_inv_range:
275 movm [d2,d3,a2],(sp)
276
277 mov CHCTR,a0
278 movhu (a0),d2
279 btst CHCTR_ICEN,d2
280 beq mn10300_local_icache_inv_range_reg_end
281
282 /* calculate alignsize
283 *
284 * alignsize = L1_CACHE_BYTES;
285 * for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) {
286 * alignsize <<= 1;
287 * }
288 * d2 = alignsize;
289 */
290 mov L1_CACHE_BYTES,d2
291 sub d0,d1,d3
292 add -1,d3
293 lsr L1_CACHE_SHIFT,d3
294 beq 2f
2951:
296 add d2,d2
297 lsr 1,d3
298 bne 1b
2992:
300
301 /* a1 = end */
302 mov d1,a1
303
304 LOCAL_CLI_SAVE(d3)
305
306 mov ICIVCR,a0
307 /* wait for busy bit of area invalidation */
308 setlb
309 mov (a0),d1
310 btst ICIVCR_ICIVBSY,d1
311 lne
312
313 /* set mask
314 *
315 * mask = ~(alignsize-1);
316 * ICIVMR = mask;
317 */
318 mov d2,d1
319 add -1,d1
320 not d1
321 mov d1,(ICIVMR)
322 /* a2 = mask & start */
323 and d1,d0,a2
324
325icivloop:
326 /* area invalidate
327 *
328 * ICIVCR = (mask & start) | ICIVCR_ICI
329 */
330 mov a2,d0
331 or ICIVCR_ICI,d0
332 mov d0,(a0)
333
334 /* wait for busy bit of area invalidation */
335 setlb
336 mov (a0),d1
337 btst ICIVCR_ICIVBSY,d1
338 lne
339
340 /* check invalidating of end address
341 *
342 * a2 = a2 + alignsize
343 * if (a2 < end) {
344 * goto icivloop;
345 * } */
346 add d2,a2
347 cmp a1,a2
348 bns icivloop
349
350 LOCAL_IRQ_RESTORE(d3)
351
352mn10300_local_icache_inv_range_reg_end:
353 ret [d2,d3,a2],12
354 .size mn10300_local_icache_inv_page,.-mn10300_local_icache_inv_page
355 .size mn10300_local_icache_inv_range,.-mn10300_local_icache_inv_range
356 .size mn10300_local_icache_inv_range2,.-mn10300_local_icache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S
new file mode 100644
index 000000000000..e9713b40c0ff
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-by-tag.S
@@ -0,0 +1,348 @@
1/* MN10300 CPU core caching routines
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18
19#define mn10300_local_dcache_inv_range_intr_interval \
20 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
21
22#if mn10300_local_dcache_inv_range_intr_interval > 0xff
23#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
24#endif
25
26 .am33_2
27
28 .globl mn10300_local_icache_inv_page
29 .globl mn10300_local_icache_inv_range
30 .globl mn10300_local_icache_inv_range2
31
32mn10300_local_icache_inv_page = mn10300_local_icache_inv
33mn10300_local_icache_inv_range = mn10300_local_icache_inv
34mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
35
36#ifndef CONFIG_SMP
37 .globl mn10300_icache_inv
38 .globl mn10300_icache_inv_page
39 .globl mn10300_icache_inv_range
40 .globl mn10300_icache_inv_range2
41 .globl mn10300_dcache_inv
42 .globl mn10300_dcache_inv_page
43 .globl mn10300_dcache_inv_range
44 .globl mn10300_dcache_inv_range2
45
46mn10300_icache_inv = mn10300_local_icache_inv
47mn10300_icache_inv_page = mn10300_local_icache_inv_page
48mn10300_icache_inv_range = mn10300_local_icache_inv_range
49mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
50mn10300_dcache_inv = mn10300_local_dcache_inv
51mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
52mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
53mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
54
55#endif /* !CONFIG_SMP */
56
57###############################################################################
58#
59# void mn10300_local_icache_inv(void)
60# Invalidate the entire icache
61#
62###############################################################################
63 ALIGN
64 .globl mn10300_local_icache_inv
65 .type mn10300_local_icache_inv,@function
66mn10300_local_icache_inv:
67 mov CHCTR,a0
68
69 movhu (a0),d0
70 btst CHCTR_ICEN,d0
71 beq mn10300_local_icache_inv_end
72
73#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
74 LOCAL_CLI_SAVE(d1)
75
76 # disable the icache
77 and ~CHCTR_ICEN,d0
78 movhu d0,(a0)
79
80 # and wait for it to calm down
81 setlb
82 movhu (a0),d0
83 btst CHCTR_ICBUSY,d0
84 lne
85
86 # invalidate
87 or CHCTR_ICINV,d0
88 movhu d0,(a0)
89
90 # wait for the cache to finish
91 mov CHCTR,a0
92 setlb
93 movhu (a0),d0
94 btst CHCTR_ICBUSY,d0
95 lne
96
97 # and reenable it
98 and ~CHCTR_ICINV,d0
99 or CHCTR_ICEN,d0
100 movhu d0,(a0)
101 movhu (a0),d0
102
103 LOCAL_IRQ_RESTORE(d1)
104#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
105 # invalidate
106 or CHCTR_ICINV,d0
107 movhu d0,(a0)
108 movhu (a0),d0
109#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
110
111mn10300_local_icache_inv_end:
112 ret [],0
113 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
114
115###############################################################################
116#
117# void mn10300_local_dcache_inv(void)
118# Invalidate the entire dcache
119#
120###############################################################################
121 ALIGN
122 .globl mn10300_local_dcache_inv
123 .type mn10300_local_dcache_inv,@function
124mn10300_local_dcache_inv:
125 mov CHCTR,a0
126
127 movhu (a0),d0
128 btst CHCTR_DCEN,d0
129 beq mn10300_local_dcache_inv_end
130
131#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
132 LOCAL_CLI_SAVE(d1)
133
134 # disable the dcache
135 and ~CHCTR_DCEN,d0
136 movhu d0,(a0)
137
138 # and wait for it to calm down
139 setlb
140 movhu (a0),d0
141 btst CHCTR_DCBUSY,d0
142 lne
143
144 # invalidate
145 or CHCTR_DCINV,d0
146 movhu d0,(a0)
147
148 # wait for the cache to finish
149 mov CHCTR,a0
150 setlb
151 movhu (a0),d0
152 btst CHCTR_DCBUSY,d0
153 lne
154
155 # and reenable it
156 and ~CHCTR_DCINV,d0
157 or CHCTR_DCEN,d0
158 movhu d0,(a0)
159 movhu (a0),d0
160
161 LOCAL_IRQ_RESTORE(d1)
162#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
163 # invalidate
164 or CHCTR_DCINV,d0
165 movhu d0,(a0)
166 movhu (a0),d0
167#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
168
169mn10300_local_dcache_inv_end:
170 ret [],0
171 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
172
173###############################################################################
174#
175# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
176# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
177# void mn10300_local_dcache_inv_page(unsigned long start)
178# Invalidate a range of addresses on a page in the dcache
179#
180###############################################################################
181 ALIGN
182 .globl mn10300_local_dcache_inv_page
183 .globl mn10300_local_dcache_inv_range
184 .globl mn10300_local_dcache_inv_range2
185 .type mn10300_local_dcache_inv_page,@function
186 .type mn10300_local_dcache_inv_range,@function
187 .type mn10300_local_dcache_inv_range2,@function
188mn10300_local_dcache_inv_page:
189 and ~(PAGE_SIZE-1),d0
190 mov PAGE_SIZE,d1
191mn10300_local_dcache_inv_range2:
192 add d0,d1
193mn10300_local_dcache_inv_range:
194 # If we are in writeback mode we check the start and end alignments,
195 # and if they're not cacheline-aligned, we must flush any bits outside
196 # the range that share cachelines with stuff inside the range
197#ifdef CONFIG_MN10300_CACHE_WBACK
198 btst ~(L1_CACHE_BYTES-1),d0
199 bne 1f
200 btst ~(L1_CACHE_BYTES-1),d1
201 beq 2f
2021:
203 bra mn10300_local_dcache_flush_inv_range
2042:
205#endif /* CONFIG_MN10300_CACHE_WBACK */
206
207 movm [d2,d3,a2],(sp)
208
209 mov CHCTR,a2
210 movhu (a2),d2
211 btst CHCTR_DCEN,d2
212 beq mn10300_local_dcache_inv_range_end
213
214#ifndef CONFIG_MN10300_CACHE_WBACK
215 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
216 # addr down
217
218 add L1_CACHE_BYTES,d1 # round end addr up
219 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
220#endif /* !CONFIG_MN10300_CACHE_WBACK */
221 mov d0,a1
222
223 clr d2 # we're going to clear tag RAM
224 # entries
225
226 # read the tags from the tag RAM, and if they indicate a valid dirty
227 # cache line then invalidate that line
228 mov DCACHE_TAG(0,0),a0
229 mov a1,d0
230 and L1_CACHE_TAG_ENTRY,d0
231 add d0,a0 # starting dcache tag RAM
232 # access address
233
234 sub a1,d1
235 lsr L1_CACHE_SHIFT,d1 # total number of entries to
236 # examine
237
238 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
239
240mn10300_local_dcache_inv_range_outer_loop:
241 LOCAL_CLI_SAVE(d3)
242
243 # disable the dcache
244 movhu (a2),d0
245 and ~CHCTR_DCEN,d0
246 movhu d0,(a2)
247
248 # and wait for it to calm down
249 setlb
250 movhu (a2),d0
251 btst CHCTR_DCBUSY,d0
252 lne
253
254mn10300_local_dcache_inv_range_loop:
255
256 # process the way 0 slot
257 mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
258 btst L1_CACHE_TAG_VALID,d0
259 beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
260 # is not valid
261
262 xor a1,d0
263 lsr 12,d0
264 bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
265
266 mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
267
268mn10300_local_dcache_inv_range_skip_0:
269
270 # process the way 1 slot
271 mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
272 btst L1_CACHE_TAG_VALID,d0
273 beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
274 # is not valid
275
276 xor a1,d0
277 lsr 12,d0
278 bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
279
280 mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
281
282mn10300_local_dcache_inv_range_skip_1:
283
284 # process the way 2 slot
285 mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
286 btst L1_CACHE_TAG_VALID,d0
287 beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
288 # is not valid
289
290 xor a1,d0
291 lsr 12,d0
292 bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
293
294 mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
295
296mn10300_local_dcache_inv_range_skip_2:
297
298 # process the way 3 slot
299 mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
300 btst L1_CACHE_TAG_VALID,d0
301 beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
302 # is not valid
303
304 xor a1,d0
305 lsr 12,d0
306 bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
307
308 mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
309
310mn10300_local_dcache_inv_range_skip_3:
311
312 # approx every N steps we re-enable the cache and see if there are any
313 # interrupts to be processed
314 # we also break out if we've reached the end of the loop
315 # (the bottom nibble of the count is zero in both cases)
316 add L1_CACHE_BYTES,a0
317 add L1_CACHE_BYTES,a1
318 and ~L1_CACHE_WAYDISP,a0
319 add -1,d1
320 btst mn10300_local_dcache_inv_range_intr_interval,d1
321 bne mn10300_local_dcache_inv_range_loop
322
323 # wait for the cache to finish what it's doing
324 setlb
325 movhu (a2),d0
326 btst CHCTR_DCBUSY,d0
327 lne
328
329 # and reenable it
330 or CHCTR_DCEN,d0
331 movhu d0,(a2)
332 movhu (a2),d0
333
334 # re-enable interrupts
335 # - we don't bother with delay NOPs as we'll have enough instructions
336 # before we disable interrupts again to give the interrupts a chance
337 # to happen
338 LOCAL_IRQ_RESTORE(d3)
339
340 # go around again if the counter hasn't yet reached zero
341 add 0,d1
342 bne mn10300_local_dcache_inv_range_outer_loop
343
344mn10300_local_dcache_inv_range_end:
345 ret [d2,d3,a2],12
346 .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
347 .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
348 .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c
new file mode 100644
index 000000000000..a8933a60b2d4
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-icache.c
@@ -0,0 +1,129 @@
1/* Invalidate icache when dcache doesn't need invalidation as it's in
2 * write-through mode
3 *
4 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/module.h>
13#include <linux/mm.h>
14#include <asm/cacheflush.h>
15#include <asm/smp.h>
16#include "cache-smp.h"
17
18/**
19 * flush_icache_page_range - Flush dcache and invalidate icache for part of a
20 * single page
21 * @start: The starting virtual address of the page part.
22 * @end: The ending virtual address of the page part.
23 *
24 * Invalidate the icache for part of a single page, as determined by the
25 * virtual addresses given. The page must be in the paged area. The dcache is
26 * not flushed as the cache must be in write-through mode to get here.
27 */
28static void flush_icache_page_range(unsigned long start, unsigned long end)
29{
30 unsigned long addr, size, off;
31 struct page *page;
32 pgd_t *pgd;
33 pud_t *pud;
34 pmd_t *pmd;
35 pte_t *ppte, pte;
36
37 /* work out how much of the page to flush */
38 off = start & ~PAGE_MASK;
39 size = end - start;
40
41 /* get the physical address the page is mapped to from the page
42 * tables */
43 pgd = pgd_offset(current->mm, start);
44 if (!pgd || !pgd_val(*pgd))
45 return;
46
47 pud = pud_offset(pgd, start);
48 if (!pud || !pud_val(*pud))
49 return;
50
51 pmd = pmd_offset(pud, start);
52 if (!pmd || !pmd_val(*pmd))
53 return;
54
55 ppte = pte_offset_map(pmd, start);
56 if (!ppte)
57 return;
58 pte = *ppte;
59 pte_unmap(ppte);
60
61 if (pte_none(pte))
62 return;
63
64 page = pte_page(pte);
65 if (!page)
66 return;
67
68 addr = page_to_phys(page);
69
70 /* invalidate the icache coverage on that region */
71 mn10300_local_icache_inv_range2(addr + off, size);
72 smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end);
73}
74
75/**
76 * flush_icache_range - Globally flush dcache and invalidate icache for region
77 * @start: The starting virtual address of the region.
78 * @end: The ending virtual address of the region.
79 *
80 * This is used by the kernel to globally flush some code it has just written
81 * from the dcache back to RAM and then to globally invalidate the icache over
82 * that region so that that code can be run on all CPUs in the system.
83 */
84void flush_icache_range(unsigned long start, unsigned long end)
85{
86 unsigned long start_page, end_page;
87 unsigned long flags;
88
89 flags = smp_lock_cache();
90
91 if (end > 0x80000000UL) {
92 /* addresses above 0xa0000000 do not go through the cache */
93 if (end > 0xa0000000UL) {
94 end = 0xa0000000UL;
95 if (start >= end)
96 goto done;
97 }
98
99 /* kernel addresses between 0x80000000 and 0x9fffffff do not
100 * require page tables, so we just map such addresses
101 * directly */
102 start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
103 mn10300_icache_inv_range(start_page, end);
104 smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end);
105 if (start_page == start)
106 goto done;
107 end = start_page;
108 }
109
110 start_page = start & PAGE_MASK;
111 end_page = (end - 1) & PAGE_MASK;
112
113 if (start_page == end_page) {
114 /* the first and last bytes are on the same page */
115 flush_icache_page_range(start, end);
116 } else if (start_page + 1 == end_page) {
117 /* split over two virtually contiguous pages */
118 flush_icache_page_range(start, end_page);
119 flush_icache_page_range(end_page, end);
120 } else {
121 /* more than 2 pages; just flush the entire cache */
122 mn10300_local_icache_inv();
123 smp_cache_call(SMP_ICACHE_INV, 0, 0);
124 }
125
126done:
127 smp_unlock_cache(flags);
128}
129EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-mn10300.S b/arch/mn10300/mm/cache-mn10300.S
deleted file mode 100644
index e839d0aedd69..000000000000
--- a/arch/mn10300/mm/cache-mn10300.S
+++ /dev/null
@@ -1,289 +0,0 @@
1/* MN10300 CPU core caching routines
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16
17#define mn10300_dcache_inv_range_intr_interval \
18 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
19
20#if mn10300_dcache_inv_range_intr_interval > 0xff
21#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
22#endif
23
24 .am33_2
25
26 .globl mn10300_icache_inv
27 .globl mn10300_dcache_inv
28 .globl mn10300_dcache_inv_range
29 .globl mn10300_dcache_inv_range2
30 .globl mn10300_dcache_inv_page
31
32###############################################################################
33#
34# void mn10300_icache_inv(void)
35# Invalidate the entire icache
36#
37###############################################################################
38 ALIGN
39mn10300_icache_inv:
40 mov CHCTR,a0
41
42 movhu (a0),d0
43 btst CHCTR_ICEN,d0
44 beq mn10300_icache_inv_end
45
46 mov epsw,d1
47 and ~EPSW_IE,epsw
48 nop
49 nop
50
51 # disable the icache
52 and ~CHCTR_ICEN,d0
53 movhu d0,(a0)
54
55 # and wait for it to calm down
56 setlb
57 movhu (a0),d0
58 btst CHCTR_ICBUSY,d0
59 lne
60
61 # invalidate
62 or CHCTR_ICINV,d0
63 movhu d0,(a0)
64
65 # wait for the cache to finish
66 mov CHCTR,a0
67 setlb
68 movhu (a0),d0
69 btst CHCTR_ICBUSY,d0
70 lne
71
72 # and reenable it
73 and ~CHCTR_ICINV,d0
74 or CHCTR_ICEN,d0
75 movhu d0,(a0)
76 movhu (a0),d0
77
78 mov d1,epsw
79
80mn10300_icache_inv_end:
81 ret [],0
82
83###############################################################################
84#
85# void mn10300_dcache_inv(void)
86# Invalidate the entire dcache
87#
88###############################################################################
89 ALIGN
90mn10300_dcache_inv:
91 mov CHCTR,a0
92
93 movhu (a0),d0
94 btst CHCTR_DCEN,d0
95 beq mn10300_dcache_inv_end
96
97 mov epsw,d1
98 and ~EPSW_IE,epsw
99 nop
100 nop
101
102 # disable the dcache
103 and ~CHCTR_DCEN,d0
104 movhu d0,(a0)
105
106 # and wait for it to calm down
107 setlb
108 movhu (a0),d0
109 btst CHCTR_DCBUSY,d0
110 lne
111
112 # invalidate
113 or CHCTR_DCINV,d0
114 movhu d0,(a0)
115
116 # wait for the cache to finish
117 mov CHCTR,a0
118 setlb
119 movhu (a0),d0
120 btst CHCTR_DCBUSY,d0
121 lne
122
123 # and reenable it
124 and ~CHCTR_DCINV,d0
125 or CHCTR_DCEN,d0
126 movhu d0,(a0)
127 movhu (a0),d0
128
129 mov d1,epsw
130
131mn10300_dcache_inv_end:
132 ret [],0
133
134###############################################################################
135#
136# void mn10300_dcache_inv_range(unsigned start, unsigned end)
137# void mn10300_dcache_inv_range2(unsigned start, unsigned size)
138# void mn10300_dcache_inv_page(unsigned start)
139# Invalidate a range of addresses on a page in the dcache
140#
141###############################################################################
142 ALIGN
143mn10300_dcache_inv_page:
144 mov PAGE_SIZE,d1
145mn10300_dcache_inv_range2:
146 add d0,d1
147mn10300_dcache_inv_range:
148 movm [d2,d3,a2],(sp)
149 mov CHCTR,a2
150
151 movhu (a2),d2
152 btst CHCTR_DCEN,d2
153 beq mn10300_dcache_inv_range_end
154
155 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
156 # addr down
157 mov d0,a1
158
159 add L1_CACHE_BYTES,d1 # round end addr up
160 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
161
162 clr d2 # we're going to clear tag ram
163 # entries
164
165 # read the tags from the tag RAM, and if they indicate a valid dirty
166 # cache line then invalidate that line
167 mov DCACHE_TAG(0,0),a0
168 mov a1,d0
169 and L1_CACHE_TAG_ENTRY,d0
170 add d0,a0 # starting dcache tag RAM
171 # access address
172
173 sub a1,d1
174 lsr L1_CACHE_SHIFT,d1 # total number of entries to
175 # examine
176
177 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
178
179mn10300_dcache_inv_range_outer_loop:
180 # disable interrupts
181 mov epsw,d3
182 and ~EPSW_IE,epsw
183 nop # note that reading CHCTR and
184 # AND'ing D0 occupy two delay
185 # slots after disabling
186 # interrupts
187
188 # disable the dcache
189 movhu (a2),d0
190 and ~CHCTR_DCEN,d0
191 movhu d0,(a2)
192
193 # and wait for it to calm down
194 setlb
195 movhu (a2),d0
196 btst CHCTR_DCBUSY,d0
197 lne
198
199mn10300_dcache_inv_range_loop:
200
201 # process the way 0 slot
202 mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
203 btst L1_CACHE_TAG_VALID,d0
204 beq mn10300_dcache_inv_range_skip_0 # jump if this cacheline is not
205 # valid
206
207 xor a1,d0
208 lsr 12,d0
209 bne mn10300_dcache_inv_range_skip_0 # jump if not this cacheline
210
211 mov d2,(a0) # kill the tag
212
213mn10300_dcache_inv_range_skip_0:
214
215 # process the way 1 slot
216 mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
217 btst L1_CACHE_TAG_VALID,d0
218 beq mn10300_dcache_inv_range_skip_1 # jump if this cacheline is not
219 # valid
220
221 xor a1,d0
222 lsr 12,d0
223 bne mn10300_dcache_inv_range_skip_1 # jump if not this cacheline
224
225 mov d2,(a0) # kill the tag
226
227mn10300_dcache_inv_range_skip_1:
228
229 # process the way 2 slot
230 mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
231 btst L1_CACHE_TAG_VALID,d0
232 beq mn10300_dcache_inv_range_skip_2 # jump if this cacheline is not
233 # valid
234
235 xor a1,d0
236 lsr 12,d0
237 bne mn10300_dcache_inv_range_skip_2 # jump if not this cacheline
238
239 mov d2,(a0) # kill the tag
240
241mn10300_dcache_inv_range_skip_2:
242
243 # process the way 3 slot
244 mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
245 btst L1_CACHE_TAG_VALID,d0
246 beq mn10300_dcache_inv_range_skip_3 # jump if this cacheline is not
247 # valid
248
249 xor a1,d0
250 lsr 12,d0
251 bne mn10300_dcache_inv_range_skip_3 # jump if not this cacheline
252
253 mov d2,(a0) # kill the tag
254
255mn10300_dcache_inv_range_skip_3:
256
257 # approx every N steps we re-enable the cache and see if there are any
258 # interrupts to be processed
259 # we also break out if we've reached the end of the loop
260 # (the bottom nibble of the count is zero in both cases)
261 add L1_CACHE_BYTES,a0
262 add L1_CACHE_BYTES,a1
263 add -1,d1
264 btst mn10300_dcache_inv_range_intr_interval,d1
265 bne mn10300_dcache_inv_range_loop
266
267 # wait for the cache to finish what it's doing
268 setlb
269 movhu (a2),d0
270 btst CHCTR_DCBUSY,d0
271 lne
272
273 # and reenable it
274 or CHCTR_DCEN,d0
275 movhu d0,(a2)
276 movhu (a2),d0
277
278 # re-enable interrupts
279 # - we don't bother with delay NOPs as we'll have enough instructions
280 # before we disable interrupts again to give the interrupts a chance
281 # to happen
282 mov d3,epsw
283
284 # go around again if the counter hasn't yet reached zero
285 add 0,d1
286 bne mn10300_dcache_inv_range_outer_loop
287
288mn10300_dcache_inv_range_end:
289 ret [d2,d3,a2],12
diff --git a/arch/mn10300/mm/cache-smp-flush.c b/arch/mn10300/mm/cache-smp-flush.c
new file mode 100644
index 000000000000..fd51af5eaf70
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp-flush.c
@@ -0,0 +1,156 @@
1/* Functions for global dcache flush when writeback caching in SMP
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/mm.h>
12#include <asm/cacheflush.h>
13#include "cache-smp.h"
14
15/**
16 * mn10300_dcache_flush - Globally flush data cache
17 *
18 * Flush the data cache on all CPUs.
19 */
20void mn10300_dcache_flush(void)
21{
22 unsigned long flags;
23
24 flags = smp_lock_cache();
25 mn10300_local_dcache_flush();
26 smp_cache_call(SMP_DCACHE_FLUSH, 0, 0);
27 smp_unlock_cache(flags);
28}
29
30/**
31 * mn10300_dcache_flush_page - Globally flush a page of data cache
32 * @start: The address of the page of memory to be flushed.
33 *
34 * Flush a range of addresses in the data cache on all CPUs covering
35 * the page that includes the given address.
36 */
37void mn10300_dcache_flush_page(unsigned long start)
38{
39 unsigned long flags;
40
41 start &= ~(PAGE_SIZE-1);
42
43 flags = smp_lock_cache();
44 mn10300_local_dcache_flush_page(start);
45 smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + PAGE_SIZE);
46 smp_unlock_cache(flags);
47}
48
49/**
50 * mn10300_dcache_flush_range - Globally flush range of data cache
51 * @start: The start address of the region to be flushed.
52 * @end: The end address of the region to be flushed.
53 *
54 * Flush a range of addresses in the data cache on all CPUs, between start and
55 * end-1 inclusive.
56 */
57void mn10300_dcache_flush_range(unsigned long start, unsigned long end)
58{
59 unsigned long flags;
60
61 flags = smp_lock_cache();
62 mn10300_local_dcache_flush_range(start, end);
63 smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, end);
64 smp_unlock_cache(flags);
65}
66
67/**
68 * mn10300_dcache_flush_range2 - Globally flush range of data cache
69 * @start: The start address of the region to be flushed.
70 * @size: The size of the region to be flushed.
71 *
72 * Flush a range of addresses in the data cache on all CPUs, between start and
73 * start+size-1 inclusive.
74 */
75void mn10300_dcache_flush_range2(unsigned long start, unsigned long size)
76{
77 unsigned long flags;
78
79 flags = smp_lock_cache();
80 mn10300_local_dcache_flush_range2(start, size);
81 smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + size);
82 smp_unlock_cache(flags);
83}
84
85/**
86 * mn10300_dcache_flush_inv - Globally flush and invalidate data cache
87 *
88 * Flush and invalidate the data cache on all CPUs.
89 */
90void mn10300_dcache_flush_inv(void)
91{
92 unsigned long flags;
93
94 flags = smp_lock_cache();
95 mn10300_local_dcache_flush_inv();
96 smp_cache_call(SMP_DCACHE_FLUSH_INV, 0, 0);
97 smp_unlock_cache(flags);
98}
99
100/**
101 * mn10300_dcache_flush_inv_page - Globally flush and invalidate a page of data
102 * cache
103 * @start: The address of the page of memory to be flushed and invalidated.
104 *
105 * Flush and invalidate a range of addresses in the data cache on all CPUs
106 * covering the page that includes the given address.
107 */
108void mn10300_dcache_flush_inv_page(unsigned long start)
109{
110 unsigned long flags;
111
112 start &= ~(PAGE_SIZE-1);
113
114 flags = smp_lock_cache();
115 mn10300_local_dcache_flush_inv_page(start);
116 smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + PAGE_SIZE);
117 smp_unlock_cache(flags);
118}
119
120/**
121 * mn10300_dcache_flush_inv_range - Globally flush and invalidate range of data
122 * cache
123 * @start: The start address of the region to be flushed and invalidated.
124 * @end: The end address of the region to be flushed and invalidated.
125 *
126 * Flush and invalidate a range of addresses in the data cache on all CPUs,
127 * between start and end-1 inclusive.
128 */
129void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end)
130{
131 unsigned long flags;
132
133 flags = smp_lock_cache();
134 mn10300_local_dcache_flush_inv_range(start, end);
135 smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, end);
136 smp_unlock_cache(flags);
137}
138
139/**
140 * mn10300_dcache_flush_inv_range2 - Globally flush and invalidate range of data
141 * cache
142 * @start: The start address of the region to be flushed and invalidated.
143 * @size: The size of the region to be flushed and invalidated.
144 *
145 * Flush and invalidate a range of addresses in the data cache on all CPUs,
146 * between start and start+size-1 inclusive.
147 */
148void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size)
149{
150 unsigned long flags;
151
152 flags = smp_lock_cache();
153 mn10300_local_dcache_flush_inv_range2(start, size);
154 smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + size);
155 smp_unlock_cache(flags);
156}
diff --git a/arch/mn10300/mm/cache-smp-inv.c b/arch/mn10300/mm/cache-smp-inv.c
new file mode 100644
index 000000000000..ff1787358c8e
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp-inv.c
@@ -0,0 +1,153 @@
1/* Functions for global i/dcache invalidation when caching in SMP
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/mm.h>
12#include <asm/cacheflush.h>
13#include "cache-smp.h"
14
15/**
16 * mn10300_icache_inv - Globally invalidate instruction cache
17 *
18 * Invalidate the instruction cache on all CPUs.
19 */
20void mn10300_icache_inv(void)
21{
22 unsigned long flags;
23
24 flags = smp_lock_cache();
25 mn10300_local_icache_inv();
26 smp_cache_call(SMP_ICACHE_INV, 0, 0);
27 smp_unlock_cache(flags);
28}
29
30/**
31 * mn10300_icache_inv_page - Globally invalidate a page of instruction cache
32 * @start: The address of the page of memory to be invalidated.
33 *
34 * Invalidate a range of addresses in the instruction cache on all CPUs
35 * covering the page that includes the given address.
36 */
37void mn10300_icache_inv_page(unsigned long start)
38{
39 unsigned long flags;
40
41 start &= ~(PAGE_SIZE-1);
42
43 flags = smp_lock_cache();
44 mn10300_local_icache_inv_page(start);
45 smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + PAGE_SIZE);
46 smp_unlock_cache(flags);
47}
48
49/**
50 * mn10300_icache_inv_range - Globally invalidate range of instruction cache
51 * @start: The start address of the region to be invalidated.
52 * @end: The end address of the region to be invalidated.
53 *
54 * Invalidate a range of addresses in the instruction cache on all CPUs,
55 * between start and end-1 inclusive.
56 */
57void mn10300_icache_inv_range(unsigned long start, unsigned long end)
58{
59 unsigned long flags;
60
61 flags = smp_lock_cache();
62 mn10300_local_icache_inv_range(start, end);
63 smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
64 smp_unlock_cache(flags);
65}
66
67/**
68 * mn10300_icache_inv_range2 - Globally invalidate range of instruction cache
69 * @start: The start address of the region to be invalidated.
70 * @size: The size of the region to be invalidated.
71 *
72 * Invalidate a range of addresses in the instruction cache on all CPUs,
73 * between start and start+size-1 inclusive.
74 */
75void mn10300_icache_inv_range2(unsigned long start, unsigned long size)
76{
77 unsigned long flags;
78
79 flags = smp_lock_cache();
80 mn10300_local_icache_inv_range2(start, size);
81 smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + size);
82 smp_unlock_cache(flags);
83}
84
85/**
86 * mn10300_dcache_inv - Globally invalidate data cache
87 *
88 * Invalidate the data cache on all CPUs.
89 */
90void mn10300_dcache_inv(void)
91{
92 unsigned long flags;
93
94 flags = smp_lock_cache();
95 mn10300_local_dcache_inv();
96 smp_cache_call(SMP_DCACHE_INV, 0, 0);
97 smp_unlock_cache(flags);
98}
99
100/**
101 * mn10300_dcache_inv_page - Globally invalidate a page of data cache
102 * @start: The address of the page of memory to be invalidated.
103 *
104 * Invalidate a range of addresses in the data cache on all CPUs covering the
105 * page that includes the given address.
106 */
107void mn10300_dcache_inv_page(unsigned long start)
108{
109 unsigned long flags;
110
111 start &= ~(PAGE_SIZE-1);
112
113 flags = smp_lock_cache();
114 mn10300_local_dcache_inv_page(start);
115 smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + PAGE_SIZE);
116 smp_unlock_cache(flags);
117}
118
119/**
120 * mn10300_dcache_inv_range - Globally invalidate range of data cache
121 * @start: The start address of the region to be invalidated.
122 * @end: The end address of the region to be invalidated.
123 *
124 * Invalidate a range of addresses in the data cache on all CPUs, between start
125 * and end-1 inclusive.
126 */
127void mn10300_dcache_inv_range(unsigned long start, unsigned long end)
128{
129 unsigned long flags;
130
131 flags = smp_lock_cache();
132 mn10300_local_dcache_inv_range(start, end);
133 smp_cache_call(SMP_DCACHE_INV_RANGE, start, end);
134 smp_unlock_cache(flags);
135}
136
137/**
138 * mn10300_dcache_inv_range2 - Globally invalidate range of data cache
139 * @start: The start address of the region to be invalidated.
140 * @size: The size of the region to be invalidated.
141 *
142 * Invalidate a range of addresses in the data cache on all CPUs, between start
143 * and start+size-1 inclusive.
144 */
145void mn10300_dcache_inv_range2(unsigned long start, unsigned long size)
146{
147 unsigned long flags;
148
149 flags = smp_lock_cache();
150 mn10300_local_dcache_inv_range2(start, size);
151 smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + size);
152 smp_unlock_cache(flags);
153}
diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c
new file mode 100644
index 000000000000..4a6e9a4b5b27
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp.c
@@ -0,0 +1,105 @@
1/* SMP global caching code
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/mm.h>
13#include <linux/mman.h>
14#include <linux/threads.h>
15#include <linux/interrupt.h>
16#include <asm/page.h>
17#include <asm/pgtable.h>
18#include <asm/processor.h>
19#include <asm/cacheflush.h>
20#include <asm/io.h>
21#include <asm/uaccess.h>
22#include <asm/smp.h>
23#include "cache-smp.h"
24
25DEFINE_SPINLOCK(smp_cache_lock);
26static unsigned long smp_cache_mask;
27static unsigned long smp_cache_start;
28static unsigned long smp_cache_end;
29static cpumask_t smp_cache_ipi_map; /* Bitmask of cache IPI done CPUs */
30
31/**
32 * smp_cache_interrupt - Handle IPI request to flush caches.
33 *
34 * Handle a request delivered by IPI to flush the current CPU's
35 * caches. The parameters are stored in smp_cache_*.
36 */
37void smp_cache_interrupt(void)
38{
39 unsigned long opr_mask = smp_cache_mask;
40
41 switch ((enum smp_dcache_ops)(opr_mask & SMP_DCACHE_OP_MASK)) {
42 case SMP_DCACHE_NOP:
43 break;
44 case SMP_DCACHE_INV:
45 mn10300_local_dcache_inv();
46 break;
47 case SMP_DCACHE_INV_RANGE:
48 mn10300_local_dcache_inv_range(smp_cache_start, smp_cache_end);
49 break;
50 case SMP_DCACHE_FLUSH:
51 mn10300_local_dcache_flush();
52 break;
53 case SMP_DCACHE_FLUSH_RANGE:
54 mn10300_local_dcache_flush_range(smp_cache_start,
55 smp_cache_end);
56 break;
57 case SMP_DCACHE_FLUSH_INV:
58 mn10300_local_dcache_flush_inv();
59 break;
60 case SMP_DCACHE_FLUSH_INV_RANGE:
61 mn10300_local_dcache_flush_inv_range(smp_cache_start,
62 smp_cache_end);
63 break;
64 }
65
66 switch ((enum smp_icache_ops)(opr_mask & SMP_ICACHE_OP_MASK)) {
67 case SMP_ICACHE_NOP:
68 break;
69 case SMP_ICACHE_INV:
70 mn10300_local_icache_inv();
71 break;
72 case SMP_ICACHE_INV_RANGE:
73 mn10300_local_icache_inv_range(smp_cache_start, smp_cache_end);
74 break;
75 }
76
77 cpu_clear(smp_processor_id(), smp_cache_ipi_map);
78}
79
80/**
81 * smp_cache_call - Issue an IPI to request the other CPUs flush caches
82 * @opr_mask: Cache operation flags
83 * @start: Start address of request
84 * @end: End address of request
85 *
86 * Send cache flush IPI to other CPUs. This invokes smp_cache_interrupt()
87 * above on those other CPUs and then waits for them to finish.
88 *
89 * The caller must hold smp_cache_lock.
90 */
91void smp_cache_call(unsigned long opr_mask,
92 unsigned long start, unsigned long end)
93{
94 smp_cache_mask = opr_mask;
95 smp_cache_start = start;
96 smp_cache_end = end;
97 smp_cache_ipi_map = cpu_online_map;
98 cpu_clear(smp_processor_id(), smp_cache_ipi_map);
99
100 send_IPI_allbutself(FLUSH_CACHE_IPI);
101
102 while (!cpus_empty(smp_cache_ipi_map))
103 /* nothing. lockup detection does not belong here */
104 mb();
105}
diff --git a/arch/mn10300/mm/cache-smp.h b/arch/mn10300/mm/cache-smp.h
new file mode 100644
index 000000000000..cb52892aa66a
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp.h
@@ -0,0 +1,69 @@
1/* SMP caching definitions
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12
13/*
14 * Operation requests for smp_cache_call().
15 *
16 * One of smp_icache_ops and one of smp_dcache_ops can be OR'd together.
17 */
18enum smp_icache_ops {
19 SMP_ICACHE_NOP = 0x0000,
20 SMP_ICACHE_INV = 0x0001,
21 SMP_ICACHE_INV_RANGE = 0x0002,
22};
23#define SMP_ICACHE_OP_MASK 0x0003
24
25enum smp_dcache_ops {
26 SMP_DCACHE_NOP = 0x0000,
27 SMP_DCACHE_INV = 0x0004,
28 SMP_DCACHE_INV_RANGE = 0x0008,
29 SMP_DCACHE_FLUSH = 0x000c,
30 SMP_DCACHE_FLUSH_RANGE = 0x0010,
31 SMP_DCACHE_FLUSH_INV = 0x0014,
32 SMP_DCACHE_FLUSH_INV_RANGE = 0x0018,
33};
34#define SMP_DCACHE_OP_MASK 0x001c
35
36#define SMP_IDCACHE_INV_FLUSH (SMP_ICACHE_INV | SMP_DCACHE_FLUSH)
37#define SMP_IDCACHE_INV_FLUSH_RANGE (SMP_ICACHE_INV_RANGE | SMP_DCACHE_FLUSH_RANGE)
38
39/*
40 * cache-smp.c
41 */
42#ifdef CONFIG_SMP
43extern spinlock_t smp_cache_lock;
44
45extern void smp_cache_call(unsigned long opr_mask,
46 unsigned long addr, unsigned long end);
47
48static inline unsigned long smp_lock_cache(void)
49 __acquires(&smp_cache_lock)
50{
51 unsigned long flags;
52 spin_lock_irqsave(&smp_cache_lock, flags);
53 return flags;
54}
55
56static inline void smp_unlock_cache(unsigned long flags)
57 __releases(&smp_cache_lock)
58{
59 spin_unlock_irqrestore(&smp_cache_lock, flags);
60}
61
62#else
63static inline unsigned long smp_lock_cache(void) { return 0; }
64static inline void smp_unlock_cache(unsigned long flags) {}
65static inline void smp_cache_call(unsigned long opr_mask,
66 unsigned long addr, unsigned long end)
67{
68}
69#endif /* CONFIG_SMP */
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
index 9261217e8d2c..0a1f0aa92ebc 100644
--- a/arch/mn10300/mm/cache.c
+++ b/arch/mn10300/mm/cache.c
@@ -18,8 +18,13 @@
18#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
19#include <asm/io.h> 19#include <asm/io.h>
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21#include <asm/smp.h>
22#include "cache-smp.h"
21 23
22EXPORT_SYMBOL(mn10300_icache_inv); 24EXPORT_SYMBOL(mn10300_icache_inv);
25EXPORT_SYMBOL(mn10300_icache_inv_range);
26EXPORT_SYMBOL(mn10300_icache_inv_range2);
27EXPORT_SYMBOL(mn10300_icache_inv_page);
23EXPORT_SYMBOL(mn10300_dcache_inv); 28EXPORT_SYMBOL(mn10300_dcache_inv);
24EXPORT_SYMBOL(mn10300_dcache_inv_range); 29EXPORT_SYMBOL(mn10300_dcache_inv_range);
25EXPORT_SYMBOL(mn10300_dcache_inv_range2); 30EXPORT_SYMBOL(mn10300_dcache_inv_range2);
@@ -37,96 +42,6 @@ EXPORT_SYMBOL(mn10300_dcache_flush_page);
37#endif 42#endif
38 43
39/* 44/*
40 * write a page back from the dcache and invalidate the icache so that we can
41 * run code from it that we've just written into it
42 */
43void flush_icache_page(struct vm_area_struct *vma, struct page *page)
44{
45 mn10300_dcache_flush_page(page_to_phys(page));
46 mn10300_icache_inv();
47}
48EXPORT_SYMBOL(flush_icache_page);
49
50/*
51 * write some code we've just written back from the dcache and invalidate the
52 * icache so that we can run that code
53 */
54void flush_icache_range(unsigned long start, unsigned long end)
55{
56#ifdef CONFIG_MN10300_CACHE_WBACK
57 unsigned long addr, size, base, off;
58 struct page *page;
59 pgd_t *pgd;
60 pud_t *pud;
61 pmd_t *pmd;
62 pte_t *ppte, pte;
63
64 if (end > 0x80000000UL) {
65 /* addresses above 0xa0000000 do not go through the cache */
66 if (end > 0xa0000000UL) {
67 end = 0xa0000000UL;
68 if (start >= end)
69 return;
70 }
71
72 /* kernel addresses between 0x80000000 and 0x9fffffff do not
73 * require page tables, so we just map such addresses directly */
74 base = (start >= 0x80000000UL) ? start : 0x80000000UL;
75 mn10300_dcache_flush_range(base, end);
76 if (base == start)
77 goto invalidate;
78 end = base;
79 }
80
81 for (; start < end; start += size) {
82 /* work out how much of the page to flush */
83 off = start & (PAGE_SIZE - 1);
84
85 size = end - start;
86 if (size > PAGE_SIZE - off)
87 size = PAGE_SIZE - off;
88
89 /* get the physical address the page is mapped to from the page
90 * tables */
91 pgd = pgd_offset(current->mm, start);
92 if (!pgd || !pgd_val(*pgd))
93 continue;
94
95 pud = pud_offset(pgd, start);
96 if (!pud || !pud_val(*pud))
97 continue;
98
99 pmd = pmd_offset(pud, start);
100 if (!pmd || !pmd_val(*pmd))
101 continue;
102
103 ppte = pte_offset_map(pmd, start);
104 if (!ppte)
105 continue;
106 pte = *ppte;
107 pte_unmap(ppte);
108
109 if (pte_none(pte))
110 continue;
111
112 page = pte_page(pte);
113 if (!page)
114 continue;
115
116 addr = page_to_phys(page);
117
118 /* flush the dcache and invalidate the icache coverage on that
119 * region */
120 mn10300_dcache_flush_range2(addr + off, size);
121 }
122#endif
123
124invalidate:
125 mn10300_icache_inv();
126}
127EXPORT_SYMBOL(flush_icache_range);
128
129/*
130 * allow userspace to flush the instruction cache 45 * allow userspace to flush the instruction cache
131 */ 46 */
132asmlinkage long sys_cacheflush(unsigned long start, unsigned long end) 47asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 81f153fa51b4..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
@@ -100,8 +96,6 @@ static void print_pagetable_entries(pgd_t *pgdir, unsigned long address)
100} 96}
101#endif 97#endif
102 98
103asmlinkage void monitor_signal(struct pt_regs *);
104
105/* 99/*
106 * This routine handles page faults. It determines the address, 100 * This routine handles page faults. It determines the address,
107 * and the problem, and then passes it off to one of the appropriate 101 * and the problem, and then passes it off to one of the appropriate
@@ -279,7 +273,6 @@ good_area:
279 */ 273 */
280bad_area: 274bad_area:
281 up_read(&mm->mmap_sem); 275 up_read(&mm->mmap_sem);
282 monitor_signal(regs);
283 276
284 /* User mode accesses just cause a SIGSEGV */ 277 /* User mode accesses just cause a SIGSEGV */
285 if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) { 278 if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
@@ -292,7 +285,6 @@ bad_area:
292 } 285 }
293 286
294no_context: 287no_context:
295 monitor_signal(regs);
296 /* Are we prepared to handle this kernel fault? */ 288 /* Are we prepared to handle this kernel fault? */
297 if (fixup_exception(regs)) 289 if (fixup_exception(regs))
298 return; 290 return;
@@ -338,14 +330,13 @@ no_context:
338 */ 330 */
339out_of_memory: 331out_of_memory:
340 up_read(&mm->mmap_sem); 332 up_read(&mm->mmap_sem);
341 if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR) 333 printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
342 goto no_context; 334 if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
343 pagefault_out_of_memory(); 335 do_exit(SIGKILL);
344 return; 336 goto no_context;
345 337
346do_sigbus: 338do_sigbus:
347 up_read(&mm->mmap_sem); 339 up_read(&mm->mmap_sem);
348 monitor_signal(regs);
349 340
350 /* 341 /*
351 * Send a sigbus, regardless of whether we were in kernel 342 * Send a sigbus, regardless of whether we were in kernel
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
index 6e6bc0e51521..48907cc3bdb7 100644
--- a/arch/mn10300/mm/init.c
+++ b/arch/mn10300/mm/init.c
@@ -41,6 +41,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
41 41
42unsigned long highstart_pfn, highend_pfn; 42unsigned long highstart_pfn, highend_pfn;
43 43
44#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
45static struct vm_struct user_iomap_vm;
46#endif
47
44/* 48/*
45 * set up paging 49 * set up paging
46 */ 50 */
@@ -73,7 +77,24 @@ void __init paging_init(void)
73 /* pass the memory from the bootmem allocator to the main allocator */ 77 /* pass the memory from the bootmem allocator to the main allocator */
74 free_area_init(zones_size); 78 free_area_init(zones_size);
75 79
76 __flush_tlb_all(); 80#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
81 /* The Atomic Operation Unit registers need to be mapped to userspace
82 * for all processes. The following uses vm_area_register_early() to
83 * reserve the first page of the vmalloc area and sets the pte for that
84 * page.
85 *
86 * glibc hardcodes this virtual mapping, so we're pretty much stuck with
87 * it from now on.
88 */
89 user_iomap_vm.flags = VM_USERMAP;
90 user_iomap_vm.size = 1 << PAGE_SHIFT;
91 vm_area_register_early(&user_iomap_vm, PAGE_SIZE);
92 ppte = kernel_vmalloc_ptes;
93 set_pte(ppte, pfn_pte(USER_ATOMIC_OPS_PAGE_ADDR >> PAGE_SHIFT,
94 PAGE_USERIO));
95#endif
96
97 local_flush_tlb_all();
77} 98}
78 99
79/* 100/*
@@ -84,8 +105,7 @@ void __init mem_init(void)
84 int codesize, reservedpages, datasize, initsize; 105 int codesize, reservedpages, datasize, initsize;
85 int tmp; 106 int tmp;
86 107
87 if (!mem_map) 108 BUG_ON(!mem_map);
88 BUG();
89 109
90#define START_PFN (contig_page_data.bdata->node_min_pfn) 110#define START_PFN (contig_page_data.bdata->node_min_pfn)
91#define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn) 111#define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn)
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index 6dffbf97ac26..eef989c1d0c1 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -449,8 +449,7 @@ found_opcode:
449 regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]); 449 regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
450 450
451 tmp = format_tbl[pop->format].opsz; 451 tmp = format_tbl[pop->format].opsz;
452 if (tmp > noc) 452 BUG_ON(tmp > noc); /* match was less complete than it ought to have been */
453 BUG(); /* match was less complete than it ought to have been */
454 453
455 if (tmp < noc) { 454 if (tmp < noc) {
456 tmp = noc - tmp; 455 tmp = noc - tmp;
diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c
index 36ba02191d40..a4f7d3dcc6e6 100644
--- a/arch/mn10300/mm/mmu-context.c
+++ b/arch/mn10300/mm/mmu-context.c
@@ -13,40 +13,15 @@
13#include <asm/mmu_context.h> 13#include <asm/mmu_context.h>
14#include <asm/tlbflush.h> 14#include <asm/tlbflush.h>
15 15
16#ifdef CONFIG_MN10300_TLB_USE_PIDR
16/* 17/*
17 * list of the MMU contexts last allocated on each CPU 18 * list of the MMU contexts last allocated on each CPU
18 */ 19 */
19unsigned long mmu_context_cache[NR_CPUS] = { 20unsigned long mmu_context_cache[NR_CPUS] = {
20 [0 ... NR_CPUS - 1] = MMU_CONTEXT_FIRST_VERSION * 2 - 1, 21 [0 ... NR_CPUS - 1] =
22 MMU_CONTEXT_FIRST_VERSION * 2 - (1 - MMU_CONTEXT_TLBPID_LOCK_NR),
21}; 23};
22 24#endif /* CONFIG_MN10300_TLB_USE_PIDR */
23/*
24 * flush the specified TLB entry
25 */
26void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
27{
28 unsigned long pteu, cnx, flags;
29
30 addr &= PAGE_MASK;
31
32 /* make sure the context doesn't migrate and defend against
33 * interference from vmalloc'd regions */
34 local_irq_save(flags);
35
36 cnx = mm_context(vma->vm_mm);
37
38 if (cnx != MMU_NO_CONTEXT) {
39 pteu = addr | (cnx & 0x000000ffUL);
40 IPTEU = pteu;
41 DPTEU = pteu;
42 if (IPTEL & xPTEL_V)
43 IPTEL = 0;
44 if (DPTEL & xPTEL_V)
45 DPTEL = 0;
46 }
47
48 local_irq_restore(flags);
49}
50 25
51/* 26/*
52 * preemptively set a TLB entry 27 * preemptively set a TLB entry
@@ -63,10 +38,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *pte
63 * interference from vmalloc'd regions */ 38 * interference from vmalloc'd regions */
64 local_irq_save(flags); 39 local_irq_save(flags);
65 40
41 cnx = ~MMU_NO_CONTEXT;
42#ifdef CONFIG_MN10300_TLB_USE_PIDR
66 cnx = mm_context(vma->vm_mm); 43 cnx = mm_context(vma->vm_mm);
44#endif
67 45
68 if (cnx != MMU_NO_CONTEXT) { 46 if (cnx != MMU_NO_CONTEXT) {
69 pteu = addr | (cnx & 0x000000ffUL); 47 pteu = addr;
48#ifdef CONFIG_MN10300_TLB_USE_PIDR
49 pteu |= cnx & MMU_CONTEXT_TLBPID_MASK;
50#endif
70 if (!(pte_val(pte) & _PAGE_NX)) { 51 if (!(pte_val(pte) & _PAGE_NX)) {
71 IPTEU = pteu; 52 IPTEU = pteu;
72 if (IPTEL & xPTEL_V) 53 if (IPTEL & xPTEL_V)
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
index 9c1624c9e4e9..450f7ba3f8f2 100644
--- a/arch/mn10300/mm/pgtable.c
+++ b/arch/mn10300/mm/pgtable.c
@@ -59,7 +59,7 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
59 * It's enough to flush this one mapping. 59 * It's enough to flush this one mapping.
60 * (PGE mappings get flushed as well) 60 * (PGE mappings get flushed as well)
61 */ 61 */
62 __flush_tlb_one(vaddr); 62 local_flush_tlb_one(vaddr);
63} 63}
64 64
65pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) 65pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S
index 7095147dcb8b..b9940177d81b 100644
--- a/arch/mn10300/mm/tlb-mn10300.S
+++ b/arch/mn10300/mm/tlb-mn10300.S
@@ -27,7 +27,6 @@
27############################################################################### 27###############################################################################
28 .type itlb_miss,@function 28 .type itlb_miss,@function
29ENTRY(itlb_miss) 29ENTRY(itlb_miss)
30 and ~EPSW_NMID,epsw
31#ifdef CONFIG_GDBSTUB 30#ifdef CONFIG_GDBSTUB
32 movm [d2,d3,a2],(sp) 31 movm [d2,d3,a2],(sp)
33#else 32#else
@@ -38,6 +37,12 @@ ENTRY(itlb_miss)
38 nop 37 nop
39#endif 38#endif
40 39
40#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
41 mov (MMUCTR),d2
42 mov d2,(MMUCTR)
43#endif
44
45 and ~EPSW_NMID,epsw
41 mov (IPTEU),d3 46 mov (IPTEU),d3
42 mov (PTBR),a2 47 mov (PTBR),a2
43 mov d3,d2 48 mov d3,d2
@@ -56,10 +61,16 @@ ENTRY(itlb_miss)
56 btst _PAGE_VALID,d2 61 btst _PAGE_VALID,d2
57 beq itlb_miss_fault # jump if doesn't point to a page 62 beq itlb_miss_fault # jump if doesn't point to a page
58 # (might be a swap id) 63 # (might be a swap id)
64#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
59 bset _PAGE_ACCESSED,(0,a2) 65 bset _PAGE_ACCESSED,(0,a2)
60 and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2 66#elif ((_PAGE_ACCESSED & 0xffff00ff) == 0)
67 bset +(_PAGE_ACCESSED >> 8),(1,a2)
68#else
69#error "_PAGE_ACCESSED value is out of range"
70#endif
71 and ~xPTEL2_UNUSED1,d2
61itlb_miss_set: 72itlb_miss_set:
62 mov d2,(IPTEL) # change the TLB 73 mov d2,(IPTEL2) # change the TLB
63#ifdef CONFIG_GDBSTUB 74#ifdef CONFIG_GDBSTUB
64 movm (sp),[d2,d3,a2] 75 movm (sp),[d2,d3,a2]
65#endif 76#endif
@@ -79,7 +90,6 @@ itlb_miss_fault:
79############################################################################### 90###############################################################################
80 .type dtlb_miss,@function 91 .type dtlb_miss,@function
81ENTRY(dtlb_miss) 92ENTRY(dtlb_miss)
82 and ~EPSW_NMID,epsw
83#ifdef CONFIG_GDBSTUB 93#ifdef CONFIG_GDBSTUB
84 movm [d2,d3,a2],(sp) 94 movm [d2,d3,a2],(sp)
85#else 95#else
@@ -90,6 +100,12 @@ ENTRY(dtlb_miss)
90 nop 100 nop
91#endif 101#endif
92 102
103#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
104 mov (MMUCTR),d2
105 mov d2,(MMUCTR)
106#endif
107
108 and ~EPSW_NMID,epsw
93 mov (DPTEU),d3 109 mov (DPTEU),d3
94 mov (PTBR),a2 110 mov (PTBR),a2
95 mov d3,d2 111 mov d3,d2
@@ -108,10 +124,16 @@ ENTRY(dtlb_miss)
108 btst _PAGE_VALID,d2 124 btst _PAGE_VALID,d2
109 beq dtlb_miss_fault # jump if doesn't point to a page 125 beq dtlb_miss_fault # jump if doesn't point to a page
110 # (might be a swap id) 126 # (might be a swap id)
127#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
111 bset _PAGE_ACCESSED,(0,a2) 128 bset _PAGE_ACCESSED,(0,a2)
112 and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2 129#elif ((_PAGE_ACCESSED & 0xffff00ff) == 0)
130 bset +(_PAGE_ACCESSED >> 8),(1,a2)
131#else
132#error "_PAGE_ACCESSED value is out of range"
133#endif
134 and ~xPTEL2_UNUSED1,d2
113dtlb_miss_set: 135dtlb_miss_set:
114 mov d2,(DPTEL) # change the TLB 136 mov d2,(DPTEL2) # change the TLB
115#ifdef CONFIG_GDBSTUB 137#ifdef CONFIG_GDBSTUB
116 movm (sp),[d2,d3,a2] 138 movm (sp),[d2,d3,a2]
117#endif 139#endif
@@ -130,9 +152,15 @@ dtlb_miss_fault:
130############################################################################### 152###############################################################################
131 .type itlb_aerror,@function 153 .type itlb_aerror,@function
132ENTRY(itlb_aerror) 154ENTRY(itlb_aerror)
133 and ~EPSW_NMID,epsw
134 add -4,sp 155 add -4,sp
135 SAVE_ALL 156 SAVE_ALL
157
158#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
159 mov (MMUCTR),d1
160 mov d1,(MMUCTR)
161#endif
162
163 and ~EPSW_NMID,epsw
136 add -4,sp # need to pass three params 164 add -4,sp # need to pass three params
137 165
138 # calculate the fault code 166 # calculate the fault code
@@ -140,15 +168,13 @@ ENTRY(itlb_aerror)
140 or 0x00010000,d1 # it's an instruction fetch 168 or 0x00010000,d1 # it's an instruction fetch
141 169
142 # determine the page address 170 # determine the page address
143 mov (IPTEU),a2 171 mov (IPTEU),d0
144 mov a2,d0
145 and PAGE_MASK,d0 172 and PAGE_MASK,d0
146 mov d0,(12,sp) 173 mov d0,(12,sp)
147 174
148 clr d0 175 clr d0
149 mov d0,(IPTEL) 176 mov d0,(IPTEL2)
150 177
151 and ~EPSW_NMID,epsw
152 or EPSW_IE,epsw 178 or EPSW_IE,epsw
153 mov fp,d0 179 mov fp,d0
154 call do_page_fault[],0 # do_page_fault(regs,code,addr 180 call do_page_fault[],0 # do_page_fault(regs,code,addr
@@ -163,10 +189,16 @@ ENTRY(itlb_aerror)
163############################################################################### 189###############################################################################
164 .type dtlb_aerror,@function 190 .type dtlb_aerror,@function
165ENTRY(dtlb_aerror) 191ENTRY(dtlb_aerror)
166 and ~EPSW_NMID,epsw
167 add -4,sp 192 add -4,sp
168 SAVE_ALL 193 SAVE_ALL
194
195#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
196 mov (MMUCTR),d1
197 mov d1,(MMUCTR)
198#endif
199
169 add -4,sp # need to pass three params 200 add -4,sp # need to pass three params
201 and ~EPSW_NMID,epsw
170 202
171 # calculate the fault code 203 # calculate the fault code
172 movhu (MMUFCR_DFC),d1 204 movhu (MMUFCR_DFC),d1
@@ -178,9 +210,8 @@ ENTRY(dtlb_aerror)
178 mov d0,(12,sp) 210 mov d0,(12,sp)
179 211
180 clr d0 212 clr d0
181 mov d0,(DPTEL) 213 mov d0,(DPTEL2)
182 214
183 and ~EPSW_NMID,epsw
184 or EPSW_IE,epsw 215 or EPSW_IE,epsw
185 mov fp,d0 216 mov fp,d0
186 call do_page_fault[],0 # do_page_fault(regs,code,addr 217 call do_page_fault[],0 # do_page_fault(regs,code,addr
diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c
new file mode 100644
index 000000000000..0b6a5ad1960e
--- /dev/null
+++ b/arch/mn10300/mm/tlb-smp.c
@@ -0,0 +1,214 @@
1/* SMP TLB 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#include <linux/interrupt.h>
16#include <linux/spinlock.h>
17#include <linux/init.h>
18#include <linux/jiffies.h>
19#include <linux/cpumask.h>
20#include <linux/err.h>
21#include <linux/kernel.h>
22#include <linux/delay.h>
23#include <linux/sched.h>
24#include <linux/profile.h>
25#include <linux/smp.h>
26#include <asm/tlbflush.h>
27#include <asm/system.h>
28#include <asm/bitops.h>
29#include <asm/processor.h>
30#include <asm/bug.h>
31#include <asm/exceptions.h>
32#include <asm/hardirq.h>
33#include <asm/fpu.h>
34#include <asm/mmu_context.h>
35#include <asm/thread_info.h>
36#include <asm/cpu-regs.h>
37#include <asm/intctl-regs.h>
38
39/*
40 * For flush TLB
41 */
42#define FLUSH_ALL 0xffffffff
43
44static cpumask_t flush_cpumask;
45static struct mm_struct *flush_mm;
46static unsigned long flush_va;
47static DEFINE_SPINLOCK(tlbstate_lock);
48
49DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
50 &init_mm, 0
51};
52
53static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
54 unsigned long va);
55static void do_flush_tlb_all(void *info);
56
57/**
58 * smp_flush_tlb - Callback to invalidate the TLB.
59 * @unused: Callback context (ignored).
60 */
61void smp_flush_tlb(void *unused)
62{
63 unsigned long cpu_id;
64
65 cpu_id = get_cpu();
66
67 if (!cpu_isset(cpu_id, flush_cpumask))
68 /* This was a BUG() but until someone can quote me the line
69 * from the intel manual that guarantees an IPI to multiple
70 * CPUs is retried _only_ on the erroring CPUs its staying as a
71 * return
72 *
73 * BUG();
74 */
75 goto out;
76
77 if (flush_va == FLUSH_ALL)
78 local_flush_tlb();
79 else
80 local_flush_tlb_page(flush_mm, flush_va);
81
82 smp_mb__before_clear_bit();
83 cpu_clear(cpu_id, flush_cpumask);
84 smp_mb__after_clear_bit();
85out:
86 put_cpu();
87}
88
89/**
90 * flush_tlb_others - Tell the specified CPUs to invalidate their TLBs
91 * @cpumask: The list of CPUs to target.
92 * @mm: The VM context to flush from (if va!=FLUSH_ALL).
93 * @va: Virtual address to flush or FLUSH_ALL to flush everything.
94 */
95static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
96 unsigned long va)
97{
98 cpumask_t tmp;
99
100 /* A couple of sanity checks (to be removed):
101 * - mask must not be empty
102 * - current CPU must not be in mask
103 * - we do not send IPIs to as-yet unbooted CPUs.
104 */
105 BUG_ON(!mm);
106 BUG_ON(cpus_empty(cpumask));
107 BUG_ON(cpu_isset(smp_processor_id(), cpumask));
108
109 cpus_and(tmp, cpumask, cpu_online_map);
110 BUG_ON(!cpus_equal(cpumask, tmp));
111
112 /* I'm not happy about this global shared spinlock in the MM hot path,
113 * but we'll see how contended it is.
114 *
115 * Temporarily this turns IRQs off, so that lockups are detected by the
116 * NMI watchdog.
117 */
118 spin_lock(&tlbstate_lock);
119
120 flush_mm = mm;
121 flush_va = va;
122#if NR_CPUS <= BITS_PER_LONG
123 atomic_set_mask(cpumask.bits[0], &flush_cpumask.bits[0]);
124#else
125#error Not supported.
126#endif
127
128 /* FIXME: if NR_CPUS>=3, change send_IPI_mask */
129 smp_call_function(smp_flush_tlb, NULL, 1);
130
131 while (!cpus_empty(flush_cpumask))
132 /* Lockup detection does not belong here */
133 smp_mb();
134
135 flush_mm = NULL;
136 flush_va = 0;
137 spin_unlock(&tlbstate_lock);
138}
139
140/**
141 * flush_tlb_mm - Invalidate TLB of specified VM context
142 * @mm: The VM context to invalidate.
143 */
144void flush_tlb_mm(struct mm_struct *mm)
145{
146 cpumask_t cpu_mask;
147
148 preempt_disable();
149 cpu_mask = mm->cpu_vm_mask;
150 cpu_clear(smp_processor_id(), cpu_mask);
151
152 local_flush_tlb();
153 if (!cpus_empty(cpu_mask))
154 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
155
156 preempt_enable();
157}
158
159/**
160 * flush_tlb_current_task - Invalidate TLB of current task
161 */
162void flush_tlb_current_task(void)
163{
164 struct mm_struct *mm = current->mm;
165 cpumask_t cpu_mask;
166
167 preempt_disable();
168 cpu_mask = mm->cpu_vm_mask;
169 cpu_clear(smp_processor_id(), cpu_mask);
170
171 local_flush_tlb();
172 if (!cpus_empty(cpu_mask))
173 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
174
175 preempt_enable();
176}
177
178/**
179 * flush_tlb_page - Invalidate TLB of page
180 * @vma: The VM context to invalidate the page for.
181 * @va: The virtual address of the page to invalidate.
182 */
183void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
184{
185 struct mm_struct *mm = vma->vm_mm;
186 cpumask_t cpu_mask;
187
188 preempt_disable();
189 cpu_mask = mm->cpu_vm_mask;
190 cpu_clear(smp_processor_id(), cpu_mask);
191
192 local_flush_tlb_page(mm, va);
193 if (!cpus_empty(cpu_mask))
194 flush_tlb_others(cpu_mask, mm, va);
195
196 preempt_enable();
197}
198
199/**
200 * do_flush_tlb_all - Callback to completely invalidate a TLB
201 * @unused: Callback context (ignored).
202 */
203static void do_flush_tlb_all(void *unused)
204{
205 local_flush_tlb_all();
206}
207
208/**
209 * flush_tlb_all - Completely invalidate TLBs on all CPUs
210 */
211void flush_tlb_all(void)
212{
213 on_each_cpu(do_flush_tlb_all, 0, 1);
214}
diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h
index bdc1f9a59b4c..c1528004163c 100644
--- a/arch/mn10300/proc-mn103e010/include/proc/cache.h
+++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h
@@ -30,4 +30,13 @@
30 */ 30 */
31#define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4 31#define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4
32 32
33/*
34 * The size of range at which it becomes more economical to just flush the
35 * whole cache rather than trying to flush the specified range.
36 */
37#define MN10300_DCACHE_FLUSH_BORDER \
38 +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
39#define MN10300_DCACHE_FLUSH_INV_BORDER \
40 +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
41
33#endif /* _ASM_PROC_CACHE_H */ 42#endif /* _ASM_PROC_CACHE_H */
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/dmactl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h
new file mode 100644
index 000000000000..d72d328d1f9c
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h
@@ -0,0 +1,102 @@
1/* MN103E010 on-board DMA controller registers
2 *
3 * Copyright (C) 2007 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#ifndef _ASM_PROC_DMACTL_REGS_H
13#define _ASM_PROC_DMACTL_REGS_H
14
15#include <asm/cpu-regs.h>
16
17#ifdef __KERNEL__
18
19/* DMA registers */
20#define DMxCTR(N) __SYSREG(0xd2000000 + ((N) * 0x100), u32) /* control reg */
21#define DMxCTR_BG 0x0000001f /* transfer request source */
22#define DMxCTR_BG_SOFT 0x00000000 /* - software source */
23#define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */
24#define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */
25#define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */
26#define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */
27#define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */
28#define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */
29#define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */
30#define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */
31#define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */
32#define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */
33#define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */
34#define DMxCTR_BG_AFE 0x0000000d /* - analogue front-end interrupt source */
35#define DMxCTR_BG_ADC 0x0000000e /* - A/D conversion end interrupt source */
36#define DMxCTR_BG_IRDA 0x0000000f /* - IrDA interrupt source */
37#define DMxCTR_BG_RTC 0x00000010 /* - RTC interrupt source */
38#define DMxCTR_BG_XIRQ0 0x00000011 /* - XIRQ0 pin interrupt source */
39#define DMxCTR_BG_XIRQ1 0x00000012 /* - XIRQ1 pin interrupt source */
40#define DMxCTR_BG_XDMR0 0x00000013 /* - external request 0 source (XDMR0 pin) */
41#define DMxCTR_BG_XDMR1 0x00000014 /* - external request 1 source (XDMR1 pin) */
42#define DMxCTR_SAM 0x000000e0 /* DMA transfer src addr mode */
43#define DMxCTR_SAM_INCR 0x00000000 /* - increment */
44#define DMxCTR_SAM_DECR 0x00000020 /* - decrement */
45#define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */
46#define DMxCTR_DAM 0x00000000 /* DMA transfer dest addr mode */
47#define DMxCTR_DAM_INCR 0x00000000 /* - increment */
48#define DMxCTR_DAM_DECR 0x00000100 /* - decrement */
49#define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */
50#define DMxCTR_TM 0x00001800 /* DMA transfer mode */
51#define DMxCTR_TM_BATCH 0x00000000 /* - batch transfer */
52#define DMxCTR_TM_INTERM 0x00001000 /* - intermittent transfer */
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_TEN 0x00010000 /* DMA channel transfer enable */
59#define DMxCTR_RQM 0x00060000 /* external request input source mode */
60#define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */
61#define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */
62#define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */
63#define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */
64#define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */
65#define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */
66
67#define DMxSRC(N) __SYSREG(0xd2000004 + ((N) * 0x100), u32) /* control reg */
68
69#define DMxDST(N) __SYSREG(0xd2000008 + ((N) * 0x100), u32) /* src addr reg */
70
71#define DMxSIZ(N) __SYSREG(0xd200000c + ((N) * 0x100), u32) /* dest addr reg */
72#define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */
73
74#define DMxCYC(N) __SYSREG(0xd2000010 + ((N) * 0x100), u32) /* intermittent
75 * size reg */
76#define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */
77
78#define DM0IRQ 16 /* DMA channel 0 complete IRQ */
79#define DM1IRQ 17 /* DMA channel 1 complete IRQ */
80#define DM2IRQ 18 /* DMA channel 2 complete IRQ */
81#define DM3IRQ 19 /* DMA channel 3 complete IRQ */
82
83#define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */
84#define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */
85#define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */
86#define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */
87
88#ifndef __ASSEMBLY__
89
90struct mn10300_dmactl_regs {
91 u32 ctr;
92 const void *src;
93 void *dst;
94 u32 siz;
95 u32 cyc;
96} __attribute__((aligned(0x100)));
97
98#endif /* __ASSEMBLY__ */
99
100#endif /* __KERNEL__ */
101
102#endif /* _ASM_PROC_DMACTL_REGS_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/include/proc/proc.h b/arch/mn10300/proc-mn103e010/include/proc/proc.h
index 22a2b93f70b7..39c4f8e7d2d3 100644
--- a/arch/mn10300/proc-mn103e010/include/proc/proc.h
+++ b/arch/mn10300/proc-mn103e010/include/proc/proc.h
@@ -12,7 +12,7 @@
12#ifndef _ASM_PROC_PROC_H 12#ifndef _ASM_PROC_PROC_H
13#define _ASM_PROC_PROC_H 13#define _ASM_PROC_PROC_H
14 14
15#define PROCESSOR_VENDOR_NAME "Matsushita" 15#define PROCESSOR_VENDOR_NAME "Panasonic"
16#define PROCESSOR_MODEL_NAME "mn103e010" 16#define PROCESSOR_MODEL_NAME "mn103e010"
17 17
18#endif /* _ASM_PROC_PROC_H */ 18#endif /* _ASM_PROC_PROC_H */
diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c
index 9a482efafa82..27b97980dca4 100644
--- a/arch/mn10300/proc-mn103e010/proc-init.c
+++ b/arch/mn10300/proc-mn103e010/proc-init.c
@@ -9,7 +9,9 @@
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#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <asm/fpu.h>
12#include <asm/rtc.h> 13#include <asm/rtc.h>
14#include <asm/busctl-regs.h>
13 15
14/* 16/*
15 * initialise the on-silicon processor peripherals 17 * initialise the on-silicon processor peripherals
@@ -28,6 +30,7 @@ asmlinkage void __init processor_init(void)
28 __set_intr_stub(EXCEP_DAERROR, dtlb_aerror); 30 __set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
29 __set_intr_stub(EXCEP_BUSERROR, raw_bus_error); 31 __set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
30 __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault); 32 __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
33 __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled);
31 __set_intr_stub(EXCEP_SYSCALL0, system_call); 34 __set_intr_stub(EXCEP_SYSCALL0, system_call);
32 35
33 __set_intr_stub(EXCEP_NMI, nmi_handler); 36 __set_intr_stub(EXCEP_NMI, nmi_handler);
@@ -73,3 +76,37 @@ asmlinkage void __init processor_init(void)
73 76
74 calibrate_clock(); 77 calibrate_clock();
75} 78}
79
80/*
81 * determine the memory size and base from the memory controller regs
82 */
83void __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
5obj-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
91struct 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 */
34asmlinkage 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 */
109void __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
19extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
20extern unsigned long mn10300_iobclk;
21extern 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 f206b63c95b4..cc18fe7d8b90 100644
--- a/arch/mn10300/unit-asb2303/include/unit/timex.h
+++ b/arch/mn10300/unit-asb2303/include/unit/timex.h
@@ -1,6 +1,6 @@
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, 2010 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 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -17,67 +17,72 @@
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
23 */ 24 */
24 25
25#define TMJCBR_MAX 0xffff 26#define TMJCBR_MAX 0xffff
26#define TMJCBC TM01BC
27
28#define TMJCMD TM01MD
29#define TMJCBR TM01BR
30#define TMJCIRQ TM1IRQ 27#define TMJCIRQ TM1IRQ
31#define TMJCICR TM1ICR 28#define TMJCICR TM1ICR
32#define TMJCICR_LEVEL GxICR_LEVEL_5
33 29
34#ifndef __ASSEMBLY__ 30#ifndef __ASSEMBLY__
35 31
36static inline void startup_jiffies_counter(void) 32#define MN10300_SRC_IOCLK MN10300_IOCLK
33
34#ifndef HZ
35# error HZ undeclared.
36#endif /* !HZ */
37/* use as little prescaling as possible to avoid losing accuracy */
38#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
39# define IOCLK_PRESCALE 1
40# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK
41# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK
42#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
43# define IOCLK_PRESCALE 8
44# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8
45# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8
46#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
47# define IOCLK_PRESCALE 32
48# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32
49# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32
50#else
51# error You lose.
52#endif
53
54#define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
55#define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
56
57#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
58#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
59
60static inline void stop_jiffies_counter(void)
37{ 61{
38 unsigned rate; 62 u16 tmp;
39 u16 md, t16; 63 TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
40 64 tmp = TM01MD;
41 /* use as little prescaling as possible to avoid losing accuracy */ 65}
42 md = TM0MD_SRC_IOCLK;
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 if (rate > TMJCBR_MAX)
54 BUG();
55 }
56 }
57 66
58 TMJCBR = rate - 1; 67static inline void reload_jiffies_counter(u32 cnt)
59 t16 = TMJCBR; 68{
69 u32 tmp;
60 70
61 TMJCMD = 71 TM01BR = cnt;
62 md | 72 tmp = TM01BR;
63 TM1MD_SRC_TM0CASCADE << 8 |
64 TM0MD_INIT_COUNTER |
65 TM1MD_INIT_COUNTER << 8;
66 73
67 TMJCMD = 74 TM01MD = JC_TIMER_CLKSRC | \
68 md | 75 TM1MD_SRC_TM0CASCADE << 8 | \
69 TM1MD_SRC_TM0CASCADE << 8 | 76 TM0MD_INIT_COUNTER | \
70 TM0MD_COUNT_ENABLE | 77 TM1MD_INIT_COUNTER << 8;
71 TM1MD_COUNT_ENABLE << 8;
72 78
73 t16 = TMJCMD;
74 79
75 TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; 80 TM01MD = JC_TIMER_CLKSRC | \
76 t16 = TMJCICR; 81 TM1MD_SRC_TM0CASCADE << 8 | \
77} 82 TM0MD_COUNT_ENABLE | \
83 TM1MD_COUNT_ENABLE << 8;
78 84
79static inline void shutdown_jiffies_counter(void) 85 tmp = TM01MD;
80{
81} 86}
82 87
83#endif /* !__ASSEMBLY__ */ 88#endif /* !__ASSEMBLY__ */
@@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void)
94 99
95static inline void startup_timestamp_counter(void) 100static inline void startup_timestamp_counter(void)
96{ 101{
102 u32 t32;
103
97 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time 104 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
98 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate 105 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
99 */ 106 */
100 TM45BR = TMTSCBR_MAX; 107 TM45BR = TMTSCBR_MAX;
108 t32 = TM45BR;
101 109
102 TM4MD = TM4MD_SRC_IOCLK; 110 TM4MD = TSC_TIMER_CLKSRC;
103 TM4MD |= TM4MD_INIT_COUNTER; 111 TM4MD |= TM4MD_INIT_COUNTER;
104 TM4MD &= ~TM4MD_INIT_COUNTER; 112 TM4MD &= ~TM4MD_INIT_COUNTER;
105 TM4ICR = 0; 113 TM4ICR = 0;
114 t32 = TM4ICR;
106 115
107 TM5MD = TM5MD_SRC_TM4CASCADE; 116 TM5MD = TM5MD_SRC_TM4CASCADE;
108 TM5MD |= TM5MD_INIT_COUNTER; 117 TM5MD |= TM5MD_INIT_COUNTER;
109 TM5MD &= ~TM5MD_INIT_COUNTER; 118 TM5MD &= ~TM5MD_INIT_COUNTER;
110 TM5ICR = 0; 119 TM5ICR = 0;
120 t32 = TM5ICR;
111 121
112 TM5MD |= TM5MD_COUNT_ENABLE; 122 TM5MD |= TM5MD_COUNT_ENABLE;
113 TM4MD |= TM4MD_COUNT_ENABLE; 123 TM4MD |= TM4MD_COUNT_ENABLE;
124 t32 = TM5MD;
125 t32 = TM4MD;
114} 126}
115 127
116static inline void shutdown_timestamp_counter(void) 128static inline void shutdown_timestamp_counter(void)
117{ 129{
130 u8 t8;
118 TM4MD = 0; 131 TM4MD = 0;
119 TM5MD = 0; 132 TM5MD = 0;
133 t8 = TM4MD;
134 t8 = TM5MD;
120} 135}
121 136
122/* 137/*
@@ -127,7 +142,7 @@ typedef unsigned long cycles_t;
127 142
128static inline cycles_t read_timestamp_counter(void) 143static inline cycles_t read_timestamp_counter(void)
129{ 144{
130 return (cycles_t)TMTSCBC; 145 return (cycles_t)~TMTSCBC;
131} 146}
132 147
133#endif /* !__ASSEMBLY__ */ 148#endif /* !__ASSEMBLY__ */
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
19extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
20extern unsigned long mn10300_iobclk;
21extern 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 d1c72d59fa9f..758af30d1a16 100644
--- a/arch/mn10300/unit-asb2305/include/unit/timex.h
+++ b/arch/mn10300/unit-asb2305/include/unit/timex.h
@@ -1,6 +1,6 @@
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, 2010 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 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -17,67 +17,72 @@
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
23 */ 24 */
24 25
25#define TMJCBR_MAX 0xffff 26#define TMJCBR_MAX 0xffff
26#define TMJCBC TM01BC
27
28#define TMJCMD TM01MD
29#define TMJCBR TM01BR
30#define TMJCIRQ TM1IRQ 27#define TMJCIRQ TM1IRQ
31#define TMJCICR TM1ICR 28#define TMJCICR TM1ICR
32#define TMJCICR_LEVEL GxICR_LEVEL_5
33 29
34#ifndef __ASSEMBLY__ 30#ifndef __ASSEMBLY__
35 31
36static inline void startup_jiffies_counter(void) 32#define MN10300_SRC_IOCLK MN10300_IOCLK
33
34#ifndef HZ
35# error HZ undeclared.
36#endif /* !HZ */
37/* use as little prescaling as possible to avoid losing accuracy */
38#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
39# define IOCLK_PRESCALE 1
40# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK
41# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK
42#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
43# define IOCLK_PRESCALE 8
44# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8
45# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8
46#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
47# define IOCLK_PRESCALE 32
48# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32
49# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32
50#else
51# error You lose.
52#endif
53
54#define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
55#define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
56
57#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
58#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
59
60static inline void stop_jiffies_counter(void)
37{ 61{
38 unsigned rate; 62 u16 tmp;
39 u16 md, t16; 63 TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
40 64 tmp = TM01MD;
41 /* use as little prescaling as possible to avoid losing accuracy */ 65}
42 md = TM0MD_SRC_IOCLK;
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 if (rate > TMJCBR_MAX)
54 BUG();
55 }
56 }
57 66
58 TMJCBR = rate - 1; 67static inline void reload_jiffies_counter(u32 cnt)
59 t16 = TMJCBR; 68{
69 u32 tmp;
60 70
61 TMJCMD = 71 TM01BR = cnt;
62 md | 72 tmp = TM01BR;
63 TM1MD_SRC_TM0CASCADE << 8 |
64 TM0MD_INIT_COUNTER |
65 TM1MD_INIT_COUNTER << 8;
66 73
67 TMJCMD = 74 TM01MD = JC_TIMER_CLKSRC | \
68 md | 75 TM1MD_SRC_TM0CASCADE << 8 | \
69 TM1MD_SRC_TM0CASCADE << 8 | 76 TM0MD_INIT_COUNTER | \
70 TM0MD_COUNT_ENABLE | 77 TM1MD_INIT_COUNTER << 8;
71 TM1MD_COUNT_ENABLE << 8;
72 78
73 t16 = TMJCMD;
74 79
75 TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; 80 TM01MD = JC_TIMER_CLKSRC | \
76 t16 = TMJCICR; 81 TM1MD_SRC_TM0CASCADE << 8 | \
77} 82 TM0MD_COUNT_ENABLE | \
83 TM1MD_COUNT_ENABLE << 8;
78 84
79static inline void shutdown_jiffies_counter(void) 85 tmp = TM01MD;
80{
81} 86}
82 87
83#endif /* !__ASSEMBLY__ */ 88#endif /* !__ASSEMBLY__ */
@@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void)
94 99
95static inline void startup_timestamp_counter(void) 100static inline void startup_timestamp_counter(void)
96{ 101{
102 u32 t32;
103
97 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time 104 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
98 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate 105 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
99 */ 106 */
100 TM45BR = TMTSCBR_MAX; 107 TM45BR = TMTSCBR_MAX;
108 t32 = TM45BR;
101 109
102 TM4MD = TM4MD_SRC_IOCLK; 110 TM4MD = TSC_TIMER_CLKSRC;
103 TM4MD |= TM4MD_INIT_COUNTER; 111 TM4MD |= TM4MD_INIT_COUNTER;
104 TM4MD &= ~TM4MD_INIT_COUNTER; 112 TM4MD &= ~TM4MD_INIT_COUNTER;
105 TM4ICR = 0; 113 TM4ICR = 0;
114 t32 = TM4ICR;
106 115
107 TM5MD = TM5MD_SRC_TM4CASCADE; 116 TM5MD = TM5MD_SRC_TM4CASCADE;
108 TM5MD |= TM5MD_INIT_COUNTER; 117 TM5MD |= TM5MD_INIT_COUNTER;
109 TM5MD &= ~TM5MD_INIT_COUNTER; 118 TM5MD &= ~TM5MD_INIT_COUNTER;
110 TM5ICR = 0; 119 TM5ICR = 0;
120 t32 = TM5ICR;
111 121
112 TM5MD |= TM5MD_COUNT_ENABLE; 122 TM5MD |= TM5MD_COUNT_ENABLE;
113 TM4MD |= TM4MD_COUNT_ENABLE; 123 TM4MD |= TM4MD_COUNT_ENABLE;
124 t32 = TM5MD;
125 t32 = TM4MD;
114} 126}
115 127
116static inline void shutdown_timestamp_counter(void) 128static inline void shutdown_timestamp_counter(void)
117{ 129{
130 u8 t8;
118 TM4MD = 0; 131 TM4MD = 0;
119 TM5MD = 0; 132 TM5MD = 0;
133 t8 = TM4MD;
134 t8 = TM5MD;
120} 135}
121 136
122/* 137/*
@@ -127,7 +142,7 @@ typedef unsigned long cycles_t;
127 142
128static inline cycles_t read_timestamp_counter(void) 143static inline cycles_t read_timestamp_counter(void)
129{ 144{
130 return (cycles_t) TMTSCBC; 145 return (cycles_t)~TMTSCBC;
131} 146}
132 147
133#endif /* !__ASSEMBLY__ */ 148#endif /* !__ASSEMBLY__ */
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index 45b40ac6c464..8e6763e6f250 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -93,7 +93,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
93 struct pci_bus *bus; 93 struct pci_bus *bus;
94 struct pci_dev *dev; 94 struct pci_dev *dev;
95 int idx; 95 int idx;
96 struct resource *r, *pr; 96 struct resource *r;
97 97
98 /* Depth-First Search on bus tree */ 98 /* Depth-First Search on bus tree */
99 list_for_each_entry(bus, bus_list, node) { 99 list_for_each_entry(bus, bus_list, node) {
@@ -105,10 +105,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
105 r = &dev->resource[idx]; 105 r = &dev->resource[idx];
106 if (!r->flags) 106 if (!r->flags)
107 continue; 107 continue;
108 pr = pci_find_parent_resource(dev, r);
109 if (!r->start || 108 if (!r->start ||
110 !pr || 109 pci_claim_resource(dev, idx) < 0) {
111 request_resource(pr, r) < 0) {
112 printk(KERN_ERR "PCI:" 110 printk(KERN_ERR "PCI:"
113 " Cannot allocate resource" 111 " Cannot allocate resource"
114 " region %d of bridge %s\n", 112 " region %d of bridge %s\n",
@@ -131,7 +129,7 @@ static void __init pcibios_allocate_resources(int pass)
131 struct pci_dev *dev = NULL; 129 struct pci_dev *dev = NULL;
132 int idx, disabled; 130 int idx, disabled;
133 u16 command; 131 u16 command;
134 struct resource *r, *pr; 132 struct resource *r;
135 133
136 for_each_pci_dev(dev) { 134 for_each_pci_dev(dev) {
137 pci_read_config_word(dev, PCI_COMMAND, &command); 135 pci_read_config_word(dev, PCI_COMMAND, &command);
@@ -150,8 +148,7 @@ static void __init pcibios_allocate_resources(int pass)
150 " (f=%lx, d=%d, p=%d)\n", 148 " (f=%lx, d=%d, p=%d)\n",
151 pci_name(dev), r->start, r->end, r->flags, 149 pci_name(dev), r->start, r->end, r->flags,
152 disabled, pass); 150 disabled, pass);
153 pr = pci_find_parent_resource(dev, r); 151 if (pci_claim_resource(dev, idx) < 0) {
154 if (!pr || request_resource(pr, r) < 0) {
155 printk(KERN_ERR "PCI:" 152 printk(KERN_ERR "PCI:"
156 " Cannot allocate resource" 153 " Cannot allocate resource"
157 " region %d of device %s\n", 154 " region %d of device %s\n",
@@ -184,7 +181,7 @@ static void __init pcibios_allocate_resources(int pass)
184static int __init pcibios_assign_resources(void) 181static int __init pcibios_assign_resources(void)
185{ 182{
186 struct pci_dev *dev = NULL; 183 struct pci_dev *dev = NULL;
187 struct resource *r, *pr; 184 struct resource *r;
188 185
189 if (!(pci_probe & PCI_ASSIGN_ROMS)) { 186 if (!(pci_probe & PCI_ASSIGN_ROMS)) {
190 /* Try to use BIOS settings for ROMs, otherwise let 187 /* Try to use BIOS settings for ROMs, otherwise let
@@ -194,8 +191,7 @@ static int __init pcibios_assign_resources(void)
194 r = &dev->resource[PCI_ROM_RESOURCE]; 191 r = &dev->resource[PCI_ROM_RESOURCE];
195 if (!r->flags || !r->start) 192 if (!r->flags || !r->start)
196 continue; 193 continue;
197 pr = pci_find_parent_resource(dev, r); 194 if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
198 if (!pr || request_resource(pr, r) < 0) {
199 r->end -= r->start; 195 r->end -= r->start;
200 r->start = 0; 196 r->start = 0;
201 } 197 }
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..b3263ecfc4ff
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/Makefile
@@ -0,0 +1,12 @@
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
10obj-y := unit-init.o leds.o irq-fpga.o
11
12obj-$(CONFIG_SMSC911X) += smsc911x.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..7cf12054db65
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
@@ -0,0 +1,52 @@
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(X) __SYSREG(0xa9001590+((X)*4), u16)
18#define ASB2364_FPGA_REG_IRQ_LAN ASB2364_FPGA_REG_IRQ(0)
19#define ASB2364_FPGA_REG_IRQ_UART ASB2364_FPGA_REG_IRQ(1)
20#define ASB2364_FPGA_REG_IRQ_I2C ASB2364_FPGA_REG_IRQ(2)
21#define ASB2364_FPGA_REG_IRQ_USB ASB2364_FPGA_REG_IRQ(3)
22#define ASB2364_FPGA_REG_IRQ_FPGA ASB2364_FPGA_REG_IRQ(5)
23
24#define ASB2364_FPGA_REG_MASK(X) __SYSREG(0xa9001590+((X)*4), u16)
25#define ASB2364_FPGA_REG_MASK_LAN ASB2364_FPGA_REG_MASK(0)
26#define ASB2364_FPGA_REG_MASK_UART ASB2364_FPGA_REG_MASK(1)
27#define ASB2364_FPGA_REG_MASK_I2C ASB2364_FPGA_REG_MASK(2)
28#define ASB2364_FPGA_REG_MASK_USB ASB2364_FPGA_REG_MASK(3)
29#define ASB2364_FPGA_REG_MASK_FPGA ASB2364_FPGA_REG_MASK(5)
30
31#define ASB2364_FPGA_REG_CPLD5_SET1 __SYSREG(0xa9002500, u16)
32#define ASB2364_FPGA_REG_CPLD5_SET2 __SYSREG(0xa9002504, u16)
33#define ASB2364_FPGA_REG_CPLD6_SET1 __SYSREG(0xa9002600, u16)
34#define ASB2364_FPGA_REG_CPLD6_SET2 __SYSREG(0xa9002604, u16)
35#define ASB2364_FPGA_REG_CPLD7_SET1 __SYSREG(0xa9002700, u16)
36#define ASB2364_FPGA_REG_CPLD7_SET2 __SYSREG(0xa9002704, u16)
37#define ASB2364_FPGA_REG_CPLD8_SET1 __SYSREG(0xa9002800, u16)
38#define ASB2364_FPGA_REG_CPLD8_SET2 __SYSREG(0xa9002804, u16)
39#define ASB2364_FPGA_REG_CPLD9_SET1 __SYSREG(0xa9002900, u16)
40#define ASB2364_FPGA_REG_CPLD9_SET2 __SYSREG(0xa9002904, u16)
41#define ASB2364_FPGA_REG_CPLD10_SET1 __SYSREG(0xa9002a00, u16)
42#define ASB2364_FPGA_REG_CPLD10_SET2 __SYSREG(0xa9002a04, u16)
43
44#define SyncExBus() \
45 do { \
46 unsigned short w; \
47 w = *(volatile short *)0xa9000000; \
48 } while (0)
49
50#endif /* __KERNEL__ */
51
52#endif /* _ASM_UNIT_FPGA_REGS_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/irq.h b/arch/mn10300/unit-asb2364/include/unit/irq.h
new file mode 100644
index 000000000000..786148e46565
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/irq.h
@@ -0,0 +1,35 @@
1/* ASB2364 FPGA irq numbers
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#ifndef _UNIT_IRQ_H
12#define _UNIT_IRQ_H
13
14#ifndef __ASSEMBLY__
15
16#ifdef CONFIG_SMP
17#define NR_CPU_IRQS GxICR_NUM_EXT_IRQS
18#else
19#define NR_CPU_IRQS GxICR_NUM_IRQS
20#endif
21
22enum {
23 FPGA_LAN_IRQ = NR_CPU_IRQS,
24 FPGA_UART_IRQ,
25 FPGA_I2C_IRQ,
26 FPGA_USB_IRQ,
27 FPGA_RESERVED_IRQ,
28 FPGA_FPGA_IRQ,
29 NR_IRQS
30};
31
32extern void __init irq_fpga_init(void);
33
34#endif /* !__ASSEMBLY__ */
35#endif /* _UNIT_IRQ_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__
47extern void peripheral_leds_display_exception(enum exception_code);
48extern void peripheral_leds_led_chase(void);
49extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int);
50extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int);
51extern 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
51static 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
82static 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 \
120do { \
121 /* release reset */ \
122 ASB2364_FPGA_REG_RESET_UART = 0x0001; \
123 SyncExBus(); \
124} while (0)
125
126#define SERIAL_CHECK_INTERRUPT \
127do { \
128 if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) { \
129 return IRQ_NONE; \
130 } \
131} while (0)
132
133#define SERIAL_CLEAR_INTERRUPT \
134do { \
135 ASB2364_FPGA_REG_IRQ_UART = 0x0001; \
136 SyncExBus(); \
137} while (0)
138
139#define SERIAL_SET_INT_MASK \
140do { \
141 ASB2364_FPGA_REG_MASK_UART = 0x0001; \
142 SyncExBus(); \
143} while (0)
144
145#define SERIAL_CLEAR_INT_MASK \
146do { \
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/smsc911x.h b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
new file mode 100644
index 000000000000..4c1ede535fa9
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
@@ -0,0 +1,171 @@
1/* Support for the SMSC911x NIC
2 *
3 * Copyright (C) 2006 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#ifndef _ASM_UNIT_SMSC911X_H
12#define _ASM_UNIT_SMSC911X_H
13
14#include <linux/netdevice.h>
15#include <proc/irq.h>
16#include <unit/fpga-regs.h>
17
18#define MN10300_USE_EXT_EEPROM
19
20
21#define SMSC911X_BASE 0xA8000000UL
22#define SMSC911X_BASE_END 0xA8000100UL
23#define SMSC911X_IRQ FPGA_LAN_IRQ
24
25/*
26 * Allow the FPGA to be initialised by the SMSC911x driver
27 */
28#undef SMSC_INITIALIZE
29#define SMSC_INITIALIZE() \
30do { \
31 /* release reset */ \
32 ASB2364_FPGA_REG_RESET_LAN = 0x0001; \
33 SyncExBus(); \
34} while (0)
35
36#ifdef MN10300_USE_EXT_EEPROM
37#include <linux/delay.h>
38#include <unit/clock.h>
39
40#define EEPROM_ADDRESS 0xA0
41#define MAC_OFFSET 0x0008
42#define USE_IIC_CH 0 /* 0 or 1 */
43#define IIC_OFFSET (0x80000 * USE_IIC_CH)
44#define IIC_DTRM __SYSREG(0xd8400000 + IIC_OFFSET, u32)
45#define IIC_DREC __SYSREG(0xd8400004 + IIC_OFFSET, u32)
46#define IIC_MYADD __SYSREG(0xd8400008 + IIC_OFFSET, u32)
47#define IIC_CLK __SYSREG(0xd840000c + IIC_OFFSET, u32)
48#define IIC_BRST __SYSREG(0xd8400010 + IIC_OFFSET, u32)
49#define IIC_HOLD __SYSREG(0xd8400014 + IIC_OFFSET, u32)
50#define IIC_BSTS __SYSREG(0xd8400018 + IIC_OFFSET, u32)
51#define IIC_ICR __SYSREG(0xd4000080 + 4 * USE_IIC_CH, u16)
52
53#define IIC_CLK_PLS ((unsigned short)(MN10300_IOCLK / 100000 - 1))
54#define IIC_CLK_LOW ((unsigned short)(IIC_CLK_PLS / 2))
55
56#define SYS_IIC_DTRM_Bit_STA ((unsigned short)0x0400)
57#define SYS_IIC_DTRM_Bit_STO ((unsigned short)0x0200)
58#define SYS_IIC_DTRM_Bit_ACK ((unsigned short)0x0100)
59#define SYS_IIC_DTRM_Bit_DATA ((unsigned short)0x00FF)
60
61static inline void POLL_INT_REQ(volatile u16 *icr)
62{
63 unsigned long flags;
64 u16 tmp;
65
66 while (!(*icr & GxICR_REQUEST))
67 ;
68 flags = arch_local_cli_save();
69 tmp = *icr;
70 *icr = (tmp & GxICR_LEVEL) | GxICR_DETECT;
71 tmp = *icr;
72 arch_local_irq_restore(flags);
73}
74
75/*
76 * Implement the SMSC911x hook for MAC address retrieval
77 */
78#undef smsc_get_mac
79static inline int smsc_get_mac(struct net_device *dev)
80{
81 unsigned char *mac_buf = dev->dev_addr;
82 int i;
83 unsigned short value;
84 unsigned int data;
85 int mac_length = 6;
86 int check;
87 u16 orig_gicr, tmp;
88 unsigned long flags;
89
90 /* save original GnICR and clear GnICR.IE */
91 flags = arch_local_cli_save();
92 orig_gicr = IIC_ICR;
93 IIC_ICR = orig_gicr & GxICR_LEVEL;
94 tmp = IIC_ICR;
95 arch_local_irq_restore(flags);
96
97 IIC_MYADD = 0x00000008;
98 IIC_CLK = (IIC_CLK_LOW << 16) + (IIC_CLK_PLS);
99 /* bus hung recovery */
100
101 while (1) {
102 check = 0;
103 for (i = 0; i < 3; i++) {
104 if ((IIC_BSTS & 0x00000003) == 0x00000003)
105 check++;
106 udelay(3);
107 }
108
109 if (check == 3) {
110 IIC_BRST = 0x00000003;
111 break;
112 } else {
113 for (i = 0; i < 3; i++) {
114 IIC_BRST = 0x00000002;
115 udelay(8);
116 IIC_BRST = 0x00000003;
117 udelay(8);
118 }
119 }
120 }
121
122 IIC_BRST = 0x00000002;
123 IIC_BRST = 0x00000003;
124
125 value = SYS_IIC_DTRM_Bit_STA | SYS_IIC_DTRM_Bit_ACK;
126 value |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
127 (unsigned short)0x0000);
128 IIC_DTRM = value;
129 POLL_INT_REQ(&IIC_ICR);
130
131 /** send offset of MAC address in EEPROM **/
132 IIC_DTRM = (unsigned char)((MAC_OFFSET & 0xFF00) >> 8);
133 POLL_INT_REQ(&IIC_ICR);
134
135 IIC_DTRM = (unsigned char)(MAC_OFFSET & 0x00FF);
136 POLL_INT_REQ(&IIC_ICR);
137
138 udelay(1000);
139
140 value = SYS_IIC_DTRM_Bit_STA;
141 value |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
142 (unsigned short)0x0001);
143 IIC_DTRM = value;
144 POLL_INT_REQ(&IIC_ICR);
145
146 IIC_DTRM = 0x00000000;
147 while (mac_length > 0) {
148 POLL_INT_REQ(&IIC_ICR);
149
150 data = IIC_DREC;
151 mac_length--;
152 if (mac_length == 0)
153 value = 0x00000300; /* stop IIC bus */
154 else if (mac_length == 1)
155 value = 0x00000100; /* no ack */
156 else
157 value = 0x00000000; /* ack */
158 IIC_DTRM = value;
159 *mac_buf++ = (unsigned char)(data & 0xff);
160 }
161
162 /* restore GnICR.LV and GnICR.IE */
163 flags = arch_local_cli_save();
164 IIC_ICR = (orig_gicr & (GxICR_LEVEL | GxICR_ENABLE));
165 tmp = IIC_ICR;
166 arch_local_irq_restore(flags);
167
168 return 0;
169}
170#endif /* MN10300_USE_EXT_EEPROM */
171#endif /* _ASM_UNIT_SMSC911X_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..ddb7ed010706
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/timex.h
@@ -0,0 +1,159 @@
1/* timex.h: MN2WS0038 architecture timer specifications
2 *
3 * Copyright (C) 2002, 2010 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 TMJCIRQ TMTIRQ
28
29#ifndef __ASSEMBLY__
30
31#define MN10300_SRC_IOBCLK MN10300_IOBCLK
32
33#ifndef HZ
34# error HZ undeclared.
35#endif /* !HZ */
36
37#define MN10300_JCCLK (MN10300_SRC_IOBCLK)
38#define MN10300_TSCCLK (MN10300_SRC_IOBCLK)
39
40#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
41#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
42
43/* Check bit width of MTM interval value that sets base register */
44#if (MN10300_JC_PER_HZ - 1) > TMJCBR_MAX
45# error MTM tick timer interval value is overflow.
46#endif
47
48static inline void stop_jiffies_counter(void)
49{
50 u16 tmp;
51 TMTMD = 0;
52 tmp = TMTMD;
53}
54
55static inline void reload_jiffies_counter(u32 cnt)
56{
57 u32 tmp;
58
59 TMTBR = cnt;
60 tmp = TMTBR;
61
62 TMTMD = TMTMD_TMTLDE;
63 TMTMD = TMTMD_TMTCNE;
64 tmp = TMTMD;
65}
66
67#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS) && \
68 !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
69/*
70 * If we aren't using broadcasting, each core needs its own event timer.
71 * Since CPU0 uses the tick timer which is 24-bits, we use timer 4 & 5
72 * cascaded to 32-bits for CPU1 (but only really use 24-bits to match
73 * CPU0).
74 */
75
76#define TMJC1IRQ TM5IRQ
77
78static inline void stop_jiffies_counter1(void)
79{
80 u8 tmp;
81 TM4MD = 0;
82 TM5MD = 0;
83 tmp = TM4MD;
84 tmp = TM5MD;
85}
86
87static inline void reload_jiffies_counter1(u32 cnt)
88{
89 u32 tmp;
90
91 TM45BR = cnt;
92 tmp = TM45BR;
93
94 TM4MD = TM4MD_INIT_COUNTER;
95 tmp = TM4MD;
96
97 TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_INIT_COUNTER;
98 TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_COUNT_ENABLE;
99 tmp = TM5MD;
100
101 TM4MD = TM4MD_COUNT_ENABLE;
102 tmp = TM4MD;
103}
104#endif /* CONFIG_SMP&GENERIC_CLOCKEVENTS&!GENERIC_CLOCKEVENTS_BROADCAST */
105
106#endif /* !__ASSEMBLY__ */
107
108
109/*
110 * timestamp counter specifications
111 */
112#define TMTSCBR_MAX 0xffffffff
113
114#ifndef __ASSEMBLY__
115
116/* Use 32-bit timestamp counter */
117#define TMTSCMD TMSMD
118#define TMTSCBR TMSBR
119#define TMTSCBC TMSBC
120#define TMTSCICR TMSICR
121
122static inline void startup_timestamp_counter(void)
123{
124 u32 sync;
125
126 /* set up TMS(Timestamp) 32bit timer register to count real time
127 * - count down from 4Gig-1 to 0 and wrap at IOBCLK rate
128 */
129
130 TMTSCBR = TMTSCBR_MAX;
131 sync = TMTSCBR;
132
133 TMTSCICR = 0;
134 sync = TMTSCICR;
135
136 TMTSCMD = TMTMD_TMTLDE;
137 TMTSCMD = TMTMD_TMTCNE;
138 sync = TMTSCMD;
139}
140
141static inline void shutdown_timestamp_counter(void)
142{
143 TMTSCMD = 0;
144}
145
146/*
147 * we use a cascaded pair of 16-bit down-counting timers to count I/O
148 * clock cycles for the purposes of time keeping
149 */
150typedef unsigned long cycles_t;
151
152static inline cycles_t read_timestamp_counter(void)
153{
154 return (cycles_t)~TMTSCBC;
155}
156
157#endif /* !__ASSEMBLY__ */
158
159#endif /* _ASM_UNIT_TIMEX_H */
diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c
new file mode 100644
index 000000000000..fcf29754e4d1
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/irq-fpga.c
@@ -0,0 +1,96 @@
1/* ASB2364 FPGA interrupt multiplexing
2 *
3 * Copyright (C) 2010 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/interrupt.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15#include <unit/fpga-regs.h>
16
17/*
18 * FPGA PIC operations
19 */
20static void asb2364_fpga_mask(unsigned int irq)
21{
22 ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
23 SyncExBus();
24}
25
26static void asb2364_fpga_ack(unsigned int irq)
27{
28 ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
29 SyncExBus();
30}
31
32static void asb2364_fpga_mask_ack(unsigned int irq)
33{
34 ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
35 SyncExBus();
36 ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
37 SyncExBus();
38}
39
40static void asb2364_fpga_unmask(unsigned int irq)
41{
42 ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000;
43 SyncExBus();
44}
45
46static struct irq_chip asb2364_fpga_pic = {
47 .name = "fpga",
48 .ack = asb2364_fpga_ack,
49 .mask = asb2364_fpga_mask,
50 .mask_ack = asb2364_fpga_mask_ack,
51 .unmask = asb2364_fpga_unmask,
52};
53
54/*
55 * FPGA PIC interrupt handler
56 */
57static irqreturn_t fpga_interrupt(int irq, void *_mask)
58{
59 if ((ASB2364_FPGA_REG_IRQ_LAN & 0x0001) != 0x0001)
60 generic_handle_irq(FPGA_LAN_IRQ);
61 if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) != 0x0001)
62 generic_handle_irq(FPGA_UART_IRQ);
63 if ((ASB2364_FPGA_REG_IRQ_I2C & 0x0001) != 0x0001)
64 generic_handle_irq(FPGA_I2C_IRQ);
65 if ((ASB2364_FPGA_REG_IRQ_USB & 0x0001) != 0x0001)
66 generic_handle_irq(FPGA_USB_IRQ);
67 if ((ASB2364_FPGA_REG_IRQ_FPGA & 0x0001) != 0x0001)
68 generic_handle_irq(FPGA_FPGA_IRQ);
69
70 return IRQ_HANDLED;
71}
72
73/*
74 * Define an interrupt action for each FPGA PIC output
75 */
76static struct irqaction fpga_irq[] = {
77 [0] = {
78 .handler = fpga_interrupt,
79 .flags = IRQF_DISABLED | IRQF_SHARED,
80 .name = "fpga",
81 },
82};
83
84/*
85 * Initialise the FPGA's PIC
86 */
87void __init irq_fpga_init(void)
88{
89 int irq;
90
91 for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
92 set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq);
93
94 /* the FPGA drives the XIRQ1 input on the CPU PIC */
95 setup_irq(XIRQ1, &fpga_irq[0]);
96}
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
23static 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
28static 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
37static unsigned asb2364_led_chase;
38
39void 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
55void 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 */
72void 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
86void 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 */
94void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { }
95void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { }
96void peripheral_leds_display_exception(enum exception_code code) { }
97void peripheral_leds_led_chase(void) { }
98#endif /* MN10300_USE_7SEGLEDS */
diff --git a/arch/mn10300/unit-asb2364/smsc911x.c b/arch/mn10300/unit-asb2364/smsc911x.c
new file mode 100644
index 000000000000..544a73e94c81
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/smsc911x.c
@@ -0,0 +1,58 @@
1/* Specification for the SMSC911x NIC
2 *
3 * Copyright (C) 2006 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#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/io.h>
16#include <linux/ioport.h>
17#include <linux/smsc911x.h>
18#include <unit/smsc911x.h>
19
20static struct smsc911x_platform_config smsc911x_config = {
21 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
22 .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
23 .flags = SMSC911X_USE_32BIT,
24};
25
26static struct resource smsc911x_resources[] = {
27 [0] = {
28 .start = SMSC911X_BASE,
29 .end = SMSC911X_BASE_END,
30 .flags = IORESOURCE_MEM,
31 },
32 [1] = {
33 .start = SMSC911X_IRQ,
34 .end = SMSC911X_IRQ,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39static struct platform_device smsc911x_device = {
40 .name = "smsc911x",
41 .id = 0,
42 .num_resources = ARRAY_SIZE(smsc911x_resources),
43 .resource = smsc911x_resources,
44 .dev = {
45 .platform_data = &smsc911x_config,
46 }
47};
48
49/*
50 * add platform devices
51 */
52static int __init unit_device_init(void)
53{
54 platform_device_register(&smsc911x_device);
55 return 0;
56}
57
58device_initcall(unit_device_init);
diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c
new file mode 100644
index 000000000000..11440803db10
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/unit-init.c
@@ -0,0 +1,88 @@
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#include <unit/fpga-regs.h>
24
25/*
26 * initialise some of the unit hardware before gdbstub is set up
27 */
28asmlinkage void __init unit_init(void)
29{
30 /* set up the external interrupts */
31
32 /* XIRQ[0]: NAND RXBY */
33 /* SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_LOWLEVEL); */
34
35 /* XIRQ[1]: LAN, UART, I2C, USB, PCI, FPGA */
36 SET_XIRQ_TRIGGER(1, XIRQ_TRIGGER_LOWLEVEL);
37
38 /* XIRQ[2]: Extend Slot 1-9 */
39 /* SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL); */
40
41#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL) && \
42 defined(CONFIG_ETHERNET_IRQ_LEVEL) && \
43 (CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL)
44# error CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL
45#endif
46
47#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL)
48 set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
49#elif defined(CONFIG_ETHERNET_IRQ_LEVEL)
50 set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL));
51#endif
52}
53
54/*
55 * initialise the rest of the unit hardware after gdbstub is ready
56 */
57asmlinkage void __init unit_setup(void)
58{
59
60}
61
62/*
63 * initialise the external interrupts used by a unit of this type
64 */
65void __init unit_init_IRQ(void)
66{
67 unsigned int extnum;
68
69 for (extnum = 0 ; extnum < NR_XIRQS ; extnum++) {
70 switch (GET_XIRQ_TRIGGER(extnum)) {
71 /* LEVEL triggered interrupts should be made
72 * post-ACK'able as they hold their lines until
73 * serviced
74 */
75 case XIRQ_TRIGGER_HILEVEL:
76 case XIRQ_TRIGGER_LOWLEVEL:
77 mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
78 break;
79 default:
80 break;
81 }
82 }
83
84#define IRQCTL __SYSREG(0xd5000090, u32)
85 IRQCTL |= 0x02;
86
87 irq_fpga_init();
88}