History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-mn10300

* git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-mn10300: (44 commits) MN10300: Save frame pointer in thread_info struct rather than global var MN10300: Change "Matsushita" to "Panasonic". MN10300: Create a defconfig for the ASB2364 board MN10300: Update the ASB2303 defconfig MN10300: ASB2364: Add support for SMSC911X and SMC911X MN10300: ASB2364: Handle the IRQ multiplexer in the FPGA MN10300: Generic time support MN10300: Specify an ELF HWCAP flag for MN10300 Atomic Operations Unit support MN10300: Map userspace atomic op regs as a vmalloc page MN10300: And Panasonic AM34 subarch and implement SMP MN10300: Delete idle_timestamp from irq_cpustat_t MN10300: Make various interrupt priority settings configurable MN10300: Optimise do_csum() MN10300: Implement atomic ops using atomic ops unit MN10300: Make the FPU operate in non-lazy mode under SMP MN10300: SMP TLB flushing MN10300: Use the [ID]PTEL2 registers rather than [ID]PTEL for TLB control MN10300: Make the use of PIDR to mark TLB entries controllable MN10300: Rename __flush_tlb*() to local_flush_tlb*() MN10300: AM34 erratum requires MMUCTR read and write on exception entry ...

Linus Torvalds committed 16 years ago

Commit bdab2252 parents 7c5814c 7c7fcf7145 files · +9424 −1963Browse files

Unified · Split

145 files
  1. Kbuild +1 −1
  2. MAINTAINERS +1 −1
  3. arch/mn10300/Kconfig +219 −60
  4. arch/mn10300/Makefile +6 −0
  5. arch/mn10300/boot/compressed/head.S +67 −2
  6. arch/mn10300/configs/asb2303_defconfig +2 −0
  7. arch/mn10300/configs/asb2364_defconfig +98 −0
  8. arch/mn10300/include/asm/atomic.h +350 −0
  9. arch/mn10300/include/asm/bitops.h +7 −7
  10. arch/mn10300/include/asm/cache.h +9 −5
  11. arch/mn10300/include/asm/cacheflush.h +109 −55
  12. arch/mn10300/include/asm/cpu-regs.h +77 −14
  13. arch/mn10300/include/asm/dmactl-regs.h +1 −86
  14. arch/mn10300/include/asm/elf.h +10 −2
  15. arch/mn10300/include/asm/exceptions.h +4 −4
  16. arch/mn10300/include/asm/fpu.h +104 −53
  17. arch/mn10300/include/asm/frame.inc +13 −7
  18. arch/mn10300/include/asm/gdb-stub.h +1 −1
  19. arch/mn10300/include/asm/hardirq.h +2 −1
  20. arch/mn10300/include/asm/highmem.h +2 −2
  21. arch/mn10300/include/asm/intctl-regs.h +20 −17
  22. arch/mn10300/include/asm/io.h +13 −0
  23. arch/mn10300/include/asm/irq.h +10 −2
  24. arch/mn10300/include/asm/irq_regs.h +5 −1
  25. arch/mn10300/include/asm/irqflags.h +102 −9
  26. arch/mn10300/include/asm/mmu_context.h +48 −25
  27. arch/mn10300/include/asm/pgalloc.h +0 −1
  28. arch/mn10300/include/asm/pgtable.h +52 −36
  29. arch/mn10300/include/asm/processor.h +39 −27
  30. arch/mn10300/include/asm/ptrace.h +2 −11
  31. arch/mn10300/include/asm/reset-regs.h +1 −1
  32. arch/mn10300/include/asm/rtc.h +0 −11
  33. arch/mn10300/include/asm/rwlock.h +125 −0
  34. arch/mn10300/include/asm/serial-regs.h +41 −10
  35. arch/mn10300/include/asm/serial.h +4 −4
  36. arch/mn10300/include/asm/smp.h +89 −2
  37. arch/mn10300/include/asm/smsc911x.h +1 −0
  38. arch/mn10300/include/asm/spinlock.h +178 −1
  39. arch/mn10300/include/asm/spinlock_types.h +20 −0
  40. arch/mn10300/include/asm/system.h +22 −51
  41. arch/mn10300/include/asm/thread_info.h +14 −4
  42. arch/mn10300/include/asm/timer-regs.h +175 −16
  43. arch/mn10300/include/asm/timex.h +16 −4
  44. arch/mn10300/include/asm/tlbflush.h +124 −50
  45. arch/mn10300/include/asm/uaccess.h +2 −4
  46. arch/mn10300/kernel/Makefile +10 −5
  47. arch/mn10300/kernel/asm-offsets.c +10 −1
  48. arch/mn10300/kernel/cevt-mn10300.c +131 −0
  49. arch/mn10300/kernel/csrc-mn10300.c +35 −0
  50. arch/mn10300/kernel/entry.S +98 −48
  51. arch/mn10300/kernel/fpu-low.S +163 −102
  52. arch/mn10300/kernel/fpu-nofpu-low.S +39 −0
  53. arch/mn10300/kernel/fpu-nofpu.c +30 −0
  54. arch/mn10300/kernel/fpu.c +56 −85
  55. arch/mn10300/kernel/gdb-io-serial-low.S +3 −2
  56. arch/mn10300/kernel/gdb-io-serial.c +27 −10
  57. arch/mn10300/kernel/gdb-io-ttysm.c +13 −11
  58. arch/mn10300/kernel/gdb-stub.c +6 −11
  59. arch/mn10300/kernel/head.S +198 −4
  60. arch/mn10300/kernel/internal.h +25 −0
  61. arch/mn10300/kernel/irq.c +246 −30
  62. arch/mn10300/kernel/kprobes.c +4 −0
  63. arch/mn10300/kernel/mn10300-serial-low.S +3 −3
  64. arch/mn10300/kernel/mn10300-serial.c +181 −29
  65. arch/mn10300/kernel/mn10300-watchdog-low.S +8 −1
  66. arch/mn10300/kernel/mn10300-watchdog.c +61 −39
  67. arch/mn10300/kernel/process.c +47 −14
  68. arch/mn10300/kernel/profile.c +1 −1
  69. arch/mn10300/kernel/rtc.c +10 −31
  70. arch/mn10300/kernel/setup.c +43 −36
  71. arch/mn10300/kernel/signal.c +11 −9
  72. arch/mn10300/kernel/smp-low.S +97 −0
  73. arch/mn10300/kernel/smp.c +1152 −0
  74. arch/mn10300/kernel/switch_to.S +3 −4
  75. arch/mn10300/kernel/time.c +85 −27
  76. arch/mn10300/kernel/traps.c +13 −29
  77. arch/mn10300/lib/bitops.c +2 −2
  78. arch/mn10300/lib/delay.c +4 −4
  79. arch/mn10300/lib/do_csum.S +22 −27
  80. arch/mn10300/mm/Kconfig.cache +101 −0
  81. arch/mn10300/mm/Makefile +12 −2
  82. arch/mn10300/mm/cache-flush-by-reg.S +308 −0
  83. arch/mn10300/mm/cache-flush-by-tag.S +251 −0
  84. arch/mn10300/mm/cache-flush-icache.c +155 −0
  85. arch/mn10300/mm/cache-flush-mn10300.S +0 −192
  86. arch/mn10300/mm/cache-inv-by-reg.S +356 −0
  87. arch/mn10300/mm/cache-inv-by-tag.S +348 −0
  88. arch/mn10300/mm/cache-inv-icache.c +129 −0
  89. arch/mn10300/mm/cache-mn10300.S +0 −289
  90. arch/mn10300/mm/cache-smp-flush.c +156 −0
  91. arch/mn10300/mm/cache-smp-inv.c +153 −0
  92. arch/mn10300/mm/cache-smp.c +105 −0
  93. arch/mn10300/mm/cache-smp.h +69 −0
  94. arch/mn10300/mm/cache.c +5 −90
  95. arch/mn10300/mm/fault.c +4 −13
  96. arch/mn10300/mm/init.c +23 −3
  97. arch/mn10300/mm/misalignment.c +1 −2
  98. arch/mn10300/mm/mmu-context.c +11 −30
  99. arch/mn10300/mm/pgtable.c +1 −1
  100. arch/mn10300/mm/tlb-mn10300.S +45 −14
  101. arch/mn10300/mm/tlb-smp.c +214 −0
  102. arch/mn10300/proc-mn103e010/include/proc/cache.h +9 −0
  103. arch/mn10300/proc-mn103e010/include/proc/clock.h +0 −2
  104. arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h +102 −0
  105. arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h +29 −0
  106. arch/mn10300/proc-mn103e010/include/proc/proc.h +1 −1
  107. arch/mn10300/proc-mn103e010/proc-init.c +37 −0
  108. arch/mn10300/proc-mn2ws0050/Makefile +5 −0
  109. arch/mn10300/proc-mn2ws0050/include/proc/cache.h +48 −0
  110. arch/mn10300/proc-mn2ws0050/include/proc/clock.h +20 −0
  111. arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h +103 −0
  112. arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h +29 −0
  113. arch/mn10300/proc-mn2ws0050/include/proc/irq.h +49 −0
  114. arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h +120 −0
  115. arch/mn10300/proc-mn2ws0050/include/proc/proc.h +18 −0
  116. arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h +51 −0
  117. arch/mn10300/proc-mn2ws0050/proc-init.c +134 −0
  118. arch/mn10300/unit-asb2303/include/unit/clock.h +2 −23
  119. arch/mn10300/unit-asb2303/include/unit/serial.h +5 −0
  120. arch/mn10300/unit-asb2303/include/unit/timex.h +62 −47
  121. arch/mn10300/unit-asb2303/unit-init.c +9 −1
  122. arch/mn10300/unit-asb2305/include/unit/clock.h +2 −23
  123. arch/mn10300/unit-asb2305/include/unit/serial.h +5 −0
  124. arch/mn10300/unit-asb2305/include/unit/timex.h +62 −47
  125. arch/mn10300/unit-asb2305/pci-asb2305.c +6 −10
  126. arch/mn10300/unit-asb2305/pci.c +1 −1
  127. arch/mn10300/unit-asb2305/unit-init.c +4 −2
  128. arch/mn10300/unit-asb2364/Makefile +12 −0
  129. arch/mn10300/unit-asb2364/include/unit/clock.h +29 −0
  130. arch/mn10300/unit-asb2364/include/unit/fpga-regs.h +52 −0
  131. arch/mn10300/unit-asb2364/include/unit/irq.h +35 −0
  132. arch/mn10300/unit-asb2364/include/unit/leds.h +54 −0
  133. arch/mn10300/unit-asb2364/include/unit/serial.h +151 −0
  134. arch/mn10300/unit-asb2364/include/unit/smsc911x.h +171 −0
  135. arch/mn10300/unit-asb2364/include/unit/timex.h +159 −0
  136. arch/mn10300/unit-asb2364/irq-fpga.c +96 −0
  137. arch/mn10300/unit-asb2364/leds.c +98 −0
  138. arch/mn10300/unit-asb2364/smsc911x.c +58 −0
  139. arch/mn10300/unit-asb2364/unit-init.c +88 −0
  140. drivers/net/Kconfig +10 −2
  141. drivers/net/smsc911x.c +2 −1
  142. drivers/net/smsc911x.h +11 −0
  143. include/linux/smp.h +10 −9
  144. kernel/smp.c +4 −4
  145. mm/maccess.c +1 −1
Kbuild+1−1
@@ -53,7 +53,7 @@ targets += arch/$(SRCARCH)/kernel/asm-offsets.s · 52 unmodified lines
5353 # Default sed regexp - multiline due to syntax constraints
5454 define sed-y
5555 "/^->/{s:->#\(.*\):/* \1 */:; \
56− s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \
56+ s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
5757 s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
5858 s:->::; p;}"
5959 endef
MAINTAINERS+1−1
@@ -4448,7 +4448,7 @@ L: platform-driver-x86@vger.kernel.org · 4447 unmodified lines
44484448 S: Maintained
44494449 F: drivers/platform/x86/panasonic-laptop.c
44504450
4451−PANASONIC MN10300/AM33 PORT
4451+PANASONIC MN10300/AM33/AM34 PORT
44524452 M: David Howells <dhowells@redhat.com>
44534453 M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
44544454 L: linux-am33-list@redhat.com (moderated for non-subscribers)
arch/mn10300/Kconfig+219−60
@@ -9,8 +9,19 @@ config MN10300 · 8 unmodified lines
99 def_bool y
1010 select HAVE_OPROFILE
1111
12−config AM33
13− def_bool y
12+config AM33_2
13+ def_bool n
14+
15+config AM33_3
16+ def_bool n
17+
18+config AM34_2
19+ def_bool n
20+ select MN10300_HAS_ATOMIC_OPS_UNIT
21+ select MN10300_HAS_CACHE_SNOOP
22+
23+config ERRATUM_NEED_TO_RELOAD_MMUCTR
24+ def_bool y if AM33_3 || AM34_2
1425
1526 config MMU
1627 def_bool y
@@ -37,7 +48,7 @@ config GENERIC_CALIBRATE_DELAY · 20 unmodified lines
3748 def_bool y
3849
3950 config GENERIC_CMOS_UPDATE
40− def_bool y
51+ def_bool n
4152
4253 config GENERIC_FIND_NEXT_BIT
4354 def_bool y
@@ -45,6 +56,27 @@ config GENERIC_FIND_NEXT_BIT · 1 unmodified line
4556 config GENERIC_HWEIGHT
4657 def_bool y
4758
59+config GENERIC_TIME
60+ def_bool y
61+
62+config GENERIC_CLOCKEVENTS
63+ def_bool y
64+
65+config GENERIC_CLOCKEVENTS_BUILD
66+ def_bool y
67+ depends on GENERIC_CLOCKEVENTS
68+
69+config GENERIC_CLOCKEVENTS_BROADCAST
70+ bool
71+
72+config CEVT_MN10300
73+ def_bool y
74+ depends on GENERIC_CLOCKEVENTS
75+
76+config CSRC_MN10300
77+ def_bool y
78+ depends on GENERIC_TIME
79+
4880 config GENERIC_BUG
4981 def_bool y
5082
@@ -61,18 +93,14 @@ config GENERIC_HARDIRQS · 10 unmodified lines
6193 config HOTPLUG_CPU
6294 def_bool n
6395
64−config HZ
65− int
66− default 1000
67−
68−mainmenu "Matsushita MN10300/AM33 Kernel Configuration"
96+mainmenu "Panasonic MN10300/AM33 Kernel Configuration"
6997
7098 source "init/Kconfig"
7199
72100 source "kernel/Kconfig.freezer"
73101
74102
75−menu "Matsushita MN10300 system setup"
103+menu "Panasonic MN10300 system setup"
76104
77105 choice
78106 prompt "Unit type"
@@ -87,6 +115,10 @@ config MN10300_UNIT_ASB2303 · 8 unmodified lines
87115 config MN10300_UNIT_ASB2305
88116 bool "ASB2305"
89117
118+config MN10300_UNIT_ASB2364
119+ bool "ASB2364"
120+ select SMSC911X_ARCH_HOOKS if SMSC911X
121+
90122 endchoice
91123
92124 choice
@@ -99,57 +131,51 @@ choice · 6 unmodified lines
99131 config MN10300_PROC_MN103E010
100132 bool "MN103E010"
101133 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+
139+config MN10300_PROC_MN2WS0050
140+ bool "MN2WS0050"
141+ depends on MN10300_UNIT_ASB2364
142+ select AM34_2
102143 select MN10300_PROC_HAS_TTYSM0
103144 select MN10300_PROC_HAS_TTYSM1
104145 select MN10300_PROC_HAS_TTYSM2
105146
106147 endchoice
107148
108−choice
109− prompt "Processor core support"
110− default MN10300_CPU_AM33V2
149+config MN10300_HAS_ATOMIC_OPS_UNIT
150+ def_bool n
111151 help
112− This option specifies the processor core for which the kernel will be
113− compiled. It affects the instruction set used.
114−
115−config MN10300_CPU_AM33V2
116− bool "AM33v2"
117−
118−endchoice
152+ This should be enabled if the processor has an atomic ops unit
153+ capable of doing LL/SC equivalent operations.
119154
120155 config FPU
121156 bool "FPU present"
122157 default y
123− depends on MN10300_PROC_MN103E010
158+ depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
124159
125−choice
126− prompt "CPU Caching mode"
127− default MN10300_CACHE_WBACK
160+config LAZY_SAVE_FPU
161+ bool "Save FPU state lazily"
162+ default y
163+ depends on FPU && !SMP
128164 help
129− This option determines the caching mode for the kernel.
130−
131− Write-Back caching mode involves the all reads and writes causing
132− the affected cacheline to be read into the cache first before being
133− operated upon. Memory is not then updated by a write until the cache
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.
165+ Enable this to be lazy in the saving of the FPU state to the owning
166+ task's thread struct. This is useful if most tasks on the system
167+ don't use the FPU as only those tasks that use it will pass it
168+ between them, and the state needn't be saved for a task that isn't
169+ using it.
142170
143−config MN10300_CACHE_WBACK
144− bool "Write-Back"
171+ This can't be so easily used on SMP as the process that owns the FPU
172+ state on a CPU may be currently running on another CPU, so for the
173+ moment, it is disabled.
145174
146−config MN10300_CACHE_WTHRU
147− bool "Write-Through"
175+source "arch/mn10300/mm/Kconfig.cache"
148176
149−config MN10300_CACHE_DISABLED
150− bool "Disabled"
151−
152−endchoice
177+config MN10300_TLB_USE_PIDR
178+ def_bool y
153179
154180 menu "Memory layout options"
155181
@@ -170,24 +196,55 @@ config KERNEL_TEXT_ADDRESS · 14 unmodified lines
170196
171197 config KERNEL_ZIMAGE_BASE_ADDRESS
172198 hex "Base address of compressed vmlinux image"
173− default "0x90700000"
199+ default "0x50700000"
174200
201+config BOOT_STACK_OFFSET
202+ hex
203+ default "0xF00" if SMP
204+ default "0xFF0" if !SMP
205+
206+config BOOT_STACK_SIZE
207+ hex
208+ depends on SMP
209+ default "0x100"
175210 endmenu
176211
177−config PREEMPT
178− bool "Preemptible Kernel"
179− help
180− This option reduces the latency of the kernel when reacting to
181− real-time or interactive events by allowing a low priority process to
182− be preempted even if it is in kernel mode executing a system call.
183− This allows applications to run more reliably even when the system is
184− under load.
212+config SMP
213+ bool "Symmetric multi-processing support"
214+ default y
215+ depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050
216+ ---help---
217+ This enables support for systems with more than one CPU. If you have
218+ a system with only one CPU, like most personal computers, say N. If
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.
185226
186− Say Y here if you are building a kernel for a desktop, embedded
187− or real-time system. Say N if you are unsure.
227+ See also <file:Documentation/i386/IO-APIC.txt>,
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+
233+config NR_CPUS
234+ int
235+ depends on SMP
236+ default "2"
237+
238+config USE_GENERIC_SMP_HELPERS
239+ bool
240+ depends on SMP
241+ default y
242+
243+source "kernel/Kconfig.preempt"
188244
189245 config MN10300_CURRENT_IN_E2
190246 bool "Hold current task address in E2 register"
247+ depends on !SMP
191248 default y
192249 help
193250 This option removes the E2/R2 register from the set available to gcc
@@ -209,12 +266,15 @@ config MN10300_USING_JTAG · 15 unmodified lines
209266 suppresses the use of certain hardware debugging features, such as
210267 single-stepping, which are taken over completely by the JTAG unit.
211268
269+source "kernel/Kconfig.hz"
270+source "kernel/time/Kconfig"
271+
212272 config MN10300_RTC
213273 bool "Using MN10300 RTC"
214− depends on MN10300_PROC_MN103E010
274+ depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
275+ select GENERIC_CMOS_UPDATE
215276 default n
216277 help
217−
218278 This option enables support for the RTC, thus enabling time to be
219279 tracked, even when system is powered down. This is available on-chip
220280 on the MN103E010.
@@ -306,14 +366,23 @@ config MN10300_TTYSM1 · 85 unmodified lines
306366
307367 choice
308368 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
310373 depends on MN10300_TTYSM1
311374
375+config MN10300_TTYSM1_TIMER12
376+ bool "Use timer 12 (16-bit)"
377+ depends on !(AM33_2 || AM33_3)
378+
312379 config MN10300_TTYSM1_TIMER9
313380 bool "Use timer 9 (16-bit)"
381+ depends on AM33_2 || AM33_3
314382
315383 config MN10300_TTYSM1_TIMER3
316384 bool "Use timer 3 (8-bit)"
385+ depends on AM33_2 || AM33_3
317386
318387 endchoice
319388
@@ -328,17 +397,107 @@ config MN10300_TTYSM2 · 8 unmodified lines
328397
329398 choice
330399 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
332404 depends on MN10300_TTYSM2
333405
406+config MN10300_TTYSM2_TIMER9
407+ bool "Use timer 9 (16-bit)"
408+ depends on !(AM33_2 || AM33_3)
409+
410+config MN10300_TTYSM2_TIMER1
411+ bool "Use timer 1 (8-bit)"
412+ depends on !(AM33_2 || AM33_3)
413+
414+config MN10300_TTYSM2_TIMER3
415+ bool "Use timer 3 (8-bit)"
416+ depends on !(AM33_2 || AM33_3)
417+
334418 config MN10300_TTYSM2_TIMER10
335419 bool "Use timer 10 (16-bit)"
420+ depends on AM33_2 || AM33_3
336421
337422 endchoice
338423
339424 config MN10300_TTYSM2_CTS
340425 bool "Enable the use of the CTS line /dev/ttySM2"
341− depends on MN10300_TTYSM2
426+ depends on MN10300_TTYSM2 && AM33_2
427+
428+endmenu
429+
430+menu "Interrupt request priority options"
431+
432+comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highest, 6 is lowest)"
433+
434+comment "____Non-maskable interrupt levels____"
435+comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
436+
437+config 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+
447+comment "The following must be set to a higher priority than local_irq_disable()"
448+
449+config 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+
459+comment "-"
460+comment "____Maskable interrupt levels____"
461+
462+config 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+
477+comment "The following must be set to a equal to or lower priority than LINUX_CLI_LEVEL"
478+
479+config TIMER_IRQ_LEVEL
480+ int "Kernel timer interrupt priority"
481+ range LINUX_CLI_LEVEL 6
482+ default 4
483+
484+config PCI_IRQ_LEVEL
485+ int "PCI interrupt priority"
486+ depends on PCI
487+ range LINUX_CLI_LEVEL 6
488+ default 5
489+
490+config ETHERNET_IRQ_LEVEL
491+ int "Ethernet interrupt priority"
492+ depends on SMC91X || SMC911X || SMSC911X
493+ range LINUX_CLI_LEVEL 6
494+ default 6
495+
496+config 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
342501
343502 endmenu
344503
arch/mn10300/Makefile+6−0
@@ -36,6 +36,9 @@ endif · 35 unmodified lines
3636 ifeq ($(CONFIG_MN10300_PROC_MN103E010),y)
3737 PROCESSOR := mn103e010
3838 endif
39+ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y)
40+PROCESSOR := mn2ws0050
41+endif
3942
4043 ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y)
4144 UNIT := asb2303
@@ -43,6 +46,9 @@ endif · 1 unmodified line
4346 ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y)
4447 UNIT := asb2305
4548 endif
49+ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y)
50+UNIT := asb2364
51+endif
4652
4753
4854 head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o
arch/mn10300/boot/compressed/head.S+67−2
@@ -14,10 +14,29 @@ · 13 unmodified lines
1414
1515 #include <linux/linkage.h>
1616 #include <asm/cpu-regs.h>
17+#include <asm/cache.h>
18+#ifdef CONFIG_SMP
19+#include <proc/smp-regs.h>
20+#endif
1721
1822 .globl startup_32
1923 startup_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+
36+startup_primary:
37+#endif /* CONFIG_SMP */
38+
39+ # first save parameters from bootloader
2140 mov param_save_area,a0
2241 mov d0,(a0)
2342 mov d1,(4,a0)
@@ -37,8 +56,15 @@ startup_32: · 13 unmodified lines
3756 mov (a0),d0
3857 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
3958 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 */
4166 movhu d0,(a0) # enable
67+#endif /* !ENABLED */
4268
4369 # clear the BSS area
4470 mov __bss_start,a0
@@ -54,6 +80,9 @@ bssclear_end: · 9 unmodified lines
5480
5581 # decompress the kernel
5682 call decompress_kernel[],0
83+#ifdef CONFIG_MN10300_CACHE_WBACK
84+ call mn10300_dcache_flush_inv[],0
85+#endif
5786
5887 # disable caches again
5988 mov CHCTR,a0
@@ -69,10 +98,46 @@ bssclear_end: · 9 unmodified lines
6998 mov (4,a0),d1
7099 mov (8,a0),d2
71100
101+ # jump to the kernel proper entry point
72102 mov a3,sp
73103 mov CONFIG_KERNEL_TEXT_ADDRESS,a0
74104 jmp (a0)
75105
106+
107+###############################################################################
108+#
109+# Cache flush routines
110+#
111+###############################################################################
112+#ifdef CONFIG_MN10300_CACHE_WBACK
113+mn10300_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+
121+mn10300_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+
131+mn10300_dcache_flush_inv_end:
132+ ret [],0
133+#endif /* CONFIG_MN10300_CACHE_WBACK */
134+
135+
136+###############################################################################
137+#
138+# Data areas
139+#
140+###############################################################################
76141 .data
77142 .align 4
78143 param_save_area:
arch/mn10300/configs/asb2303_defconfig+2−0
@@ -12,6 +12,8 @@ CONFIG_SLAB=y · 11 unmodified lines
1212 CONFIG_PROFILING=y
1313 # CONFIG_BLOCK is not set
1414 CONFIG_PREEMPT=y
15+CONFIG_NO_HZ=y
16+CONFIG_HIGH_RES_TIMERS=y
1517 CONFIG_MN10300_RTC=y
1618 CONFIG_MN10300_TTYSM_CONSOLE=y
1719 CONFIG_MN10300_TTYSM0=y
arch/mn10300/configs/asb2364_defconfig+98−0
@@ -0,0 +1,98 @@
1+CONFIG_EXPERIMENTAL=y
2+CONFIG_SYSVIPC=y
3+CONFIG_POSIX_MQUEUE=y
4+CONFIG_BSD_PROCESS_ACCT=y
5+CONFIG_TASKSTATS=y
6+CONFIG_TASK_DELAY_ACCT=y
7+CONFIG_TASK_XACCT=y
8+CONFIG_TASK_IO_ACCOUNTING=y
9+CONFIG_LOG_BUF_SHIFT=14
10+CONFIG_CGROUPS=y
11+CONFIG_CGROUP_NS=y
12+CONFIG_CGROUP_FREEZER=y
13+CONFIG_CGROUP_DEVICE=y
14+CONFIG_CGROUP_CPUACCT=y
15+CONFIG_RESOURCE_COUNTERS=y
16+CONFIG_RELAY=y
17+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
18+CONFIG_EMBEDDED=y
19+# CONFIG_KALLSYMS is not set
20+# CONFIG_VM_EVENT_COUNTERS is not set
21+CONFIG_SLAB=y
22+CONFIG_PROFILING=y
23+CONFIG_MODULES=y
24+CONFIG_MODULE_UNLOAD=y
25+# CONFIG_BLOCK is not set
26+CONFIG_MN10300_UNIT_ASB2364=y
27+CONFIG_PREEMPT=y
28+# CONFIG_MN10300_USING_JTAG is not set
29+CONFIG_NO_HZ=y
30+CONFIG_HIGH_RES_TIMERS=y
31+CONFIG_MN10300_TTYSM_CONSOLE=y
32+CONFIG_MN10300_TTYSM0=y
33+CONFIG_MN10300_TTYSM0_TIMER2=y
34+CONFIG_MN10300_TTYSM1=y
35+CONFIG_NET=y
36+CONFIG_PACKET=y
37+CONFIG_UNIX=y
38+CONFIG_INET=y
39+CONFIG_IP_MULTICAST=y
40+CONFIG_IP_PNP=y
41+CONFIG_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
47+CONFIG_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
52+CONFIG_CONNECTOR=y
53+CONFIG_MTD=y
54+CONFIG_MTD_DEBUG=y
55+CONFIG_MTD_PARTITIONS=y
56+CONFIG_MTD_REDBOOT_PARTS=y
57+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
58+CONFIG_MTD_CHAR=y
59+CONFIG_MTD_CFI=y
60+CONFIG_MTD_JEDECPROBE=y
61+CONFIG_MTD_CFI_ADV_OPTIONS=y
62+CONFIG_MTD_CFI_GEOMETRY=y
63+CONFIG_MTD_CFI_I4=y
64+CONFIG_MTD_CFI_AMDSTD=y
65+CONFIG_MTD_PHYSMAP=y
66+CONFIG_NETDEVICES=y
67+CONFIG_NET_ETHERNET=y
68+CONFIG_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
76+CONFIG_SERIAL_8250=y
77+CONFIG_SERIAL_8250_CONSOLE=y
78+CONFIG_SERIAL_8250_EXTENDED=y
79+CONFIG_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
84+CONFIG_PROC_KCORE=y
85+# CONFIG_PROC_PAGE_MONITOR is not set
86+CONFIG_TMPFS=y
87+CONFIG_TMPFS_POSIX_ACL=y
88+CONFIG_JFFS2_FS=y
89+CONFIG_NFS_FS=y
90+CONFIG_NFS_V3=y
91+CONFIG_ROOT_NFS=y
92+CONFIG_MAGIC_SYSRQ=y
93+CONFIG_STRIP_ASM_SYMS=y
94+CONFIG_DEBUG_KERNEL=y
95+CONFIG_DETECT_HUNG_TASK=y
96+# CONFIG_DEBUG_BUGVERBOSE is not set
97+CONFIG_DEBUG_INFO=y
98+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
arch/mn10300/include/asm/atomic.h+350−0
@@ -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
20+static inline
21+unsigned 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+
41+static 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+ */
73+struct __xchg_dummy { unsigned long a[100]; };
74+#define __xg(x) ((struct __xchg_dummy *)(x))
75+
76+static inline
77+unsigned 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+ */
92+static 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
1123 #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+ */
162+static 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+ */
201+static 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+
231+static inline int atomic_add_negative(int i, atomic_t *v)
232+{
233+ return atomic_add_return(i, v) < 0;
234+}
235+
236+static inline void atomic_add(int i, atomic_t *v)
237+{
238+ atomic_add_return(i, v);
239+}
240+
241+static inline void atomic_sub(int i, atomic_t *v)
242+{
243+ atomic_sub_return(i, v);
244+}
245+
246+static inline void atomic_inc(atomic_t *v)
247+{
248+ atomic_add_return(1, v);
249+}
250+
251+static 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+ */
281+static 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+ */
315+static 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 */
arch/mn10300/include/asm/bitops.h+7−7
@@ -57,7 +57,7 @@ · 56 unmodified lines
5757 #define clear_bit(nr, addr) ___clear_bit((nr), (addr))
5858
5959
60−static inline void __clear_bit(int nr, volatile void *addr)
60+static inline void __clear_bit(unsigned long nr, volatile void *addr)
6161 {
6262 unsigned int *a = (unsigned int *) addr;
6363 int mask;
@@ -70,15 +70,15 @@ static inline void __clear_bit(int nr, volatile void *addr) · 6 unmodified lines
7070 /*
7171 * test bit
7272 */
73−static inline int test_bit(int nr, const volatile void *addr)
73+static inline int test_bit(unsigned long nr, const volatile void *addr)
7474 {
75− return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
75+ return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
7676 }
7777
7878 /*
7979 * change bit
8080 */
81−static inline void __change_bit(int nr, volatile void *addr)
81+static inline void __change_bit(unsigned long nr, volatile void *addr)
8282 {
8383 int mask;
8484 unsigned int *a = (unsigned int *) addr;
@@ -88,7 +88,7 @@ static inline void __change_bit(int nr, volatile void *addr) · 3 unmodified lines
8888 *a ^= mask;
8989 }
9090
91−extern void change_bit(int nr, volatile void *addr);
91+extern void change_bit(unsigned long nr, volatile void *addr);
9292
9393 /*
9494 * test and set bit
@@ -135,7 +135,7 @@ extern void change_bit(int nr, volatile void *addr); · 40 unmodified lines
135135 /*
136136 * test and change bit
137137 */
138−static inline int __test_and_change_bit(int nr, volatile void *addr)
138+static inline int __test_and_change_bit(unsigned long nr, volatile void *addr)
139139 {
140140 int mask, retval;
141141 unsigned int *a = (unsigned int *)addr;
@@ -148,7 +148,7 @@ static inline int __test_and_change_bit(int nr, volatile void *addr) · 6 unmodified lines
148148 return retval;
149149 }
150150
151−extern int test_and_change_bit(int nr, volatile void *addr);
151+extern int test_and_change_bit(unsigned long nr, volatile void *addr);
152152
153153 #include <asm-generic/bitops/lock.h>
154154
arch/mn10300/include/asm/cache.h+9−5
@@ -43,14 +43,18 @@ · 42 unmodified lines
4343
4444 /* instruction cache access registers */
4545 #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)
4748 #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)
4951
50−/* instruction cache access registers */
52+/* data cache access registers */
5153 #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)
5356 #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)
5559
5660 #endif /* _ASM_CACHE_H */
arch/mn10300/include/asm/cacheflush.h+109−55
@@ -17,66 +17,55 @@ · 16 unmodified lines
1717 #include <linux/mm.h>
1818
1919 /*
20− * virtually-indexed cache management (our cache is physically indexed)
20+ * Primitive routines
2121 */
22−#define flush_cache_all() do {} while (0)
23−#define flush_cache_mm(mm) do {} while (0)
24−#define flush_cache_dup_mm(mm) do {} while (0)
25−#define flush_cache_range(mm, start, end) do {} while (0)
26−#define flush_cache_page(vma, vmaddr, pfn) do {} while (0)
27−#define flush_cache_vmap(start, end) do {} while (0)
28−#define flush_cache_vunmap(start, end) do {} while (0)
29−#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
30−#define flush_dcache_page(page) do {} while (0)
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−
39−extern void flush_icache_range(unsigned long start, unsigned long end);
40−extern 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
22+#ifdef CONFIG_MN10300_CACHE_ENABLED
23+extern void mn10300_local_icache_inv(void);
24+extern void mn10300_local_icache_inv_page(unsigned long start);
25+extern void mn10300_local_icache_inv_range(unsigned long start, unsigned long end);
26+extern void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size);
27+extern void mn10300_local_dcache_inv(void);
28+extern void mn10300_local_dcache_inv_page(unsigned long start);
29+extern void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end);
30+extern void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size);
6531 extern void mn10300_icache_inv(void);
32+extern void mn10300_icache_inv_page(unsigned long start);
33+extern void mn10300_icache_inv_range(unsigned long start, unsigned long end);
34+extern void mn10300_icache_inv_range2(unsigned long start, unsigned long size);
6635 extern void mn10300_dcache_inv(void);
67−extern void mn10300_dcache_inv_page(unsigned start);
68−extern void mn10300_dcache_inv_range(unsigned start, unsigned end);
69−extern void mn10300_dcache_inv_range2(unsigned start, unsigned size);
36+extern void mn10300_dcache_inv_page(unsigned long start);
37+extern void mn10300_dcache_inv_range(unsigned long start, unsigned long end);
38+extern void mn10300_dcache_inv_range2(unsigned long start, unsigned long size);
7039 #ifdef CONFIG_MN10300_CACHE_WBACK
40+extern void mn10300_local_dcache_flush(void);
41+extern void mn10300_local_dcache_flush_page(unsigned long start);
42+extern void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end);
43+extern void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size);
44+extern void mn10300_local_dcache_flush_inv(void);
45+extern void mn10300_local_dcache_flush_inv_page(unsigned long start);
46+extern void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end);
47+extern void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size);
7148 extern void mn10300_dcache_flush(void);
72−extern void mn10300_dcache_flush_page(unsigned start);
73−extern void mn10300_dcache_flush_range(unsigned start, unsigned end);
74−extern void mn10300_dcache_flush_range2(unsigned start, unsigned size);
49+extern void mn10300_dcache_flush_page(unsigned long start);
50+extern void mn10300_dcache_flush_range(unsigned long start, unsigned long end);
51+extern void mn10300_dcache_flush_range2(unsigned long start, unsigned long size);
7552 extern void mn10300_dcache_flush_inv(void);
76−extern void mn10300_dcache_flush_inv_page(unsigned start);
77−extern void mn10300_dcache_flush_inv_range(unsigned start, unsigned end);
78−extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size);
53+extern void mn10300_dcache_flush_inv_page(unsigned long start);
54+extern void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end);
55+extern void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size);
7956 #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)
8069 #define mn10300_dcache_flush() do {} while (0)
8170 #define mn10300_dcache_flush_page(start) do {} while (0)
8271 #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); · 7 unmodified lines
9079 mn10300_dcache_inv_range2((start), (size))
9180 #endif /* CONFIG_MN10300_CACHE_WBACK */
9281 #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)
9398 #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)
94102 #define mn10300_dcache_inv() do {} while (0)
95103 #define mn10300_dcache_inv_page(start) do {} while (0)
96104 #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); · 6 unmodified lines
103111 #define mn10300_dcache_flush_page(start) do {} while (0)
104112 #define mn10300_dcache_flush_range(start, end) do {} while (0)
105113 #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)
135+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
136+extern void flush_icache_range(unsigned long start, unsigned long end);
137+#elif defined(CONFIG_MN10300_CACHE_INV_ICACHE)
138+static 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+}
143+extern 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)
107161
108162 /*
109− * internal debugging function
163+ * Internal debugging function
110164 */
111165 #ifdef CONFIG_DEBUG_PAGEALLOC
112166 extern void kernel_map_pages(struct page *page, int numpages, int enable);
arch/mn10300/include/asm/cpu-regs.h+77−14
@@ -15,7 +15,6 @@ · 14 unmodified lines
1515 #include <linux/types.h>
1616 #endif
1717
18−#ifdef CONFIG_MN10300_CPU_AM33V2
1918 /* we tell the compiler to pretend to be AM33 so that it doesn't try and use
2019 * the FP regs, but tell the assembler that we're actually allowed AM33v2
2120 * instructions */
@@ -24,7 +23,6 @@ asm(" .am33_2\n"); · 2 unmodified lines
2423 #else
2524 .am33_2
2625 #endif
27−#endif
2826
2927 #ifdef __KERNEL__
3028
@@ -58,6 +56,9 @@ asm(" .am33_2\n"); · 27 unmodified lines
5856 #define EPSW_nAR 0x00040000 /* register bank control */
5957 #define EPSW_ML 0x00080000 /* monitor level */
6058 #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)
6162
6263 /* FPU registers */
6364 #define FPCR_EF_I 0x00000001 /* inexact result FPU exception flag */
@@ -99,9 +100,11 @@ asm(" .am33_2\n"); · 35 unmodified lines
99100 #define CPUREV __SYSREGC(0xc0000050, u32) /* CPU revision register */
100101 #define CPUREV_TYPE 0x0000000f /* CPU type */
101102 #define CPUREV_TYPE_S 0
102−#define CPUREV_TYPE_AM33V1 0x00000000 /* - AM33 V1 core, AM33/1.00 arch */
103−#define CPUREV_TYPE_AM33V2 0x00000001 /* - AM33 V2 core, AM33/2.00 arch */
104−#define CPUREV_TYPE_AM34V1 0x00000002 /* - AM34 V1 core, AM33/2.00 arch */
103+#define CPUREV_TYPE_AM33_1 0x00000000 /* - AM33-1 core, AM33/1.00 arch */
104+#define CPUREV_TYPE_AM33_2 0x00000001 /* - AM33-2 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 */
105108 #define CPUREV_REVISION 0x000000f0 /* CPU revision */
106109 #define CPUREV_REVISION_S 4
107110 #define CPUREV_ICWAY 0x00000f00 /* number of instruction cache ways */
@@ -180,6 +183,21 @@ asm(" .am33_2\n"); · 72 unmodified lines
180183 #define CHCTR_ICWMD 0x0f00 /* instruction cache way mode */
181184 #define CHCTR_DCWMD 0xf000 /* data cache way mode */
182185
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+
183201 /* MMU control registers */
184202 #define MMUCTR __SYSREG(0xc0000090, u32) /* MMU control register */
185203 #define MMUCTR_IRP 0x0000003f /* instruction TLB replace pointer */
@@ -203,6 +221,9 @@ asm(" .am33_2\n"); · 17 unmodified lines
203221 #define MMUCTR_DTL_LOCK0_3 0x03000000 /* - entry 0-3 locked */
204222 #define MMUCTR_DTL_LOCK0_7 0x04000000 /* - entry 0-7 locked */
205223 #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
206227
207228 #define PIDR __SYSREG(0xc0000094, u16) /* PID register */
208229 #define PIDR_PID 0x00ff /* process identifier */
@@ -231,14 +252,6 @@ asm(" .am33_2\n"); · 22 unmodified lines
231252 #define xPTEL_PS_4Mb 0x00000c00 /* - 4Mb page */
232253 #define xPTEL_PPN 0xfffff006 /* physical page number */
233254
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−
242255 #define IPTEU __SYSREG(0xc00000a4, u32) /* instruction TLB virtual addr */
243256 #define DPTEU __SYSREG(0xc00000b4, u32) /* data TLB virtual addr */
244257 #define xPTEU_VPN 0xfffffc00 /* virtual page number */
@@ -262,7 +275,16 @@ asm(" .am33_2\n"); · 17 unmodified lines
262275 #define xPTEL2_PS_128Kb 0x00000100 /* - 128Kb page */
263276 #define xPTEL2_PS_1Kb 0x00000200 /* - 1Kb page */
264277 #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
266288
267289 #define MMUFCR __SYSREGC(0xc000009c, u32) /* MMU exception cause */
268290 #define MMUFCR_IFC __SYSREGC(0xc000009c, u16) /* MMU instruction excep cause */
@@ -285,6 +307,47 @@ asm(" .am33_2\n"); · 16 unmodified lines
285307 #define MMUFCR_xFC_PR_RWK_RWU 0x01c0 /* - R/W kernel and R/W user */
286308 #define MMUFCR_xFC_ILLADDR 0x0200 /* illegal address excep flag */
287309
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__
334+asm(
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+
288351 #endif /* __KERNEL__ */
289352
290353 #endif /* _ASM_CPU_REGS_H */
arch/mn10300/include/asm/dmactl-regs.h+1−86
@@ -11,91 +11,6 @@ · 10 unmodified lines
1111 #ifndef _ASM_DMACTL_REGS_H
1212 #define _ASM_DMACTL_REGS_H
1313
14−#include <asm/cpu-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−
89−struct 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__ */
14+#include <proc/dmactl-regs.h>
10015
10116 #endif /* _ASM_DMACTL_REGS_H */
arch/mn10300/include/asm/elf.h+10−2
@@ -31,6 +31,12 @@ · 30 unmodified lines
3131 #define R_MN10300_SYM_DIFF 33 /* Adjustment when relaxing. */
3232 #define R_MN10300_ALIGN 34 /* Alignment requirement. */
3333
34+/*
35+ * AM33/AM34 HW Capabilities
36+ */
37+#define HWCAP_MN10300_ATOMIC_OP_UNIT 1 /* Has AM34 Atomic Operations */
38+
39+
3440 /*
3541 * ELF register definitions..
3642 */
@@ -47,8 +53,6 @@ typedef struct { · 10 unmodified lines
4753 u_int32_t fpcr;
4854 } elf_fpregset_t;
4955
50−extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
51−
5256 /*
5357 * This is used to ensure we don't load something for the wrong architecture
5458 */
@@ -130,7 +134,11 @@ do { \ · 75 unmodified lines
130134 * instruction set this CPU supports. This could be done in user space,
131135 * but it's not easy, and we've already done it here.
132136 */
137+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
138+#define ELF_HWCAP (HWCAP_MN10300_ATOMIC_OP_UNIT)
139+#else
133140 #define ELF_HWCAP (0)
141+#endif
134142
135143 /*
136144 * This yields a string that ld.so will use to load implementation
arch/mn10300/include/asm/exceptions.h+4−4
@@ -15,8 +15,8 @@ · 14 unmodified lines
1515
1616 /*
1717 * define the breakpoint instruction opcode to use
18− * - note that the JTAG unit steals 0xFF, so we want to avoid that if we can
19− * (can use 0xF7)
18+ * - note that the JTAG unit steals 0xFF, so you can't use JTAG and GDBSTUB at
19+ * the same time.
2020 */
2121 #define GDBSTUB_BKPT 0xFF
2222
@@ -90,7 +90,6 @@ enum exception_code { · 67 unmodified lines
9090
9191 extern void __set_intr_stub(enum exception_code code, void *handler);
9292 extern void set_intr_stub(enum exception_code code, void *handler);
93−extern void set_jtag_stub(enum exception_code code, void *handler);
9493
9594 struct pt_regs;
9695
@@ -102,7 +101,6 @@ extern asmlinkage void dtlb_aerror(void); · 5 unmodified lines
102101 extern asmlinkage void raw_bus_error(void);
103102 extern asmlinkage void double_fault(void);
104103 extern asmlinkage int system_call(struct pt_regs *);
105−extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
106104 extern asmlinkage void nmi(struct pt_regs *, enum exception_code);
107105 extern asmlinkage void uninitialised_exception(struct pt_regs *,
108106 enum exception_code);
@@ -116,6 +114,8 @@ extern void die(const char *, struct pt_regs *, enum exception_code) · 7 unmodified lines
116114
117115 extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code);
118116
117+#define NUM2EXCEP_IRQ_LEVEL(num) (EXCEP_IRQ_LEVEL0 + (num) * 8)
118+
119119 #endif /* __ASSEMBLY__ */
120120
121121 #endif /* _ASM_EXCEPTIONS_H */
arch/mn10300/include/asm/fpu.h+104−53
@@ -12,74 +12,125 @@ · 11 unmodified lines
1212 #ifndef _ASM_FPU_H
1313 #define _ASM_FPU_H
1414
15−#include <asm/processor.h>
15+#ifndef __ASSEMBLY__
16+
17+#include <linux/sched.h>
18+#include <asm/exceptions.h>
1619 #include <asm/sigcontext.h>
17−#include <asm/user.h>
1820
1921 #ifdef __KERNEL__
2022
21−/* the task that owns the FPU state */
23+extern 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 */
2229 extern struct task_struct *fpu_state_owner;
30+#endif
2331
24−#define set_using_fpu(tsk) \
25−do { \
26− (tsk)->thread.fpu_flags |= THREAD_USING_FPU; \
27−} while (0)
32+#if (THREAD_USING_FPU & ~0xff)
33+#error THREAD_USING_FPU must be smaller than 0x100.
34+#endif
2835
29−#define clear_using_fpu(tsk) \
30−do { \
31− (tsk)->thread.fpu_flags &= ~THREAD_USING_FPU; \
32−} while (0)
36+static inline void set_using_fpu(struct task_struct *tsk)
37+{
38+ asm volatile(
39+ "bset %0,(0,%1)"
40+ :
41+ : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
42+ : "memory", "cc");
43+}
3344
34−#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
45+static 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+}
3553
36−#define unlazy_fpu(tsk) \
37−do { \
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() \
45−do { \
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() \
54−do { \
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)
54+#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
6455
65−extern asmlinkage void fpu_init_state(void);
6656 extern asmlinkage void fpu_kill_state(struct task_struct *);
67−extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code);
6857 extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
69−
70−#ifdef CONFIG_FPU
58+extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
59+extern asmlinkage void fpu_init_state(void);
7160 extern asmlinkage void fpu_save(struct fpu_state_struct *);
72−extern 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− */
8161 extern int fpu_setup_sigcontext(struct fpucontext *buf);
8262 extern int fpu_restore_sigcontext(struct fpucontext *buf);
8363
64+static 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+
80+static 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+
92+static 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+
114+extern asmlinkage
115+void 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+
119+struct task_struct;
120+struct fpu_state_struct;
121+static inline bool is_using_fpu(struct task_struct *tsk) { return false; }
122+static inline void set_using_fpu(struct task_struct *tsk) {}
123+static inline void clear_using_fpu(struct task_struct *tsk) {}
124+static inline void fpu_init_state(void) {}
125+static inline void fpu_save(struct fpu_state_struct *s) {}
126+static inline void fpu_kill_state(struct task_struct *tsk) {}
127+static inline void unlazy_fpu(struct task_struct *tsk) {}
128+static inline void exit_fpu(void) {}
129+static inline void flush_fpu(void) {}
130+static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
131+static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
132+#endif /* CONFIG_FPU */
133+
84134 #endif /* __KERNEL__ */
135+#endif /* !__ASSEMBLY__ */
85136 #endif /* _ASM_FPU_H */
arch/mn10300/include/asm/frame.inc+13−7
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #ifndef __ASM_OFFSETS_H__
1919 #include <asm/asm-offsets.h>
2020 #endif
21+#include <asm/thread_info.h>
2122
2223 #define pi break
2324
@@ -37,11 +38,15 @@ · 13 unmodified lines
3738 movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
3839 mov sp,fp # FRAME pointer in A3
3940 add -12,sp # allow for calls to be made
40− mov (__frame),a1
41− mov a1,(REG_NEXT,fp)
42− mov fp,(__frame)
4341
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
4550
4651 # we may be holding current in E2
4752 #ifdef CONFIG_MN10300_CURRENT_IN_E2
@@ -57,10 +62,11 @@ · 9 unmodified lines
5762 .macro RESTORE_ALL
5863 # peel back the stack to the calling frame
5964 # - 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
6167 mov fp,sp
62− mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
63− mov d0,(__frame)
68+ mov (REG_NEXT,fp),d0
69+ mov d0,(TI_frame,a0) # userspace has regs->next == 0
6470
6571 #ifndef CONFIG_MN10300_USING_JTAG
6672 mov (REG_EPSW,fp),d0
arch/mn10300/include/asm/gdb-stub.h+1−1
@@ -110,7 +110,7 @@ extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code); · 109 unmodified lines
110110 extern asmlinkage void __gdbstub_bug_trap(void);
111111 extern asmlinkage void __gdbstub_pause(void);
112112
113−#ifndef CONFIG_MN10300_CACHE_DISABLED
113+#ifdef CONFIG_MN10300_CACHE_ENABLED
114114 extern asmlinkage void gdbstub_purge_cache(void);
115115 #else
116116 #define gdbstub_purge_cache() do {} while (0)
arch/mn10300/include/asm/hardirq.h+2−1
@@ -19,9 +19,10 @@ · 18 unmodified lines
1919 /* assembly code in softirq.h is sensitive to the offsets of these fields */
2020 typedef struct {
2121 unsigned int __softirq_pending;
22− unsigned long idle_timestamp;
22+#ifdef CONFIG_MN10300_WD_TIMER
2323 unsigned int __nmi_count; /* arch dependent */
2424 unsigned int __irq_count; /* arch dependent */
25+#endif
2526 } ____cacheline_aligned irq_cpustat_t;
2627
2728 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
arch/mn10300/include/asm/highmem.h+2−2
@@ -87,7 +87,7 @@ static inline unsigned long __kmap_atomic(struct page *page) · 86 unmodified lines
8787 BUG();
8888 #endif
8989 set_pte(kmap_pte - idx, mk_pte(page, kmap_prot));
90− __flush_tlb_one(vaddr);
90+ local_flush_tlb_one(vaddr);
9191
9292 return vaddr;
9393 }
@@ -116,7 +116,7 @@ static inline void __kunmap_atomic(unsigned long vaddr) · 22 unmodified lines
116116 * this pte without first remap it
117117 */
118118 pte_clear(kmap_pte - idx);
119− __flush_tlb_one(vaddr);
119+ local_flush_tlb_one(vaddr);
120120 }
121121 #endif
122122
arch/mn10300/include/asm/intctl-regs.h+20−17
@@ -15,24 +15,19 @@ · 14 unmodified lines
1515
1616 #ifdef __KERNEL__
1717
18−/* interrupt controller registers */
19−#define GxICR(X) __SYSREG(0xd4000000 + (X) * 4, u16) /* group irq ctrl regs */
20−
21−#define IAGR __SYSREG(0xd4000100, u16) /* intr acceptance group reg */
22−#define IAGR_GN 0x00fc /* group number register
23− * (documentation _has_ to be wrong)
24− */
18+/*
19+ * Interrupt controller registers
20+ * - Registers 64-191 are at addresses offset from the main array
21+ */
22+#define GxICR(X) \
23+ __SYSREG(0xd4000000 + (X) * 4 + \
24+ (((X) >= 64) && ((X) < 192)) * 0xf00, u16)
2525
26−#define EXTMD __SYSREG(0xd4000200, u16) /* external pin intr spec reg */
27−#define GET_XIRQ_TRIGGER(X) ((EXTMD >> ((X) * 2)) & 3)
26+#define GxICR_u8(X) \
27+ __SYSREG(0xd4000000 + (X) * 4 + \
28+ (((X) >= 64) && ((X) < 192)) * 0xf00, u8)
2829
29−#define SET_XIRQ_TRIGGER(X,Y) \
30−do { \
31− u16 x = EXTMD; \
32− x &= ~(3 << ((X) * 2)); \
33− x |= ((Y) & 3) << ((X) * 2); \
34− EXTMD = x; \
35−} while (0)
30+#include <proc/intctl-regs.h>
3631
3732 #define XIRQ_TRIGGER_LOWLEVEL 0
3833 #define XIRQ_TRIGGER_HILEVEL 1
@@ -59,10 +54,18 @@ do { \ · 20 unmodified lines
5954 #define GxICR_LEVEL_5 0x5000 /* - level 5 */
6055 #define GxICR_LEVEL_6 0x6000 /* - level 6 */
6156 #define GxICR_LEVEL_SHIFT 12
57+#define GxICR_NMI 0x8000 /* nmi request flag */
58+
59+#define NUM2GxICR_LEVEL(num) ((num) << GxICR_LEVEL_SHIFT)
6260
6361 #ifndef __ASSEMBLY__
6462 extern void set_intr_level(int irq, u16 level);
65−extern void set_intr_postackable(int irq);
63+extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
64+extern void mn10300_intc_clear(unsigned int irq);
65+extern void mn10300_intc_set(unsigned int irq);
66+extern void mn10300_intc_enable(unsigned int irq);
67+extern void mn10300_intc_disable(unsigned int irq);
68+extern void mn10300_set_lateack_irq_type(int irq);
6669 #endif
6770
6871 /* external interrupts */
arch/mn10300/include/asm/io.h+13−0
@@ -206,6 +206,19 @@ static inline void outsl(unsigned long addr, const void *buffer, int count) · 205 unmodified lines
206206 #define iowrite32_rep(p, src, count) \
207207 outsl((unsigned long) (p), (src), (count))
208208
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))
209222
210223 #define IO_SPACE_LIMIT 0xffffffff
211224
arch/mn10300/include/asm/irq.h+10−2
@@ -21,8 +21,16 @@ · 20 unmodified lines
2121 /* this number is used when no interrupt has been assigned */
2222 #define NO_IRQ INT_MAX
2323
24−/* hardware irq numbers */
25−#define NR_IRQS GxICR_NUM_IRQS
24+/*
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
2634
2735 /* external hardware irq numbers */
2836 #define NR_XIRQS GxICR_NUM_XIRQS
arch/mn10300/include/asm/irq_regs.h+5−1
@@ -18,7 +18,11 @@ · 17 unmodified lines
1818 #define ARCH_HAS_OWN_IRQ_REGS
1919
2020 #ifndef __ASSEMBLY__
21−#define get_irq_regs() (__frame)
21+static inline __attribute__((const))
22+struct pt_regs *get_irq_regs(void)
23+{
24+ return current_frame();
25+}
2226 #endif
2327
2428 #endif /* _ASM_IRQ_REGS_H */
arch/mn10300/include/asm/irqflags.h+102−9
@@ -13,6 +13,9 @@ · 12 unmodified lines
1313 #define _ASM_IRQFLAGS_H
1414
1515 #include <asm/cpu-regs.h>
16+#ifndef __ASSEMBLY__
17+#include <linux/smp.h>
18+#endif
1619
1720 /*
1821 * interrupt control
@@ -23,11 +26,7 @@ · 4 unmodified lines
2326 * - level 6 - timer interrupt
2427 * - "enabled": run in IM7
2528 */
26−#ifdef CONFIG_MN10300_TTYSM
27−#define MN10300_CLI_LEVEL EPSW_IM_2
28−#else
29−#define MN10300_CLI_LEVEL EPSW_IM_1
30−#endif
29+#define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
3130
3231 #ifndef __ASSEMBLY__
3332
@@ -64,11 +63,12 @@ static inline unsigned long arch_local_irq_save(void) · 30 unmodified lines
6463 /*
6564 * we make sure arch_irq_enable() doesn't cause priority inversion
6665 */
67−extern unsigned long __mn10300_irq_enabled_epsw;
66+extern unsigned long __mn10300_irq_enabled_epsw[];
6867
6968 static inline void arch_local_irq_enable(void)
7069 {
7170 unsigned long tmp;
71+ int cpu = raw_smp_processor_id();
7272
7373 asm volatile(
7474 " mov epsw,%0 \n"
@@ -76,8 +76,8 @@ static inline void arch_local_irq_enable(void) · 1 unmodified line
7676 " or %2,%0 \n"
7777 " mov %0,epsw \n"
7878 : "=&d"(tmp)
79− : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
80− : "memory");
79+ : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
80+ : "memory", "cc");
8181 }
8282
8383 static inline void arch_local_irq_restore(unsigned long flags)
@@ -94,7 +94,7 @@ static inline void arch_local_irq_restore(unsigned long flags) · 10 unmodified lines
9494
9595 static inline bool arch_irqs_disabled_flags(unsigned long flags)
9696 {
97− return (flags & EPSW_IM) <= MN10300_CLI_LEVEL;
97+ return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
9898 }
9999
100100 static inline bool arch_irqs_disabled(void)
@@ -109,6 +109,9 @@ static inline bool arch_irqs_disabled(void) · 8 unmodified lines
109109 */
110110 static inline void arch_safe_halt(void)
111111 {
112+#ifdef CONFIG_SMP
113+ arch_local_irq_enable();
114+#else
112115 asm volatile(
113116 " or %0,epsw \n"
114117 " nop \n"
@@ -117,7 +120,97 @@ static inline void arch_safe_halt(void) · 2 unmodified lines
117120 :
118121 : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
119122 : "cc");
123+#endif
120124 }
121125
126+#define __sleep_cpu() \
127+do { \
128+ asm volatile( \
129+ " bset %1,(%0)\n" \
130+ "1: btst %1,(%0)\n" \
131+ " bne 1b\n" \
132+ : \
133+ : "i"(&CPUM), "i"(CPUM_SLEEP) \
134+ : "cc" \
135+ ); \
136+} while (0)
137+
138+static 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+
151+static 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+
158+static inline void arch_local_sti(void)
159+{
160+ asm volatile(
161+ " or %0,epsw \n"
162+ :
163+ : "i"(EPSW_IE)
164+ : "memory");
165+}
166+
167+static 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+
122215 #endif /* __ASSEMBLY__ */
123216 #endif /* _ASM_IRQFLAGS_H */
arch/mn10300/include/asm/mmu_context.h+48−25
@@ -27,28 +27,38 @@ · 26 unmodified lines
2727 #include <asm/tlbflush.h>
2828 #include <asm-generic/mm_hooks.h>
2929
30+#define MMU_CONTEXT_TLBPID_NR 256
3031 #define MMU_CONTEXT_TLBPID_MASK 0x000000ffUL
3132 #define MMU_CONTEXT_VERSION_MASK 0xffffff00UL
3233 #define MMU_CONTEXT_FIRST_VERSION 0x00000100UL
3334 #define MMU_NO_CONTEXT 0x00000000UL
34−
35−extern unsigned long mmu_context_cache[NR_CPUS];
36−#define mm_context(mm) (mm->context.tlbpid[smp_processor_id()])
35+#define MMU_CONTEXT_TLBPID_LOCK_NR 0
3736
3837 #define enter_lazy_tlb(mm, tsk) do {} while (0)
3938
39+static inline void cpu_ran_vm(int cpu, struct mm_struct *mm)
40+{
4041 #ifdef CONFIG_SMP
41−#define cpu_ran_vm(cpu, mm) \
42− cpumask_set_cpu((cpu), mm_cpumask(mm))
43−#define cpu_maybe_ran_vm(cpu, mm) \
44− cpumask_test_and_set_cpu((cpu), mm_cpumask(mm))
42+ cpumask_set_cpu(cpu, mm_cpumask(mm));
43+#endif
44+}
45+
46+static 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));
4550 #else
46−#define cpu_ran_vm(cpu, mm) do {} while (0)
47−#define cpu_maybe_ran_vm(cpu, mm) true
48−#endif /* CONFIG_SMP */
51+ return true;
52+#endif
53+}
4954
50−/*
51− * allocate an MMU context
55+#ifdef CONFIG_MN10300_TLB_USE_PIDR
56+extern 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
5262 */
5363 static inline unsigned long allocate_mmu_context(struct mm_struct *mm)
5464 {
@@ -58,7 +68,7 @@ static inline unsigned long allocate_mmu_context(struct mm_struct *mm) · 3 unmodified lines
5868 if (!(mc & MMU_CONTEXT_TLBPID_MASK)) {
5969 /* we exhausted the TLB PIDs of this version on this CPU, so we
6070 * flush this CPU's TLB in its entirety and start new cycle */
61− flush_tlb_all();
71+ local_flush_tlb_all();
6272
6373 /* fix the TLB version if needed (we avoid version #0 so as to
6474 * distingush MMU_NO_CONTEXT) */
@@ -100,23 +110,35 @@ static inline int init_new_context(struct task_struct *tsk, · 35 unmodified lines
100110 return 0;
101111 }
102112
103−/*
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−
109113 /*
110114 * after we have set current->mm to a new value, this activates the context for
111115 * the new mm so we see the new mappings.
112116 */
113−static inline void activate_context(struct mm_struct *mm, int cpu)
117+static inline void activate_context(struct mm_struct *mm)
114118 {
115119 PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK;
116120 }
121+#else /* CONFIG_MN10300_TLB_USE_PIDR */
117122
118−/*
119− * change between virtual memory sets
123+#define init_new_context(tsk, mm) (0)
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.
120142 */
121143 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
122144 struct task_struct *tsk)
@@ -124,11 +146,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, · 1 unmodified line
124146 int cpu = smp_processor_id();
125147
126148 if (prev != next) {
149+#ifdef CONFIG_SMP
150+ per_cpu(cpu_tlbstate, cpu).active_mm = next;
151+#endif
127152 cpu_ran_vm(cpu, next);
128− activate_context(next, cpu);
129153 PTBR = (unsigned long) next->pgd;
130− } else if (!cpu_maybe_ran_vm(cpu, next)) {
131− activate_context(next, cpu);
154+ activate_context(next);
132155 }
133156 }
134157
arch/mn10300/include/asm/pgalloc.h+0−1
@@ -11,7 +11,6 @@ · 10 unmodified lines
1111 #ifndef _ASM_PGALLOC_H
1212 #define _ASM_PGALLOC_H
1313
14−#include <asm/processor.h>
1514 #include <asm/page.h>
1615 #include <linux/threads.h>
1716 #include <linux/mm.h> /* for struct page */
arch/mn10300/include/asm/pgtable.h+52−36
@@ -90,46 +90,58 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; · 89 unmodified lines
9090 * The vmalloc() routines also leaves a hole of 4kB between each vmalloced
9191 * area to catch addressing errors.
9292 */
93+#ifndef __ASSEMBLY__
94+#define VMALLOC_OFFSET (8UL * 1024 * 1024)
95+#define VMALLOC_START (0x70000000UL)
96+#define VMALLOC_END (0x7C000000UL)
97+#else
9398 #define VMALLOC_OFFSET (8 * 1024 * 1024)
9499 #define VMALLOC_START (0x70000000)
95100 #define VMALLOC_END (0x7C000000)
101+#endif
96102
97103 #ifndef __ASSEMBLY__
98104 extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE];
99105 #endif
100106
101−/* IPTEL/DPTEL bit assignments */
102−#define _PAGE_BIT_VALID xPTEL_V_BIT
103−#define _PAGE_BIT_ACCESSED xPTEL_UNUSED1_BIT /* mustn't be loaded into IPTEL/DPTEL */
104−#define _PAGE_BIT_NX xPTEL_UNUSED2_BIT /* mustn't be loaded into IPTEL/DPTEL */
105−#define _PAGE_BIT_CACHE xPTEL_C_BIT
106−#define _PAGE_BIT_PRESENT xPTEL_PV_BIT
107−#define _PAGE_BIT_DIRTY xPTEL_D_BIT
108−#define _PAGE_BIT_GLOBAL xPTEL_G_BIT
109−
110−#define _PAGE_VALID xPTEL_V
111−#define _PAGE_ACCESSED xPTEL_UNUSED1
112−#define _PAGE_NX xPTEL_UNUSED2 /* no-execute bit */
113−#define _PAGE_CACHE xPTEL_C
114−#define _PAGE_PRESENT xPTEL_PV
115−#define _PAGE_DIRTY xPTEL_D
116−#define _PAGE_PROT xPTEL_PR
117−#define _PAGE_PROT_RKNU xPTEL_PR_ROK
118−#define _PAGE_PROT_WKNU xPTEL_PR_RWK
119−#define _PAGE_PROT_RKRU xPTEL_PR_ROK_ROU
120−#define _PAGE_PROT_WKRU xPTEL_PR_RWK_ROU
121−#define _PAGE_PROT_WKWU xPTEL_PR_RWK_RWU
122−#define _PAGE_GLOBAL xPTEL_G
123−#define _PAGE_PSE xPTEL_PS_4Mb /* 4MB page */
124−
125−#define _PAGE_FILE xPTEL_UNUSED1_BIT /* set:pagecache unset:swap */
126−
127−#define __PAGE_PROT_UWAUX 0x040
128−#define __PAGE_PROT_USER 0x080
129−#define __PAGE_PROT_WRITE 0x100
107+/* IPTEL2/DPTEL2 bit assignments */
108+#define _PAGE_BIT_VALID xPTEL2_V_BIT
109+#define _PAGE_BIT_CACHE xPTEL2_C_BIT
110+#define _PAGE_BIT_PRESENT xPTEL2_PV_BIT
111+#define _PAGE_BIT_DIRTY xPTEL2_D_BIT
112+#define _PAGE_BIT_GLOBAL xPTEL2_G_BIT
113+#define _PAGE_BIT_ACCESSED xPTEL2_UNUSED1_BIT /* mustn't be loaded into IPTEL2/DPTEL2 */
114+
115+#define _PAGE_VALID xPTEL2_V
116+#define _PAGE_CACHE xPTEL2_C
117+#define _PAGE_PRESENT xPTEL2_PV
118+#define _PAGE_DIRTY xPTEL2_D
119+#define _PAGE_PROT xPTEL2_PR
120+#define _PAGE_PROT_RKNU xPTEL2_PR_ROK
121+#define _PAGE_PROT_WKNU xPTEL2_PR_RWK
122+#define _PAGE_PROT_RKRU xPTEL2_PR_ROK_ROU
123+#define _PAGE_PROT_WKRU xPTEL2_PR_RWK_ROU
124+#define _PAGE_PROT_WKWU xPTEL2_PR_RWK_RWU
125+#define _PAGE_GLOBAL xPTEL2_G
126+#define _PAGE_PS_MASK xPTEL2_PS
127+#define _PAGE_PS_4Kb xPTEL2_PS_4Kb
128+#define _PAGE_PS_128Kb xPTEL2_PS_128Kb
129+#define _PAGE_PS_1Kb xPTEL2_PS_1Kb
130+#define _PAGE_PS_4Mb xPTEL2_PS_4Mb
131+#define _PAGE_PSE xPTEL2_PS_4Mb /* 4MB page */
132+#define _PAGE_CACHE_WT xPTEL2_CWT
133+#define _PAGE_ACCESSED xPTEL2_UNUSED1
134+#define _PAGE_NX 0 /* no-execute bit */
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
130143
131144 #define _PAGE_PRESENTV (_PAGE_PRESENT|_PAGE_VALID)
132−#define _PAGE_PROTNONE 0x000 /* If not present */
133145
134146 #ifndef __ASSEMBLY__
135147
@@ -170,6 +182,9 @@ extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; · 34 unmodified lines
170182 #define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE)
171183 #define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC)
172184
185+#define __PAGE_USERIO (__PAGE_KERNEL_BASE | _PAGE_PROT_WKWU | _PAGE_NX)
186+#define PAGE_USERIO __pgprot(__PAGE_USERIO)
187+
173188 /*
174189 * Whilst the MN10300 can do page protection for execute (given separate data
175190 * 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) · 147 unmodified lines
323338 return 1;
324339 }
325340
326−/*
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
341+#define PTE_FILE_MAX_BITS 30
331342
332343 #define pte_to_pgoff(pte) (pte_val(pte) >> 2)
333344 #define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE)
@@ -373,8 +384,13 @@ static inline void ptep_mkdirty(pte_t *ptep) · 39 unmodified lines
373384 * Macro to mark a page protection value as "uncacheable". On processors which
374385 * do not support it, this is a no-op.
375386 */
376−#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE)
387+#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHE)
377388
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)
378394
379395 /*
380396 * Conversion functions: convert a page and protection to a page entry,
arch/mn10300/include/asm/processor.h+39−27
@@ -13,10 +13,13 @@ · 12 unmodified lines
1313 #ifndef _ASM_PROCESSOR_H
1414 #define _ASM_PROCESSOR_H
1515
16+#include <linux/threads.h>
17+#include <linux/thread_info.h>
1618 #include <asm/page.h>
1719 #include <asm/ptrace.h>
1820 #include <asm/cpu-regs.h>
19−#include <linux/threads.h>
21+#include <asm/uaccess.h>
22+#include <asm/current.h>
2023
2124 /* Forward declaration, a strange C thing */
2225 struct task_struct;
@@ -33,6 +36,8 @@ struct mm_struct; · 10 unmodified lines
3336 __pc; \
3437 })
3538
39+extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size);
40+
3641 extern void show_registers(struct pt_regs *regs);
3742
3843 /*
@@ -43,17 +48,22 @@ extern void show_registers(struct pt_regs *regs); · 4 unmodified lines
4348
4449 struct mn10300_cpuinfo {
4550 int type;
46− unsigned long loops_per_sec;
51+ unsigned long loops_per_jiffy;
4752 char hard_math;
48− unsigned long *pgd_quick;
49− unsigned long *pte_quick;
50− unsigned long pgtable_cache_sz;
5153 };
5254
5355 extern struct mn10300_cpuinfo boot_cpu_data;
5456
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
61+extern struct mn10300_cpuinfo cpu_data[];
62+#define current_cpu_data cpu_data[smp_processor_id()]
63+#else /* CONFIG_SMP */
5564 #define cpu_data &boot_cpu_data
5665 #define current_cpu_data boot_cpu_data
66+#endif /* CONFIG_SMP */
5767
5868 extern void identify_cpu(struct mn10300_cpuinfo *);
5969 extern void print_cpu_info(struct mn10300_cpuinfo *);
@@ -76,10 +86,6 @@ extern void dodgy_tsc(void); · 16 unmodified lines
7686 */
7787 #define TASK_UNMAPPED_BASE 0x30000000
7888
79−typedef struct {
80− unsigned long seg;
81−} mm_segment_t;
82−
8389 struct fpu_state_struct {
8490 unsigned long fs[32]; /* fpu registers */
8591 unsigned long fpcr; /* fpu control register */
@@ -92,20 +98,19 @@ struct thread_struct { · 6 unmodified lines
9298 unsigned long a3; /* kernel FP */
9399 unsigned long wchan;
94100 unsigned long usp;
95− struct pt_regs *__frame;
96101 unsigned long fpu_flags;
97102 #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 */
98104 struct fpu_state_struct fpu_state;
99105 };
100106
101−#define INIT_THREAD \
102−{ \
103− .uregs = init_uregs, \
104− .pc = 0, \
105− .sp = 0, \
106− .a3 = 0, \
107− .wchan = 0, \
108− .__frame = NULL, \
107+#define INIT_THREAD \
108+{ \
109+ .uregs = init_uregs, \
110+ .pc = 0, \
111+ .sp = 0, \
112+ .a3 = 0, \
113+ .wchan = 0, \
109114 }
110115
111116 #define INIT_MMAP \
@@ -117,13 +122,20 @@ struct thread_struct { · 5 unmodified lines
117122 * - need to discard the frame stacked by the kernel thread invoking the execve
118123 * syscall (see RESTORE_ALL macro)
119124 */
120−#define start_thread(regs, new_pc, new_sp) do { \
121− set_fs(USER_DS); \
122− __frame = current->thread.uregs; \
123− __frame->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; \
124− __frame->pc = new_pc; \
125− __frame->sp = new_sp; \
126−} while (0)
125+static inline void start_thread(struct pt_regs *regs,
126+ unsigned long new_pc, unsigned long new_sp)
127+{
128+ struct thread_info *ti = current_thread_info();
129+ struct pt_regs *frame0;
130+ set_fs(USER_DS);
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+
127139
128140 /* Free all resources held by a thread. */
129141 extern void release_thread(struct task_struct *);
@@ -157,7 +169,7 @@ unsigned long get_wchan(struct task_struct *p); · 27 unmodified lines
157169
158170 static inline void prefetch(const void *x)
159171 {
160−#ifndef CONFIG_MN10300_CACHE_DISABLED
172+#ifdef CONFIG_MN10300_CACHE_ENABLED
161173 #ifdef CONFIG_MN10300_PROC_MN103E010
162174 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
163175 #else
@@ -168,7 +180,7 @@ static inline void prefetch(const void *x) · 4 unmodified lines
168180
169181 static inline void prefetchw(const void *x)
170182 {
171−#ifndef CONFIG_MN10300_CACHE_DISABLED
183+#ifdef CONFIG_MN10300_CACHE_ENABLED
172184 #ifdef CONFIG_MN10300_PROC_MN103E010
173185 asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
174186 #else
arch/mn10300/include/asm/ptrace.h+2−11
@@ -40,7 +40,6 @@ · 39 unmodified lines
4040 #define PT_PC 26
4141 #define NR_PTREGS 27
4242
43−#ifndef __ASSEMBLY__
4443 /*
4544 * This defines the way registers are stored in the event of an exception
4645 * - the strange order is due to the MOVM instruction
@@ -75,7 +74,6 @@ struct pt_regs { · 28 unmodified lines
7574 unsigned long epsw;
7675 unsigned long pc;
7776 };
78−#endif
7977
8078 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
8179 #define PTRACE_GETREGS 12
@@ -86,12 +84,7 @@ struct pt_regs { · 4 unmodified lines
8684 /* options set using PTRACE_SETOPTIONS */
8785 #define PTRACE_O_TRACESYSGOOD 0x00000001
8886
89−#if defined(__KERNEL__)
90−
91−extern struct pt_regs *__frame; /* current frame pointer */
92−
93−#if !defined(__ASSEMBLY__)
94−struct task_struct;
87+#ifdef __KERNEL__
9588
9689 #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
9790 #define instruction_pointer(regs) ((regs)->pc)
@@ -100,9 +93,7 @@ extern void show_regs(struct pt_regs *); · 2 unmodified lines
10093
10194 #define arch_has_single_step() (1)
10295
103−#endif /* !__ASSEMBLY */
104−
10596 #define profile_pc(regs) ((regs)->pc)
10697
107−#endif /* __KERNEL__ */
98+#endif /* __KERNEL__ */
10899 #endif /* _ASM_PTRACE_H */
arch/mn10300/include/asm/reset-regs.h+1−1
@@ -50,7 +50,7 @@ static inline void mn10300_proc_hard_reset(void) · 49 unmodified lines
5050 RSTCTR |= RSTCTR_CHIPRST;
5151 }
5252
53−extern unsigned int watchdog_alert_counter;
53+extern unsigned int watchdog_alert_counter[];
5454
5555 extern void watchdog_go(void);
5656 extern asmlinkage void watchdog_handler(void);
arch/mn10300/include/asm/rtc.h+0−11
@@ -15,25 +15,14 @@ · 14 unmodified lines
1515
1616 #include <linux/init.h>
1717
18−extern void check_rtc_time(void);
1918 extern void __init calibrate_clock(void);
20−extern unsigned long __init get_initial_rtc_time(void);
2119
2220 #else /* !CONFIG_MN10300_RTC */
2321
24−static inline void check_rtc_time(void)
25−{
26−}
27−
2822 static inline void calibrate_clock(void)
2923 {
3024 }
3125
32−static inline unsigned long get_initial_rtc_time(void)
33−{
34− return 0;
35−}
36−
3726 #endif /* !CONFIG_MN10300_RTC */
3827
3928 #include <asm-generic/rtc.h>
arch/mn10300/include/asm/rwlock.h+125−0
@@ -0,0 +1,125 @@
1+/*
2+ * Helpers used by both rw spinlocks and rw semaphores.
3+ *
4+ * Based in part on code from semaphore.h and
5+ * spinlock.h Copyright 1996 Linus Torvalds.
6+ *
7+ * Copyright 1999 Red Hat, Inc.
8+ *
9+ * Written by Benjamin LaHaise.
10+ *
11+ * Modified by Matsushita Electric Industrial Co., Ltd.
12+ * Modifications:
13+ * 13-Nov-2006 MEI Temporarily delete lock functions for SMP support.
14+ *
15+ * This program is free software; you can redistribute it and/or modify it
16+ * under the terms of the GNU General Public License as published by the Free
17+ * Software Foundation; either version 2 of the License, or (at your option)
18+ * any later version.
19+ */
20+#ifndef _ASM_RWLOCK_H
21+#define _ASM_RWLOCK_H
22+
23+#define RW_LOCK_BIAS 0x01000000
24+
25+#ifndef CONFIG_SMP
26+
27+typedef struct { unsigned long a[100]; } __dummy_lock_t;
28+#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
29+
30+#define RW_LOCK_BIAS_STR "0x01000000"
31+
32+#define __build_read_lock_ptr(rw, helper) \
33+ do { \
34+ asm volatile( \
35+ " mov (%0),d3 \n" \
36+ " sub 1,d3 \n" \
37+ " mov d3,(%0) \n" \
38+ " blt 1f \n" \
39+ " bra 2f \n" \
40+ "1: jmp 3f \n" \
41+ "2: \n" \
42+ " .section .text.lock,\"ax\" \n" \
43+ "3: call "helper"[],0 \n" \
44+ " jmp 2b \n" \
45+ " .previous" \
46+ : \
47+ : "d" (rw) \
48+ : "memory", "d3", "cc"); \
49+ } while (0)
50+
51+#define __build_read_lock_const(rw, helper) \
52+ do { \
53+ asm volatile( \
54+ " mov (%0),d3 \n" \
55+ " sub 1,d3 \n" \
56+ " mov d3,(%0) \n" \
57+ " blt 1f \n" \
58+ " bra 2f \n" \
59+ "1: jmp 3f \n" \
60+ "2: \n" \
61+ " .section .text.lock,\"ax\" \n" \
62+ "3: call "helper"[],0 \n" \
63+ " jmp 2b \n" \
64+ " .previous" \
65+ : \
66+ : "d" (rw) \
67+ : "memory", "d3", "cc"); \
68+ } while (0)
69+
70+#define __build_read_lock(rw, helper) \
71+ do { \
72+ if (__builtin_constant_p(rw)) \
73+ __build_read_lock_const(rw, helper); \
74+ else \
75+ __build_read_lock_ptr(rw, helper); \
76+ } while (0)
77+
78+#define __build_write_lock_ptr(rw, helper) \
79+ do { \
80+ asm volatile( \
81+ " mov (%0),d3 \n" \
82+ " sub 1,d3 \n" \
83+ " mov d3,(%0) \n" \
84+ " blt 1f \n" \
85+ " bra 2f \n" \
86+ "1: jmp 3f \n" \
87+ "2: \n" \
88+ " .section .text.lock,\"ax\" \n" \
89+ "3: call "helper"[],0 \n" \
90+ " jmp 2b \n" \
91+ " .previous" \
92+ : \
93+ : "d" (rw) \
94+ : "memory", "d3", "cc"); \
95+ } while (0)
96+
97+#define __build_write_lock_const(rw, helper) \
98+ do { \
99+ asm volatile( \
100+ " mov (%0),d3 \n" \
101+ " sub 1,d3 \n" \
102+ " mov d3,(%0) \n" \
103+ " blt 1f \n" \
104+ " bra 2f \n" \
105+ "1: jmp 3f \n" \
106+ "2: \n" \
107+ " .section .text.lock,\"ax\" \n" \
108+ "3: call "helper"[],0 \n" \
109+ " jmp 2b \n" \
110+ " .previous" \
111+ : \
112+ : "d" (rw) \
113+ : "memory", "d3", "cc"); \
114+ } while (0)
115+
116+#define __build_write_lock(rw, helper) \
117+ do { \
118+ if (__builtin_constant_p(rw)) \
119+ __build_write_lock_const(rw, helper); \
120+ else \
121+ __build_write_lock_ptr(rw, helper); \
122+ } while (0)
123+
124+#endif /* CONFIG_SMP */
125+#endif /* _ASM_RWLOCK_H */
arch/mn10300/include/asm/serial-regs.h+41−10
@@ -20,18 +20,25 @@ · 19 unmodified lines
2020 /* serial port 0 */
2121 #define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */
2222 #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) */
2523 #define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */
2624 #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) */
2729 #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) */
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) */
30+#define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */
3131 #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) */
3235 #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 */
34−#define SC01CTR_CK_EXTERN 0x0007 /* - external closk */
36+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
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 */
3542 #define SC01CTR_STB 0x0008 /* stop bit select */
3643 #define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */
3744 #define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */
@@ -100,11 +107,23 @@ · 62 unmodified lines
100107
101108 /* serial port 2 */
102109 #define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */
110+#ifdef CONFIG_AM33_2
103111 #define SC2CTR_CK 0x0003 /* clock source select */
104112 #define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */
105113 #define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */
106114 #define SC2CTR_CK_EXTERN 0x0002 /* - external closk */
107115 #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 */
108127 #define SC2CTR_STB 0x0008 /* stop bit select */
109128 #define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */
110129 #define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */
@@ -134,9 +153,14 @@ · 23 unmodified lines
134153 #define SC2ICR_RES 0x04 /* receive error select */
135154 #define SC2ICR_RI 0x01 /* receive interrupt cause */
136155
137−#define SC2TXB __SYSREG(0xd4002018, u8) /* transmit buffer reg */
138−#define SC2RXB __SYSREG(0xd4002019, u8) /* receive buffer reg */
139−#define SC2STR __SYSREG(0xd400201c, u8) /* status reg */
156+#define SC2TXB __SYSREG(0xd4002028, u8) /* transmit buffer reg */
157+#define SC2RXB __SYSREG(0xd4002029, u8) /* receive buffer 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 */
140164 #define SC2STR_OEF 0x0001 /* overrun error found */
141165 #define SC2STR_PEF 0x0002 /* parity error found */
142166 #define SC2STR_FEF 0x0004 /* framing error found */
@@ -146,10 +170,17 @@ · 3 unmodified lines
146170 #define SC2STR_RXF 0x0040 /* receive status */
147171 #define SC2STR_TXF 0x0080 /* transmit status */
148172
173+#ifdef CONFIG_AM33_2
149174 #define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */
175+#endif
150176
177+#ifdef CONFIG_AM33_2
151178 #define SC2RXIRQ 24 /* serial 2 Receive IRQ */
152179 #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 */
153184
154185 #define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */
155186 #define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */
arch/mn10300/include/asm/serial.h+4−4
@@ -9,10 +9,8 @@ · 8 unmodified lines
99 * 2 of the Licence, or (at your option) any later version.
1010 */
1111
12−/*
13− * The ASB2305 has an 18.432 MHz clock the UART
14− */
15−#define BASE_BAUD (18432000 / 16)
12+#ifndef _ASM_SERIAL_H
13+#define _ASM_SERIAL_H
1614
1715 /* Standard COM flags (except for COM4, because of the 8514 problem) */
1816 #ifdef CONFIG_SERIAL_DETECT_IRQ
@@ -34,3 +32,5 @@ · 15 unmodified lines
3432 #endif
3533
3634 #include <unit/serial.h>
35+
36+#endif /* _ASM_SERIAL_H */
arch/mn10300/include/asm/smp.h+89−2
@@ -3,6 +3,16 @@ · 2 unmodified lines
33 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
44 * Written by David Howells (dhowells@redhat.com)
55 *
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+ *
616 * This program is free software; you can redistribute it and/or
717 * modify it under the terms of the GNU General Public Licence
818 * as published by the Free Software Foundation; either version
@@ -11,8 +21,85 @@ · 2 unmodified lines
1121 #ifndef _ASM_SMP_H
1222 #define _ASM_SMP_H
1323
14−#ifdef CONFIG_SMP
15−#error SMP not yet supported for MN10300
24+#ifndef __ASSEMBLY__
25+#include <linux/threads.h>
26+#include <linux/cpumask.h>
1627 #endif
1728
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)
1868 #endif
69+
70+static inline int cpu_logical_map(int cpu)
71+{
72+ return cpu;
73+}
74+
75+static inline int cpu_number_map(int cpu)
76+{
77+ return cpu;
78+}
79+
80+
81+extern cpumask_t cpu_boot_map;
82+
83+extern void smp_init_cpus(void);
84+extern void smp_cache_interrupt(void);
85+extern void send_IPI_allbutself(int irq);
86+extern int smp_nmi_call_function(smp_call_func_t func, void *info, int wait);
87+
88+extern void arch_send_call_function_single_ipi(int cpu);
89+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
90+
91+#ifdef CONFIG_HOTPLUG_CPU
92+extern int __cpu_disable(void);
93+extern void __cpu_die(unsigned int cpu);
94+#endif /* CONFIG_HOTPLUG_CPU */
95+
96+#endif /* __ASSEMBLY__ */
97+#else /* CONFIG_SMP */
98+#ifndef __ASSEMBLY__
99+
100+static inline void smp_init_cpus(void) {}
101+
102+#endif /* __ASSEMBLY__ */
103+#endif /* CONFIG_SMP */
104+
105+#endif /* _ASM_SMP_H */
arch/mn10300/include/asm/smsc911x.h+1−0
@@ -0,0 +1 @@
1+#include <unit/smsc911x.h>
arch/mn10300/include/asm/spinlock.h+178−1
@@ -11,6 +11,183 @@ · 10 unmodified lines
1111 #ifndef _ASM_SPINLOCK_H
1212 #define _ASM_SPINLOCK_H
1313
14−#error SMP spinlocks not implemented for MN10300
14+#include <asm/atomic.h>
15+#include <asm/rwlock.h>
16+#include <asm/page.h>
1517
18+/*
19+ * Simple spin lock operations. There are two variants, one clears IRQ's
20+ * on the local processor, one does not.
21+ *
22+ * We make no fairness assumptions. They have a cost.
23+ */
24+
25+#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) != 0)
26+#define arch_spin_unlock_wait(x) do { barrier(); } while (arch_spin_is_locked(x))
27+
28+static inline void arch_spin_unlock(arch_spinlock_t *lock)
29+{
30+ asm volatile(
31+ " bclr 1,(0,%0) \n"
32+ :
33+ : "a"(&lock->slock)
34+ : "memory", "cc");
35+}
36+
37+static inline int arch_spin_trylock(arch_spinlock_t *lock)
38+{
39+ int ret;
40+
41+ asm volatile(
42+ " mov 1,%0 \n"
43+ " bset %0,(%1) \n"
44+ " bne 1f \n"
45+ " clr %0 \n"
46+ "1: xor 1,%0 \n"
47+ : "=d"(ret)
48+ : "a"(&lock->slock)
49+ : "memory", "cc");
50+
51+ return ret;
52+}
53+
54+static inline void arch_spin_lock(arch_spinlock_t *lock)
55+{
56+ asm volatile(
57+ "1: bset 1,(0,%0) \n"
58+ " bne 1b \n"
59+ :
60+ : "a"(&lock->slock)
61+ : "memory", "cc");
62+}
63+
64+static inline void arch_spin_lock_flags(arch_spinlock_t *lock,
65+ unsigned long flags)
66+{
67+ int temp;
68+
69+ asm volatile(
70+ "1: bset 1,(0,%2) \n"
71+ " beq 3f \n"
72+ " mov %1,epsw \n"
73+ "2: mov (0,%2),%0 \n"
74+ " or %0,%0 \n"
75+ " bne 2b \n"
76+ " mov %3,%0 \n"
77+ " mov %0,epsw \n"
78+ " nop \n"
79+ " nop \n"
80+ " bra 1b\n"
81+ "3: \n"
82+ : "=&d" (temp)
83+ : "d" (flags), "a"(&lock->slock), "i"(EPSW_IE | MN10300_CLI_LEVEL)
84+ : "memory", "cc");
85+}
86+
87+#ifdef __KERNEL__
88+
89+/*
90+ * Read-write spinlocks, allowing multiple readers
91+ * but only one writer.
92+ *
93+ * NOTE! it is quite common to have readers in interrupts
94+ * but no interrupt writers. For those circumstances we
95+ * can "mix" irq-safe locks - any writer needs to get a
96+ * irq-safe write-lock, but readers can get non-irqsafe
97+ * read-locks.
98+ */
99+
100+/**
101+ * read_can_lock - would read_trylock() succeed?
102+ * @lock: the rwlock in question.
103+ */
104+#define arch_read_can_lock(x) ((int)(x)->lock > 0)
105+
106+/**
107+ * write_can_lock - would write_trylock() succeed?
108+ * @lock: the rwlock in question.
109+ */
110+#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
111+
112+/*
113+ * On mn10300, we implement read-write locks as a 32-bit counter
114+ * with the high bit (sign) being the "contended" bit.
115+ */
116+static inline void arch_read_lock(arch_rwlock_t *rw)
117+{
118+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
119+ __build_read_lock(rw, "__read_lock_failed");
120+#else
121+ {
122+ atomic_t *count = (atomic_t *)rw;
123+ while (atomic_dec_return(count) < 0)
124+ atomic_inc(count);
125+ }
126+#endif
127+}
128+
129+static inline void arch_write_lock(arch_rwlock_t *rw)
130+{
131+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
132+ __build_write_lock(rw, "__write_lock_failed");
133+#else
134+ {
135+ atomic_t *count = (atomic_t *)rw;
136+ while (!atomic_sub_and_test(RW_LOCK_BIAS, count))
137+ atomic_add(RW_LOCK_BIAS, count);
138+ }
139+#endif
140+}
141+
142+static inline void arch_read_unlock(arch_rwlock_t *rw)
143+{
144+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
145+ __build_read_unlock(rw);
146+#else
147+ {
148+ atomic_t *count = (atomic_t *)rw;
149+ atomic_inc(count);
150+ }
151+#endif
152+}
153+
154+static inline void arch_write_unlock(arch_rwlock_t *rw)
155+{
156+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
157+ __build_write_unlock(rw);
158+#else
159+ {
160+ atomic_t *count = (atomic_t *)rw;
161+ atomic_add(RW_LOCK_BIAS, count);
162+ }
163+#endif
164+}
165+
166+static inline int arch_read_trylock(arch_rwlock_t *lock)
167+{
168+ atomic_t *count = (atomic_t *)lock;
169+ atomic_dec(count);
170+ if (atomic_read(count) >= 0)
171+ return 1;
172+ atomic_inc(count);
173+ return 0;
174+}
175+
176+static inline int arch_write_trylock(arch_rwlock_t *lock)
177+{
178+ atomic_t *count = (atomic_t *)lock;
179+ if (atomic_sub_and_test(RW_LOCK_BIAS, count))
180+ return 1;
181+ atomic_add(RW_LOCK_BIAS, count);
182+ return 0;
183+}
184+
185+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
186+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
187+
188+#define _raw_spin_relax(lock) cpu_relax()
189+#define _raw_read_relax(lock) cpu_relax()
190+#define _raw_write_relax(lock) cpu_relax()
191+
192+#endif /* __KERNEL__ */
16193 #endif /* _ASM_SPINLOCK_H */
arch/mn10300/include/asm/spinlock_types.h+20−0
@@ -0,0 +1,20 @@
1+#ifndef _ASM_SPINLOCK_TYPES_H
2+#define _ASM_SPINLOCK_TYPES_H
3+
4+#ifndef __LINUX_SPINLOCK_TYPES_H
5+# error "please don't include this file directly"
6+#endif
7+
8+typedef struct arch_spinlock {
9+ unsigned int slock;
10+} arch_spinlock_t;
11+
12+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
13+
14+typedef struct {
15+ unsigned int lock;
16+} arch_rwlock_t;
17+
18+#define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
19+
20+#endif /* _ASM_SPINLOCK_TYPES_H */
arch/mn10300/include/asm/system.h+22−51
@@ -12,12 +12,29 @@ · 11 unmodified lines
1212 #define _ASM_SYSTEM_H
1313
1414 #include <asm/cpu-regs.h>
15+#include <asm/intctl-regs.h>
1516
1617 #ifdef __KERNEL__
1718 #ifndef __ASSEMBLY__
1819
1920 #include <linux/kernel.h>
2021 #include <linux/irqflags.h>
22+#include <asm/atomic.h>
23+
24+#if !defined(CONFIG_LAZY_SAVE_FPU)
25+struct fpu_state_struct;
26+extern 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
2138
2239 struct task_struct;
2340 struct thread_struct;
@@ -30,6 +47,7 @@ struct task_struct *__switch_to(struct thread_struct *prev, · 6 unmodified lines
3047 /* context switching is now performed out-of-line in switch_to.S */
3148 #define switch_to(prev, next, last) \
3249 do { \
50+ switch_fpu(prev, next); \
3351 current->thread.wchan = (u_long) __builtin_return_address(0); \
3452 (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
3553 mb(); \
@@ -40,8 +58,6 @@ do { \ · 4 unmodified lines
4058
4159 #define nop() asm volatile ("nop")
4260
43−#endif /* !__ASSEMBLY__ */
44−
4561 /*
4662 * Force strict CPU ordering.
4763 * And yes, this is required on UP too when we're talking
@@ -68,64 +84,19 @@ do { \ · 20 unmodified lines
6884 #define smp_mb() mb()
6985 #define smp_rmb() rmb()
7086 #define smp_wmb() wmb()
71−#else
87+#define set_mb(var, value) do { xchg(&var, value); } while (0)
88+#else /* CONFIG_SMP */
7289 #define smp_mb() barrier()
7390 #define smp_rmb() barrier()
7491 #define smp_wmb() barrier()
75−#endif
76−
7792 #define set_mb(var, value) do { var = value; mb(); } while (0)
93+#endif /* CONFIG_SMP */
94+
7895 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
7996
8097 #define read_barrier_depends() do {} while (0)
8198 #define smp_read_barrier_depends() do {} while (0)
8299
83−/*****************************************************************************/
84−/*
85− * MN10300 doesn't actually have an exchange instruction
86− */
87−#ifndef __ASSEMBLY__
88−
89−struct __xchg_dummy { unsigned long a[100]; };
90−#define __xg(x) ((struct __xchg_dummy *)(x))
91−
92−static inline
93−unsigned 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−
109−static 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−
128100 #endif /* !__ASSEMBLY__ */
129−
130101 #endif /* __KERNEL__ */
131102 #endif /* _ASM_SYSTEM_H */
arch/mn10300/include/asm/thread_info.h+14−4
@@ -16,10 +16,6 @@ · 15 unmodified lines
1616
1717 #include <asm/page.h>
1818
19−#ifndef __ASSEMBLY__
20−#include <asm/processor.h>
21−#endif
22−
2319 #define PREEMPT_ACTIVE 0x10000000
2420
2521 #ifdef CONFIG_4KSTACKS
@@ -38,10 +34,14 @@ · 12 unmodified lines
3834 * must also be changed
3935 */
4036 #ifndef __ASSEMBLY__
37+typedef struct {
38+ unsigned long seg;
39+} mm_segment_t;
4140
4241 struct thread_info {
4342 struct task_struct *task; /* main task structure */
4443 struct exec_domain *exec_domain; /* execution domain */
44+ struct pt_regs *frame; /* current exception frame */
4545 unsigned long flags; /* low level flags */
4646 __u32 cpu; /* current CPU */
4747 __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
@@ -55,6 +55,10 @@ struct thread_info { · 7 unmodified lines
5555 __u8 supervisor_stack[0];
5656 };
5757
58+#define thread_info_to_uregs(ti) \
59+ ((struct pt_regs *) \
60+ ((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs)))
61+
5862 #else /* !__ASSEMBLY__ */
5963
6064 #ifndef __ASM_OFFSETS_H__
@@ -102,6 +106,12 @@ struct thread_info *current_thread_info(void) · 41 unmodified lines
102106 return ti;
103107 }
104108
109+static inline __attribute__((const))
110+struct pt_regs *current_frame(void)
111+{
112+ return current_thread_info()->frame;
113+}
114+
105115 /* how to get the current stack pointer from C */
106116 static inline unsigned long current_stack_pointer(void)
107117 {
arch/mn10300/include/asm/timer-regs.h+175−16
@@ -17,21 +17,27 @@ · 16 unmodified lines
1717
1818 #ifdef __KERNEL__
1919
20−/* timer prescalar control */
20+/*
21+ * Timer prescalar control
22+ */
2123 #define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */
2224 #define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */
2325 #define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */
2426
25−/* 8 bit timers */
27+/*
28+ * 8-bit timers
29+ */
2630 #define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */
2731 #define TM0MD_SRC 0x07 /* timer source */
2832 #define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */
2933 #define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
3034 #define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
31−#define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */
3235 #define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
3336 #define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
37+#if defined(CONFIG_AM33_2)
38+#define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */
3439 #define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */
40+#endif /* CONFIG_AM33_2 */
3541 #define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
3642 #define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */
3743
@@ -43,7 +49,9 @@ · 5 unmodified lines
4349 #define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */
4450 #define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
4551 #define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
52+#if defined(CONFIG_AM33_2)
4653 #define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */
54+#endif /* CONFIG_AM33_2 */
4755 #define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
4856 #define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */
4957
@@ -55,7 +63,9 @@ · 5 unmodified lines
5563 #define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */
5664 #define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
5765 #define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
66+#if defined(CONFIG_AM33_2)
5867 #define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */
68+#endif /* CONFIG_AM33_2 */
5969 #define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
6070 #define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */
6171
@@ -64,11 +74,13 @@ · 2 unmodified lines
6474 #define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */
6575 #define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
6676 #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 */
6878 #define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
6979 #define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
7080 #define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
81+#if defined(CONFIG_AM33_2)
7182 #define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */
83+#endif /* CONFIG_AM33_2 */
7284 #define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
7385 #define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */
7486
@@ -96,7 +108,9 @@ · 21 unmodified lines
96108 #define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */
97109 #define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */
98110
99−/* 16-bit timers 4,5 & 7-11 */
111+/*
112+ * 16-bit timers 4,5 & 7-15
113+ */
100114 #define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */
101115 #define TM4MD_SRC 0x07 /* timer source */
102116 #define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */
@@ -105,7 +119,9 @@ · 2 unmodified lines
105119 #define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
106120 #define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
107121 #define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
122+#if defined(CONFIG_AM33_2)
108123 #define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */
124+#endif /* CONFIG_AM33_2 */
109125 #define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
110126 #define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */
111127
@@ -118,7 +134,11 @@ · 6 unmodified lines
118134 #define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
119135 #define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
120136 #define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
137+#if defined(CONFIG_AM33_2)
121138 #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 */
122142 #define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
123143 #define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */
124144
@@ -130,7 +150,9 @@ · 5 unmodified lines
130150 #define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
131151 #define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
132152 #define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
153+#if defined(CONFIG_AM33_2)
133154 #define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */
155+#endif /* CONFIG_AM33_2 */
134156 #define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
135157 #define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */
136158
@@ -143,7 +165,11 @@ · 6 unmodified lines
143165 #define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
144166 #define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
145167 #define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
168+#if defined(CONFIG_AM33_2)
146169 #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 */
147173 #define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
148174 #define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */
149175
@@ -156,7 +182,11 @@ · 6 unmodified lines
156182 #define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
157183 #define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
158184 #define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
185+#if defined(CONFIG_AM33_2)
159186 #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 */
160190 #define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
161191 #define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */
162192
@@ -169,7 +199,11 @@ · 6 unmodified lines
169199 #define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
170200 #define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
171201 #define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
202+#if defined(CONFIG_AM33_2)
172203 #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 */
173207 #define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
174208 #define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */
175209
@@ -178,32 +212,101 @@ · 2 unmodified lines
178212 #define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */
179213 #define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
180214 #define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
181−#define TM11MD_SRC_TM7CASCADE 0x03 /* - cascade with timer 7 */
182215 #define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
183216 #define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
184217 #define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
218+#if defined(CONFIG_AM33_2)
185219 #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 */
186223 #define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
187224 #define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */
188225
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+
189279 #define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */
190280 #define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */
281+#define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */
191282 #define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */
192283 #define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */
193284 #define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */
285+#define TM89BR __SYSREG(0xd4003098, u32) /* timer 8:9 base register */
194286 #define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */
195287 #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 */
197294
198295 #define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */
199296 #define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */
200297 #define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */
201−
202298 #define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */
203299 #define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */
204300 #define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */
301+#define TM89BC __SYSREG(0xd40030a8, u32) /* timer 8:9 binary counter */
205302 #define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */
206303 #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 */
207310
208311 #define TM4IRQ 6 /* timer 4 IRQ */
209312 #define TM5IRQ 7 /* timer 5 IRQ */
@@ -212,6 +315,12 @@ · 2 unmodified lines
212315 #define TM9IRQ 13 /* timer 9 IRQ */
213316 #define TM10IRQ 14 /* timer 10 IRQ */
214317 #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 */
215324
216325 #define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */
217326 #define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */
@@ -220,8 +329,16 @@ · 2 unmodified lines
220329 #define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */
221330 #define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */
222331 #define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */
223−
224−/* 16-bit timer 6 */
332+#if defined(CONFIG_AM34_2)
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+ */
225342 #define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */
226343 #define TM6MD_SRC 0x0007 /* timer source */
227344 #define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */
@@ -229,10 +346,14 @@ · 1 unmodified line
229346 #define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */
230347 #define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */
231348 #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) */
233352 #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 */
235354 #define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */
355+#define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */
356+#if defined(CONFIG_AM33_2)
236357 #define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */
237358 #define TM6MD_PWM 0x3800 /* PWM output mode */
238359 #define TM6MD_PWM_DIS 0x0000 /* - disabled */
@@ -240,10 +361,15 @@ · 1 unmodified line
240361 #define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */
241362 #define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */
242363 #define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */
364+#endif /* CONFIG_AM33_2 */
365+
243366 #define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */
244367 #define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */
245368
246369 #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)
247373 #define TM6MDA_OUT 0x07 /* output select */
248374 #define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */
249375 #define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */
@@ -251,30 +377,35 @@ · 1 unmodified line
251377 #define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */
252378 #define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */
253379 #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 */
256380 #define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */
257381 #define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */
258382 #define TM6MDA_EDGE 0x20 /* compare A edge select */
259383 #define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */
260384 #define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */
261385 #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 */
262389
263390 #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)
264394 #define TM6MDB_OUT 0x07 /* output select */
265395 #define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */
266396 #define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */
267397 #define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */
268398 #define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */
269399 #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 */
272400 #define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */
273401 #define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */
274402 #define TM6MDB_EDGE 0x20 /* compare B edge select */
275403 #define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */
276404 #define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */
277405 #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 */
278409
279410 #define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */
280411 #define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */
@@ -288,6 +419,34 @@ · 7 unmodified lines
288419 #define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */
289420 #define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */
290421
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+
291450 #endif /* __KERNEL__ */
292451
293452 #endif /* _ASM_TIMER_REGS_H */
arch/mn10300/include/asm/timex.h+16−4
@@ -16,18 +16,30 @@ · 15 unmodified lines
1616
1717 #define TICK_SIZE (tick_nsec / 1000)
1818
19−#define CLOCK_TICK_RATE 1193180 /* Underlying HZ - this should probably be set
20− * to something appropriate, but what? */
21−
22−extern cycles_t cacheflush_time;
19+#define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */
2320
2421 #ifdef __KERNEL__
2522
23+extern cycles_t cacheflush_time;
24+
2625 static inline cycles_t get_cycles(void)
2726 {
2827 return read_timestamp_counter();
2928 }
3029
30+extern int init_clockevents(void);
31+extern int init_clocksource(void);
32+
33+static 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+
3143 #endif /* __KERNEL__ */
3244
3345 #endif /* _ASM_TIMEX_H */
arch/mn10300/include/asm/tlbflush.h+124−50
@@ -11,24 +11,78 @@ · 10 unmodified lines
1111 #ifndef _ASM_TLBFLUSH_H
1212 #define _ASM_TLBFLUSH_H
1313
14+#include <linux/mm.h>
1415 #include <asm/processor.h>
1516
16−#define __flush_tlb() \
17−do { \
18− int w; \
19− __asm__ __volatile__ \
20− (" mov %1,%0 \n" \
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)
17+struct tlb_state {
18+ struct mm_struct *active_mm;
19+ int state;
20+};
21+DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
2822
29−#define __flush_tlb_all() __flush_tlb()
30−#define __flush_tlb_one(addr) __flush_tlb()
23+/**
24+ * local_flush_tlb - Flush the current MM's entries from the local CPU's TLBs
25+ */
26+static 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+ */
41+static inline void local_flush_tlb_all(void)
42+{
43+ local_flush_tlb();
44+}
3145
46+/**
47+ * local_flush_tlb_one - Flush one entry from the local CPU's TLBs
48+ */
49+static 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+ */
59+static inline
60+void 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+}
3286
3387 /*
3488 * TLB flushing:
@@ -40,41 +94,61 @@ do { \ · 5 unmodified lines
4094 * - flush_tlb_range(mm, start, end) flushes a range of pages
4195 * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
4296 */
43−#define flush_tlb_all() \
44−do { \
45− preempt_disable(); \
46− __flush_tlb_all(); \
47− preempt_enable(); \
48−} while (0)
49−
50−#define flush_tlb_mm(mm) \
51−do { \
52− preempt_disable(); \
53− __flush_tlb_all(); \
54− preempt_enable(); \
55−} while (0)
56−
57−#define flush_tlb_range(vma, start, end) \
58−do { \
59− unsigned long __s __attribute__((unused)) = (start); \
60− unsigned long __e __attribute__((unused)) = (end); \
61− preempt_disable(); \
62− __flush_tlb_all(); \
63− preempt_enable(); \
64−} while (0)
65−
66−
67−#define __flush_tlb_global() flush_tlb_all()
68−#define flush_tlb() flush_tlb_all()
69−#define flush_tlb_kernel_range(start, end) \
70−do { \
71− unsigned long __s __attribute__((unused)) = (start); \
72− unsigned long __e __attribute__((unused)) = (end); \
73− flush_tlb_all(); \
74−} while (0)
75−
76−extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
77−
78−#define flush_tlb_pgtables(mm, start, end) do {} while (0)
97+#ifdef CONFIG_SMP
98+
99+#include <asm/smp.h>
100+
101+extern void flush_tlb_all(void);
102+extern void flush_tlb_current_task(void);
103+extern void flush_tlb_mm(struct mm_struct *);
104+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
105+
106+#define flush_tlb() flush_tlb_current_task()
107+
108+static inline void flush_tlb_range(struct vm_area_struct *vma,
109+ unsigned long start, unsigned long end)
110+{
111+ flush_tlb_mm(vma->vm_mm);
112+}
113+
114+#else /* CONFIG_SMP */
115+
116+static inline void flush_tlb_all(void)
117+{
118+ preempt_disable();
119+ local_flush_tlb_all();
120+ preempt_enable();
121+}
122+
123+static inline void flush_tlb_mm(struct mm_struct *mm)
124+{
125+ preempt_disable();
126+ local_flush_tlb_all();
127+ preempt_enable();
128+}
129+
130+static inline void flush_tlb_range(struct vm_area_struct *vma,
131+ unsigned long start, unsigned long end)
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+
143+static inline void flush_tlb_kernel_range(unsigned long start,
144+ unsigned long end)
145+{
146+ flush_tlb_all();
147+}
148+
149+static inline void flush_tlb_pgtables(struct mm_struct *mm,
150+ unsigned long start, unsigned long end)
151+{
152+}
79153
80154 #endif /* _ASM_TLBFLUSH_H */
arch/mn10300/include/asm/uaccess.h+2−4
@@ -14,9 +14,8 @@ · 13 unmodified lines
1414 /*
1515 * User space memory access functions
1616 */
17−#include <linux/sched.h>
17+#include <linux/thread_info.h>
1818 #include <asm/page.h>
19−#include <asm/pgtable.h>
2019 #include <asm/errno.h>
2120
2221 #define VERIFY_READ 0
@@ -29,7 +28,6 @@ · 6 unmodified lines
2928 *
3029 * For historical reasons, these macros are grossly misnamed.
3130 */
32−
3331 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
3432
3533 #define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF)
@@ -377,7 +375,7 @@ unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, · 341 unmodified lines
377375
378376
379377 #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"
381379 /* Optimize just a little bit when we know the size of the move. */
382380 #define __constant_copy_user(to, from, size) \
383381 do { \
arch/mn10300/kernel/Makefile+10−5
@@ -3,13 +3,16 @@ · 2 unmodified lines
33 #
44 extra-y := head.o init_task.o vmlinux.lds
55
6−obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
6+fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
7+fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
8+
9+obj-y := process.o signal.o entry.o traps.o irq.o \
710 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)
912
10−obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
13+obj-$(CONFIG_SMP) += smp.o smp-low.o
1114
12−obj-$(CONFIG_FPU) += fpu-low.o
15+obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
1316
1417 obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
1518 mn10300-debug.o
@@ -17,7 +20,7 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o · 1 unmodified line
1720 obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
1821 obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
1922
20−ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
23+ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
2124 obj-$(CONFIG_GDBSTUB) += gdb-cache.o
2225 endif
2326
@@ -25,3 +28,5 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o · 1 unmodified line
2528 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
2629 obj-$(CONFIG_MODULES) += module.o
2730 obj-$(CONFIG_KPROBES) += kprobes.o
31+obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o
32+obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o
arch/mn10300/kernel/asm-offsets.c+10−1
@@ -23,6 +23,7 @@ void foo(void) · 22 unmodified lines
2323
2424 OFFSET(TI_task, thread_info, task);
2525 OFFSET(TI_exec_domain, thread_info, exec_domain);
26+ OFFSET(TI_frame, thread_info, frame);
2627 OFFSET(TI_flags, thread_info, flags);
2728 OFFSET(TI_cpu, thread_info, cpu);
2829 OFFSET(TI_preempt_count, thread_info, preempt_count);
@@ -66,7 +67,15 @@ void foo(void) · 37 unmodified lines
6667 OFFSET(THREAD_SP, thread_struct, sp);
6768 OFFSET(THREAD_A3, thread_struct, a3);
6869 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);
7079 BLANK();
7180
7281 DEFINE(CLONE_VM_asm, CLONE_VM);
arch/mn10300/kernel/cevt-mn10300.c+131−0
@@ -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+
29+static 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+
44+static void set_clock_mode(enum clock_event_mode mode,
45+ struct clock_event_device *evt)
46+{
47+ /* Nothing to do ... */
48+}
49+
50+static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device);
51+static DEFINE_PER_CPU(struct irqaction, timer_irq);
52+
53+static 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+
69+static void event_handler(struct clock_event_device *dev)
70+{
71+}
72+
73+int __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+}
arch/mn10300/kernel/csrc-mn10300.c+35−0
@@ -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+
16+static cycle_t mn10300_read(struct clocksource *cs)
17+{
18+ return read_timestamp_counter();
19+}
20+
21+static 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+
29+int __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+}
arch/mn10300/kernel/entry.S+98−48
@@ -28,25 +28,17 @@ · 27 unmodified lines
2828 #include <asm/asm-offsets.h>
2929 #include <asm/frame.inc>
3030
31+#if defined(CONFIG_SMP) && defined(CONFIG_GDBSTUB)
32+#include <asm/gdb-stub.h>
33+#endif /* CONFIG_SMP && CONFIG_GDBSTUB */
34+
3135 #ifdef CONFIG_PREEMPT
32−#define preempt_stop __cli
36+#define preempt_stop LOCAL_IRQ_DISABLE
3337 #else
3438 #define preempt_stop
3539 #define resume_kernel restore_all
3640 #endif
3741
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−
5042 .am33_2
5143
5244 ###############################################################################
@@ -88,7 +80,7 @@ syscall_call: · 35 unmodified lines
8880 syscall_exit:
8981 # make sure we don't miss an interrupt setting need_resched or
9082 # sigpending between sampling and the rti
91− __cli
83+ LOCAL_IRQ_DISABLE
9284 mov (TI_flags,a2),d2
9385 btst _TIF_ALLWORK_MASK,d2
9486 bne syscall_exit_work
@@ -105,7 +97,7 @@ restore_all: · 10 unmodified lines
10597 syscall_exit_work:
10698 btst _TIF_SYSCALL_TRACE,d2
10799 beq work_pending
108− __sti # could let syscall_trace_exit() call
100+ LOCAL_IRQ_ENABLE # could let syscall_trace_exit() call
109101 # schedule() instead
110102 mov fp,d0
111103 call syscall_trace_exit[],0 # do_syscall_trace(regs)
@@ -121,7 +113,7 @@ work_resched: · 9 unmodified lines
121113
122114 # make sure we don't miss an interrupt setting need_resched or
123115 # sigpending between sampling and the rti
124− __cli
116+ LOCAL_IRQ_DISABLE
125117
126118 # is there any work to be done other than syscall tracing?
127119 mov (TI_flags,a2),d2
@@ -168,7 +160,7 @@ ret_from_intr: · 40 unmodified lines
168160 ENTRY(resume_userspace)
169161 # make sure we don't miss an interrupt setting need_resched or
170162 # sigpending between sampling and the rti
171− __cli
163+ LOCAL_IRQ_DISABLE
172164
173165 # is there any work to be done on int/exception return?
174166 mov (TI_flags,a2),d2
@@ -178,7 +170,7 @@ ENTRY(resume_userspace) · 3 unmodified lines
178170
179171 #ifdef CONFIG_PREEMPT
180172 ENTRY(resume_kernel)
181− __cli
173+ LOCAL_IRQ_DISABLE
182174 mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
183175 cmp 0,d0
184176 bne restore_all
@@ -214,31 +206,6 @@ ENTRY(irq_handler) · 29 unmodified lines
214206
215207 jmp ret_from_intr
216208
217−###############################################################################
218−#
219−# Monitor Signal handler entry point
220−#
221−###############################################################################
222−ENTRY(monitor_signal)
223− movbu (0xae000001),d1
224− cmp 1,d1
225− beq monsignal
226− ret [],0
227−
228−monsignal:
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
240−here: jmp 0x8e000008-here+0x8e000008
241−
242209 ###############################################################################
243210 #
244211 # Double Fault handler entry point
@@ -276,6 +243,10 @@ double_fault_loop: · 31 unmodified lines
276243 ENTRY(raw_bus_error)
277244 add -4,sp
278245 mov d0,(sp)
246+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
247+ mov (MMUCTR),d0
248+ mov d0,(MMUCTR)
249+#endif
279250 mov (BCBERR),d0 # what
280251 btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error
281252 beq __common_exception_aux # it wasn't
@@ -302,11 +273,88 @@ ENTRY(nmi_handler) · 20 unmodified lines
302273 add -4,sp
303274 mov d0,(sp)
304275 mov (TBR),d0
276+
277+#ifdef CONFIG_SMP
278+ add -4,sp
279+ mov d0,(sp) # save d0(TBR)
280+ movhu (NMIAGR),d0
281+ and NMIAGR_GN,d0
282+ lsr 0x2,d0
283+ cmp CALL_FUNCTION_NMI_IPI,d0
284+ bne 5f # if not call function, jump
285+
286+ # function call nmi ipi
287+ add 4,sp # no need to store TBR
288+ mov GxICR_DETECT,d0 # clear NMI request
289+ movbu d0,(GxICR(CALL_FUNCTION_NMI_IPI))
290+ movhu (GxICR(CALL_FUNCTION_NMI_IPI)),d0
291+ and ~EPSW_NMID,epsw # enable NMI
292+
293+ mov (sp),d0 # restore d0
294+ SAVE_ALL
295+ call smp_nmi_call_function_interrupt[],0
296+ RESTORE_ALL
297+
298+5:
299+#ifdef CONFIG_GDBSTUB
300+ cmp GDB_NMI_IPI,d0
301+ bne 3f # if not gdb nmi ipi, jump
302+
303+ # gdb nmi ipi
304+ add 4,sp # no need to store TBR
305+ mov GxICR_DETECT,d0 # clear NMI
306+ movbu d0,(GxICR(GDB_NMI_IPI))
307+ movhu (GxICR(GDB_NMI_IPI)),d0
308+ and ~EPSW_NMID,epsw # enable NMI
309+#ifdef CONFIG_MN10300_CACHE_ENABLED
310+ mov (gdbstub_nmi_opr_type),d0
311+ cmp GDBSTUB_NMI_CACHE_PURGE,d0
312+ bne 4f # if not gdb cache purge, jump
313+
314+ # gdb cache purge nmi ipi
315+ add -20,sp
316+ mov d1,(4,sp)
317+ mov a0,(8,sp)
318+ mov a1,(12,sp)
319+ mov mdr,d0
320+ mov d0,(16,sp)
321+ call gdbstub_local_purge_cache[],0
322+ mov 0x1,d0
323+ mov (CPUID),d1
324+ asl d1,d0
325+ mov gdbstub_nmi_cpumask,a0
326+ bclr d0,(a0)
327+ mov (4,sp),d1
328+ mov (8,sp),a0
329+ mov (12,sp),a1
330+ mov (16,sp),d0
331+ mov d0,mdr
332+ add 20,sp
333+ mov (sp),d0
334+ add 4,sp
335+ rti
336+4:
337+#endif /* CONFIG_MN10300_CACHE_ENABLED */
338+ # gdb wait nmi ipi
339+ mov (sp),d0
340+ SAVE_ALL
341+ call gdbstub_nmi_wait[],0
342+ RESTORE_ALL
343+3:
344+#endif /* CONFIG_GDBSTUB */
345+ mov (sp),d0 # restore TBR to d0
346+ add 4,sp
347+#endif /* CONFIG_SMP */
348+
305349 bra __common_exception_nonmi
306350
307351 ENTRY(__common_exception)
308352 add -4,sp
309353 mov d0,(sp)
354+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
355+ mov (MMUCTR),d0
356+ mov d0,(MMUCTR)
357+#endif
310358
311359 __common_exception_aux:
312360 mov (TBR),d0
@@ -331,15 +379,21 @@ __common_exception_nonmi: · 18 unmodified lines
331379 mov d0,(REG_ORIG_D0,fp)
332380
333381 #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 */
334387 btst 0x01,(gdbstub_busy)
335388 beq 2f
389+#endif /* CONFIG_SMP */
336390 and ~EPSW_IE,epsw
337391 mov fp,d0
338392 mov a2,d1
339393 call gdbstub_exception[],0 # gdbstub itself caused an exception
340394 bra restore_all
341395 2:
342−#endif
396+#endif /* CONFIG_GDBSTUB */
343397
344398 mov fp,d0 # arg 0: stacked register file
345399 mov a2,d1 # arg 1: exception number
@@ -374,11 +428,7 @@ ENTRY(set_excp_vector) · 28 unmodified lines
374428 add exception_table,d0
375429 mov d1,(d0)
376430 mov 4,d1
377−#if defined(CONFIG_MN10300_CACHE_WBACK)
378− jmp mn10300_dcache_flush_inv_range2
379−#else
380431 ret [],0
381−#endif
382432
383433 ###############################################################################
384434 #
arch/mn10300/kernel/fpu-low.S+163−102
@@ -8,25 +8,14 @@ · 7 unmodified lines
88 * as published by the Free Software Foundation; either version
99 * 2 of the Licence, or (at your option) any later version.
1010 */
11+#include <linux/linkage.h>
1112 #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>
1217
13−###############################################################################
14−#
15−# void fpu_init_state(void)
16−# - initialise the FPU
17−#
18−###############################################################################
19− .globl fpu_init_state
20− .type fpu_init_state,@function
21−fpu_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
18+.macro FPU_INIT_STATE_ALL
3019 fmov 0,fs0
3120 fmov fs0,fs1
3221 fmov fs0,fs2
@@ -60,7 +49,100 @@ fpu_init_state: · 27 unmodified lines
6049 fmov fs0,fs30
6150 fmov fs0,fs31
6251 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
63127
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
136+fpu_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
64146 #ifdef CONFIG_MN10300_PROC_MN103E010
65147 nop
66148 nop
@@ -89,40 +171,7 @@ fpu_save: · 22 unmodified lines
89171 nop
90172 #endif
91173 mov d0,a0
92− fmov fs0,(a0+)
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)
174+ FPU_SAVE_ALL a0,d0
126175 #ifdef CONFIG_MN10300_PROC_MN103E010
127176 nop
128177 nop
@@ -135,63 +184,75 @@ fpu_save: · 6 unmodified lines
135184
136185 ###############################################################################
137186 #
138−# void fpu_restore(struct fpu_state_struct *)
139−# - restore the fpu state
140−# - note that an FPU Operational exception might occur during this process
187+# void fpu_disabled(void)
188+# - handle an exception due to the FPU being disabled
189+# when CONFIG_FPU is enabled
141190 #
142191 ###############################################################################
143− .globl fpu_restore
144− .type fpu_restore,@function
145−fpu_restore:
146− mov epsw,d1
147− or EPSW_FE,epsw /* enable the FPU so we can access it */
148−
149−#ifdef CONFIG_MN10300_PROC_MN103E010
192+ .type fpu_disabled,@function
193+ .globl fpu_disabled
194+fpu_disabled:
195+ or EPSW_nAR|EPSW_FE,epsw
150196 nop
151197 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
189198 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+
226+fpu_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+
236+fpu_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+
242+fpu_used_in_kernel:
243+ and ~(EPSW_nAR|EPSW_FE),epsw
190244 nop
191245 nop
192−#endif
193246
194− mov d1,epsw
195− ret [],0
247+ add -4,sp
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
196257
197− .size fpu_restore,.-fpu_restore
258+ .size fpu_disabled,.-fpu_disabled
arch/mn10300/kernel/fpu-nofpu-low.S+39−0
@@ -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
27+fpu_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
arch/mn10300/kernel/fpu-nofpu.c+30−0
@@ -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+ */
18+asmlinkage
19+void 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+ */
27+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
28+{
29+ return 0; /* not valid */
30+}
arch/mn10300/kernel/fpu.c+56−85
@@ -12,56 +12,19 @@ · 11 unmodified lines
1212 #include <asm/fpu.h>
1313 #include <asm/elf.h>
1414 #include <asm/exceptions.h>
15+#include <asm/system.h>
1516
17+#ifdef CONFIG_LAZY_SAVE_FPU
1618 struct task_struct *fpu_state_owner;
19+#endif
1720
1821 /*
19− * handle an exception due to the FPU being disabled
22+ * error functions in FPU disabled exception
2023 */
21−asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
24+asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs)
2225 {
23− struct task_struct *tsk = current;
24−
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 */
26+ die_if_no_fixup("An FPU Disabled exception happened in kernel space\n",
27+ regs, EXCEP_FPU_DISABLED);
6528 }
6629
6730 /*
@@ -71,15 +34,16 @@ asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code) · 3 unmodified lines
7134 */
7235 asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
7336 {
74− struct task_struct *tsk = fpu_state_owner;
37+ struct task_struct *tsk = current;
7538 siginfo_t info;
39+ u32 fpcr;
7640
7741 if (!user_mode(regs))
7842 die_if_no_fixup("An FPU Operation exception happened in"
7943 " kernel space\n",
8044 regs, code);
8145
82− if (!tsk)
46+ if (!is_using_fpu(tsk))
8347 die_if_no_fixup("An FPU Operation exception happened,"
8448 " but the FPU is not in use",
8549 regs, code);
@@ -89,48 +53,45 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) · 3 unmodified lines
8953 info.si_addr = (void *) tsk->thread.uregs->pc;
9054 info.si_code = FPE_FLTINV;
9155
92−#ifdef CONFIG_FPU
93− {
94− u32 fpcr;
56+ unlazy_fpu(tsk);
9557
96− /* get FPCR (we need to enable the FPU whilst we do this) */
97− asm volatile(" or %1,epsw \n"
98−#ifdef CONFIG_MN10300_PROC_MN103E010
99− " nop \n"
100− " nop \n"
101− " nop \n"
102−#endif
103− " fmov fpcr,%0 \n"
104−#ifdef CONFIG_MN10300_PROC_MN103E010
105− " nop \n"
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
58+ fpcr = tsk->thread.fpu_state.fpcr;
59+
60+ if (fpcr & FPCR_EC_Z)
61+ info.si_code = FPE_FLTDIV;
62+ else if (fpcr & FPCR_EC_O)
63+ info.si_code = FPE_FLTOVF;
64+ else if (fpcr & FPCR_EC_U)
65+ info.si_code = FPE_FLTUND;
66+ else if (fpcr & FPCR_EC_I)
67+ info.si_code = FPE_FLTRES;
12468
12569 force_sig_info(SIGFPE, &info, tsk);
12670 }
12771
72+/*
73+ * handle an FPU invalid_op exception
74+ * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
75+ */
76+asmlinkage 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+
12890 /*
12991 * save the FPU state to a signal context
13092 */
13193 int fpu_setup_sigcontext(struct fpucontext *fpucontext)
13294 {
133−#ifdef CONFIG_FPU
13495 struct task_struct *tsk = current;
13596
13697 if (!is_using_fpu(tsk))
@@ -142,11 +103,19 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) · 5 unmodified lines
142103 */
143104 preempt_disable();
144105
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 */
145113 if (fpu_state_owner == tsk) {
146114 fpu_save(&tsk->thread.fpu_state);
147115 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
148116 fpu_state_owner = NULL;
149117 }
118+#endif /* !CONFIG_LAZY_SAVE_FPU */
150119
151120 preempt_enable();
152121
@@ -161,9 +130,6 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) · 8 unmodified lines
161130 return -1;
162131
163132 return 1;
164−#else
165− return 0;
166−#endif
167133 }
168134
169135 /*
@@ -171,17 +137,23 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) · 1 unmodified line
171137 */
172138 void fpu_kill_state(struct task_struct *tsk)
173139 {
174−#ifdef CONFIG_FPU
175140 /* disown anything left in the FPU */
176141 preempt_disable();
177142
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 */
178149 if (fpu_state_owner == tsk) {
179150 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
180151 fpu_state_owner = NULL;
181152 }
153+#endif /* !CONFIG_LAZY_SAVE_FPU */
182154
183155 preempt_enable();
184−#endif
156+
185157 /* we no longer have a valid current FPU state */
186158 clear_using_fpu(tsk);
187159 }
@@ -195,8 +167,7 @@ int fpu_restore_sigcontext(struct fpucontext *fpucontext) · 7 unmodified lines
195167 int ret;
196168
197169 /* load up the old FPU state */
198− ret = copy_from_user(&tsk->thread.fpu_state,
199− fpucontext,
170+ ret = copy_from_user(&tsk->thread.fpu_state, fpucontext,
200171 min(sizeof(struct fpu_state_struct),
201172 sizeof(struct fpucontext)));
202173 if (!ret)
arch/mn10300/kernel/gdb-io-serial-low.S+3−2
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <asm/thread_info.h>
1919 #include <asm/frame.inc>
2020 #include <asm/intctl-regs.h>
21+#include <asm/irqflags.h>
2122 #include <unit/serial.h>
2223
2324 .text
@@ -69,7 +70,7 @@ gdbstub_io_rx_overflow: · 45 unmodified lines
6970 bra gdbstub_io_rx_done
7071
7172 gdbstub_io_rx_enter:
72− or EPSW_IE|EPSW_IM_1,epsw
73+ LOCAL_CHANGE_INTR_MASK_LEVEL(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL+1))
7374 add -4,sp
7475 SAVE_ALL
7576
@@ -80,7 +81,7 @@ gdbstub_io_rx_enter: · 4 unmodified lines
8081 mov fp,d0
8182 call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep)
8283
83− and ~EPSW_IE,epsw
84+ LOCAL_CLI
8485 bclr 0x01,(gdbstub_busy)
8586
8687 .globl gdbstub_return
arch/mn10300/kernel/gdb-io-serial.c+27−10
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include <asm/exceptions.h>
2424 #include <asm/serial-regs.h>
2525 #include <unit/serial.h>
26+#include <asm/smp.h>
2627
2728 /*
2829 * initialise the GDB stub
@@ -45,22 +46,34 @@ void gdbstub_io_init(void) · 16 unmodified lines
4546 XIRQxICR(GDBPORT_SERIAL_IRQ) = 0;
4647 tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
4748
49+#if CONFIG_GDBSTUB_IRQ_LEVEL == 0
4850 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);
5067
5168 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);
5371 tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
5472
5573 GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
5674
5775 /* permit level 0 IRQs to take place */
58− asm volatile(
59− " and %0,epsw \n"
60− " or %1,epsw \n"
61− :
62− : "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1)
63− );
76+ local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
6477 }
6578
6679 /*
@@ -87,6 +100,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) · 20 unmodified lines
87100 {
88101 unsigned ix;
89102 u8 ch, st;
103+#if defined(CONFIG_MN10300_WD_TIMER)
104+ int cpu;
105+#endif
90106
91107 *_ch = 0xff;
92108
@@ -104,8 +120,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) · 11 unmodified lines
104120 if (nonblock)
105121 return -EAGAIN;
106122 #ifdef CONFIG_MN10300_WD_TIMER
107− watchdog_alert_counter = 0;
108−#endif /* CONFIG_MN10300_WD_TIMER */
123+ for (cpu = 0; cpu < NR_CPUS; cpu++)
124+ watchdog_alert_counter[cpu] = 0;
125+#endif
109126 goto try_again;
110127 }
111128
arch/mn10300/kernel/gdb-io-ttysm.c+13−11
@@ -58,9 +58,12 @@ void __init gdbstub_io_init(void) · 57 unmodified lines
5858 gdbstub_io_set_baud(115200);
5959
6060 /* we want to get serial receive interrupts */
61− set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0);
62− set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0);
63− set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
61+ set_intr_level(gdbstub_port->rx_irq,
62+ NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
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);
6467
6568 *gdbstub_port->rx_icr |= GxICR_ENABLE;
6669 tmp = *gdbstub_port->rx_icr;
@@ -84,12 +87,7 @@ void __init gdbstub_io_init(void) · 17 unmodified lines
8487 tmp = *gdbstub_port->_control;
8588
8689 /* permit level 0 IRQs only */
87− asm volatile(
88− " and %0,epsw \n"
89− " or %1,epsw \n"
90− :
91− : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1)
92− );
90+ local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
9391 }
9492
9593 /*
@@ -184,6 +182,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) · 88 unmodified lines
184182 {
185183 unsigned ix;
186184 u8 ch, st;
185+#if defined(CONFIG_MN10300_WD_TIMER)
186+ int cpu;
187+#endif
187188
188189 *_ch = 0xff;
189190
@@ -201,8 +202,9 @@ try_again: · 11 unmodified lines
201202 if (nonblock)
202203 return -EAGAIN;
203204 #ifdef CONFIG_MN10300_WD_TIMER
204− watchdog_alert_counter = 0;
205−#endif /* CONFIG_MN10300_WD_TIMER */
205+ for (cpu = 0; cpu < NR_CPUS; cpu++)
206+ watchdog_alert_counter[cpu] = 0;
207+#endif
206208 goto try_again;
207209 }
208210
arch/mn10300/kernel/gdb-stub.c+6−11
@@ -440,15 +440,11 @@ static const unsigned char gdbstub_insn_sizes[256] = · 439 unmodified lines
440440
441441 static int __gdbstub_mark_bp(u8 *addr, int ix)
442442 {
443− if (addr < (u8 *) 0x70000000UL)
444− return 0;
445− /* 70000000-7fffffff: vmalloc area */
446− if (addr < (u8 *) 0x80000000UL)
443+ /* vmalloc area */
444+ if (((u8 *) VMALLOC_START <= addr) && (addr < (u8 *) VMALLOC_END))
447445 goto okay;
448− if (addr < (u8 *) 0x8c000000UL)
449− return 0;
450− /* 8c000000-93ffffff: SRAM, SDRAM */
451− if (addr < (u8 *) 0x94000000UL)
446+ /* SRAM, SDRAM */
447+ if (((u8 *) 0x80000000UL <= addr) && (addr < (u8 *) 0xa0000000UL))
452448 goto okay;
453449 return 0;
454450
@@ -1197,9 +1193,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) · 742 unmodified lines
11971193 mn10300_set_gdbleds(1);
11981194
11991195 asm volatile("mov mdr,%0" : "=d"(mdr));
1200− asm volatile("mov epsw,%0" : "=d"(epsw));
1201− asm volatile("mov %0,epsw"
1202− :: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1));
1196+ local_save_flags(epsw);
1197+ local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
12031198
12041199 gdbstub_store_fpu();
12051200
arch/mn10300/kernel/head.S+198−4
@@ -19,6 +19,12 @@ · 18 unmodified lines
1919 #include <asm/frame.inc>
2020 #include <asm/param.h>
2121 #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 */
2228
2329 __HEAD
2430
@@ -30,17 +36,51 @@ · 5 unmodified lines
3036 .globl _start
3137 .type _start,@function
3238 _start:
39+#ifdef CONFIG_SMP
40+ #
41+ # If this is a secondary CPU (AP), then deal with that elsewhere
42+ #
43+ mov (CPUID),d3
44+ and CPUID_MASK,d3
45+ bne startup_secondary
46+
47+ #
48+ # We're dealing with the primary CPU (BP) here, then.
49+ # Keep BP's D0,D1,D2 register for boot check.
50+ #
51+
52+ # Set up the Boot IPI for each secondary CPU
53+ mov 0x1,a0
54+loop_set_secondary_icr:
55+ mov a0,a1
56+ asl CROSS_ICR_CPU_SHIFT,a1
57+ add CROSS_GxICR(SMP_BOOT_IRQ,0),a1
58+ movhu (a1),d3
59+ or GxICR_ENABLE|GxICR_LEVEL_0,d3
60+ movhu d3,(a1)
61+ movhu (a1),d3 # flush
62+ inc a0
63+ cmp NR_CPUS,a0
64+ bne loop_set_secondary_icr
65+#endif /* CONFIG_SMP */
66+
3367 # save commandline pointer
3468 mov d0,a3
3569
3670 # preload the PGD pointer register
3771 mov swapper_pg_dir,d0
3872 mov d0,(PTBR)
73+ clr d0
74+ movbu d0,(PIDR)
3975
4076 # turn on the TLBs
4177 mov MMUCTR_IIV|MMUCTR_DIV,d0
4278 mov d0,(MMUCTR)
79+#ifdef CONFIG_AM34_2
80+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
81+#else
4382 mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
83+#endif
4484 mov d0,(MMUCTR)
4585
4686 # turn on AM33v2 exception handling mode and set the trap table base
@@ -51,6 +91,11 @@ _start: · 4 unmodified lines
5191 mov d0,(TBR)
5292
5393 # invalidate and enable both of the caches
94+#ifdef CONFIG_SMP
95+ mov ECHCTR,a0
96+ clr d0
97+ mov d0,(a0)
98+#endif
5499 mov CHCTR,a0
55100 clr d0
56101 movhu d0,(a0) # turn off first
@@ -61,18 +106,18 @@ _start: · 4 unmodified lines
61106 btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
62107 lne
63108
64−#ifndef CONFIG_MN10300_CACHE_DISABLED
109+#ifdef CONFIG_MN10300_CACHE_ENABLED
65110 #ifdef CONFIG_MN10300_CACHE_WBACK
66111 #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
67112 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
68113 #else
69114 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
70−#endif /* CACHE_DISABLED */
115+#endif /* NOWRALLOC */
71116 #else
72117 mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
73118 #endif /* WBACK */
74119 movhu d0,(a0) # enable
75−#endif /* NOWRALLOC */
120+#endif /* ENABLED */
76121
77122 # turn on RTS on the debug serial port if applicable
78123 #ifdef CONFIG_MN10300_UNIT_ASB2305
@@ -206,6 +251,44 @@ __no_parameters: · 127 unmodified lines
206251 call processor_init[],0
207252 call unit_init[],0
208253
254+#ifdef CONFIG_SMP
255+ # mark the primary CPU in cpu_boot_map
256+ mov cpu_boot_map,a0
257+ mov 0x1,d0
258+ mov d0,(a0)
259+
260+ # signal each secondary CPU to begin booting
261+ mov 0x1,d2 # CPU ID
262+
263+loop_request_boot_secondary:
264+ mov d2,a0
265+ # send SMP_BOOT_IPI to secondary CPU
266+ asl CROSS_ICR_CPU_SHIFT,a0
267+ add CROSS_GxICR(SMP_BOOT_IRQ,0),a0
268+ movhu (a0),d0
269+ or GxICR_REQUEST|GxICR_DETECT,d0
270+ movhu d0,(a0)
271+ movhu (a0),d0 # flush
272+
273+ # wait up to 100ms for AP's IPI to be received
274+ clr d3
275+wait_on_secondary_boot:
276+ mov DELAY_TIME_BOOT_IPI,d0
277+ call __delay[],0
278+ inc d3
279+ mov cpu_boot_map,a0
280+ mov (a0),d0
281+ lsr d2,d0
282+ btst 0x1,d0
283+ bne 1f
284+ cmp TIME_OUT_COUNT_BOOT_IPI,d3
285+ bne wait_on_secondary_boot
286+1:
287+ inc d2
288+ cmp NR_CPUS,d2
289+ bne loop_request_boot_secondary
290+#endif /* CONFIG_SMP */
291+
209292 #ifdef CONFIG_GDBSTUB
210293 call gdbstub_init[],0
211294
@@ -217,7 +300,118 @@ __gdbstub_pause: · 5 unmodified lines
217300 #endif
218301
219302 jmp start_kernel
220− .size _start, _start-.
303+ .size _start,.-_start
304+
305+###############################################################################
306+#
307+# Secondary CPU boot point
308+#
309+###############################################################################
310+#ifdef CONFIG_SMP
311+startup_secondary:
312+ # preload the PGD pointer register
313+ mov swapper_pg_dir,d0
314+ mov d0,(PTBR)
315+ clr d0
316+ movbu d0,(PIDR)
317+
318+ # turn on the TLBs
319+ mov MMUCTR_IIV|MMUCTR_DIV,d0
320+ mov d0,(MMUCTR)
321+#ifdef CONFIG_AM34_2
322+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
323+#else
324+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
325+#endif
326+ mov d0,(MMUCTR)
327+
328+ # turn on AM33v2 exception handling mode and set the trap table base
329+ movhu (CPUP),d0
330+ or CPUP_EXM_AM33V2,d0
331+ movhu d0,(CPUP)
332+
333+ # set the interrupt vector table
334+ mov CONFIG_INTERRUPT_VECTOR_BASE,d0
335+ mov d0,(TBR)
336+
337+ # invalidate and enable both of the caches
338+ mov ECHCTR,a0
339+ clr d0
340+ mov d0,(a0)
341+ mov CHCTR,a0
342+ clr d0
343+ movhu d0,(a0) # turn off first
344+ mov CHCTR_ICINV|CHCTR_DCINV,d0
345+ movhu d0,(a0)
346+ setlb
347+ mov (a0),d0
348+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
349+ lne
350+
351+#ifdef CONFIG_MN10300_CACHE_ENABLED
352+#ifdef CONFIG_MN10300_CACHE_WBACK
353+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
354+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
355+#else
356+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
357+#endif /* !NOWRALLOC */
358+#else
359+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
360+#endif /* WBACK */
361+ movhu d0,(a0) # enable
362+#endif /* ENABLED */
363+
364+ # Clear the boot IPI interrupt for this CPU
365+ movhu (GxICR(SMP_BOOT_IRQ)),d0
366+ and ~GxICR_REQUEST,d0
367+ movhu d0,(GxICR(SMP_BOOT_IRQ))
368+ movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush
369+
370+ /* get stack */
371+ mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0
372+ mov (CPUID),d0
373+ and CPUID_MASK,d0
374+ mulu CONFIG_BOOT_STACK_SIZE,d0
375+ sub d0,a0
376+ mov a0,sp
377+
378+ # init interrupt for AP
379+ call smp_prepare_cpu_init[],0
380+
381+ # mark this secondary CPU in cpu_boot_map
382+ mov (CPUID),d0
383+ mov 0x1,d1
384+ asl d0,d1
385+ mov cpu_boot_map,a0
386+ bset d1,(a0)
387+
388+ or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts
389+ nop
390+ nop
391+#ifdef CONFIG_MN10300_CACHE_WBACK
392+ # flush the local cache if it's in writeback mode
393+ call mn10300_local_dcache_flush_inv[],0
394+ setlb
395+ mov (CHCTR),d0
396+ btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
397+ lne
398+#endif
399+
400+ # now sleep waiting for further instructions
401+secondary_sleep:
402+ mov CPUM_SLEEP,d0
403+ movhu d0,(CPUM)
404+ nop
405+ nop
406+ bra secondary_sleep
407+ .size startup_secondary,.-startup_secondary
408+#endif /* CONFIG_SMP */
409+
410+###############################################################################
411+#
412+#
413+#
414+###############################################################################
221415 ENTRY(__head_end)
222416
223417 /*
arch/mn10300/kernel/internal.h+25−0
@@ -9,6 +9,9 @@ · 8 unmodified lines
99 * 2 of the Licence, or (at your option) any later version.
1010 */
1111
12+struct clocksource;
13+struct clock_event_device;
14+
1215 /*
1316 * kthread.S
1417 */
@@ -18,3 +21,25 @@ extern int kernel_thread_helper(int); · 3 unmodified lines
1821 * entry.S
1922 */
2023 extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
24+
25+/*
26+ * smp-low.S
27+ */
28+#ifdef CONFIG_SMP
29+extern void mn10300_low_ipi_handler(void);
30+#endif
31+
32+/*
33+ * time.c
34+ */
35+extern irqreturn_t local_timer_interrupt(void);
36+
37+/*
38+ * time.c
39+ */
40+#ifdef CONFIG_CEVT_MN10300
41+extern void clockevent_set_clock(struct clock_event_device *, unsigned int);
42+#endif
43+#ifdef CONFIG_CSRC_MN10300
44+extern void clocksource_set_clock(struct clocksource *, unsigned int);
45+#endif
arch/mn10300/kernel/irq.c+246−30
@@ -12,11 +12,26 @@ · 11 unmodified lines
1212 #include <linux/interrupt.h>
1313 #include <linux/kernel_stat.h>
1414 #include <linux/seq_file.h>
15+#include <linux/cpumask.h>
1516 #include <asm/setup.h>
17+#include <asm/serial-regs.h>
1618
17−unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7;
19+unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = {
20+ [0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7
21+};
1822 EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
1923
24+#ifdef CONFIG_SMP
25+static char irq_affinity_online[NR_IRQS] = {
26+ [0 ... NR_IRQS - 1] = 0
27+};
28+
29+#define NR_IRQ_WORDS ((NR_IRQS + 31) / 32)
30+static unsigned long irq_affinity_request[NR_IRQ_WORDS] = {
31+ [0 ... NR_IRQ_WORDS - 1] = 0
32+};
33+#endif /* CONFIG_SMP */
34+
2035 atomic_t irq_err_count;
2136
2237 /*
@@ -24,30 +39,67 @@ atomic_t irq_err_count; · 1 unmodified line
2439 */
2540 static void mn10300_cpupic_ack(unsigned int irq)
2641 {
42+ unsigned long flags;
2743 u16 tmp;
28− *(volatile u8 *) &GxICR(irq) = GxICR_DETECT;
44+
45+ flags = arch_local_cli_save();
46+ GxICR_u8(irq) = GxICR_DETECT;
2947 tmp = GxICR(irq);
48+ arch_local_irq_restore(flags);
3049 }
3150
32−static void mn10300_cpupic_mask(unsigned int irq)
51+static void __mask_and_set_icr(unsigned int irq,
52+ unsigned int mask, unsigned int set)
3353 {
34− u16 tmp = GxICR(irq);
35− GxICR(irq) = (tmp & GxICR_LEVEL);
54+ unsigned long flags;
55+ u16 tmp;
56+
57+ flags = arch_local_cli_save();
58+ tmp = GxICR(irq);
59+ GxICR(irq) = (tmp & mask) | set;
3660 tmp = GxICR(irq);
61+ arch_local_irq_restore(flags);
62+}
63+
64+static void mn10300_cpupic_mask(unsigned int irq)
65+{
66+ __mask_and_set_icr(irq, GxICR_LEVEL, 0);
3767 }
3868
3969 static void mn10300_cpupic_mask_ack(unsigned int irq)
4070 {
41− u16 tmp = GxICR(irq);
42− GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
43− tmp = GxICR(irq);
71+#ifdef CONFIG_SMP
72+ unsigned long flags;
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 */
4498 }
4599
46100 static void mn10300_cpupic_unmask(unsigned int irq)
47101 {
48− u16 tmp = GxICR(irq);
49− GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
50− tmp = GxICR(irq);
102+ __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
51103 }
52104
53105 static void mn10300_cpupic_unmask_clear(unsigned int irq)
@@ -56,11 +108,89 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) · 2 unmodified lines
56108 * device has ceased to assert its interrupt line and the interrupt
57109 * channel has been disabled in the PIC, so for level-triggered
58110 * interrupts we need to clear the request bit when we re-enable */
59− u16 tmp = GxICR(irq);
60− GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
61− tmp = GxICR(irq);
111+#ifdef CONFIG_SMP
112+ unsigned long flags;
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 */
62133 }
63134
135+#ifdef CONFIG_SMP
136+static int
137+mn10300_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+
64194 /*
65195 * MN10300 PIC level-triggered IRQ handling.
66196 *
@@ -79,6 +209,9 @@ static struct irq_chip mn10300_cpu_pic_level = { · 12 unmodified lines
79209 .mask = mn10300_cpupic_mask,
80210 .mask_ack = mn10300_cpupic_mask,
81211 .unmask = mn10300_cpupic_unmask_clear,
212+#ifdef CONFIG_SMP
213+ .set_affinity = mn10300_cpupic_setaffinity,
214+#endif
82215 };
83216
84217 /*
@@ -94,6 +227,9 @@ static struct irq_chip mn10300_cpu_pic_edge = { · 9 unmodified lines
94227 .mask = mn10300_cpupic_mask,
95228 .mask_ack = mn10300_cpupic_mask_ack,
96229 .unmask = mn10300_cpupic_unmask,
230+#ifdef CONFIG_SMP
231+ .set_affinity = mn10300_cpupic_setaffinity,
232+#endif
97233 };
98234
99235 /*
@@ -111,14 +247,34 @@ void ack_bad_irq(int irq) · 11 unmodified lines
111247 */
112248 void set_intr_level(int irq, u16 level)
113249 {
114− u16 tmp;
250+ BUG_ON(in_interrupt());
115251
116− if (in_interrupt())
117− BUG();
252+ __mask_and_set_icr(irq, GxICR_ENABLE, level);
253+}
118254
119− tmp = GxICR(irq);
120− GxICR(irq) = (tmp & GxICR_ENABLE) | level;
121− tmp = GxICR(irq);
255+void mn10300_intc_set_level(unsigned int irq, unsigned int level)
256+{
257+ set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
258+}
259+
260+void mn10300_intc_clear(unsigned int irq)
261+{
262+ __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
263+}
264+
265+void mn10300_intc_set(unsigned int irq)
266+{
267+ __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
268+}
269+
270+void mn10300_intc_enable(unsigned int irq)
271+{
272+ mn10300_cpupic_unmask(irq);
273+}
274+
275+void mn10300_intc_disable(unsigned int irq)
276+{
277+ mn10300_cpupic_mask(irq);
122278 }
123279
124280 /*
@@ -126,7 +282,7 @@ void set_intr_level(int irq, u16 level) · 1 unmodified line
126282 * than before
127283 * - see Documentation/mn10300/features.txt
128284 */
129−void set_intr_postackable(int irq)
285+void mn10300_set_lateack_irq_type(int irq)
130286 {
131287 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
132288 handle_level_irq);
@@ -147,6 +303,7 @@ void __init init_IRQ(void) · 14 unmodified lines
147303 * interrupts */
148304 set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
149305 handle_level_irq);
306+
150307 unit_init_IRQ();
151308 }
152309
@@ -156,20 +313,22 @@ void __init init_IRQ(void) · 3 unmodified lines
156313 asmlinkage void do_IRQ(void)
157314 {
158315 unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
316+ unsigned int cpu_id = smp_processor_id();
159317 int irq;
160318
161319 sp = current_stack_pointer();
162− if (sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN)
163− BUG();
320+ BUG_ON(sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN);
164321
165322 /* make sure local_irq_enable() doesn't muck up the interrupt priority
166323 * setting in EPSW */
167− old_irq_enabled_epsw = __mn10300_irq_enabled_epsw;
324+ old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id];
168325 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);
170327 irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
171328
172− __IRQ_STAT(smp_processor_id(), __irq_count)++;
329+#ifdef CONFIG_MN10300_WD_TIMER
330+ __IRQ_STAT(cpu_id, __irq_count)++;
331+#endif
173332
174333 irq_enter();
175334
@@ -189,7 +348,7 @@ asmlinkage void do_IRQ(void) · 13 unmodified lines
189348 local_irq_restore(epsw);
190349 }
191350
192− __mn10300_irq_enabled_epsw = old_irq_enabled_epsw;
351+ __mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw;
193352
194353 irq_exit();
195354 }
@@ -222,9 +381,16 @@ int show_interrupts(struct seq_file *p, void *v) · 26 unmodified lines
222381 seq_printf(p, "%3d: ", i);
223382 for_each_present_cpu(cpu)
224383 seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
225− seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
226− (GxICR(i) & GxICR_LEVEL) >>
227− GxICR_LEVEL_SHIFT);
384+
385+ if (i < NR_CPU_IRQS)
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+
228394 seq_printf(p, " %s", action->name);
229395
230396 for (action = action->next;
@@ -240,11 +406,13 @@ int show_interrupts(struct seq_file *p, void *v) · 9 unmodified lines
240406
241407 /* polish off with NMI and error counters */
242408 case NR_IRQS:
409+#ifdef CONFIG_MN10300_WD_TIMER
243410 seq_printf(p, "NMI: ");
244411 for (j = 0; j < NR_CPUS; j++)
245412 if (cpu_online(j))
246413 seq_printf(p, "%10u ", nmi_count(j));
247414 seq_putc(p, '\n');
415+#endif
248416
249417 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
250418 break;
@@ -252,3 +420,51 @@ int show_interrupts(struct seq_file *p, void *v) · 1 unmodified line
252420
253421 return 0;
254422 }
423+
424+#ifdef CONFIG_HOTPLUG_CPU
425+void 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 */
arch/mn10300/kernel/kprobes.c+4−0
@@ -377,8 +377,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) · 376 unmodified lines
377377
378378 void __kprobes arch_disarm_kprobe(struct kprobe *p)
379379 {
380+#ifndef CONFIG_MN10300_CACHE_SNOOP
380381 mn10300_dcache_flush();
381382 mn10300_icache_inv();
383+#endif
382384 }
383385
384386 void arch_remove_kprobe(struct kprobe *p)
@@ -390,8 +392,10 @@ void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs) · 5 unmodified lines
390392 {
391393 *p->addr = p->opcode;
392394 regs->pc = (unsigned long) p->addr;
395+#ifndef CONFIG_MN10300_CACHE_SNOOP
393396 mn10300_dcache_flush();
394397 mn10300_icache_inv();
398+#endif
395399 }
396400
397401 static inline
arch/mn10300/kernel/mn10300-serial-low.S+3−3
@@ -39,7 +39,7 @@ · 38 unmodified lines
3939 ###############################################################################
4040 .balign L1_CACHE_BYTES
4141 ENTRY(mn10300_serial_vdma_interrupt)
42− or EPSW_IE,psw # permit overriding by
42+# or EPSW_IE,psw # permit overriding by
4343 # debugging interrupts
4444 movm [d2,d3,a2,a3,exreg0],(sp)
4545
@@ -164,7 +164,7 @@ mnsc_vdma_tx_noint: · 118 unmodified lines
164164 rti
165165
166166 mnsc_vdma_tx_empty:
167− mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
167+ mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
168168 movhu d2,(e3) # disable the interrupt
169169 movhu (e3),d2 # flush
170170
@@ -175,7 +175,7 @@ mnsc_vdma_tx_break: · 4 unmodified lines
175175 movhu (SCxCTR,e2),d2 # turn on break mode
176176 or SC01CTR_BKE,d2
177177 movhu d2,(SCxCTR,e2)
178− mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
178+ mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
179179 movhu d2,(e3) # disable transmit interrupts on this
180180 # channel
181181 movhu (e3),d2 # flush
arch/mn10300/kernel/mn10300-serial.c+181−29
@@ -44,6 +44,11 @@ static const char serial_revdate[] = "2007-11-06"; · 43 unmodified lines
4444 #include <unit/timex.h>
4545 #include "mn10300-serial.h"
4646
47+#ifdef CONFIG_SMP
48+#undef GxICR
49+#define GxICR(X) CROSS_GxICR(X, 0)
50+#endif /* CONFIG_SMP */
51+
4752 #define kenter(FMT, ...) \
4853 printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
4954 #define _enter(FMT, ...) \
@@ -57,6 +62,11 @@ static const char serial_revdate[] = "2007-11-06"; · 7 unmodified lines
5762 #define _proto(FMT, ...) \
5863 no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
5964
65+#ifndef CODMSB
66+/* c_cflag bit meaning */
67+#define CODMSB 004000000000 /* change Transfer bit-order */
68+#endif
69+
6070 #define NR_UARTS 3
6171
6272 #ifdef CONFIG_MN10300_TTYSM_CONSOLE
@@ -152,26 +162,35 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { · 89 unmodified lines
152162 .name = "ttySM0",
153163 ._iobase = &SC0CTR,
154164 ._control = &SC0CTR,
155− ._status = (volatile u8 *) &SC0STR,
165+ ._status = (volatile u8 *)&SC0STR,
156166 ._intr = &SC0ICR,
157167 ._rxb = &SC0RXB,
158168 ._txb = &SC0TXB,
159169 .rx_name = "ttySM0:Rx",
160170 .tx_name = "ttySM0:Tx",
161−#ifdef CONFIG_MN10300_TTYSM0_TIMER8
171+#if defined(CONFIG_MN10300_TTYSM0_TIMER8)
162172 .tm_name = "ttySM0:Timer8",
163173 ._tmxmd = &TM8MD,
164174 ._tmxbr = &TM8BR,
165175 ._tmicr = &TM8ICR,
166176 .tm_irq = TM8IRQ,
167177 .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)
169186 .tm_name = "ttySM0:Timer2",
170187 ._tmxmd = &TM2MD,
171− ._tmxbr = (volatile u16 *) &TM2BR,
188+ ._tmxbr = (volatile u16 *)&TM2BR,
172189 ._tmicr = &TM2ICR,
173190 .tm_irq = TM2IRQ,
174191 .div_timer = MNSCx_DIV_TIMER_8BIT,
192+#else
193+#error "Unknown config for ttySM0"
175194 #endif
176195 .rx_irq = SC0RXIRQ,
177196 .tx_irq = SC0TXIRQ,
@@ -205,26 +224,35 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { · 27 unmodified lines
205224 .name = "ttySM1",
206225 ._iobase = &SC1CTR,
207226 ._control = &SC1CTR,
208− ._status = (volatile u8 *) &SC1STR,
227+ ._status = (volatile u8 *)&SC1STR,
209228 ._intr = &SC1ICR,
210229 ._rxb = &SC1RXB,
211230 ._txb = &SC1TXB,
212231 .rx_name = "ttySM1:Rx",
213232 .tx_name = "ttySM1:Tx",
214−#ifdef CONFIG_MN10300_TTYSM1_TIMER9
233+#if defined(CONFIG_MN10300_TTYSM1_TIMER9)
215234 .tm_name = "ttySM1:Timer9",
216235 ._tmxmd = &TM9MD,
217236 ._tmxbr = &TM9BR,
218237 ._tmicr = &TM9ICR,
219238 .tm_irq = TM9IRQ,
220239 .div_timer = MNSCx_DIV_TIMER_16BIT,
221−#else /* CONFIG_MN10300_TTYSM1_TIMER3 */
240+#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
222241 .tm_name = "ttySM1:Timer3",
223242 ._tmxmd = &TM3MD,
224− ._tmxbr = (volatile u16 *) &TM3BR,
243+ ._tmxbr = (volatile u16 *)&TM3BR,
225244 ._tmicr = &TM3ICR,
226245 .tm_irq = TM3IRQ,
227246 .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"
228256 #endif
229257 .rx_irq = SC1RXIRQ,
230258 .tx_irq = SC1TXIRQ,
@@ -260,20 +288,45 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { · 29 unmodified lines
260288 .uart.lock =
261289 __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
262290 .name = "ttySM2",
263− .rx_name = "ttySM2:Rx",
264− .tx_name = "ttySM2:Tx",
265− .tm_name = "ttySM2:Timer10",
266291 ._iobase = &SC2CTR,
267292 ._control = &SC2CTR,
268− ._status = &SC2STR,
293+ ._status = (volatile u8 *)&SC2STR,
269294 ._intr = &SC2ICR,
270295 ._rxb = &SC2RXB,
271296 ._txb = &SC2TXB,
297+ .rx_name = "ttySM2:Rx",
298+ .tx_name = "ttySM2:Tx",
299+#if defined(CONFIG_MN10300_TTYSM2_TIMER10)
300+ .tm_name = "ttySM2/Timer10",
272301 ._tmxmd = &TM10MD,
273302 ._tmxbr = &TM10BR,
274303 ._tmicr = &TM10ICR,
275304 .tm_irq = TM10IRQ,
276305 .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
277330 .rx_irq = SC2RXIRQ,
278331 .tx_irq = SC2TXIRQ,
279332 .rx_icr = &GxICR(SC2RXIRQ),
@@ -322,9 +375,13 @@ struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = { · 42 unmodified lines
322375 */
323376 static void mn10300_serial_mask_ack(unsigned int irq)
324377 {
378+ unsigned long flags;
325379 u16 tmp;
380+
381+ flags = arch_local_cli_save();
326382 GxICR(irq) = GxICR_LEVEL_6;
327383 tmp = GxICR(irq); /* flush write buffer */
384+ arch_local_irq_restore(flags);
328385 }
329386
330387 static void mn10300_serial_nop(unsigned int irq)
@@ -348,23 +405,36 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS]; · 17 unmodified lines
348405
349406 static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
350407 {
408+ unsigned long flags;
351409 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);
353413 x = *port->tx_icr;
414+ arch_local_irq_restore(flags);
354415 }
355416
356417 static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
357418 {
419+ unsigned long flags;
358420 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;
360425 x = *port->tx_icr;
426+ arch_local_irq_restore(flags);
361427 }
362428
363429 static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
364430 {
431+ unsigned long flags;
365432 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);
367436 x = *port->rx_icr;
437+ arch_local_irq_restore(flags);
368438 }
369439
370440 /*
@@ -650,7 +720,7 @@ static unsigned int mn10300_serial_tx_empty(struct uart_port *_port) · 279 unmodified lines
650720 static void mn10300_serial_set_mctrl(struct uart_port *_port,
651721 unsigned int mctrl)
652722 {
653− struct mn10300_serial_port *port =
723+ struct mn10300_serial_port *port __attribute__ ((unused)) =
654724 container_of(_port, struct mn10300_serial_port, uart);
655725
656726 _enter("%s,%x", port->name, mctrl);
@@ -706,6 +776,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port) · 49 unmodified lines
706776 UART_XMIT_SIZE));
707777
708778 /* kick the virtual DMA controller */
779+ arch_local_cli();
709780 x = *port->tx_icr;
710781 x |= GxICR_ENABLE;
711782
@@ -716,10 +787,14 @@ static void mn10300_serial_start_tx(struct uart_port *_port) · 4 unmodified lines
716787
717788 _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
718789 *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);
720794
721795 *port->tx_icr = x;
722796 x = *port->tx_icr;
797+ arch_local_sti();
723798 }
724799
725800 /*
@@ -842,8 +917,10 @@ static int mn10300_serial_startup(struct uart_port *_port) · 116 unmodified lines
842917 pint->port = port;
843918 pint->vdma = mn10300_serial_vdma_tx_handler;
844919
845− set_intr_level(port->rx_irq, GxICR_LEVEL_1);
846− set_intr_level(port->tx_irq, GxICR_LEVEL_1);
920+ set_intr_level(port->rx_irq,
921+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
922+ set_intr_level(port->tx_irq,
923+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
847924 set_irq_chip(port->tm_irq, &mn10300_serial_pic);
848925
849926 if (request_irq(port->rx_irq, mn10300_serial_interrupt,
@@ -876,6 +953,7 @@ error: · 26 unmodified lines
876953 */
877954 static void mn10300_serial_shutdown(struct uart_port *_port)
878955 {
956+ u16 x;
879957 struct mn10300_serial_port *port =
880958 container_of(_port, struct mn10300_serial_port, uart);
881959
@@ -897,8 +975,12 @@ static void mn10300_serial_shutdown(struct uart_port *_port) · 15 unmodified lines
897975 free_irq(port->rx_irq, port);
898976 free_irq(port->tx_irq, port);
899977
900− *port->rx_icr = GxICR_LEVEL_1;
901− *port->tx_icr = GxICR_LEVEL_1;
978+ arch_local_cli();
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();
902984 }
903985
904986 /*
@@ -947,11 +1029,66 @@ static void mn10300_serial_change_speed(struct mn10300_serial_port *port, · 42 unmodified lines
9471029 /* Determine divisor based on baud rate */
9481030 battempt = 0;
9491031
950− if (div_timer == MNSCx_DIV_TIMER_16BIT)
951− scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8
952− * == SC2CTR_CK_TM10UFLOW) */
953− else if (div_timer == MNSCx_DIV_TIMER_8BIT)
1032+ switch (port->uart.line) {
1033+#ifdef CONFIG_MN10300_TTYSM0
1034+ case 0: /* ttySM0 */
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)
9541040 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+ }
9551092
9561093 try_alternative:
9571094 baud = uart_get_baud_rate(&port->uart, new, old, 0,
@@ -1195,6 +1332,12 @@ static void mn10300_serial_set_termios(struct uart_port *_port, · 237 unmodified lines
11951332 ctr &= ~SC2CTR_TWE;
11961333 *port->_control = ctr;
11971334 }
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 */
11981341 }
11991342
12001343 /*
@@ -1302,11 +1445,16 @@ static int __init mn10300_serial_init(void) · 101 unmodified lines
13021445 printk(KERN_INFO "%s version %s (%s)\n",
13031446 serial_name, serial_version, serial_revdate);
13041447
1305−#ifdef CONFIG_MN10300_TTYSM2
1306− SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
1448+#if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2)
1449+ {
1450+ int tmp;
1451+ SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
1452+ tmp = SC2TIM;
1453+ }
13071454 #endif
13081455
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);
13101458
13111459 ret = uart_register_driver(&mn10300_serial_driver);
13121460 if (!ret) {
@@ -1366,9 +1514,11 @@ static void mn10300_serial_console_write(struct console *co, · 53 unmodified lines
13661514 port = mn10300_serial_ports[co->index];
13671515
13681516 /* firstly hijack the serial port from the "virtual DMA" controller */
1517+ arch_local_cli();
13691518 txicr = *port->tx_icr;
1370− *port->tx_icr = GxICR_LEVEL_1;
1519+ *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
13711520 tmp = *port->tx_icr;
1521+ arch_local_sti();
13721522
13731523 /* the transmitter may be disabled */
13741524 scxctr = *port->_control;
@@ -1422,8 +1572,10 @@ static void mn10300_serial_console_write(struct console *co, · 47 unmodified lines
14221572 if (!(scxctr & SC01CTR_TXE))
14231573 *port->_control = scxctr;
14241574
1575+ arch_local_cli();
14251576 *port->tx_icr = txicr;
14261577 tmp = *port->tx_icr;
1578+ arch_local_sti();
14271579 }
14281580
14291581 /*
arch/mn10300/kernel/mn10300-watchdog-low.S+8−1
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <asm/intctl-regs.h>
1717 #include <asm/timer-regs.h>
1818 #include <asm/frame.inc>
19+#include <linux/threads.h>
1920
2021 .text
2122
@@ -53,7 +54,13 @@ watchdog_handler: · 31 unmodified lines
5354 .type touch_nmi_watchdog,@function
5455 touch_nmi_watchdog:
5556 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
5764 ret [],0
5865
5966 .size touch_nmi_watchdog,.-touch_nmi_watchdog
arch/mn10300/kernel/mn10300-watchdog.c+61−39
@@ -30,7 +30,7 @@ · 29 unmodified lines
3030 static DEFINE_SPINLOCK(watchdog_print_lock);
3131 static unsigned int watchdog;
3232 static unsigned int watchdog_hz = 1;
33−unsigned int watchdog_alert_counter;
33+unsigned int watchdog_alert_counter[NR_CPUS];
3434
3535 EXPORT_SYMBOL(touch_nmi_watchdog);
3636
@@ -39,9 +39,6 @@ EXPORT_SYMBOL(touch_nmi_watchdog); · 2 unmodified lines
3939 * is to check its timer makes IRQ counts. If they are not
4040 * changing then that CPU has some problem.
4141 *
42− * as these watchdog NMI IRQs are generated on every CPU, we only
43− * have to check the current processor.
44− *
4542 * since NMIs dont listen to _any_ locks, we have to be extremely
4643 * careful not to rely on unsafe variables. The printk might lock
4744 * up though, so we have to break up any console locks first ...
@@ -69,8 +66,8 @@ int __init check_watchdog(void) · 21 unmodified lines
6966
7067 printk(KERN_INFO "OK.\n");
7168
72− /* now that we know it works we can reduce NMI frequency to
73− * something more reasonable; makes a difference in some configs
69+ /* now that we know it works we can reduce NMI frequency to something
70+ * more reasonable; makes a difference in some configs
7471 */
7572 watchdog_hz = 1;
7673
@@ -121,15 +118,22 @@ void __init watchdog_go(void) · 44 unmodified lines
121118 }
122119 }
123120
121+#ifdef CONFIG_SMP
122+static void watchdog_dump_register(void *dummy)
123+{
124+ printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
125+ show_registers(current_frame());
126+}
127+#endif
128+
124129 asmlinkage
125130 void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
126131 {
127−
128132 /*
129133 * Since current-> is always on the stack, and we always switch
130134 * the stack NMI-atomically, it's safe to use smp_processor_id().
131135 */
132− int sum, cpu = smp_processor_id();
136+ int sum, cpu;
133137 int irq = NMIIRQ;
134138 u8 wdt, tmp;
135139
@@ -138,43 +142,61 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) · 2 unmodified lines
138142 tmp = WDCTR;
139143 NMICR = NMICR_WDIF;
140144
141− nmi_count(cpu)++;
145+ nmi_count(smp_processor_id())++;
142146 kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
143− sum = irq_stat[cpu].__irq_count;
144−
145− if (last_irq_sums[cpu] == sum) {
146− /*
147− * Ayiee, looks like this CPU is stuck ...
148− * wait a few IRQs (5 seconds) before doing the oops ...
149− */
150− watchdog_alert_counter++;
151− if (watchdog_alert_counter == 5 * watchdog_hz) {
152− spin_lock(&watchdog_print_lock);
147+
148+ for_each_online_cpu(cpu) {
149+
150+ sum = irq_stat[cpu].__irq_count;
151+
152+ if ((last_irq_sums[cpu] == sum)
153+#if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP)
154+ && !(CHK_GDBSTUB_BUSY()
155+ || atomic_read(&cpu_doing_single_step))
156+#endif
157+ ) {
153158 /*
154− * We are in trouble anyway, lets at least try
155− * to get a message out.
159+ * Ayiee, looks like this CPU is stuck ...
160+ * wait a few IRQs (5 seconds) before doing the oops ...
156161 */
157− bust_spinlocks(1);
158− printk(KERN_ERR
159− "NMI Watchdog detected LOCKUP on CPU%d,"
160− " pc %08lx, registers:\n",
161− cpu, regs->pc);
162− show_registers(regs);
163− printk("console shuts up ...\n");
164− console_silent();
165− spin_unlock(&watchdog_print_lock);
166− bust_spinlocks(0);
162+ watchdog_alert_counter[cpu]++;
163+ if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) {
164+ spin_lock(&watchdog_print_lock);
165+ /*
166+ * We are in trouble anyway, lets at least try
167+ * to get a message out.
168+ */
169+ bust_spinlocks(1);
170+ printk(KERN_ERR
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);
167188 #ifdef CONFIG_GDBSTUB
168− if (gdbstub_busy)
169− gdbstub_exception(regs, excep);
170− else
171− gdbstub_intercept(regs, excep);
189+ if (CHK_GDBSTUB_BUSY_AND_ACTIVE())
190+ gdbstub_exception(regs, excep);
191+ else
192+ gdbstub_intercept(regs, excep);
172193 #endif
173− do_exit(SIGSEGV);
194+ do_exit(SIGSEGV);
195+ }
196+ } else {
197+ last_irq_sums[cpu] = sum;
198+ watchdog_alert_counter[cpu] = 0;
174199 }
175− } else {
176− last_irq_sums[cpu] = sum;
177− watchdog_alert_counter = 0;
178200 }
179201
180202 WDCTR = wdt | WDCTR_WDRST;
arch/mn10300/kernel/process.c+47−14
@@ -57,6 +57,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) · 56 unmodified lines
5757 void (*pm_power_off)(void);
5858 EXPORT_SYMBOL(pm_power_off);
5959
60+#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
6061 /*
6162 * we use this if we don't have any better idle routine
6263 */
@@ -69,6 +70,35 @@ static void default_idle(void) · 6 unmodified lines
6970 local_irq_enable();
7071 }
7172
73+#else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
74+/*
75+ * On SMP it's slightly faster (but much more power-consuming!)
76+ * to poll the ->work.need_resched flag instead of waiting for the
77+ * cross-CPU IPI to arrive. Use this option with caution.
78+ */
79+static inline void poll_idle(void)
80+{
81+ int oldval;
82+
83+ local_irq_enable();
84+
85+ /*
86+ * Deal with another CPU just having chosen a thread to
87+ * run here:
88+ */
89+ oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
90+
91+ if (!oldval) {
92+ set_thread_flag(TIF_POLLING_NRFLAG);
93+ while (!need_resched())
94+ cpu_relax();
95+ clear_thread_flag(TIF_POLLING_NRFLAG);
96+ } else {
97+ set_need_resched();
98+ }
99+}
100+#endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
101+
72102 /*
73103 * the idle thread
74104 * - 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) · 2 unmodified lines
77107 */
78108 void cpu_idle(void)
79109 {
80− int cpu = smp_processor_id();
81−
82110 /* endless idle loop with no priority at all */
83111 for (;;) {
84112 while (!need_resched()) {
@@ -86,10 +114,13 @@ void cpu_idle(void) · 1 unmodified line
86114
87115 smp_rmb();
88116 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 */
90121 idle = default_idle;
91−
92− irq_stat[cpu].idle_timestamp = jiffies;
122+#endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
123+ }
93124 idle();
94125 }
95126
@@ -197,6 +228,7 @@ int copy_thread(unsigned long clone_flags, · 101 unmodified lines
197228 unsigned long c_usp, unsigned long ustk_size,
198229 struct task_struct *p, struct pt_regs *kregs)
199230 {
231+ struct thread_info *ti = task_thread_info(p);
200232 struct pt_regs *c_uregs, *c_kregs, *uregs;
201233 unsigned long c_ksp;
202234
@@ -217,7 +249,7 @@ int copy_thread(unsigned long clone_flags, · 14 unmodified lines
217249
218250 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
219251 if (clone_flags & CLONE_SETTLS)
220− c_uregs->e2 = __frame->d3;
252+ c_uregs->e2 = current_frame()->d3;
221253
222254 /* set up the return kernel frame if called from kernel_thread() */
223255 c_kregs = c_uregs;
@@ -235,7 +267,7 @@ int copy_thread(unsigned long clone_flags, · 11 unmodified lines
235267 }
236268
237269 /* set up things up so the scheduler can start the new task */
238− p->thread.__frame = c_kregs;
270+ ti->frame = c_kregs;
239271 p->thread.a3 = (unsigned long) c_kregs;
240272 p->thread.sp = c_ksp;
241273 p->thread.pc = (unsigned long) ret_from_fork;
@@ -247,25 +279,26 @@ int copy_thread(unsigned long clone_flags, · 5 unmodified lines
247279
248280 /*
249281 * clone a process
250− * - tlsptr is retrieved by copy_thread() from __frame->d3
282+ * - tlsptr is retrieved by copy_thread() from current_frame()->d3
251283 */
252284 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
253285 int __user *parent_tidptr, int __user *child_tidptr,
254286 int __user *tlsptr)
255287 {
256− return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
257− parent_tidptr, child_tidptr);
288+ return do_fork(clone_flags, newsp ?: current_frame()->sp,
289+ current_frame(), 0, parent_tidptr, child_tidptr);
258290 }
259291
260292 asmlinkage long sys_fork(void)
261293 {
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);
263296 }
264297
265298 asmlinkage long sys_vfork(void)
266299 {
267− return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
268− 0, NULL, NULL);
300+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
301+ current_frame(), 0, NULL, NULL);
269302 }
270303
271304 asmlinkage long sys_execve(const char __user *name,
@@ -279,7 +312,7 @@ asmlinkage long sys_execve(const char __user *name, · 7 unmodified lines
279312 error = PTR_ERR(filename);
280313 if (IS_ERR(filename))
281314 return error;
282− error = do_execve(filename, argv, envp, __frame);
315+ error = do_execve(filename, argv, envp, current_frame());
283316 putname(filename);
284317 return error;
285318 }
arch/mn10300/kernel/profile.c+1−1
@@ -41,7 +41,7 @@ static __init int profile_init(void) · 40 unmodified lines
4141 tmp = TM11ICR;
4242
4343 printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n",
44− mn10300_ioclk / 8 / (TM11BR + 1));
44+ MN10300_IOCLK / 8 / (TM11BR + 1));
4545 printk(KERN_INFO "Profile histogram stored %p-%p\n",
4646 prof_buffer, (u8 *)(prof_buffer + prof_len) - 1);
4747
arch/mn10300/kernel/rtc.c+10−31
@@ -20,18 +20,22 @@ · 19 unmodified lines
2020 DEFINE_SPINLOCK(rtc_lock);
2121 EXPORT_SYMBOL(rtc_lock);
2222
23−/* time for RTC to update itself in ioclks */
24−static unsigned long mn10300_rtc_update_period;
25−
23+/*
24+ * Read the current RTC time
25+ */
2626 void read_persistent_clock(struct timespec *ts)
2727 {
2828 struct rtc_time tm;
2929
3030 get_rtc_time(&tm);
3131
32− ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
33− tm.tm_hour, tm.tm_min, tm.tm_sec);
3432 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);
3539 }
3640
3741 /*
@@ -115,39 +119,14 @@ int update_persistent_clock(struct timespec now) · 77 unmodified lines
115119 */
116120 void __init calibrate_clock(void)
117121 {
118− unsigned long count0, counth, count1;
119122 unsigned char status;
120123
121124 /* make sure the RTC is running and is set to operate in 24hr mode */
122125 status = RTSRC;
123126 RTCRB |= RTCRB_SET;
124127 RTCRB |= RTCRB_TM_24HR;
128+ RTCRB &= ~RTCRB_DM_BINARY;
125129 RTCRA |= RTCRA_DVR;
126130 RTCRA &= ~RTCRA_DVR;
127131 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;
153132 }
arch/mn10300/kernel/setup.c+43−36
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 #include <linux/init.h>
2323 #include <linux/bootmem.h>
2424 #include <linux/seq_file.h>
25+#include <linux/cpu.h>
2526 #include <asm/processor.h>
2627 #include <linux/console.h>
2728 #include <asm/uaccess.h>
@@ -30,7 +31,6 @@ · 2 unmodified lines
3031 #include <asm/io.h>
3132 #include <asm/smp.h>
3233 #include <proc/proc.h>
33−#include <asm/busctl-regs.h>
3434 #include <asm/fpu.h>
3535 #include <asm/sections.h>
3636
@@ -64,11 +64,13 @@ unsigned long memory_size; · 27 unmodified lines
6464 struct thread_info *__current_ti = &init_thread_union.thread_info;
6565 struct task_struct *__current = &init_task;
6666
67−#define mn10300_known_cpus 3
67+#define mn10300_known_cpus 5
6868 static const char *const mn10300_cputypes[] = {
69− "am33v1",
70− "am33v2",
71− "am34v1",
69+ "am33-1",
70+ "am33-2",
71+ "am34-1",
72+ "am33-3",
73+ "am34-2",
7274 "unknown"
7375 };
7476
@@ -123,6 +125,7 @@ void __init setup_arch(char **cmdline_p) · 48 unmodified lines
123125
124126 cpu_init();
125127 unit_setup();
128+ smp_init_cpus();
126129 parse_mem_cmdline(cmdline_p);
127130
128131 init_mm.start_code = (unsigned long)&_text;
@@ -179,57 +182,55 @@ void __init setup_arch(char **cmdline_p) · 50 unmodified lines
179182 void __init cpu_init(void)
180183 {
181184 unsigned long cpurev = CPUREV, type;
182− unsigned long base, size;
183185
184186 type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
185187 if (type > mn10300_known_cpus)
186188 type = mn10300_known_cpus;
187189
188− printk(KERN_INFO "Matsushita %s, rev %ld\n",
190+ printk(KERN_INFO "Panasonic %s, rev %ld\n",
189191 mn10300_cputypes[type],
190192 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S);
191193
192− /* determine the memory size and base from the memory controller regs */
193− memory_size = 0;
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;
194+ get_mem_info(&phys_memory_base, &memory_size);
195+ phys_memory_end = phys_memory_base + memory_size;
200196
201− printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
202− memory_size += size;
203− phys_memory_base = base;
204− }
197+ fpu_init_state();
198+}
205199
206− base = SDBASE(1);
207− if (base & SDBASE_CE) {
208− size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
209− size = ~size + 1;
210− base &= SDBASE_CBA;
200+static struct cpu cpu_devices[NR_CPUS];
211201
212− printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
213− memory_size += size;
214− if (phys_memory_base == 0)
215− phys_memory_base = base;
216− }
202+static int __init topology_init(void)
203+{
204+ int i;
217205
218− phys_memory_end = phys_memory_base + memory_size;
206+ for_each_present_cpu(i)
207+ register_cpu(&cpu_devices[i], i);
219208
220−#ifdef CONFIG_FPU
221− fpu_init_state();
222−#endif
209+ return 0;
223210 }
224211
212+subsys_initcall(topology_init);
213+
225214 /*
226215 * Get CPU information for use by the procfs.
227216 */
228217 static int show_cpuinfo(struct seq_file *m, void *v)
229218 {
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;
230225 unsigned long cpurev = CPUREV, type, icachesz, dcachesz;
226+#endif /* CONFIG_SMP */
231227
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;
233234 if (type > mn10300_known_cpus)
234235 type = mn10300_known_cpus;
235236
@@ -244,13 +245,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) · 8 unmodified lines
244245 1024;
245246
246247 seq_printf(m,
247− "processor : 0\n"
248− "vendor_id : Matsushita\n"
248+ "processor : %ld\n"
249+ "vendor_id : " PROCESSOR_VENDOR_NAME "\n"
249250 "cpu core : %s\n"
250251 "cpu rev : %lu\n"
251252 "model name : " PROCESSOR_MODEL_NAME "\n"
252253 "icache size: %lu\n"
253254 "dcache size: %lu\n",
255+ cpu_id,
254256 mn10300_cputypes[type],
255257 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S,
256258 icachesz,
@@ -262,8 +264,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) · 5 unmodified lines
262264 "bogomips : %lu.%02lu\n\n",
263265 MN10300_IOCLK / 1000000,
264266 (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 */
265271 loops_per_jiffy / (500000 / HZ),
266272 (loops_per_jiffy / (5000 / HZ)) % 100
273+#endif /* CONFIG_SMP */
267274 );
268275
269276 return 0;
arch/mn10300/kernel/signal.c+11−9
@@ -91,7 +91,7 @@ asmlinkage long sys_sigaction(int sig, · 90 unmodified lines
9191 */
9292 asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
9393 {
94− return do_sigaltstack(uss, uoss, __frame->sp);
94+ return do_sigaltstack(uss, uoss, current_frame()->sp);
9595 }
9696
9797 /*
@@ -156,10 +156,11 @@ badframe: · 58 unmodified lines
156156 */
157157 asmlinkage long sys_sigreturn(void)
158158 {
159− struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
159+ struct sigframe __user *frame;
160160 sigset_t set;
161161 long d0;
162162
163+ frame = (struct sigframe __user *) current_frame()->sp;
163164 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
164165 goto badframe;
165166 if (__get_user(set.sig[0], &frame->sc.oldmask))
@@ -176,7 +177,7 @@ asmlinkage long sys_sigreturn(void) · 10 unmodified lines
176177 recalc_sigpending();
177178 spin_unlock_irq(&current->sighand->siglock);
178179
179− if (restore_sigcontext(__frame, &frame->sc, &d0))
180+ if (restore_sigcontext(current_frame(), &frame->sc, &d0))
180181 goto badframe;
181182
182183 return d0;
@@ -191,11 +192,11 @@ badframe: · 8 unmodified lines
191192 */
192193 asmlinkage long sys_rt_sigreturn(void)
193194 {
194− struct rt_sigframe __user *frame =
195− (struct rt_sigframe __user *) __frame->sp;
195+ struct rt_sigframe __user *frame;
196196 sigset_t set;
197− unsigned long d0;
197+ long d0;
198198
199+ frame = (struct rt_sigframe __user *) current_frame()->sp;
199200 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
200201 goto badframe;
201202 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -207,10 +208,11 @@ asmlinkage long sys_rt_sigreturn(void) · 5 unmodified lines
207208 recalc_sigpending();
208209 spin_unlock_irq(&current->sighand->siglock);
209210
210− if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
211+ if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
211212 goto badframe;
212213
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)
214216 goto badframe;
215217
216218 return d0;
@@ -572,7 +574,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) · 355 unmodified lines
572574
573575 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
574576 clear_thread_flag(TIF_NOTIFY_RESUME);
575− tracehook_notify_resume(__frame);
577+ tracehook_notify_resume(current_frame());
576578 if (current->replacement_session_keyring)
577579 key_replace_session_keyring();
578580 }
arch/mn10300/kernel/smp-low.S+97−0
@@ -0,0 +1,97 @@
1+/* SMP IPI low-level handler
2+ *
3+ * Copyright (C) 2006-2007 Matsushita Electric Industrial Co., Ltd.
4+ * All Rights Reserved.
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version
9+ * 2 of the License, or (at your option) any later version.
10+ *
11+ */
12+
13+#include <linux/sys.h>
14+#include <linux/linkage.h>
15+#include <asm/smp.h>
16+#include <asm/system.h>
17+#include <asm/thread_info.h>
18+#include <asm/cpu-regs.h>
19+#include <proc/smp-regs.h>
20+#include <asm/asm-offsets.h>
21+#include <asm/frame.inc>
22+
23+ .am33_2
24+
25+###############################################################################
26+#
27+# IPI interrupt handler
28+#
29+###############################################################################
30+ .globl mn10300_low_ipi_handler
31+mn10300_low_ipi_handler:
32+ add -4,sp
33+ mov d0,(sp)
34+ movhu (IAGR),d0
35+ and IAGR_GN,d0
36+ lsr 0x2,d0
37+#ifdef CONFIG_MN10300_CACHE_ENABLED
38+ cmp FLUSH_CACHE_IPI,d0
39+ beq mn10300_flush_cache_ipi
40+#endif
41+ cmp SMP_BOOT_IRQ,d0
42+ beq mn10300_smp_boot_ipi
43+ /* OTHERS */
44+ mov (sp),d0
45+ add 4,sp
46+#ifdef CONFIG_GDBSTUB
47+ jmp gdbstub_io_rx_handler
48+#else
49+ jmp end
50+#endif
51+
52+###############################################################################
53+#
54+# Cache flush IPI interrupt handler
55+#
56+###############################################################################
57+#ifdef CONFIG_MN10300_CACHE_ENABLED
58+mn10300_flush_cache_ipi:
59+ mov (sp),d0
60+ add 4,sp
61+
62+ /* FLUSH_CACHE_IPI */
63+ add -4,sp
64+ SAVE_ALL
65+ mov GxICR_DETECT,d2
66+ movbu d2,(GxICR(FLUSH_CACHE_IPI)) # ACK the interrupt
67+ movhu (GxICR(FLUSH_CACHE_IPI)),d2
68+ call smp_cache_interrupt[],0
69+ RESTORE_ALL
70+ jmp end
71+#endif
72+
73+###############################################################################
74+#
75+# SMP boot CPU IPI interrupt handler
76+#
77+###############################################################################
78+mn10300_smp_boot_ipi:
79+ /* clear interrupt */
80+ movhu (GxICR(SMP_BOOT_IRQ)),d0
81+ and ~GxICR_REQUEST,d0
82+ movhu d0,(GxICR(SMP_BOOT_IRQ))
83+ mov (sp),d0
84+ add 4,sp
85+
86+ # get stack
87+ mov (CPUID),a0
88+ add -1,a0
89+ add a0,a0
90+ add a0,a0
91+ mov (start_stack,a0),a0
92+ mov a0,sp
93+ jmp initialize_secondary
94+
95+
96+# Jump here after RTI to suppress the icache lookahead
97+end:
arch/mn10300/kernel/smp.c+1152−0
@@ -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+
45+static unsigned long sleep_mode[NR_CPUS];
46+
47+static void run_sleep_cpu(unsigned int cpu);
48+static void run_wakeup_cpu(unsigned int cpu);
49+#endif /* CONFIG_HOTPLUG_CPU */
50+
51+/*
52+ * Debug Message function
53+ */
54+
55+#undef DEBUG_SMP
56+#ifdef DEBUG_SMP
57+#define Dprintk(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__)
58+#else
59+#define Dprintk(fmt, ...) no_printk(KERN_DEBUG fmt, ##__VA_ARGS__)
60+#endif
61+
62+/* timeout value in msec for smp_nmi_call_function. zero is no timeout. */
63+#define CALL_FUNCTION_NMI_IPI_TIMEOUT 0
64+
65+/*
66+ * Structure and data for smp_nmi_call_function().
67+ */
68+struct nmi_call_data_struct {
69+ smp_call_func_t func;
70+ void *info;
71+ cpumask_t started;
72+ cpumask_t finished;
73+ int wait;
74+ char size_alignment[0]
75+ __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
76+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
77+
78+static DEFINE_SPINLOCK(smp_nmi_call_lock);
79+static struct nmi_call_data_struct *nmi_call_data;
80+
81+/*
82+ * Data structures and variables
83+ */
84+static cpumask_t cpu_callin_map; /* Bitmask of callin CPUs */
85+static cpumask_t cpu_callout_map; /* Bitmask of callout CPUs */
86+cpumask_t cpu_boot_map; /* Bitmask of boot APs */
87+unsigned long start_stack[NR_CPUS - 1];
88+
89+/*
90+ * Per CPU parameters
91+ */
92+struct mn10300_cpuinfo cpu_data[NR_CPUS] __cacheline_aligned;
93+
94+static int cpucount; /* The count of boot CPUs */
95+static cpumask_t smp_commenced_mask;
96+cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
97+
98+/*
99+ * Function Prototypes
100+ */
101+static int do_boot_cpu(int);
102+static void smp_show_cpu_info(int cpu_id);
103+static void smp_callin(void);
104+static void smp_online(void);
105+static void smp_store_cpu_info(int);
106+static void smp_cpu_init(void);
107+static void smp_tune_scheduling(void);
108+static void send_IPI_mask(const cpumask_t *cpumask, int irq);
109+static void init_ipi(void);
110+
111+/*
112+ * IPI Initialization interrupt definitions
113+ */
114+static void mn10300_ipi_disable(unsigned int irq);
115+static void mn10300_ipi_enable(unsigned int irq);
116+static void mn10300_ipi_ack(unsigned int irq);
117+static void mn10300_ipi_nop(unsigned int irq);
118+
119+static struct irq_chip mn10300_ipi_type = {
120+ .name = "cpu_ipi",
121+ .disable = mn10300_ipi_disable,
122+ .enable = mn10300_ipi_enable,
123+ .ack = mn10300_ipi_ack,
124+ .eoi = mn10300_ipi_nop
125+};
126+
127+static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
128+static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id);
129+
130+static struct irqaction reschedule_ipi = {
131+ .handler = smp_reschedule_interrupt,
132+ .name = "smp reschedule IPI"
133+};
134+static 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)
140+static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
141+static 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+ */
151+static 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+ */
207+static 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+ */
225+static 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+ */
243+static 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+ */
264+static 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+ */
279+static 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+ */
292+static 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+ */
314+void 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+ */
327+void 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+
336+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
337+{
338+ BUG();
339+ /*send_IPI_mask(mask, CALL_FUNCTION_IPI);*/
340+}
341+
342+void 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+ */
351+void 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+ */
369+int 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+ */
432+void 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+ */
457+void 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+ */
472+static 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+ */
485+static 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+ */
495+void 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+ */
523+static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id)
524+{
525+ return local_timer_interrupt();
526+}
527+#endif
528+
529+void __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+ */
544+static 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+ */
594+void 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+ */
629+int __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+ */
653+void __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+
680+smp_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+ */
690+static 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+ */
704+static 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+ */
715+static 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+ */
785+static 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+ */
801+static 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+ */
843+static 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+ */
861+void __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+ */
871+void __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+ */
883+void 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+ */
896+int __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+ */
927+int setup_profiling_timer(unsigned int multiplier)
928+{
929+ return -EINVAL;
930+}
931+
932+/*
933+ * CPU hotplug routines
934+ */
935+#ifdef CONFIG_HOTPLUG_CPU
936+
937+static DEFINE_PER_CPU(struct cpu, cpu_devices);
938+
939+static 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+
953+subsys_initcall(topology_init);
954+
955+int __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+
966+void __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
975+static 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+
992+static 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+
1005+static 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+ */
1035+static 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+
1080+static 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+
1090+static 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. */
1100+static 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+
1114+static 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+
1126+static 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+
1134+static 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 */
arch/mn10300/kernel/switch_to.S+3−4
@@ -15,6 +15,9 @@ · 14 unmodified lines
1515 #include <linux/linkage.h>
1616 #include <asm/thread_info.h>
1717 #include <asm/cpu-regs.h>
18+#ifdef CONFIG_SMP
19+#include <proc/smp-regs.h>
20+#endif /* CONFIG_SMP */
1821
1922 .text
2023
@@ -35,8 +38,6 @@ ENTRY(__switch_to) · 14 unmodified lines
3538 mov d1,a1
3639
3740 # save prev context
38− mov (__frame),d0
39− mov d0,(THREAD_FRAME,a0)
4041 mov __switch_back,d0
4142 mov d0,(THREAD_PC,a0)
4243 mov sp,a2
@@ -58,8 +59,6 @@ ENTRY(__switch_to) · 15 unmodified lines
5859 mov a2,e2
5960 #endif
6061
61− mov (THREAD_FRAME,a1),a2
62− mov a2,(__frame)
6362 mov (THREAD_PC,a1),a2
6463 mov d2,d0 # for ret_from_fork
6564 mov d0,a0 # for __switch_to
arch/mn10300/kernel/time.c+85−27
@@ -17,29 +17,18 @@ · 16 unmodified lines
1717 #include <linux/smp.h>
1818 #include <linux/profile.h>
1919 #include <linux/cnt32_to_63.h>
20+#include <linux/clocksource.h>
21+#include <linux/clockchips.h>
2022 #include <asm/irq.h>
2123 #include <asm/div64.h>
2224 #include <asm/processor.h>
2325 #include <asm/intctl-regs.h>
2426 #include <asm/rtc.h>
25−
26−#ifdef CONFIG_MN10300_RTC
27−unsigned long mn10300_ioclk; /* system I/O clock frequency */
28−unsigned long mn10300_iobclk; /* system I/O clock frequency */
29−unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */
30−#endif /* CONFIG_MN10300_RTC */
27+#include "internal.h"
3128
3229 static unsigned long mn10300_last_tsc; /* time-stamp counter at last time
3330 * interrupt occurred */
3431
35−static irqreturn_t timer_interrupt(int irq, void *dev_id);
36−
37−static struct irqaction timer_irq = {
38− .handler = timer_interrupt,
39− .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
40− .name = "timer",
41−};
42−
4332 static unsigned long sched_clock_multiplier;
4433
4534 /*
@@ -54,9 +43,12 @@ unsigned long long sched_clock(void) · 8 unmodified lines
5443 unsigned long tsc, tmp;
5544 unsigned product[3]; /* 96-bit intermediate value */
5645
46+ /* cnt32_to_63() is not safe with preemption */
47+ preempt_disable();
48+
5749 /* read the TSC value
5850 */
59− tsc = 0 - get_cycles(); /* get_cycles() counts down */
51+ tsc = get_cycles();
6052
6153 /* expand to 64-bits.
6254 * - sched_clock() must be called once a minute or better or the
@@ -64,6 +56,8 @@ unsigned long long sched_clock(void) · 1 unmodified line
6456 */
6557 tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
6658
59+ preempt_enable();
60+
6761 /* scale the 64-bit TSC value to a nanosecond value via a 96-bit
6862 * intermediate
6963 */
@@ -90,6 +84,20 @@ static void __init mn10300_sched_clock_init(void) · 20 unmodified lines
9084 __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK);
9185 }
9286
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+ */
93+irqreturn_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
93101 /*
94102 * advance the kernel's time keeping clocks (xtime and jiffies)
95103 * - 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) · 2 unmodified lines
98106 static irqreturn_t timer_interrupt(int irq, void *dev_id)
99107 {
100108 unsigned tsc, elapse;
109+ irqreturn_t ret;
101110
102111 write_seqlock(&xtime_lock);
103112
104113 while (tsc = get_cycles(),
105− elapse = mn10300_last_tsc - tsc, /* time elapsed since last
114+ elapse = tsc - mn10300_last_tsc, /* time elapsed since last
106115 * tick */
107116 elapse > MN10300_TSC_PER_HZ
108117 ) {
109− mn10300_last_tsc -= MN10300_TSC_PER_HZ;
118+ mn10300_last_tsc += MN10300_TSC_PER_HZ;
110119
111120 /* advance the kernel's time tracking system */
112− profile_tick(CPU_PROFILING);
113121 do_timer(1);
114122 }
115123
116124 write_sequnlock(&xtime_lock);
117125
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+}
119132
120− return IRQ_HANDLED;
133+static 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
141+void __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;
121155 }
156+#endif
157+
158+#if CONFIG_CEVT_MN10300
159+void __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
122176
123177 /*
124178 * initialise the various timers used by the main part of the kernel
@@ -131,21 +185,25 @@ void __init time_init(void) · 6 unmodified lines
131185 */
132186 TMPSCNT |= TMPSCNT_ENABLE;
133187
188+#ifdef CONFIG_GENERIC_TIME
189+ init_clocksource();
190+#else
134191 startup_timestamp_counter();
192+#endif
135193
136194 printk(KERN_INFO
137195 "timestamp counter I/O clock running at %lu.%02lu"
138196 " (calibrated against RTC)\n",
139197 MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100);
140198
141− mn10300_last_tsc = TMTSCBC;
142−
143− /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */
144− setup_irq(TMJCIRQ, &timer_irq);
199+ mn10300_last_tsc = read_timestamp_counter();
145200
146− set_intr_level(TMJCIRQ, TMJCICR_LEVEL);
147−
148− startup_jiffies_counter();
201+#ifdef CONFIG_GENERIC_CLOCKEVENTS
202+ init_clockevents();
203+#else
204+ reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
205+ setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL);
206+#endif
149207
150208 #ifdef CONFIG_MN10300_WD_TIMER
151209 /* start the watchdog timer */
arch/mn10300/kernel/traps.c+13−29
@@ -45,9 +45,6 @@ · 44 unmodified lines
4545 #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
4646 #endif
4747
48−struct pt_regs *__frame; /* current frame pointer */
49−EXPORT_SYMBOL(__frame);
50−
5148 int kstack_depth_to_print = 24;
5249
5350 spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
@@ -101,7 +98,6 @@ DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); · 47 unmodified lines
10198 DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
10299 DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
103100 DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
104−DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
105101
106102 DO_ERROR(SIGTRAP,
107103 #ifndef CONFIG_MN10300_USING_JTAG
@@ -222,11 +218,14 @@ void show_registers_only(struct pt_regs *regs) · 114 unmodified lines
222218 printk(KERN_EMERG "threadinfo=%p task=%p)\n",
223219 current_thread_info(), current);
224220
225− if ((unsigned long) current >= 0x90000000UL &&
226− (unsigned long) current < 0x94000000UL)
221+ if ((unsigned long) current >= PAGE_OFFSET &&
222+ (unsigned long) current < (unsigned long)high_memory)
227223 printk(KERN_EMERG "Process %s (pid: %d)\n",
228224 current->comm, current->pid);
229225
226+#ifdef CONFIG_SMP
227+ printk(KERN_EMERG "CPUID: %08x\n", CPUID);
228+#endif
230229 printk(KERN_EMERG "CPUP: %04hx\n", CPUP);
231230 printk(KERN_EMERG "TBR: %08x\n", TBR);
232231 printk(KERN_EMERG "DEAR: %08x\n", DEAR);
@@ -522,8 +521,12 @@ void __init set_intr_stub(enum exception_code code, void *handler) · 289 unmodified lines
522521 {
523522 unsigned long addr;
524523 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
524+ unsigned long flags;
525525
526526 addr = (unsigned long) handler - (unsigned long) vector;
527+
528+ flags = arch_local_cli_save();
529+
527530 vector[0] = 0xdc; /* JMP handler */
528531 vector[1] = addr;
529532 vector[2] = addr >> 8;
@@ -533,30 +536,12 @@ void __init set_intr_stub(enum exception_code code, void *handler) · 3 unmodified lines
533536 vector[6] = 0xcb;
534537 vector[7] = 0xcb;
535538
536− mn10300_dcache_flush_inv();
537− mn10300_icache_inv();
538−}
539−
540−/*
541− * set an interrupt stub to invoke the JTAG unit and then jump to a handler
542− */
543−void __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;
539+ arch_local_irq_restore(flags);
557540
541+#ifndef CONFIG_MN10300_CACHE_SNOOP
558542 mn10300_dcache_flush_inv();
559− flush_icache_range((unsigned long) vector, (unsigned long) vector + 8);
543+ mn10300_icache_inv();
544+#endif
560545 }
561546
562547 /*
@@ -581,7 +566,6 @@ void __init trap_init(void) · 18 unmodified lines
581566 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
582567 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
583568 set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
584− set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
585569 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
586570 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
587571
arch/mn10300/lib/bitops.c+2−2
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515 /*
1616 * try flipping a bit using BSET and BCLR
1717 */
18−void change_bit(int nr, volatile void *addr)
18+void change_bit(unsigned long nr, volatile void *addr)
1919 {
2020 if (test_bit(nr, addr))
2121 goto try_clear_bit;
@@ -34,7 +34,7 @@ try_clear_bit: · 12 unmodified lines
3434 /*
3535 * try flipping a bit using BSET and BCLR and returning the old value
3636 */
37−int test_and_change_bit(int nr, volatile void *addr)
37+int test_and_change_bit(unsigned long nr, volatile void *addr)
3838 {
3939 if (test_bit(nr, addr))
4040 goto try_clear_bit;
arch/mn10300/lib/delay.c+4−4
@@ -38,14 +38,14 @@ EXPORT_SYMBOL(__delay); · 37 unmodified lines
3838 */
3939 void __udelay(unsigned long usecs)
4040 {
41− signed long ioclk, stop;
41+ unsigned long start, stop, cnt;
4242
4343 /* usecs * CLK / 1E6 */
4444 stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
45− stop = TMTSCBC - stop;
45+ start = TMTSCBC;
4646
4747 do {
48− ioclk = TMTSCBC;
49− } while (stop < ioclk);
48+ cnt = start - TMTSCBC;
49+ } while (cnt < stop);
5050 }
5151 EXPORT_SYMBOL(__udelay);
arch/mn10300/lib/do_csum.S+22−27
@@ -10,26 +10,25 @@ · 9 unmodified lines
1010 */
1111 #include <asm/cache.h>
1212
13− .section .text
14− .balign L1_CACHE_BYTES
13+ .section .text
14+ .balign L1_CACHE_BYTES
1515
1616 ###############################################################################
1717 #
18−# unsigned int do_csum(const unsigned char *buff, size_t len)
18+# unsigned int do_csum(const unsigned char *buff, int len)
1919 #
2020 ###############################################################################
2121 .globl do_csum
22− .type do_csum,@function
22+ .type do_csum,@function
2323 do_csum:
2424 movm [d2,d3],(sp)
25− mov d0,(12,sp)
26− mov d1,(16,sp)
2725 mov d1,d2 # count
2826 mov d0,a0 # buff
27+ mov a0,a1
2928 clr d1 # accumulator
3029
3130 cmp +0,d2
32− beq do_csum_done # return if zero-length buffer
31+ ble do_csum_done # check for zero length or negative
3332
3433 # 4-byte align the buffer pointer
3534 btst +3,a0
@@ -41,17 +40,15 @@ do_csum: · 5 unmodified lines
4140 inc a0
4241 asl +8,d0
4342 add d0,d1
44− addc +0,d1
4543 add -1,d2
46−do_csum_addr_not_odd:
4744
45+do_csum_addr_not_odd:
4846 cmp +2,d2
4947 bcs do_csum_fewer_than_4
5048 btst +2,a0
5149 beq do_csum_now_4b_aligned
5250 movhu (a0+),d0
5351 add d0,d1
54− addc +0,d1
5552 add -2,d2
5653 cmp +4,d2
5754 bcs do_csum_fewer_than_4
@@ -66,20 +63,20 @@ do_csum_now_4b_aligned: · 8 unmodified lines
6663
6764 do_csum_loop:
6865 mov (a0+),d0
69− add d0,d1
7066 mov (a0+),e0
71− addc e0,d1
7267 mov (a0+),e1
73− addc e1,d1
7468 mov (a0+),e3
69+ add d0,d1
70+ addc e0,d1
71+ addc e1,d1
7572 addc e3,d1
7673 mov (a0+),d0
77− addc d0,d1
7874 mov (a0+),e0
79− addc e0,d1
8075 mov (a0+),e1
81− addc e1,d1
8276 mov (a0+),e3
77+ addc d0,d1
78+ addc e0,d1
79+ addc e1,d1
8380 addc e3,d1
8481 addc +0,d1
8582
@@ -94,12 +91,12 @@ do_csum_remainder: · 8 unmodified lines
9491 cmp +16,d2
9592 bcs do_csum_fewer_than_16
9693 mov (a0+),d0
97− add d0,d1
9894 mov (a0+),e0
99− addc e0,d1
10095 mov (a0+),e1
101− addc e1,d1
10296 mov (a0+),e3
97+ add d0,d1
98+ addc e0,d1
99+ addc e1,d1
103100 addc e3,d1
104101 addc +0,d1
105102 add -16,d2
@@ -131,9 +128,9 @@ do_csum_fewer_than_4: · 25 unmodified lines
131128 xor_cmp d0,d0,+2,d2
132129 bcs do_csum_fewer_than_2
133130 movhu (a0+),d0
134−do_csum_fewer_than_2:
135131 and +1,d2
136132 beq do_csum_add_last_bit
133+do_csum_fewer_than_2:
137134 movbu (a0),d3
138135 add d3,d0
139136 do_csum_add_last_bit:
@@ -142,21 +139,19 @@ do_csum_add_last_bit: · 2 unmodified lines
142139
143140 do_csum_done:
144141 # compress the checksum down to 16 bits
145− mov +0xffff0000,d2
146− and d1,d2
142+ mov +0xffff0000,d0
143+ and d1,d0
147144 asl +16,d1
148− add d2,d1,d0
145+ add d1,d0
149146 addc +0xffff,d0
150147 lsr +16,d0
151148
152149 # flip the halves of the word result if the buffer was oddly aligned
153− mov (12,sp),d1
154− and +1,d1
150+ and +1,a1
155151 beq do_csum_not_oddly_aligned
156152 swaph d0,d0 # exchange bits 15:8 with 7:0
157153
158154 do_csum_not_oddly_aligned:
159155 ret [d2,d3],8
160156
161−do_csum_end:
162− .size do_csum, do_csum_end-do_csum
157+ .size do_csum, .-do_csum
arch/mn10300/mm/Kconfig.cache+101−0
@@ -0,0 +1,101 @@
1+#
2+# MN10300 CPU cache options
3+#
4+
5+choice
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+
23+config 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+
30+config 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+
41+config MN10300_CACHE_DISABLED
42+ bool "Disabled"
43+ help
44+ The icache and dcache are disabled.
45+
46+endchoice
47+
48+config MN10300_CACHE_ENABLED
49+ def_bool y if !MN10300_CACHE_DISABLED
50+
51+
52+choice
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+
61+config MN10300_CACHE_MANAGE_BY_TAG
62+ bool "Use the cache tag registers directly"
63+ depends on !(SMP && MN10300_CACHE_WTHRU)
64+
65+config MN10300_CACHE_MANAGE_BY_REG
66+ bool "Flush areas by way of automatic purge registers (AM34 only)"
67+ depends on AM34_2
68+
69+endchoice
70+
71+config MN10300_CACHE_INV_BY_TAG
72+ def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED
73+
74+config MN10300_CACHE_INV_BY_REG
75+ def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED
76+
77+config MN10300_CACHE_FLUSH_BY_TAG
78+ def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK
79+
80+config MN10300_CACHE_FLUSH_BY_REG
81+ def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK
82+
83+
84+config MN10300_HAS_CACHE_SNOOP
85+ def_bool n
86+
87+config MN10300_CACHE_SNOOP
88+ bool "Use CPU Cache Snooping"
89+ depends on MN10300_CACHE_ENABLED && MN10300_HAS_CACHE_SNOOP
90+ default y
91+
92+config 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+
97+config 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.
arch/mn10300/mm/Makefile+12−2
@@ -2,11 +2,21 @@ · 1 unmodified line
22 # Makefile for the MN10300-specific memory management code
33 #
44
5−cacheflush-y := cache.o cache-mn10300.o
6−cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o
5+cache-smp-wback-$(CONFIG_MN10300_CACHE_WBACK) := cache-smp-flush.o
6+
7+cacheflush-y := cache.o
8+cacheflush-$(CONFIG_SMP) += cache-smp.o cache-smp-inv.o $(cache-smp-wback-y)
9+cacheflush-$(CONFIG_MN10300_CACHE_INV_ICACHE) += cache-inv-icache.o
10+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_ICACHE) += cache-flush-icache.o
11+cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o
12+cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
13+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
14+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
715
816 cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
917
1018 obj-y := \
1119 init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
1220 misalignment.o dma-alloc.o $(cacheflush-y)
21+
22+obj-$(CONFIG_SMP) += tlb-smp.o
arch/mn10300/mm/cache-flush-by-reg.S+308−0
@@ -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+
31+mn10300_dcache_flush = mn10300_local_dcache_flush
32+mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
33+mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
34+mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
35+mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
36+mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
37+mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
38+mn10300_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
51+mn10300_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+
85+mn10300_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
104+mn10300_local_dcache_flush_page:
105+ and ~(PAGE_SIZE-1),d0
106+ mov PAGE_SIZE,d1
107+mn10300_local_dcache_flush_range2:
108+ add d0,d1
109+mn10300_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
128+1:
129+ add d2,d2
130+ lsr 1,d3
131+ bne 1b
132+2:
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+
152+dcpgloop:
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+
171+mn10300_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
187+mn10300_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+
218+mn10300_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
237+mn10300_local_dcache_flush_inv_page:
238+ and ~(PAGE_SIZE-1),d0
239+ mov PAGE_SIZE,d1
240+mn10300_local_dcache_flush_inv_range2:
241+ add d0,d1
242+mn10300_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
261+1:
262+ add d2,d2
263+ lsr 1,d3
264+ bne 1b
265+2:
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+
285+dcpgivloop:
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+
304+mn10300_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
arch/mn10300/mm/cache-flush-by-tag.S+251−0
@@ -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+
31+mn10300_dcache_flush = mn10300_local_dcache_flush
32+mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
33+mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
34+mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
35+mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
36+mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
37+mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
38+mn10300_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
51+mn10300_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+
63+mn10300_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+
75+mn10300_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
94+mn10300_local_dcache_flush_page:
95+ and ~(PAGE_SIZE-1),d0
96+ mov PAGE_SIZE,d1
97+mn10300_local_dcache_flush_range2:
98+ add d0,d1
99+mn10300_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
112+1:
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+
135+mn10300_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+
145+mn10300_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
161+mn10300_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+
169+mn10300_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+
179+mn10300_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
198+mn10300_local_dcache_flush_inv_page:
199+ and ~(PAGE_SIZE-1),d0
200+ mov PAGE_SIZE,d1
201+mn10300_local_dcache_flush_inv_range2:
202+ add d0,d1
203+mn10300_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
216+1:
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+
237+mn10300_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+
247+mn10300_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
arch/mn10300/mm/cache-flush-icache.c+155−0
@@ -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+ */
25+void 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+}
38+EXPORT_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+ */
50+static 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+ */
108+void 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+
152+done:
153+ smp_unlock_cache(flags);
154+}
155+EXPORT_SYMBOL(flush_icache_range);
arch/mn10300/mm/cache-flush-mn10300.S+0−192
@@ -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
35−mn10300_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−
47−mn10300_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−
54−mn10300_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−
60−mn10300_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
72−mn10300_dcache_flush_page:
73− mov PAGE_SIZE,d1
74−mn10300_dcache_flush_range2:
75− add d0,d1
76−mn10300_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−
104−mn10300_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−
114−mn10300_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
124−mn10300_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−
133−mn10300_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−
140−mn10300_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
152−mn10300_dcache_flush_inv_page:
153− mov PAGE_SIZE,d1
154−mn10300_dcache_flush_inv_range2:
155− add d0,d1
156−mn10300_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−
181−mn10300_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−
191−mn10300_dcache_flush_inv_range_end:
192− ret [d2,d3],8
arch/mn10300/mm/cache-inv-by-reg.S+356−0
@@ -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+
38+mn10300_icache_inv = mn10300_local_icache_inv
39+mn10300_icache_inv_page = mn10300_local_icache_inv_page
40+mn10300_icache_inv_range = mn10300_local_icache_inv_range
41+mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
42+mn10300_dcache_inv = mn10300_local_dcache_inv
43+mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
44+mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
45+mn10300_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
58+mn10300_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+
70+mn10300_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
83+mn10300_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+
95+mn10300_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
114+mn10300_local_dcache_inv_page:
115+ and ~(PAGE_SIZE-1),d0
116+ mov PAGE_SIZE,d1
117+mn10300_local_dcache_inv_range2:
118+ add d0,d1
119+mn10300_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
128+1:
129+ bra mn10300_local_dcache_flush_inv_range
130+2:
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+
169+dcivloop:
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+
186+1:
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+
213+2:
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+
248+mn10300_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
269+mn10300_local_icache_inv_page:
270+ and ~(PAGE_SIZE-1),d0
271+ mov PAGE_SIZE,d1
272+mn10300_local_icache_inv_range2:
273+ add d0,d1
274+mn10300_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
295+1:
296+ add d2,d2
297+ lsr 1,d3
298+ bne 1b
299+2:
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+
325+icivloop:
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+
352+mn10300_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
arch/mn10300/mm/cache-inv-by-tag.S+348−0
@@ -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+
32+mn10300_local_icache_inv_page = mn10300_local_icache_inv
33+mn10300_local_icache_inv_range = mn10300_local_icache_inv
34+mn10300_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+
46+mn10300_icache_inv = mn10300_local_icache_inv
47+mn10300_icache_inv_page = mn10300_local_icache_inv_page
48+mn10300_icache_inv_range = mn10300_local_icache_inv_range
49+mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
50+mn10300_dcache_inv = mn10300_local_dcache_inv
51+mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
52+mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
53+mn10300_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
66+mn10300_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+
111+mn10300_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
124+mn10300_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+
169+mn10300_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
188+mn10300_local_dcache_inv_page:
189+ and ~(PAGE_SIZE-1),d0
190+ mov PAGE_SIZE,d1
191+mn10300_local_dcache_inv_range2:
192+ add d0,d1
193+mn10300_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
202+1:
203+ bra mn10300_local_dcache_flush_inv_range
204+2:
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+
240+mn10300_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+
254+mn10300_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+
268+mn10300_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+
282+mn10300_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+
296+mn10300_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+
310+mn10300_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+
344+mn10300_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
arch/mn10300/mm/cache-inv-icache.c+129−0
@@ -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+ */
28+static 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+ */
84+void 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+
126+done:
127+ smp_unlock_cache(flags);
128+}
129+EXPORT_SYMBOL(flush_icache_range);
arch/mn10300/mm/cache-mn10300.S+0−289
@@ -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
39−mn10300_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−
80−mn10300_icache_inv_end:
81− ret [],0
82−
83−###############################################################################
84−#
85−# void mn10300_dcache_inv(void)
86−# Invalidate the entire dcache
87−#
88−###############################################################################
89− ALIGN
90−mn10300_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−
131−mn10300_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
143−mn10300_dcache_inv_page:
144− mov PAGE_SIZE,d1
145−mn10300_dcache_inv_range2:
146− add d0,d1
147−mn10300_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−
179−mn10300_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−
199−mn10300_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−
213−mn10300_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−
227−mn10300_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−
241−mn10300_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−
255−mn10300_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−
288−mn10300_dcache_inv_range_end:
289− ret [d2,d3,a2],12
arch/mn10300/mm/cache-smp-flush.c+156−0
@@ -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+ */
20+void 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+ */
37+void 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+ */
57+void 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+ */
75+void 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+ */
90+void 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+ */
108+void 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+ */
129+void 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+ */
148+void 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+}
arch/mn10300/mm/cache-smp-inv.c+153−0
@@ -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+ */
20+void 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+ */
37+void 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+ */
57+void 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+ */
75+void 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+ */
90+void 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+ */
107+void 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+ */
127+void 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+ */
145+void 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+}
arch/mn10300/mm/cache-smp.c+105−0
@@ -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+
25+DEFINE_SPINLOCK(smp_cache_lock);
26+static unsigned long smp_cache_mask;
27+static unsigned long smp_cache_start;
28+static unsigned long smp_cache_end;
29+static 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+ */
37+void 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+ */
91+void 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+}
arch/mn10300/mm/cache-smp.h+69−0
@@ -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+ */
18+enum 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+
25+enum 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
43+extern spinlock_t smp_cache_lock;
44+
45+extern void smp_cache_call(unsigned long opr_mask,
46+ unsigned long addr, unsigned long end);
47+
48+static 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+
56+static 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
63+static inline unsigned long smp_lock_cache(void) { return 0; }
64+static inline void smp_unlock_cache(unsigned long flags) {}
65+static inline void smp_cache_call(unsigned long opr_mask,
66+ unsigned long addr, unsigned long end)
67+{
68+}
69+#endif /* CONFIG_SMP */
arch/mn10300/mm/cache.c+5−90
@@ -18,8 +18,13 @@ · 17 unmodified lines
1818 #include <asm/cacheflush.h>
1919 #include <asm/io.h>
2020 #include <asm/uaccess.h>
21+#include <asm/smp.h>
22+#include "cache-smp.h"
2123
2224 EXPORT_SYMBOL(mn10300_icache_inv);
25+EXPORT_SYMBOL(mn10300_icache_inv_range);
26+EXPORT_SYMBOL(mn10300_icache_inv_range2);
27+EXPORT_SYMBOL(mn10300_icache_inv_page);
2328 EXPORT_SYMBOL(mn10300_dcache_inv);
2429 EXPORT_SYMBOL(mn10300_dcache_inv_range);
2530 EXPORT_SYMBOL(mn10300_dcache_inv_range2);
@@ -36,96 +41,6 @@ EXPORT_SYMBOL(mn10300_dcache_flush_range2); · 10 unmodified lines
3641 EXPORT_SYMBOL(mn10300_dcache_flush_page);
3742 #endif
3843
39−/*
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− */
43−void 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−}
48−EXPORT_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− */
54−void 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−
124−invalidate:
125− mn10300_icache_inv();
126−}
127−EXPORT_SYMBOL(flush_icache_range);
128−
12944 /*
13045 * allow userspace to flush the instruction cache
13146 */
arch/mn10300/mm/fault.c+4−13
@@ -39,10 +39,6 @@ void bust_spinlocks(int yes) · 38 unmodified lines
3939 {
4040 if (yes) {
4141 oops_in_progress = 1;
42−#ifdef CONFIG_SMP
43− /* Many serial drivers do __global_cli() */
44− global_irq_lock = 0;
45−#endif
4642 } else {
4743 int loglevel_save = console_loglevel;
4844 #ifdef CONFIG_VT
@@ -100,8 +96,6 @@ static void print_pagetable_entries(pgd_t *pgdir, unsigned long address) · 51 unmodified lines
10096 }
10197 #endif
10298
103−asmlinkage void monitor_signal(struct pt_regs *);
104−
10599 /*
106100 * This routine handles page faults. It determines the address,
107101 * and the problem, and then passes it off to one of the appropriate
@@ -279,7 +273,6 @@ good_area: · 171 unmodified lines
279273 */
280274 bad_area:
281275 up_read(&mm->mmap_sem);
282− monitor_signal(regs);
283276
284277 /* User mode accesses just cause a SIGSEGV */
285278 if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
@@ -292,7 +285,6 @@ bad_area: · 6 unmodified lines
292285 }
293286
294287 no_context:
295− monitor_signal(regs);
296288 /* Are we prepared to handle this kernel fault? */
297289 if (fixup_exception(regs))
298290 return;
@@ -338,14 +330,13 @@ no_context: · 39 unmodified lines
338330 */
339331 out_of_memory:
340332 up_read(&mm->mmap_sem);
341− if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR)
342− goto no_context;
343− pagefault_out_of_memory();
344− return;
333+ printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
334+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
335+ do_exit(SIGKILL);
336+ goto no_context;
345337
346338 do_sigbus:
347339 up_read(&mm->mmap_sem);
348− monitor_signal(regs);
349340
350341 /*
351342 * Send a sigbus, regardless of whether we were in kernel
arch/mn10300/mm/init.c+23−3
@@ -41,6 +41,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); · 40 unmodified lines
4141
4242 unsigned long highstart_pfn, highend_pfn;
4343
44+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
45+static struct vm_struct user_iomap_vm;
46+#endif
47+
4448 /*
4549 * set up paging
4650 */
@@ -73,7 +77,24 @@ void __init paging_init(void) · 26 unmodified lines
7377 /* pass the memory from the bootmem allocator to the main allocator */
7478 free_area_init(zones_size);
7579
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();
7798 }
7899
79100 /*
@@ -84,8 +105,7 @@ void __init mem_init(void) · 4 unmodified lines
84105 int codesize, reservedpages, datasize, initsize;
85106 int tmp;
86107
87− if (!mem_map)
88− BUG();
108+ BUG_ON(!mem_map);
89109
90110 #define START_PFN (contig_page_data.bdata->node_min_pfn)
91111 #define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn)
arch/mn10300/mm/misalignment.c+1−2
@@ -449,8 +449,7 @@ found_opcode: · 448 unmodified lines
449449 regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
450450
451451 tmp = format_tbl[pop->format].opsz;
452− if (tmp > noc)
453− BUG(); /* match was less complete than it ought to have been */
452+ BUG_ON(tmp > noc); /* match was less complete than it ought to have been */
454453
455454 if (tmp < noc) {
456455 tmp = noc - tmp;
arch/mn10300/mm/mmu-context.c+11−30
@@ -13,40 +13,15 @@ · 12 unmodified lines
1313 #include <asm/mmu_context.h>
1414 #include <asm/tlbflush.h>
1515
16+#ifdef CONFIG_MN10300_TLB_USE_PIDR
1617 /*
1718 * list of the MMU contexts last allocated on each CPU
1819 */
1920 unsigned 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),
2123 };
22−
23−/*
24− * flush the specified TLB entry
25− */
26−void 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−}
24+#endif /* CONFIG_MN10300_TLB_USE_PIDR */
5025
5126 /*
5227 * preemptively set a TLB entry
@@ -63,10 +38,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *pte · 10 unmodified lines
6338 * interference from vmalloc'd regions */
6439 local_irq_save(flags);
6540
41+ cnx = ~MMU_NO_CONTEXT;
42+#ifdef CONFIG_MN10300_TLB_USE_PIDR
6643 cnx = mm_context(vma->vm_mm);
44+#endif
6745
6846 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
7051 if (!(pte_val(pte) & _PAGE_NX)) {
7152 IPTEU = pteu;
7253 if (IPTEL & xPTEL_V)
arch/mn10300/mm/pgtable.c+1−1
@@ -59,7 +59,7 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) · 58 unmodified lines
5959 * It's enough to flush this one mapping.
6060 * (PGE mappings get flushed as well)
6161 */
62− __flush_tlb_one(vaddr);
62+ local_flush_tlb_one(vaddr);
6363 }
6464
6565 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
arch/mn10300/mm/tlb-mn10300.S+45−14
@@ -27,7 +27,6 @@ · 26 unmodified lines
2727 ###############################################################################
2828 .type itlb_miss,@function
2929 ENTRY(itlb_miss)
30− and ~EPSW_NMID,epsw
3130 #ifdef CONFIG_GDBSTUB
3231 movm [d2,d3,a2],(sp)
3332 #else
@@ -38,6 +37,12 @@ ENTRY(itlb_miss) · 4 unmodified lines
3837 nop
3938 #endif
4039
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
4146 mov (IPTEU),d3
4247 mov (PTBR),a2
4348 mov d3,d2
@@ -56,10 +61,16 @@ ENTRY(itlb_miss) · 12 unmodified lines
5661 btst _PAGE_VALID,d2
5762 beq itlb_miss_fault # jump if doesn't point to a page
5863 # (might be a swap id)
64+#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
5965 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
6172 itlb_miss_set:
62− mov d2,(IPTEL) # change the TLB
73+ mov d2,(IPTEL2) # change the TLB
6374 #ifdef CONFIG_GDBSTUB
6475 movm (sp),[d2,d3,a2]
6576 #endif
@@ -79,7 +90,6 @@ itlb_miss_fault: · 13 unmodified lines
7990 ###############################################################################
8091 .type dtlb_miss,@function
8192 ENTRY(dtlb_miss)
82− and ~EPSW_NMID,epsw
8393 #ifdef CONFIG_GDBSTUB
8494 movm [d2,d3,a2],(sp)
8595 #else
@@ -90,6 +100,12 @@ ENTRY(dtlb_miss) · 4 unmodified lines
90100 nop
91101 #endif
92102
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
93109 mov (DPTEU),d3
94110 mov (PTBR),a2
95111 mov d3,d2
@@ -108,10 +124,16 @@ ENTRY(dtlb_miss) · 12 unmodified lines
108124 btst _PAGE_VALID,d2
109125 beq dtlb_miss_fault # jump if doesn't point to a page
110126 # (might be a swap id)
127+#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
111128 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
113135 dtlb_miss_set:
114− mov d2,(DPTEL) # change the TLB
136+ mov d2,(DPTEL2) # change the TLB
115137 #ifdef CONFIG_GDBSTUB
116138 movm (sp),[d2,d3,a2]
117139 #endif
@@ -130,9 +152,15 @@ dtlb_miss_fault: · 12 unmodified lines
130152 ###############################################################################
131153 .type itlb_aerror,@function
132154 ENTRY(itlb_aerror)
133− and ~EPSW_NMID,epsw
134155 add -4,sp
135156 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
136164 add -4,sp # need to pass three params
137165
138166 # calculate the fault code
@@ -140,15 +168,13 @@ ENTRY(itlb_aerror) · 1 unmodified line
140168 or 0x00010000,d1 # it's an instruction fetch
141169
142170 # determine the page address
143− mov (IPTEU),a2
144− mov a2,d0
171+ mov (IPTEU),d0
145172 and PAGE_MASK,d0
146173 mov d0,(12,sp)
147174
148175 clr d0
149− mov d0,(IPTEL)
176+ mov d0,(IPTEL2)
150177
151− and ~EPSW_NMID,epsw
152178 or EPSW_IE,epsw
153179 mov fp,d0
154180 call do_page_fault[],0 # do_page_fault(regs,code,addr
@@ -163,10 +189,16 @@ ENTRY(itlb_aerror) · 8 unmodified lines
163189 ###############################################################################
164190 .type dtlb_aerror,@function
165191 ENTRY(dtlb_aerror)
166− and ~EPSW_NMID,epsw
167192 add -4,sp
168193 SAVE_ALL
194+
195+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
196+ mov (MMUCTR),d1
197+ mov d1,(MMUCTR)
198+#endif
199+
169200 add -4,sp # need to pass three params
201+ and ~EPSW_NMID,epsw
170202
171203 # calculate the fault code
172204 movhu (MMUFCR_DFC),d1
@@ -178,9 +210,8 @@ ENTRY(dtlb_aerror) · 5 unmodified lines
178210 mov d0,(12,sp)
179211
180212 clr d0
181− mov d0,(DPTEL)
213+ mov d0,(DPTEL2)
182214
183− and ~EPSW_NMID,epsw
184215 or EPSW_IE,epsw
185216 mov fp,d0
186217 call do_page_fault[],0 # do_page_fault(regs,code,addr
arch/mn10300/mm/tlb-smp.c+214−0
@@ -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+
44+static cpumask_t flush_cpumask;
45+static struct mm_struct *flush_mm;
46+static unsigned long flush_va;
47+static DEFINE_SPINLOCK(tlbstate_lock);
48+
49+DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
50+ &init_mm, 0
51+};
52+
53+static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
54+ unsigned long va);
55+static void do_flush_tlb_all(void *info);
56+
57+/**
58+ * smp_flush_tlb - Callback to invalidate the TLB.
59+ * @unused: Callback context (ignored).
60+ */
61+void 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();
85+out:
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+ */
95+static 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+ */
144+void 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+ */
162+void 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+ */
183+void 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+ */
203+static 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+ */
211+void flush_tlb_all(void)
212+{
213+ on_each_cpu(do_flush_tlb_all, 0, 1);
214+}
arch/mn10300/proc-mn103e010/include/proc/cache.h+9−0
@@ -30,4 +30,13 @@ · 29 unmodified lines
3030 */
3131 #define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4
3232
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+
3342 #endif /* _ASM_PROC_CACHE_H */
arch/mn10300/proc-mn103e010/include/proc/clock.h+0−2
@@ -13,6 +13,4 @@ · 12 unmodified lines
1313
1414 #include <unit/clock.h>
1515
16−#define MN10300_WDCLK MN10300_IOCLK
17−
1816 #endif /* _ASM_PROC_CLOCK_H */
arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h+102−0
@@ -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+
90+struct 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 */
arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h+29−0
@@ -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 */
arch/mn10300/proc-mn103e010/include/proc/proc.h+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
1212 #ifndef _ASM_PROC_PROC_H
1313 #define _ASM_PROC_PROC_H
1414
15−#define PROCESSOR_VENDOR_NAME "Matsushita"
15+#define PROCESSOR_VENDOR_NAME "Panasonic"
1616 #define PROCESSOR_MODEL_NAME "mn103e010"
1717
1818 #endif /* _ASM_PROC_PROC_H */
arch/mn10300/proc-mn103e010/proc-init.c+37−0
@@ -9,7 +9,9 @@ · 8 unmodified lines
99 * 2 of the Licence, or (at your option) any later version.
1010 */
1111 #include <linux/kernel.h>
12+#include <asm/fpu.h>
1213 #include <asm/rtc.h>
14+#include <asm/busctl-regs.h>
1315
1416 /*
1517 * initialise the on-silicon processor peripherals
@@ -28,6 +30,7 @@ asmlinkage void __init processor_init(void) · 12 unmodified lines
2830 __set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
2931 __set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
3032 __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
33+ __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled);
3134 __set_intr_stub(EXCEP_SYSCALL0, system_call);
3235
3336 __set_intr_stub(EXCEP_NMI, nmi_handler);
@@ -73,3 +76,37 @@ asmlinkage void __init processor_init(void) · 39 unmodified lines
7376
7477 calibrate_clock();
7578 }
79+
80+/*
81+ * determine the memory size and base from the memory controller regs
82+ */
83+void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
84+{
85+ unsigned long base, size;
86+
87+ *mem_base = 0;
88+ *mem_size = 0;
89+
90+ base = SDBASE(0);
91+ if (base & SDBASE_CE) {
92+ size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
93+ size = ~size + 1;
94+ base &= SDBASE_CBA;
95+
96+ printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
97+ *mem_size += size;
98+ *mem_base = base;
99+ }
100+
101+ base = SDBASE(1);
102+ if (base & SDBASE_CE) {
103+ size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
104+ size = ~size + 1;
105+ base &= SDBASE_CBA;
106+
107+ printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
108+ *mem_size += size;
109+ if (*mem_base == 0)
110+ *mem_base = base;
111+ }
112+}
arch/mn10300/proc-mn2ws0050/Makefile+5−0
@@ -0,0 +1,5 @@
1+#
2+# Makefile for the linux kernel.
3+#
4+
5+obj-y := proc-init.o
arch/mn10300/proc-mn2ws0050/include/proc/cache.h+48−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/include/proc/clock.h+20−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h+103−0
@@ -0,0 +1,103 @@
1+/* MN2WS0050 on-board DMA controller registers
2+ *
3+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4+ * Written by David Howells (dhowells@redhat.com)
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * version 2 as published by the Free Software Foundation.
9+ */
10+
11+#ifndef _ASM_PROC_DMACTL_REGS_H
12+#define _ASM_PROC_DMACTL_REGS_H
13+
14+#include <asm/cpu-regs.h>
15+
16+#ifdef __KERNEL__
17+
18+/* DMA registers */
19+#define DMxCTR(N) __SYSREG(0xd4005000+(N*0x100), u32) /* control reg */
20+#define DMxCTR_BG 0x0000001f /* transfer request source */
21+#define DMxCTR_BG_SOFT 0x00000000 /* - software source */
22+#define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */
23+#define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */
24+#define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */
25+#define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */
26+#define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */
27+#define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */
28+#define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */
29+#define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */
30+#define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */
31+#define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */
32+#define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */
33+#define DMxCTR_BG_RYBY 0x0000000d /* - NAND Flash RY/BY request source */
34+#define DMxCTR_BG_RMC 0x0000000e /* - remote controller output */
35+#define DMxCTR_BG_XIRQ12 0x00000011 /* - XIRQ12 pin interrupt source */
36+#define DMxCTR_BG_XIRQ13 0x00000012 /* - XIRQ13 pin interrupt source */
37+#define DMxCTR_BG_TCK 0x00000014 /* - tick timer underflow */
38+#define DMxCTR_BG_SC4TX 0x00000019 /* - serial port4 transmission */
39+#define DMxCTR_BG_SC4RX 0x0000001a /* - serial port4 reception */
40+#define DMxCTR_BG_SC5TX 0x0000001b /* - serial port5 transmission */
41+#define DMxCTR_BG_SC5RX 0x0000001c /* - serial port5 reception */
42+#define DMxCTR_BG_SC6TX 0x0000001d /* - serial port6 transmission */
43+#define DMxCTR_BG_SC6RX 0x0000001e /* - serial port6 reception */
44+#define DMxCTR_BG_TMSUFLOW 0x0000001f /* - timestamp timer underflow */
45+#define DMxCTR_SAM 0x00000060 /* DMA transfer src addr mode */
46+#define DMxCTR_SAM_INCR 0x00000000 /* - increment */
47+#define DMxCTR_SAM_DECR 0x00000020 /* - decrement */
48+#define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */
49+#define DMxCTR_DAM 0x00000300 /* DMA transfer dest addr mode */
50+#define DMxCTR_DAM_INCR 0x00000000 /* - increment */
51+#define DMxCTR_DAM_DECR 0x00000100 /* - decrement */
52+#define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */
53+#define DMxCTR_UT 0x00006000 /* DMA transfer unit */
54+#define DMxCTR_UT_1 0x00000000 /* - 1 byte */
55+#define DMxCTR_UT_2 0x00002000 /* - 2 byte */
56+#define DMxCTR_UT_4 0x00004000 /* - 4 byte */
57+#define DMxCTR_UT_16 0x00006000 /* - 16 byte */
58+#define DMxCTR_RRE 0x00008000 /* DMA round robin enable */
59+#define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */
60+#define DMxCTR_RQM 0x00060000 /* external request input source mode */
61+#define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */
62+#define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */
63+#define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */
64+#define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */
65+#define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */
66+#define DMxCTR_PERR 0x40000000 /* DMA transfer parameter error flag */
67+#define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */
68+
69+#define DMxSRC(N) __SYSREG(0xd4005004+(N*0x100), u32) /* control reg */
70+
71+#define DMxDST(N) __SYSREG(0xd4005008+(N*0x100), u32) /* source addr reg */
72+
73+#define DMxSIZ(N) __SYSREG(0xd400500c+(N*0x100), u32) /* dest addr reg */
74+#define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */
75+
76+#define DMxCYC(N) __SYSREG(0xd4005010+(N*0x100), u32) /* intermittent size reg */
77+#define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */
78+
79+#define DM0IRQ 16 /* DMA channel 0 complete IRQ */
80+#define DM1IRQ 17 /* DMA channel 1 complete IRQ */
81+#define DM2IRQ 18 /* DMA channel 2 complete IRQ */
82+#define DM3IRQ 19 /* DMA channel 3 complete IRQ */
83+
84+#define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */
85+#define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */
86+#define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */
87+#define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */
88+
89+#ifndef __ASSEMBLY__
90+
91+struct mn10300_dmactl_regs {
92+ u32 ctr;
93+ const void *src;
94+ void *dst;
95+ u32 siz;
96+ u32 cyc;
97+} __attribute__((aligned(0x100)));
98+
99+#endif /* __ASSEMBLY__ */
100+
101+#endif /* __KERNEL__ */
102+
103+#endif /* _ASM_PROC_DMACTL_REGS_H */
arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h+29−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/include/proc/irq.h+49−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h+120−0
@@ -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_ */
arch/mn10300/proc-mn2ws0050/include/proc/proc.h+18−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h+51−0
@@ -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 */
arch/mn10300/proc-mn2ws0050/proc-init.c+134−0
@@ -0,0 +1,134 @@
1+/* MN2WS0050 processor initialisation
2+ *
3+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4+ * Written by David Howells (dhowells@redhat.com)
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version
9+ * 2 of the License, or (at your option) any later version.
10+ */
11+#include <linux/sched.h>
12+#include <linux/kernel.h>
13+#include <linux/init.h>
14+#include <linux/delay.h>
15+#include <linux/interrupt.h>
16+
17+#include <asm/processor.h>
18+#include <asm/system.h>
19+#include <asm/uaccess.h>
20+#include <asm/io.h>
21+#include <asm/atomic.h>
22+#include <asm/smp.h>
23+#include <asm/pgalloc.h>
24+#include <asm/busctl-regs.h>
25+#include <unit/timex.h>
26+#include <asm/fpu.h>
27+#include <asm/rtc.h>
28+
29+#define MEMCONF __SYSREGC(0xdf800400, u32)
30+
31+/*
32+ * initialise the on-silicon processor peripherals
33+ */
34+asmlinkage void __init processor_init(void)
35+{
36+ int loop;
37+
38+ /* set up the exception table first */
39+ for (loop = 0x000; loop < 0x400; loop += 8)
40+ __set_intr_stub(loop, __common_exception);
41+
42+ __set_intr_stub(EXCEP_ITLBMISS, itlb_miss);
43+ __set_intr_stub(EXCEP_DTLBMISS, dtlb_miss);
44+ __set_intr_stub(EXCEP_IAERROR, itlb_aerror);
45+ __set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
46+ __set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
47+ __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
48+ __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled);
49+ __set_intr_stub(EXCEP_SYSCALL0, system_call);
50+
51+ __set_intr_stub(EXCEP_NMI, nmi_handler);
52+ __set_intr_stub(EXCEP_WDT, nmi_handler);
53+ __set_intr_stub(EXCEP_IRQ_LEVEL0, irq_handler);
54+ __set_intr_stub(EXCEP_IRQ_LEVEL1, irq_handler);
55+ __set_intr_stub(EXCEP_IRQ_LEVEL2, irq_handler);
56+ __set_intr_stub(EXCEP_IRQ_LEVEL3, irq_handler);
57+ __set_intr_stub(EXCEP_IRQ_LEVEL4, irq_handler);
58+ __set_intr_stub(EXCEP_IRQ_LEVEL5, irq_handler);
59+ __set_intr_stub(EXCEP_IRQ_LEVEL6, irq_handler);
60+
61+ IVAR0 = EXCEP_IRQ_LEVEL0;
62+ IVAR1 = EXCEP_IRQ_LEVEL1;
63+ IVAR2 = EXCEP_IRQ_LEVEL2;
64+ IVAR3 = EXCEP_IRQ_LEVEL3;
65+ IVAR4 = EXCEP_IRQ_LEVEL4;
66+ IVAR5 = EXCEP_IRQ_LEVEL5;
67+ IVAR6 = EXCEP_IRQ_LEVEL6;
68+
69+#ifndef CONFIG_MN10300_HAS_CACHE_SNOOP
70+ mn10300_dcache_flush_inv();
71+ mn10300_icache_inv();
72+#endif
73+
74+ /* disable all interrupts and set to priority 6 (lowest) */
75+#ifdef CONFIG_SMP
76+ for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
77+ GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
78+#else /* !CONFIG_SMP */
79+ for (loop = 0; loop < NR_IRQS; loop++)
80+ GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
81+#endif /* !CONFIG_SMP */
82+
83+ /* clear the timers */
84+ TM0MD = 0;
85+ TM1MD = 0;
86+ TM2MD = 0;
87+ TM3MD = 0;
88+ TM4MD = 0;
89+ TM5MD = 0;
90+ TM6MD = 0;
91+ TM6MDA = 0;
92+ TM6MDB = 0;
93+ TM7MD = 0;
94+ TM8MD = 0;
95+ TM9MD = 0;
96+ TM10MD = 0;
97+ TM11MD = 0;
98+ TM12MD = 0;
99+ TM13MD = 0;
100+ TM14MD = 0;
101+ TM15MD = 0;
102+
103+ calibrate_clock();
104+}
105+
106+/*
107+ * determine the memory size and base from the memory controller regs
108+ */
109+void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
110+{
111+ unsigned long memconf = MEMCONF;
112+ unsigned long size = 0; /* order: MByte */
113+
114+ *mem_base = 0x90000000; /* fixed address */
115+
116+ switch (memconf & 0x00000003) {
117+ case 0x01:
118+ size = 256 / 8; /* 256 Mbit per chip */
119+ break;
120+ case 0x02:
121+ size = 512 / 8; /* 512 Mbit per chip */
122+ break;
123+ case 0x03:
124+ size = 1024 / 8; /* 1 Gbit per chip */
125+ break;
126+ default:
127+ panic("Invalid SDRAM size");
128+ break;
129+ }
130+
131+ printk(KERN_INFO "DDR2-SDRAM: %luMB x 2 @%08lx\n", size, *mem_base);
132+
133+ *mem_size = (size * 2) << 20;
134+}
arch/mn10300/unit-asb2303/include/unit/clock.h+2−23
@@ -14,32 +14,11 @@ · 13 unmodified lines
1414
1515 #ifndef __ASSEMBLY__
1616
17−#ifdef CONFIG_MN10300_RTC
18−
19−extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
20−extern unsigned long mn10300_iobclk;
21−extern unsigned long mn10300_tsc_per_HZ;
22−
23−#define MN10300_IOCLK mn10300_ioclk
24−/* If this processors has a another clock, uncomment the below. */
25−/* #define MN10300_IOBCLK mn10300_iobclk */
26−
27−#else /* !CONFIG_MN10300_RTC */
28−
2917 #define MN10300_IOCLK 33333333UL
3018 /* #define MN10300_IOBCLK 66666666UL */
3119
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−
4320 #endif /* !__ASSEMBLY__ */
4421
22+#define MN10300_WDCLK MN10300_IOCLK
23+
4524 #endif /* _ASM_UNIT_CLOCK_H */
arch/mn10300/unit-asb2303/include/unit/serial.h+5−0
@@ -21,6 +21,11 @@ · 20 unmodified lines
2121
2222 #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */
2323
24+/*
25+ * The ASB2303 has an 18.432 MHz clock the UART
26+ */
27+#define BASE_BAUD (18432000 / 16)
28+
2429 /*
2530 * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
2631 */
arch/mn10300/unit-asb2303/include/unit/timex.h+62−47
@@ -1,6 +1,6 @@
1−/* ASB2303-specific timer specifcations
1+/* ASB2303-specific timer specifications
22 *
3− * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
3+ * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved.
44 * Written by David Howells (dhowells@redhat.com)
55 *
66 * This program is free software; you can redistribute it and/or
@@ -17,67 +17,72 @@ · 10 unmodified lines
1717
1818 #include <asm/timer-regs.h>
1919 #include <unit/clock.h>
20+#include <asm/param.h>
2021
2122 /*
2223 * jiffies counter specifications
2324 */
2425
2526 #define TMJCBR_MAX 0xffff
26−#define TMJCBC TM01BC
27−
28−#define TMJCMD TM01MD
29−#define TMJCBR TM01BR
3027 #define TMJCIRQ TM1IRQ
3128 #define TMJCICR TM1ICR
32−#define TMJCICR_LEVEL GxICR_LEVEL_5
3329
3430 #ifndef __ASSEMBLY__
3531
36−static 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+
60+static inline void stop_jiffies_counter(void)
3761 {
38− unsigned rate;
39− u16 md, t16;
40−
41− /* use as little prescaling as possible to avoid losing accuracy */
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− }
62+ u16 tmp;
63+ TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
64+ tmp = TM01MD;
65+}
5766
58− TMJCBR = rate - 1;
59− t16 = TMJCBR;
67+static inline void reload_jiffies_counter(u32 cnt)
68+{
69+ u32 tmp;
6070
61− TMJCMD =
62− md |
63− TM1MD_SRC_TM0CASCADE << 8 |
64− TM0MD_INIT_COUNTER |
65− TM1MD_INIT_COUNTER << 8;
71+ TM01BR = cnt;
72+ tmp = TM01BR;
6673
67− TMJCMD =
68− md |
69− TM1MD_SRC_TM0CASCADE << 8 |
70− TM0MD_COUNT_ENABLE |
71− TM1MD_COUNT_ENABLE << 8;
74+ TM01MD = JC_TIMER_CLKSRC | \
75+ TM1MD_SRC_TM0CASCADE << 8 | \
76+ TM0MD_INIT_COUNTER | \
77+ TM1MD_INIT_COUNTER << 8;
7278
73− t16 = TMJCMD;
7479
75− TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
76− t16 = TMJCICR;
77−}
80+ TM01MD = JC_TIMER_CLKSRC | \
81+ TM1MD_SRC_TM0CASCADE << 8 | \
82+ TM0MD_COUNT_ENABLE | \
83+ TM1MD_COUNT_ENABLE << 8;
7884
79−static inline void shutdown_jiffies_counter(void)
80−{
85+ tmp = TM01MD;
8186 }
8287
8388 #endif /* !__ASSEMBLY__ */
@@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void) · 10 unmodified lines
9499
95100 static inline void startup_timestamp_counter(void)
96101 {
102+ u32 t32;
103+
97104 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
98105 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
99106 */
100107 TM45BR = TMTSCBR_MAX;
108+ t32 = TM45BR;
101109
102− TM4MD = TM4MD_SRC_IOCLK;
110+ TM4MD = TSC_TIMER_CLKSRC;
103111 TM4MD |= TM4MD_INIT_COUNTER;
104112 TM4MD &= ~TM4MD_INIT_COUNTER;
105113 TM4ICR = 0;
114+ t32 = TM4ICR;
106115
107116 TM5MD = TM5MD_SRC_TM4CASCADE;
108117 TM5MD |= TM5MD_INIT_COUNTER;
109118 TM5MD &= ~TM5MD_INIT_COUNTER;
110119 TM5ICR = 0;
120+ t32 = TM5ICR;
111121
112122 TM5MD |= TM5MD_COUNT_ENABLE;
113123 TM4MD |= TM4MD_COUNT_ENABLE;
124+ t32 = TM5MD;
125+ t32 = TM4MD;
114126 }
115127
116128 static inline void shutdown_timestamp_counter(void)
117129 {
130+ u8 t8;
118131 TM4MD = 0;
119132 TM5MD = 0;
133+ t8 = TM4MD;
134+ t8 = TM5MD;
120135 }
121136
122137 /*
@@ -127,7 +142,7 @@ typedef unsigned long cycles_t; · 4 unmodified lines
127142
128143 static inline cycles_t read_timestamp_counter(void)
129144 {
130− return (cycles_t)TMTSCBC;
145+ return (cycles_t)~TMTSCBC;
131146 }
132147
133148 #endif /* !__ASSEMBLY__ */
arch/mn10300/unit-asb2303/unit-init.c+9−1
@@ -31,6 +31,14 @@ asmlinkage void __init unit_init(void) · 30 unmodified lines
3131 SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL);
3232 SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL);
3333 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
3442 }
3543
3644 /*
@@ -51,7 +59,7 @@ void __init unit_init_IRQ(void) · 14 unmodified lines
5159 switch (GET_XIRQ_TRIGGER(extnum)) {
5260 case XIRQ_TRIGGER_HILEVEL:
5361 case XIRQ_TRIGGER_LOWLEVEL:
54− set_intr_postackable(XIRQ2IRQ(extnum));
62+ mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
5563 break;
5664 default:
5765 break;
arch/mn10300/unit-asb2305/include/unit/clock.h+2−23
@@ -14,32 +14,11 @@ · 13 unmodified lines
1414
1515 #ifndef __ASSEMBLY__
1616
17−#ifdef CONFIG_MN10300_RTC
18−
19−extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
20−extern unsigned long mn10300_iobclk;
21−extern unsigned long mn10300_tsc_per_HZ;
22−
23−#define MN10300_IOCLK mn10300_ioclk
24−/* If this processors has a another clock, uncomment the below. */
25−/* #define MN10300_IOBCLK mn10300_iobclk */
26−
27−#else /* !CONFIG_MN10300_RTC */
28−
2917 #define MN10300_IOCLK 33333333UL
3018 /* #define MN10300_IOBCLK 66666666UL */
3119
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−
4320 #endif /* !__ASSEMBLY__ */
4421
22+#define MN10300_WDCLK MN10300_IOCLK
23+
4524 #endif /* _ASM_UNIT_CLOCK_H */
arch/mn10300/unit-asb2305/include/unit/serial.h+5−0
@@ -20,6 +20,11 @@ · 19 unmodified lines
2020
2121 #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */
2222
23+/*
24+ * The ASB2305 has an 18.432 MHz clock the UART
25+ */
26+#define BASE_BAUD (18432000 / 16)
27+
2328 /*
2429 * dispose of the /dev/ttyS0 serial port
2530 */
arch/mn10300/unit-asb2305/include/unit/timex.h+62−47
@@ -1,6 +1,6 @@
1−/* ASB2305 timer specifcations
1+/* ASB2305-specific timer specifications
22 *
3− * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
3+ * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved.
44 * Written by David Howells (dhowells@redhat.com)
55 *
66 * This program is free software; you can redistribute it and/or
@@ -17,67 +17,72 @@ · 10 unmodified lines
1717
1818 #include <asm/timer-regs.h>
1919 #include <unit/clock.h>
20+#include <asm/param.h>
2021
2122 /*
2223 * jiffies counter specifications
2324 */
2425
2526 #define TMJCBR_MAX 0xffff
26−#define TMJCBC TM01BC
27−
28−#define TMJCMD TM01MD
29−#define TMJCBR TM01BR
3027 #define TMJCIRQ TM1IRQ
3128 #define TMJCICR TM1ICR
32−#define TMJCICR_LEVEL GxICR_LEVEL_5
3329
3430 #ifndef __ASSEMBLY__
3531
36−static 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+
60+static inline void stop_jiffies_counter(void)
3761 {
38− unsigned rate;
39− u16 md, t16;
40−
41− /* use as little prescaling as possible to avoid losing accuracy */
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− }
62+ u16 tmp;
63+ TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
64+ tmp = TM01MD;
65+}
5766
58− TMJCBR = rate - 1;
59− t16 = TMJCBR;
67+static inline void reload_jiffies_counter(u32 cnt)
68+{
69+ u32 tmp;
6070
61− TMJCMD =
62− md |
63− TM1MD_SRC_TM0CASCADE << 8 |
64− TM0MD_INIT_COUNTER |
65− TM1MD_INIT_COUNTER << 8;
71+ TM01BR = cnt;
72+ tmp = TM01BR;
6673
67− TMJCMD =
68− md |
69− TM1MD_SRC_TM0CASCADE << 8 |
70− TM0MD_COUNT_ENABLE |
71− TM1MD_COUNT_ENABLE << 8;
74+ TM01MD = JC_TIMER_CLKSRC | \
75+ TM1MD_SRC_TM0CASCADE << 8 | \
76+ TM0MD_INIT_COUNTER | \
77+ TM1MD_INIT_COUNTER << 8;
7278
73− t16 = TMJCMD;
7479
75− TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
76− t16 = TMJCICR;
77−}
80+ TM01MD = JC_TIMER_CLKSRC | \
81+ TM1MD_SRC_TM0CASCADE << 8 | \
82+ TM0MD_COUNT_ENABLE | \
83+ TM1MD_COUNT_ENABLE << 8;
7884
79−static inline void shutdown_jiffies_counter(void)
80−{
85+ tmp = TM01MD;
8186 }
8287
8388 #endif /* !__ASSEMBLY__ */
@@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void) · 10 unmodified lines
9499
95100 static inline void startup_timestamp_counter(void)
96101 {
102+ u32 t32;
103+
97104 /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
98105 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
99106 */
100107 TM45BR = TMTSCBR_MAX;
108+ t32 = TM45BR;
101109
102− TM4MD = TM4MD_SRC_IOCLK;
110+ TM4MD = TSC_TIMER_CLKSRC;
103111 TM4MD |= TM4MD_INIT_COUNTER;
104112 TM4MD &= ~TM4MD_INIT_COUNTER;
105113 TM4ICR = 0;
114+ t32 = TM4ICR;
106115
107116 TM5MD = TM5MD_SRC_TM4CASCADE;
108117 TM5MD |= TM5MD_INIT_COUNTER;
109118 TM5MD &= ~TM5MD_INIT_COUNTER;
110119 TM5ICR = 0;
120+ t32 = TM5ICR;
111121
112122 TM5MD |= TM5MD_COUNT_ENABLE;
113123 TM4MD |= TM4MD_COUNT_ENABLE;
124+ t32 = TM5MD;
125+ t32 = TM4MD;
114126 }
115127
116128 static inline void shutdown_timestamp_counter(void)
117129 {
130+ u8 t8;
118131 TM4MD = 0;
119132 TM5MD = 0;
133+ t8 = TM4MD;
134+ t8 = TM5MD;
120135 }
121136
122137 /*
@@ -127,7 +142,7 @@ typedef unsigned long cycles_t; · 4 unmodified lines
127142
128143 static inline cycles_t read_timestamp_counter(void)
129144 {
130− return (cycles_t) TMTSCBC;
145+ return (cycles_t)~TMTSCBC;
131146 }
132147
133148 #endif /* !__ASSEMBLY__ */
arch/mn10300/unit-asb2305/pci-asb2305.c+6−10
@@ -93,7 +93,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) · 92 unmodified lines
9393 struct pci_bus *bus;
9494 struct pci_dev *dev;
9595 int idx;
96− struct resource *r, *pr;
96+ struct resource *r;
9797
9898 /* Depth-First Search on bus tree */
9999 list_for_each_entry(bus, bus_list, node) {
@@ -105,10 +105,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) · 5 unmodified lines
105105 r = &dev->resource[idx];
106106 if (!r->flags)
107107 continue;
108− pr = pci_find_parent_resource(dev, r);
109108 if (!r->start ||
110− !pr ||
111− request_resource(pr, r) < 0) {
109+ pci_claim_resource(dev, idx) < 0) {
112110 printk(KERN_ERR "PCI:"
113111 " Cannot allocate resource"
114112 " region %d of bridge %s\n",
@@ -131,7 +129,7 @@ static void __init pcibios_allocate_resources(int pass) · 16 unmodified lines
131129 struct pci_dev *dev = NULL;
132130 int idx, disabled;
133131 u16 command;
134− struct resource *r, *pr;
132+ struct resource *r;
135133
136134 for_each_pci_dev(dev) {
137135 pci_read_config_word(dev, PCI_COMMAND, &command);
@@ -150,8 +148,7 @@ static void __init pcibios_allocate_resources(int pass) · 12 unmodified lines
150148 " (f=%lx, d=%d, p=%d)\n",
151149 pci_name(dev), r->start, r->end, r->flags,
152150 disabled, pass);
153− pr = pci_find_parent_resource(dev, r);
154− if (!pr || request_resource(pr, r) < 0) {
151+ if (pci_claim_resource(dev, idx) < 0) {
155152 printk(KERN_ERR "PCI:"
156153 " Cannot allocate resource"
157154 " region %d of device %s\n",
@@ -184,7 +181,7 @@ static void __init pcibios_allocate_resources(int pass) · 26 unmodified lines
184181 static int __init pcibios_assign_resources(void)
185182 {
186183 struct pci_dev *dev = NULL;
187− struct resource *r, *pr;
184+ struct resource *r;
188185
189186 if (!(pci_probe & PCI_ASSIGN_ROMS)) {
190187 /* Try to use BIOS settings for ROMs, otherwise let
@@ -194,8 +191,7 @@ static int __init pcibios_assign_resources(void) · 3 unmodified lines
194191 r = &dev->resource[PCI_ROM_RESOURCE];
195192 if (!r->flags || !r->start)
196193 continue;
197− pr = pci_find_parent_resource(dev, r);
198− if (!pr || request_resource(pr, r) < 0) {
194+ if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
199195 r->end -= r->start;
200196 r->start = 0;
201197 }
arch/mn10300/unit-asb2305/pci.c+1−1
@@ -503,7 +503,7 @@ asmlinkage void __init unit_pci_init(void) · 502 unmodified lines
503503 struct pci_ops *o = &pci_direct_ampci;
504504 u32 x;
505505
506− set_intr_level(XIRQ1, GxICR_LEVEL_3);
506+ set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL));
507507
508508 memset(&bus, 0, sizeof(bus));
509509
arch/mn10300/unit-asb2305/unit-init.c+4−2
@@ -26,8 +26,10 @@ asmlinkage void __init unit_init(void) · 25 unmodified lines
2626 {
2727 #ifndef CONFIG_GDBSTUB_ON_TTYSx
2828 /* 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));
3031 #endif
32+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
3133 }
3234
3335 /*
@@ -51,7 +53,7 @@ void __init unit_init_IRQ(void) · 17 unmodified lines
5153 switch (GET_XIRQ_TRIGGER(extnum)) {
5254 case XIRQ_TRIGGER_HILEVEL:
5355 case XIRQ_TRIGGER_LOWLEVEL:
54− set_intr_postackable(XIRQ2IRQ(extnum));
56+ mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
5557 break;
5658 default:
5759 break;
arch/mn10300/unit-asb2364/Makefile+12−0
@@ -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+
10+obj-y := unit-init.o leds.o irq-fpga.o
11+
12+obj-$(CONFIG_SMSC911X) += smsc911x.o
arch/mn10300/unit-asb2364/include/unit/clock.h+29−0
@@ -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 */
arch/mn10300/unit-asb2364/include/unit/fpga-regs.h+52−0
@@ -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 */
arch/mn10300/unit-asb2364/include/unit/irq.h+35−0
@@ -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+
22+enum {
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+
32+extern void __init irq_fpga_init(void);
33+
34+#endif /* !__ASSEMBLY__ */
35+#endif /* _UNIT_IRQ_H */
arch/mn10300/unit-asb2364/include/unit/leds.h+54−0
@@ -0,0 +1,54 @@
1+/* Unit-specific leds
2+ *
3+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4+ * Written by David Howells (dhowells@redhat.com)
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version
9+ * 2 of the License, or (at your option) any later version.
10+ */
11+
12+#ifndef _ASM_UNIT_LEDS_H
13+#define _ASM_UNIT_LEDS_H
14+
15+#include <asm/pio-regs.h>
16+#include <asm/cpu-regs.h>
17+#include <asm/exceptions.h>
18+
19+#define MN10300_USE_7SEGLEDS 0
20+
21+#define ASB2364_7SEGLEDS __SYSREG(0xA9001630, u32)
22+
23+/*
24+ * use the 7-segment LEDs to indicate states
25+ */
26+
27+#if MN10300_USE_7SEGLEDS
28+/* flip the 7-segment LEDs between "Gdb-" and "----" */
29+#define mn10300_set_gdbleds(ONOFF) \
30+ do { \
31+ ASB2364_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f; \
32+ } while (0)
33+#else
34+#define mn10300_set_gdbleds(ONOFF) do {} while (0)
35+#endif
36+
37+#if MN10300_USE_7SEGLEDS
38+/* indicate double-fault by displaying "db-f" on the LEDs */
39+#define mn10300_set_dbfleds \
40+ mov 0x43077f1d,d0 ; \
41+ mov d0,(ASB2364_7SEGLEDS)
42+#else
43+#define mn10300_set_dbfleds
44+#endif
45+
46+#ifndef __ASSEMBLY__
47+extern void peripheral_leds_display_exception(enum exception_code);
48+extern void peripheral_leds_led_chase(void);
49+extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int);
50+extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int);
51+extern void debug_to_serial(const char *, int);
52+#endif /* __ASSEMBLY__ */
53+
54+#endif /* _ASM_UNIT_LEDS_H */
arch/mn10300/unit-asb2364/include/unit/serial.h+151−0
@@ -0,0 +1,151 @@
1+/* Unit-specific 8250 serial ports
2+ *
3+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4+ * Written by David Howells (dhowells@redhat.com)
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version
9+ * 2 of the License, or (at your option) any later version.
10+ */
11+
12+#ifndef _ASM_UNIT_SERIAL_H
13+#define _ASM_UNIT_SERIAL_H
14+
15+#include <asm/cpu-regs.h>
16+#include <proc/irq.h>
17+#include <unit/fpga-regs.h>
18+#include <linux/serial_reg.h>
19+
20+#define SERIAL_PORT0_BASE_ADDRESS 0xA8200000
21+
22+#define SERIAL_IRQ XIRQ1 /* single serial (TL16C550C) (Lo) */
23+
24+/*
25+ * The ASB2364 has an 12.288 MHz clock
26+ * for your UART.
27+ *
28+ * It'd be nice if someone built a serial card with a 24.576 MHz
29+ * clock, since the 16550A is capable of handling a top speed of 1.5
30+ * megabits/second; but this requires the faster clock.
31+ */
32+#define BASE_BAUD (12288000 / 16)
33+
34+/*
35+ * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
36+ */
37+#ifndef CONFIG_GDBSTUB_ON_TTYSx
38+
39+#define SERIAL_PORT_DFNS \
40+ { \
41+ .baud_base = BASE_BAUD, \
42+ .irq = SERIAL_IRQ, \
43+ .flags = STD_COM_FLAGS, \
44+ .iomem_base = (u8 *) SERIAL_PORT0_BASE_ADDRESS, \
45+ .iomem_reg_shift = 1, \
46+ .io_type = SERIAL_IO_MEM, \
47+ },
48+
49+#ifndef __ASSEMBLY__
50+
51+static inline void __debug_to_serial(const char *p, int n)
52+{
53+}
54+
55+#endif /* !__ASSEMBLY__ */
56+
57+#else /* CONFIG_GDBSTUB_ON_TTYSx */
58+
59+#define SERIAL_PORT_DFNS /* stolen by gdb-stub */
60+
61+#if defined(CONFIG_GDBSTUB_ON_TTYS0)
62+#define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 4, u8)
63+#define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 4, u8)
64+#define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
65+#define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
66+#define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
67+#define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
68+#define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
69+#define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
70+#define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
71+#define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
72+#define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
73+#define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
74+#define GDBPORT_SERIAL_IRQ SERIAL_IRQ
75+
76+#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
77+#error The ASB2364 does not have a /dev/ttyS1
78+#endif
79+
80+#ifndef __ASSEMBLY__
81+
82+static inline void __debug_to_serial(const char *p, int n)
83+{
84+ char ch;
85+
86+#define LSR_WAIT_FOR(STATE) \
87+ do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE))
88+#define FLOWCTL_QUERY(LINE) \
89+ ({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; })
90+#define FLOWCTL_WAIT_FOR(LINE) \
91+ do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE))
92+#define FLOWCTL_CLEAR(LINE) \
93+ do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0)
94+#define FLOWCTL_SET(LINE) \
95+ do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0)
96+
97+ FLOWCTL_SET(DTR);
98+
99+ for (; n > 0; n--) {
100+ LSR_WAIT_FOR(THRE);
101+ FLOWCTL_WAIT_FOR(CTS);
102+
103+ ch = *p++;
104+ if (ch == 0x0a) {
105+ GDBPORT_SERIAL_TX = 0x0d;
106+ LSR_WAIT_FOR(THRE);
107+ FLOWCTL_WAIT_FOR(CTS);
108+ }
109+ GDBPORT_SERIAL_TX = ch;
110+ }
111+
112+ FLOWCTL_CLEAR(DTR);
113+}
114+
115+#endif /* !__ASSEMBLY__ */
116+
117+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
118+
119+#define SERIAL_INITIALIZE \
120+do { \
121+ /* release reset */ \
122+ ASB2364_FPGA_REG_RESET_UART = 0x0001; \
123+ SyncExBus(); \
124+} while (0)
125+
126+#define SERIAL_CHECK_INTERRUPT \
127+do { \
128+ if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) { \
129+ return IRQ_NONE; \
130+ } \
131+} while (0)
132+
133+#define SERIAL_CLEAR_INTERRUPT \
134+do { \
135+ ASB2364_FPGA_REG_IRQ_UART = 0x0001; \
136+ SyncExBus(); \
137+} while (0)
138+
139+#define SERIAL_SET_INT_MASK \
140+do { \
141+ ASB2364_FPGA_REG_MASK_UART = 0x0001; \
142+ SyncExBus(); \
143+} while (0)
144+
145+#define SERIAL_CLEAR_INT_MASK \
146+do { \
147+ ASB2364_FPGA_REG_MASK_UART = 0x0000; \
148+ SyncExBus(); \
149+} while (0)
150+
151+#endif /* _ASM_UNIT_SERIAL_H */
arch/mn10300/unit-asb2364/include/unit/smsc911x.h+171−0
@@ -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() \
30+do { \
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+
61+static 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
79+static 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 */
arch/mn10300/unit-asb2364/include/unit/timex.h+159−0
@@ -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+
48+static inline void stop_jiffies_counter(void)
49+{
50+ u16 tmp;
51+ TMTMD = 0;
52+ tmp = TMTMD;
53+}
54+
55+static 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+
78+static inline void stop_jiffies_counter1(void)
79+{
80+ u8 tmp;
81+ TM4MD = 0;
82+ TM5MD = 0;
83+ tmp = TM4MD;
84+ tmp = TM5MD;
85+}
86+
87+static 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+
122+static 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+
141+static 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+ */
150+typedef unsigned long cycles_t;
151+
152+static 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 */
arch/mn10300/unit-asb2364/irq-fpga.c+96−0
@@ -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+ */
20+static void asb2364_fpga_mask(unsigned int irq)
21+{
22+ ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
23+ SyncExBus();
24+}
25+
26+static void asb2364_fpga_ack(unsigned int irq)
27+{
28+ ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
29+ SyncExBus();
30+}
31+
32+static 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+
40+static void asb2364_fpga_unmask(unsigned int irq)
41+{
42+ ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000;
43+ SyncExBus();
44+}
45+
46+static 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+ */
57+static 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+ */
76+static 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+ */
87+void __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+}
arch/mn10300/unit-asb2364/leds.c+98−0
@@ -0,0 +1,98 @@
1+/* leds.c: ASB2364 peripheral 7seg LEDs x4 support
2+ *
3+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4+ * Written by David Howells (dhowells@redhat.com)
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version
9+ * 2 of the License, or (at your option) any later version.
10+ */
11+
12+#include <linux/kernel.h>
13+#include <linux/param.h>
14+#include <linux/init.h>
15+
16+#include <asm/io.h>
17+#include <asm/processor.h>
18+#include <asm/intctl-regs.h>
19+#include <asm/rtc-regs.h>
20+#include <unit/leds.h>
21+
22+#if MN10300_USE_7SEGLEDS
23+static const u8 asb2364_led_hex_tbl[16] = {
24+ 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
25+ 0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
26+};
27+
28+static const u32 asb2364_led_chase_tbl[6] = {
29+ ~0x02020202, /* top - segA */
30+ ~0x04040404, /* right top - segB */
31+ ~0x08080808, /* right bottom - segC */
32+ ~0x10101010, /* bottom - segD */
33+ ~0x20202020, /* left bottom - segE */
34+ ~0x40404040, /* left top - segF */
35+};
36+
37+static unsigned asb2364_led_chase;
38+
39+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points)
40+{
41+ u32 leds;
42+
43+ leds = asb2364_led_hex_tbl[(val/1000) % 10];
44+ leds <<= 8;
45+ leds |= asb2364_led_hex_tbl[(val/100) % 10];
46+ leds <<= 8;
47+ leds |= asb2364_led_hex_tbl[(val/10) % 10];
48+ leds <<= 8;
49+ leds |= asb2364_led_hex_tbl[val % 10];
50+ leds |= points^0x01010101;
51+
52+ ASB2364_7SEGLEDS = leds;
53+}
54+
55+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points)
56+{
57+ u32 leds;
58+
59+ leds = asb2364_led_hex_tbl[(val/1000) % 10];
60+ leds <<= 8;
61+ leds |= asb2364_led_hex_tbl[(val/100) % 10];
62+ leds <<= 8;
63+ leds |= asb2364_led_hex_tbl[(val/10) % 10];
64+ leds <<= 8;
65+ leds |= asb2364_led_hex_tbl[val % 10];
66+ leds |= points^0x01010101;
67+
68+ ASB2364_7SEGLEDS = leds;
69+}
70+
71+/* display triple horizontal bar and exception code */
72+void peripheral_leds_display_exception(enum exception_code code)
73+{
74+ u32 leds;
75+
76+ leds = asb2364_led_hex_tbl[(code/0x100) % 0x10];
77+ leds <<= 8;
78+ leds |= asb2364_led_hex_tbl[(code/0x10) % 0x10];
79+ leds <<= 8;
80+ leds |= asb2364_led_hex_tbl[code % 0x10];
81+ leds |= 0x6d010101;
82+
83+ ASB2364_7SEGLEDS = leds;
84+}
85+
86+void peripheral_leds_led_chase(void)
87+{
88+ ASB2364_7SEGLEDS = asb2364_led_chase_tbl[asb2364_led_chase];
89+ asb2364_led_chase++;
90+ if (asb2364_led_chase >= 6)
91+ asb2364_led_chase = 0;
92+}
93+#else /* MN10300_USE_7SEGLEDS */
94+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { }
95+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { }
96+void peripheral_leds_display_exception(enum exception_code code) { }
97+void peripheral_leds_led_chase(void) { }
98+#endif /* MN10300_USE_7SEGLEDS */
arch/mn10300/unit-asb2364/smsc911x.c+58−0
@@ -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+
20+static 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+
26+static 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+
39+static 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+ */
52+static int __init unit_device_init(void)
53+{
54+ platform_device_register(&smsc911x_device);
55+ return 0;
56+}
57+
58+device_initcall(unit_device_init);
arch/mn10300/unit-asb2364/unit-init.c+88−0
@@ -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+ */
28+asmlinkage 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+ */
57+asmlinkage void __init unit_setup(void)
58+{
59+
60+}
61+
62+/*
63+ * initialise the external interrupts used by a unit of this type
64+ */
65+void __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+}
drivers/net/Kconfig+10−2
@@ -1041,7 +1041,7 @@ config SMC911X · 1040 unmodified lines
10411041 tristate "SMSC LAN911[5678] support"
10421042 select CRC32
10431043 select MII
1044− depends on ARM || SUPERH
1044+ depends on ARM || SUPERH || MN10300
10451045 help
10461046 This is a driver for SMSC's LAN911x series of Ethernet chipsets
10471047 including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -1055,7 +1055,7 @@ config SMC911X · 7 unmodified lines
10551055
10561056 config SMSC911X
10571057 tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
1058− depends on ARM || SUPERH || BLACKFIN || MIPS
1058+ depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300
10591059 select CRC32
10601060 select MII
10611061 select PHYLIB
@@ -1067,6 +1067,14 @@ config SMSC911X · 5 unmodified lines
10671067 <file:Documentation/networking/net-modules.txt>. The module
10681068 will be called smsc911x.
10691069
1070+config SMSC911X_ARCH_HOOKS
1071+ def_bool n
1072+ depends on SMSC911X
1073+ help
1074+ If the arch enables this, it allows the arch to implement various
1075+ hooks for more comprehensive interrupt control and also to override
1076+ the source of the MAC address.
1077+
10701078 config NET_VENDOR_RACAL
10711079 bool "Racal-Interlan (Micom) NI cards"
10721080 depends on ISA
drivers/net/smsc911x.c+2−1
@@ -2075,7 +2075,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) · 2074 unmodified lines
20752075 } else {
20762076 /* Try reading mac address from device. if EEPROM is present
20772077 * it will already have been set */
2078− smsc911x_read_mac_address(dev);
2078+ smsc_get_mac(dev);
20792079
20802080 if (is_valid_ether_addr(dev->dev_addr)) {
20812081 /* eeprom values are valid so use them */
@@ -2176,6 +2176,7 @@ static struct platform_driver smsc911x_driver = { · 94 unmodified lines
21762176 /* Entry point for loading the module */
21772177 static int __init smsc911x_init_module(void)
21782178 {
2179+ SMSC_INITIALIZE();
21792180 return platform_driver_register(&smsc911x_driver);
21802181 }
21812182
drivers/net/smsc911x.h+11−0
@@ -394,4 +394,15 @@ · 393 unmodified lines
394394 #define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \
395395 LPA_PAUSE_ASYM)
396396
397+/*
398+ * Provide hooks to let the arch add to the initialisation procedure
399+ * and to override the source of the MAC address.
400+ */
401+#define SMSC_INITIALIZE() do {} while (0)
402+#define smsc_get_mac(dev) smsc911x_read_mac_address((dev))
403+
404+#ifdef CONFIG_SMSC911X_ARCH_HOOKS
405+#include <asm/smsc911x.h>
406+#endif
407+
397408 #endif /* __SMSC911X_H__ */
include/linux/smp.h+10−9
@@ -13,9 +13,10 @@ · 12 unmodified lines
1313
1414 extern void cpu_idle(void);
1515
16+typedef void (*smp_call_func_t)(void *info);
1617 struct call_single_data {
1718 struct list_head list;
18− void (*func) (void *info);
19+ smp_call_func_t func;
1920 void *info;
2021 u16 flags;
2122 u16 priv;
@@ -24,8 +25,8 @@ struct call_single_data { · 2 unmodified lines
2425 /* total number of cpus in this system (may exceed NR_CPUS) */
2526 extern unsigned int total_cpus;
2627
27−int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
28− int wait);
28+int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
29+ int wait);
2930
3031 #ifdef CONFIG_SMP
3132
@@ -69,15 +70,15 @@ extern void smp_cpus_done(unsigned int max_cpus); · 37 unmodified lines
6970 /*
7071 * Call a function on all other processors
7172 */
72−int smp_call_function(void(*func)(void *info), void *info, int wait);
73+int smp_call_function(smp_call_func_t func, void *info, int wait);
7374 void smp_call_function_many(const struct cpumask *mask,
74− void (*func)(void *info), void *info, bool wait);
75+ smp_call_func_t func, void *info, bool wait);
7576
7677 void __smp_call_function_single(int cpuid, struct call_single_data *data,
7778 int wait);
7879
7980 int smp_call_function_any(const struct cpumask *mask,
80− void (*func)(void *info), void *info, int wait);
81+ smp_call_func_t func, void *info, int wait);
8182
8283 /*
8384 * Generic and arch helpers
@@ -94,7 +95,7 @@ void ipi_call_unlock_irq(void); · 10 unmodified lines
9495 /*
9596 * Call a function on all processors
9697 */
97−int on_each_cpu(void (*func) (void *info), void *info, int wait);
98+int on_each_cpu(smp_call_func_t func, void *info, int wait);
9899
99100 #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
100101 #define MSG_ALL 0x8001
@@ -122,7 +123,7 @@ static inline void smp_send_stop(void) { } · 21 unmodified lines
122123 * These macros fold the SMP functionality into a single CPU system
123124 */
124125 #define raw_smp_processor_id() 0
125−static inline int up_smp_call_function(void (*func)(void *), void *info)
126+static inline int up_smp_call_function(smp_call_func_t func, void *info)
126127 {
127128 return 0;
128129 }
@@ -143,7 +144,7 @@ static inline void smp_send_reschedule(int cpu) { } · 14 unmodified lines
143144 static inline void init_call_single_data(void) { }
144145
145146 static inline int
146−smp_call_function_any(const struct cpumask *mask, void (*func)(void *info),
147+smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
147148 void *info, int wait)
148149 {
149150 return smp_call_function_single(0, func, info, wait);
kernel/smp.c+4−4
@@ -267,7 +267,7 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_single_data, csd_data); · 266 unmodified lines
267267 *
268268 * Returns 0 on success, else a negative status code.
269269 */
270−int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
270+int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
271271 int wait)
272272 {
273273 struct call_single_data d = {
@@ -336,7 +336,7 @@ EXPORT_SYMBOL(smp_call_function_single); · 62 unmodified lines
336336 * 3) any other online cpu in @mask
337337 */
338338 int smp_call_function_any(const struct cpumask *mask,
339− void (*func)(void *info), void *info, int wait)
339+ smp_call_func_t func, void *info, int wait)
340340 {
341341 unsigned int cpu;
342342 const struct cpumask *nodemask;
@@ -416,7 +416,7 @@ void __smp_call_function_single(int cpu, struct call_single_data *data, · 73 unmodified lines
416416 * must be disabled when calling this function.
417417 */
418418 void smp_call_function_many(const struct cpumask *mask,
419− void (*func)(void *), void *info, bool wait)
419+ smp_call_func_t func, void *info, bool wait)
420420 {
421421 struct call_function_data *data;
422422 unsigned long flags;
@@ -500,7 +500,7 @@ EXPORT_SYMBOL(smp_call_function_many); · 77 unmodified lines
500500 * You must not call this function with disabled interrupts or from a
501501 * hardware interrupt handler or from a bottom half handler.
502502 */
503−int smp_call_function(void (*func)(void *), void *info, int wait)
503+int smp_call_function(smp_call_func_t func, void *info, int wait)
504504 {
505505 preempt_disable();
506506 smp_call_function_many(cpu_online_mask, func, info, wait);
mm/maccess.c+1−1
@@ -1,9 +1,9 @@
11 /*
22 * Access kernel memory without faulting.
33 */
4−#include <linux/uaccess.h>
54 #include <linux/module.h>
65 #include <linux/mm.h>
6+#include <linux/uaccess.h>
77
88 /**
99 * probe_kernel_read(): safely attempt to read from a location

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t