diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 21:53:26 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 21:53:26 -0400 | 
| commit | bdab225015fbbb45ccd8913f5d7c01b2bf67d8b2 (patch) | |
| tree | 5ef62301face958977a084bf2b6c5300296a25f2 | |
| parent | 7c5814c7199851c5fe9395d08fc1ab3c8c1531ea (diff) | |
| parent | 7c7fcf762e405eb040ee10d22d656a791f616122 (diff) | |
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
  ...
145 files changed, 9424 insertions, 1963 deletions
| @@ -53,7 +53,7 @@ targets += arch/$(SRCARCH)/kernel/asm-offsets.s | |||
| 53 | # Default sed regexp - multiline due to syntax constraints | 53 | # Default sed regexp - multiline due to syntax constraints | 
| 54 | define sed-y | 54 | define sed-y | 
| 55 | "/^->/{s:->#\(.*\):/* \1 */:; \ | 55 | "/^->/{s:->#\(.*\):/* \1 */:; \ | 
| 56 | s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \ | 56 | s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ | 
| 57 | s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ | 57 | s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ | 
| 58 | s:->::; p;}" | 58 | s:->::; p;}" | 
| 59 | endef | 59 | endef | 
| diff --git a/MAINTAINERS b/MAINTAINERS index debde0128cd0..1e6b6bdf6340 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4448,7 +4448,7 @@ L: platform-driver-x86@vger.kernel.org | |||
| 4448 | S: Maintained | 4448 | S: Maintained | 
| 4449 | F: drivers/platform/x86/panasonic-laptop.c | 4449 | F: drivers/platform/x86/panasonic-laptop.c | 
| 4450 | 4450 | ||
| 4451 | PANASONIC MN10300/AM33 PORT | 4451 | PANASONIC MN10300/AM33/AM34 PORT | 
| 4452 | M: David Howells <dhowells@redhat.com> | 4452 | M: David Howells <dhowells@redhat.com> | 
| 4453 | M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> | 4453 | M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> | 
| 4454 | L: linux-am33-list@redhat.com (moderated for non-subscribers) | 4454 | L: linux-am33-list@redhat.com (moderated for non-subscribers) | 
| diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 7c2a2f7f8dc1..365766a3d536 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
| @@ -9,8 +9,19 @@ config MN10300 | |||
| 9 | def_bool y | 9 | def_bool y | 
| 10 | select HAVE_OPROFILE | 10 | select HAVE_OPROFILE | 
| 11 | 11 | ||
| 12 | config AM33 | 12 | config AM33_2 | 
| 13 | def_bool y | 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 | ||
| 14 | 25 | ||
| 15 | config MMU | 26 | config MMU | 
| 16 | def_bool y | 27 | def_bool y | 
| @@ -37,7 +48,7 @@ config GENERIC_CALIBRATE_DELAY | |||
| 37 | def_bool y | 48 | def_bool y | 
| 38 | 49 | ||
| 39 | config GENERIC_CMOS_UPDATE | 50 | config GENERIC_CMOS_UPDATE | 
| 40 | def_bool y | 51 | def_bool n | 
| 41 | 52 | ||
| 42 | config GENERIC_FIND_NEXT_BIT | 53 | config GENERIC_FIND_NEXT_BIT | 
| 43 | def_bool y | 54 | def_bool y | 
| @@ -45,6 +56,27 @@ config GENERIC_FIND_NEXT_BIT | |||
| 45 | config GENERIC_HWEIGHT | 56 | config GENERIC_HWEIGHT | 
| 46 | def_bool y | 57 | def_bool y | 
| 47 | 58 | ||
| 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 | |||
| 48 | config GENERIC_BUG | 80 | config GENERIC_BUG | 
| 49 | def_bool y | 81 | def_bool y | 
| 50 | 82 | ||
| @@ -61,18 +93,14 @@ config GENERIC_HARDIRQS | |||
| 61 | config HOTPLUG_CPU | 93 | config HOTPLUG_CPU | 
| 62 | def_bool n | 94 | def_bool n | 
| 63 | 95 | ||
| 64 | config HZ | 96 | mainmenu "Panasonic MN10300/AM33 Kernel Configuration" | 
| 65 | int | ||
| 66 | default 1000 | ||
| 67 | |||
| 68 | mainmenu "Matsushita MN10300/AM33 Kernel Configuration" | ||
| 69 | 97 | ||
| 70 | source "init/Kconfig" | 98 | source "init/Kconfig" | 
| 71 | 99 | ||
| 72 | source "kernel/Kconfig.freezer" | 100 | source "kernel/Kconfig.freezer" | 
| 73 | 101 | ||
| 74 | 102 | ||
| 75 | menu "Matsushita MN10300 system setup" | 103 | menu "Panasonic MN10300 system setup" | 
| 76 | 104 | ||
| 77 | choice | 105 | choice | 
| 78 | prompt "Unit type" | 106 | prompt "Unit type" | 
| @@ -87,6 +115,10 @@ config MN10300_UNIT_ASB2303 | |||
| 87 | config MN10300_UNIT_ASB2305 | 115 | config MN10300_UNIT_ASB2305 | 
| 88 | bool "ASB2305" | 116 | bool "ASB2305" | 
| 89 | 117 | ||
| 118 | config MN10300_UNIT_ASB2364 | ||
| 119 | bool "ASB2364" | ||
| 120 | select SMSC911X_ARCH_HOOKS if SMSC911X | ||
| 121 | |||
| 90 | endchoice | 122 | endchoice | 
| 91 | 123 | ||
| 92 | choice | 124 | choice | 
| @@ -99,57 +131,51 @@ choice | |||
| 99 | config MN10300_PROC_MN103E010 | 131 | config MN10300_PROC_MN103E010 | 
| 100 | bool "MN103E010" | 132 | bool "MN103E010" | 
| 101 | depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305 | 133 | depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305 | 
| 134 | select AM33_2 | ||
| 135 | select MN10300_PROC_HAS_TTYSM0 | ||
| 136 | select MN10300_PROC_HAS_TTYSM1 | ||
| 137 | select MN10300_PROC_HAS_TTYSM2 | ||
| 138 | |||
| 139 | config MN10300_PROC_MN2WS0050 | ||
| 140 | bool "MN2WS0050" | ||
| 141 | depends on MN10300_UNIT_ASB2364 | ||
| 142 | select AM34_2 | ||
| 102 | select MN10300_PROC_HAS_TTYSM0 | 143 | select MN10300_PROC_HAS_TTYSM0 | 
| 103 | select MN10300_PROC_HAS_TTYSM1 | 144 | select MN10300_PROC_HAS_TTYSM1 | 
| 104 | select MN10300_PROC_HAS_TTYSM2 | 145 | select MN10300_PROC_HAS_TTYSM2 | 
| 105 | 146 | ||
| 106 | endchoice | 147 | endchoice | 
| 107 | 148 | ||
| 108 | choice | 149 | config MN10300_HAS_ATOMIC_OPS_UNIT | 
| 109 | prompt "Processor core support" | 150 | def_bool n | 
| 110 | default MN10300_CPU_AM33V2 | ||
| 111 | help | 151 | help | 
| 112 | This option specifies the processor core for which the kernel will be | 152 | This should be enabled if the processor has an atomic ops unit | 
| 113 | compiled. It affects the instruction set used. | 153 | capable of doing LL/SC equivalent operations. | 
| 114 | |||
| 115 | config MN10300_CPU_AM33V2 | ||
| 116 | bool "AM33v2" | ||
| 117 | |||
| 118 | endchoice | ||
| 119 | 154 | ||
| 120 | config FPU | 155 | config FPU | 
| 121 | bool "FPU present" | 156 | bool "FPU present" | 
| 122 | default y | 157 | default y | 
| 123 | depends on MN10300_PROC_MN103E010 | 158 | depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050 | 
| 124 | 159 | ||
| 125 | choice | 160 | config LAZY_SAVE_FPU | 
| 126 | prompt "CPU Caching mode" | 161 | bool "Save FPU state lazily" | 
| 127 | default MN10300_CACHE_WBACK | 162 | default y | 
| 163 | depends on FPU && !SMP | ||
| 128 | help | 164 | help | 
| 129 | This option determines the caching mode for the kernel. | 165 | Enable this to be lazy in the saving of the FPU state to the owning | 
| 130 | 166 | task's thread struct. This is useful if most tasks on the system | |
| 131 | Write-Back caching mode involves the all reads and writes causing | 167 | don't use the FPU as only those tasks that use it will pass it | 
| 132 | the affected cacheline to be read into the cache first before being | 168 | between them, and the state needn't be saved for a task that isn't | 
| 133 | operated upon. Memory is not then updated by a write until the cache | 169 | using it. | 
| 134 | is filled and a cacheline needs to be displaced from the cache to | ||
| 135 | make room. Only at that point is it written back. | ||
| 136 | |||
| 137 | Write-Through caching only fetches cachelines from memory on a | ||
| 138 | read. Writes always get written directly to memory. If the affected | ||
| 139 | cacheline is also in cache, it will be updated too. | ||
| 140 | |||
| 141 | The final option is to turn of caching entirely. | ||
| 142 | 170 | ||
| 143 | config MN10300_CACHE_WBACK | 171 | This can't be so easily used on SMP as the process that owns the FPU | 
| 144 | bool "Write-Back" | 172 | state on a CPU may be currently running on another CPU, so for the | 
| 173 | moment, it is disabled. | ||
| 145 | 174 | ||
| 146 | config MN10300_CACHE_WTHRU | 175 | source "arch/mn10300/mm/Kconfig.cache" | 
| 147 | bool "Write-Through" | ||
| 148 | 176 | ||
| 149 | config MN10300_CACHE_DISABLED | 177 | config MN10300_TLB_USE_PIDR | 
| 150 | bool "Disabled" | 178 | def_bool y | 
| 151 | |||
| 152 | endchoice | ||
| 153 | 179 | ||
| 154 | menu "Memory layout options" | 180 | menu "Memory layout options" | 
| 155 | 181 | ||
| @@ -170,24 +196,55 @@ config KERNEL_TEXT_ADDRESS | |||
| 170 | 196 | ||
| 171 | config KERNEL_ZIMAGE_BASE_ADDRESS | 197 | config KERNEL_ZIMAGE_BASE_ADDRESS | 
| 172 | hex "Base address of compressed vmlinux image" | 198 | hex "Base address of compressed vmlinux image" | 
| 173 | default "0x90700000" | 199 | default "0x50700000" | 
| 174 | 200 | ||
| 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" | ||
| 175 | endmenu | 210 | endmenu | 
| 176 | 211 | ||
| 177 | config PREEMPT | 212 | config SMP | 
| 178 | bool "Preemptible Kernel" | 213 | bool "Symmetric multi-processing support" | 
| 179 | help | 214 | default y | 
| 180 | This option reduces the latency of the kernel when reacting to | 215 | depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050 | 
| 181 | real-time or interactive events by allowing a low priority process to | 216 | ---help--- | 
| 182 | be preempted even if it is in kernel mode executing a system call. | 217 | This enables support for systems with more than one CPU. If you have | 
| 183 | This allows applications to run more reliably even when the system is | 218 | a system with only one CPU, like most personal computers, say N. If | 
| 184 | under load. | 219 | you have a system with more than one CPU, say Y. | 
| 220 | |||
| 221 | If you say N here, the kernel will run on single and multiprocessor | ||
| 222 | machines, but will use only one CPU of a multiprocessor machine. If | ||
| 223 | you say Y here, the kernel will run on many, but not all, | ||
| 224 | singleprocessor machines. On a singleprocessor machine, the kernel | ||
| 225 | will run faster if you say N here. | ||
| 185 | 226 | ||
| 186 | Say Y here if you are building a kernel for a desktop, embedded | 227 | See also <file:Documentation/i386/IO-APIC.txt>, | 
| 187 | or real-time system. Say N if you are unsure. | 228 | <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at | 
| 229 | <http://www.tldp.org/docs.html#howto>. | ||
| 230 | |||
| 231 | If you don't know what to do here, say N. | ||
| 232 | |||
| 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" | ||
| 188 | 244 | ||
| 189 | config MN10300_CURRENT_IN_E2 | 245 | config MN10300_CURRENT_IN_E2 | 
| 190 | bool "Hold current task address in E2 register" | 246 | bool "Hold current task address in E2 register" | 
| 247 | depends on !SMP | ||
| 191 | default y | 248 | default y | 
| 192 | help | 249 | help | 
| 193 | This option removes the E2/R2 register from the set available to gcc | 250 | This option removes the E2/R2 register from the set available to gcc | 
| @@ -209,12 +266,15 @@ config MN10300_USING_JTAG | |||
| 209 | suppresses the use of certain hardware debugging features, such as | 266 | suppresses the use of certain hardware debugging features, such as | 
| 210 | single-stepping, which are taken over completely by the JTAG unit. | 267 | single-stepping, which are taken over completely by the JTAG unit. | 
| 211 | 268 | ||
| 269 | source "kernel/Kconfig.hz" | ||
| 270 | source "kernel/time/Kconfig" | ||
| 271 | |||
| 212 | config MN10300_RTC | 272 | config MN10300_RTC | 
| 213 | bool "Using MN10300 RTC" | 273 | bool "Using MN10300 RTC" | 
| 214 | depends on MN10300_PROC_MN103E010 | 274 | depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050 | 
| 275 | select GENERIC_CMOS_UPDATE | ||
| 215 | default n | 276 | default n | 
| 216 | help | 277 | help | 
| 217 | |||
| 218 | This option enables support for the RTC, thus enabling time to be | 278 | This option enables support for the RTC, thus enabling time to be | 
| 219 | tracked, even when system is powered down. This is available on-chip | 279 | tracked, even when system is powered down. This is available on-chip | 
| 220 | on the MN103E010. | 280 | on the MN103E010. | 
| @@ -306,14 +366,23 @@ config MN10300_TTYSM1 | |||
| 306 | 366 | ||
| 307 | choice | 367 | choice | 
| 308 | prompt "Select the timer to supply the clock for SIF1" | 368 | prompt "Select the timer to supply the clock for SIF1" | 
| 309 | default MN10300_TTYSM0_TIMER9 | 369 | default MN10300_TTYSM1_TIMER12 \ | 
| 370 | if !(AM33_2 || AM33_3) | ||
| 371 | default MN10300_TTYSM1_TIMER9 \ | ||
| 372 | if AM33_2 || AM33_3 | ||
| 310 | depends on MN10300_TTYSM1 | 373 | depends on MN10300_TTYSM1 | 
| 311 | 374 | ||
| 375 | config MN10300_TTYSM1_TIMER12 | ||
| 376 | bool "Use timer 12 (16-bit)" | ||
| 377 | depends on !(AM33_2 || AM33_3) | ||
| 378 | |||
| 312 | config MN10300_TTYSM1_TIMER9 | 379 | config MN10300_TTYSM1_TIMER9 | 
| 313 | bool "Use timer 9 (16-bit)" | 380 | bool "Use timer 9 (16-bit)" | 
| 381 | depends on AM33_2 || AM33_3 | ||
| 314 | 382 | ||
| 315 | config MN10300_TTYSM1_TIMER3 | 383 | config MN10300_TTYSM1_TIMER3 | 
| 316 | bool "Use timer 3 (8-bit)" | 384 | bool "Use timer 3 (8-bit)" | 
| 385 | depends on AM33_2 || AM33_3 | ||
| 317 | 386 | ||
| 318 | endchoice | 387 | endchoice | 
| 319 | 388 | ||
| @@ -328,17 +397,107 @@ config MN10300_TTYSM2 | |||
| 328 | 397 | ||
| 329 | choice | 398 | choice | 
| 330 | prompt "Select the timer to supply the clock for SIF2" | 399 | prompt "Select the timer to supply the clock for SIF2" | 
| 331 | default MN10300_TTYSM0_TIMER10 | 400 | default MN10300_TTYSM2_TIMER3 \ | 
| 401 | if !(AM33_2 || AM33_3) | ||
| 402 | default MN10300_TTYSM2_TIMER10 \ | ||
| 403 | if AM33_2 || AM33_3 | ||
| 332 | depends on MN10300_TTYSM2 | 404 | depends on MN10300_TTYSM2 | 
| 333 | 405 | ||
| 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 | |||
| 334 | config MN10300_TTYSM2_TIMER10 | 418 | config MN10300_TTYSM2_TIMER10 | 
| 335 | bool "Use timer 10 (16-bit)" | 419 | bool "Use timer 10 (16-bit)" | 
| 420 | depends on AM33_2 || AM33_3 | ||
| 336 | 421 | ||
| 337 | endchoice | 422 | endchoice | 
| 338 | 423 | ||
| 339 | config MN10300_TTYSM2_CTS | 424 | config MN10300_TTYSM2_CTS | 
| 340 | bool "Enable the use of the CTS line /dev/ttySM2" | 425 | bool "Enable the use of the CTS line /dev/ttySM2" | 
| 341 | depends on MN10300_TTYSM2 | 426 | depends on MN10300_TTYSM2 && AM33_2 | 
| 427 | |||
| 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 | ||
| 342 | 501 | ||
| 343 | endmenu | 502 | endmenu | 
| 344 | 503 | ||
| diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index ac5c6bdb2f05..7120282bf0d8 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile | |||
| @@ -36,6 +36,9 @@ endif | |||
| 36 | ifeq ($(CONFIG_MN10300_PROC_MN103E010),y) | 36 | ifeq ($(CONFIG_MN10300_PROC_MN103E010),y) | 
| 37 | PROCESSOR := mn103e010 | 37 | PROCESSOR := mn103e010 | 
| 38 | endif | 38 | endif | 
| 39 | ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y) | ||
| 40 | PROCESSOR := mn2ws0050 | ||
| 41 | endif | ||
| 39 | 42 | ||
| 40 | ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y) | 43 | ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y) | 
| 41 | UNIT := asb2303 | 44 | UNIT := asb2303 | 
| @@ -43,6 +46,9 @@ endif | |||
| 43 | ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y) | 46 | ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y) | 
| 44 | UNIT := asb2305 | 47 | UNIT := asb2305 | 
| 45 | endif | 48 | endif | 
| 49 | ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y) | ||
| 50 | UNIT := asb2364 | ||
| 51 | endif | ||
| 46 | 52 | ||
| 47 | 53 | ||
| 48 | head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o | 54 | head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o | 
| diff --git a/arch/mn10300/boot/compressed/head.S b/arch/mn10300/boot/compressed/head.S index 502e1eb56709..7b50345b9e84 100644 --- a/arch/mn10300/boot/compressed/head.S +++ b/arch/mn10300/boot/compressed/head.S | |||
| @@ -14,10 +14,29 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> | 
| 16 | #include <asm/cpu-regs.h> | 16 | #include <asm/cpu-regs.h> | 
| 17 | #include <asm/cache.h> | ||
| 18 | #ifdef CONFIG_SMP | ||
| 19 | #include <proc/smp-regs.h> | ||
| 20 | #endif | ||
| 17 | 21 | ||
| 18 | .globl startup_32 | 22 | .globl startup_32 | 
| 19 | startup_32: | 23 | 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 | ||
| 21 | mov param_save_area,a0 | 40 | mov param_save_area,a0 | 
| 22 | mov d0,(a0) | 41 | mov d0,(a0) | 
| 23 | mov d1,(4,a0) | 42 | mov d1,(4,a0) | 
| @@ -37,8 +56,15 @@ startup_32: | |||
| 37 | mov (a0),d0 | 56 | mov (a0),d0 | 
| 38 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy | 57 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy | 
| 39 | lne | 58 | lne | 
| 40 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD,d0 # writethru dcache | 59 | |
| 60 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
| 61 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
| 62 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | ||
| 63 | #else | ||
| 64 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | ||
| 65 | #endif /* WBACK */ | ||
| 41 | movhu d0,(a0) # enable | 66 | movhu d0,(a0) # enable | 
| 67 | #endif /* !ENABLED */ | ||
| 42 | 68 | ||
| 43 | # clear the BSS area | 69 | # clear the BSS area | 
| 44 | mov __bss_start,a0 | 70 | mov __bss_start,a0 | 
| @@ -54,6 +80,9 @@ bssclear_end: | |||
| 54 | 80 | ||
| 55 | # decompress the kernel | 81 | # decompress the kernel | 
| 56 | call decompress_kernel[],0 | 82 | call decompress_kernel[],0 | 
| 83 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
| 84 | call mn10300_dcache_flush_inv[],0 | ||
| 85 | #endif | ||
| 57 | 86 | ||
| 58 | # disable caches again | 87 | # disable caches again | 
| 59 | mov CHCTR,a0 | 88 | mov CHCTR,a0 | 
| @@ -69,10 +98,46 @@ bssclear_end: | |||
| 69 | mov (4,a0),d1 | 98 | mov (4,a0),d1 | 
| 70 | mov (8,a0),d2 | 99 | mov (8,a0),d2 | 
| 71 | 100 | ||
| 101 | # jump to the kernel proper entry point | ||
| 72 | mov a3,sp | 102 | mov a3,sp | 
| 73 | mov CONFIG_KERNEL_TEXT_ADDRESS,a0 | 103 | mov CONFIG_KERNEL_TEXT_ADDRESS,a0 | 
| 74 | jmp (a0) | 104 | jmp (a0) | 
| 75 | 105 | ||
| 106 | |||
| 107 | ############################################################################### | ||
| 108 | # | ||
| 109 | # Cache flush routines | ||
| 110 | # | ||
| 111 | ############################################################################### | ||
| 112 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
| 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 | ############################################################################### | ||
| 76 | .data | 141 | .data | 
| 77 | .align 4 | 142 | .align 4 | 
| 78 | param_save_area: | 143 | param_save_area: | 
| diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig index d80dfcb2c902..3f749b69ca71 100644 --- a/arch/mn10300/configs/asb2303_defconfig +++ b/arch/mn10300/configs/asb2303_defconfig | |||
| @@ -12,6 +12,8 @@ CONFIG_SLAB=y | |||
| 12 | CONFIG_PROFILING=y | 12 | CONFIG_PROFILING=y | 
| 13 | # CONFIG_BLOCK is not set | 13 | # CONFIG_BLOCK is not set | 
| 14 | CONFIG_PREEMPT=y | 14 | CONFIG_PREEMPT=y | 
| 15 | CONFIG_NO_HZ=y | ||
| 16 | CONFIG_HIGH_RES_TIMERS=y | ||
| 15 | CONFIG_MN10300_RTC=y | 17 | CONFIG_MN10300_RTC=y | 
| 16 | CONFIG_MN10300_TTYSM_CONSOLE=y | 18 | CONFIG_MN10300_TTYSM_CONSOLE=y | 
| 17 | CONFIG_MN10300_TTYSM0=y | 19 | CONFIG_MN10300_TTYSM0=y | 
| diff --git a/arch/mn10300/configs/asb2364_defconfig b/arch/mn10300/configs/asb2364_defconfig new file mode 100644 index 000000000000..83ce2f27b12a --- /dev/null +++ b/arch/mn10300/configs/asb2364_defconfig | |||
| @@ -0,0 +1,98 @@ | |||
| 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 | ||
| diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index f0cc1f84a72f..92d2f9298e38 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h | |||
| @@ -1 +1,351 @@ | |||
| 1 | /* MN10300 Atomic counter operations | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _ASM_ATOMIC_H | ||
| 12 | #define _ASM_ATOMIC_H | ||
| 13 | |||
| 14 | #include <asm/irqflags.h> | ||
| 15 | |||
| 16 | #ifndef __ASSEMBLY__ | ||
| 17 | |||
| 18 | #ifdef CONFIG_SMP | ||
| 19 | #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 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 | ||
| 1 | #include <asm-generic/atomic.h> | 123 | #include <asm-generic/atomic.h> | 
| 124 | #else | ||
| 125 | |||
| 126 | /* | ||
| 127 | * Atomic operations that C can't guarantee us. Useful for | ||
| 128 | * resource counting etc.. | ||
| 129 | */ | ||
| 130 | |||
| 131 | #define ATOMIC_INIT(i) { (i) } | ||
| 132 | |||
| 133 | #ifdef __KERNEL__ | ||
| 134 | |||
| 135 | /** | ||
| 136 | * atomic_read - read atomic variable | ||
| 137 | * @v: pointer of type atomic_t | ||
| 138 | * | ||
| 139 | * Atomically reads the value of @v. Note that the guaranteed | ||
| 140 | * useful range of an atomic_t is only 24 bits. | ||
| 141 | */ | ||
| 142 | #define atomic_read(v) ((v)->counter) | ||
| 143 | |||
| 144 | /** | ||
| 145 | * atomic_set - set atomic variable | ||
| 146 | * @v: pointer of type atomic_t | ||
| 147 | * @i: required value | ||
| 148 | * | ||
| 149 | * Atomically sets the value of @v to @i. Note that the guaranteed | ||
| 150 | * useful range of an atomic_t is only 24 bits. | ||
| 151 | */ | ||
| 152 | #define atomic_set(v, i) (((v)->counter) = (i)) | ||
| 153 | |||
| 154 | /** | ||
| 155 | * atomic_add_return - add integer to atomic variable | ||
| 156 | * @i: integer value to add | ||
| 157 | * @v: pointer of type atomic_t | ||
| 158 | * | ||
| 159 | * Atomically adds @i to @v and returns the result | ||
| 160 | * Note that the guaranteed useful range of an atomic_t is only 24 bits. | ||
| 161 | */ | ||
| 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 */ | ||
| diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h index 3f50e9661076..3b8a868188f5 100644 --- a/arch/mn10300/include/asm/bitops.h +++ b/arch/mn10300/include/asm/bitops.h | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | #define clear_bit(nr, addr) ___clear_bit((nr), (addr)) | 57 | #define clear_bit(nr, addr) ___clear_bit((nr), (addr)) | 
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | static inline void __clear_bit(int nr, volatile void *addr) | 60 | static inline void __clear_bit(unsigned long nr, volatile void *addr) | 
| 61 | { | 61 | { | 
| 62 | unsigned int *a = (unsigned int *) addr; | 62 | unsigned int *a = (unsigned int *) addr; | 
| 63 | int mask; | 63 | int mask; | 
| @@ -70,15 +70,15 @@ static inline void __clear_bit(int nr, volatile void *addr) | |||
| 70 | /* | 70 | /* | 
| 71 | * test bit | 71 | * test bit | 
| 72 | */ | 72 | */ | 
| 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) | 
| 74 | { | 74 | { | 
| 75 | return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31)); | 75 | return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31)); | 
| 76 | } | 76 | } | 
| 77 | 77 | ||
| 78 | /* | 78 | /* | 
| 79 | * change bit | 79 | * change bit | 
| 80 | */ | 80 | */ | 
| 81 | static inline void __change_bit(int nr, volatile void *addr) | 81 | static inline void __change_bit(unsigned long nr, volatile void *addr) | 
| 82 | { | 82 | { | 
| 83 | int mask; | 83 | int mask; | 
| 84 | unsigned int *a = (unsigned int *) addr; | 84 | unsigned int *a = (unsigned int *) addr; | 
| @@ -88,7 +88,7 @@ static inline void __change_bit(int nr, volatile void *addr) | |||
| 88 | *a ^= mask; | 88 | *a ^= mask; | 
| 89 | } | 89 | } | 
| 90 | 90 | ||
| 91 | extern void change_bit(int nr, volatile void *addr); | 91 | extern void change_bit(unsigned long nr, volatile void *addr); | 
| 92 | 92 | ||
| 93 | /* | 93 | /* | 
| 94 | * test and set bit | 94 | * test and set bit | 
| @@ -135,7 +135,7 @@ extern void change_bit(int nr, volatile void *addr); | |||
| 135 | /* | 135 | /* | 
| 136 | * test and change bit | 136 | * test and change bit | 
| 137 | */ | 137 | */ | 
| 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) | 
| 139 | { | 139 | { | 
| 140 | int mask, retval; | 140 | int mask, retval; | 
| 141 | unsigned int *a = (unsigned int *)addr; | 141 | unsigned int *a = (unsigned int *)addr; | 
| @@ -148,7 +148,7 @@ static inline int __test_and_change_bit(int nr, volatile void *addr) | |||
| 148 | return retval; | 148 | return retval; | 
| 149 | } | 149 | } | 
| 150 | 150 | ||
| 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); | 
| 152 | 152 | ||
| 153 | #include <asm-generic/bitops/lock.h> | 153 | #include <asm-generic/bitops/lock.h> | 
| 154 | 154 | ||
| diff --git a/arch/mn10300/include/asm/cache.h b/arch/mn10300/include/asm/cache.h index 781bf613366d..f29cde2cfc91 100644 --- a/arch/mn10300/include/asm/cache.h +++ b/arch/mn10300/include/asm/cache.h | |||
| @@ -43,14 +43,18 @@ | |||
| 43 | 43 | ||
| 44 | /* instruction cache access registers */ | 44 | /* instruction cache access registers */ | 
| 45 | #define ICACHE_DATA(WAY, ENTRY, OFF) \ | 45 | #define ICACHE_DATA(WAY, ENTRY, OFF) \ | 
| 46 | __SYSREG(0xc8000000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10 + (OFF) * 4, u32) | 46 | __SYSREG(0xc8000000 + (WAY) * L1_CACHE_WAYDISP + \ | 
| 47 | (ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32) | ||
| 47 | #define ICACHE_TAG(WAY, ENTRY) \ | 48 | #define ICACHE_TAG(WAY, ENTRY) \ | 
| 48 | __SYSREG(0xc8100000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10, u32) | 49 | __SYSREG(0xc8100000 + (WAY) * L1_CACHE_WAYDISP + \ | 
| 50 | (ENTRY) * L1_CACHE_BYTES, u32) | ||
| 49 | 51 | ||
| 50 | /* instruction cache access registers */ | 52 | /* data cache access registers */ | 
| 51 | #define DCACHE_DATA(WAY, ENTRY, OFF) \ | 53 | #define DCACHE_DATA(WAY, ENTRY, OFF) \ | 
| 52 | __SYSREG(0xc8200000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10 + (OFF) * 4, u32) | 54 | __SYSREG(0xc8200000 + (WAY) * L1_CACHE_WAYDISP + \ | 
| 55 | (ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32) | ||
| 53 | #define DCACHE_TAG(WAY, ENTRY) \ | 56 | #define DCACHE_TAG(WAY, ENTRY) \ | 
| 54 | __SYSREG(0xc8300000 + (WAY) * L1_CACHE_WAYDISP + (ENTRY) * 0x10, u32) | 57 | __SYSREG(0xc8300000 + (WAY) * L1_CACHE_WAYDISP + \ | 
| 58 | (ENTRY) * L1_CACHE_BYTES, u32) | ||
| 55 | 59 | ||
| 56 | #endif /* _ASM_CACHE_H */ | 60 | #endif /* _ASM_CACHE_H */ | 
| diff --git a/arch/mn10300/include/asm/cacheflush.h b/arch/mn10300/include/asm/cacheflush.h index 29e692f7f030..faed90240ded 100644 --- a/arch/mn10300/include/asm/cacheflush.h +++ b/arch/mn10300/include/asm/cacheflush.h | |||
| @@ -17,66 +17,55 @@ | |||
| 17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> | 
| 18 | 18 | ||
| 19 | /* | 19 | /* | 
| 20 | * virtually-indexed cache management (our cache is physically indexed) | 20 | * Primitive routines | 
| 21 | */ | 21 | */ | 
| 22 | #define flush_cache_all() do {} while (0) | 22 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 
| 23 | #define flush_cache_mm(mm) do {} while (0) | 23 | extern void mn10300_local_icache_inv(void); | 
| 24 | #define flush_cache_dup_mm(mm) do {} while (0) | 24 | extern void mn10300_local_icache_inv_page(unsigned long start); | 
| 25 | #define flush_cache_range(mm, start, end) do {} while (0) | 25 | extern void mn10300_local_icache_inv_range(unsigned long start, unsigned long end); | 
| 26 | #define flush_cache_page(vma, vmaddr, pfn) do {} while (0) | 26 | extern void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size); | 
| 27 | #define flush_cache_vmap(start, end) do {} while (0) | 27 | extern void mn10300_local_dcache_inv(void); | 
| 28 | #define flush_cache_vunmap(start, end) do {} while (0) | 28 | extern void mn10300_local_dcache_inv_page(unsigned long start); | 
| 29 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | 29 | extern void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end); | 
| 30 | #define flush_dcache_page(page) do {} while (0) | 30 | extern void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size); | 
| 31 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | ||
| 32 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | ||
| 33 | |||
| 34 | /* | ||
| 35 | * physically-indexed cache management | ||
| 36 | */ | ||
| 37 | #ifndef CONFIG_MN10300_CACHE_DISABLED | ||
| 38 | |||
| 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 | ||
| 65 | extern void mn10300_icache_inv(void); | 31 | 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); | ||
| 66 | extern void mn10300_dcache_inv(void); | 35 | extern void mn10300_dcache_inv(void); | 
| 67 | extern void mn10300_dcache_inv_page(unsigned start); | 36 | extern void mn10300_dcache_inv_page(unsigned long start); | 
| 68 | extern void mn10300_dcache_inv_range(unsigned start, unsigned end); | 37 | extern void mn10300_dcache_inv_range(unsigned long start, unsigned long end); | 
| 69 | extern void mn10300_dcache_inv_range2(unsigned start, unsigned size); | 38 | extern void mn10300_dcache_inv_range2(unsigned long start, unsigned long size); | 
| 70 | #ifdef CONFIG_MN10300_CACHE_WBACK | 39 | #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); | ||
| 71 | extern void mn10300_dcache_flush(void); | 48 | extern void mn10300_dcache_flush(void); | 
| 72 | extern void mn10300_dcache_flush_page(unsigned start); | 49 | extern void mn10300_dcache_flush_page(unsigned long start); | 
| 73 | extern void mn10300_dcache_flush_range(unsigned start, unsigned end); | 50 | extern void mn10300_dcache_flush_range(unsigned long start, unsigned long end); | 
| 74 | extern void mn10300_dcache_flush_range2(unsigned start, unsigned size); | 51 | extern void mn10300_dcache_flush_range2(unsigned long start, unsigned long size); | 
| 75 | extern void mn10300_dcache_flush_inv(void); | 52 | extern void mn10300_dcache_flush_inv(void); | 
| 76 | extern void mn10300_dcache_flush_inv_page(unsigned start); | 53 | extern void mn10300_dcache_flush_inv_page(unsigned long start); | 
| 77 | extern void mn10300_dcache_flush_inv_range(unsigned start, unsigned end); | 54 | extern void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end); | 
| 78 | extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size); | 55 | extern void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size); | 
| 79 | #else | 56 | #else | 
| 57 | #define mn10300_local_dcache_flush() do {} while (0) | ||
| 58 | #define mn10300_local_dcache_flush_page(start) do {} while (0) | ||
| 59 | #define mn10300_local_dcache_flush_range(start, end) do {} while (0) | ||
| 60 | #define mn10300_local_dcache_flush_range2(start, size) do {} while (0) | ||
| 61 | #define mn10300_local_dcache_flush_inv() \ | ||
| 62 | mn10300_local_dcache_inv() | ||
| 63 | #define mn10300_local_dcache_flush_inv_page(start) \ | ||
| 64 | mn10300_local_dcache_inv_page(start) | ||
| 65 | #define mn10300_local_dcache_flush_inv_range(start, end) \ | ||
| 66 | mn10300_local_dcache_inv_range(start, end) | ||
| 67 | #define mn10300_local_dcache_flush_inv_range2(start, size) \ | ||
| 68 | mn10300_local_dcache_inv_range2(start, size) | ||
| 80 | #define mn10300_dcache_flush() do {} while (0) | 69 | #define mn10300_dcache_flush() do {} while (0) | 
| 81 | #define mn10300_dcache_flush_page(start) do {} while (0) | 70 | #define mn10300_dcache_flush_page(start) do {} while (0) | 
| 82 | #define mn10300_dcache_flush_range(start, end) do {} while (0) | 71 | #define mn10300_dcache_flush_range(start, end) do {} while (0) | 
| @@ -90,7 +79,26 @@ extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size); | |||
| 90 | mn10300_dcache_inv_range2((start), (size)) | 79 | mn10300_dcache_inv_range2((start), (size)) | 
| 91 | #endif /* CONFIG_MN10300_CACHE_WBACK */ | 80 | #endif /* CONFIG_MN10300_CACHE_WBACK */ | 
| 92 | #else | 81 | #else | 
| 82 | #define mn10300_local_icache_inv() do {} while (0) | ||
| 83 | #define mn10300_local_icache_inv_page(start) do {} while (0) | ||
| 84 | #define mn10300_local_icache_inv_range(start, end) do {} while (0) | ||
| 85 | #define mn10300_local_icache_inv_range2(start, size) do {} while (0) | ||
| 86 | #define mn10300_local_dcache_inv() do {} while (0) | ||
| 87 | #define mn10300_local_dcache_inv_page(start) do {} while (0) | ||
| 88 | #define mn10300_local_dcache_inv_range(start, end) do {} while (0) | ||
| 89 | #define mn10300_local_dcache_inv_range2(start, size) do {} while (0) | ||
| 90 | #define mn10300_local_dcache_flush() do {} while (0) | ||
| 91 | #define mn10300_local_dcache_flush_inv_page(start) do {} while (0) | ||
| 92 | #define mn10300_local_dcache_flush_inv() do {} while (0) | ||
| 93 | #define mn10300_local_dcache_flush_inv_range(start, end)do {} while (0) | ||
| 94 | #define mn10300_local_dcache_flush_inv_range2(start, size) do {} while (0) | ||
| 95 | #define mn10300_local_dcache_flush_page(start) do {} while (0) | ||
| 96 | #define mn10300_local_dcache_flush_range(start, end) do {} while (0) | ||
| 97 | #define mn10300_local_dcache_flush_range2(start, size) do {} while (0) | ||
| 93 | #define mn10300_icache_inv() do {} while (0) | 98 | #define mn10300_icache_inv() do {} while (0) | 
| 99 | #define mn10300_icache_inv_page(start) do {} while (0) | ||
| 100 | #define mn10300_icache_inv_range(start, end) do {} while (0) | ||
| 101 | #define mn10300_icache_inv_range2(start, size) do {} while (0) | ||
| 94 | #define mn10300_dcache_inv() do {} while (0) | 102 | #define mn10300_dcache_inv() do {} while (0) | 
| 95 | #define mn10300_dcache_inv_page(start) do {} while (0) | 103 | #define mn10300_dcache_inv_page(start) do {} while (0) | 
| 96 | #define mn10300_dcache_inv_range(start, end) do {} while (0) | 104 | #define mn10300_dcache_inv_range(start, end) do {} while (0) | 
| @@ -103,10 +111,56 @@ extern void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size); | |||
| 103 | #define mn10300_dcache_flush_page(start) do {} while (0) | 111 | #define mn10300_dcache_flush_page(start) do {} while (0) | 
| 104 | #define mn10300_dcache_flush_range(start, end) do {} while (0) | 112 | #define mn10300_dcache_flush_range(start, end) do {} while (0) | 
| 105 | #define mn10300_dcache_flush_range2(start, size) do {} while (0) | 113 | #define mn10300_dcache_flush_range2(start, size) do {} while (0) | 
| 106 | #endif /* CONFIG_MN10300_CACHE_DISABLED */ | 114 | #endif /* CONFIG_MN10300_CACHE_ENABLED */ | 
| 115 | |||
| 116 | /* | ||
| 117 | * Virtually-indexed cache management (our cache is physically indexed) | ||
| 118 | */ | ||
| 119 | #define flush_cache_all() do {} while (0) | ||
| 120 | #define flush_cache_mm(mm) do {} while (0) | ||
| 121 | #define flush_cache_dup_mm(mm) do {} while (0) | ||
| 122 | #define flush_cache_range(mm, start, end) do {} while (0) | ||
| 123 | #define flush_cache_page(vma, vmaddr, pfn) do {} while (0) | ||
| 124 | #define flush_cache_vmap(start, end) do {} while (0) | ||
| 125 | #define flush_cache_vunmap(start, end) do {} while (0) | ||
| 126 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
| 127 | #define flush_dcache_page(page) do {} while (0) | ||
| 128 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | ||
| 129 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Physically-indexed cache management | ||
| 133 | */ | ||
| 134 | #if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) | ||
| 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) | ||
| 107 | 161 | ||
| 108 | /* | 162 | /* | 
| 109 | * internal debugging function | 163 | * Internal debugging function | 
| 110 | */ | 164 | */ | 
| 111 | #ifdef CONFIG_DEBUG_PAGEALLOC | 165 | #ifdef CONFIG_DEBUG_PAGEALLOC | 
| 112 | extern void kernel_map_pages(struct page *page, int numpages, int enable); | 166 | extern void kernel_map_pages(struct page *page, int numpages, int enable); | 
| diff --git a/arch/mn10300/include/asm/cpu-regs.h b/arch/mn10300/include/asm/cpu-regs.h index 757e9b5388ea..90ed4a365c97 100644 --- a/arch/mn10300/include/asm/cpu-regs.h +++ b/arch/mn10300/include/asm/cpu-regs.h | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> | 
| 16 | #endif | 16 | #endif | 
| 17 | 17 | ||
| 18 | #ifdef CONFIG_MN10300_CPU_AM33V2 | ||
| 19 | /* we tell the compiler to pretend to be AM33 so that it doesn't try and use | 18 | /* we tell the compiler to pretend to be AM33 so that it doesn't try and use | 
| 20 | * the FP regs, but tell the assembler that we're actually allowed AM33v2 | 19 | * the FP regs, but tell the assembler that we're actually allowed AM33v2 | 
| 21 | * instructions */ | 20 | * instructions */ | 
| @@ -24,7 +23,6 @@ asm(" .am33_2\n"); | |||
| 24 | #else | 23 | #else | 
| 25 | .am33_2 | 24 | .am33_2 | 
| 26 | #endif | 25 | #endif | 
| 27 | #endif | ||
| 28 | 26 | ||
| 29 | #ifdef __KERNEL__ | 27 | #ifdef __KERNEL__ | 
| 30 | 28 | ||
| @@ -58,6 +56,9 @@ asm(" .am33_2\n"); | |||
| 58 | #define EPSW_nAR 0x00040000 /* register bank control */ | 56 | #define EPSW_nAR 0x00040000 /* register bank control */ | 
| 59 | #define EPSW_ML 0x00080000 /* monitor level */ | 57 | #define EPSW_ML 0x00080000 /* monitor level */ | 
| 60 | #define EPSW_FE 0x00100000 /* FPU enable */ | 58 | #define EPSW_FE 0x00100000 /* FPU enable */ | 
| 59 | #define EPSW_IM_SHIFT 8 /* EPSW_IM_SHIFT determines the interrupt mode */ | ||
| 60 | |||
| 61 | #define NUM2EPSW_IM(num) ((num) << EPSW_IM_SHIFT) | ||
| 61 | 62 | ||
| 62 | /* FPU registers */ | 63 | /* FPU registers */ | 
| 63 | #define FPCR_EF_I 0x00000001 /* inexact result FPU exception flag */ | 64 | #define FPCR_EF_I 0x00000001 /* inexact result FPU exception flag */ | 
| @@ -99,9 +100,11 @@ asm(" .am33_2\n"); | |||
| 99 | #define CPUREV __SYSREGC(0xc0000050, u32) /* CPU revision register */ | 100 | #define CPUREV __SYSREGC(0xc0000050, u32) /* CPU revision register */ | 
| 100 | #define CPUREV_TYPE 0x0000000f /* CPU type */ | 101 | #define CPUREV_TYPE 0x0000000f /* CPU type */ | 
| 101 | #define CPUREV_TYPE_S 0 | 102 | #define CPUREV_TYPE_S 0 | 
| 102 | #define CPUREV_TYPE_AM33V1 0x00000000 /* - AM33 V1 core, AM33/1.00 arch */ | 103 | #define CPUREV_TYPE_AM33_1 0x00000000 /* - AM33-1 core, AM33/1.00 arch */ | 
| 103 | #define CPUREV_TYPE_AM33V2 0x00000001 /* - AM33 V2 core, AM33/2.00 arch */ | 104 | #define CPUREV_TYPE_AM33_2 0x00000001 /* - AM33-2 core, AM33/2.00 arch */ | 
| 104 | #define CPUREV_TYPE_AM34V1 0x00000002 /* - AM34 V1 core, AM33/2.00 arch */ | 105 | #define CPUREV_TYPE_AM34_1 0x00000002 /* - AM34-1 core, AM33/2.00 arch */ | 
| 106 | #define CPUREV_TYPE_AM33_3 0x00000003 /* - AM33-3 core, AM33/2.00 arch */ | ||
| 107 | #define CPUREV_TYPE_AM34_2 0x00000004 /* - AM34-2 core, AM33/3.00 arch */ | ||
| 105 | #define CPUREV_REVISION 0x000000f0 /* CPU revision */ | 108 | #define CPUREV_REVISION 0x000000f0 /* CPU revision */ | 
| 106 | #define CPUREV_REVISION_S 4 | 109 | #define CPUREV_REVISION_S 4 | 
| 107 | #define CPUREV_ICWAY 0x00000f00 /* number of instruction cache ways */ | 110 | #define CPUREV_ICWAY 0x00000f00 /* number of instruction cache ways */ | 
| @@ -180,6 +183,21 @@ asm(" .am33_2\n"); | |||
| 180 | #define CHCTR_ICWMD 0x0f00 /* instruction cache way mode */ | 183 | #define CHCTR_ICWMD 0x0f00 /* instruction cache way mode */ | 
| 181 | #define CHCTR_DCWMD 0xf000 /* data cache way mode */ | 184 | #define CHCTR_DCWMD 0xf000 /* data cache way mode */ | 
| 182 | 185 | ||
| 186 | #ifdef CONFIG_AM34_2 | ||
| 187 | #define ICIVCR __SYSREG(0xc0000c00, u32) /* icache area invalidate control */ | ||
| 188 | #define ICIVCR_ICIVBSY 0x00000008 /* icache area invalidate busy */ | ||
| 189 | #define ICIVCR_ICI 0x00000001 /* icache area invalidate */ | ||
| 190 | |||
| 191 | #define ICIVMR __SYSREG(0xc0000c04, u32) /* icache area invalidate mask */ | ||
| 192 | |||
| 193 | #define DCPGCR __SYSREG(0xc0000c10, u32) /* data cache area purge control */ | ||
| 194 | #define DCPGCR_DCPGBSY 0x00000008 /* data cache area purge busy */ | ||
| 195 | #define DCPGCR_DCP 0x00000002 /* data cache area purge */ | ||
| 196 | #define DCPGCR_DCI 0x00000001 /* data cache area invalidate */ | ||
| 197 | |||
| 198 | #define DCPGMR __SYSREG(0xc0000c14, u32) /* data cache area purge mask */ | ||
| 199 | #endif /* CONFIG_AM34_2 */ | ||
| 200 | |||
| 183 | /* MMU control registers */ | 201 | /* MMU control registers */ | 
| 184 | #define MMUCTR __SYSREG(0xc0000090, u32) /* MMU control register */ | 202 | #define MMUCTR __SYSREG(0xc0000090, u32) /* MMU control register */ | 
| 185 | #define MMUCTR_IRP 0x0000003f /* instruction TLB replace pointer */ | 203 | #define MMUCTR_IRP 0x0000003f /* instruction TLB replace pointer */ | 
| @@ -203,6 +221,9 @@ asm(" .am33_2\n"); | |||
| 203 | #define MMUCTR_DTL_LOCK0_3 0x03000000 /* - entry 0-3 locked */ | 221 | #define MMUCTR_DTL_LOCK0_3 0x03000000 /* - entry 0-3 locked */ | 
| 204 | #define MMUCTR_DTL_LOCK0_7 0x04000000 /* - entry 0-7 locked */ | 222 | #define MMUCTR_DTL_LOCK0_7 0x04000000 /* - entry 0-7 locked */ | 
| 205 | #define MMUCTR_DTL_LOCK0_15 0x05000000 /* - entry 0-15 locked */ | 223 | #define MMUCTR_DTL_LOCK0_15 0x05000000 /* - entry 0-15 locked */ | 
| 224 | #ifdef CONFIG_AM34_2 | ||
| 225 | #define MMUCTR_WTE 0x80000000 /* write-through cache TLB entry bit enable */ | ||
| 226 | #endif | ||
| 206 | 227 | ||
| 207 | #define PIDR __SYSREG(0xc0000094, u16) /* PID register */ | 228 | #define PIDR __SYSREG(0xc0000094, u16) /* PID register */ | 
| 208 | #define PIDR_PID 0x00ff /* process identifier */ | 229 | #define PIDR_PID 0x00ff /* process identifier */ | 
| @@ -231,14 +252,6 @@ asm(" .am33_2\n"); | |||
| 231 | #define xPTEL_PS_4Mb 0x00000c00 /* - 4Mb page */ | 252 | #define xPTEL_PS_4Mb 0x00000c00 /* - 4Mb page */ | 
| 232 | #define xPTEL_PPN 0xfffff006 /* physical page number */ | 253 | #define xPTEL_PPN 0xfffff006 /* physical page number */ | 
| 233 | 254 | ||
| 234 | #define xPTEL_V_BIT 0 /* bit numbers corresponding to above masks */ | ||
| 235 | #define xPTEL_UNUSED1_BIT 1 | ||
| 236 | #define xPTEL_UNUSED2_BIT 2 | ||
| 237 | #define xPTEL_C_BIT 3 | ||
| 238 | #define xPTEL_PV_BIT 4 | ||
| 239 | #define xPTEL_D_BIT 5 | ||
| 240 | #define xPTEL_G_BIT 9 | ||
| 241 | |||
| 242 | #define IPTEU __SYSREG(0xc00000a4, u32) /* instruction TLB virtual addr */ | 255 | #define IPTEU __SYSREG(0xc00000a4, u32) /* instruction TLB virtual addr */ | 
| 243 | #define DPTEU __SYSREG(0xc00000b4, u32) /* data TLB virtual addr */ | 256 | #define DPTEU __SYSREG(0xc00000b4, u32) /* data TLB virtual addr */ | 
| 244 | #define xPTEU_VPN 0xfffffc00 /* virtual page number */ | 257 | #define xPTEU_VPN 0xfffffc00 /* virtual page number */ | 
| @@ -262,7 +275,16 @@ asm(" .am33_2\n"); | |||
| 262 | #define xPTEL2_PS_128Kb 0x00000100 /* - 128Kb page */ | 275 | #define xPTEL2_PS_128Kb 0x00000100 /* - 128Kb page */ | 
| 263 | #define xPTEL2_PS_1Kb 0x00000200 /* - 1Kb page */ | 276 | #define xPTEL2_PS_1Kb 0x00000200 /* - 1Kb page */ | 
| 264 | #define xPTEL2_PS_4Mb 0x00000300 /* - 4Mb page */ | 277 | #define xPTEL2_PS_4Mb 0x00000300 /* - 4Mb page */ | 
| 265 | #define xPTEL2_PPN 0xfffffc00 /* physical page number */ | 278 | #define xPTEL2_CWT 0x00000400 /* cacheable write-through */ | 
| 279 | #define xPTEL2_UNUSED1 0x00000800 /* unused bit (broadcast mask) */ | ||
| 280 | #define xPTEL2_PPN 0xfffff000 /* physical page number */ | ||
| 281 | |||
| 282 | #define xPTEL2_V_BIT 0 /* bit numbers corresponding to above masks */ | ||
| 283 | #define xPTEL2_C_BIT 1 | ||
| 284 | #define xPTEL2_PV_BIT 2 | ||
| 285 | #define xPTEL2_D_BIT 3 | ||
| 286 | #define xPTEL2_G_BIT 7 | ||
| 287 | #define xPTEL2_UNUSED1_BIT 11 | ||
| 266 | 288 | ||
| 267 | #define MMUFCR __SYSREGC(0xc000009c, u32) /* MMU exception cause */ | 289 | #define MMUFCR __SYSREGC(0xc000009c, u32) /* MMU exception cause */ | 
| 268 | #define MMUFCR_IFC __SYSREGC(0xc000009c, u16) /* MMU instruction excep cause */ | 290 | #define MMUFCR_IFC __SYSREGC(0xc000009c, u16) /* MMU instruction excep cause */ | 
| @@ -285,6 +307,47 @@ asm(" .am33_2\n"); | |||
| 285 | #define MMUFCR_xFC_PR_RWK_RWU 0x01c0 /* - R/W kernel and R/W user */ | 307 | #define MMUFCR_xFC_PR_RWK_RWU 0x01c0 /* - R/W kernel and R/W user */ | 
| 286 | #define MMUFCR_xFC_ILLADDR 0x0200 /* illegal address excep flag */ | 308 | #define MMUFCR_xFC_ILLADDR 0x0200 /* illegal address excep flag */ | 
| 287 | 309 | ||
| 310 | #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 311 | /* atomic operation registers */ | ||
| 312 | #define AAR __SYSREG(0xc0000a00, u32) /* cacheable address */ | ||
| 313 | #define AAR2 __SYSREG(0xc0000a04, u32) /* uncacheable address */ | ||
| 314 | #define ADR __SYSREG(0xc0000a08, u32) /* data */ | ||
| 315 | #define ASR __SYSREG(0xc0000a0c, u32) /* status */ | ||
| 316 | #define AARU __SYSREG(0xd400aa00, u32) /* user address */ | ||
| 317 | #define ADRU __SYSREG(0xd400aa08, u32) /* user data */ | ||
| 318 | #define ASRU __SYSREG(0xd400aa0c, u32) /* user status */ | ||
| 319 | |||
| 320 | #define ASR_RW 0x00000008 /* read */ | ||
| 321 | #define ASR_BW 0x00000004 /* bus error */ | ||
| 322 | #define ASR_IW 0x00000002 /* interrupt */ | ||
| 323 | #define ASR_LW 0x00000001 /* bus lock */ | ||
| 324 | |||
| 325 | #define ASRU_RW ASR_RW /* read */ | ||
| 326 | #define ASRU_BW ASR_BW /* bus error */ | ||
| 327 | #define ASRU_IW ASR_IW /* interrupt */ | ||
| 328 | #define ASRU_LW ASR_LW /* bus lock */ | ||
| 329 | |||
| 330 | /* in inline ASM, we stick the base pointer in to a reg and use offsets from | ||
| 331 | * it */ | ||
| 332 | #define ATOMIC_OPS_BASE_ADDR 0xc0000a00 | ||
| 333 | #ifndef __ASSEMBLY__ | ||
| 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 | |||
| 288 | #endif /* __KERNEL__ */ | 351 | #endif /* __KERNEL__ */ | 
| 289 | 352 | ||
| 290 | #endif /* _ASM_CPU_REGS_H */ | 353 | #endif /* _ASM_CPU_REGS_H */ | 
| diff --git a/arch/mn10300/include/asm/dmactl-regs.h b/arch/mn10300/include/asm/dmactl-regs.h index 58a199da0f4a..80337b339c90 100644 --- a/arch/mn10300/include/asm/dmactl-regs.h +++ b/arch/mn10300/include/asm/dmactl-regs.h | |||
| @@ -11,91 +11,6 @@ | |||
| 11 | #ifndef _ASM_DMACTL_REGS_H | 11 | #ifndef _ASM_DMACTL_REGS_H | 
| 12 | #define _ASM_DMACTL_REGS_H | 12 | #define _ASM_DMACTL_REGS_H | 
| 13 | 13 | ||
| 14 | #include <asm/cpu-regs.h> | 14 | #include <proc/dmactl-regs.h> | 
| 15 | |||
| 16 | #ifdef __KERNEL__ | ||
| 17 | |||
| 18 | /* DMA registers */ | ||
| 19 | #define DMxCTR(N) __SYSREG(0xd2000000 + ((N) * 0x100), u32) /* control reg */ | ||
| 20 | #define DMxCTR_BG 0x0000001f /* transfer request source */ | ||
| 21 | #define DMxCTR_BG_SOFT 0x00000000 /* - software source */ | ||
| 22 | #define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */ | ||
| 23 | #define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */ | ||
| 24 | #define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */ | ||
| 25 | #define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */ | ||
| 26 | #define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */ | ||
| 27 | #define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */ | ||
| 28 | #define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */ | ||
| 29 | #define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */ | ||
| 30 | #define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */ | ||
| 31 | #define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */ | ||
| 32 | #define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */ | ||
| 33 | #define DMxCTR_BG_AFE 0x0000000d /* - analogue front-end interrupt source */ | ||
| 34 | #define DMxCTR_BG_ADC 0x0000000e /* - A/D conversion end interrupt source */ | ||
| 35 | #define DMxCTR_BG_IRDA 0x0000000f /* - IrDA interrupt source */ | ||
| 36 | #define DMxCTR_BG_RTC 0x00000010 /* - RTC interrupt source */ | ||
| 37 | #define DMxCTR_BG_XIRQ0 0x00000011 /* - XIRQ0 pin interrupt source */ | ||
| 38 | #define DMxCTR_BG_XIRQ1 0x00000012 /* - XIRQ1 pin interrupt source */ | ||
| 39 | #define DMxCTR_BG_XDMR0 0x00000013 /* - external request 0 source (XDMR0 pin) */ | ||
| 40 | #define DMxCTR_BG_XDMR1 0x00000014 /* - external request 1 source (XDMR1 pin) */ | ||
| 41 | #define DMxCTR_SAM 0x000000e0 /* DMA transfer src addr mode */ | ||
| 42 | #define DMxCTR_SAM_INCR 0x00000000 /* - increment */ | ||
| 43 | #define DMxCTR_SAM_DECR 0x00000020 /* - decrement */ | ||
| 44 | #define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */ | ||
| 45 | #define DMxCTR_DAM 0x00000000 /* DMA transfer dest addr mode */ | ||
| 46 | #define DMxCTR_DAM_INCR 0x00000000 /* - increment */ | ||
| 47 | #define DMxCTR_DAM_DECR 0x00000100 /* - decrement */ | ||
| 48 | #define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */ | ||
| 49 | #define DMxCTR_TM 0x00001800 /* DMA transfer mode */ | ||
| 50 | #define DMxCTR_TM_BATCH 0x00000000 /* - batch transfer */ | ||
| 51 | #define DMxCTR_TM_INTERM 0x00001000 /* - intermittent transfer */ | ||
| 52 | #define DMxCTR_UT 0x00006000 /* DMA transfer unit */ | ||
| 53 | #define DMxCTR_UT_1 0x00000000 /* - 1 byte */ | ||
| 54 | #define DMxCTR_UT_2 0x00002000 /* - 2 byte */ | ||
| 55 | #define DMxCTR_UT_4 0x00004000 /* - 4 byte */ | ||
| 56 | #define DMxCTR_UT_16 0x00006000 /* - 16 byte */ | ||
| 57 | #define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */ | ||
| 58 | #define DMxCTR_RQM 0x00060000 /* external request input source mode */ | ||
| 59 | #define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */ | ||
| 60 | #define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */ | ||
| 61 | #define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */ | ||
| 62 | #define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */ | ||
| 63 | #define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */ | ||
| 64 | #define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */ | ||
| 65 | |||
| 66 | #define DMxSRC(N) __SYSREG(0xd2000004 + ((N) * 0x100), u32) /* control reg */ | ||
| 67 | |||
| 68 | #define DMxDST(N) __SYSREG(0xd2000008 + ((N) * 0x100), u32) /* src addr reg */ | ||
| 69 | |||
| 70 | #define DMxSIZ(N) __SYSREG(0xd200000c + ((N) * 0x100), u32) /* dest addr reg */ | ||
| 71 | #define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */ | ||
| 72 | |||
| 73 | #define DMxCYC(N) __SYSREG(0xd2000010 + ((N) * 0x100), u32) /* intermittent | ||
| 74 | * size reg */ | ||
| 75 | #define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */ | ||
| 76 | |||
| 77 | #define DM0IRQ 16 /* DMA channel 0 complete IRQ */ | ||
| 78 | #define DM1IRQ 17 /* DMA channel 1 complete IRQ */ | ||
| 79 | #define DM2IRQ 18 /* DMA channel 2 complete IRQ */ | ||
| 80 | #define DM3IRQ 19 /* DMA channel 3 complete IRQ */ | ||
| 81 | |||
| 82 | #define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */ | ||
| 83 | #define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */ | ||
| 84 | #define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */ | ||
| 85 | #define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */ | ||
| 86 | |||
| 87 | #ifndef __ASSEMBLY__ | ||
| 88 | |||
| 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__ */ | ||
| 100 | 15 | ||
| 101 | #endif /* _ASM_DMACTL_REGS_H */ | 16 | #endif /* _ASM_DMACTL_REGS_H */ | 
| diff --git a/arch/mn10300/include/asm/elf.h b/arch/mn10300/include/asm/elf.h index e5fa97cd9a14..8157c9267f42 100644 --- a/arch/mn10300/include/asm/elf.h +++ b/arch/mn10300/include/asm/elf.h | |||
| @@ -32,6 +32,12 @@ | |||
| 32 | #define R_MN10300_ALIGN 34 /* Alignment requirement. */ | 32 | #define R_MN10300_ALIGN 34 /* Alignment requirement. */ | 
| 33 | 33 | ||
| 34 | /* | 34 | /* | 
| 35 | * AM33/AM34 HW Capabilities | ||
| 36 | */ | ||
| 37 | #define HWCAP_MN10300_ATOMIC_OP_UNIT 1 /* Has AM34 Atomic Operations */ | ||
| 38 | |||
| 39 | |||
| 40 | /* | ||
| 35 | * ELF register definitions.. | 41 | * ELF register definitions.. | 
| 36 | */ | 42 | */ | 
| 37 | typedef unsigned long elf_greg_t; | 43 | typedef unsigned long elf_greg_t; | 
| @@ -47,8 +53,6 @@ typedef struct { | |||
| 47 | u_int32_t fpcr; | 53 | u_int32_t fpcr; | 
| 48 | } elf_fpregset_t; | 54 | } elf_fpregset_t; | 
| 49 | 55 | ||
| 50 | extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); | ||
| 51 | |||
| 52 | /* | 56 | /* | 
| 53 | * This is used to ensure we don't load something for the wrong architecture | 57 | * This is used to ensure we don't load something for the wrong architecture | 
| 54 | */ | 58 | */ | 
| @@ -130,7 +134,11 @@ do { \ | |||
| 130 | * instruction set this CPU supports. This could be done in user space, | 134 | * instruction set this CPU supports. This could be done in user space, | 
| 131 | * but it's not easy, and we've already done it here. | 135 | * but it's not easy, and we've already done it here. | 
| 132 | */ | 136 | */ | 
| 137 | #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 138 | #define ELF_HWCAP (HWCAP_MN10300_ATOMIC_OP_UNIT) | ||
| 139 | #else | ||
| 133 | #define ELF_HWCAP (0) | 140 | #define ELF_HWCAP (0) | 
| 141 | #endif | ||
| 134 | 142 | ||
| 135 | /* | 143 | /* | 
| 136 | * This yields a string that ld.so will use to load implementation | 144 | * This yields a string that ld.so will use to load implementation | 
| diff --git a/arch/mn10300/include/asm/exceptions.h b/arch/mn10300/include/asm/exceptions.h index fa16466ef3f9..ca3e20508c77 100644 --- a/arch/mn10300/include/asm/exceptions.h +++ b/arch/mn10300/include/asm/exceptions.h | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | /* | 16 | /* | 
| 17 | * define the breakpoint instruction opcode to use | 17 | * define the breakpoint instruction opcode to use | 
| 18 | * - note that the JTAG unit steals 0xFF, so we want to avoid that if we can | 18 | * - note that the JTAG unit steals 0xFF, so you can't use JTAG and GDBSTUB at | 
| 19 | * (can use 0xF7) | 19 | * the same time. | 
| 20 | */ | 20 | */ | 
| 21 | #define GDBSTUB_BKPT 0xFF | 21 | #define GDBSTUB_BKPT 0xFF | 
| 22 | 22 | ||
| @@ -90,7 +90,6 @@ enum exception_code { | |||
| 90 | 90 | ||
| 91 | extern void __set_intr_stub(enum exception_code code, void *handler); | 91 | extern void __set_intr_stub(enum exception_code code, void *handler); | 
| 92 | extern void set_intr_stub(enum exception_code code, void *handler); | 92 | extern void set_intr_stub(enum exception_code code, void *handler); | 
| 93 | extern void set_jtag_stub(enum exception_code code, void *handler); | ||
| 94 | 93 | ||
| 95 | struct pt_regs; | 94 | struct pt_regs; | 
| 96 | 95 | ||
| @@ -102,7 +101,6 @@ extern asmlinkage void dtlb_aerror(void); | |||
| 102 | extern asmlinkage void raw_bus_error(void); | 101 | extern asmlinkage void raw_bus_error(void); | 
| 103 | extern asmlinkage void double_fault(void); | 102 | extern asmlinkage void double_fault(void); | 
| 104 | extern asmlinkage int system_call(struct pt_regs *); | 103 | extern asmlinkage int system_call(struct pt_regs *); | 
| 105 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); | ||
| 106 | extern asmlinkage void nmi(struct pt_regs *, enum exception_code); | 104 | extern asmlinkage void nmi(struct pt_regs *, enum exception_code); | 
| 107 | extern asmlinkage void uninitialised_exception(struct pt_regs *, | 105 | extern asmlinkage void uninitialised_exception(struct pt_regs *, | 
| 108 | enum exception_code); | 106 | enum exception_code); | 
| @@ -116,6 +114,8 @@ extern void die(const char *, struct pt_regs *, enum exception_code) | |||
| 116 | 114 | ||
| 117 | extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code); | 115 | extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code); | 
| 118 | 116 | ||
| 117 | #define NUM2EXCEP_IRQ_LEVEL(num) (EXCEP_IRQ_LEVEL0 + (num) * 8) | ||
| 118 | |||
| 119 | #endif /* __ASSEMBLY__ */ | 119 | #endif /* __ASSEMBLY__ */ | 
| 120 | 120 | ||
| 121 | #endif /* _ASM_EXCEPTIONS_H */ | 121 | #endif /* _ASM_EXCEPTIONS_H */ | 
| diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h index 64a2b83a7a6a..b7625de8eade 100644 --- a/arch/mn10300/include/asm/fpu.h +++ b/arch/mn10300/include/asm/fpu.h | |||
| @@ -12,74 +12,125 @@ | |||
| 12 | #ifndef _ASM_FPU_H | 12 | #ifndef _ASM_FPU_H | 
| 13 | #define _ASM_FPU_H | 13 | #define _ASM_FPU_H | 
| 14 | 14 | ||
| 15 | #include <asm/processor.h> | 15 | #ifndef __ASSEMBLY__ | 
| 16 | |||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <asm/exceptions.h> | ||
| 16 | #include <asm/sigcontext.h> | 19 | #include <asm/sigcontext.h> | 
| 17 | #include <asm/user.h> | ||
| 18 | 20 | ||
| 19 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ | 
| 20 | 22 | ||
| 21 | /* the task that owns the FPU state */ | 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 */ | ||
| 22 | extern struct task_struct *fpu_state_owner; | 29 | extern struct task_struct *fpu_state_owner; | 
| 30 | #endif | ||
| 23 | 31 | ||
| 24 | #define set_using_fpu(tsk) \ | 32 | #if (THREAD_USING_FPU & ~0xff) | 
| 25 | do { \ | 33 | #error THREAD_USING_FPU must be smaller than 0x100. | 
| 26 | (tsk)->thread.fpu_flags |= THREAD_USING_FPU; \ | 34 | #endif | 
| 27 | } while (0) | ||
| 28 | 35 | ||
| 29 | #define clear_using_fpu(tsk) \ | 36 | static inline void set_using_fpu(struct task_struct *tsk) | 
| 30 | do { \ | 37 | { | 
| 31 | (tsk)->thread.fpu_flags &= ~THREAD_USING_FPU; \ | 38 | asm volatile( | 
| 32 | } while (0) | 39 | "bset %0,(0,%1)" | 
| 40 | : | ||
| 41 | : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags) | ||
| 42 | : "memory", "cc"); | ||
| 43 | } | ||
| 33 | 44 | ||
| 34 | #define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU) | 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 | } | ||
| 35 | 53 | ||
| 36 | #define unlazy_fpu(tsk) \ | 54 | #define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU) | 
| 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) | ||
| 64 | 55 | ||
| 65 | extern asmlinkage void fpu_init_state(void); | ||
| 66 | extern asmlinkage void fpu_kill_state(struct task_struct *); | 56 | extern asmlinkage void fpu_kill_state(struct task_struct *); | 
| 67 | extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code); | ||
| 68 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); | 57 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); | 
| 69 | 58 | extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code); | |
| 70 | #ifdef CONFIG_FPU | 59 | extern asmlinkage void fpu_init_state(void); | 
| 71 | extern asmlinkage void fpu_save(struct fpu_state_struct *); | 60 | 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 | */ | ||
| 81 | extern int fpu_setup_sigcontext(struct fpucontext *buf); | 61 | extern int fpu_setup_sigcontext(struct fpucontext *buf); | 
| 82 | extern int fpu_restore_sigcontext(struct fpucontext *buf); | 62 | extern int fpu_restore_sigcontext(struct fpucontext *buf); | 
| 83 | 63 | ||
| 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 | |||
| 84 | #endif /* __KERNEL__ */ | 134 | #endif /* __KERNEL__ */ | 
| 135 | #endif /* !__ASSEMBLY__ */ | ||
| 85 | #endif /* _ASM_FPU_H */ | 136 | #endif /* _ASM_FPU_H */ | 
| diff --git a/arch/mn10300/include/asm/frame.inc b/arch/mn10300/include/asm/frame.inc index 5b1949bdf039..2ee58e3eb6b3 100644 --- a/arch/mn10300/include/asm/frame.inc +++ b/arch/mn10300/include/asm/frame.inc | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #ifndef __ASM_OFFSETS_H__ | 18 | #ifndef __ASM_OFFSETS_H__ | 
| 19 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> | 
| 20 | #endif | 20 | #endif | 
| 21 | #include <asm/thread_info.h> | ||
| 21 | 22 | ||
| 22 | #define pi break | 23 | #define pi break | 
| 23 | 24 | ||
| @@ -37,11 +38,15 @@ | |||
| 37 | movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp) | 38 | movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp) | 
| 38 | mov sp,fp # FRAME pointer in A3 | 39 | mov sp,fp # FRAME pointer in A3 | 
| 39 | add -12,sp # allow for calls to be made | 40 | add -12,sp # allow for calls to be made | 
| 40 | mov (__frame),a1 | ||
| 41 | mov a1,(REG_NEXT,fp) | ||
| 42 | mov fp,(__frame) | ||
| 43 | 41 | ||
| 44 | and ~EPSW_FE,epsw # disable the FPU inside the kernel | 42 | # push the exception frame onto the front of the list | 
| 43 | GET_THREAD_INFO a1 | ||
| 44 | mov (TI_frame,a1),a0 | ||
| 45 | mov a0,(REG_NEXT,fp) | ||
| 46 | mov fp,(TI_frame,a1) | ||
| 47 | |||
| 48 | # disable the FPU inside the kernel | ||
| 49 | and ~EPSW_FE,epsw | ||
| 45 | 50 | ||
| 46 | # we may be holding current in E2 | 51 | # we may be holding current in E2 | 
| 47 | #ifdef CONFIG_MN10300_CURRENT_IN_E2 | 52 | #ifdef CONFIG_MN10300_CURRENT_IN_E2 | 
| @@ -57,10 +62,11 @@ | |||
| 57 | .macro RESTORE_ALL | 62 | .macro RESTORE_ALL | 
| 58 | # peel back the stack to the calling frame | 63 | # peel back the stack to the calling frame | 
| 59 | # - this permits execve() to discard extra frames due to kernel syscalls | 64 | # - this permits execve() to discard extra frames due to kernel syscalls | 
| 60 | mov (__frame),fp | 65 | GET_THREAD_INFO a0 | 
| 66 | mov (TI_frame,a0),fp | ||
| 61 | mov fp,sp | 67 | mov fp,sp | 
| 62 | mov (REG_NEXT,fp),d0 # userspace has regs->next == 0 | 68 | mov (REG_NEXT,fp),d0 | 
| 63 | mov d0,(__frame) | 69 | mov d0,(TI_frame,a0) # userspace has regs->next == 0 | 
| 64 | 70 | ||
| 65 | #ifndef CONFIG_MN10300_USING_JTAG | 71 | #ifndef CONFIG_MN10300_USING_JTAG | 
| 66 | mov (REG_EPSW,fp),d0 | 72 | mov (REG_EPSW,fp),d0 | 
| diff --git a/arch/mn10300/include/asm/gdb-stub.h b/arch/mn10300/include/asm/gdb-stub.h index 41ed26763964..f5495ad82b77 100644 --- a/arch/mn10300/include/asm/gdb-stub.h +++ b/arch/mn10300/include/asm/gdb-stub.h | |||
| @@ -110,7 +110,7 @@ extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code); | |||
| 110 | extern asmlinkage void __gdbstub_bug_trap(void); | 110 | extern asmlinkage void __gdbstub_bug_trap(void); | 
| 111 | extern asmlinkage void __gdbstub_pause(void); | 111 | extern asmlinkage void __gdbstub_pause(void); | 
| 112 | 112 | ||
| 113 | #ifndef CONFIG_MN10300_CACHE_DISABLED | 113 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 
| 114 | extern asmlinkage void gdbstub_purge_cache(void); | 114 | extern asmlinkage void gdbstub_purge_cache(void); | 
| 115 | #else | 115 | #else | 
| 116 | #define gdbstub_purge_cache() do {} while (0) | 116 | #define gdbstub_purge_cache() do {} while (0) | 
| diff --git a/arch/mn10300/include/asm/hardirq.h b/arch/mn10300/include/asm/hardirq.h index 54d950117674..0000d650b55f 100644 --- a/arch/mn10300/include/asm/hardirq.h +++ b/arch/mn10300/include/asm/hardirq.h | |||
| @@ -19,9 +19,10 @@ | |||
| 19 | /* assembly code in softirq.h is sensitive to the offsets of these fields */ | 19 | /* assembly code in softirq.h is sensitive to the offsets of these fields */ | 
| 20 | typedef struct { | 20 | typedef struct { | 
| 21 | unsigned int __softirq_pending; | 21 | unsigned int __softirq_pending; | 
| 22 | unsigned long idle_timestamp; | 22 | #ifdef CONFIG_MN10300_WD_TIMER | 
| 23 | unsigned int __nmi_count; /* arch dependent */ | 23 | unsigned int __nmi_count; /* arch dependent */ | 
| 24 | unsigned int __irq_count; /* arch dependent */ | 24 | unsigned int __irq_count; /* arch dependent */ | 
| 25 | #endif | ||
| 25 | } ____cacheline_aligned irq_cpustat_t; | 26 | } ____cacheline_aligned irq_cpustat_t; | 
| 26 | 27 | ||
| 27 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | 28 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | 
| diff --git a/arch/mn10300/include/asm/highmem.h b/arch/mn10300/include/asm/highmem.h index e2155e686451..bfe2d88604d9 100644 --- a/arch/mn10300/include/asm/highmem.h +++ b/arch/mn10300/include/asm/highmem.h | |||
| @@ -87,7 +87,7 @@ static inline unsigned long __kmap_atomic(struct page *page) | |||
| 87 | BUG(); | 87 | BUG(); | 
| 88 | #endif | 88 | #endif | 
| 89 | set_pte(kmap_pte - idx, mk_pte(page, kmap_prot)); | 89 | set_pte(kmap_pte - idx, mk_pte(page, kmap_prot)); | 
| 90 | __flush_tlb_one(vaddr); | 90 | local_flush_tlb_one(vaddr); | 
| 91 | 91 | ||
| 92 | return vaddr; | 92 | return vaddr; | 
| 93 | } | 93 | } | 
| @@ -116,7 +116,7 @@ static inline void __kunmap_atomic(unsigned long vaddr) | |||
| 116 | * this pte without first remap it | 116 | * this pte without first remap it | 
| 117 | */ | 117 | */ | 
| 118 | pte_clear(kmap_pte - idx); | 118 | pte_clear(kmap_pte - idx); | 
| 119 | __flush_tlb_one(vaddr); | 119 | local_flush_tlb_one(vaddr); | 
| 120 | } | 120 | } | 
| 121 | #endif | 121 | #endif | 
| 122 | 122 | ||
| diff --git a/arch/mn10300/include/asm/intctl-regs.h b/arch/mn10300/include/asm/intctl-regs.h index ba544c796c5a..585b708c2bc0 100644 --- a/arch/mn10300/include/asm/intctl-regs.h +++ b/arch/mn10300/include/asm/intctl-regs.h | |||
| @@ -15,24 +15,19 @@ | |||
| 15 | 15 | ||
| 16 | #ifdef __KERNEL__ | 16 | #ifdef __KERNEL__ | 
| 17 | 17 | ||
| 18 | /* interrupt controller registers */ | 18 | /* | 
| 19 | #define GxICR(X) __SYSREG(0xd4000000 + (X) * 4, u16) /* group irq ctrl regs */ | 19 | * Interrupt controller registers | 
| 20 | 20 | * - Registers 64-191 are at addresses offset from the main array | |
| 21 | #define IAGR __SYSREG(0xd4000100, u16) /* intr acceptance group reg */ | 21 | */ | 
| 22 | #define IAGR_GN 0x00fc /* group number register | 22 | #define GxICR(X) \ | 
| 23 | * (documentation _has_ to be wrong) | 23 | __SYSREG(0xd4000000 + (X) * 4 + \ | 
| 24 | */ | 24 | (((X) >= 64) && ((X) < 192)) * 0xf00, u16) | 
| 25 | 25 | ||
| 26 | #define EXTMD __SYSREG(0xd4000200, u16) /* external pin intr spec reg */ | 26 | #define GxICR_u8(X) \ | 
| 27 | #define GET_XIRQ_TRIGGER(X) ((EXTMD >> ((X) * 2)) & 3) | 27 | __SYSREG(0xd4000000 + (X) * 4 + \ | 
| 28 | (((X) >= 64) && ((X) < 192)) * 0xf00, u8) | ||
| 28 | 29 | ||
| 29 | #define SET_XIRQ_TRIGGER(X,Y) \ | 30 | #include <proc/intctl-regs.h> | 
| 30 | do { \ | ||
| 31 | u16 x = EXTMD; \ | ||
| 32 | x &= ~(3 << ((X) * 2)); \ | ||
| 33 | x |= ((Y) & 3) << ((X) * 2); \ | ||
| 34 | EXTMD = x; \ | ||
| 35 | } while (0) | ||
| 36 | 31 | ||
| 37 | #define XIRQ_TRIGGER_LOWLEVEL 0 | 32 | #define XIRQ_TRIGGER_LOWLEVEL 0 | 
| 38 | #define XIRQ_TRIGGER_HILEVEL 1 | 33 | #define XIRQ_TRIGGER_HILEVEL 1 | 
| @@ -59,10 +54,18 @@ do { \ | |||
| 59 | #define GxICR_LEVEL_5 0x5000 /* - level 5 */ | 54 | #define GxICR_LEVEL_5 0x5000 /* - level 5 */ | 
| 60 | #define GxICR_LEVEL_6 0x6000 /* - level 6 */ | 55 | #define GxICR_LEVEL_6 0x6000 /* - level 6 */ | 
| 61 | #define GxICR_LEVEL_SHIFT 12 | 56 | #define GxICR_LEVEL_SHIFT 12 | 
| 57 | #define GxICR_NMI 0x8000 /* nmi request flag */ | ||
| 58 | |||
| 59 | #define NUM2GxICR_LEVEL(num) ((num) << GxICR_LEVEL_SHIFT) | ||
| 62 | 60 | ||
| 63 | #ifndef __ASSEMBLY__ | 61 | #ifndef __ASSEMBLY__ | 
| 64 | extern void set_intr_level(int irq, u16 level); | 62 | extern void set_intr_level(int irq, u16 level); | 
| 65 | extern void set_intr_postackable(int irq); | 63 | extern void mn10300_intc_set_level(unsigned int irq, unsigned int level); | 
| 64 | extern void mn10300_intc_clear(unsigned int irq); | ||
| 65 | extern void mn10300_intc_set(unsigned int irq); | ||
| 66 | extern void mn10300_intc_enable(unsigned int irq); | ||
| 67 | extern void mn10300_intc_disable(unsigned int irq); | ||
| 68 | extern void mn10300_set_lateack_irq_type(int irq); | ||
| 66 | #endif | 69 | #endif | 
| 67 | 70 | ||
| 68 | /* external interrupts */ | 71 | /* external interrupts */ | 
| diff --git a/arch/mn10300/include/asm/io.h b/arch/mn10300/include/asm/io.h index c1a4119e6497..787255da744e 100644 --- a/arch/mn10300/include/asm/io.h +++ b/arch/mn10300/include/asm/io.h | |||
| @@ -206,6 +206,19 @@ static inline void outsl(unsigned long addr, const void *buffer, int count) | |||
| 206 | #define iowrite32_rep(p, src, count) \ | 206 | #define iowrite32_rep(p, src, count) \ | 
| 207 | outsl((unsigned long) (p), (src), (count)) | 207 | outsl((unsigned long) (p), (src), (count)) | 
| 208 | 208 | ||
| 209 | #define readsb(p, dst, count) \ | ||
| 210 | insb((unsigned long) (p), (dst), (count)) | ||
| 211 | #define readsw(p, dst, count) \ | ||
| 212 | insw((unsigned long) (p), (dst), (count)) | ||
| 213 | #define readsl(p, dst, count) \ | ||
| 214 | insl((unsigned long) (p), (dst), (count)) | ||
| 215 | |||
| 216 | #define writesb(p, src, count) \ | ||
| 217 | outsb((unsigned long) (p), (src), (count)) | ||
| 218 | #define writesw(p, src, count) \ | ||
| 219 | outsw((unsigned long) (p), (src), (count)) | ||
| 220 | #define writesl(p, src, count) \ | ||
| 221 | outsl((unsigned long) (p), (src), (count)) | ||
| 209 | 222 | ||
| 210 | #define IO_SPACE_LIMIT 0xffffffff | 223 | #define IO_SPACE_LIMIT 0xffffffff | 
| 211 | 224 | ||
| diff --git a/arch/mn10300/include/asm/irq.h b/arch/mn10300/include/asm/irq.h index 25c045d16d1c..1a73fb3f60c6 100644 --- a/arch/mn10300/include/asm/irq.h +++ b/arch/mn10300/include/asm/irq.h | |||
| @@ -21,8 +21,16 @@ | |||
| 21 | /* this number is used when no interrupt has been assigned */ | 21 | /* this number is used when no interrupt has been assigned */ | 
| 22 | #define NO_IRQ INT_MAX | 22 | #define NO_IRQ INT_MAX | 
| 23 | 23 | ||
| 24 | /* hardware irq numbers */ | 24 | /* | 
| 25 | #define NR_IRQS GxICR_NUM_IRQS | 25 | * hardware irq numbers | 
| 26 | * - the ASB2364 has an FPGA with an IRQ multiplexer on it | ||
| 27 | */ | ||
| 28 | #ifdef CONFIG_MN10300_UNIT_ASB2364 | ||
| 29 | #include <unit/irq.h> | ||
| 30 | #else | ||
| 31 | #define NR_CPU_IRQS GxICR_NUM_IRQS | ||
| 32 | #define NR_IRQS NR_CPU_IRQS | ||
| 33 | #endif | ||
| 26 | 34 | ||
| 27 | /* external hardware irq numbers */ | 35 | /* external hardware irq numbers */ | 
| 28 | #define NR_XIRQS GxICR_NUM_XIRQS | 36 | #define NR_XIRQS GxICR_NUM_XIRQS | 
| diff --git a/arch/mn10300/include/asm/irq_regs.h b/arch/mn10300/include/asm/irq_regs.h index a848cd232eb4..97d0cb5af807 100644 --- a/arch/mn10300/include/asm/irq_regs.h +++ b/arch/mn10300/include/asm/irq_regs.h | |||
| @@ -18,7 +18,11 @@ | |||
| 18 | #define ARCH_HAS_OWN_IRQ_REGS | 18 | #define ARCH_HAS_OWN_IRQ_REGS | 
| 19 | 19 | ||
| 20 | #ifndef __ASSEMBLY__ | 20 | #ifndef __ASSEMBLY__ | 
| 21 | #define get_irq_regs() (__frame) | 21 | static inline __attribute__((const)) | 
| 22 | struct pt_regs *get_irq_regs(void) | ||
| 23 | { | ||
| 24 | return current_frame(); | ||
| 25 | } | ||
| 22 | #endif | 26 | #endif | 
| 23 | 27 | ||
| 24 | #endif /* _ASM_IRQ_REGS_H */ | 28 | #endif /* _ASM_IRQ_REGS_H */ | 
| diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index 5e529a117cb2..7a7ae12c7119 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h | |||
| @@ -13,6 +13,9 @@ | |||
| 13 | #define _ASM_IRQFLAGS_H | 13 | #define _ASM_IRQFLAGS_H | 
| 14 | 14 | ||
| 15 | #include <asm/cpu-regs.h> | 15 | #include <asm/cpu-regs.h> | 
| 16 | #ifndef __ASSEMBLY__ | ||
| 17 | #include <linux/smp.h> | ||
| 18 | #endif | ||
| 16 | 19 | ||
| 17 | /* | 20 | /* | 
| 18 | * interrupt control | 21 | * interrupt control | 
| @@ -23,11 +26,7 @@ | |||
| 23 | * - level 6 - timer interrupt | 26 | * - level 6 - timer interrupt | 
| 24 | * - "enabled": run in IM7 | 27 | * - "enabled": run in IM7 | 
| 25 | */ | 28 | */ | 
| 26 | #ifdef CONFIG_MN10300_TTYSM | 29 | #define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT) | 
| 27 | #define MN10300_CLI_LEVEL EPSW_IM_2 | ||
| 28 | #else | ||
| 29 | #define MN10300_CLI_LEVEL EPSW_IM_1 | ||
| 30 | #endif | ||
| 31 | 30 | ||
| 32 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ | 
| 33 | 32 | ||
| @@ -64,11 +63,12 @@ static inline unsigned long arch_local_irq_save(void) | |||
| 64 | /* | 63 | /* | 
| 65 | * we make sure arch_irq_enable() doesn't cause priority inversion | 64 | * we make sure arch_irq_enable() doesn't cause priority inversion | 
| 66 | */ | 65 | */ | 
| 67 | extern unsigned long __mn10300_irq_enabled_epsw; | 66 | extern unsigned long __mn10300_irq_enabled_epsw[]; | 
| 68 | 67 | ||
| 69 | static inline void arch_local_irq_enable(void) | 68 | static inline void arch_local_irq_enable(void) | 
| 70 | { | 69 | { | 
| 71 | unsigned long tmp; | 70 | unsigned long tmp; | 
| 71 | int cpu = raw_smp_processor_id(); | ||
| 72 | 72 | ||
| 73 | asm volatile( | 73 | asm volatile( | 
| 74 | " mov epsw,%0 \n" | 74 | " mov epsw,%0 \n" | 
| @@ -76,8 +76,8 @@ static inline void arch_local_irq_enable(void) | |||
| 76 | " or %2,%0 \n" | 76 | " or %2,%0 \n" | 
| 77 | " mov %0,epsw \n" | 77 | " mov %0,epsw \n" | 
| 78 | : "=&d"(tmp) | 78 | : "=&d"(tmp) | 
| 79 | : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw) | 79 | : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu]) | 
| 80 | : "memory"); | 80 | : "memory", "cc"); | 
| 81 | } | 81 | } | 
| 82 | 82 | ||
| 83 | static inline void arch_local_irq_restore(unsigned long flags) | 83 | static inline void arch_local_irq_restore(unsigned long flags) | 
| @@ -94,7 +94,7 @@ static inline void arch_local_irq_restore(unsigned long flags) | |||
| 94 | 94 | ||
| 95 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | 95 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | 
| 96 | { | 96 | { | 
| 97 | return (flags & EPSW_IM) <= MN10300_CLI_LEVEL; | 97 | return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7); | 
| 98 | } | 98 | } | 
| 99 | 99 | ||
| 100 | static inline bool arch_irqs_disabled(void) | 100 | static inline bool arch_irqs_disabled(void) | 
| @@ -109,6 +109,9 @@ static inline bool arch_irqs_disabled(void) | |||
| 109 | */ | 109 | */ | 
| 110 | static inline void arch_safe_halt(void) | 110 | static inline void arch_safe_halt(void) | 
| 111 | { | 111 | { | 
| 112 | #ifdef CONFIG_SMP | ||
| 113 | arch_local_irq_enable(); | ||
| 114 | #else | ||
| 112 | asm volatile( | 115 | asm volatile( | 
| 113 | " or %0,epsw \n" | 116 | " or %0,epsw \n" | 
| 114 | " nop \n" | 117 | " nop \n" | 
| @@ -117,7 +120,97 @@ static inline void arch_safe_halt(void) | |||
| 117 | : | 120 | : | 
| 118 | : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP) | 121 | : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP) | 
| 119 | : "cc"); | 122 | : "cc"); | 
| 123 | #endif | ||
| 120 | } | 124 | } | 
| 121 | 125 | ||
| 126 | #define __sleep_cpu() \ | ||
| 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 | |||
| 122 | #endif /* __ASSEMBLY__ */ | 215 | #endif /* __ASSEMBLY__ */ | 
| 123 | #endif /* _ASM_IRQFLAGS_H */ | 216 | #endif /* _ASM_IRQFLAGS_H */ | 
| diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h index cb294c244de3..c8f6c82672ad 100644 --- a/arch/mn10300/include/asm/mmu_context.h +++ b/arch/mn10300/include/asm/mmu_context.h | |||
| @@ -27,28 +27,38 @@ | |||
| 27 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> | 
| 28 | #include <asm-generic/mm_hooks.h> | 28 | #include <asm-generic/mm_hooks.h> | 
| 29 | 29 | ||
| 30 | #define MMU_CONTEXT_TLBPID_NR 256 | ||
| 30 | #define MMU_CONTEXT_TLBPID_MASK 0x000000ffUL | 31 | #define MMU_CONTEXT_TLBPID_MASK 0x000000ffUL | 
| 31 | #define MMU_CONTEXT_VERSION_MASK 0xffffff00UL | 32 | #define MMU_CONTEXT_VERSION_MASK 0xffffff00UL | 
| 32 | #define MMU_CONTEXT_FIRST_VERSION 0x00000100UL | 33 | #define MMU_CONTEXT_FIRST_VERSION 0x00000100UL | 
| 33 | #define MMU_NO_CONTEXT 0x00000000UL | 34 | #define MMU_NO_CONTEXT 0x00000000UL | 
| 34 | 35 | #define MMU_CONTEXT_TLBPID_LOCK_NR 0 | |
| 35 | extern unsigned long mmu_context_cache[NR_CPUS]; | ||
| 36 | #define mm_context(mm) (mm->context.tlbpid[smp_processor_id()]) | ||
| 37 | 36 | ||
| 38 | #define enter_lazy_tlb(mm, tsk) do {} while (0) | 37 | #define enter_lazy_tlb(mm, tsk) do {} while (0) | 
| 39 | 38 | ||
| 39 | static inline void cpu_ran_vm(int cpu, struct mm_struct *mm) | ||
| 40 | { | ||
| 40 | #ifdef CONFIG_SMP | 41 | #ifdef CONFIG_SMP | 
| 41 | #define cpu_ran_vm(cpu, mm) \ | 42 | cpumask_set_cpu(cpu, mm_cpumask(mm)); | 
| 42 | cpumask_set_cpu((cpu), mm_cpumask(mm)) | 43 | #endif | 
| 43 | #define cpu_maybe_ran_vm(cpu, mm) \ | 44 | } | 
| 44 | cpumask_test_and_set_cpu((cpu), mm_cpumask(mm)) | 45 | |
| 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)); | ||
| 45 | #else | 50 | #else | 
| 46 | #define cpu_ran_vm(cpu, mm) do {} while (0) | 51 | return true; | 
| 47 | #define cpu_maybe_ran_vm(cpu, mm) true | 52 | #endif | 
| 48 | #endif /* CONFIG_SMP */ | 53 | } | 
| 49 | 54 | ||
| 50 | /* | 55 | #ifdef CONFIG_MN10300_TLB_USE_PIDR | 
| 51 | * allocate an MMU context | 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 | ||
| 52 | */ | 62 | */ | 
| 53 | static inline unsigned long allocate_mmu_context(struct mm_struct *mm) | 63 | static inline unsigned long allocate_mmu_context(struct mm_struct *mm) | 
| 54 | { | 64 | { | 
| @@ -58,7 +68,7 @@ static inline unsigned long allocate_mmu_context(struct mm_struct *mm) | |||
| 58 | if (!(mc & MMU_CONTEXT_TLBPID_MASK)) { | 68 | if (!(mc & MMU_CONTEXT_TLBPID_MASK)) { | 
| 59 | /* we exhausted the TLB PIDs of this version on this CPU, so we | 69 | /* we exhausted the TLB PIDs of this version on this CPU, so we | 
| 60 | * flush this CPU's TLB in its entirety and start new cycle */ | 70 | * flush this CPU's TLB in its entirety and start new cycle */ | 
| 61 | flush_tlb_all(); | 71 | local_flush_tlb_all(); | 
| 62 | 72 | ||
| 63 | /* fix the TLB version if needed (we avoid version #0 so as to | 73 | /* fix the TLB version if needed (we avoid version #0 so as to | 
| 64 | * distingush MMU_NO_CONTEXT) */ | 74 | * distingush MMU_NO_CONTEXT) */ | 
| @@ -101,22 +111,34 @@ static inline int init_new_context(struct task_struct *tsk, | |||
| 101 | } | 111 | } | 
| 102 | 112 | ||
| 103 | /* | 113 | /* | 
| 104 | * destroy context related info for an mm_struct that is about to be put to | ||
| 105 | * rest | ||
| 106 | */ | ||
| 107 | #define destroy_context(mm) do { } while (0) | ||
| 108 | |||
| 109 | /* | ||
| 110 | * after we have set current->mm to a new value, this activates the context for | 114 | * after we have set current->mm to a new value, this activates the context for | 
| 111 | * the new mm so we see the new mappings. | 115 | * the new mm so we see the new mappings. | 
| 112 | */ | 116 | */ | 
| 113 | static inline void activate_context(struct mm_struct *mm, int cpu) | 117 | static inline void activate_context(struct mm_struct *mm) | 
| 114 | { | 118 | { | 
| 115 | PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK; | 119 | PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK; | 
| 116 | } | 120 | } | 
| 121 | #else /* CONFIG_MN10300_TLB_USE_PIDR */ | ||
| 117 | 122 | ||
| 118 | /* | 123 | #define init_new_context(tsk, mm) (0) | 
| 119 | * change between virtual memory sets | 124 | #define activate_context(mm) local_flush_tlb() | 
| 125 | |||
| 126 | #endif /* CONFIG_MN10300_TLB_USE_PIDR */ | ||
| 127 | |||
| 128 | /** | ||
| 129 | * destroy_context - Destroy mm context information | ||
| 130 | * @mm: The MM being destroyed. | ||
| 131 | * | ||
| 132 | * Destroy context related info for an mm_struct that is about to be put to | ||
| 133 | * rest | ||
| 134 | */ | ||
| 135 | #define destroy_context(mm) do {} while (0) | ||
| 136 | |||
| 137 | /** | ||
| 138 | * switch_mm - Change between userspace virtual memory contexts | ||
| 139 | * @prev: The outgoing MM context. | ||
| 140 | * @next: The incoming MM context. | ||
| 141 | * @tsk: The incoming task. | ||
| 120 | */ | 142 | */ | 
| 121 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 143 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 
| 122 | struct task_struct *tsk) | 144 | struct task_struct *tsk) | 
| @@ -124,11 +146,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
| 124 | int cpu = smp_processor_id(); | 146 | int cpu = smp_processor_id(); | 
| 125 | 147 | ||
| 126 | if (prev != next) { | 148 | if (prev != next) { | 
| 149 | #ifdef CONFIG_SMP | ||
| 150 | per_cpu(cpu_tlbstate, cpu).active_mm = next; | ||
| 151 | #endif | ||
| 127 | cpu_ran_vm(cpu, next); | 152 | cpu_ran_vm(cpu, next); | 
| 128 | activate_context(next, cpu); | ||
| 129 | PTBR = (unsigned long) next->pgd; | 153 | PTBR = (unsigned long) next->pgd; | 
| 130 | } else if (!cpu_maybe_ran_vm(cpu, next)) { | 154 | activate_context(next); | 
| 131 | activate_context(next, cpu); | ||
| 132 | } | 155 | } | 
| 133 | } | 156 | } | 
| 134 | 157 | ||
| diff --git a/arch/mn10300/include/asm/pgalloc.h b/arch/mn10300/include/asm/pgalloc.h index a19f11327cd8..146bacf193ea 100644 --- a/arch/mn10300/include/asm/pgalloc.h +++ b/arch/mn10300/include/asm/pgalloc.h | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #ifndef _ASM_PGALLOC_H | 11 | #ifndef _ASM_PGALLOC_H | 
| 12 | #define _ASM_PGALLOC_H | 12 | #define _ASM_PGALLOC_H | 
| 13 | 13 | ||
| 14 | #include <asm/processor.h> | ||
| 15 | #include <asm/page.h> | 14 | #include <asm/page.h> | 
| 16 | #include <linux/threads.h> | 15 | #include <linux/threads.h> | 
| 17 | #include <linux/mm.h> /* for struct page */ | 16 | #include <linux/mm.h> /* for struct page */ | 
| diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h index b049a8bd1577..a1e894b5f65b 100644 --- a/arch/mn10300/include/asm/pgtable.h +++ b/arch/mn10300/include/asm/pgtable.h | |||
| @@ -90,46 +90,58 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
| 90 | * The vmalloc() routines also leaves a hole of 4kB between each vmalloced | 90 | * The vmalloc() routines also leaves a hole of 4kB between each vmalloced | 
| 91 | * area to catch addressing errors. | 91 | * area to catch addressing errors. | 
| 92 | */ | 92 | */ | 
| 93 | #ifndef __ASSEMBLY__ | ||
| 94 | #define VMALLOC_OFFSET (8UL * 1024 * 1024) | ||
| 95 | #define VMALLOC_START (0x70000000UL) | ||
| 96 | #define VMALLOC_END (0x7C000000UL) | ||
| 97 | #else | ||
| 93 | #define VMALLOC_OFFSET (8 * 1024 * 1024) | 98 | #define VMALLOC_OFFSET (8 * 1024 * 1024) | 
| 94 | #define VMALLOC_START (0x70000000) | 99 | #define VMALLOC_START (0x70000000) | 
| 95 | #define VMALLOC_END (0x7C000000) | 100 | #define VMALLOC_END (0x7C000000) | 
| 101 | #endif | ||
| 96 | 102 | ||
| 97 | #ifndef __ASSEMBLY__ | 103 | #ifndef __ASSEMBLY__ | 
| 98 | extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; | 104 | extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; | 
| 99 | #endif | 105 | #endif | 
| 100 | 106 | ||
| 101 | /* IPTEL/DPTEL bit assignments */ | 107 | /* IPTEL2/DPTEL2 bit assignments */ | 
| 102 | #define _PAGE_BIT_VALID xPTEL_V_BIT | 108 | #define _PAGE_BIT_VALID xPTEL2_V_BIT | 
| 103 | #define _PAGE_BIT_ACCESSED xPTEL_UNUSED1_BIT /* mustn't be loaded into IPTEL/DPTEL */ | 109 | #define _PAGE_BIT_CACHE xPTEL2_C_BIT | 
| 104 | #define _PAGE_BIT_NX xPTEL_UNUSED2_BIT /* mustn't be loaded into IPTEL/DPTEL */ | 110 | #define _PAGE_BIT_PRESENT xPTEL2_PV_BIT | 
| 105 | #define _PAGE_BIT_CACHE xPTEL_C_BIT | 111 | #define _PAGE_BIT_DIRTY xPTEL2_D_BIT | 
| 106 | #define _PAGE_BIT_PRESENT xPTEL_PV_BIT | 112 | #define _PAGE_BIT_GLOBAL xPTEL2_G_BIT | 
| 107 | #define _PAGE_BIT_DIRTY xPTEL_D_BIT | 113 | #define _PAGE_BIT_ACCESSED xPTEL2_UNUSED1_BIT /* mustn't be loaded into IPTEL2/DPTEL2 */ | 
| 108 | #define _PAGE_BIT_GLOBAL xPTEL_G_BIT | 114 | |
| 109 | 115 | #define _PAGE_VALID xPTEL2_V | |
| 110 | #define _PAGE_VALID xPTEL_V | 116 | #define _PAGE_CACHE xPTEL2_C | 
| 111 | #define _PAGE_ACCESSED xPTEL_UNUSED1 | 117 | #define _PAGE_PRESENT xPTEL2_PV | 
| 112 | #define _PAGE_NX xPTEL_UNUSED2 /* no-execute bit */ | 118 | #define _PAGE_DIRTY xPTEL2_D | 
| 113 | #define _PAGE_CACHE xPTEL_C | 119 | #define _PAGE_PROT xPTEL2_PR | 
| 114 | #define _PAGE_PRESENT xPTEL_PV | 120 | #define _PAGE_PROT_RKNU xPTEL2_PR_ROK | 
| 115 | #define _PAGE_DIRTY xPTEL_D | 121 | #define _PAGE_PROT_WKNU xPTEL2_PR_RWK | 
| 116 | #define _PAGE_PROT xPTEL_PR | 122 | #define _PAGE_PROT_RKRU xPTEL2_PR_ROK_ROU | 
| 117 | #define _PAGE_PROT_RKNU xPTEL_PR_ROK | 123 | #define _PAGE_PROT_WKRU xPTEL2_PR_RWK_ROU | 
| 118 | #define _PAGE_PROT_WKNU xPTEL_PR_RWK | 124 | #define _PAGE_PROT_WKWU xPTEL2_PR_RWK_RWU | 
| 119 | #define _PAGE_PROT_RKRU xPTEL_PR_ROK_ROU | 125 | #define _PAGE_GLOBAL xPTEL2_G | 
| 120 | #define _PAGE_PROT_WKRU xPTEL_PR_RWK_ROU | 126 | #define _PAGE_PS_MASK xPTEL2_PS | 
| 121 | #define _PAGE_PROT_WKWU xPTEL_PR_RWK_RWU | 127 | #define _PAGE_PS_4Kb xPTEL2_PS_4Kb | 
| 122 | #define _PAGE_GLOBAL xPTEL_G | 128 | #define _PAGE_PS_128Kb xPTEL2_PS_128Kb | 
| 123 | #define _PAGE_PSE xPTEL_PS_4Mb /* 4MB page */ | 129 | #define _PAGE_PS_1Kb xPTEL2_PS_1Kb | 
| 124 | 130 | #define _PAGE_PS_4Mb xPTEL2_PS_4Mb | |
| 125 | #define _PAGE_FILE xPTEL_UNUSED1_BIT /* set:pagecache unset:swap */ | 131 | #define _PAGE_PSE xPTEL2_PS_4Mb /* 4MB page */ | 
| 126 | 132 | #define _PAGE_CACHE_WT xPTEL2_CWT | |
| 127 | #define __PAGE_PROT_UWAUX 0x040 | 133 | #define _PAGE_ACCESSED xPTEL2_UNUSED1 | 
| 128 | #define __PAGE_PROT_USER 0x080 | 134 | #define _PAGE_NX 0 /* no-execute bit */ | 
| 129 | #define __PAGE_PROT_WRITE 0x100 | 135 | |
| 136 | /* If _PAGE_VALID is clear, we use these: */ | ||
| 137 | #define _PAGE_FILE xPTEL2_C /* set:pagecache unset:swap */ | ||
| 138 | #define _PAGE_PROTNONE 0x000 /* If not present */ | ||
| 139 | |||
| 140 | #define __PAGE_PROT_UWAUX 0x010 | ||
| 141 | #define __PAGE_PROT_USER 0x020 | ||
| 142 | #define __PAGE_PROT_WRITE 0x040 | ||
| 130 | 143 | ||
| 131 | #define _PAGE_PRESENTV (_PAGE_PRESENT|_PAGE_VALID) | 144 | #define _PAGE_PRESENTV (_PAGE_PRESENT|_PAGE_VALID) | 
| 132 | #define _PAGE_PROTNONE 0x000 /* If not present */ | ||
| 133 | 145 | ||
| 134 | #ifndef __ASSEMBLY__ | 146 | #ifndef __ASSEMBLY__ | 
| 135 | 147 | ||
| @@ -170,6 +182,9 @@ extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE]; | |||
| 170 | #define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE) | 182 | #define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE) | 
| 171 | #define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC) | 183 | #define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC) | 
| 172 | 184 | ||
| 185 | #define __PAGE_USERIO (__PAGE_KERNEL_BASE | _PAGE_PROT_WKWU | _PAGE_NX) | ||
| 186 | #define PAGE_USERIO __pgprot(__PAGE_USERIO) | ||
| 187 | |||
| 173 | /* | 188 | /* | 
| 174 | * Whilst the MN10300 can do page protection for execute (given separate data | 189 | * Whilst the MN10300 can do page protection for execute (given separate data | 
| 175 | * and insn TLBs), we are not supporting it at the moment. Write permission, | 190 | * and insn TLBs), we are not supporting it at the moment. Write permission, | 
| @@ -323,11 +338,7 @@ static inline int pte_exec_kernel(pte_t pte) | |||
| 323 | return 1; | 338 | return 1; | 
| 324 | } | 339 | } | 
| 325 | 340 | ||
| 326 | /* | 341 | #define PTE_FILE_MAX_BITS 30 | 
| 327 | * Bits 0 and 1 are taken, split up the 29 bits of offset | ||
| 328 | * into this range: | ||
| 329 | */ | ||
| 330 | #define PTE_FILE_MAX_BITS 29 | ||
| 331 | 342 | ||
| 332 | #define pte_to_pgoff(pte) (pte_val(pte) >> 2) | 343 | #define pte_to_pgoff(pte) (pte_val(pte) >> 2) | 
| 333 | #define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) | 344 | #define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) | 
| @@ -373,8 +384,13 @@ static inline void ptep_mkdirty(pte_t *ptep) | |||
| 373 | * Macro to mark a page protection value as "uncacheable". On processors which | 384 | * Macro to mark a page protection value as "uncacheable". On processors which | 
| 374 | * do not support it, this is a no-op. | 385 | * do not support it, this is a no-op. | 
| 375 | */ | 386 | */ | 
| 376 | #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE) | 387 | #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHE) | 
| 377 | 388 | ||
| 389 | /* | ||
| 390 | * Macro to mark a page protection value as "Write-Through". | ||
| 391 | * On processors which do not support it, this is a no-op. | ||
| 392 | */ | ||
| 393 | #define pgprot_through(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE_WT) | ||
| 378 | 394 | ||
| 379 | /* | 395 | /* | 
| 380 | * Conversion functions: convert a page and protection to a page entry, | 396 | * Conversion functions: convert a page and protection to a page entry, | 
| diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h index f7d4b0d285e8..4c1b5cc14c19 100644 --- a/arch/mn10300/include/asm/processor.h +++ b/arch/mn10300/include/asm/processor.h | |||
| @@ -13,10 +13,13 @@ | |||
| 13 | #ifndef _ASM_PROCESSOR_H | 13 | #ifndef _ASM_PROCESSOR_H | 
| 14 | #define _ASM_PROCESSOR_H | 14 | #define _ASM_PROCESSOR_H | 
| 15 | 15 | ||
| 16 | #include <linux/threads.h> | ||
| 17 | #include <linux/thread_info.h> | ||
| 16 | #include <asm/page.h> | 18 | #include <asm/page.h> | 
| 17 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> | 
| 18 | #include <asm/cpu-regs.h> | 20 | #include <asm/cpu-regs.h> | 
| 19 | #include <linux/threads.h> | 21 | #include <asm/uaccess.h> | 
| 22 | #include <asm/current.h> | ||
| 20 | 23 | ||
| 21 | /* Forward declaration, a strange C thing */ | 24 | /* Forward declaration, a strange C thing */ | 
| 22 | struct task_struct; | 25 | struct task_struct; | 
| @@ -33,6 +36,8 @@ struct mm_struct; | |||
| 33 | __pc; \ | 36 | __pc; \ | 
| 34 | }) | 37 | }) | 
| 35 | 38 | ||
| 39 | extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size); | ||
| 40 | |||
| 36 | extern void show_registers(struct pt_regs *regs); | 41 | extern void show_registers(struct pt_regs *regs); | 
| 37 | 42 | ||
| 38 | /* | 43 | /* | 
| @@ -43,17 +48,22 @@ extern void show_registers(struct pt_regs *regs); | |||
| 43 | 48 | ||
| 44 | struct mn10300_cpuinfo { | 49 | struct mn10300_cpuinfo { | 
| 45 | int type; | 50 | int type; | 
| 46 | unsigned long loops_per_sec; | 51 | unsigned long loops_per_jiffy; | 
| 47 | char hard_math; | 52 | char hard_math; | 
| 48 | unsigned long *pgd_quick; | ||
| 49 | unsigned long *pte_quick; | ||
| 50 | unsigned long pgtable_cache_sz; | ||
| 51 | }; | 53 | }; | 
| 52 | 54 | ||
| 53 | extern struct mn10300_cpuinfo boot_cpu_data; | 55 | extern struct mn10300_cpuinfo boot_cpu_data; | 
| 54 | 56 | ||
| 57 | #ifdef CONFIG_SMP | ||
| 58 | #if CONFIG_NR_CPUS < 2 || CONFIG_NR_CPUS > 8 | ||
| 59 | # error Sorry, NR_CPUS should be 2 to 8 | ||
| 60 | #endif | ||
| 61 | extern struct mn10300_cpuinfo cpu_data[]; | ||
| 62 | #define current_cpu_data cpu_data[smp_processor_id()] | ||
| 63 | #else /* CONFIG_SMP */ | ||
| 55 | #define cpu_data &boot_cpu_data | 64 | #define cpu_data &boot_cpu_data | 
| 56 | #define current_cpu_data boot_cpu_data | 65 | #define current_cpu_data boot_cpu_data | 
| 66 | #endif /* CONFIG_SMP */ | ||
| 57 | 67 | ||
| 58 | extern void identify_cpu(struct mn10300_cpuinfo *); | 68 | extern void identify_cpu(struct mn10300_cpuinfo *); | 
| 59 | extern void print_cpu_info(struct mn10300_cpuinfo *); | 69 | extern void print_cpu_info(struct mn10300_cpuinfo *); | 
| @@ -76,10 +86,6 @@ extern void dodgy_tsc(void); | |||
| 76 | */ | 86 | */ | 
| 77 | #define TASK_UNMAPPED_BASE 0x30000000 | 87 | #define TASK_UNMAPPED_BASE 0x30000000 | 
| 78 | 88 | ||
| 79 | typedef struct { | ||
| 80 | unsigned long seg; | ||
| 81 | } mm_segment_t; | ||
| 82 | |||
| 83 | struct fpu_state_struct { | 89 | struct fpu_state_struct { | 
| 84 | unsigned long fs[32]; /* fpu registers */ | 90 | unsigned long fs[32]; /* fpu registers */ | 
| 85 | unsigned long fpcr; /* fpu control register */ | 91 | unsigned long fpcr; /* fpu control register */ | 
| @@ -92,20 +98,19 @@ struct thread_struct { | |||
| 92 | unsigned long a3; /* kernel FP */ | 98 | unsigned long a3; /* kernel FP */ | 
| 93 | unsigned long wchan; | 99 | unsigned long wchan; | 
| 94 | unsigned long usp; | 100 | unsigned long usp; | 
| 95 | struct pt_regs *__frame; | ||
| 96 | unsigned long fpu_flags; | 101 | unsigned long fpu_flags; | 
| 97 | #define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */ | 102 | #define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */ | 
| 103 | #define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */ | ||
| 98 | struct fpu_state_struct fpu_state; | 104 | struct fpu_state_struct fpu_state; | 
| 99 | }; | 105 | }; | 
| 100 | 106 | ||
| 101 | #define INIT_THREAD \ | 107 | #define INIT_THREAD \ | 
| 102 | { \ | 108 | { \ | 
| 103 | .uregs = init_uregs, \ | 109 | .uregs = init_uregs, \ | 
| 104 | .pc = 0, \ | 110 | .pc = 0, \ | 
| 105 | .sp = 0, \ | 111 | .sp = 0, \ | 
| 106 | .a3 = 0, \ | 112 | .a3 = 0, \ | 
| 107 | .wchan = 0, \ | 113 | .wchan = 0, \ | 
| 108 | .__frame = NULL, \ | ||
| 109 | } | 114 | } | 
| 110 | 115 | ||
| 111 | #define INIT_MMAP \ | 116 | #define INIT_MMAP \ | 
| @@ -117,13 +122,20 @@ struct thread_struct { | |||
| 117 | * - need to discard the frame stacked by the kernel thread invoking the execve | 122 | * - need to discard the frame stacked by the kernel thread invoking the execve | 
| 118 | * syscall (see RESTORE_ALL macro) | 123 | * syscall (see RESTORE_ALL macro) | 
| 119 | */ | 124 | */ | 
| 120 | #define start_thread(regs, new_pc, new_sp) do { \ | 125 | static inline void start_thread(struct pt_regs *regs, | 
| 121 | set_fs(USER_DS); \ | 126 | unsigned long new_pc, unsigned long new_sp) | 
| 122 | __frame = current->thread.uregs; \ | 127 | { | 
| 123 | __frame->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; \ | 128 | struct thread_info *ti = current_thread_info(); | 
| 124 | __frame->pc = new_pc; \ | 129 | struct pt_regs *frame0; | 
| 125 | __frame->sp = new_sp; \ | 130 | set_fs(USER_DS); | 
| 126 | } while (0) | 131 | |
| 132 | frame0 = thread_info_to_uregs(ti); | ||
| 133 | frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; | ||
| 134 | frame0->pc = new_pc; | ||
| 135 | frame0->sp = new_sp; | ||
| 136 | ti->frame = frame0; | ||
| 137 | } | ||
| 138 | |||
| 127 | 139 | ||
| 128 | /* Free all resources held by a thread. */ | 140 | /* Free all resources held by a thread. */ | 
| 129 | extern void release_thread(struct task_struct *); | 141 | extern void release_thread(struct task_struct *); | 
| @@ -157,7 +169,7 @@ unsigned long get_wchan(struct task_struct *p); | |||
| 157 | 169 | ||
| 158 | static inline void prefetch(const void *x) | 170 | static inline void prefetch(const void *x) | 
| 159 | { | 171 | { | 
| 160 | #ifndef CONFIG_MN10300_CACHE_DISABLED | 172 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 
| 161 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 173 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 
| 162 | asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); | 174 | asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); | 
| 163 | #else | 175 | #else | 
| @@ -168,7 +180,7 @@ static inline void prefetch(const void *x) | |||
| 168 | 180 | ||
| 169 | static inline void prefetchw(const void *x) | 181 | static inline void prefetchw(const void *x) | 
| 170 | { | 182 | { | 
| 171 | #ifndef CONFIG_MN10300_CACHE_DISABLED | 183 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 
| 172 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 184 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 
| 173 | asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); | 185 | asm volatile ("nop; nop; dcpf (%0)" : : "r"(x)); | 
| 174 | #else | 186 | #else | 
| diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h index 7c2e911052b6..b6961811d445 100644 --- a/arch/mn10300/include/asm/ptrace.h +++ b/arch/mn10300/include/asm/ptrace.h | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | #define PT_PC 26 | 40 | #define PT_PC 26 | 
| 41 | #define NR_PTREGS 27 | 41 | #define NR_PTREGS 27 | 
| 42 | 42 | ||
| 43 | #ifndef __ASSEMBLY__ | ||
| 44 | /* | 43 | /* | 
| 45 | * This defines the way registers are stored in the event of an exception | 44 | * This defines the way registers are stored in the event of an exception | 
| 46 | * - the strange order is due to the MOVM instruction | 45 | * - the strange order is due to the MOVM instruction | 
| @@ -75,7 +74,6 @@ struct pt_regs { | |||
| 75 | unsigned long epsw; | 74 | unsigned long epsw; | 
| 76 | unsigned long pc; | 75 | unsigned long pc; | 
| 77 | }; | 76 | }; | 
| 78 | #endif | ||
| 79 | 77 | ||
| 80 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ | 78 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ | 
| 81 | #define PTRACE_GETREGS 12 | 79 | #define PTRACE_GETREGS 12 | 
| @@ -86,12 +84,7 @@ struct pt_regs { | |||
| 86 | /* options set using PTRACE_SETOPTIONS */ | 84 | /* options set using PTRACE_SETOPTIONS */ | 
| 87 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 85 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 
| 88 | 86 | ||
| 89 | #if defined(__KERNEL__) | 87 | #ifdef __KERNEL__ | 
| 90 | |||
| 91 | extern struct pt_regs *__frame; /* current frame pointer */ | ||
| 92 | |||
| 93 | #if !defined(__ASSEMBLY__) | ||
| 94 | struct task_struct; | ||
| 95 | 88 | ||
| 96 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) | 89 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) | 
| 97 | #define instruction_pointer(regs) ((regs)->pc) | 90 | #define instruction_pointer(regs) ((regs)->pc) | 
| @@ -100,9 +93,7 @@ extern void show_regs(struct pt_regs *); | |||
| 100 | 93 | ||
| 101 | #define arch_has_single_step() (1) | 94 | #define arch_has_single_step() (1) | 
| 102 | 95 | ||
| 103 | #endif /* !__ASSEMBLY */ | ||
| 104 | |||
| 105 | #define profile_pc(regs) ((regs)->pc) | 96 | #define profile_pc(regs) ((regs)->pc) | 
| 106 | 97 | ||
| 107 | #endif /* __KERNEL__ */ | 98 | #endif /* __KERNEL__ */ | 
| 108 | #endif /* _ASM_PTRACE_H */ | 99 | #endif /* _ASM_PTRACE_H */ | 
| diff --git a/arch/mn10300/include/asm/reset-regs.h b/arch/mn10300/include/asm/reset-regs.h index 174523d50132..10c7502a113f 100644 --- a/arch/mn10300/include/asm/reset-regs.h +++ b/arch/mn10300/include/asm/reset-regs.h | |||
| @@ -50,7 +50,7 @@ static inline void mn10300_proc_hard_reset(void) | |||
| 50 | RSTCTR |= RSTCTR_CHIPRST; | 50 | RSTCTR |= RSTCTR_CHIPRST; | 
| 51 | } | 51 | } | 
| 52 | 52 | ||
| 53 | extern unsigned int watchdog_alert_counter; | 53 | extern unsigned int watchdog_alert_counter[]; | 
| 54 | 54 | ||
| 55 | extern void watchdog_go(void); | 55 | extern void watchdog_go(void); | 
| 56 | extern asmlinkage void watchdog_handler(void); | 56 | extern asmlinkage void watchdog_handler(void); | 
| diff --git a/arch/mn10300/include/asm/rtc.h b/arch/mn10300/include/asm/rtc.h index c295194cc703..6c14bb1d0d9b 100644 --- a/arch/mn10300/include/asm/rtc.h +++ b/arch/mn10300/include/asm/rtc.h | |||
| @@ -15,25 +15,14 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> | 
| 17 | 17 | ||
| 18 | extern void check_rtc_time(void); | ||
| 19 | extern void __init calibrate_clock(void); | 18 | extern void __init calibrate_clock(void); | 
| 20 | extern unsigned long __init get_initial_rtc_time(void); | ||
| 21 | 19 | ||
| 22 | #else /* !CONFIG_MN10300_RTC */ | 20 | #else /* !CONFIG_MN10300_RTC */ | 
| 23 | 21 | ||
| 24 | static inline void check_rtc_time(void) | ||
| 25 | { | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline void calibrate_clock(void) | 22 | static inline void calibrate_clock(void) | 
| 29 | { | 23 | { | 
| 30 | } | 24 | } | 
| 31 | 25 | ||
| 32 | static inline unsigned long get_initial_rtc_time(void) | ||
| 33 | { | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | #endif /* !CONFIG_MN10300_RTC */ | 26 | #endif /* !CONFIG_MN10300_RTC */ | 
| 38 | 27 | ||
| 39 | #include <asm-generic/rtc.h> | 28 | #include <asm-generic/rtc.h> | 
| diff --git a/arch/mn10300/include/asm/rwlock.h b/arch/mn10300/include/asm/rwlock.h new file mode 100644 index 000000000000..6d594d4a0e10 --- /dev/null +++ b/arch/mn10300/include/asm/rwlock.h | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* | ||
| 2 | * Helpers used by both rw spinlocks and rw semaphores. | ||
| 3 | * | ||
| 4 | * Based in part on code from semaphore.h and | ||
| 5 | * spinlock.h Copyright 1996 Linus Torvalds. | ||
| 6 | * | ||
| 7 | * Copyright 1999 Red Hat, Inc. | ||
| 8 | * | ||
| 9 | * Written by Benjamin LaHaise. | ||
| 10 | * | ||
| 11 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 12 | * Modifications: | ||
| 13 | * 13-Nov-2006 MEI Temporarily delete lock functions for SMP support. | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or modify it | ||
| 16 | * under the terms of the GNU General Public License as published by the Free | ||
| 17 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 18 | * any later version. | ||
| 19 | */ | ||
| 20 | #ifndef _ASM_RWLOCK_H | ||
| 21 | #define _ASM_RWLOCK_H | ||
| 22 | |||
| 23 | #define RW_LOCK_BIAS 0x01000000 | ||
| 24 | |||
| 25 | #ifndef CONFIG_SMP | ||
| 26 | |||
| 27 | typedef struct { unsigned long a[100]; } __dummy_lock_t; | ||
| 28 | #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) | ||
| 29 | |||
| 30 | #define RW_LOCK_BIAS_STR "0x01000000" | ||
| 31 | |||
| 32 | #define __build_read_lock_ptr(rw, helper) \ | ||
| 33 | do { \ | ||
| 34 | asm volatile( \ | ||
| 35 | " mov (%0),d3 \n" \ | ||
| 36 | " sub 1,d3 \n" \ | ||
| 37 | " mov d3,(%0) \n" \ | ||
| 38 | " blt 1f \n" \ | ||
| 39 | " bra 2f \n" \ | ||
| 40 | "1: jmp 3f \n" \ | ||
| 41 | "2: \n" \ | ||
| 42 | " .section .text.lock,\"ax\" \n" \ | ||
| 43 | "3: call "helper"[],0 \n" \ | ||
| 44 | " jmp 2b \n" \ | ||
| 45 | " .previous" \ | ||
| 46 | : \ | ||
| 47 | : "d" (rw) \ | ||
| 48 | : "memory", "d3", "cc"); \ | ||
| 49 | } while (0) | ||
| 50 | |||
| 51 | #define __build_read_lock_const(rw, helper) \ | ||
| 52 | do { \ | ||
| 53 | asm volatile( \ | ||
| 54 | " mov (%0),d3 \n" \ | ||
| 55 | " sub 1,d3 \n" \ | ||
| 56 | " mov d3,(%0) \n" \ | ||
| 57 | " blt 1f \n" \ | ||
| 58 | " bra 2f \n" \ | ||
| 59 | "1: jmp 3f \n" \ | ||
| 60 | "2: \n" \ | ||
| 61 | " .section .text.lock,\"ax\" \n" \ | ||
| 62 | "3: call "helper"[],0 \n" \ | ||
| 63 | " jmp 2b \n" \ | ||
| 64 | " .previous" \ | ||
| 65 | : \ | ||
| 66 | : "d" (rw) \ | ||
| 67 | : "memory", "d3", "cc"); \ | ||
| 68 | } while (0) | ||
| 69 | |||
| 70 | #define __build_read_lock(rw, helper) \ | ||
| 71 | do { \ | ||
| 72 | if (__builtin_constant_p(rw)) \ | ||
| 73 | __build_read_lock_const(rw, helper); \ | ||
| 74 | else \ | ||
| 75 | __build_read_lock_ptr(rw, helper); \ | ||
| 76 | } while (0) | ||
| 77 | |||
| 78 | #define __build_write_lock_ptr(rw, helper) \ | ||
| 79 | do { \ | ||
| 80 | asm volatile( \ | ||
| 81 | " mov (%0),d3 \n" \ | ||
| 82 | " sub 1,d3 \n" \ | ||
| 83 | " mov d3,(%0) \n" \ | ||
| 84 | " blt 1f \n" \ | ||
| 85 | " bra 2f \n" \ | ||
| 86 | "1: jmp 3f \n" \ | ||
| 87 | "2: \n" \ | ||
| 88 | " .section .text.lock,\"ax\" \n" \ | ||
| 89 | "3: call "helper"[],0 \n" \ | ||
| 90 | " jmp 2b \n" \ | ||
| 91 | " .previous" \ | ||
| 92 | : \ | ||
| 93 | : "d" (rw) \ | ||
| 94 | : "memory", "d3", "cc"); \ | ||
| 95 | } while (0) | ||
| 96 | |||
| 97 | #define __build_write_lock_const(rw, helper) \ | ||
| 98 | do { \ | ||
| 99 | asm volatile( \ | ||
| 100 | " mov (%0),d3 \n" \ | ||
| 101 | " sub 1,d3 \n" \ | ||
| 102 | " mov d3,(%0) \n" \ | ||
| 103 | " blt 1f \n" \ | ||
| 104 | " bra 2f \n" \ | ||
| 105 | "1: jmp 3f \n" \ | ||
| 106 | "2: \n" \ | ||
| 107 | " .section .text.lock,\"ax\" \n" \ | ||
| 108 | "3: call "helper"[],0 \n" \ | ||
| 109 | " jmp 2b \n" \ | ||
| 110 | " .previous" \ | ||
| 111 | : \ | ||
| 112 | : "d" (rw) \ | ||
| 113 | : "memory", "d3", "cc"); \ | ||
| 114 | } while (0) | ||
| 115 | |||
| 116 | #define __build_write_lock(rw, helper) \ | ||
| 117 | do { \ | ||
| 118 | if (__builtin_constant_p(rw)) \ | ||
| 119 | __build_write_lock_const(rw, helper); \ | ||
| 120 | else \ | ||
| 121 | __build_write_lock_ptr(rw, helper); \ | ||
| 122 | } while (0) | ||
| 123 | |||
| 124 | #endif /* CONFIG_SMP */ | ||
| 125 | #endif /* _ASM_RWLOCK_H */ | ||
| diff --git a/arch/mn10300/include/asm/serial-regs.h b/arch/mn10300/include/asm/serial-regs.h index 6498469e93ac..8320cda32f5a 100644 --- a/arch/mn10300/include/asm/serial-regs.h +++ b/arch/mn10300/include/asm/serial-regs.h | |||
| @@ -20,18 +20,25 @@ | |||
| 20 | /* serial port 0 */ | 20 | /* serial port 0 */ | 
| 21 | #define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */ | 21 | #define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */ | 
| 22 | #define SC01CTR_CK 0x0007 /* clock source select */ | 22 | #define SC01CTR_CK 0x0007 /* clock source select */ | 
| 23 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ | ||
| 24 | #define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */ | ||
| 25 | #define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ | 23 | #define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ | 
| 26 | #define SC01CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 24 | #define SC01CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 
| 25 | #define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | ||
| 26 | #define SC01CTR_CK_EXTERN 0x0007 /* - external closk */ | ||
| 27 | #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) | ||
| 28 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ | ||
| 27 | #define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */ | 29 | #define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */ | 
| 28 | #define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */ | 30 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */ | 
| 29 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 0 only) */ | ||
| 30 | #define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 2 underflow (serial port 1 only) */ | ||
| 31 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ | 31 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ | 
| 32 | #define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */ | ||
| 33 | #define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */ | ||
| 34 | #define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 1 only) */ | ||
| 32 | #define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */ | 35 | #define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */ | 
| 33 | #define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | 36 | #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | 
| 34 | #define SC01CTR_CK_EXTERN 0x0007 /* - external closk */ | 37 | #define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */ | 
| 38 | #define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */ | ||
| 39 | #define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */ | ||
| 40 | #define SC1CTR_CK_TM12UFLOW_8 0x0000 /* - 1/8 timer 12 underflow (serial port 1 only) */ | ||
| 41 | #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
| 35 | #define SC01CTR_STB 0x0008 /* stop bit select */ | 42 | #define SC01CTR_STB 0x0008 /* stop bit select */ | 
| 36 | #define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 43 | #define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 
| 37 | #define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 44 | #define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 
| @@ -100,11 +107,23 @@ | |||
| 100 | 107 | ||
| 101 | /* serial port 2 */ | 108 | /* serial port 2 */ | 
| 102 | #define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */ | 109 | #define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */ | 
| 110 | #ifdef CONFIG_AM33_2 | ||
| 103 | #define SC2CTR_CK 0x0003 /* clock source select */ | 111 | #define SC2CTR_CK 0x0003 /* clock source select */ | 
| 104 | #define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */ | 112 | #define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */ | 
| 105 | #define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */ | 113 | #define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */ | 
| 106 | #define SC2CTR_CK_EXTERN 0x0002 /* - external closk */ | 114 | #define SC2CTR_CK_EXTERN 0x0002 /* - external closk */ | 
| 107 | #define SC2CTR_CK_TM3UFLOW 0x0003 /* - timer 3 underflow */ | 115 | #define SC2CTR_CK_TM3UFLOW 0x0003 /* - timer 3 underflow */ | 
| 116 | #else /* CONFIG_AM33_2 */ | ||
| 117 | #define SC2CTR_CK 0x0007 /* clock source select */ | ||
| 118 | #define SC2CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow */ | ||
| 119 | #define SC2CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */ | ||
| 120 | #define SC2CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | ||
| 121 | #define SC2CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow */ | ||
| 122 | #define SC2CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow */ | ||
| 123 | #define SC2CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow */ | ||
| 124 | #define SC2CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */ | ||
| 125 | #define SC2CTR_CK_EXTERN 0x0007 /* - external closk */ | ||
| 126 | #endif /* CONFIG_AM33_2 */ | ||
| 108 | #define SC2CTR_STB 0x0008 /* stop bit select */ | 127 | #define SC2CTR_STB 0x0008 /* stop bit select */ | 
| 109 | #define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 128 | #define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */ | 
| 110 | #define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 129 | #define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */ | 
| @@ -134,9 +153,14 @@ | |||
| 134 | #define SC2ICR_RES 0x04 /* receive error select */ | 153 | #define SC2ICR_RES 0x04 /* receive error select */ | 
| 135 | #define SC2ICR_RI 0x01 /* receive interrupt cause */ | 154 | #define SC2ICR_RI 0x01 /* receive interrupt cause */ | 
| 136 | 155 | ||
| 137 | #define SC2TXB __SYSREG(0xd4002018, u8) /* transmit buffer reg */ | 156 | #define SC2TXB __SYSREG(0xd4002028, u8) /* transmit buffer reg */ | 
| 138 | #define SC2RXB __SYSREG(0xd4002019, u8) /* receive buffer reg */ | 157 | #define SC2RXB __SYSREG(0xd4002029, u8) /* receive buffer reg */ | 
| 139 | #define SC2STR __SYSREG(0xd400201c, u8) /* status reg */ | 158 | |
| 159 | #ifdef CONFIG_AM33_2 | ||
| 160 | #define SC2STR __SYSREG(0xd400202c, u8) /* status reg */ | ||
| 161 | #else /* CONFIG_AM33_2 */ | ||
| 162 | #define SC2STR __SYSREG(0xd400202c, u16) /* status reg */ | ||
| 163 | #endif /* CONFIG_AM33_2 */ | ||
| 140 | #define SC2STR_OEF 0x0001 /* overrun error found */ | 164 | #define SC2STR_OEF 0x0001 /* overrun error found */ | 
| 141 | #define SC2STR_PEF 0x0002 /* parity error found */ | 165 | #define SC2STR_PEF 0x0002 /* parity error found */ | 
| 142 | #define SC2STR_FEF 0x0004 /* framing error found */ | 166 | #define SC2STR_FEF 0x0004 /* framing error found */ | 
| @@ -146,10 +170,17 @@ | |||
| 146 | #define SC2STR_RXF 0x0040 /* receive status */ | 170 | #define SC2STR_RXF 0x0040 /* receive status */ | 
| 147 | #define SC2STR_TXF 0x0080 /* transmit status */ | 171 | #define SC2STR_TXF 0x0080 /* transmit status */ | 
| 148 | 172 | ||
| 173 | #ifdef CONFIG_AM33_2 | ||
| 149 | #define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */ | 174 | #define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */ | 
| 175 | #endif | ||
| 150 | 176 | ||
| 177 | #ifdef CONFIG_AM33_2 | ||
| 151 | #define SC2RXIRQ 24 /* serial 2 Receive IRQ */ | 178 | #define SC2RXIRQ 24 /* serial 2 Receive IRQ */ | 
| 152 | #define SC2TXIRQ 25 /* serial 2 Transmit IRQ */ | 179 | #define SC2TXIRQ 25 /* serial 2 Transmit IRQ */ | 
| 180 | #else /* CONFIG_AM33_2 */ | ||
| 181 | #define SC2RXIRQ 68 /* serial 2 Receive IRQ */ | ||
| 182 | #define SC2TXIRQ 69 /* serial 2 Transmit IRQ */ | ||
| 183 | #endif /* CONFIG_AM33_2 */ | ||
| 153 | 184 | ||
| 154 | #define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */ | 185 | #define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */ | 
| 155 | #define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */ | 186 | #define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */ | 
| diff --git a/arch/mn10300/include/asm/serial.h b/arch/mn10300/include/asm/serial.h index a29445cddd6f..23a799293599 100644 --- a/arch/mn10300/include/asm/serial.h +++ b/arch/mn10300/include/asm/serial.h | |||
| @@ -9,10 +9,8 @@ | |||
| 9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. | 
| 10 | */ | 10 | */ | 
| 11 | 11 | ||
| 12 | /* | 12 | #ifndef _ASM_SERIAL_H | 
| 13 | * The ASB2305 has an 18.432 MHz clock the UART | 13 | #define _ASM_SERIAL_H | 
| 14 | */ | ||
| 15 | #define BASE_BAUD (18432000 / 16) | ||
| 16 | 14 | ||
| 17 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ | 15 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ | 
| 18 | #ifdef CONFIG_SERIAL_DETECT_IRQ | 16 | #ifdef CONFIG_SERIAL_DETECT_IRQ | 
| @@ -34,3 +32,5 @@ | |||
| 34 | #endif | 32 | #endif | 
| 35 | 33 | ||
| 36 | #include <unit/serial.h> | 34 | #include <unit/serial.h> | 
| 35 | |||
| 36 | #endif /* _ASM_SERIAL_H */ | ||
| diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index 4eb8c61b7dab..a3930e43a958 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h | |||
| @@ -3,6 +3,16 @@ | |||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) | 
| 5 | * | 5 | * | 
| 6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 7 | * Modifications: | ||
| 8 | * 13-Nov-2006 MEI Define IPI-IRQ number and add inline/macro function | ||
| 9 | * for SMP support. | ||
| 10 | * 22-Jan-2007 MEI Add the define related to SMP_BOOT_IRQ. | ||
| 11 | * 23-Feb-2007 MEI Add the define related to SMP icahce invalidate. | ||
| 12 | * 23-Jun-2008 MEI Delete INTC_IPI. | ||
| 13 | * 22-Jul-2008 MEI Add smp_nmi_call_function and related defines. | ||
| 14 | * 04-Aug-2008 MEI Delete USE_DOIRQ_CACHE_IPI. | ||
| 15 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | 16 | * This program is free software; you can redistribute it and/or | 
| 7 | * modify it under the terms of the GNU General Public Licence | 17 | * modify it under the terms of the GNU General Public Licence | 
| 8 | * as published by the Free Software Foundation; either version | 18 | * as published by the Free Software Foundation; either version | 
| @@ -11,8 +21,85 @@ | |||
| 11 | #ifndef _ASM_SMP_H | 21 | #ifndef _ASM_SMP_H | 
| 12 | #define _ASM_SMP_H | 22 | #define _ASM_SMP_H | 
| 13 | 23 | ||
| 14 | #ifdef CONFIG_SMP | 24 | #ifndef __ASSEMBLY__ | 
| 15 | #error SMP not yet supported for MN10300 | 25 | #include <linux/threads.h> | 
| 26 | #include <linux/cpumask.h> | ||
| 16 | #endif | 27 | #endif | 
| 17 | 28 | ||
| 29 | #ifdef CONFIG_SMP | ||
| 30 | #include <proc/smp-regs.h> | ||
| 31 | |||
| 32 | #define RESCHEDULE_IPI 63 | ||
| 33 | #define CALL_FUNC_SINGLE_IPI 192 | ||
| 34 | #define LOCAL_TIMER_IPI 193 | ||
| 35 | #define FLUSH_CACHE_IPI 194 | ||
| 36 | #define CALL_FUNCTION_NMI_IPI 195 | ||
| 37 | #define GDB_NMI_IPI 196 | ||
| 38 | |||
| 39 | #define SMP_BOOT_IRQ 195 | ||
| 40 | |||
| 41 | #define RESCHEDULE_GxICR_LV GxICR_LEVEL_6 | ||
| 42 | #define CALL_FUNCTION_GxICR_LV GxICR_LEVEL_4 | ||
| 43 | #define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4 | ||
| 44 | #define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0 | ||
| 45 | #define SMP_BOOT_GxICR_LV GxICR_LEVEL_0 | ||
| 46 | |||
| 47 | #define TIME_OUT_COUNT_BOOT_IPI 100 | ||
| 48 | #define DELAY_TIME_BOOT_IPI 75000 | ||
| 49 | |||
| 50 | |||
| 51 | #ifndef __ASSEMBLY__ | ||
| 52 | |||
| 53 | /** | ||
| 54 | * raw_smp_processor_id - Determine the raw CPU ID of the CPU running it | ||
| 55 | * | ||
| 56 | * What we really want to do is to use the CPUID hardware CPU register to get | ||
| 57 | * this information, but accesses to that aren't cached, and run at system bus | ||
| 58 | * speed, not CPU speed. A copy of this value is, however, stored in the | ||
| 59 | * thread_info struct, and that can be cached. | ||
| 60 | * | ||
| 61 | * An alternate way of dealing with this could be to use the EPSW.S bits to | ||
| 62 | * cache this information for systems with up to four CPUs. | ||
| 63 | */ | ||
| 64 | #if 0 | ||
| 65 | #define raw_smp_processor_id() (CPUID) | ||
| 66 | #else | ||
| 67 | #define raw_smp_processor_id() (current_thread_info()->cpu) | ||
| 18 | #endif | 68 | #endif | 
| 69 | |||
| 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 */ | ||
| diff --git a/arch/mn10300/include/asm/smsc911x.h b/arch/mn10300/include/asm/smsc911x.h new file mode 100644 index 000000000000..2fcd1080322b --- /dev/null +++ b/arch/mn10300/include/asm/smsc911x.h | |||
| @@ -0,0 +1 @@ | |||
| #include <unit/smsc911x.h> | |||
| diff --git a/arch/mn10300/include/asm/spinlock.h b/arch/mn10300/include/asm/spinlock.h index 4bf9c8b169e0..93429154e898 100644 --- a/arch/mn10300/include/asm/spinlock.h +++ b/arch/mn10300/include/asm/spinlock.h | |||
| @@ -11,6 +11,183 @@ | |||
| 11 | #ifndef _ASM_SPINLOCK_H | 11 | #ifndef _ASM_SPINLOCK_H | 
| 12 | #define _ASM_SPINLOCK_H | 12 | #define _ASM_SPINLOCK_H | 
| 13 | 13 | ||
| 14 | #error SMP spinlocks not implemented for MN10300 | 14 | #include <asm/atomic.h> | 
| 15 | #include <asm/rwlock.h> | ||
| 16 | #include <asm/page.h> | ||
| 15 | 17 | ||
| 18 | /* | ||
| 19 | * Simple spin lock operations. There are two variants, one clears IRQ's | ||
| 20 | * on the local processor, one does not. | ||
| 21 | * | ||
| 22 | * We make no fairness assumptions. They have a cost. | ||
| 23 | */ | ||
| 24 | |||
| 25 | #define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) != 0) | ||
| 26 | #define arch_spin_unlock_wait(x) do { barrier(); } while (arch_spin_is_locked(x)) | ||
| 27 | |||
| 28 | static inline void arch_spin_unlock(arch_spinlock_t *lock) | ||
| 29 | { | ||
| 30 | asm volatile( | ||
| 31 | " bclr 1,(0,%0) \n" | ||
| 32 | : | ||
| 33 | : "a"(&lock->slock) | ||
| 34 | : "memory", "cc"); | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline int arch_spin_trylock(arch_spinlock_t *lock) | ||
| 38 | { | ||
| 39 | int ret; | ||
| 40 | |||
| 41 | asm volatile( | ||
| 42 | " mov 1,%0 \n" | ||
| 43 | " bset %0,(%1) \n" | ||
| 44 | " bne 1f \n" | ||
| 45 | " clr %0 \n" | ||
| 46 | "1: xor 1,%0 \n" | ||
| 47 | : "=d"(ret) | ||
| 48 | : "a"(&lock->slock) | ||
| 49 | : "memory", "cc"); | ||
| 50 | |||
| 51 | return ret; | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline void arch_spin_lock(arch_spinlock_t *lock) | ||
| 55 | { | ||
| 56 | asm volatile( | ||
| 57 | "1: bset 1,(0,%0) \n" | ||
| 58 | " bne 1b \n" | ||
| 59 | : | ||
| 60 | : "a"(&lock->slock) | ||
| 61 | : "memory", "cc"); | ||
| 62 | } | ||
| 63 | |||
| 64 | static inline void arch_spin_lock_flags(arch_spinlock_t *lock, | ||
| 65 | unsigned long flags) | ||
| 66 | { | ||
| 67 | int temp; | ||
| 68 | |||
| 69 | asm volatile( | ||
| 70 | "1: bset 1,(0,%2) \n" | ||
| 71 | " beq 3f \n" | ||
| 72 | " mov %1,epsw \n" | ||
| 73 | "2: mov (0,%2),%0 \n" | ||
| 74 | " or %0,%0 \n" | ||
| 75 | " bne 2b \n" | ||
| 76 | " mov %3,%0 \n" | ||
| 77 | " mov %0,epsw \n" | ||
| 78 | " nop \n" | ||
| 79 | " nop \n" | ||
| 80 | " bra 1b\n" | ||
| 81 | "3: \n" | ||
| 82 | : "=&d" (temp) | ||
| 83 | : "d" (flags), "a"(&lock->slock), "i"(EPSW_IE | MN10300_CLI_LEVEL) | ||
| 84 | : "memory", "cc"); | ||
| 85 | } | ||
| 86 | |||
| 87 | #ifdef __KERNEL__ | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Read-write spinlocks, allowing multiple readers | ||
| 91 | * but only one writer. | ||
| 92 | * | ||
| 93 | * NOTE! it is quite common to have readers in interrupts | ||
| 94 | * but no interrupt writers. For those circumstances we | ||
| 95 | * can "mix" irq-safe locks - any writer needs to get a | ||
| 96 | * irq-safe write-lock, but readers can get non-irqsafe | ||
| 97 | * read-locks. | ||
| 98 | */ | ||
| 99 | |||
| 100 | /** | ||
| 101 | * read_can_lock - would read_trylock() succeed? | ||
| 102 | * @lock: the rwlock in question. | ||
| 103 | */ | ||
| 104 | #define arch_read_can_lock(x) ((int)(x)->lock > 0) | ||
| 105 | |||
| 106 | /** | ||
| 107 | * write_can_lock - would write_trylock() succeed? | ||
| 108 | * @lock: the rwlock in question. | ||
| 109 | */ | ||
| 110 | #define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS) | ||
| 111 | |||
| 112 | /* | ||
| 113 | * On mn10300, we implement read-write locks as a 32-bit counter | ||
| 114 | * with the high bit (sign) being the "contended" bit. | ||
| 115 | */ | ||
| 116 | static inline void arch_read_lock(arch_rwlock_t *rw) | ||
| 117 | { | ||
| 118 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 119 | __build_read_lock(rw, "__read_lock_failed"); | ||
| 120 | #else | ||
| 121 | { | ||
| 122 | atomic_t *count = (atomic_t *)rw; | ||
| 123 | while (atomic_dec_return(count) < 0) | ||
| 124 | atomic_inc(count); | ||
| 125 | } | ||
| 126 | #endif | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline void arch_write_lock(arch_rwlock_t *rw) | ||
| 130 | { | ||
| 131 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 132 | __build_write_lock(rw, "__write_lock_failed"); | ||
| 133 | #else | ||
| 134 | { | ||
| 135 | atomic_t *count = (atomic_t *)rw; | ||
| 136 | while (!atomic_sub_and_test(RW_LOCK_BIAS, count)) | ||
| 137 | atomic_add(RW_LOCK_BIAS, count); | ||
| 138 | } | ||
| 139 | #endif | ||
| 140 | } | ||
| 141 | |||
| 142 | static inline void arch_read_unlock(arch_rwlock_t *rw) | ||
| 143 | { | ||
| 144 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 145 | __build_read_unlock(rw); | ||
| 146 | #else | ||
| 147 | { | ||
| 148 | atomic_t *count = (atomic_t *)rw; | ||
| 149 | atomic_inc(count); | ||
| 150 | } | ||
| 151 | #endif | ||
| 152 | } | ||
| 153 | |||
| 154 | static inline void arch_write_unlock(arch_rwlock_t *rw) | ||
| 155 | { | ||
| 156 | #if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 157 | __build_write_unlock(rw); | ||
| 158 | #else | ||
| 159 | { | ||
| 160 | atomic_t *count = (atomic_t *)rw; | ||
| 161 | atomic_add(RW_LOCK_BIAS, count); | ||
| 162 | } | ||
| 163 | #endif | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline int arch_read_trylock(arch_rwlock_t *lock) | ||
| 167 | { | ||
| 168 | atomic_t *count = (atomic_t *)lock; | ||
| 169 | atomic_dec(count); | ||
| 170 | if (atomic_read(count) >= 0) | ||
| 171 | return 1; | ||
| 172 | atomic_inc(count); | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static inline int arch_write_trylock(arch_rwlock_t *lock) | ||
| 177 | { | ||
| 178 | atomic_t *count = (atomic_t *)lock; | ||
| 179 | if (atomic_sub_and_test(RW_LOCK_BIAS, count)) | ||
| 180 | return 1; | ||
| 181 | atomic_add(RW_LOCK_BIAS, count); | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) | ||
| 186 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) | ||
| 187 | |||
| 188 | #define _raw_spin_relax(lock) cpu_relax() | ||
| 189 | #define _raw_read_relax(lock) cpu_relax() | ||
| 190 | #define _raw_write_relax(lock) cpu_relax() | ||
| 191 | |||
| 192 | #endif /* __KERNEL__ */ | ||
| 16 | #endif /* _ASM_SPINLOCK_H */ | 193 | #endif /* _ASM_SPINLOCK_H */ | 
| diff --git a/arch/mn10300/include/asm/spinlock_types.h b/arch/mn10300/include/asm/spinlock_types.h new file mode 100644 index 000000000000..653dc519b405 --- /dev/null +++ b/arch/mn10300/include/asm/spinlock_types.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef _ASM_SPINLOCK_TYPES_H | ||
| 2 | #define _ASM_SPINLOCK_TYPES_H | ||
| 3 | |||
| 4 | #ifndef __LINUX_SPINLOCK_TYPES_H | ||
| 5 | # error "please don't include this file directly" | ||
| 6 | #endif | ||
| 7 | |||
| 8 | typedef struct arch_spinlock { | ||
| 9 | unsigned int slock; | ||
| 10 | } arch_spinlock_t; | ||
| 11 | |||
| 12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } | ||
| 13 | |||
| 14 | typedef struct { | ||
| 15 | unsigned int lock; | ||
| 16 | } arch_rwlock_t; | ||
| 17 | |||
| 18 | #define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
| 19 | |||
| 20 | #endif /* _ASM_SPINLOCK_TYPES_H */ | ||
| diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h index 9f7c7e17c01e..8ff3e5aaca41 100644 --- a/arch/mn10300/include/asm/system.h +++ b/arch/mn10300/include/asm/system.h | |||
| @@ -12,12 +12,29 @@ | |||
| 12 | #define _ASM_SYSTEM_H | 12 | #define _ASM_SYSTEM_H | 
| 13 | 13 | ||
| 14 | #include <asm/cpu-regs.h> | 14 | #include <asm/cpu-regs.h> | 
| 15 | #include <asm/intctl-regs.h> | ||
| 15 | 16 | ||
| 16 | #ifdef __KERNEL__ | 17 | #ifdef __KERNEL__ | 
| 17 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ | 
| 18 | 19 | ||
| 19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> | 
| 20 | #include <linux/irqflags.h> | 21 | #include <linux/irqflags.h> | 
| 22 | #include <asm/atomic.h> | ||
| 23 | |||
| 24 | #if !defined(CONFIG_LAZY_SAVE_FPU) | ||
| 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 | ||
| 21 | 38 | ||
| 22 | struct task_struct; | 39 | struct task_struct; | 
| 23 | struct thread_struct; | 40 | struct thread_struct; | 
| @@ -30,6 +47,7 @@ struct task_struct *__switch_to(struct thread_struct *prev, | |||
| 30 | /* context switching is now performed out-of-line in switch_to.S */ | 47 | /* context switching is now performed out-of-line in switch_to.S */ | 
| 31 | #define switch_to(prev, next, last) \ | 48 | #define switch_to(prev, next, last) \ | 
| 32 | do { \ | 49 | do { \ | 
| 50 | switch_fpu(prev, next); \ | ||
| 33 | current->thread.wchan = (u_long) __builtin_return_address(0); \ | 51 | current->thread.wchan = (u_long) __builtin_return_address(0); \ | 
| 34 | (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \ | 52 | (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \ | 
| 35 | mb(); \ | 53 | mb(); \ | 
| @@ -40,8 +58,6 @@ do { \ | |||
| 40 | 58 | ||
| 41 | #define nop() asm volatile ("nop") | 59 | #define nop() asm volatile ("nop") | 
| 42 | 60 | ||
| 43 | #endif /* !__ASSEMBLY__ */ | ||
| 44 | |||
| 45 | /* | 61 | /* | 
| 46 | * Force strict CPU ordering. | 62 | * Force strict CPU ordering. | 
| 47 | * And yes, this is required on UP too when we're talking | 63 | * And yes, this is required on UP too when we're talking | 
| @@ -68,64 +84,19 @@ do { \ | |||
| 68 | #define smp_mb() mb() | 84 | #define smp_mb() mb() | 
| 69 | #define smp_rmb() rmb() | 85 | #define smp_rmb() rmb() | 
| 70 | #define smp_wmb() wmb() | 86 | #define smp_wmb() wmb() | 
| 71 | #else | 87 | #define set_mb(var, value) do { xchg(&var, value); } while (0) | 
| 88 | #else /* CONFIG_SMP */ | ||
| 72 | #define smp_mb() barrier() | 89 | #define smp_mb() barrier() | 
| 73 | #define smp_rmb() barrier() | 90 | #define smp_rmb() barrier() | 
| 74 | #define smp_wmb() barrier() | 91 | #define smp_wmb() barrier() | 
| 75 | #endif | ||
| 76 | |||
| 77 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 92 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 
| 93 | #endif /* CONFIG_SMP */ | ||
| 94 | |||
| 78 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | 95 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | 
| 79 | 96 | ||
| 80 | #define read_barrier_depends() do {} while (0) | 97 | #define read_barrier_depends() do {} while (0) | 
| 81 | #define smp_read_barrier_depends() do {} while (0) | 98 | #define smp_read_barrier_depends() do {} while (0) | 
| 82 | 99 | ||
| 83 | /*****************************************************************************/ | ||
| 84 | /* | ||
| 85 | * MN10300 doesn't actually have an exchange instruction | ||
| 86 | */ | ||
| 87 | #ifndef __ASSEMBLY__ | ||
| 88 | |||
| 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 | |||
| 128 | #endif /* !__ASSEMBLY__ */ | 100 | #endif /* !__ASSEMBLY__ */ | 
| 129 | |||
| 130 | #endif /* __KERNEL__ */ | 101 | #endif /* __KERNEL__ */ | 
| 131 | #endif /* _ASM_SYSTEM_H */ | 102 | #endif /* _ASM_SYSTEM_H */ | 
| diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h index 2001cb657a95..aa07a4a5d794 100644 --- a/arch/mn10300/include/asm/thread_info.h +++ b/arch/mn10300/include/asm/thread_info.h | |||
| @@ -16,10 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | #include <asm/page.h> | 17 | #include <asm/page.h> | 
| 18 | 18 | ||
| 19 | #ifndef __ASSEMBLY__ | ||
| 20 | #include <asm/processor.h> | ||
| 21 | #endif | ||
| 22 | |||
| 23 | #define PREEMPT_ACTIVE 0x10000000 | 19 | #define PREEMPT_ACTIVE 0x10000000 | 
| 24 | 20 | ||
| 25 | #ifdef CONFIG_4KSTACKS | 21 | #ifdef CONFIG_4KSTACKS | 
| @@ -38,10 +34,14 @@ | |||
| 38 | * must also be changed | 34 | * must also be changed | 
| 39 | */ | 35 | */ | 
| 40 | #ifndef __ASSEMBLY__ | 36 | #ifndef __ASSEMBLY__ | 
| 37 | typedef struct { | ||
| 38 | unsigned long seg; | ||
| 39 | } mm_segment_t; | ||
| 41 | 40 | ||
| 42 | struct thread_info { | 41 | struct thread_info { | 
| 43 | struct task_struct *task; /* main task structure */ | 42 | struct task_struct *task; /* main task structure */ | 
| 44 | struct exec_domain *exec_domain; /* execution domain */ | 43 | struct exec_domain *exec_domain; /* execution domain */ | 
| 44 | struct pt_regs *frame; /* current exception frame */ | ||
| 45 | unsigned long flags; /* low level flags */ | 45 | unsigned long flags; /* low level flags */ | 
| 46 | __u32 cpu; /* current CPU */ | 46 | __u32 cpu; /* current CPU */ | 
| 47 | __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ | 47 | __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ | 
| @@ -55,6 +55,10 @@ struct thread_info { | |||
| 55 | __u8 supervisor_stack[0]; | 55 | __u8 supervisor_stack[0]; | 
| 56 | }; | 56 | }; | 
| 57 | 57 | ||
| 58 | #define thread_info_to_uregs(ti) \ | ||
| 59 | ((struct pt_regs *) \ | ||
| 60 | ((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs))) | ||
| 61 | |||
| 58 | #else /* !__ASSEMBLY__ */ | 62 | #else /* !__ASSEMBLY__ */ | 
| 59 | 63 | ||
| 60 | #ifndef __ASM_OFFSETS_H__ | 64 | #ifndef __ASM_OFFSETS_H__ | 
| @@ -102,6 +106,12 @@ struct thread_info *current_thread_info(void) | |||
| 102 | return ti; | 106 | return ti; | 
| 103 | } | 107 | } | 
| 104 | 108 | ||
| 109 | static inline __attribute__((const)) | ||
| 110 | struct pt_regs *current_frame(void) | ||
| 111 | { | ||
| 112 | return current_thread_info()->frame; | ||
| 113 | } | ||
| 114 | |||
| 105 | /* how to get the current stack pointer from C */ | 115 | /* how to get the current stack pointer from C */ | 
| 106 | static inline unsigned long current_stack_pointer(void) | 116 | static inline unsigned long current_stack_pointer(void) | 
| 107 | { | 117 | { | 
| diff --git a/arch/mn10300/include/asm/timer-regs.h b/arch/mn10300/include/asm/timer-regs.h index 1d883b7f94ab..c634977caf66 100644 --- a/arch/mn10300/include/asm/timer-regs.h +++ b/arch/mn10300/include/asm/timer-regs.h | |||
| @@ -17,21 +17,27 @@ | |||
| 17 | 17 | ||
| 18 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ | 
| 19 | 19 | ||
| 20 | /* timer prescalar control */ | 20 | /* | 
| 21 | * Timer prescalar control | ||
| 22 | */ | ||
| 21 | #define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */ | 23 | #define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */ | 
| 22 | #define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */ | 24 | #define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */ | 
| 23 | #define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */ | 25 | #define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */ | 
| 24 | 26 | ||
| 25 | /* 8 bit timers */ | 27 | /* | 
| 28 | * 8-bit timers | ||
| 29 | */ | ||
| 26 | #define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */ | 30 | #define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */ | 
| 27 | #define TM0MD_SRC 0x07 /* timer source */ | 31 | #define TM0MD_SRC 0x07 /* timer source */ | 
| 28 | #define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */ | 32 | #define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */ | 
| 29 | #define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 33 | #define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 
| 30 | #define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 34 | #define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 
| 31 | #define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */ | ||
| 32 | #define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 35 | #define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 33 | #define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 36 | #define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 37 | #if defined(CONFIG_AM33_2) | ||
| 38 | #define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */ | ||
| 34 | #define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */ | 39 | #define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */ | 
| 40 | #endif /* CONFIG_AM33_2 */ | ||
| 35 | #define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 41 | #define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 36 | #define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */ | 42 | #define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 37 | 43 | ||
| @@ -43,7 +49,9 @@ | |||
| 43 | #define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */ | 49 | #define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */ | 
| 44 | #define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 50 | #define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 45 | #define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 51 | #define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 52 | #if defined(CONFIG_AM33_2) | ||
| 46 | #define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */ | 53 | #define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */ | 
| 54 | #endif /* CONFIG_AM33_2 */ | ||
| 47 | #define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 55 | #define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 48 | #define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */ | 56 | #define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 49 | 57 | ||
| @@ -55,7 +63,9 @@ | |||
| 55 | #define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */ | 63 | #define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */ | 
| 56 | #define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 64 | #define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 57 | #define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 65 | #define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 66 | #if defined(CONFIG_AM33_2) | ||
| 58 | #define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */ | 67 | #define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */ | 
| 68 | #endif /* CONFIG_AM33_2 */ | ||
| 59 | #define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 69 | #define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 60 | #define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */ | 70 | #define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 61 | 71 | ||
| @@ -64,11 +74,13 @@ | |||
| 64 | #define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */ | 74 | #define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */ | 
| 65 | #define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 75 | #define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 
| 66 | #define TM3MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 76 | #define TM3MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 
| 67 | #define TM3MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 2 */ | 77 | #define TM3MD_SRC_TM2CASCADE 0x03 /* - cascade with timer 2 */ | 
| 68 | #define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 78 | #define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 69 | #define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 79 | #define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 70 | #define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 80 | #define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 81 | #if defined(CONFIG_AM33_2) | ||
| 71 | #define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */ | 82 | #define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */ | 
| 83 | #endif /* CONFIG_AM33_2 */ | ||
| 72 | #define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 84 | #define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 73 | #define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */ | 85 | #define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 74 | 86 | ||
| @@ -96,7 +108,9 @@ | |||
| 96 | #define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */ | 108 | #define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */ | 
| 97 | #define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */ | 109 | #define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */ | 
| 98 | 110 | ||
| 99 | /* 16-bit timers 4,5 & 7-11 */ | 111 | /* | 
| 112 | * 16-bit timers 4,5 & 7-15 | ||
| 113 | */ | ||
| 100 | #define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */ | 114 | #define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */ | 
| 101 | #define TM4MD_SRC 0x07 /* timer source */ | 115 | #define TM4MD_SRC 0x07 /* timer source */ | 
| 102 | #define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */ | 116 | #define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */ | 
| @@ -105,7 +119,9 @@ | |||
| 105 | #define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 119 | #define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 106 | #define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 120 | #define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 107 | #define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 121 | #define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 122 | #if defined(CONFIG_AM33_2) | ||
| 108 | #define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */ | 123 | #define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */ | 
| 124 | #endif /* CONFIG_AM33_2 */ | ||
| 109 | #define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 125 | #define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 110 | #define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */ | 126 | #define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 111 | 127 | ||
| @@ -118,7 +134,11 @@ | |||
| 118 | #define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 134 | #define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 119 | #define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 135 | #define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 120 | #define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 136 | #define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 137 | #if defined(CONFIG_AM33_2) | ||
| 121 | #define TM5MD_SRC_TM5IO 0x07 /* - TM5IO pin input */ | 138 | #define TM5MD_SRC_TM5IO 0x07 /* - TM5IO pin input */ | 
| 139 | #else /* !CONFIG_AM33_2 */ | ||
| 140 | #define TM5MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 141 | #endif /* CONFIG_AM33_2 */ | ||
| 122 | #define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 142 | #define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 123 | #define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */ | 143 | #define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 124 | 144 | ||
| @@ -130,7 +150,9 @@ | |||
| 130 | #define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 150 | #define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 131 | #define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 151 | #define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 132 | #define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 152 | #define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 153 | #if defined(CONFIG_AM33_2) | ||
| 133 | #define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */ | 154 | #define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */ | 
| 155 | #endif /* CONFIG_AM33_2 */ | ||
| 134 | #define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 156 | #define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 135 | #define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */ | 157 | #define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 136 | 158 | ||
| @@ -143,7 +165,11 @@ | |||
| 143 | #define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 165 | #define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 144 | #define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 166 | #define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 145 | #define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 167 | #define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 168 | #if defined(CONFIG_AM33_2) | ||
| 146 | #define TM8MD_SRC_TM8IO 0x07 /* - TM8IO pin input */ | 169 | #define TM8MD_SRC_TM8IO 0x07 /* - TM8IO pin input */ | 
| 170 | #else /* !CONFIG_AM33_2 */ | ||
| 171 | #define TM8MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 172 | #endif /* CONFIG_AM33_2 */ | ||
| 147 | #define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 173 | #define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 148 | #define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */ | 174 | #define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 149 | 175 | ||
| @@ -156,7 +182,11 @@ | |||
| 156 | #define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 182 | #define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 157 | #define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 183 | #define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 158 | #define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 184 | #define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 185 | #if defined(CONFIG_AM33_2) | ||
| 159 | #define TM9MD_SRC_TM9IO 0x07 /* - TM9IO pin input */ | 186 | #define TM9MD_SRC_TM9IO 0x07 /* - TM9IO pin input */ | 
| 187 | #else /* !CONFIG_AM33_2 */ | ||
| 188 | #define TM9MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 189 | #endif /* CONFIG_AM33_2 */ | ||
| 160 | #define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 190 | #define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 161 | #define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */ | 191 | #define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 162 | 192 | ||
| @@ -169,7 +199,11 @@ | |||
| 169 | #define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 199 | #define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 170 | #define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 200 | #define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 171 | #define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 201 | #define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 202 | #if defined(CONFIG_AM33_2) | ||
| 172 | #define TM10MD_SRC_TM10IO 0x07 /* - TM10IO pin input */ | 203 | #define TM10MD_SRC_TM10IO 0x07 /* - TM10IO pin input */ | 
| 204 | #else /* !CONFIG_AM33_2 */ | ||
| 205 | #define TM10MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 206 | #endif /* CONFIG_AM33_2 */ | ||
| 173 | #define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 207 | #define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 174 | #define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */ | 208 | #define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 175 | 209 | ||
| @@ -178,32 +212,101 @@ | |||
| 178 | #define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */ | 212 | #define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */ | 
| 179 | #define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 213 | #define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | 
| 180 | #define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 214 | #define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | 
| 181 | #define TM11MD_SRC_TM7CASCADE 0x03 /* - cascade with timer 7 */ | ||
| 182 | #define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 215 | #define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | 
| 183 | #define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 216 | #define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | 
| 184 | #define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 217 | #define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | 
| 218 | #if defined(CONFIG_AM33_2) | ||
| 185 | #define TM11MD_SRC_TM11IO 0x07 /* - TM11IO pin input */ | 219 | #define TM11MD_SRC_TM11IO 0x07 /* - TM11IO pin input */ | 
| 220 | #else /* !CONFIG_AM33_2 */ | ||
| 221 | #define TM11MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 222 | #endif /* CONFIG_AM33_2 */ | ||
| 186 | #define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 223 | #define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | 
| 187 | #define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */ | 224 | #define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */ | 
| 188 | 225 | ||
| 226 | #if defined(CONFIG_AM34_2) | ||
| 227 | #define TM12MD __SYSREG(0xd4003180, u8) /* timer 11 mode register */ | ||
| 228 | #define TM12MD_SRC 0x07 /* timer source */ | ||
| 229 | #define TM12MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
| 230 | #define TM12MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
| 231 | #define TM12MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
| 232 | #define TM12MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
| 233 | #define TM12MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
| 234 | #define TM12MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
| 235 | #define TM12MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 236 | #define TM12MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
| 237 | #define TM12MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
| 238 | |||
| 239 | #define TM13MD __SYSREG(0xd4003182, u8) /* timer 11 mode register */ | ||
| 240 | #define TM13MD_SRC 0x07 /* timer source */ | ||
| 241 | #define TM13MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
| 242 | #define TM13MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
| 243 | #define TM13MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
| 244 | #define TM13MD_SRC_TM12CASCADE 0x03 /* - cascade with timer 12 */ | ||
| 245 | #define TM13MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
| 246 | #define TM13MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
| 247 | #define TM13MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
| 248 | #define TM13MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 249 | #define TM13MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
| 250 | #define TM13MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
| 251 | |||
| 252 | #define TM14MD __SYSREG(0xd4003184, u8) /* timer 11 mode register */ | ||
| 253 | #define TM14MD_SRC 0x07 /* timer source */ | ||
| 254 | #define TM14MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
| 255 | #define TM14MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
| 256 | #define TM14MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
| 257 | #define TM14MD_SRC_TM13CASCADE 0x03 /* - cascade with timer 13 */ | ||
| 258 | #define TM14MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
| 259 | #define TM14MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
| 260 | #define TM14MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
| 261 | #define TM14MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 262 | #define TM14MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
| 263 | #define TM14MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
| 264 | |||
| 265 | #define TM15MD __SYSREG(0xd4003186, u8) /* timer 11 mode register */ | ||
| 266 | #define TM15MD_SRC 0x07 /* timer source */ | ||
| 267 | #define TM15MD_SRC_IOCLK 0x00 /* - IOCLK */ | ||
| 268 | #define TM15MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */ | ||
| 269 | #define TM15MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */ | ||
| 270 | #define TM15MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */ | ||
| 271 | #define TM15MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */ | ||
| 272 | #define TM15MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */ | ||
| 273 | #define TM15MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */ | ||
| 274 | #define TM15MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */ | ||
| 275 | #define TM15MD_COUNT_ENABLE 0x80 /* timer count enable */ | ||
| 276 | #endif /* CONFIG_AM34_2 */ | ||
| 277 | |||
| 278 | |||
| 189 | #define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */ | 279 | #define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */ | 
| 190 | #define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */ | 280 | #define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */ | 
| 281 | #define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */ | ||
| 191 | #define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */ | 282 | #define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */ | 
| 192 | #define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */ | 283 | #define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */ | 
| 193 | #define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */ | 284 | #define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */ | 
| 285 | #define TM89BR __SYSREG(0xd4003098, u32) /* timer 8:9 base register */ | ||
| 194 | #define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */ | 286 | #define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */ | 
| 195 | #define TM11BR __SYSREG(0xd400309e, u16) /* timer 11 base register */ | 287 | #define TM11BR __SYSREG(0xd400309e, u16) /* timer 11 base register */ | 
| 196 | #define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */ | 288 | #if defined(CONFIG_AM34_2) | 
| 289 | #define TM12BR __SYSREG(0xd4003190, u16) /* timer 12 base register */ | ||
| 290 | #define TM13BR __SYSREG(0xd4003192, u16) /* timer 13 base register */ | ||
| 291 | #define TM14BR __SYSREG(0xd4003194, u16) /* timer 14 base register */ | ||
| 292 | #define TM15BR __SYSREG(0xd4003196, u16) /* timer 15 base register */ | ||
| 293 | #endif /* CONFIG_AM34_2 */ | ||
| 197 | 294 | ||
| 198 | #define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */ | 295 | #define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */ | 
| 199 | #define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */ | 296 | #define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */ | 
| 200 | #define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */ | 297 | #define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */ | 
| 201 | |||
| 202 | #define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */ | 298 | #define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */ | 
| 203 | #define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */ | 299 | #define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */ | 
| 204 | #define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */ | 300 | #define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */ | 
| 301 | #define TM89BC __SYSREG(0xd40030a8, u32) /* timer 8:9 binary counter */ | ||
| 205 | #define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */ | 302 | #define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */ | 
| 206 | #define TM11BC __SYSREG(0xd40030ae, u16) /* timer 11 binary counter */ | 303 | #define TM11BC __SYSREG(0xd40030ae, u16) /* timer 11 binary counter */ | 
| 304 | #if defined(CONFIG_AM34_2) | ||
| 305 | #define TM12BC __SYSREG(0xd40031a0, u16) /* timer 12 binary counter */ | ||
| 306 | #define TM13BC __SYSREG(0xd40031a2, u16) /* timer 13 binary counter */ | ||
| 307 | #define TM14BC __SYSREG(0xd40031a4, u16) /* timer 14 binary counter */ | ||
| 308 | #define TM15BC __SYSREG(0xd40031a6, u16) /* timer 15 binary counter */ | ||
| 309 | #endif /* CONFIG_AM34_2 */ | ||
| 207 | 310 | ||
| 208 | #define TM4IRQ 6 /* timer 4 IRQ */ | 311 | #define TM4IRQ 6 /* timer 4 IRQ */ | 
| 209 | #define TM5IRQ 7 /* timer 5 IRQ */ | 312 | #define TM5IRQ 7 /* timer 5 IRQ */ | 
| @@ -212,6 +315,12 @@ | |||
| 212 | #define TM9IRQ 13 /* timer 9 IRQ */ | 315 | #define TM9IRQ 13 /* timer 9 IRQ */ | 
| 213 | #define TM10IRQ 14 /* timer 10 IRQ */ | 316 | #define TM10IRQ 14 /* timer 10 IRQ */ | 
| 214 | #define TM11IRQ 15 /* timer 11 IRQ */ | 317 | #define TM11IRQ 15 /* timer 11 IRQ */ | 
| 318 | #if defined(CONFIG_AM34_2) | ||
| 319 | #define TM12IRQ 64 /* timer 12 IRQ */ | ||
| 320 | #define TM13IRQ 65 /* timer 13 IRQ */ | ||
| 321 | #define TM14IRQ 66 /* timer 14 IRQ */ | ||
| 322 | #define TM15IRQ 67 /* timer 15 IRQ */ | ||
| 323 | #endif /* CONFIG_AM34_2 */ | ||
| 215 | 324 | ||
| 216 | #define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */ | 325 | #define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */ | 
| 217 | #define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */ | 326 | #define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */ | 
| @@ -220,8 +329,16 @@ | |||
| 220 | #define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */ | 329 | #define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */ | 
| 221 | #define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */ | 330 | #define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */ | 
| 222 | #define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */ | 331 | #define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */ | 
| 223 | 332 | #if defined(CONFIG_AM34_2) | |
| 224 | /* 16-bit timer 6 */ | 333 | #define TM12ICR GxICR(TM12IRQ) /* timer 12 uflow intr ctrl reg */ | 
| 334 | #define TM13ICR GxICR(TM13IRQ) /* timer 13 uflow intr ctrl reg */ | ||
| 335 | #define TM14ICR GxICR(TM14IRQ) /* timer 14 uflow intr ctrl reg */ | ||
| 336 | #define TM15ICR GxICR(TM15IRQ) /* timer 15 uflow intr ctrl reg */ | ||
| 337 | #endif /* CONFIG_AM34_2 */ | ||
| 338 | |||
| 339 | /* | ||
| 340 | * 16-bit timer 6 | ||
| 341 | */ | ||
| 225 | #define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */ | 342 | #define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */ | 
| 226 | #define TM6MD_SRC 0x0007 /* timer source */ | 343 | #define TM6MD_SRC 0x0007 /* timer source */ | 
| 227 | #define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */ | 344 | #define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */ | 
| @@ -229,10 +346,14 @@ | |||
| 229 | #define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 346 | #define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */ | 
| 230 | #define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */ | 347 | #define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */ | 
| 231 | #define TM6MD_SRC_TM1UFLOW 0x0005 /* - timer 1 underflow */ | 348 | #define TM6MD_SRC_TM1UFLOW 0x0005 /* - timer 1 underflow */ | 
| 232 | #define TM6MD_SRC_TM6IOB_BOTH 0x0006 /* - TM6IOB pin input (both edges) */ | 349 | #define TM6MD_SRC_TM2UFLOW 0x0006 /* - timer 2 underflow */ | 
| 350 | #if defined(CONFIG_AM33_2) | ||
| 351 | /* #define TM6MD_SRC_TM6IOB_BOTH 0x0006 */ /* - TM6IOB pin input (both edges) */ | ||
| 233 | #define TM6MD_SRC_TM6IOB_SINGLE 0x0007 /* - TM6IOB pin input (single edge) */ | 352 | #define TM6MD_SRC_TM6IOB_SINGLE 0x0007 /* - TM6IOB pin input (single edge) */ | 
| 234 | #define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */ | 353 | #endif /* CONFIG_AM33_2 */ | 
| 235 | #define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */ | 354 | #define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */ | 
| 355 | #define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */ | ||
| 356 | #if defined(CONFIG_AM33_2) | ||
| 236 | #define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */ | 357 | #define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */ | 
| 237 | #define TM6MD_PWM 0x3800 /* PWM output mode */ | 358 | #define TM6MD_PWM 0x3800 /* PWM output mode */ | 
| 238 | #define TM6MD_PWM_DIS 0x0000 /* - disabled */ | 359 | #define TM6MD_PWM_DIS 0x0000 /* - disabled */ | 
| @@ -240,10 +361,15 @@ | |||
| 240 | #define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */ | 361 | #define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */ | 
| 241 | #define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */ | 362 | #define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */ | 
| 242 | #define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */ | 363 | #define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */ | 
| 364 | #endif /* CONFIG_AM33_2 */ | ||
| 365 | |||
| 243 | #define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */ | 366 | #define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */ | 
| 244 | #define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */ | 367 | #define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */ | 
| 245 | 368 | ||
| 246 | #define TM6MDA __SYSREG(0xd40030b4, u8) /* timer6 cmp/cap A mode reg */ | 369 | #define TM6MDA __SYSREG(0xd40030b4, u8) /* timer6 cmp/cap A mode reg */ | 
| 370 | #define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
| 371 | #define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
| 372 | #if defined(CONFIG_AM33_2) | ||
| 247 | #define TM6MDA_OUT 0x07 /* output select */ | 373 | #define TM6MDA_OUT 0x07 /* output select */ | 
| 248 | #define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */ | 374 | #define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */ | 
| 249 | #define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */ | 375 | #define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */ | 
| @@ -251,30 +377,35 @@ | |||
| 251 | #define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */ | 377 | #define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */ | 
| 252 | #define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */ | 378 | #define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */ | 
| 253 | #define TM6MDA_MODE 0xc0 /* compare A register mode */ | 379 | #define TM6MDA_MODE 0xc0 /* compare A register mode */ | 
| 254 | #define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
| 255 | #define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
| 256 | #define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 380 | #define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 
| 257 | #define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 381 | #define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 
| 258 | #define TM6MDA_EDGE 0x20 /* compare A edge select */ | 382 | #define TM6MDA_EDGE 0x20 /* compare A edge select */ | 
| 259 | #define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */ | 383 | #define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */ | 
| 260 | #define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */ | 384 | #define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */ | 
| 261 | #define TM6MDA_CAPTURE_ENABLE 0x10 /* capture enable */ | 385 | #define TM6MDA_CAPTURE_ENABLE 0x10 /* capture enable */ | 
| 386 | #else /* !CONFIG_AM33_2 */ | ||
| 387 | #define TM6MDA_MODE 0x40 /* compare A register mode */ | ||
| 388 | #endif /* CONFIG_AM33_2 */ | ||
| 262 | 389 | ||
| 263 | #define TM6MDB __SYSREG(0xd40030b5, u8) /* timer6 cmp/cap B mode reg */ | 390 | #define TM6MDB __SYSREG(0xd40030b5, u8) /* timer6 cmp/cap B mode reg */ | 
| 391 | #define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
| 392 | #define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
| 393 | #if defined(CONFIG_AM33_2) | ||
| 264 | #define TM6MDB_OUT 0x07 /* output select */ | 394 | #define TM6MDB_OUT 0x07 /* output select */ | 
| 265 | #define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */ | 395 | #define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */ | 
| 266 | #define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */ | 396 | #define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */ | 
| 267 | #define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */ | 397 | #define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */ | 
| 268 | #define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */ | 398 | #define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */ | 
| 269 | #define TM6MDB_MODE 0xc0 /* compare B register mode */ | 399 | #define TM6MDB_MODE 0xc0 /* compare B register mode */ | 
| 270 | #define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */ | ||
| 271 | #define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */ | ||
| 272 | #define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 400 | #define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */ | 
| 273 | #define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 401 | #define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */ | 
| 274 | #define TM6MDB_EDGE 0x20 /* compare B edge select */ | 402 | #define TM6MDB_EDGE 0x20 /* compare B edge select */ | 
| 275 | #define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */ | 403 | #define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */ | 
| 276 | #define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */ | 404 | #define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */ | 
| 277 | #define TM6MDB_CAPTURE_ENABLE 0x10 /* capture enable */ | 405 | #define TM6MDB_CAPTURE_ENABLE 0x10 /* capture enable */ | 
| 406 | #else /* !CONFIG_AM33_2 */ | ||
| 407 | #define TM6MDB_MODE 0x40 /* compare B register mode */ | ||
| 408 | #endif /* CONFIG_AM33_2 */ | ||
| 278 | 409 | ||
| 279 | #define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */ | 410 | #define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */ | 
| 280 | #define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */ | 411 | #define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */ | 
| @@ -288,6 +419,34 @@ | |||
| 288 | #define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */ | 419 | #define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */ | 
| 289 | #define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */ | 420 | #define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */ | 
| 290 | 421 | ||
| 422 | #if defined(CONFIG_AM34_2) | ||
| 423 | /* | ||
| 424 | * MTM: OS Tick-Timer | ||
| 425 | */ | ||
| 426 | #define TMTMD __SYSREG(0xd4004100, u8) /* Tick Timer mode register */ | ||
| 427 | #define TMTMD_TMTLDE 0x40 /* initialize TMTBC = TMTBR */ | ||
| 428 | #define TMTMD_TMTCNE 0x80 /* timer count enable */ | ||
| 429 | |||
| 430 | #define TMTBR __SYSREG(0xd4004110, u32) /* Tick Timer mode reg */ | ||
| 431 | #define TMTBC __SYSREG(0xd4004120, u32) /* Tick Timer mode reg */ | ||
| 432 | |||
| 433 | /* | ||
| 434 | * MTM: OS Timestamp-Timer | ||
| 435 | */ | ||
| 436 | #define TMSMD __SYSREG(0xd4004140, u8) /* Tick Timer mode register */ | ||
| 437 | #define TMSMD_TMSLDE 0x40 /* initialize TMSBC = TMSBR */ | ||
| 438 | #define TMSMD_TMSCNE 0x80 /* timer count enable */ | ||
| 439 | |||
| 440 | #define TMSBR __SYSREG(0xd4004150, u32) /* Tick Timer mode register */ | ||
| 441 | #define TMSBC __SYSREG(0xd4004160, u32) /* Tick Timer mode register */ | ||
| 442 | |||
| 443 | #define TMTIRQ 119 /* OS Tick timer IRQ */ | ||
| 444 | #define TMSIRQ 120 /* Timestamp timer IRQ */ | ||
| 445 | |||
| 446 | #define TMTICR GxICR(TMTIRQ) /* OS Tick timer uflow intr ctrl reg */ | ||
| 447 | #define TMSICR GxICR(TMSIRQ) /* Timestamp timer uflow intr ctrl reg */ | ||
| 448 | #endif /* CONFIG_AM34_2 */ | ||
| 449 | |||
| 291 | #endif /* __KERNEL__ */ | 450 | #endif /* __KERNEL__ */ | 
| 292 | 451 | ||
| 293 | #endif /* _ASM_TIMER_REGS_H */ | 452 | #endif /* _ASM_TIMER_REGS_H */ | 
| diff --git a/arch/mn10300/include/asm/timex.h b/arch/mn10300/include/asm/timex.h index 8d031f9e117d..bd4e90dfe6c2 100644 --- a/arch/mn10300/include/asm/timex.h +++ b/arch/mn10300/include/asm/timex.h | |||
| @@ -16,18 +16,30 @@ | |||
| 16 | 16 | ||
| 17 | #define TICK_SIZE (tick_nsec / 1000) | 17 | #define TICK_SIZE (tick_nsec / 1000) | 
| 18 | 18 | ||
| 19 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ - this should probably be set | 19 | #define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */ | 
| 20 | * to something appropriate, but what? */ | ||
| 21 | |||
| 22 | extern cycles_t cacheflush_time; | ||
| 23 | 20 | ||
| 24 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ | 
| 25 | 22 | ||
| 23 | extern cycles_t cacheflush_time; | ||
| 24 | |||
| 26 | static inline cycles_t get_cycles(void) | 25 | static inline cycles_t get_cycles(void) | 
| 27 | { | 26 | { | 
| 28 | return read_timestamp_counter(); | 27 | return read_timestamp_counter(); | 
| 29 | } | 28 | } | 
| 30 | 29 | ||
| 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 | |||
| 31 | #endif /* __KERNEL__ */ | 43 | #endif /* __KERNEL__ */ | 
| 32 | 44 | ||
| 33 | #endif /* _ASM_TIMEX_H */ | 45 | #endif /* _ASM_TIMEX_H */ | 
| diff --git a/arch/mn10300/include/asm/tlbflush.h b/arch/mn10300/include/asm/tlbflush.h index 1a7e29281c5d..efddd6e1adea 100644 --- a/arch/mn10300/include/asm/tlbflush.h +++ b/arch/mn10300/include/asm/tlbflush.h | |||
| @@ -11,24 +11,78 @@ | |||
| 11 | #ifndef _ASM_TLBFLUSH_H | 11 | #ifndef _ASM_TLBFLUSH_H | 
| 12 | #define _ASM_TLBFLUSH_H | 12 | #define _ASM_TLBFLUSH_H | 
| 13 | 13 | ||
| 14 | #include <linux/mm.h> | ||
| 14 | #include <asm/processor.h> | 15 | #include <asm/processor.h> | 
| 15 | 16 | ||
| 16 | #define __flush_tlb() \ | 17 | struct tlb_state { | 
| 17 | do { \ | 18 | struct mm_struct *active_mm; | 
| 18 | int w; \ | 19 | int state; | 
| 19 | __asm__ __volatile__ \ | 20 | }; | 
| 20 | (" mov %1,%0 \n" \ | 21 | DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); | 
| 21 | " or %2,%0 \n" \ | ||
| 22 | " mov %0,%1 \n" \ | ||
| 23 | : "=d"(w) \ | ||
| 24 | : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV) \ | ||
| 25 | : "cc", "memory" \ | ||
| 26 | ); \ | ||
| 27 | } while (0) | ||
| 28 | 22 | ||
| 29 | #define __flush_tlb_all() __flush_tlb() | 23 | /** | 
| 30 | #define __flush_tlb_one(addr) __flush_tlb() | 24 | * local_flush_tlb - Flush the current MM's entries from the local CPU's TLBs | 
| 25 | */ | ||
| 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 | } | ||
| 31 | 45 | ||
| 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 | } | ||
| 32 | 86 | ||
| 33 | /* | 87 | /* | 
| 34 | * TLB flushing: | 88 | * TLB flushing: | 
| @@ -40,41 +94,61 @@ do { \ | |||
| 40 | * - flush_tlb_range(mm, start, end) flushes a range of pages | 94 | * - flush_tlb_range(mm, start, end) flushes a range of pages | 
| 41 | * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables | 95 | * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables | 
| 42 | */ | 96 | */ | 
| 43 | #define flush_tlb_all() \ | 97 | #ifdef CONFIG_SMP | 
| 44 | do { \ | 98 | |
| 45 | preempt_disable(); \ | 99 | #include <asm/smp.h> | 
| 46 | __flush_tlb_all(); \ | 100 | |
| 47 | preempt_enable(); \ | 101 | extern void flush_tlb_all(void); | 
| 48 | } while (0) | 102 | extern void flush_tlb_current_task(void); | 
| 49 | 103 | extern void flush_tlb_mm(struct mm_struct *); | |
| 50 | #define flush_tlb_mm(mm) \ | 104 | extern void flush_tlb_page(struct vm_area_struct *, unsigned long); | 
| 51 | do { \ | 105 | |
| 52 | preempt_disable(); \ | 106 | #define flush_tlb() flush_tlb_current_task() | 
| 53 | __flush_tlb_all(); \ | 107 | |
| 54 | preempt_enable(); \ | 108 | static inline void flush_tlb_range(struct vm_area_struct *vma, | 
| 55 | } while (0) | 109 | unsigned long start, unsigned long end) | 
| 56 | 110 | { | |
| 57 | #define flush_tlb_range(vma, start, end) \ | 111 | flush_tlb_mm(vma->vm_mm); | 
| 58 | do { \ | 112 | } | 
| 59 | unsigned long __s __attribute__((unused)) = (start); \ | 113 | |
| 60 | unsigned long __e __attribute__((unused)) = (end); \ | 114 | #else /* CONFIG_SMP */ | 
| 61 | preempt_disable(); \ | 115 | |
| 62 | __flush_tlb_all(); \ | 116 | static inline void flush_tlb_all(void) | 
| 63 | preempt_enable(); \ | 117 | { | 
| 64 | } while (0) | 118 | preempt_disable(); | 
| 65 | 119 | local_flush_tlb_all(); | |
| 66 | 120 | preempt_enable(); | |
| 67 | #define __flush_tlb_global() flush_tlb_all() | 121 | } | 
| 68 | #define flush_tlb() flush_tlb_all() | 122 | |
| 69 | #define flush_tlb_kernel_range(start, end) \ | 123 | static inline void flush_tlb_mm(struct mm_struct *mm) | 
| 70 | do { \ | 124 | { | 
| 71 | unsigned long __s __attribute__((unused)) = (start); \ | 125 | preempt_disable(); | 
| 72 | unsigned long __e __attribute__((unused)) = (end); \ | 126 | local_flush_tlb_all(); | 
| 73 | flush_tlb_all(); \ | 127 | preempt_enable(); | 
| 74 | } while (0) | 128 | } | 
| 75 | 129 | ||
| 76 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); | 130 | static inline void flush_tlb_range(struct vm_area_struct *vma, | 
| 77 | 131 | unsigned long start, unsigned long end) | |
| 78 | #define flush_tlb_pgtables(mm, start, end) do {} while (0) | 132 | { | 
| 133 | preempt_disable(); | ||
| 134 | local_flush_tlb_all(); | ||
| 135 | preempt_enable(); | ||
| 136 | } | ||
| 137 | |||
| 138 | #define flush_tlb_page(vma, addr) local_flush_tlb_page((vma)->vm_mm, addr) | ||
| 139 | #define flush_tlb() flush_tlb_all() | ||
| 140 | |||
| 141 | #endif /* CONFIG_SMP */ | ||
| 142 | |||
| 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 | } | ||
| 79 | 153 | ||
| 80 | #endif /* _ASM_TLBFLUSH_H */ | 154 | #endif /* _ASM_TLBFLUSH_H */ | 
| diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 197a7af3dd8a..679dee0bbd08 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h | |||
| @@ -14,9 +14,8 @@ | |||
| 14 | /* | 14 | /* | 
| 15 | * User space memory access functions | 15 | * User space memory access functions | 
| 16 | */ | 16 | */ | 
| 17 | #include <linux/sched.h> | 17 | #include <linux/thread_info.h> | 
| 18 | #include <asm/page.h> | 18 | #include <asm/page.h> | 
| 19 | #include <asm/pgtable.h> | ||
| 20 | #include <asm/errno.h> | 19 | #include <asm/errno.h> | 
| 21 | 20 | ||
| 22 | #define VERIFY_READ 0 | 21 | #define VERIFY_READ 0 | 
| @@ -29,7 +28,6 @@ | |||
| 29 | * | 28 | * | 
| 30 | * For historical reasons, these macros are grossly misnamed. | 29 | * For historical reasons, these macros are grossly misnamed. | 
| 31 | */ | 30 | */ | 
| 32 | |||
| 33 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | 31 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | 
| 34 | 32 | ||
| 35 | #define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF) | 33 | #define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF) | 
| @@ -377,7 +375,7 @@ unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, | |||
| 377 | 375 | ||
| 378 | 376 | ||
| 379 | #if 0 | 377 | #if 0 | 
| 380 | #error don't use - these macros don't increment to & from pointers | 378 | #error "don't use - these macros don't increment to & from pointers" | 
| 381 | /* Optimize just a little bit when we know the size of the move. */ | 379 | /* Optimize just a little bit when we know the size of the move. */ | 
| 382 | #define __constant_copy_user(to, from, size) \ | 380 | #define __constant_copy_user(to, from, size) \ | 
| 383 | do { \ | 381 | do { \ | 
| diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 23f2ab67574c..8f5f1e81baf5 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile | |||
| @@ -3,13 +3,16 @@ | |||
| 3 | # | 3 | # | 
| 4 | extra-y := head.o init_task.o vmlinux.lds | 4 | extra-y := head.o init_task.o vmlinux.lds | 
| 5 | 5 | ||
| 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 \ | ||
| 7 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ | 10 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ | 
| 8 | switch_to.o mn10300_ksyms.o kernel_execve.o | 11 | switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) | 
| 9 | 12 | ||
| 10 | obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o | 13 | obj-$(CONFIG_SMP) += smp.o smp-low.o | 
| 11 | 14 | ||
| 12 | obj-$(CONFIG_FPU) += fpu-low.o | 15 | obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o | 
| 13 | 16 | ||
| 14 | obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ | 17 | obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ | 
| 15 | mn10300-debug.o | 18 | mn10300-debug.o | 
| @@ -17,7 +20,7 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o | |||
| 17 | obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o | 20 | obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o | 
| 18 | obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o | 21 | obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o | 
| 19 | 22 | ||
| 20 | ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y) | 23 | ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y) | 
| 21 | obj-$(CONFIG_GDBSTUB) += gdb-cache.o | 24 | obj-$(CONFIG_GDBSTUB) += gdb-cache.o | 
| 22 | endif | 25 | endif | 
| 23 | 26 | ||
| @@ -25,3 +28,5 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o | |||
| 25 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o | 28 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o | 
| 26 | obj-$(CONFIG_MODULES) += module.o | 29 | obj-$(CONFIG_MODULES) += module.o | 
| 27 | obj-$(CONFIG_KPROBES) += kprobes.o | 30 | obj-$(CONFIG_KPROBES) += kprobes.o | 
| 31 | obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o | ||
| 32 | obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o | ||
| diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c index 02dc7e461fef..96f24fab7de6 100644 --- a/arch/mn10300/kernel/asm-offsets.c +++ b/arch/mn10300/kernel/asm-offsets.c | |||
| @@ -23,6 +23,7 @@ void foo(void) | |||
| 23 | 23 | ||
| 24 | OFFSET(TI_task, thread_info, task); | 24 | OFFSET(TI_task, thread_info, task); | 
| 25 | OFFSET(TI_exec_domain, thread_info, exec_domain); | 25 | OFFSET(TI_exec_domain, thread_info, exec_domain); | 
| 26 | OFFSET(TI_frame, thread_info, frame); | ||
| 26 | OFFSET(TI_flags, thread_info, flags); | 27 | OFFSET(TI_flags, thread_info, flags); | 
| 27 | OFFSET(TI_cpu, thread_info, cpu); | 28 | OFFSET(TI_cpu, thread_info, cpu); | 
| 28 | OFFSET(TI_preempt_count, thread_info, preempt_count); | 29 | OFFSET(TI_preempt_count, thread_info, preempt_count); | 
| @@ -66,7 +67,15 @@ void foo(void) | |||
| 66 | OFFSET(THREAD_SP, thread_struct, sp); | 67 | OFFSET(THREAD_SP, thread_struct, sp); | 
| 67 | OFFSET(THREAD_A3, thread_struct, a3); | 68 | OFFSET(THREAD_A3, thread_struct, a3); | 
| 68 | OFFSET(THREAD_USP, thread_struct, usp); | 69 | OFFSET(THREAD_USP, thread_struct, usp); | 
| 69 | OFFSET(THREAD_FRAME, thread_struct, __frame); | 70 | #ifdef CONFIG_FPU | 
| 71 | OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags); | ||
| 72 | OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state); | ||
| 73 | DEFINE(__THREAD_USING_FPU, THREAD_USING_FPU); | ||
| 74 | DEFINE(__THREAD_HAS_FPU, THREAD_HAS_FPU); | ||
| 75 | #endif /* CONFIG_FPU */ | ||
| 76 | BLANK(); | ||
| 77 | |||
| 78 | OFFSET(TASK_THREAD, task_struct, thread); | ||
| 70 | BLANK(); | 79 | BLANK(); | 
| 71 | 80 | ||
| 72 | DEFINE(CLONE_VM_asm, CLONE_VM); | 81 | DEFINE(CLONE_VM_asm, CLONE_VM); | 
| diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c new file mode 100644 index 000000000000..d4cb535bf786 --- /dev/null +++ b/arch/mn10300/kernel/cevt-mn10300.c | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* MN10300 clockevents | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by Mark Salter (msalter@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/clockchips.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/percpu.h> | ||
| 14 | #include <linux/smp.h> | ||
| 15 | #include <asm/timex.h> | ||
| 16 | #include "internal.h" | ||
| 17 | |||
| 18 | #ifdef CONFIG_SMP | ||
| 19 | #if (CONFIG_NR_CPUS > 2) && !defined(CONFIG_GEENERIC_CLOCKEVENTS_BROADCAST) | ||
| 20 | #error "This doesn't scale well! Need per-core local timers." | ||
| 21 | #endif | ||
| 22 | #else /* CONFIG_SMP */ | ||
| 23 | #define stop_jiffies_counter1() | ||
| 24 | #define reload_jiffies_counter1(x) | ||
| 25 | #define TMJC1IRQ TMJCIRQ | ||
| 26 | #endif | ||
| 27 | |||
| 28 | |||
| 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 | } | ||
| diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c new file mode 100644 index 000000000000..ba2f0c4d6e01 --- /dev/null +++ b/arch/mn10300/kernel/csrc-mn10300.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* MN10300 clocksource | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by Mark Salter (msalter@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/clocksource.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <asm/timex.h> | ||
| 14 | #include "internal.h" | ||
| 15 | |||
| 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 | } | ||
| diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 3d394b4eefba..f00b9bafcd3e 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S | |||
| @@ -28,25 +28,17 @@ | |||
| 28 | #include <asm/asm-offsets.h> | 28 | #include <asm/asm-offsets.h> | 
| 29 | #include <asm/frame.inc> | 29 | #include <asm/frame.inc> | 
| 30 | 30 | ||
| 31 | #if defined(CONFIG_SMP) && defined(CONFIG_GDBSTUB) | ||
| 32 | #include <asm/gdb-stub.h> | ||
| 33 | #endif /* CONFIG_SMP && CONFIG_GDBSTUB */ | ||
| 34 | |||
| 31 | #ifdef CONFIG_PREEMPT | 35 | #ifdef CONFIG_PREEMPT | 
| 32 | #define preempt_stop __cli | 36 | #define preempt_stop LOCAL_IRQ_DISABLE | 
| 33 | #else | 37 | #else | 
| 34 | #define preempt_stop | 38 | #define preempt_stop | 
| 35 | #define resume_kernel restore_all | 39 | #define resume_kernel restore_all | 
| 36 | #endif | 40 | #endif | 
| 37 | 41 | ||
| 38 | .macro __cli | ||
| 39 | and ~EPSW_IM,epsw | ||
| 40 | or EPSW_IE|MN10300_CLI_LEVEL,epsw | ||
| 41 | nop | ||
| 42 | nop | ||
| 43 | nop | ||
| 44 | .endm | ||
| 45 | .macro __sti | ||
| 46 | or EPSW_IE|EPSW_IM_7,epsw | ||
| 47 | .endm | ||
| 48 | |||
| 49 | |||
| 50 | .am33_2 | 42 | .am33_2 | 
| 51 | 43 | ||
| 52 | ############################################################################### | 44 | ############################################################################### | 
| @@ -88,7 +80,7 @@ syscall_call: | |||
| 88 | syscall_exit: | 80 | syscall_exit: | 
| 89 | # make sure we don't miss an interrupt setting need_resched or | 81 | # make sure we don't miss an interrupt setting need_resched or | 
| 90 | # sigpending between sampling and the rti | 82 | # sigpending between sampling and the rti | 
| 91 | __cli | 83 | LOCAL_IRQ_DISABLE | 
| 92 | mov (TI_flags,a2),d2 | 84 | mov (TI_flags,a2),d2 | 
| 93 | btst _TIF_ALLWORK_MASK,d2 | 85 | btst _TIF_ALLWORK_MASK,d2 | 
| 94 | bne syscall_exit_work | 86 | bne syscall_exit_work | 
| @@ -105,7 +97,7 @@ restore_all: | |||
| 105 | syscall_exit_work: | 97 | syscall_exit_work: | 
| 106 | btst _TIF_SYSCALL_TRACE,d2 | 98 | btst _TIF_SYSCALL_TRACE,d2 | 
| 107 | beq work_pending | 99 | beq work_pending | 
| 108 | __sti # could let syscall_trace_exit() call | 100 | LOCAL_IRQ_ENABLE # could let syscall_trace_exit() call | 
| 109 | # schedule() instead | 101 | # schedule() instead | 
| 110 | mov fp,d0 | 102 | mov fp,d0 | 
| 111 | call syscall_trace_exit[],0 # do_syscall_trace(regs) | 103 | call syscall_trace_exit[],0 # do_syscall_trace(regs) | 
| @@ -121,7 +113,7 @@ work_resched: | |||
| 121 | 113 | ||
| 122 | # make sure we don't miss an interrupt setting need_resched or | 114 | # make sure we don't miss an interrupt setting need_resched or | 
| 123 | # sigpending between sampling and the rti | 115 | # sigpending between sampling and the rti | 
| 124 | __cli | 116 | LOCAL_IRQ_DISABLE | 
| 125 | 117 | ||
| 126 | # is there any work to be done other than syscall tracing? | 118 | # is there any work to be done other than syscall tracing? | 
| 127 | mov (TI_flags,a2),d2 | 119 | mov (TI_flags,a2),d2 | 
| @@ -168,7 +160,7 @@ ret_from_intr: | |||
| 168 | ENTRY(resume_userspace) | 160 | ENTRY(resume_userspace) | 
| 169 | # make sure we don't miss an interrupt setting need_resched or | 161 | # make sure we don't miss an interrupt setting need_resched or | 
| 170 | # sigpending between sampling and the rti | 162 | # sigpending between sampling and the rti | 
| 171 | __cli | 163 | LOCAL_IRQ_DISABLE | 
| 172 | 164 | ||
| 173 | # is there any work to be done on int/exception return? | 165 | # is there any work to be done on int/exception return? | 
| 174 | mov (TI_flags,a2),d2 | 166 | mov (TI_flags,a2),d2 | 
| @@ -178,7 +170,7 @@ ENTRY(resume_userspace) | |||
| 178 | 170 | ||
| 179 | #ifdef CONFIG_PREEMPT | 171 | #ifdef CONFIG_PREEMPT | 
| 180 | ENTRY(resume_kernel) | 172 | ENTRY(resume_kernel) | 
| 181 | __cli | 173 | LOCAL_IRQ_DISABLE | 
| 182 | mov (TI_preempt_count,a2),d0 # non-zero preempt_count ? | 174 | mov (TI_preempt_count,a2),d0 # non-zero preempt_count ? | 
| 183 | cmp 0,d0 | 175 | cmp 0,d0 | 
| 184 | bne restore_all | 176 | bne restore_all | 
| @@ -216,31 +208,6 @@ ENTRY(irq_handler) | |||
| 216 | 208 | ||
| 217 | ############################################################################### | 209 | ############################################################################### | 
| 218 | # | 210 | # | 
| 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 | |||
| 242 | ############################################################################### | ||
| 243 | # | ||
| 244 | # Double Fault handler entry point | 211 | # Double Fault handler entry point | 
| 245 | # - note that there will not be a stack, D0/A0 will hold EPSW/PC as were | 212 | # - note that there will not be a stack, D0/A0 will hold EPSW/PC as were | 
| 246 | # | 213 | # | 
| @@ -276,6 +243,10 @@ double_fault_loop: | |||
| 276 | ENTRY(raw_bus_error) | 243 | ENTRY(raw_bus_error) | 
| 277 | add -4,sp | 244 | add -4,sp | 
| 278 | mov d0,(sp) | 245 | mov d0,(sp) | 
| 246 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 247 | mov (MMUCTR),d0 | ||
| 248 | mov d0,(MMUCTR) | ||
| 249 | #endif | ||
| 279 | mov (BCBERR),d0 # what | 250 | mov (BCBERR),d0 # what | 
| 280 | btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error | 251 | btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error | 
| 281 | beq __common_exception_aux # it wasn't | 252 | beq __common_exception_aux # it wasn't | 
| @@ -302,11 +273,88 @@ ENTRY(nmi_handler) | |||
| 302 | add -4,sp | 273 | add -4,sp | 
| 303 | mov d0,(sp) | 274 | mov d0,(sp) | 
| 304 | mov (TBR),d0 | 275 | mov (TBR),d0 | 
| 276 | |||
| 277 | #ifdef CONFIG_SMP | ||
| 278 | add -4,sp | ||
| 279 | mov d0,(sp) # save d0(TBR) | ||
| 280 | movhu (NMIAGR),d0 | ||
| 281 | and NMIAGR_GN,d0 | ||
| 282 | lsr 0x2,d0 | ||
| 283 | cmp CALL_FUNCTION_NMI_IPI,d0 | ||
| 284 | bne 5f # if not call function, jump | ||
| 285 | |||
| 286 | # function call nmi ipi | ||
| 287 | add 4,sp # no need to store TBR | ||
| 288 | mov GxICR_DETECT,d0 # clear NMI request | ||
| 289 | movbu d0,(GxICR(CALL_FUNCTION_NMI_IPI)) | ||
| 290 | movhu (GxICR(CALL_FUNCTION_NMI_IPI)),d0 | ||
| 291 | and ~EPSW_NMID,epsw # enable NMI | ||
| 292 | |||
| 293 | mov (sp),d0 # restore d0 | ||
| 294 | SAVE_ALL | ||
| 295 | call smp_nmi_call_function_interrupt[],0 | ||
| 296 | RESTORE_ALL | ||
| 297 | |||
| 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 | |||
| 305 | bra __common_exception_nonmi | 349 | bra __common_exception_nonmi | 
| 306 | 350 | ||
| 307 | ENTRY(__common_exception) | 351 | ENTRY(__common_exception) | 
| 308 | add -4,sp | 352 | add -4,sp | 
| 309 | mov d0,(sp) | 353 | mov d0,(sp) | 
| 354 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 355 | mov (MMUCTR),d0 | ||
| 356 | mov d0,(MMUCTR) | ||
| 357 | #endif | ||
| 310 | 358 | ||
| 311 | __common_exception_aux: | 359 | __common_exception_aux: | 
| 312 | mov (TBR),d0 | 360 | mov (TBR),d0 | 
| @@ -331,15 +379,21 @@ __common_exception_nonmi: | |||
| 331 | mov d0,(REG_ORIG_D0,fp) | 379 | mov d0,(REG_ORIG_D0,fp) | 
| 332 | 380 | ||
| 333 | #ifdef CONFIG_GDBSTUB | 381 | #ifdef CONFIG_GDBSTUB | 
| 382 | #ifdef CONFIG_SMP | ||
| 383 | call gdbstub_busy_check[],0 | ||
| 384 | and d0,d0 # check return value | ||
| 385 | beq 2f | ||
| 386 | #else /* CONFIG_SMP */ | ||
| 334 | btst 0x01,(gdbstub_busy) | 387 | btst 0x01,(gdbstub_busy) | 
| 335 | beq 2f | 388 | beq 2f | 
| 389 | #endif /* CONFIG_SMP */ | ||
| 336 | and ~EPSW_IE,epsw | 390 | and ~EPSW_IE,epsw | 
| 337 | mov fp,d0 | 391 | mov fp,d0 | 
| 338 | mov a2,d1 | 392 | mov a2,d1 | 
| 339 | call gdbstub_exception[],0 # gdbstub itself caused an exception | 393 | call gdbstub_exception[],0 # gdbstub itself caused an exception | 
| 340 | bra restore_all | 394 | bra restore_all | 
| 341 | 2: | 395 | 2: | 
| 342 | #endif | 396 | #endif /* CONFIG_GDBSTUB */ | 
| 343 | 397 | ||
| 344 | mov fp,d0 # arg 0: stacked register file | 398 | mov fp,d0 # arg 0: stacked register file | 
| 345 | mov a2,d1 # arg 1: exception number | 399 | mov a2,d1 # arg 1: exception number | 
| @@ -374,11 +428,7 @@ ENTRY(set_excp_vector) | |||
| 374 | add exception_table,d0 | 428 | add exception_table,d0 | 
| 375 | mov d1,(d0) | 429 | mov d1,(d0) | 
| 376 | mov 4,d1 | 430 | mov 4,d1 | 
| 377 | #if defined(CONFIG_MN10300_CACHE_WBACK) | ||
| 378 | jmp mn10300_dcache_flush_inv_range2 | ||
| 379 | #else | ||
| 380 | ret [],0 | 431 | ret [],0 | 
| 381 | #endif | ||
| 382 | 432 | ||
| 383 | ############################################################################### | 433 | ############################################################################### | 
| 384 | # | 434 | # | 
| diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S index 96cfd47e68d5..78df25cfae29 100644 --- a/arch/mn10300/kernel/fpu-low.S +++ b/arch/mn10300/kernel/fpu-low.S | |||
| @@ -8,25 +8,14 @@ | |||
| 8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version | 
| 9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. | 
| 10 | */ | 10 | */ | 
| 11 | #include <linux/linkage.h> | ||
| 11 | #include <asm/cpu-regs.h> | 12 | #include <asm/cpu-regs.h> | 
| 13 | #include <asm/smp.h> | ||
| 14 | #include <asm/thread_info.h> | ||
| 15 | #include <asm/asm-offsets.h> | ||
| 16 | #include <asm/frame.inc> | ||
| 12 | 17 | ||
| 13 | ############################################################################### | 18 | .macro FPU_INIT_STATE_ALL | 
| 14 | # | ||
| 15 | # void fpu_init_state(void) | ||
| 16 | # - initialise the FPU | ||
| 17 | # | ||
| 18 | ############################################################################### | ||
| 19 | .globl fpu_init_state | ||
| 20 | .type fpu_init_state,@function | ||
| 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 | ||
| 30 | fmov 0,fs0 | 19 | fmov 0,fs0 | 
| 31 | fmov fs0,fs1 | 20 | fmov fs0,fs1 | 
| 32 | fmov fs0,fs2 | 21 | fmov fs0,fs2 | 
| @@ -60,7 +49,100 @@ fpu_init_state: | |||
| 60 | fmov fs0,fs30 | 49 | fmov fs0,fs30 | 
| 61 | fmov fs0,fs31 | 50 | fmov fs0,fs31 | 
| 62 | fmov FPCR_INIT,fpcr | 51 | fmov FPCR_INIT,fpcr | 
| 52 | .endm | ||
| 53 | |||
| 54 | .macro FPU_SAVE_ALL areg,dreg | ||
| 55 | fmov fs0,(\areg+) | ||
| 56 | fmov fs1,(\areg+) | ||
| 57 | fmov fs2,(\areg+) | ||
| 58 | fmov fs3,(\areg+) | ||
| 59 | fmov fs4,(\areg+) | ||
| 60 | fmov fs5,(\areg+) | ||
| 61 | fmov fs6,(\areg+) | ||
| 62 | fmov fs7,(\areg+) | ||
| 63 | fmov fs8,(\areg+) | ||
| 64 | fmov fs9,(\areg+) | ||
| 65 | fmov fs10,(\areg+) | ||
| 66 | fmov fs11,(\areg+) | ||
| 67 | fmov fs12,(\areg+) | ||
| 68 | fmov fs13,(\areg+) | ||
| 69 | fmov fs14,(\areg+) | ||
| 70 | fmov fs15,(\areg+) | ||
| 71 | fmov fs16,(\areg+) | ||
| 72 | fmov fs17,(\areg+) | ||
| 73 | fmov fs18,(\areg+) | ||
| 74 | fmov fs19,(\areg+) | ||
| 75 | fmov fs20,(\areg+) | ||
| 76 | fmov fs21,(\areg+) | ||
| 77 | fmov fs22,(\areg+) | ||
| 78 | fmov fs23,(\areg+) | ||
| 79 | fmov fs24,(\areg+) | ||
| 80 | fmov fs25,(\areg+) | ||
| 81 | fmov fs26,(\areg+) | ||
| 82 | fmov fs27,(\areg+) | ||
| 83 | fmov fs28,(\areg+) | ||
| 84 | fmov fs29,(\areg+) | ||
| 85 | fmov fs30,(\areg+) | ||
| 86 | fmov fs31,(\areg+) | ||
| 87 | fmov fpcr,\dreg | ||
| 88 | mov \dreg,(\areg) | ||
| 89 | .endm | ||
| 90 | |||
| 91 | .macro FPU_RESTORE_ALL areg,dreg | ||
| 92 | fmov (\areg+),fs0 | ||
| 93 | fmov (\areg+),fs1 | ||
| 94 | fmov (\areg+),fs2 | ||
| 95 | fmov (\areg+),fs3 | ||
| 96 | fmov (\areg+),fs4 | ||
| 97 | fmov (\areg+),fs5 | ||
| 98 | fmov (\areg+),fs6 | ||
| 99 | fmov (\areg+),fs7 | ||
| 100 | fmov (\areg+),fs8 | ||
| 101 | fmov (\areg+),fs9 | ||
| 102 | fmov (\areg+),fs10 | ||
| 103 | fmov (\areg+),fs11 | ||
| 104 | fmov (\areg+),fs12 | ||
| 105 | fmov (\areg+),fs13 | ||
| 106 | fmov (\areg+),fs14 | ||
| 107 | fmov (\areg+),fs15 | ||
| 108 | fmov (\areg+),fs16 | ||
| 109 | fmov (\areg+),fs17 | ||
| 110 | fmov (\areg+),fs18 | ||
| 111 | fmov (\areg+),fs19 | ||
| 112 | fmov (\areg+),fs20 | ||
| 113 | fmov (\areg+),fs21 | ||
| 114 | fmov (\areg+),fs22 | ||
| 115 | fmov (\areg+),fs23 | ||
| 116 | fmov (\areg+),fs24 | ||
| 117 | fmov (\areg+),fs25 | ||
| 118 | fmov (\areg+),fs26 | ||
| 119 | fmov (\areg+),fs27 | ||
| 120 | fmov (\areg+),fs28 | ||
| 121 | fmov (\areg+),fs29 | ||
| 122 | fmov (\areg+),fs30 | ||
| 123 | fmov (\areg+),fs31 | ||
| 124 | mov (\areg),\dreg | ||
| 125 | fmov \dreg,fpcr | ||
| 126 | .endm | ||
| 63 | 127 | ||
| 128 | ############################################################################### | ||
| 129 | # | ||
| 130 | # void fpu_init_state(void) | ||
| 131 | # - initialise the FPU | ||
| 132 | # | ||
| 133 | ############################################################################### | ||
| 134 | .globl fpu_init_state | ||
| 135 | .type fpu_init_state,@function | ||
| 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 | ||
| 64 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 146 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 
| 65 | nop | 147 | nop | 
| 66 | nop | 148 | nop | 
| @@ -89,40 +171,7 @@ fpu_save: | |||
| 89 | nop | 171 | nop | 
| 90 | #endif | 172 | #endif | 
| 91 | mov d0,a0 | 173 | mov d0,a0 | 
| 92 | fmov fs0,(a0+) | 174 | FPU_SAVE_ALL a0,d0 | 
| 93 | fmov fs1,(a0+) | ||
| 94 | fmov fs2,(a0+) | ||
| 95 | fmov fs3,(a0+) | ||
| 96 | fmov fs4,(a0+) | ||
| 97 | fmov fs5,(a0+) | ||
| 98 | fmov fs6,(a0+) | ||
| 99 | fmov fs7,(a0+) | ||
| 100 | fmov fs8,(a0+) | ||
| 101 | fmov fs9,(a0+) | ||
| 102 | fmov fs10,(a0+) | ||
| 103 | fmov fs11,(a0+) | ||
| 104 | fmov fs12,(a0+) | ||
| 105 | fmov fs13,(a0+) | ||
| 106 | fmov fs14,(a0+) | ||
| 107 | fmov fs15,(a0+) | ||
| 108 | fmov fs16,(a0+) | ||
| 109 | fmov fs17,(a0+) | ||
| 110 | fmov fs18,(a0+) | ||
| 111 | fmov fs19,(a0+) | ||
| 112 | fmov fs20,(a0+) | ||
| 113 | fmov fs21,(a0+) | ||
| 114 | fmov fs22,(a0+) | ||
| 115 | fmov fs23,(a0+) | ||
| 116 | fmov fs24,(a0+) | ||
| 117 | fmov fs25,(a0+) | ||
| 118 | fmov fs26,(a0+) | ||
| 119 | fmov fs27,(a0+) | ||
| 120 | fmov fs28,(a0+) | ||
| 121 | fmov fs29,(a0+) | ||
| 122 | fmov fs30,(a0+) | ||
| 123 | fmov fs31,(a0+) | ||
| 124 | fmov fpcr,d0 | ||
| 125 | mov d0,(a0) | ||
| 126 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 175 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 
| 127 | nop | 176 | nop | 
| 128 | nop | 177 | nop | 
| @@ -135,63 +184,75 @@ fpu_save: | |||
| 135 | 184 | ||
| 136 | ############################################################################### | 185 | ############################################################################### | 
| 137 | # | 186 | # | 
| 138 | # void fpu_restore(struct fpu_state_struct *) | 187 | # void fpu_disabled(void) | 
| 139 | # - restore the fpu state | 188 | # - handle an exception due to the FPU being disabled | 
| 140 | # - note that an FPU Operational exception might occur during this process | 189 | # when CONFIG_FPU is enabled | 
| 141 | # | 190 | # | 
| 142 | ############################################################################### | 191 | ############################################################################### | 
| 143 | .globl fpu_restore | 192 | .type fpu_disabled,@function | 
| 144 | .type fpu_restore,@function | 193 | .globl fpu_disabled | 
| 145 | fpu_restore: | 194 | fpu_disabled: | 
| 146 | mov epsw,d1 | 195 | or EPSW_nAR|EPSW_FE,epsw | 
| 147 | or EPSW_FE,epsw /* enable the FPU so we can access it */ | ||
| 148 | |||
| 149 | #ifdef CONFIG_MN10300_PROC_MN103E010 | ||
| 150 | nop | 196 | nop | 
| 151 | nop | 197 | nop | 
| 152 | #endif | ||
| 153 | mov d0,a0 | ||
| 154 | fmov (a0+),fs0 | ||
| 155 | fmov (a0+),fs1 | ||
| 156 | fmov (a0+),fs2 | ||
| 157 | fmov (a0+),fs3 | ||
| 158 | fmov (a0+),fs4 | ||
| 159 | fmov (a0+),fs5 | ||
| 160 | fmov (a0+),fs6 | ||
| 161 | fmov (a0+),fs7 | ||
| 162 | fmov (a0+),fs8 | ||
| 163 | fmov (a0+),fs9 | ||
| 164 | fmov (a0+),fs10 | ||
| 165 | fmov (a0+),fs11 | ||
| 166 | fmov (a0+),fs12 | ||
| 167 | fmov (a0+),fs13 | ||
| 168 | fmov (a0+),fs14 | ||
| 169 | fmov (a0+),fs15 | ||
| 170 | fmov (a0+),fs16 | ||
| 171 | fmov (a0+),fs17 | ||
| 172 | fmov (a0+),fs18 | ||
| 173 | fmov (a0+),fs19 | ||
| 174 | fmov (a0+),fs20 | ||
| 175 | fmov (a0+),fs21 | ||
| 176 | fmov (a0+),fs22 | ||
| 177 | fmov (a0+),fs23 | ||
| 178 | fmov (a0+),fs24 | ||
| 179 | fmov (a0+),fs25 | ||
| 180 | fmov (a0+),fs26 | ||
| 181 | fmov (a0+),fs27 | ||
| 182 | fmov (a0+),fs28 | ||
| 183 | fmov (a0+),fs29 | ||
| 184 | fmov (a0+),fs30 | ||
| 185 | fmov (a0+),fs31 | ||
| 186 | mov (a0),d0 | ||
| 187 | fmov d0,fpcr | ||
| 188 | #ifdef CONFIG_MN10300_PROC_MN103E010 | ||
| 189 | nop | 198 | nop | 
| 199 | |||
| 200 | mov sp,a1 | ||
| 201 | mov (a1),d1 /* get epsw of user context */ | ||
| 202 | and ~(THREAD_SIZE-1),a1 /* a1: (thread_info *ti) */ | ||
| 203 | mov (TI_task,a1),a2 /* a2: (task_struct *tsk) */ | ||
| 204 | btst EPSW_nSL,d1 | ||
| 205 | beq fpu_used_in_kernel | ||
| 206 | |||
| 207 | or EPSW_FE,d1 | ||
| 208 | mov d1,(sp) | ||
| 209 | mov (TASK_THREAD+THREAD_FPU_FLAGS,a2),d1 | ||
| 210 | #ifndef CONFIG_LAZY_SAVE_FPU | ||
| 211 | or __THREAD_HAS_FPU,d1 | ||
| 212 | mov d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2) | ||
| 213 | #else /* !CONFIG_LAZY_SAVE_FPU */ | ||
| 214 | mov (fpu_state_owner),a0 | ||
| 215 | cmp 0,a0 | ||
| 216 | beq fpu_regs_save_end | ||
| 217 | |||
| 218 | mov (TASK_THREAD+THREAD_UREGS,a0),a1 | ||
| 219 | add TASK_THREAD+THREAD_FPU_STATE,a0 | ||
| 220 | FPU_SAVE_ALL a0,d0 | ||
| 221 | |||
| 222 | mov (REG_EPSW,a1),d0 | ||
| 223 | and ~EPSW_FE,d0 | ||
| 224 | mov d0,(REG_EPSW,a1) | ||
| 225 | |||
| 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 | ||
| 190 | nop | 244 | nop | 
| 191 | nop | 245 | nop | 
| 192 | #endif | ||
| 193 | 246 | ||
| 194 | mov d1,epsw | 247 | add -4,sp | 
| 195 | ret [],0 | 248 | SAVE_ALL | 
| 249 | mov -1,d0 | ||
| 250 | mov d0,(REG_ORIG_D0,fp) | ||
| 251 | |||
| 252 | and ~EPSW_NMID,epsw | ||
| 253 | |||
| 254 | mov fp,d0 | ||
| 255 | call fpu_disabled_in_kernel[],0 | ||
| 256 | jmp ret_from_exception | ||
| 196 | 257 | ||
| 197 | .size fpu_restore,.-fpu_restore | 258 | .size fpu_disabled,.-fpu_disabled | 
| diff --git a/arch/mn10300/kernel/fpu-nofpu-low.S b/arch/mn10300/kernel/fpu-nofpu-low.S new file mode 100644 index 000000000000..7ea087a549f4 --- /dev/null +++ b/arch/mn10300/kernel/fpu-nofpu-low.S | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* MN10300 Low level FPU management operations | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/linkage.h> | ||
| 12 | #include <asm/cpu-regs.h> | ||
| 13 | #include <asm/smp.h> | ||
| 14 | #include <asm/thread_info.h> | ||
| 15 | #include <asm/asm-offsets.h> | ||
| 16 | #include <asm/frame.inc> | ||
| 17 | |||
| 18 | ############################################################################### | ||
| 19 | # | ||
| 20 | # void fpu_disabled(void) | ||
| 21 | # - handle an exception due to the FPU being disabled | ||
| 22 | # when CONFIG_FPU is disabled | ||
| 23 | # | ||
| 24 | ############################################################################### | ||
| 25 | .type fpu_disabled,@function | ||
| 26 | .globl fpu_disabled | ||
| 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 | ||
| diff --git a/arch/mn10300/kernel/fpu-nofpu.c b/arch/mn10300/kernel/fpu-nofpu.c new file mode 100644 index 000000000000..31c765b92c5d --- /dev/null +++ b/arch/mn10300/kernel/fpu-nofpu.c | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* MN10300 FPU management | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <asm/fpu.h> | ||
| 12 | |||
| 13 | /* | ||
| 14 | * handle an FPU operational exception | ||
| 15 | * - there's a possibility that if the FPU is asynchronous, the signal might | ||
| 16 | * be meant for a process other than the current one | ||
| 17 | */ | ||
| 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 | } | ||
| diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c index e705f25ad5ff..5f9c3fa19a85 100644 --- a/arch/mn10300/kernel/fpu.c +++ b/arch/mn10300/kernel/fpu.c | |||
| @@ -12,56 +12,19 @@ | |||
| 12 | #include <asm/fpu.h> | 12 | #include <asm/fpu.h> | 
| 13 | #include <asm/elf.h> | 13 | #include <asm/elf.h> | 
| 14 | #include <asm/exceptions.h> | 14 | #include <asm/exceptions.h> | 
| 15 | #include <asm/system.h> | ||
| 15 | 16 | ||
| 17 | #ifdef CONFIG_LAZY_SAVE_FPU | ||
| 16 | struct task_struct *fpu_state_owner; | 18 | struct task_struct *fpu_state_owner; | 
| 19 | #endif | ||
| 17 | 20 | ||
| 18 | /* | 21 | /* | 
| 19 | * handle an exception due to the FPU being disabled | 22 | * error functions in FPU disabled exception | 
| 20 | */ | 23 | */ | 
| 21 | asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code) | 24 | asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs) | 
| 22 | { | 25 | { | 
| 23 | struct task_struct *tsk = current; | 26 | die_if_no_fixup("An FPU Disabled exception happened in kernel space\n", | 
| 24 | 27 | regs, EXCEP_FPU_DISABLED); | |
| 25 | if (!user_mode(regs)) | ||
| 26 | die_if_no_fixup("An FPU Disabled exception happened in" | ||
| 27 | " kernel space\n", | ||
| 28 | regs, code); | ||
| 29 | |||
| 30 | #ifdef CONFIG_FPU | ||
| 31 | preempt_disable(); | ||
| 32 | |||
| 33 | /* transfer the last process's FPU state to memory */ | ||
| 34 | if (fpu_state_owner) { | ||
| 35 | fpu_save(&fpu_state_owner->thread.fpu_state); | ||
| 36 | fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; | ||
| 37 | } | ||
| 38 | |||
| 39 | /* the current process now owns the FPU state */ | ||
| 40 | fpu_state_owner = tsk; | ||
| 41 | regs->epsw |= EPSW_FE; | ||
| 42 | |||
| 43 | /* load the FPU with the current process's FPU state or invent a new | ||
| 44 | * clean one if the process doesn't have one */ | ||
| 45 | if (is_using_fpu(tsk)) { | ||
| 46 | fpu_restore(&tsk->thread.fpu_state); | ||
| 47 | } else { | ||
| 48 | fpu_init_state(); | ||
| 49 | set_using_fpu(tsk); | ||
| 50 | } | ||
| 51 | |||
| 52 | preempt_enable(); | ||
| 53 | #else | ||
| 54 | { | ||
| 55 | siginfo_t info; | ||
| 56 | |||
| 57 | info.si_signo = SIGFPE; | ||
| 58 | info.si_errno = 0; | ||
| 59 | info.si_addr = (void *) tsk->thread.uregs->pc; | ||
| 60 | info.si_code = FPE_FLTINV; | ||
| 61 | |||
| 62 | force_sig_info(SIGFPE, &info, tsk); | ||
| 63 | } | ||
| 64 | #endif /* CONFIG_FPU */ | ||
| 65 | } | 28 | } | 
| 66 | 29 | ||
| 67 | /* | 30 | /* | 
| @@ -71,15 +34,16 @@ asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code) | |||
| 71 | */ | 34 | */ | 
| 72 | asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) | 35 | asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) | 
| 73 | { | 36 | { | 
| 74 | struct task_struct *tsk = fpu_state_owner; | 37 | struct task_struct *tsk = current; | 
| 75 | siginfo_t info; | 38 | siginfo_t info; | 
| 39 | u32 fpcr; | ||
| 76 | 40 | ||
| 77 | if (!user_mode(regs)) | 41 | if (!user_mode(regs)) | 
| 78 | die_if_no_fixup("An FPU Operation exception happened in" | 42 | die_if_no_fixup("An FPU Operation exception happened in" | 
| 79 | " kernel space\n", | 43 | " kernel space\n", | 
| 80 | regs, code); | 44 | regs, code); | 
| 81 | 45 | ||
| 82 | if (!tsk) | 46 | if (!is_using_fpu(tsk)) | 
| 83 | die_if_no_fixup("An FPU Operation exception happened," | 47 | die_if_no_fixup("An FPU Operation exception happened," | 
| 84 | " but the FPU is not in use", | 48 | " but the FPU is not in use", | 
| 85 | regs, code); | 49 | regs, code); | 
| @@ -89,48 +53,45 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) | |||
| 89 | info.si_addr = (void *) tsk->thread.uregs->pc; | 53 | info.si_addr = (void *) tsk->thread.uregs->pc; | 
| 90 | info.si_code = FPE_FLTINV; | 54 | info.si_code = FPE_FLTINV; | 
| 91 | 55 | ||
| 92 | #ifdef CONFIG_FPU | 56 | unlazy_fpu(tsk); | 
| 93 | { | ||
| 94 | u32 fpcr; | ||
| 95 | 57 | ||
| 96 | /* get FPCR (we need to enable the FPU whilst we do this) */ | 58 | fpcr = tsk->thread.fpu_state.fpcr; | 
| 97 | asm volatile(" or %1,epsw \n" | 59 | |
| 98 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 60 | if (fpcr & FPCR_EC_Z) | 
| 99 | " nop \n" | 61 | info.si_code = FPE_FLTDIV; | 
| 100 | " nop \n" | 62 | else if (fpcr & FPCR_EC_O) | 
| 101 | " nop \n" | 63 | info.si_code = FPE_FLTOVF; | 
| 102 | #endif | 64 | else if (fpcr & FPCR_EC_U) | 
| 103 | " fmov fpcr,%0 \n" | 65 | info.si_code = FPE_FLTUND; | 
| 104 | #ifdef CONFIG_MN10300_PROC_MN103E010 | 66 | else if (fpcr & FPCR_EC_I) | 
| 105 | " nop \n" | 67 | info.si_code = FPE_FLTRES; | 
| 106 | " nop \n" | ||
| 107 | " nop \n" | ||
| 108 | #endif | ||
| 109 | " and %2,epsw \n" | ||
| 110 | : "=&d"(fpcr) | ||
| 111 | : "i"(EPSW_FE), "i"(~EPSW_FE) | ||
| 112 | ); | ||
| 113 | |||
| 114 | if (fpcr & FPCR_EC_Z) | ||
| 115 | info.si_code = FPE_FLTDIV; | ||
| 116 | else if (fpcr & FPCR_EC_O) | ||
| 117 | info.si_code = FPE_FLTOVF; | ||
| 118 | else if (fpcr & FPCR_EC_U) | ||
| 119 | info.si_code = FPE_FLTUND; | ||
| 120 | else if (fpcr & FPCR_EC_I) | ||
| 121 | info.si_code = FPE_FLTRES; | ||
| 122 | } | ||
| 123 | #endif | ||
| 124 | 68 | ||
| 125 | force_sig_info(SIGFPE, &info, tsk); | 69 | force_sig_info(SIGFPE, &info, tsk); | 
| 126 | } | 70 | } | 
| 127 | 71 | ||
| 128 | /* | 72 | /* | 
| 73 | * handle an FPU invalid_op exception | ||
| 74 | * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c | ||
| 75 | */ | ||
| 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 | |||
| 90 | /* | ||
| 129 | * save the FPU state to a signal context | 91 | * save the FPU state to a signal context | 
| 130 | */ | 92 | */ | 
| 131 | int fpu_setup_sigcontext(struct fpucontext *fpucontext) | 93 | int fpu_setup_sigcontext(struct fpucontext *fpucontext) | 
| 132 | { | 94 | { | 
| 133 | #ifdef CONFIG_FPU | ||
| 134 | struct task_struct *tsk = current; | 95 | struct task_struct *tsk = current; | 
| 135 | 96 | ||
| 136 | if (!is_using_fpu(tsk)) | 97 | if (!is_using_fpu(tsk)) | 
| @@ -142,11 +103,19 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) | |||
| 142 | */ | 103 | */ | 
| 143 | preempt_disable(); | 104 | preempt_disable(); | 
| 144 | 105 | ||
| 106 | #ifndef CONFIG_LAZY_SAVE_FPU | ||
| 107 | if (tsk->thread.fpu_flags & THREAD_HAS_FPU) { | ||
| 108 | fpu_save(&tsk->thread.fpu_state); | ||
| 109 | tsk->thread.uregs->epsw &= ~EPSW_FE; | ||
| 110 | tsk->thread.fpu_flags &= ~THREAD_HAS_FPU; | ||
| 111 | } | ||
| 112 | #else /* !CONFIG_LAZY_SAVE_FPU */ | ||
| 145 | if (fpu_state_owner == tsk) { | 113 | if (fpu_state_owner == tsk) { | 
| 146 | fpu_save(&tsk->thread.fpu_state); | 114 | fpu_save(&tsk->thread.fpu_state); | 
| 147 | fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; | 115 | fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; | 
| 148 | fpu_state_owner = NULL; | 116 | fpu_state_owner = NULL; | 
| 149 | } | 117 | } | 
| 118 | #endif /* !CONFIG_LAZY_SAVE_FPU */ | ||
| 150 | 119 | ||
| 151 | preempt_enable(); | 120 | preempt_enable(); | 
| 152 | 121 | ||
| @@ -161,9 +130,6 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) | |||
| 161 | return -1; | 130 | return -1; | 
| 162 | 131 | ||
| 163 | return 1; | 132 | return 1; | 
| 164 | #else | ||
| 165 | return 0; | ||
| 166 | #endif | ||
| 167 | } | 133 | } | 
| 168 | 134 | ||
| 169 | /* | 135 | /* | 
| @@ -171,17 +137,23 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext) | |||
| 171 | */ | 137 | */ | 
| 172 | void fpu_kill_state(struct task_struct *tsk) | 138 | void fpu_kill_state(struct task_struct *tsk) | 
| 173 | { | 139 | { | 
| 174 | #ifdef CONFIG_FPU | ||
| 175 | /* disown anything left in the FPU */ | 140 | /* disown anything left in the FPU */ | 
| 176 | preempt_disable(); | 141 | preempt_disable(); | 
| 177 | 142 | ||
| 143 | #ifndef CONFIG_LAZY_SAVE_FPU | ||
| 144 | if (tsk->thread.fpu_flags & THREAD_HAS_FPU) { | ||
| 145 | tsk->thread.uregs->epsw &= ~EPSW_FE; | ||
| 146 | tsk->thread.fpu_flags &= ~THREAD_HAS_FPU; | ||
| 147 | } | ||
| 148 | #else /* !CONFIG_LAZY_SAVE_FPU */ | ||
| 178 | if (fpu_state_owner == tsk) { | 149 | if (fpu_state_owner == tsk) { | 
| 179 | fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; | 150 | fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; | 
| 180 | fpu_state_owner = NULL; | 151 | fpu_state_owner = NULL; | 
| 181 | } | 152 | } | 
| 153 | #endif /* !CONFIG_LAZY_SAVE_FPU */ | ||
| 182 | 154 | ||
| 183 | preempt_enable(); | 155 | preempt_enable(); | 
| 184 | #endif | 156 | |
| 185 | /* we no longer have a valid current FPU state */ | 157 | /* we no longer have a valid current FPU state */ | 
| 186 | clear_using_fpu(tsk); | 158 | clear_using_fpu(tsk); | 
| 187 | } | 159 | } | 
| @@ -195,8 +167,7 @@ int fpu_restore_sigcontext(struct fpucontext *fpucontext) | |||
| 195 | int ret; | 167 | int ret; | 
| 196 | 168 | ||
| 197 | /* load up the old FPU state */ | 169 | /* load up the old FPU state */ | 
| 198 | ret = copy_from_user(&tsk->thread.fpu_state, | 170 | ret = copy_from_user(&tsk->thread.fpu_state, fpucontext, | 
| 199 | fpucontext, | ||
| 200 | min(sizeof(struct fpu_state_struct), | 171 | min(sizeof(struct fpu_state_struct), | 
| 201 | sizeof(struct fpucontext))); | 172 | sizeof(struct fpucontext))); | 
| 202 | if (!ret) | 173 | if (!ret) | 
| diff --git a/arch/mn10300/kernel/gdb-io-serial-low.S b/arch/mn10300/kernel/gdb-io-serial-low.S index 4998b24f5d3a..b1d0152e96cb 100644 --- a/arch/mn10300/kernel/gdb-io-serial-low.S +++ b/arch/mn10300/kernel/gdb-io-serial-low.S | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> | 
| 19 | #include <asm/frame.inc> | 19 | #include <asm/frame.inc> | 
| 20 | #include <asm/intctl-regs.h> | 20 | #include <asm/intctl-regs.h> | 
| 21 | #include <asm/irqflags.h> | ||
| 21 | #include <unit/serial.h> | 22 | #include <unit/serial.h> | 
| 22 | 23 | ||
| 23 | .text | 24 | .text | 
| @@ -69,7 +70,7 @@ gdbstub_io_rx_overflow: | |||
| 69 | bra gdbstub_io_rx_done | 70 | bra gdbstub_io_rx_done | 
| 70 | 71 | ||
| 71 | gdbstub_io_rx_enter: | 72 | gdbstub_io_rx_enter: | 
| 72 | or EPSW_IE|EPSW_IM_1,epsw | 73 | LOCAL_CHANGE_INTR_MASK_LEVEL(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL+1)) | 
| 73 | add -4,sp | 74 | add -4,sp | 
| 74 | SAVE_ALL | 75 | SAVE_ALL | 
| 75 | 76 | ||
| @@ -80,7 +81,7 @@ gdbstub_io_rx_enter: | |||
| 80 | mov fp,d0 | 81 | mov fp,d0 | 
| 81 | call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep) | 82 | call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep) | 
| 82 | 83 | ||
| 83 | and ~EPSW_IE,epsw | 84 | LOCAL_CLI | 
| 84 | bclr 0x01,(gdbstub_busy) | 85 | bclr 0x01,(gdbstub_busy) | 
| 85 | 86 | ||
| 86 | .globl gdbstub_return | 87 | .globl gdbstub_return | 
| diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c index ae663dc717e9..0d5d63c91dc3 100644 --- a/arch/mn10300/kernel/gdb-io-serial.c +++ b/arch/mn10300/kernel/gdb-io-serial.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <asm/exceptions.h> | 23 | #include <asm/exceptions.h> | 
| 24 | #include <asm/serial-regs.h> | 24 | #include <asm/serial-regs.h> | 
| 25 | #include <unit/serial.h> | 25 | #include <unit/serial.h> | 
| 26 | #include <asm/smp.h> | ||
| 26 | 27 | ||
| 27 | /* | 28 | /* | 
| 28 | * initialise the GDB stub | 29 | * initialise the GDB stub | 
| @@ -45,22 +46,34 @@ void gdbstub_io_init(void) | |||
| 45 | XIRQxICR(GDBPORT_SERIAL_IRQ) = 0; | 46 | XIRQxICR(GDBPORT_SERIAL_IRQ) = 0; | 
| 46 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 47 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 
| 47 | 48 | ||
| 49 | #if CONFIG_GDBSTUB_IRQ_LEVEL == 0 | ||
| 48 | IVAR0 = EXCEP_IRQ_LEVEL0; | 50 | IVAR0 = EXCEP_IRQ_LEVEL0; | 
| 49 | set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler); | 51 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 1 | 
| 52 | IVAR1 = EXCEP_IRQ_LEVEL1; | ||
| 53 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 2 | ||
| 54 | IVAR2 = EXCEP_IRQ_LEVEL2; | ||
| 55 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 3 | ||
| 56 | IVAR3 = EXCEP_IRQ_LEVEL3; | ||
| 57 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 4 | ||
| 58 | IVAR4 = EXCEP_IRQ_LEVEL4; | ||
| 59 | #elif CONFIG_GDBSTUB_IRQ_LEVEL == 5 | ||
| 60 | IVAR5 = EXCEP_IRQ_LEVEL5; | ||
| 61 | #else | ||
| 62 | #error "Unknown irq level for gdbstub." | ||
| 63 | #endif | ||
| 64 | |||
| 65 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), | ||
| 66 | gdbstub_io_rx_handler); | ||
| 50 | 67 | ||
| 51 | XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST; | 68 | XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST; | 
| 52 | XIRQxICR(GDBPORT_SERIAL_IRQ) = GxICR_ENABLE | GxICR_LEVEL_0; | 69 | XIRQxICR(GDBPORT_SERIAL_IRQ) = | 
| 70 | GxICR_ENABLE | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL); | ||
| 53 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 71 | tmp = XIRQxICR(GDBPORT_SERIAL_IRQ); | 
| 54 | 72 | ||
| 55 | GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI; | 73 | GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI; | 
| 56 | 74 | ||
| 57 | /* permit level 0 IRQs to take place */ | 75 | /* permit level 0 IRQs to take place */ | 
| 58 | asm volatile( | 76 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); | 
| 59 | " and %0,epsw \n" | ||
| 60 | " or %1,epsw \n" | ||
| 61 | : | ||
| 62 | : "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1) | ||
| 63 | ); | ||
| 64 | } | 77 | } | 
| 65 | 78 | ||
| 66 | /* | 79 | /* | 
| @@ -87,6 +100,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
| 87 | { | 100 | { | 
| 88 | unsigned ix; | 101 | unsigned ix; | 
| 89 | u8 ch, st; | 102 | u8 ch, st; | 
| 103 | #if defined(CONFIG_MN10300_WD_TIMER) | ||
| 104 | int cpu; | ||
| 105 | #endif | ||
| 90 | 106 | ||
| 91 | *_ch = 0xff; | 107 | *_ch = 0xff; | 
| 92 | 108 | ||
| @@ -104,8 +120,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
| 104 | if (nonblock) | 120 | if (nonblock) | 
| 105 | return -EAGAIN; | 121 | return -EAGAIN; | 
| 106 | #ifdef CONFIG_MN10300_WD_TIMER | 122 | #ifdef CONFIG_MN10300_WD_TIMER | 
| 107 | watchdog_alert_counter = 0; | 123 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 
| 108 | #endif /* CONFIG_MN10300_WD_TIMER */ | 124 | watchdog_alert_counter[cpu] = 0; | 
| 125 | #endif | ||
| 109 | goto try_again; | 126 | goto try_again; | 
| 110 | } | 127 | } | 
| 111 | 128 | ||
| diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c index a560bbc3137d..97dfda23342c 100644 --- a/arch/mn10300/kernel/gdb-io-ttysm.c +++ b/arch/mn10300/kernel/gdb-io-ttysm.c | |||
| @@ -58,9 +58,12 @@ void __init gdbstub_io_init(void) | |||
| 58 | gdbstub_io_set_baud(115200); | 58 | gdbstub_io_set_baud(115200); | 
| 59 | 59 | ||
| 60 | /* we want to get serial receive interrupts */ | 60 | /* we want to get serial receive interrupts */ | 
| 61 | set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0); | 61 | set_intr_level(gdbstub_port->rx_irq, | 
| 62 | set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0); | 62 | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); | 
| 63 | set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler); | 63 | set_intr_level(gdbstub_port->tx_irq, | 
| 64 | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); | ||
| 65 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), | ||
| 66 | gdbstub_io_rx_handler); | ||
| 64 | 67 | ||
| 65 | *gdbstub_port->rx_icr |= GxICR_ENABLE; | 68 | *gdbstub_port->rx_icr |= GxICR_ENABLE; | 
| 66 | tmp = *gdbstub_port->rx_icr; | 69 | tmp = *gdbstub_port->rx_icr; | 
| @@ -84,12 +87,7 @@ void __init gdbstub_io_init(void) | |||
| 84 | tmp = *gdbstub_port->_control; | 87 | tmp = *gdbstub_port->_control; | 
| 85 | 88 | ||
| 86 | /* permit level 0 IRQs only */ | 89 | /* permit level 0 IRQs only */ | 
| 87 | asm volatile( | 90 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); | 
| 88 | " and %0,epsw \n" | ||
| 89 | " or %1,epsw \n" | ||
| 90 | : | ||
| 91 | : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1) | ||
| 92 | ); | ||
| 93 | } | 91 | } | 
| 94 | 92 | ||
| 95 | /* | 93 | /* | 
| @@ -184,6 +182,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) | |||
| 184 | { | 182 | { | 
| 185 | unsigned ix; | 183 | unsigned ix; | 
| 186 | u8 ch, st; | 184 | u8 ch, st; | 
| 185 | #if defined(CONFIG_MN10300_WD_TIMER) | ||
| 186 | int cpu; | ||
| 187 | #endif | ||
| 187 | 188 | ||
| 188 | *_ch = 0xff; | 189 | *_ch = 0xff; | 
| 189 | 190 | ||
| @@ -201,8 +202,9 @@ try_again: | |||
| 201 | if (nonblock) | 202 | if (nonblock) | 
| 202 | return -EAGAIN; | 203 | return -EAGAIN; | 
| 203 | #ifdef CONFIG_MN10300_WD_TIMER | 204 | #ifdef CONFIG_MN10300_WD_TIMER | 
| 204 | watchdog_alert_counter = 0; | 205 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 
| 205 | #endif /* CONFIG_MN10300_WD_TIMER */ | 206 | watchdog_alert_counter[cpu] = 0; | 
| 207 | #endif | ||
| 206 | goto try_again; | 208 | goto try_again; | 
| 207 | } | 209 | } | 
| 208 | 210 | ||
| diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index 41b11706c8ed..a5fc3f05309b 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c | |||
| @@ -440,15 +440,11 @@ static const unsigned char gdbstub_insn_sizes[256] = | |||
| 440 | 440 | ||
| 441 | static int __gdbstub_mark_bp(u8 *addr, int ix) | 441 | static int __gdbstub_mark_bp(u8 *addr, int ix) | 
| 442 | { | 442 | { | 
| 443 | if (addr < (u8 *) 0x70000000UL) | 443 | /* vmalloc area */ | 
| 444 | return 0; | 444 | if (((u8 *) VMALLOC_START <= addr) && (addr < (u8 *) VMALLOC_END)) | 
| 445 | /* 70000000-7fffffff: vmalloc area */ | ||
| 446 | if (addr < (u8 *) 0x80000000UL) | ||
| 447 | goto okay; | 445 | goto okay; | 
| 448 | if (addr < (u8 *) 0x8c000000UL) | 446 | /* SRAM, SDRAM */ | 
| 449 | return 0; | 447 | if (((u8 *) 0x80000000UL <= addr) && (addr < (u8 *) 0xa0000000UL)) | 
| 450 | /* 8c000000-93ffffff: SRAM, SDRAM */ | ||
| 451 | if (addr < (u8 *) 0x94000000UL) | ||
| 452 | goto okay; | 448 | goto okay; | 
| 453 | return 0; | 449 | return 0; | 
| 454 | 450 | ||
| @@ -1197,9 +1193,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) | |||
| 1197 | mn10300_set_gdbleds(1); | 1193 | mn10300_set_gdbleds(1); | 
| 1198 | 1194 | ||
| 1199 | asm volatile("mov mdr,%0" : "=d"(mdr)); | 1195 | asm volatile("mov mdr,%0" : "=d"(mdr)); | 
| 1200 | asm volatile("mov epsw,%0" : "=d"(epsw)); | 1196 | local_save_flags(epsw); | 
| 1201 | asm volatile("mov %0,epsw" | 1197 | local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); | 
| 1202 | :: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1)); | ||
| 1203 | 1198 | ||
| 1204 | gdbstub_store_fpu(); | 1199 | gdbstub_store_fpu(); | 
| 1205 | 1200 | ||
| diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S index 14f27f3bfaf4..73e00fc78072 100644 --- a/arch/mn10300/kernel/head.S +++ b/arch/mn10300/kernel/head.S | |||
| @@ -19,6 +19,12 @@ | |||
| 19 | #include <asm/frame.inc> | 19 | #include <asm/frame.inc> | 
| 20 | #include <asm/param.h> | 20 | #include <asm/param.h> | 
| 21 | #include <unit/serial.h> | 21 | #include <unit/serial.h> | 
| 22 | #ifdef CONFIG_SMP | ||
| 23 | #include <asm/smp.h> | ||
| 24 | #include <asm/intctl-regs.h> | ||
| 25 | #include <asm/cpu-regs.h> | ||
| 26 | #include <proc/smp-regs.h> | ||
| 27 | #endif /* CONFIG_SMP */ | ||
| 22 | 28 | ||
| 23 | __HEAD | 29 | __HEAD | 
| 24 | 30 | ||
| @@ -30,17 +36,51 @@ | |||
| 30 | .globl _start | 36 | .globl _start | 
| 31 | .type _start,@function | 37 | .type _start,@function | 
| 32 | _start: | 38 | _start: | 
| 39 | #ifdef CONFIG_SMP | ||
| 40 | # | ||
| 41 | # If this is a secondary CPU (AP), then deal with that elsewhere | ||
| 42 | # | ||
| 43 | mov (CPUID),d3 | ||
| 44 | and CPUID_MASK,d3 | ||
| 45 | bne startup_secondary | ||
| 46 | |||
| 47 | # | ||
| 48 | # We're dealing with the primary CPU (BP) here, then. | ||
| 49 | # Keep BP's D0,D1,D2 register for boot check. | ||
| 50 | # | ||
| 51 | |||
| 52 | # Set up the Boot IPI for each secondary CPU | ||
| 53 | mov 0x1,a0 | ||
| 54 | loop_set_secondary_icr: | ||
| 55 | mov a0,a1 | ||
| 56 | asl CROSS_ICR_CPU_SHIFT,a1 | ||
| 57 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a1 | ||
| 58 | movhu (a1),d3 | ||
| 59 | or GxICR_ENABLE|GxICR_LEVEL_0,d3 | ||
| 60 | movhu d3,(a1) | ||
| 61 | movhu (a1),d3 # flush | ||
| 62 | inc a0 | ||
| 63 | cmp NR_CPUS,a0 | ||
| 64 | bne loop_set_secondary_icr | ||
| 65 | #endif /* CONFIG_SMP */ | ||
| 66 | |||
| 33 | # save commandline pointer | 67 | # save commandline pointer | 
| 34 | mov d0,a3 | 68 | mov d0,a3 | 
| 35 | 69 | ||
| 36 | # preload the PGD pointer register | 70 | # preload the PGD pointer register | 
| 37 | mov swapper_pg_dir,d0 | 71 | mov swapper_pg_dir,d0 | 
| 38 | mov d0,(PTBR) | 72 | mov d0,(PTBR) | 
| 73 | clr d0 | ||
| 74 | movbu d0,(PIDR) | ||
| 39 | 75 | ||
| 40 | # turn on the TLBs | 76 | # turn on the TLBs | 
| 41 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | 77 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | 
| 42 | mov d0,(MMUCTR) | 78 | mov d0,(MMUCTR) | 
| 79 | #ifdef CONFIG_AM34_2 | ||
| 80 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | ||
| 81 | #else | ||
| 43 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | 82 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | 
| 83 | #endif | ||
| 44 | mov d0,(MMUCTR) | 84 | mov d0,(MMUCTR) | 
| 45 | 85 | ||
| 46 | # turn on AM33v2 exception handling mode and set the trap table base | 86 | # turn on AM33v2 exception handling mode and set the trap table base | 
| @@ -51,6 +91,11 @@ _start: | |||
| 51 | mov d0,(TBR) | 91 | mov d0,(TBR) | 
| 52 | 92 | ||
| 53 | # invalidate and enable both of the caches | 93 | # invalidate and enable both of the caches | 
| 94 | #ifdef CONFIG_SMP | ||
| 95 | mov ECHCTR,a0 | ||
| 96 | clr d0 | ||
| 97 | mov d0,(a0) | ||
| 98 | #endif | ||
| 54 | mov CHCTR,a0 | 99 | mov CHCTR,a0 | 
| 55 | clr d0 | 100 | clr d0 | 
| 56 | movhu d0,(a0) # turn off first | 101 | movhu d0,(a0) # turn off first | 
| @@ -61,18 +106,18 @@ _start: | |||
| 61 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy | 106 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy | 
| 62 | lne | 107 | lne | 
| 63 | 108 | ||
| 64 | #ifndef CONFIG_MN10300_CACHE_DISABLED | 109 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 
| 65 | #ifdef CONFIG_MN10300_CACHE_WBACK | 110 | #ifdef CONFIG_MN10300_CACHE_WBACK | 
| 66 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | 111 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | 
| 67 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | 112 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | 
| 68 | #else | 113 | #else | 
| 69 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | 114 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | 
| 70 | #endif /* CACHE_DISABLED */ | 115 | #endif /* NOWRALLOC */ | 
| 71 | #else | 116 | #else | 
| 72 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | 117 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | 
| 73 | #endif /* WBACK */ | 118 | #endif /* WBACK */ | 
| 74 | movhu d0,(a0) # enable | 119 | movhu d0,(a0) # enable | 
| 75 | #endif /* NOWRALLOC */ | 120 | #endif /* ENABLED */ | 
| 76 | 121 | ||
| 77 | # turn on RTS on the debug serial port if applicable | 122 | # turn on RTS on the debug serial port if applicable | 
| 78 | #ifdef CONFIG_MN10300_UNIT_ASB2305 | 123 | #ifdef CONFIG_MN10300_UNIT_ASB2305 | 
| @@ -206,6 +251,44 @@ __no_parameters: | |||
| 206 | call processor_init[],0 | 251 | call processor_init[],0 | 
| 207 | call unit_init[],0 | 252 | call unit_init[],0 | 
| 208 | 253 | ||
| 254 | #ifdef CONFIG_SMP | ||
| 255 | # mark the primary CPU in cpu_boot_map | ||
| 256 | mov cpu_boot_map,a0 | ||
| 257 | mov 0x1,d0 | ||
| 258 | mov d0,(a0) | ||
| 259 | |||
| 260 | # signal each secondary CPU to begin booting | ||
| 261 | mov 0x1,d2 # CPU ID | ||
| 262 | |||
| 263 | loop_request_boot_secondary: | ||
| 264 | mov d2,a0 | ||
| 265 | # send SMP_BOOT_IPI to secondary CPU | ||
| 266 | asl CROSS_ICR_CPU_SHIFT,a0 | ||
| 267 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a0 | ||
| 268 | movhu (a0),d0 | ||
| 269 | or GxICR_REQUEST|GxICR_DETECT,d0 | ||
| 270 | movhu d0,(a0) | ||
| 271 | movhu (a0),d0 # flush | ||
| 272 | |||
| 273 | # wait up to 100ms for AP's IPI to be received | ||
| 274 | clr d3 | ||
| 275 | wait_on_secondary_boot: | ||
| 276 | mov DELAY_TIME_BOOT_IPI,d0 | ||
| 277 | call __delay[],0 | ||
| 278 | inc d3 | ||
| 279 | mov cpu_boot_map,a0 | ||
| 280 | mov (a0),d0 | ||
| 281 | lsr d2,d0 | ||
| 282 | btst 0x1,d0 | ||
| 283 | bne 1f | ||
| 284 | cmp TIME_OUT_COUNT_BOOT_IPI,d3 | ||
| 285 | bne wait_on_secondary_boot | ||
| 286 | 1: | ||
| 287 | inc d2 | ||
| 288 | cmp NR_CPUS,d2 | ||
| 289 | bne loop_request_boot_secondary | ||
| 290 | #endif /* CONFIG_SMP */ | ||
| 291 | |||
| 209 | #ifdef CONFIG_GDBSTUB | 292 | #ifdef CONFIG_GDBSTUB | 
| 210 | call gdbstub_init[],0 | 293 | call gdbstub_init[],0 | 
| 211 | 294 | ||
| @@ -217,7 +300,118 @@ __gdbstub_pause: | |||
| 217 | #endif | 300 | #endif | 
| 218 | 301 | ||
| 219 | jmp start_kernel | 302 | jmp start_kernel | 
| 220 | .size _start, _start-. | 303 | .size _start,.-_start | 
| 304 | |||
| 305 | ############################################################################### | ||
| 306 | # | ||
| 307 | # Secondary CPU boot point | ||
| 308 | # | ||
| 309 | ############################################################################### | ||
| 310 | #ifdef CONFIG_SMP | ||
| 311 | startup_secondary: | ||
| 312 | # preload the PGD pointer register | ||
| 313 | mov swapper_pg_dir,d0 | ||
| 314 | mov d0,(PTBR) | ||
| 315 | clr d0 | ||
| 316 | movbu d0,(PIDR) | ||
| 317 | |||
| 318 | # turn on the TLBs | ||
| 319 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | ||
| 320 | mov d0,(MMUCTR) | ||
| 321 | #ifdef CONFIG_AM34_2 | ||
| 322 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | ||
| 323 | #else | ||
| 324 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | ||
| 325 | #endif | ||
| 326 | mov d0,(MMUCTR) | ||
| 327 | |||
| 328 | # turn on AM33v2 exception handling mode and set the trap table base | ||
| 329 | movhu (CPUP),d0 | ||
| 330 | or CPUP_EXM_AM33V2,d0 | ||
| 331 | movhu d0,(CPUP) | ||
| 332 | |||
| 333 | # set the interrupt vector table | ||
| 334 | mov CONFIG_INTERRUPT_VECTOR_BASE,d0 | ||
| 335 | mov d0,(TBR) | ||
| 336 | |||
| 337 | # invalidate and enable both of the caches | ||
| 338 | mov ECHCTR,a0 | ||
| 339 | clr d0 | ||
| 340 | mov d0,(a0) | ||
| 341 | mov CHCTR,a0 | ||
| 342 | clr d0 | ||
| 343 | movhu d0,(a0) # turn off first | ||
| 344 | mov CHCTR_ICINV|CHCTR_DCINV,d0 | ||
| 345 | movhu d0,(a0) | ||
| 346 | setlb | ||
| 347 | mov (a0),d0 | ||
| 348 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | ||
| 349 | lne | ||
| 350 | |||
| 351 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
| 352 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
| 353 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | ||
| 354 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | ||
| 355 | #else | ||
| 356 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | ||
| 357 | #endif /* !NOWRALLOC */ | ||
| 358 | #else | ||
| 359 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | ||
| 360 | #endif /* WBACK */ | ||
| 361 | movhu d0,(a0) # enable | ||
| 362 | #endif /* ENABLED */ | ||
| 363 | |||
| 364 | # Clear the boot IPI interrupt for this CPU | ||
| 365 | movhu (GxICR(SMP_BOOT_IRQ)),d0 | ||
| 366 | and ~GxICR_REQUEST,d0 | ||
| 367 | movhu d0,(GxICR(SMP_BOOT_IRQ)) | ||
| 368 | movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush | ||
| 369 | |||
| 370 | /* get stack */ | ||
| 371 | mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0 | ||
| 372 | mov (CPUID),d0 | ||
| 373 | and CPUID_MASK,d0 | ||
| 374 | mulu CONFIG_BOOT_STACK_SIZE,d0 | ||
| 375 | sub d0,a0 | ||
| 376 | mov a0,sp | ||
| 377 | |||
| 378 | # init interrupt for AP | ||
| 379 | call smp_prepare_cpu_init[],0 | ||
| 380 | |||
| 381 | # mark this secondary CPU in cpu_boot_map | ||
| 382 | mov (CPUID),d0 | ||
| 383 | mov 0x1,d1 | ||
| 384 | asl d0,d1 | ||
| 385 | mov cpu_boot_map,a0 | ||
| 386 | bset d1,(a0) | ||
| 387 | |||
| 388 | or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts | ||
| 389 | nop | ||
| 390 | nop | ||
| 391 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
| 392 | # flush the local cache if it's in writeback mode | ||
| 393 | call mn10300_local_dcache_flush_inv[],0 | ||
| 394 | setlb | ||
| 395 | mov (CHCTR),d0 | ||
| 396 | btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | ||
| 397 | lne | ||
| 398 | #endif | ||
| 399 | |||
| 400 | # now sleep waiting for further instructions | ||
| 401 | secondary_sleep: | ||
| 402 | mov CPUM_SLEEP,d0 | ||
| 403 | movhu d0,(CPUM) | ||
| 404 | nop | ||
| 405 | nop | ||
| 406 | bra secondary_sleep | ||
| 407 | .size startup_secondary,.-startup_secondary | ||
| 408 | #endif /* CONFIG_SMP */ | ||
| 409 | |||
| 410 | ############################################################################### | ||
| 411 | # | ||
| 412 | # | ||
| 413 | # | ||
| 414 | ############################################################################### | ||
| 221 | ENTRY(__head_end) | 415 | ENTRY(__head_end) | 
| 222 | 416 | ||
| 223 | /* | 417 | /* | 
| diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index eee2eee86267..6a064ab5af07 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h | |||
| @@ -9,6 +9,9 @@ | |||
| 9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. | 
| 10 | */ | 10 | */ | 
| 11 | 11 | ||
| 12 | struct clocksource; | ||
| 13 | struct clock_event_device; | ||
| 14 | |||
| 12 | /* | 15 | /* | 
| 13 | * kthread.S | 16 | * kthread.S | 
| 14 | */ | 17 | */ | 
| @@ -18,3 +21,25 @@ extern int kernel_thread_helper(int); | |||
| 18 | * entry.S | 21 | * entry.S | 
| 19 | */ | 22 | */ | 
| 20 | extern void ret_from_fork(struct task_struct *) __attribute__((noreturn)); | 23 | 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 | ||
| diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index e2d5ed891f37..c2e44597c22b 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
| @@ -12,11 +12,26 @@ | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> | 
| 13 | #include <linux/kernel_stat.h> | 13 | #include <linux/kernel_stat.h> | 
| 14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> | 
| 15 | #include <linux/cpumask.h> | ||
| 15 | #include <asm/setup.h> | 16 | #include <asm/setup.h> | 
| 17 | #include <asm/serial-regs.h> | ||
| 16 | 18 | ||
| 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 | }; | ||
| 18 | EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); | 22 | EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); | 
| 19 | 23 | ||
| 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 | |||
| 20 | atomic_t irq_err_count; | 35 | atomic_t irq_err_count; | 
| 21 | 36 | ||
| 22 | /* | 37 | /* | 
| @@ -24,30 +39,67 @@ atomic_t irq_err_count; | |||
| 24 | */ | 39 | */ | 
| 25 | static void mn10300_cpupic_ack(unsigned int irq) | 40 | static void mn10300_cpupic_ack(unsigned int irq) | 
| 26 | { | 41 | { | 
| 42 | unsigned long flags; | ||
| 27 | u16 tmp; | 43 | u16 tmp; | 
| 28 | *(volatile u8 *) &GxICR(irq) = GxICR_DETECT; | 44 | |
| 45 | flags = arch_local_cli_save(); | ||
| 46 | GxICR_u8(irq) = GxICR_DETECT; | ||
| 29 | tmp = GxICR(irq); | 47 | tmp = GxICR(irq); | 
| 48 | arch_local_irq_restore(flags); | ||
| 30 | } | 49 | } | 
| 31 | 50 | ||
| 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) | ||
| 33 | { | 53 | { | 
| 34 | u16 tmp = GxICR(irq); | 54 | unsigned long flags; | 
| 35 | GxICR(irq) = (tmp & GxICR_LEVEL); | 55 | u16 tmp; | 
| 56 | |||
| 57 | flags = arch_local_cli_save(); | ||
| 58 | tmp = GxICR(irq); | ||
| 59 | GxICR(irq) = (tmp & mask) | set; | ||
| 36 | tmp = GxICR(irq); | 60 | tmp = GxICR(irq); | 
| 61 | arch_local_irq_restore(flags); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void mn10300_cpupic_mask(unsigned int irq) | ||
| 65 | { | ||
| 66 | __mask_and_set_icr(irq, GxICR_LEVEL, 0); | ||
| 37 | } | 67 | } | 
| 38 | 68 | ||
| 39 | static void mn10300_cpupic_mask_ack(unsigned int irq) | 69 | static void mn10300_cpupic_mask_ack(unsigned int irq) | 
| 40 | { | 70 | { | 
| 41 | u16 tmp = GxICR(irq); | 71 | #ifdef CONFIG_SMP | 
| 42 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | 72 | unsigned long flags; | 
| 43 | tmp = GxICR(irq); | 73 | u16 tmp; | 
| 74 | |||
| 75 | flags = arch_local_cli_save(); | ||
| 76 | |||
| 77 | if (!test_and_clear_bit(irq, irq_affinity_request)) { | ||
| 78 | tmp = GxICR(irq); | ||
| 79 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | ||
| 80 | tmp = GxICR(irq); | ||
| 81 | } else { | ||
| 82 | u16 tmp2; | ||
| 83 | tmp = GxICR(irq); | ||
| 84 | GxICR(irq) = (tmp & GxICR_LEVEL); | ||
| 85 | tmp2 = GxICR(irq); | ||
| 86 | |||
| 87 | irq_affinity_online[irq] = | ||
| 88 | any_online_cpu(*irq_desc[irq].affinity); | ||
| 89 | CROSS_GxICR(irq, irq_affinity_online[irq]) = | ||
| 90 | (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; | ||
| 91 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); | ||
| 92 | } | ||
| 93 | |||
| 94 | arch_local_irq_restore(flags); | ||
| 95 | #else /* CONFIG_SMP */ | ||
| 96 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_DETECT); | ||
| 97 | #endif /* CONFIG_SMP */ | ||
| 44 | } | 98 | } | 
| 45 | 99 | ||
| 46 | static void mn10300_cpupic_unmask(unsigned int irq) | 100 | static void mn10300_cpupic_unmask(unsigned int irq) | 
| 47 | { | 101 | { | 
| 48 | u16 tmp = GxICR(irq); | 102 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE); | 
| 49 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; | ||
| 50 | tmp = GxICR(irq); | ||
| 51 | } | 103 | } | 
| 52 | 104 | ||
| 53 | static void mn10300_cpupic_unmask_clear(unsigned int irq) | 105 | static void mn10300_cpupic_unmask_clear(unsigned int irq) | 
| @@ -56,11 +108,89 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) | |||
| 56 | * device has ceased to assert its interrupt line and the interrupt | 108 | * device has ceased to assert its interrupt line and the interrupt | 
| 57 | * channel has been disabled in the PIC, so for level-triggered | 109 | * channel has been disabled in the PIC, so for level-triggered | 
| 58 | * interrupts we need to clear the request bit when we re-enable */ | 110 | * interrupts we need to clear the request bit when we re-enable */ | 
| 59 | u16 tmp = GxICR(irq); | 111 | #ifdef CONFIG_SMP | 
| 60 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | 112 | unsigned long flags; | 
| 61 | tmp = GxICR(irq); | 113 | u16 tmp; | 
| 114 | |||
| 115 | flags = arch_local_cli_save(); | ||
| 116 | |||
| 117 | if (!test_and_clear_bit(irq, irq_affinity_request)) { | ||
| 118 | tmp = GxICR(irq); | ||
| 119 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | ||
| 120 | tmp = GxICR(irq); | ||
| 121 | } else { | ||
| 122 | tmp = GxICR(irq); | ||
| 123 | |||
| 124 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | ||
| 125 | CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | ||
| 126 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); | ||
| 127 | } | ||
| 128 | |||
| 129 | arch_local_irq_restore(flags); | ||
| 130 | #else /* CONFIG_SMP */ | ||
| 131 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE | GxICR_DETECT); | ||
| 132 | #endif /* CONFIG_SMP */ | ||
| 62 | } | 133 | } | 
| 63 | 134 | ||
| 135 | #ifdef CONFIG_SMP | ||
| 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 | |||
| 64 | /* | 194 | /* | 
| 65 | * MN10300 PIC level-triggered IRQ handling. | 195 | * MN10300 PIC level-triggered IRQ handling. | 
| 66 | * | 196 | * | 
| @@ -79,6 +209,9 @@ static struct irq_chip mn10300_cpu_pic_level = { | |||
| 79 | .mask = mn10300_cpupic_mask, | 209 | .mask = mn10300_cpupic_mask, | 
| 80 | .mask_ack = mn10300_cpupic_mask, | 210 | .mask_ack = mn10300_cpupic_mask, | 
| 81 | .unmask = mn10300_cpupic_unmask_clear, | 211 | .unmask = mn10300_cpupic_unmask_clear, | 
| 212 | #ifdef CONFIG_SMP | ||
| 213 | .set_affinity = mn10300_cpupic_setaffinity, | ||
| 214 | #endif | ||
| 82 | }; | 215 | }; | 
| 83 | 216 | ||
| 84 | /* | 217 | /* | 
| @@ -94,6 +227,9 @@ static struct irq_chip mn10300_cpu_pic_edge = { | |||
| 94 | .mask = mn10300_cpupic_mask, | 227 | .mask = mn10300_cpupic_mask, | 
| 95 | .mask_ack = mn10300_cpupic_mask_ack, | 228 | .mask_ack = mn10300_cpupic_mask_ack, | 
| 96 | .unmask = mn10300_cpupic_unmask, | 229 | .unmask = mn10300_cpupic_unmask, | 
| 230 | #ifdef CONFIG_SMP | ||
| 231 | .set_affinity = mn10300_cpupic_setaffinity, | ||
| 232 | #endif | ||
| 97 | }; | 233 | }; | 
| 98 | 234 | ||
| 99 | /* | 235 | /* | 
| @@ -111,14 +247,34 @@ void ack_bad_irq(int irq) | |||
| 111 | */ | 247 | */ | 
| 112 | void set_intr_level(int irq, u16 level) | 248 | void set_intr_level(int irq, u16 level) | 
| 113 | { | 249 | { | 
| 114 | u16 tmp; | 250 | BUG_ON(in_interrupt()); | 
| 115 | 251 | ||
| 116 | if (in_interrupt()) | 252 | __mask_and_set_icr(irq, GxICR_ENABLE, level); | 
| 117 | BUG(); | 253 | } | 
| 118 | 254 | ||
| 119 | tmp = GxICR(irq); | 255 | void mn10300_intc_set_level(unsigned int irq, unsigned int level) | 
| 120 | GxICR(irq) = (tmp & GxICR_ENABLE) | level; | 256 | { | 
| 121 | tmp = GxICR(irq); | 257 | set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL); | 
| 258 | } | ||
| 259 | |||
| 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); | ||
| 122 | } | 278 | } | 
| 123 | 279 | ||
| 124 | /* | 280 | /* | 
| @@ -126,7 +282,7 @@ void set_intr_level(int irq, u16 level) | |||
| 126 | * than before | 282 | * than before | 
| 127 | * - see Documentation/mn10300/features.txt | 283 | * - see Documentation/mn10300/features.txt | 
| 128 | */ | 284 | */ | 
| 129 | void set_intr_postackable(int irq) | 285 | void mn10300_set_lateack_irq_type(int irq) | 
| 130 | { | 286 | { | 
| 131 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, | 287 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, | 
| 132 | handle_level_irq); | 288 | handle_level_irq); | 
| @@ -147,6 +303,7 @@ void __init init_IRQ(void) | |||
| 147 | * interrupts */ | 303 | * interrupts */ | 
| 148 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, | 304 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, | 
| 149 | handle_level_irq); | 305 | handle_level_irq); | 
| 306 | |||
| 150 | unit_init_IRQ(); | 307 | unit_init_IRQ(); | 
| 151 | } | 308 | } | 
| 152 | 309 | ||
| @@ -156,20 +313,22 @@ void __init init_IRQ(void) | |||
| 156 | asmlinkage void do_IRQ(void) | 313 | asmlinkage void do_IRQ(void) | 
| 157 | { | 314 | { | 
| 158 | unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw; | 315 | unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw; | 
| 316 | unsigned int cpu_id = smp_processor_id(); | ||
| 159 | int irq; | 317 | int irq; | 
| 160 | 318 | ||
| 161 | sp = current_stack_pointer(); | 319 | sp = current_stack_pointer(); | 
| 162 | if (sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN) | 320 | BUG_ON(sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN); | 
| 163 | BUG(); | ||
| 164 | 321 | ||
| 165 | /* make sure local_irq_enable() doesn't muck up the interrupt priority | 322 | /* make sure local_irq_enable() doesn't muck up the interrupt priority | 
| 166 | * setting in EPSW */ | 323 | * setting in EPSW */ | 
| 167 | old_irq_enabled_epsw = __mn10300_irq_enabled_epsw; | 324 | old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id]; | 
| 168 | local_save_flags(epsw); | 325 | local_save_flags(epsw); | 
| 169 | __mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw); | 326 | __mn10300_irq_enabled_epsw[cpu_id] = EPSW_IE | (EPSW_IM & epsw); | 
| 170 | irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL; | 327 | irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL; | 
| 171 | 328 | ||
| 172 | __IRQ_STAT(smp_processor_id(), __irq_count)++; | 329 | #ifdef CONFIG_MN10300_WD_TIMER | 
| 330 | __IRQ_STAT(cpu_id, __irq_count)++; | ||
| 331 | #endif | ||
| 173 | 332 | ||
| 174 | irq_enter(); | 333 | irq_enter(); | 
| 175 | 334 | ||
| @@ -189,7 +348,7 @@ asmlinkage void do_IRQ(void) | |||
| 189 | local_irq_restore(epsw); | 348 | local_irq_restore(epsw); | 
| 190 | } | 349 | } | 
| 191 | 350 | ||
| 192 | __mn10300_irq_enabled_epsw = old_irq_enabled_epsw; | 351 | __mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw; | 
| 193 | 352 | ||
| 194 | irq_exit(); | 353 | irq_exit(); | 
| 195 | } | 354 | } | 
| @@ -222,9 +381,16 @@ int show_interrupts(struct seq_file *p, void *v) | |||
| 222 | seq_printf(p, "%3d: ", i); | 381 | seq_printf(p, "%3d: ", i); | 
| 223 | for_each_present_cpu(cpu) | 382 | for_each_present_cpu(cpu) | 
| 224 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); | 383 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); | 
| 225 | seq_printf(p, " %14s.%u", irq_desc[i].chip->name, | 384 | |
| 226 | (GxICR(i) & GxICR_LEVEL) >> | 385 | if (i < NR_CPU_IRQS) | 
| 227 | GxICR_LEVEL_SHIFT); | 386 | seq_printf(p, " %14s.%u", | 
| 387 | irq_desc[i].chip->name, | ||
| 388 | (GxICR(i) & GxICR_LEVEL) >> | ||
| 389 | GxICR_LEVEL_SHIFT); | ||
| 390 | else | ||
| 391 | seq_printf(p, " %14s", | ||
| 392 | irq_desc[i].chip->name); | ||
| 393 | |||
| 228 | seq_printf(p, " %s", action->name); | 394 | seq_printf(p, " %s", action->name); | 
| 229 | 395 | ||
| 230 | for (action = action->next; | 396 | for (action = action->next; | 
| @@ -240,11 +406,13 @@ int show_interrupts(struct seq_file *p, void *v) | |||
| 240 | 406 | ||
| 241 | /* polish off with NMI and error counters */ | 407 | /* polish off with NMI and error counters */ | 
| 242 | case NR_IRQS: | 408 | case NR_IRQS: | 
| 409 | #ifdef CONFIG_MN10300_WD_TIMER | ||
| 243 | seq_printf(p, "NMI: "); | 410 | seq_printf(p, "NMI: "); | 
| 244 | for (j = 0; j < NR_CPUS; j++) | 411 | for (j = 0; j < NR_CPUS; j++) | 
| 245 | if (cpu_online(j)) | 412 | if (cpu_online(j)) | 
| 246 | seq_printf(p, "%10u ", nmi_count(j)); | 413 | seq_printf(p, "%10u ", nmi_count(j)); | 
| 247 | seq_putc(p, '\n'); | 414 | seq_putc(p, '\n'); | 
| 415 | #endif | ||
| 248 | 416 | ||
| 249 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | 417 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | 
| 250 | break; | 418 | break; | 
| @@ -252,3 +420,51 @@ int show_interrupts(struct seq_file *p, void *v) | |||
| 252 | 420 | ||
| 253 | return 0; | 421 | return 0; | 
| 254 | } | 422 | } | 
| 423 | |||
| 424 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 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 */ | ||
| diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c index 67e6389d625a..0311a7fcea16 100644 --- a/arch/mn10300/kernel/kprobes.c +++ b/arch/mn10300/kernel/kprobes.c | |||
| @@ -377,8 +377,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) | |||
| 377 | 377 | ||
| 378 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 378 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 
| 379 | { | 379 | { | 
| 380 | #ifndef CONFIG_MN10300_CACHE_SNOOP | ||
| 380 | mn10300_dcache_flush(); | 381 | mn10300_dcache_flush(); | 
| 381 | mn10300_icache_inv(); | 382 | mn10300_icache_inv(); | 
| 383 | #endif | ||
| 382 | } | 384 | } | 
| 383 | 385 | ||
| 384 | void arch_remove_kprobe(struct kprobe *p) | 386 | void arch_remove_kprobe(struct kprobe *p) | 
| @@ -390,8 +392,10 @@ void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs) | |||
| 390 | { | 392 | { | 
| 391 | *p->addr = p->opcode; | 393 | *p->addr = p->opcode; | 
| 392 | regs->pc = (unsigned long) p->addr; | 394 | regs->pc = (unsigned long) p->addr; | 
| 395 | #ifndef CONFIG_MN10300_CACHE_SNOOP | ||
| 393 | mn10300_dcache_flush(); | 396 | mn10300_dcache_flush(); | 
| 394 | mn10300_icache_inv(); | 397 | mn10300_icache_inv(); | 
| 398 | #endif | ||
| 395 | } | 399 | } | 
| 396 | 400 | ||
| 397 | static inline | 401 | static inline | 
| diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S index 66702d256610..dfc1b6f2fa9a 100644 --- a/arch/mn10300/kernel/mn10300-serial-low.S +++ b/arch/mn10300/kernel/mn10300-serial-low.S | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | ############################################################################### | 39 | ############################################################################### | 
| 40 | .balign L1_CACHE_BYTES | 40 | .balign L1_CACHE_BYTES | 
| 41 | ENTRY(mn10300_serial_vdma_interrupt) | 41 | ENTRY(mn10300_serial_vdma_interrupt) | 
| 42 | or EPSW_IE,psw # permit overriding by | 42 | # or EPSW_IE,psw # permit overriding by | 
| 43 | # debugging interrupts | 43 | # debugging interrupts | 
| 44 | movm [d2,d3,a2,a3,exreg0],(sp) | 44 | movm [d2,d3,a2,a3,exreg0],(sp) | 
| 45 | 45 | ||
| @@ -164,7 +164,7 @@ mnsc_vdma_tx_noint: | |||
| 164 | rti | 164 | rti | 
| 165 | 165 | ||
| 166 | mnsc_vdma_tx_empty: | 166 | mnsc_vdma_tx_empty: | 
| 167 | mov +(GxICR_LEVEL_1|GxICR_DETECT),d2 | 167 | mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 | 
| 168 | movhu d2,(e3) # disable the interrupt | 168 | movhu d2,(e3) # disable the interrupt | 
| 169 | movhu (e3),d2 # flush | 169 | movhu (e3),d2 # flush | 
| 170 | 170 | ||
| @@ -175,7 +175,7 @@ mnsc_vdma_tx_break: | |||
| 175 | movhu (SCxCTR,e2),d2 # turn on break mode | 175 | movhu (SCxCTR,e2),d2 # turn on break mode | 
| 176 | or SC01CTR_BKE,d2 | 176 | or SC01CTR_BKE,d2 | 
| 177 | movhu d2,(SCxCTR,e2) | 177 | movhu d2,(SCxCTR,e2) | 
| 178 | mov +(GxICR_LEVEL_1|GxICR_DETECT),d2 | 178 | mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 | 
| 179 | movhu d2,(e3) # disable transmit interrupts on this | 179 | movhu d2,(e3) # disable transmit interrupts on this | 
| 180 | # channel | 180 | # channel | 
| 181 | movhu (e3),d2 # flush | 181 | movhu (e3),d2 # flush | 
| diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index db509dd80565..996384dba45d 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
| @@ -44,6 +44,11 @@ static const char serial_revdate[] = "2007-11-06"; | |||
| 44 | #include <unit/timex.h> | 44 | #include <unit/timex.h> | 
| 45 | #include "mn10300-serial.h" | 45 | #include "mn10300-serial.h" | 
| 46 | 46 | ||
| 47 | #ifdef CONFIG_SMP | ||
| 48 | #undef GxICR | ||
| 49 | #define GxICR(X) CROSS_GxICR(X, 0) | ||
| 50 | #endif /* CONFIG_SMP */ | ||
| 51 | |||
| 47 | #define kenter(FMT, ...) \ | 52 | #define kenter(FMT, ...) \ | 
| 48 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | 53 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | 
| 49 | #define _enter(FMT, ...) \ | 54 | #define _enter(FMT, ...) \ | 
| @@ -57,6 +62,11 @@ static const char serial_revdate[] = "2007-11-06"; | |||
| 57 | #define _proto(FMT, ...) \ | 62 | #define _proto(FMT, ...) \ | 
| 58 | no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) | 63 | no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) | 
| 59 | 64 | ||
| 65 | #ifndef CODMSB | ||
| 66 | /* c_cflag bit meaning */ | ||
| 67 | #define CODMSB 004000000000 /* change Transfer bit-order */ | ||
| 68 | #endif | ||
| 69 | |||
| 60 | #define NR_UARTS 3 | 70 | #define NR_UARTS 3 | 
| 61 | 71 | ||
| 62 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | 72 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | 
| @@ -152,26 +162,35 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { | |||
| 152 | .name = "ttySM0", | 162 | .name = "ttySM0", | 
| 153 | ._iobase = &SC0CTR, | 163 | ._iobase = &SC0CTR, | 
| 154 | ._control = &SC0CTR, | 164 | ._control = &SC0CTR, | 
| 155 | ._status = (volatile u8 *) &SC0STR, | 165 | ._status = (volatile u8 *)&SC0STR, | 
| 156 | ._intr = &SC0ICR, | 166 | ._intr = &SC0ICR, | 
| 157 | ._rxb = &SC0RXB, | 167 | ._rxb = &SC0RXB, | 
| 158 | ._txb = &SC0TXB, | 168 | ._txb = &SC0TXB, | 
| 159 | .rx_name = "ttySM0:Rx", | 169 | .rx_name = "ttySM0:Rx", | 
| 160 | .tx_name = "ttySM0:Tx", | 170 | .tx_name = "ttySM0:Tx", | 
| 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | 171 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) | 
| 162 | .tm_name = "ttySM0:Timer8", | 172 | .tm_name = "ttySM0:Timer8", | 
| 163 | ._tmxmd = &TM8MD, | 173 | ._tmxmd = &TM8MD, | 
| 164 | ._tmxbr = &TM8BR, | 174 | ._tmxbr = &TM8BR, | 
| 165 | ._tmicr = &TM8ICR, | 175 | ._tmicr = &TM8ICR, | 
| 166 | .tm_irq = TM8IRQ, | 176 | .tm_irq = TM8IRQ, | 
| 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 177 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 
| 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ | 178 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) | 
| 179 | .tm_name = "ttySM0:Timer0", | ||
| 180 | ._tmxmd = &TM0MD, | ||
| 181 | ._tmxbr = (volatile u16 *)&TM0BR, | ||
| 182 | ._tmicr = &TM0ICR, | ||
| 183 | .tm_irq = TM0IRQ, | ||
| 184 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
| 185 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | ||
| 169 | .tm_name = "ttySM0:Timer2", | 186 | .tm_name = "ttySM0:Timer2", | 
| 170 | ._tmxmd = &TM2MD, | 187 | ._tmxmd = &TM2MD, | 
| 171 | ._tmxbr = (volatile u16 *) &TM2BR, | 188 | ._tmxbr = (volatile u16 *)&TM2BR, | 
| 172 | ._tmicr = &TM2ICR, | 189 | ._tmicr = &TM2ICR, | 
| 173 | .tm_irq = TM2IRQ, | 190 | .tm_irq = TM2IRQ, | 
| 174 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 191 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 
| 192 | #else | ||
| 193 | #error "Unknown config for ttySM0" | ||
| 175 | #endif | 194 | #endif | 
| 176 | .rx_irq = SC0RXIRQ, | 195 | .rx_irq = SC0RXIRQ, | 
| 177 | .tx_irq = SC0TXIRQ, | 196 | .tx_irq = SC0TXIRQ, | 
| @@ -205,26 +224,35 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { | |||
| 205 | .name = "ttySM1", | 224 | .name = "ttySM1", | 
| 206 | ._iobase = &SC1CTR, | 225 | ._iobase = &SC1CTR, | 
| 207 | ._control = &SC1CTR, | 226 | ._control = &SC1CTR, | 
| 208 | ._status = (volatile u8 *) &SC1STR, | 227 | ._status = (volatile u8 *)&SC1STR, | 
| 209 | ._intr = &SC1ICR, | 228 | ._intr = &SC1ICR, | 
| 210 | ._rxb = &SC1RXB, | 229 | ._rxb = &SC1RXB, | 
| 211 | ._txb = &SC1TXB, | 230 | ._txb = &SC1TXB, | 
| 212 | .rx_name = "ttySM1:Rx", | 231 | .rx_name = "ttySM1:Rx", | 
| 213 | .tx_name = "ttySM1:Tx", | 232 | .tx_name = "ttySM1:Tx", | 
| 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 | 233 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) | 
| 215 | .tm_name = "ttySM1:Timer9", | 234 | .tm_name = "ttySM1:Timer9", | 
| 216 | ._tmxmd = &TM9MD, | 235 | ._tmxmd = &TM9MD, | 
| 217 | ._tmxbr = &TM9BR, | 236 | ._tmxbr = &TM9BR, | 
| 218 | ._tmicr = &TM9ICR, | 237 | ._tmicr = &TM9ICR, | 
| 219 | .tm_irq = TM9IRQ, | 238 | .tm_irq = TM9IRQ, | 
| 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 239 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 
| 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ | 240 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) | 
| 222 | .tm_name = "ttySM1:Timer3", | 241 | .tm_name = "ttySM1:Timer3", | 
| 223 | ._tmxmd = &TM3MD, | 242 | ._tmxmd = &TM3MD, | 
| 224 | ._tmxbr = (volatile u16 *) &TM3BR, | 243 | ._tmxbr = (volatile u16 *)&TM3BR, | 
| 225 | ._tmicr = &TM3ICR, | 244 | ._tmicr = &TM3ICR, | 
| 226 | .tm_irq = TM3IRQ, | 245 | .tm_irq = TM3IRQ, | 
| 227 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 246 | .div_timer = MNSCx_DIV_TIMER_8BIT, | 
| 247 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER12) | ||
| 248 | .tm_name = "ttySM1/Timer12", | ||
| 249 | ._tmxmd = &TM12MD, | ||
| 250 | ._tmxbr = &TM12BR, | ||
| 251 | ._tmicr = &TM12ICR, | ||
| 252 | .tm_irq = TM12IRQ, | ||
| 253 | .div_timer = MNSCx_DIV_TIMER_16BIT, | ||
| 254 | #else | ||
| 255 | #error "Unknown config for ttySM1" | ||
| 228 | #endif | 256 | #endif | 
| 229 | .rx_irq = SC1RXIRQ, | 257 | .rx_irq = SC1RXIRQ, | 
| 230 | .tx_irq = SC1TXIRQ, | 258 | .tx_irq = SC1TXIRQ, | 
| @@ -260,20 +288,45 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { | |||
| 260 | .uart.lock = | 288 | .uart.lock = | 
| 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 289 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 
| 262 | .name = "ttySM2", | 290 | .name = "ttySM2", | 
| 263 | .rx_name = "ttySM2:Rx", | ||
| 264 | .tx_name = "ttySM2:Tx", | ||
| 265 | .tm_name = "ttySM2:Timer10", | ||
| 266 | ._iobase = &SC2CTR, | 291 | ._iobase = &SC2CTR, | 
| 267 | ._control = &SC2CTR, | 292 | ._control = &SC2CTR, | 
| 268 | ._status = &SC2STR, | 293 | ._status = (volatile u8 *)&SC2STR, | 
| 269 | ._intr = &SC2ICR, | 294 | ._intr = &SC2ICR, | 
| 270 | ._rxb = &SC2RXB, | 295 | ._rxb = &SC2RXB, | 
| 271 | ._txb = &SC2TXB, | 296 | ._txb = &SC2TXB, | 
| 297 | .rx_name = "ttySM2:Rx", | ||
| 298 | .tx_name = "ttySM2:Tx", | ||
| 299 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | ||
| 300 | .tm_name = "ttySM2/Timer10", | ||
| 272 | ._tmxmd = &TM10MD, | 301 | ._tmxmd = &TM10MD, | 
| 273 | ._tmxbr = &TM10BR, | 302 | ._tmxbr = &TM10BR, | 
| 274 | ._tmicr = &TM10ICR, | 303 | ._tmicr = &TM10ICR, | 
| 275 | .tm_irq = TM10IRQ, | 304 | .tm_irq = TM10IRQ, | 
| 276 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 305 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 
| 306 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER9) | ||
| 307 | .tm_name = "ttySM2/Timer9", | ||
| 308 | ._tmxmd = &TM9MD, | ||
| 309 | ._tmxbr = &TM9BR, | ||
| 310 | ._tmicr = &TM9ICR, | ||
| 311 | .tm_irq = TM9IRQ, | ||
| 312 | .div_timer = MNSCx_DIV_TIMER_16BIT, | ||
| 313 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | ||
| 314 | .tm_name = "ttySM2/Timer1", | ||
| 315 | ._tmxmd = &TM1MD, | ||
| 316 | ._tmxbr = (volatile u16 *)&TM1BR, | ||
| 317 | ._tmicr = &TM1ICR, | ||
| 318 | .tm_irq = TM1IRQ, | ||
| 319 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
| 320 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | ||
| 321 | .tm_name = "ttySM2/Timer3", | ||
| 322 | ._tmxmd = &TM3MD, | ||
| 323 | ._tmxbr = (volatile u16 *)&TM3BR, | ||
| 324 | ._tmicr = &TM3ICR, | ||
| 325 | .tm_irq = TM3IRQ, | ||
| 326 | .div_timer = MNSCx_DIV_TIMER_8BIT, | ||
| 327 | #else | ||
| 328 | #error "Unknown config for ttySM2" | ||
| 329 | #endif | ||
| 277 | .rx_irq = SC2RXIRQ, | 330 | .rx_irq = SC2RXIRQ, | 
| 278 | .tx_irq = SC2TXIRQ, | 331 | .tx_irq = SC2TXIRQ, | 
| 279 | .rx_icr = &GxICR(SC2RXIRQ), | 332 | .rx_icr = &GxICR(SC2RXIRQ), | 
| @@ -322,9 +375,13 @@ struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = { | |||
| 322 | */ | 375 | */ | 
| 323 | static void mn10300_serial_mask_ack(unsigned int irq) | 376 | static void mn10300_serial_mask_ack(unsigned int irq) | 
| 324 | { | 377 | { | 
| 378 | unsigned long flags; | ||
| 325 | u16 tmp; | 379 | u16 tmp; | 
| 380 | |||
| 381 | flags = arch_local_cli_save(); | ||
| 326 | GxICR(irq) = GxICR_LEVEL_6; | 382 | GxICR(irq) = GxICR_LEVEL_6; | 
| 327 | tmp = GxICR(irq); /* flush write buffer */ | 383 | tmp = GxICR(irq); /* flush write buffer */ | 
| 384 | arch_local_irq_restore(flags); | ||
| 328 | } | 385 | } | 
| 329 | 386 | ||
| 330 | static void mn10300_serial_nop(unsigned int irq) | 387 | static void mn10300_serial_nop(unsigned int irq) | 
| @@ -348,23 +405,36 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS]; | |||
| 348 | 405 | ||
| 349 | static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) | 406 | static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) | 
| 350 | { | 407 | { | 
| 408 | unsigned long flags; | ||
| 351 | u16 x; | 409 | u16 x; | 
| 352 | *port->tx_icr = GxICR_LEVEL_1 | GxICR_DETECT; | 410 | |
| 411 | flags = arch_local_cli_save(); | ||
| 412 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
| 353 | x = *port->tx_icr; | 413 | x = *port->tx_icr; | 
| 414 | arch_local_irq_restore(flags); | ||
| 354 | } | 415 | } | 
| 355 | 416 | ||
| 356 | static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) | 417 | static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) | 
| 357 | { | 418 | { | 
| 419 | unsigned long flags; | ||
| 358 | u16 x; | 420 | u16 x; | 
| 359 | *port->tx_icr = GxICR_LEVEL_1 | GxICR_ENABLE; | 421 | |
| 422 | flags = arch_local_cli_save(); | ||
| 423 | *port->tx_icr = | ||
| 424 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; | ||
| 360 | x = *port->tx_icr; | 425 | x = *port->tx_icr; | 
| 426 | arch_local_irq_restore(flags); | ||
| 361 | } | 427 | } | 
| 362 | 428 | ||
| 363 | static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) | 429 | static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) | 
| 364 | { | 430 | { | 
| 431 | unsigned long flags; | ||
| 365 | u16 x; | 432 | u16 x; | 
| 366 | *port->rx_icr = GxICR_LEVEL_1 | GxICR_DETECT; | 433 | |
| 434 | flags = arch_local_cli_save(); | ||
| 435 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
| 367 | x = *port->rx_icr; | 436 | x = *port->rx_icr; | 
| 437 | arch_local_irq_restore(flags); | ||
| 368 | } | 438 | } | 
| 369 | 439 | ||
| 370 | /* | 440 | /* | 
| @@ -650,7 +720,7 @@ static unsigned int mn10300_serial_tx_empty(struct uart_port *_port) | |||
| 650 | static void mn10300_serial_set_mctrl(struct uart_port *_port, | 720 | static void mn10300_serial_set_mctrl(struct uart_port *_port, | 
| 651 | unsigned int mctrl) | 721 | unsigned int mctrl) | 
| 652 | { | 722 | { | 
| 653 | struct mn10300_serial_port *port = | 723 | struct mn10300_serial_port *port __attribute__ ((unused)) = | 
| 654 | container_of(_port, struct mn10300_serial_port, uart); | 724 | container_of(_port, struct mn10300_serial_port, uart); | 
| 655 | 725 | ||
| 656 | _enter("%s,%x", port->name, mctrl); | 726 | _enter("%s,%x", port->name, mctrl); | 
| @@ -706,6 +776,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port) | |||
| 706 | UART_XMIT_SIZE)); | 776 | UART_XMIT_SIZE)); | 
| 707 | 777 | ||
| 708 | /* kick the virtual DMA controller */ | 778 | /* kick the virtual DMA controller */ | 
| 779 | arch_local_cli(); | ||
| 709 | x = *port->tx_icr; | 780 | x = *port->tx_icr; | 
| 710 | x |= GxICR_ENABLE; | 781 | x |= GxICR_ENABLE; | 
| 711 | 782 | ||
| @@ -716,10 +787,14 @@ static void mn10300_serial_start_tx(struct uart_port *_port) | |||
| 716 | 787 | ||
| 717 | _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", | 788 | _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", | 
| 718 | *port->_control, *port->_intr, *port->_status, | 789 | *port->_control, *port->_intr, *port->_status, | 
| 719 | *port->_tmxmd, *port->_tmxbr, *port->tx_icr); | 790 | *port->_tmxmd, | 
| 791 | (port->div_timer == MNSCx_DIV_TIMER_8BIT) ? | ||
| 792 | *(volatile u8 *)port->_tmxbr : *port->_tmxbr, | ||
| 793 | *port->tx_icr); | ||
| 720 | 794 | ||
| 721 | *port->tx_icr = x; | 795 | *port->tx_icr = x; | 
| 722 | x = *port->tx_icr; | 796 | x = *port->tx_icr; | 
| 797 | arch_local_sti(); | ||
| 723 | } | 798 | } | 
| 724 | 799 | ||
| 725 | /* | 800 | /* | 
| @@ -842,8 +917,10 @@ static int mn10300_serial_startup(struct uart_port *_port) | |||
| 842 | pint->port = port; | 917 | pint->port = port; | 
| 843 | pint->vdma = mn10300_serial_vdma_tx_handler; | 918 | pint->vdma = mn10300_serial_vdma_tx_handler; | 
| 844 | 919 | ||
| 845 | set_intr_level(port->rx_irq, GxICR_LEVEL_1); | 920 | set_intr_level(port->rx_irq, | 
| 846 | set_intr_level(port->tx_irq, GxICR_LEVEL_1); | 921 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | 
| 922 | set_intr_level(port->tx_irq, | ||
| 923 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | ||
| 847 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); | 924 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); | 
| 848 | 925 | ||
| 849 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | 926 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | 
| @@ -876,6 +953,7 @@ error: | |||
| 876 | */ | 953 | */ | 
| 877 | static void mn10300_serial_shutdown(struct uart_port *_port) | 954 | static void mn10300_serial_shutdown(struct uart_port *_port) | 
| 878 | { | 955 | { | 
| 956 | u16 x; | ||
| 879 | struct mn10300_serial_port *port = | 957 | struct mn10300_serial_port *port = | 
| 880 | container_of(_port, struct mn10300_serial_port, uart); | 958 | container_of(_port, struct mn10300_serial_port, uart); | 
| 881 | 959 | ||
| @@ -897,8 +975,12 @@ static void mn10300_serial_shutdown(struct uart_port *_port) | |||
| 897 | free_irq(port->rx_irq, port); | 975 | free_irq(port->rx_irq, port); | 
| 898 | free_irq(port->tx_irq, port); | 976 | free_irq(port->tx_irq, port); | 
| 899 | 977 | ||
| 900 | *port->rx_icr = GxICR_LEVEL_1; | 978 | arch_local_cli(); | 
| 901 | *port->tx_icr = GxICR_LEVEL_1; | 979 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | 
| 980 | x = *port->rx_icr; | ||
| 981 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | ||
| 982 | x = *port->tx_icr; | ||
| 983 | arch_local_sti(); | ||
| 902 | } | 984 | } | 
| 903 | 985 | ||
| 904 | /* | 986 | /* | 
| @@ -947,11 +1029,66 @@ static void mn10300_serial_change_speed(struct mn10300_serial_port *port, | |||
| 947 | /* Determine divisor based on baud rate */ | 1029 | /* Determine divisor based on baud rate */ | 
| 948 | battempt = 0; | 1030 | battempt = 0; | 
| 949 | 1031 | ||
| 950 | if (div_timer == MNSCx_DIV_TIMER_16BIT) | 1032 | switch (port->uart.line) { | 
| 951 | scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8 | 1033 | #ifdef CONFIG_MN10300_TTYSM0 | 
| 952 | * == SC2CTR_CK_TM10UFLOW) */ | 1034 | case 0: /* ttySM0 */ | 
| 953 | else if (div_timer == MNSCx_DIV_TIMER_8BIT) | 1035 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) | 
| 1036 | scxctr |= SC0CTR_CK_TM8UFLOW_8; | ||
| 1037 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) | ||
| 1038 | scxctr |= SC0CTR_CK_TM0UFLOW_8; | ||
| 1039 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | ||
| 954 | scxctr |= SC0CTR_CK_TM2UFLOW_8; | 1040 | scxctr |= SC0CTR_CK_TM2UFLOW_8; | 
| 1041 | #else | ||
| 1042 | #error "Unknown config for ttySM0" | ||
| 1043 | #endif | ||
| 1044 | break; | ||
| 1045 | #endif /* CONFIG_MN10300_TTYSM0 */ | ||
| 1046 | |||
| 1047 | #ifdef CONFIG_MN10300_TTYSM1 | ||
| 1048 | case 1: /* ttySM1 */ | ||
| 1049 | #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) | ||
| 1050 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) | ||
| 1051 | scxctr |= SC1CTR_CK_TM9UFLOW_8; | ||
| 1052 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) | ||
| 1053 | scxctr |= SC1CTR_CK_TM3UFLOW_8; | ||
| 1054 | #else | ||
| 1055 | #error "Unknown config for ttySM1" | ||
| 1056 | #endif | ||
| 1057 | #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
| 1058 | #if defined(CONFIG_MN10300_TTYSM1_TIMER12) | ||
| 1059 | scxctr |= SC1CTR_CK_TM12UFLOW_8; | ||
| 1060 | #else | ||
| 1061 | #error "Unknown config for ttySM1" | ||
| 1062 | #endif | ||
| 1063 | #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | ||
| 1064 | break; | ||
| 1065 | #endif /* CONFIG_MN10300_TTYSM1 */ | ||
| 1066 | |||
| 1067 | #ifdef CONFIG_MN10300_TTYSM2 | ||
| 1068 | case 2: /* ttySM2 */ | ||
| 1069 | #if defined(CONFIG_AM33_2) | ||
| 1070 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | ||
| 1071 | scxctr |= SC2CTR_CK_TM10UFLOW; | ||
| 1072 | #else | ||
| 1073 | #error "Unknown config for ttySM2" | ||
| 1074 | #endif | ||
| 1075 | #else /* CONFIG_AM33_2 */ | ||
| 1076 | #if defined(CONFIG_MN10300_TTYSM2_TIMER9) | ||
| 1077 | scxctr |= SC2CTR_CK_TM9UFLOW_8; | ||
| 1078 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | ||
| 1079 | scxctr |= SC2CTR_CK_TM1UFLOW_8; | ||
| 1080 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | ||
| 1081 | scxctr |= SC2CTR_CK_TM3UFLOW_8; | ||
| 1082 | #else | ||
| 1083 | #error "Unknown config for ttySM2" | ||
| 1084 | #endif | ||
| 1085 | #endif /* CONFIG_AM33_2 */ | ||
| 1086 | break; | ||
| 1087 | #endif /* CONFIG_MN10300_TTYSM2 */ | ||
| 1088 | |||
| 1089 | default: | ||
| 1090 | break; | ||
| 1091 | } | ||
| 955 | 1092 | ||
| 956 | try_alternative: | 1093 | try_alternative: | 
| 957 | baud = uart_get_baud_rate(&port->uart, new, old, 0, | 1094 | baud = uart_get_baud_rate(&port->uart, new, old, 0, | 
| @@ -1195,6 +1332,12 @@ static void mn10300_serial_set_termios(struct uart_port *_port, | |||
| 1195 | ctr &= ~SC2CTR_TWE; | 1332 | ctr &= ~SC2CTR_TWE; | 
| 1196 | *port->_control = ctr; | 1333 | *port->_control = ctr; | 
| 1197 | } | 1334 | } | 
| 1335 | |||
| 1336 | /* change Transfer bit-order (LSB/MSB) */ | ||
| 1337 | if (new->c_cflag & CODMSB) | ||
| 1338 | *port->_control |= SC01CTR_OD_MSBFIRST; /* MSB MODE */ | ||
| 1339 | else | ||
| 1340 | *port->_control &= ~SC01CTR_OD_MSBFIRST; /* LSB MODE */ | ||
| 1198 | } | 1341 | } | 
| 1199 | 1342 | ||
| 1200 | /* | 1343 | /* | 
| @@ -1302,11 +1445,16 @@ static int __init mn10300_serial_init(void) | |||
| 1302 | printk(KERN_INFO "%s version %s (%s)\n", | 1445 | printk(KERN_INFO "%s version %s (%s)\n", | 
| 1303 | serial_name, serial_version, serial_revdate); | 1446 | serial_name, serial_version, serial_revdate); | 
| 1304 | 1447 | ||
| 1305 | #ifdef CONFIG_MN10300_TTYSM2 | 1448 | #if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2) | 
| 1306 | SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */ | 1449 | { | 
| 1450 | int tmp; | ||
| 1451 | SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */ | ||
| 1452 | tmp = SC2TIM; | ||
| 1453 | } | ||
| 1307 | #endif | 1454 | #endif | 
| 1308 | 1455 | ||
| 1309 | set_intr_stub(EXCEP_IRQ_LEVEL1, mn10300_serial_vdma_interrupt); | 1456 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL), | 
| 1457 | mn10300_serial_vdma_interrupt); | ||
| 1310 | 1458 | ||
| 1311 | ret = uart_register_driver(&mn10300_serial_driver); | 1459 | ret = uart_register_driver(&mn10300_serial_driver); | 
| 1312 | if (!ret) { | 1460 | if (!ret) { | 
| @@ -1366,9 +1514,11 @@ static void mn10300_serial_console_write(struct console *co, | |||
| 1366 | port = mn10300_serial_ports[co->index]; | 1514 | port = mn10300_serial_ports[co->index]; | 
| 1367 | 1515 | ||
| 1368 | /* firstly hijack the serial port from the "virtual DMA" controller */ | 1516 | /* firstly hijack the serial port from the "virtual DMA" controller */ | 
| 1517 | arch_local_cli(); | ||
| 1369 | txicr = *port->tx_icr; | 1518 | txicr = *port->tx_icr; | 
| 1370 | *port->tx_icr = GxICR_LEVEL_1; | 1519 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | 
| 1371 | tmp = *port->tx_icr; | 1520 | tmp = *port->tx_icr; | 
| 1521 | arch_local_sti(); | ||
| 1372 | 1522 | ||
| 1373 | /* the transmitter may be disabled */ | 1523 | /* the transmitter may be disabled */ | 
| 1374 | scxctr = *port->_control; | 1524 | scxctr = *port->_control; | 
| @@ -1422,8 +1572,10 @@ static void mn10300_serial_console_write(struct console *co, | |||
| 1422 | if (!(scxctr & SC01CTR_TXE)) | 1572 | if (!(scxctr & SC01CTR_TXE)) | 
| 1423 | *port->_control = scxctr; | 1573 | *port->_control = scxctr; | 
| 1424 | 1574 | ||
| 1575 | arch_local_cli(); | ||
| 1425 | *port->tx_icr = txicr; | 1576 | *port->tx_icr = txicr; | 
| 1426 | tmp = *port->tx_icr; | 1577 | tmp = *port->tx_icr; | 
| 1578 | arch_local_sti(); | ||
| 1427 | } | 1579 | } | 
| 1428 | 1580 | ||
| 1429 | /* | 1581 | /* | 
| diff --git a/arch/mn10300/kernel/mn10300-watchdog-low.S b/arch/mn10300/kernel/mn10300-watchdog-low.S index 996244745cca..f2f5c9cfaabd 100644 --- a/arch/mn10300/kernel/mn10300-watchdog-low.S +++ b/arch/mn10300/kernel/mn10300-watchdog-low.S | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <asm/intctl-regs.h> | 16 | #include <asm/intctl-regs.h> | 
| 17 | #include <asm/timer-regs.h> | 17 | #include <asm/timer-regs.h> | 
| 18 | #include <asm/frame.inc> | 18 | #include <asm/frame.inc> | 
| 19 | #include <linux/threads.h> | ||
| 19 | 20 | ||
| 20 | .text | 21 | .text | 
| 21 | 22 | ||
| @@ -53,7 +54,13 @@ watchdog_handler: | |||
| 53 | .type touch_nmi_watchdog,@function | 54 | .type touch_nmi_watchdog,@function | 
| 54 | touch_nmi_watchdog: | 55 | touch_nmi_watchdog: | 
| 55 | clr d0 | 56 | clr d0 | 
| 56 | mov d0,(watchdog_alert_counter) | 57 | clr d1 | 
| 58 | mov watchdog_alert_counter, a0 | ||
| 59 | setlb | ||
| 60 | mov d0, (a0+) | ||
| 61 | inc d1 | ||
| 62 | cmp NR_CPUS, d1 | ||
| 63 | lne | ||
| 57 | ret [],0 | 64 | ret [],0 | 
| 58 | 65 | ||
| 59 | .size touch_nmi_watchdog,.-touch_nmi_watchdog | 66 | .size touch_nmi_watchdog,.-touch_nmi_watchdog | 
| diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c index f362d9d138f1..c5e12bfd9fcd 100644 --- a/arch/mn10300/kernel/mn10300-watchdog.c +++ b/arch/mn10300/kernel/mn10300-watchdog.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | static DEFINE_SPINLOCK(watchdog_print_lock); | 30 | static DEFINE_SPINLOCK(watchdog_print_lock); | 
| 31 | static unsigned int watchdog; | 31 | static unsigned int watchdog; | 
| 32 | static unsigned int watchdog_hz = 1; | 32 | static unsigned int watchdog_hz = 1; | 
| 33 | unsigned int watchdog_alert_counter; | 33 | unsigned int watchdog_alert_counter[NR_CPUS]; | 
| 34 | 34 | ||
| 35 | EXPORT_SYMBOL(touch_nmi_watchdog); | 35 | EXPORT_SYMBOL(touch_nmi_watchdog); | 
| 36 | 36 | ||
| @@ -39,9 +39,6 @@ EXPORT_SYMBOL(touch_nmi_watchdog); | |||
| 39 | * is to check its timer makes IRQ counts. If they are not | 39 | * is to check its timer makes IRQ counts. If they are not | 
| 40 | * changing then that CPU has some problem. | 40 | * changing then that CPU has some problem. | 
| 41 | * | 41 | * | 
| 42 | * as these watchdog NMI IRQs are generated on every CPU, we only | ||
| 43 | * have to check the current processor. | ||
| 44 | * | ||
| 45 | * since NMIs dont listen to _any_ locks, we have to be extremely | 42 | * since NMIs dont listen to _any_ locks, we have to be extremely | 
| 46 | * careful not to rely on unsafe variables. The printk might lock | 43 | * careful not to rely on unsafe variables. The printk might lock | 
| 47 | * up though, so we have to break up any console locks first ... | 44 | * up though, so we have to break up any console locks first ... | 
| @@ -69,8 +66,8 @@ int __init check_watchdog(void) | |||
| 69 | 66 | ||
| 70 | printk(KERN_INFO "OK.\n"); | 67 | printk(KERN_INFO "OK.\n"); | 
| 71 | 68 | ||
| 72 | /* now that we know it works we can reduce NMI frequency to | 69 | /* now that we know it works we can reduce NMI frequency to something | 
| 73 | * something more reasonable; makes a difference in some configs | 70 | * more reasonable; makes a difference in some configs | 
| 74 | */ | 71 | */ | 
| 75 | watchdog_hz = 1; | 72 | watchdog_hz = 1; | 
| 76 | 73 | ||
| @@ -121,15 +118,22 @@ void __init watchdog_go(void) | |||
| 121 | } | 118 | } | 
| 122 | } | 119 | } | 
| 123 | 120 | ||
| 121 | #ifdef CONFIG_SMP | ||
| 122 | static void watchdog_dump_register(void *dummy) | ||
| 123 | { | ||
| 124 | printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID); | ||
| 125 | show_registers(current_frame()); | ||
| 126 | } | ||
| 127 | #endif | ||
| 128 | |||
| 124 | asmlinkage | 129 | asmlinkage | 
| 125 | void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | 130 | void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | 
| 126 | { | 131 | { | 
| 127 | |||
| 128 | /* | 132 | /* | 
| 129 | * Since current-> is always on the stack, and we always switch | 133 | * Since current-> is always on the stack, and we always switch | 
| 130 | * the stack NMI-atomically, it's safe to use smp_processor_id(). | 134 | * the stack NMI-atomically, it's safe to use smp_processor_id(). | 
| 131 | */ | 135 | */ | 
| 132 | int sum, cpu = smp_processor_id(); | 136 | int sum, cpu; | 
| 133 | int irq = NMIIRQ; | 137 | int irq = NMIIRQ; | 
| 134 | u8 wdt, tmp; | 138 | u8 wdt, tmp; | 
| 135 | 139 | ||
| @@ -138,43 +142,61 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | |||
| 138 | tmp = WDCTR; | 142 | tmp = WDCTR; | 
| 139 | NMICR = NMICR_WDIF; | 143 | NMICR = NMICR_WDIF; | 
| 140 | 144 | ||
| 141 | nmi_count(cpu)++; | 145 | nmi_count(smp_processor_id())++; | 
| 142 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 146 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 
| 143 | sum = irq_stat[cpu].__irq_count; | 147 | |
| 144 | 148 | for_each_online_cpu(cpu) { | |
| 145 | if (last_irq_sums[cpu] == sum) { | 149 | |
| 146 | /* | 150 | sum = irq_stat[cpu].__irq_count; | 
| 147 | * Ayiee, looks like this CPU is stuck ... | 151 | |
| 148 | * wait a few IRQs (5 seconds) before doing the oops ... | 152 | if ((last_irq_sums[cpu] == sum) | 
| 149 | */ | 153 | #if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP) | 
| 150 | watchdog_alert_counter++; | 154 | && !(CHK_GDBSTUB_BUSY() | 
| 151 | if (watchdog_alert_counter == 5 * watchdog_hz) { | 155 | || atomic_read(&cpu_doing_single_step)) | 
| 152 | spin_lock(&watchdog_print_lock); | 156 | #endif | 
| 157 | ) { | ||
| 153 | /* | 158 | /* | 
| 154 | * We are in trouble anyway, lets at least try | 159 | * Ayiee, looks like this CPU is stuck ... | 
| 155 | * to get a message out. | 160 | * wait a few IRQs (5 seconds) before doing the oops ... | 
| 156 | */ | 161 | */ | 
| 157 | bust_spinlocks(1); | 162 | watchdog_alert_counter[cpu]++; | 
| 158 | printk(KERN_ERR | 163 | if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) { | 
| 159 | "NMI Watchdog detected LOCKUP on CPU%d," | 164 | spin_lock(&watchdog_print_lock); | 
| 160 | " pc %08lx, registers:\n", | 165 | /* | 
| 161 | cpu, regs->pc); | 166 | * We are in trouble anyway, lets at least try | 
| 162 | show_registers(regs); | 167 | * to get a message out. | 
| 163 | printk("console shuts up ...\n"); | 168 | */ | 
| 164 | console_silent(); | 169 | bust_spinlocks(1); | 
| 165 | spin_unlock(&watchdog_print_lock); | 170 | printk(KERN_ERR | 
| 166 | bust_spinlocks(0); | 171 | "NMI Watchdog detected LOCKUP on CPU%d," | 
| 172 | " pc %08lx, registers:\n", | ||
| 173 | cpu, regs->pc); | ||
| 174 | #ifdef CONFIG_SMP | ||
| 175 | printk(KERN_ERR | ||
| 176 | "--- Register Dump (CPU%d) ---\n", | ||
| 177 | CPUID); | ||
| 178 | #endif | ||
| 179 | show_registers(regs); | ||
| 180 | #ifdef CONFIG_SMP | ||
| 181 | smp_nmi_call_function(watchdog_dump_register, | ||
| 182 | NULL, 1); | ||
| 183 | #endif | ||
| 184 | printk(KERN_NOTICE "console shuts up ...\n"); | ||
| 185 | console_silent(); | ||
| 186 | spin_unlock(&watchdog_print_lock); | ||
| 187 | bust_spinlocks(0); | ||
| 167 | #ifdef CONFIG_GDBSTUB | 188 | #ifdef CONFIG_GDBSTUB | 
| 168 | if (gdbstub_busy) | 189 | if (CHK_GDBSTUB_BUSY_AND_ACTIVE()) | 
| 169 | gdbstub_exception(regs, excep); | 190 | gdbstub_exception(regs, excep); | 
| 170 | else | 191 | else | 
| 171 | gdbstub_intercept(regs, excep); | 192 | gdbstub_intercept(regs, excep); | 
| 172 | #endif | 193 | #endif | 
| 173 | do_exit(SIGSEGV); | 194 | do_exit(SIGSEGV); | 
| 195 | } | ||
| 196 | } else { | ||
| 197 | last_irq_sums[cpu] = sum; | ||
| 198 | watchdog_alert_counter[cpu] = 0; | ||
| 174 | } | 199 | } | 
| 175 | } else { | ||
| 176 | last_irq_sums[cpu] = sum; | ||
| 177 | watchdog_alert_counter = 0; | ||
| 178 | } | 200 | } | 
| 179 | 201 | ||
| 180 | WDCTR = wdt | WDCTR_WDRST; | 202 | WDCTR = wdt | WDCTR_WDRST; | 
| diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index f48373e2bc1c..0d0f8049a17b 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
| @@ -57,6 +57,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
| 57 | void (*pm_power_off)(void); | 57 | void (*pm_power_off)(void); | 
| 58 | EXPORT_SYMBOL(pm_power_off); | 58 | EXPORT_SYMBOL(pm_power_off); | 
| 59 | 59 | ||
| 60 | #if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU) | ||
| 60 | /* | 61 | /* | 
| 61 | * we use this if we don't have any better idle routine | 62 | * we use this if we don't have any better idle routine | 
| 62 | */ | 63 | */ | 
| @@ -69,6 +70,35 @@ static void default_idle(void) | |||
| 69 | local_irq_enable(); | 70 | local_irq_enable(); | 
| 70 | } | 71 | } | 
| 71 | 72 | ||
| 73 | #else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
| 74 | /* | ||
| 75 | * On SMP it's slightly faster (but much more power-consuming!) | ||
| 76 | * to poll the ->work.need_resched flag instead of waiting for the | ||
| 77 | * cross-CPU IPI to arrive. Use this option with caution. | ||
| 78 | */ | ||
| 79 | static inline void poll_idle(void) | ||
| 80 | { | ||
| 81 | int oldval; | ||
| 82 | |||
| 83 | local_irq_enable(); | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Deal with another CPU just having chosen a thread to | ||
| 87 | * run here: | ||
| 88 | */ | ||
| 89 | oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); | ||
| 90 | |||
| 91 | if (!oldval) { | ||
| 92 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
| 93 | while (!need_resched()) | ||
| 94 | cpu_relax(); | ||
| 95 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
| 96 | } else { | ||
| 97 | set_need_resched(); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | #endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
| 101 | |||
| 72 | /* | 102 | /* | 
| 73 | * the idle thread | 103 | * the idle thread | 
| 74 | * - there's no useful work to be done, so just try to conserve power and have | 104 | * - there's no useful work to be done, so just try to conserve power and have | 
| @@ -77,8 +107,6 @@ static void default_idle(void) | |||
| 77 | */ | 107 | */ | 
| 78 | void cpu_idle(void) | 108 | void cpu_idle(void) | 
| 79 | { | 109 | { | 
| 80 | int cpu = smp_processor_id(); | ||
| 81 | |||
| 82 | /* endless idle loop with no priority at all */ | 110 | /* endless idle loop with no priority at all */ | 
| 83 | for (;;) { | 111 | for (;;) { | 
| 84 | while (!need_resched()) { | 112 | while (!need_resched()) { | 
| @@ -86,10 +114,13 @@ void cpu_idle(void) | |||
| 86 | 114 | ||
| 87 | smp_rmb(); | 115 | smp_rmb(); | 
| 88 | idle = pm_idle; | 116 | idle = pm_idle; | 
| 89 | if (!idle) | 117 | if (!idle) { | 
| 118 | #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) | ||
| 119 | idle = poll_idle; | ||
| 120 | #else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | ||
| 90 | idle = default_idle; | 121 | idle = default_idle; | 
| 91 | 122 | #endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | |
| 92 | irq_stat[cpu].idle_timestamp = jiffies; | 123 | } | 
| 93 | idle(); | 124 | idle(); | 
| 94 | } | 125 | } | 
| 95 | 126 | ||
| @@ -197,6 +228,7 @@ int copy_thread(unsigned long clone_flags, | |||
| 197 | unsigned long c_usp, unsigned long ustk_size, | 228 | unsigned long c_usp, unsigned long ustk_size, | 
| 198 | struct task_struct *p, struct pt_regs *kregs) | 229 | struct task_struct *p, struct pt_regs *kregs) | 
| 199 | { | 230 | { | 
| 231 | struct thread_info *ti = task_thread_info(p); | ||
| 200 | struct pt_regs *c_uregs, *c_kregs, *uregs; | 232 | struct pt_regs *c_uregs, *c_kregs, *uregs; | 
| 201 | unsigned long c_ksp; | 233 | unsigned long c_ksp; | 
| 202 | 234 | ||
| @@ -217,7 +249,7 @@ int copy_thread(unsigned long clone_flags, | |||
| 217 | 249 | ||
| 218 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ | 250 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ | 
| 219 | if (clone_flags & CLONE_SETTLS) | 251 | if (clone_flags & CLONE_SETTLS) | 
| 220 | c_uregs->e2 = __frame->d3; | 252 | c_uregs->e2 = current_frame()->d3; | 
| 221 | 253 | ||
| 222 | /* set up the return kernel frame if called from kernel_thread() */ | 254 | /* set up the return kernel frame if called from kernel_thread() */ | 
| 223 | c_kregs = c_uregs; | 255 | c_kregs = c_uregs; | 
| @@ -235,7 +267,7 @@ int copy_thread(unsigned long clone_flags, | |||
| 235 | } | 267 | } | 
| 236 | 268 | ||
| 237 | /* set up things up so the scheduler can start the new task */ | 269 | /* set up things up so the scheduler can start the new task */ | 
| 238 | p->thread.__frame = c_kregs; | 270 | ti->frame = c_kregs; | 
| 239 | p->thread.a3 = (unsigned long) c_kregs; | 271 | p->thread.a3 = (unsigned long) c_kregs; | 
| 240 | p->thread.sp = c_ksp; | 272 | p->thread.sp = c_ksp; | 
| 241 | p->thread.pc = (unsigned long) ret_from_fork; | 273 | p->thread.pc = (unsigned long) ret_from_fork; | 
| @@ -247,25 +279,26 @@ int copy_thread(unsigned long clone_flags, | |||
| 247 | 279 | ||
| 248 | /* | 280 | /* | 
| 249 | * clone a process | 281 | * clone a process | 
| 250 | * - tlsptr is retrieved by copy_thread() from __frame->d3 | 282 | * - tlsptr is retrieved by copy_thread() from current_frame()->d3 | 
| 251 | */ | 283 | */ | 
| 252 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | 284 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | 
| 253 | int __user *parent_tidptr, int __user *child_tidptr, | 285 | int __user *parent_tidptr, int __user *child_tidptr, | 
| 254 | int __user *tlsptr) | 286 | int __user *tlsptr) | 
| 255 | { | 287 | { | 
| 256 | return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0, | 288 | return do_fork(clone_flags, newsp ?: current_frame()->sp, | 
| 257 | parent_tidptr, child_tidptr); | 289 | current_frame(), 0, parent_tidptr, child_tidptr); | 
| 258 | } | 290 | } | 
| 259 | 291 | ||
| 260 | asmlinkage long sys_fork(void) | 292 | asmlinkage long sys_fork(void) | 
| 261 | { | 293 | { | 
| 262 | return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL); | 294 | return do_fork(SIGCHLD, current_frame()->sp, | 
| 295 | current_frame(), 0, NULL, NULL); | ||
| 263 | } | 296 | } | 
| 264 | 297 | ||
| 265 | asmlinkage long sys_vfork(void) | 298 | asmlinkage long sys_vfork(void) | 
| 266 | { | 299 | { | 
| 267 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame, | 300 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp, | 
| 268 | 0, NULL, NULL); | 301 | current_frame(), 0, NULL, NULL); | 
| 269 | } | 302 | } | 
| 270 | 303 | ||
| 271 | asmlinkage long sys_execve(const char __user *name, | 304 | asmlinkage long sys_execve(const char __user *name, | 
| @@ -279,7 +312,7 @@ asmlinkage long sys_execve(const char __user *name, | |||
| 279 | error = PTR_ERR(filename); | 312 | error = PTR_ERR(filename); | 
| 280 | if (IS_ERR(filename)) | 313 | if (IS_ERR(filename)) | 
| 281 | return error; | 314 | return error; | 
| 282 | error = do_execve(filename, argv, envp, __frame); | 315 | error = do_execve(filename, argv, envp, current_frame()); | 
| 283 | putname(filename); | 316 | putname(filename); | 
| 284 | return error; | 317 | return error; | 
| 285 | } | 318 | } | 
| diff --git a/arch/mn10300/kernel/profile.c b/arch/mn10300/kernel/profile.c index 20d7d0306b16..4f342f75d00c 100644 --- a/arch/mn10300/kernel/profile.c +++ b/arch/mn10300/kernel/profile.c | |||
| @@ -41,7 +41,7 @@ static __init int profile_init(void) | |||
| 41 | tmp = TM11ICR; | 41 | tmp = TM11ICR; | 
| 42 | 42 | ||
| 43 | printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n", | 43 | printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n", | 
| 44 | mn10300_ioclk / 8 / (TM11BR + 1)); | 44 | MN10300_IOCLK / 8 / (TM11BR + 1)); | 
| 45 | printk(KERN_INFO "Profile histogram stored %p-%p\n", | 45 | printk(KERN_INFO "Profile histogram stored %p-%p\n", | 
| 46 | prof_buffer, (u8 *)(prof_buffer + prof_len) - 1); | 46 | prof_buffer, (u8 *)(prof_buffer + prof_len) - 1); | 
| 47 | 47 | ||
| diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c index 4eef0e7224f6..e9e20f9a4dd3 100644 --- a/arch/mn10300/kernel/rtc.c +++ b/arch/mn10300/kernel/rtc.c | |||
| @@ -20,18 +20,22 @@ | |||
| 20 | DEFINE_SPINLOCK(rtc_lock); | 20 | DEFINE_SPINLOCK(rtc_lock); | 
| 21 | EXPORT_SYMBOL(rtc_lock); | 21 | EXPORT_SYMBOL(rtc_lock); | 
| 22 | 22 | ||
| 23 | /* time for RTC to update itself in ioclks */ | 23 | /* | 
| 24 | static unsigned long mn10300_rtc_update_period; | 24 | * Read the current RTC time | 
| 25 | 25 | */ | |
| 26 | void read_persistent_clock(struct timespec *ts) | 26 | void read_persistent_clock(struct timespec *ts) | 
| 27 | { | 27 | { | 
| 28 | struct rtc_time tm; | 28 | struct rtc_time tm; | 
| 29 | 29 | ||
| 30 | get_rtc_time(&tm); | 30 | get_rtc_time(&tm); | 
| 31 | 31 | ||
| 32 | ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
| 33 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 34 | ts->tv_nsec = 0; | 32 | ts->tv_nsec = 0; | 
| 33 | ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
| 34 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 35 | |||
| 36 | /* if rtc is way off in the past, set something reasonable */ | ||
| 37 | if (ts->tv_sec < 0) | ||
| 38 | ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0); | ||
| 35 | } | 39 | } | 
| 36 | 40 | ||
| 37 | /* | 41 | /* | 
| @@ -115,39 +119,14 @@ int update_persistent_clock(struct timespec now) | |||
| 115 | */ | 119 | */ | 
| 116 | void __init calibrate_clock(void) | 120 | void __init calibrate_clock(void) | 
| 117 | { | 121 | { | 
| 118 | unsigned long count0, counth, count1; | ||
| 119 | unsigned char status; | 122 | unsigned char status; | 
| 120 | 123 | ||
| 121 | /* make sure the RTC is running and is set to operate in 24hr mode */ | 124 | /* make sure the RTC is running and is set to operate in 24hr mode */ | 
| 122 | status = RTSRC; | 125 | status = RTSRC; | 
| 123 | RTCRB |= RTCRB_SET; | 126 | RTCRB |= RTCRB_SET; | 
| 124 | RTCRB |= RTCRB_TM_24HR; | 127 | RTCRB |= RTCRB_TM_24HR; | 
| 128 | RTCRB &= ~RTCRB_DM_BINARY; | ||
| 125 | RTCRA |= RTCRA_DVR; | 129 | RTCRA |= RTCRA_DVR; | 
| 126 | RTCRA &= ~RTCRA_DVR; | 130 | RTCRA &= ~RTCRA_DVR; | 
| 127 | RTCRB &= ~RTCRB_SET; | 131 | RTCRB &= ~RTCRB_SET; | 
| 128 | |||
| 129 | /* work out the clock speed by counting clock cycles between ends of | ||
| 130 | * the RTC update cycle - track the RTC through one complete update | ||
| 131 | * cycle (1 second) | ||
| 132 | */ | ||
| 133 | startup_timestamp_counter(); | ||
| 134 | |||
| 135 | while (!(RTCRA & RTCRA_UIP)) {} | ||
| 136 | while ((RTCRA & RTCRA_UIP)) {} | ||
| 137 | |||
| 138 | count0 = TMTSCBC; | ||
| 139 | |||
| 140 | while (!(RTCRA & RTCRA_UIP)) {} | ||
| 141 | |||
| 142 | counth = TMTSCBC; | ||
| 143 | |||
| 144 | while ((RTCRA & RTCRA_UIP)) {} | ||
| 145 | |||
| 146 | count1 = TMTSCBC; | ||
| 147 | |||
| 148 | shutdown_timestamp_counter(); | ||
| 149 | |||
| 150 | MN10300_TSCCLK = count0 - count1; /* the timers count down */ | ||
| 151 | mn10300_rtc_update_period = counth - count1; | ||
| 152 | MN10300_TSC_PER_HZ = MN10300_TSCCLK / HZ; | ||
| 153 | } | 132 | } | 
| diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c index d464affcba0e..9e7a3209a3e1 100644 --- a/arch/mn10300/kernel/setup.c +++ b/arch/mn10300/kernel/setup.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> | 
| 23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> | 
| 24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> | 
| 25 | #include <linux/cpu.h> | ||
| 25 | #include <asm/processor.h> | 26 | #include <asm/processor.h> | 
| 26 | #include <linux/console.h> | 27 | #include <linux/console.h> | 
| 27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> | 
| @@ -30,7 +31,6 @@ | |||
| 30 | #include <asm/io.h> | 31 | #include <asm/io.h> | 
| 31 | #include <asm/smp.h> | 32 | #include <asm/smp.h> | 
| 32 | #include <proc/proc.h> | 33 | #include <proc/proc.h> | 
| 33 | #include <asm/busctl-regs.h> | ||
| 34 | #include <asm/fpu.h> | 34 | #include <asm/fpu.h> | 
| 35 | #include <asm/sections.h> | 35 | #include <asm/sections.h> | 
| 36 | 36 | ||
| @@ -64,11 +64,13 @@ unsigned long memory_size; | |||
| 64 | struct thread_info *__current_ti = &init_thread_union.thread_info; | 64 | struct thread_info *__current_ti = &init_thread_union.thread_info; | 
| 65 | struct task_struct *__current = &init_task; | 65 | struct task_struct *__current = &init_task; | 
| 66 | 66 | ||
| 67 | #define mn10300_known_cpus 3 | 67 | #define mn10300_known_cpus 5 | 
| 68 | static const char *const mn10300_cputypes[] = { | 68 | static const char *const mn10300_cputypes[] = { | 
| 69 | "am33v1", | 69 | "am33-1", | 
| 70 | "am33v2", | 70 | "am33-2", | 
| 71 | "am34v1", | 71 | "am34-1", | 
| 72 | "am33-3", | ||
| 73 | "am34-2", | ||
| 72 | "unknown" | 74 | "unknown" | 
| 73 | }; | 75 | }; | 
| 74 | 76 | ||
| @@ -123,6 +125,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 123 | 125 | ||
| 124 | cpu_init(); | 126 | cpu_init(); | 
| 125 | unit_setup(); | 127 | unit_setup(); | 
| 128 | smp_init_cpus(); | ||
| 126 | parse_mem_cmdline(cmdline_p); | 129 | parse_mem_cmdline(cmdline_p); | 
| 127 | 130 | ||
| 128 | init_mm.start_code = (unsigned long)&_text; | 131 | init_mm.start_code = (unsigned long)&_text; | 
| @@ -179,57 +182,55 @@ void __init setup_arch(char **cmdline_p) | |||
| 179 | void __init cpu_init(void) | 182 | void __init cpu_init(void) | 
| 180 | { | 183 | { | 
| 181 | unsigned long cpurev = CPUREV, type; | 184 | unsigned long cpurev = CPUREV, type; | 
| 182 | unsigned long base, size; | ||
| 183 | 185 | ||
| 184 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | 186 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | 
| 185 | if (type > mn10300_known_cpus) | 187 | if (type > mn10300_known_cpus) | 
| 186 | type = mn10300_known_cpus; | 188 | type = mn10300_known_cpus; | 
| 187 | 189 | ||
| 188 | printk(KERN_INFO "Matsushita %s, rev %ld\n", | 190 | printk(KERN_INFO "Panasonic %s, rev %ld\n", | 
| 189 | mn10300_cputypes[type], | 191 | mn10300_cputypes[type], | 
| 190 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); | 192 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); | 
| 191 | 193 | ||
| 192 | /* determine the memory size and base from the memory controller regs */ | 194 | get_mem_info(&phys_memory_base, &memory_size); | 
| 193 | memory_size = 0; | 195 | phys_memory_end = phys_memory_base + memory_size; | 
| 194 | |||
| 195 | base = SDBASE(0); | ||
| 196 | if (base & SDBASE_CE) { | ||
| 197 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
| 198 | size = ~size + 1; | ||
| 199 | base &= SDBASE_CBA; | ||
| 200 | 196 | ||
| 201 | printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); | 197 | fpu_init_state(); | 
| 202 | memory_size += size; | 198 | } | 
| 203 | phys_memory_base = base; | ||
| 204 | } | ||
| 205 | 199 | ||
| 206 | base = SDBASE(1); | 200 | static struct cpu cpu_devices[NR_CPUS]; | 
| 207 | if (base & SDBASE_CE) { | ||
| 208 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
| 209 | size = ~size + 1; | ||
| 210 | base &= SDBASE_CBA; | ||
| 211 | 201 | ||
| 212 | printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); | 202 | static int __init topology_init(void) | 
| 213 | memory_size += size; | 203 | { | 
| 214 | if (phys_memory_base == 0) | 204 | int i; | 
| 215 | phys_memory_base = base; | ||
| 216 | } | ||
| 217 | 205 | ||
| 218 | phys_memory_end = phys_memory_base + memory_size; | 206 | for_each_present_cpu(i) | 
| 207 | register_cpu(&cpu_devices[i], i); | ||
| 219 | 208 | ||
| 220 | #ifdef CONFIG_FPU | 209 | return 0; | 
| 221 | fpu_init_state(); | ||
| 222 | #endif | ||
| 223 | } | 210 | } | 
| 224 | 211 | ||
| 212 | subsys_initcall(topology_init); | ||
| 213 | |||
| 225 | /* | 214 | /* | 
| 226 | * Get CPU information for use by the procfs. | 215 | * Get CPU information for use by the procfs. | 
| 227 | */ | 216 | */ | 
| 228 | static int show_cpuinfo(struct seq_file *m, void *v) | 217 | static int show_cpuinfo(struct seq_file *m, void *v) | 
| 229 | { | 218 | { | 
| 219 | #ifdef CONFIG_SMP | ||
| 220 | struct mn10300_cpuinfo *c = v; | ||
| 221 | unsigned long cpu_id = c - cpu_data; | ||
| 222 | unsigned long cpurev = c->type, type, icachesz, dcachesz; | ||
| 223 | #else /* CONFIG_SMP */ | ||
| 224 | unsigned long cpu_id = 0; | ||
| 230 | unsigned long cpurev = CPUREV, type, icachesz, dcachesz; | 225 | unsigned long cpurev = CPUREV, type, icachesz, dcachesz; | 
| 226 | #endif /* CONFIG_SMP */ | ||
| 231 | 227 | ||
| 232 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | 228 | #ifdef CONFIG_SMP | 
| 229 | if (!cpu_online(cpu_id)) | ||
| 230 | return 0; | ||
| 231 | #endif | ||
| 232 | |||
| 233 | type = (cpurev & CPUREV_TYPE) >> CPUREV_TYPE_S; | ||
| 233 | if (type > mn10300_known_cpus) | 234 | if (type > mn10300_known_cpus) | 
| 234 | type = mn10300_known_cpus; | 235 | type = mn10300_known_cpus; | 
| 235 | 236 | ||
| @@ -244,13 +245,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 244 | 1024; | 245 | 1024; | 
| 245 | 246 | ||
| 246 | seq_printf(m, | 247 | seq_printf(m, | 
| 247 | "processor : 0\n" | 248 | "processor : %ld\n" | 
| 248 | "vendor_id : Matsushita\n" | 249 | "vendor_id : " PROCESSOR_VENDOR_NAME "\n" | 
| 249 | "cpu core : %s\n" | 250 | "cpu core : %s\n" | 
| 250 | "cpu rev : %lu\n" | 251 | "cpu rev : %lu\n" | 
| 251 | "model name : " PROCESSOR_MODEL_NAME "\n" | 252 | "model name : " PROCESSOR_MODEL_NAME "\n" | 
| 252 | "icache size: %lu\n" | 253 | "icache size: %lu\n" | 
| 253 | "dcache size: %lu\n", | 254 | "dcache size: %lu\n", | 
| 255 | cpu_id, | ||
| 254 | mn10300_cputypes[type], | 256 | mn10300_cputypes[type], | 
| 255 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, | 257 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, | 
| 256 | icachesz, | 258 | icachesz, | 
| @@ -262,8 +264,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 262 | "bogomips : %lu.%02lu\n\n", | 264 | "bogomips : %lu.%02lu\n\n", | 
| 263 | MN10300_IOCLK / 1000000, | 265 | MN10300_IOCLK / 1000000, | 
| 264 | (MN10300_IOCLK / 10000) % 100, | 266 | (MN10300_IOCLK / 10000) % 100, | 
| 267 | #ifdef CONFIG_SMP | ||
| 268 | c->loops_per_jiffy / (500000 / HZ), | ||
| 269 | (c->loops_per_jiffy / (5000 / HZ)) % 100 | ||
| 270 | #else /* CONFIG_SMP */ | ||
| 265 | loops_per_jiffy / (500000 / HZ), | 271 | loops_per_jiffy / (500000 / HZ), | 
| 266 | (loops_per_jiffy / (5000 / HZ)) % 100 | 272 | (loops_per_jiffy / (5000 / HZ)) % 100 | 
| 273 | #endif /* CONFIG_SMP */ | ||
| 267 | ); | 274 | ); | 
| 268 | 275 | ||
| 269 | return 0; | 276 | return 0; | 
| diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index d4de05ab7864..690f4e9507d7 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c | |||
| @@ -91,7 +91,7 @@ asmlinkage long sys_sigaction(int sig, | |||
| 91 | */ | 91 | */ | 
| 92 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss) | 92 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss) | 
| 93 | { | 93 | { | 
| 94 | return do_sigaltstack(uss, uoss, __frame->sp); | 94 | return do_sigaltstack(uss, uoss, current_frame()->sp); | 
| 95 | } | 95 | } | 
| 96 | 96 | ||
| 97 | /* | 97 | /* | 
| @@ -156,10 +156,11 @@ badframe: | |||
| 156 | */ | 156 | */ | 
| 157 | asmlinkage long sys_sigreturn(void) | 157 | asmlinkage long sys_sigreturn(void) | 
| 158 | { | 158 | { | 
| 159 | struct sigframe __user *frame = (struct sigframe __user *) __frame->sp; | 159 | struct sigframe __user *frame; | 
| 160 | sigset_t set; | 160 | sigset_t set; | 
| 161 | long d0; | 161 | long d0; | 
| 162 | 162 | ||
| 163 | frame = (struct sigframe __user *) current_frame()->sp; | ||
| 163 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | 164 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | 
| 164 | goto badframe; | 165 | goto badframe; | 
| 165 | if (__get_user(set.sig[0], &frame->sc.oldmask)) | 166 | if (__get_user(set.sig[0], &frame->sc.oldmask)) | 
| @@ -176,7 +177,7 @@ asmlinkage long sys_sigreturn(void) | |||
| 176 | recalc_sigpending(); | 177 | recalc_sigpending(); | 
| 177 | spin_unlock_irq(¤t->sighand->siglock); | 178 | spin_unlock_irq(¤t->sighand->siglock); | 
| 178 | 179 | ||
| 179 | if (restore_sigcontext(__frame, &frame->sc, &d0)) | 180 | if (restore_sigcontext(current_frame(), &frame->sc, &d0)) | 
| 180 | goto badframe; | 181 | goto badframe; | 
| 181 | 182 | ||
| 182 | return d0; | 183 | return d0; | 
| @@ -191,11 +192,11 @@ badframe: | |||
| 191 | */ | 192 | */ | 
| 192 | asmlinkage long sys_rt_sigreturn(void) | 193 | asmlinkage long sys_rt_sigreturn(void) | 
| 193 | { | 194 | { | 
| 194 | struct rt_sigframe __user *frame = | 195 | struct rt_sigframe __user *frame; | 
| 195 | (struct rt_sigframe __user *) __frame->sp; | ||
| 196 | sigset_t set; | 196 | sigset_t set; | 
| 197 | unsigned long d0; | 197 | long d0; | 
| 198 | 198 | ||
| 199 | frame = (struct rt_sigframe __user *) current_frame()->sp; | ||
| 199 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | 200 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | 
| 200 | goto badframe; | 201 | goto badframe; | 
| 201 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 202 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 
| @@ -207,10 +208,11 @@ asmlinkage long sys_rt_sigreturn(void) | |||
| 207 | recalc_sigpending(); | 208 | recalc_sigpending(); | 
| 208 | spin_unlock_irq(¤t->sighand->siglock); | 209 | spin_unlock_irq(¤t->sighand->siglock); | 
| 209 | 210 | ||
| 210 | if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0)) | 211 | if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) | 
| 211 | goto badframe; | 212 | goto badframe; | 
| 212 | 213 | ||
| 213 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT) | 214 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, current_frame()->sp) == | 
| 215 | -EFAULT) | ||
| 214 | goto badframe; | 216 | goto badframe; | 
| 215 | 217 | ||
| 216 | return d0; | 218 | return d0; | 
| @@ -572,7 +574,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) | |||
| 572 | 574 | ||
| 573 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 575 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 
| 574 | clear_thread_flag(TIF_NOTIFY_RESUME); | 576 | clear_thread_flag(TIF_NOTIFY_RESUME); | 
| 575 | tracehook_notify_resume(__frame); | 577 | tracehook_notify_resume(current_frame()); | 
| 576 | if (current->replacement_session_keyring) | 578 | if (current->replacement_session_keyring) | 
| 577 | key_replace_session_keyring(); | 579 | key_replace_session_keyring(); | 
| 578 | } | 580 | } | 
| diff --git a/arch/mn10300/kernel/smp-low.S b/arch/mn10300/kernel/smp-low.S new file mode 100644 index 000000000000..72938cefc05e --- /dev/null +++ b/arch/mn10300/kernel/smp-low.S | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | /* SMP IPI low-level handler | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006-2007 Matsushita Electric Industrial Co., Ltd. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/sys.h> | ||
| 14 | #include <linux/linkage.h> | ||
| 15 | #include <asm/smp.h> | ||
| 16 | #include <asm/system.h> | ||
| 17 | #include <asm/thread_info.h> | ||
| 18 | #include <asm/cpu-regs.h> | ||
| 19 | #include <proc/smp-regs.h> | ||
| 20 | #include <asm/asm-offsets.h> | ||
| 21 | #include <asm/frame.inc> | ||
| 22 | |||
| 23 | .am33_2 | ||
| 24 | |||
| 25 | ############################################################################### | ||
| 26 | # | ||
| 27 | # IPI interrupt handler | ||
| 28 | # | ||
| 29 | ############################################################################### | ||
| 30 | .globl mn10300_low_ipi_handler | ||
| 31 | mn10300_low_ipi_handler: | ||
| 32 | add -4,sp | ||
| 33 | mov d0,(sp) | ||
| 34 | movhu (IAGR),d0 | ||
| 35 | and IAGR_GN,d0 | ||
| 36 | lsr 0x2,d0 | ||
| 37 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
| 38 | cmp FLUSH_CACHE_IPI,d0 | ||
| 39 | beq mn10300_flush_cache_ipi | ||
| 40 | #endif | ||
| 41 | cmp SMP_BOOT_IRQ,d0 | ||
| 42 | beq mn10300_smp_boot_ipi | ||
| 43 | /* OTHERS */ | ||
| 44 | mov (sp),d0 | ||
| 45 | add 4,sp | ||
| 46 | #ifdef CONFIG_GDBSTUB | ||
| 47 | jmp gdbstub_io_rx_handler | ||
| 48 | #else | ||
| 49 | jmp end | ||
| 50 | #endif | ||
| 51 | |||
| 52 | ############################################################################### | ||
| 53 | # | ||
| 54 | # Cache flush IPI interrupt handler | ||
| 55 | # | ||
| 56 | ############################################################################### | ||
| 57 | #ifdef CONFIG_MN10300_CACHE_ENABLED | ||
| 58 | mn10300_flush_cache_ipi: | ||
| 59 | mov (sp),d0 | ||
| 60 | add 4,sp | ||
| 61 | |||
| 62 | /* FLUSH_CACHE_IPI */ | ||
| 63 | add -4,sp | ||
| 64 | SAVE_ALL | ||
| 65 | mov GxICR_DETECT,d2 | ||
| 66 | movbu d2,(GxICR(FLUSH_CACHE_IPI)) # ACK the interrupt | ||
| 67 | movhu (GxICR(FLUSH_CACHE_IPI)),d2 | ||
| 68 | call smp_cache_interrupt[],0 | ||
| 69 | RESTORE_ALL | ||
| 70 | jmp end | ||
| 71 | #endif | ||
| 72 | |||
| 73 | ############################################################################### | ||
| 74 | # | ||
| 75 | # SMP boot CPU IPI interrupt handler | ||
| 76 | # | ||
| 77 | ############################################################################### | ||
| 78 | mn10300_smp_boot_ipi: | ||
| 79 | /* clear interrupt */ | ||
| 80 | movhu (GxICR(SMP_BOOT_IRQ)),d0 | ||
| 81 | and ~GxICR_REQUEST,d0 | ||
| 82 | movhu d0,(GxICR(SMP_BOOT_IRQ)) | ||
| 83 | mov (sp),d0 | ||
| 84 | add 4,sp | ||
| 85 | |||
| 86 | # get stack | ||
| 87 | mov (CPUID),a0 | ||
| 88 | add -1,a0 | ||
| 89 | add a0,a0 | ||
| 90 | add a0,a0 | ||
| 91 | mov (start_stack,a0),a0 | ||
| 92 | mov a0,sp | ||
| 93 | jmp initialize_secondary | ||
| 94 | |||
| 95 | |||
| 96 | # Jump here after RTI to suppress the icache lookahead | ||
| 97 | end: | ||
| diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c new file mode 100644 index 000000000000..0dcd1c686ba8 --- /dev/null +++ b/arch/mn10300/kernel/smp.c | |||
| @@ -0,0 +1,1152 @@ | |||
| 1 | /* SMP support routines. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006-2008 Panasonic Corporation | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/jiffies.h> | ||
| 20 | #include <linux/cpumask.h> | ||
| 21 | #include <linux/err.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/delay.h> | ||
| 24 | #include <linux/sched.h> | ||
| 25 | #include <linux/profile.h> | ||
| 26 | #include <linux/smp.h> | ||
| 27 | #include <asm/tlbflush.h> | ||
| 28 | #include <asm/system.h> | ||
| 29 | #include <asm/bitops.h> | ||
| 30 | #include <asm/processor.h> | ||
| 31 | #include <asm/bug.h> | ||
| 32 | #include <asm/exceptions.h> | ||
| 33 | #include <asm/hardirq.h> | ||
| 34 | #include <asm/fpu.h> | ||
| 35 | #include <asm/mmu_context.h> | ||
| 36 | #include <asm/thread_info.h> | ||
| 37 | #include <asm/cpu-regs.h> | ||
| 38 | #include <asm/intctl-regs.h> | ||
| 39 | #include "internal.h" | ||
| 40 | |||
| 41 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 42 | #include <linux/cpu.h> | ||
| 43 | #include <asm/cacheflush.h> | ||
| 44 | |||
| 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 */ | ||
| diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S index 630aad71b946..9074d0fb8788 100644 --- a/arch/mn10300/kernel/switch_to.S +++ b/arch/mn10300/kernel/switch_to.S | |||
| @@ -15,6 +15,9 @@ | |||
| 15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> | 
| 16 | #include <asm/thread_info.h> | 16 | #include <asm/thread_info.h> | 
| 17 | #include <asm/cpu-regs.h> | 17 | #include <asm/cpu-regs.h> | 
| 18 | #ifdef CONFIG_SMP | ||
| 19 | #include <proc/smp-regs.h> | ||
| 20 | #endif /* CONFIG_SMP */ | ||
| 18 | 21 | ||
| 19 | .text | 22 | .text | 
| 20 | 23 | ||
| @@ -35,8 +38,6 @@ ENTRY(__switch_to) | |||
| 35 | mov d1,a1 | 38 | mov d1,a1 | 
| 36 | 39 | ||
| 37 | # save prev context | 40 | # save prev context | 
| 38 | mov (__frame),d0 | ||
| 39 | mov d0,(THREAD_FRAME,a0) | ||
| 40 | mov __switch_back,d0 | 41 | mov __switch_back,d0 | 
| 41 | mov d0,(THREAD_PC,a0) | 42 | mov d0,(THREAD_PC,a0) | 
| 42 | mov sp,a2 | 43 | mov sp,a2 | 
| @@ -58,8 +59,6 @@ ENTRY(__switch_to) | |||
| 58 | mov a2,e2 | 59 | mov a2,e2 | 
| 59 | #endif | 60 | #endif | 
| 60 | 61 | ||
| 61 | mov (THREAD_FRAME,a1),a2 | ||
| 62 | mov a2,(__frame) | ||
| 63 | mov (THREAD_PC,a1),a2 | 62 | mov (THREAD_PC,a1),a2 | 
| 64 | mov d2,d0 # for ret_from_fork | 63 | mov d2,d0 # for ret_from_fork | 
| 65 | mov d0,a0 # for __switch_to | 64 | mov d0,a0 # for __switch_to | 
| diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 8f7f6d22783d..f860a340acc9 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c | |||
| @@ -17,29 +17,18 @@ | |||
| 17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> | 
| 18 | #include <linux/profile.h> | 18 | #include <linux/profile.h> | 
| 19 | #include <linux/cnt32_to_63.h> | 19 | #include <linux/cnt32_to_63.h> | 
| 20 | #include <linux/clocksource.h> | ||
| 21 | #include <linux/clockchips.h> | ||
| 20 | #include <asm/irq.h> | 22 | #include <asm/irq.h> | 
| 21 | #include <asm/div64.h> | 23 | #include <asm/div64.h> | 
| 22 | #include <asm/processor.h> | 24 | #include <asm/processor.h> | 
| 23 | #include <asm/intctl-regs.h> | 25 | #include <asm/intctl-regs.h> | 
| 24 | #include <asm/rtc.h> | 26 | #include <asm/rtc.h> | 
| 25 | 27 | #include "internal.h" | |
| 26 | #ifdef CONFIG_MN10300_RTC | ||
| 27 | unsigned long mn10300_ioclk; /* system I/O clock frequency */ | ||
| 28 | unsigned long mn10300_iobclk; /* system I/O clock frequency */ | ||
| 29 | unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */ | ||
| 30 | #endif /* CONFIG_MN10300_RTC */ | ||
| 31 | 28 | ||
| 32 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time | 29 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time | 
| 33 | * interrupt occurred */ | 30 | * interrupt occurred */ | 
| 34 | 31 | ||
| 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 | |||
| 43 | static unsigned long sched_clock_multiplier; | 32 | static unsigned long sched_clock_multiplier; | 
| 44 | 33 | ||
| 45 | /* | 34 | /* | 
| @@ -54,9 +43,12 @@ unsigned long long sched_clock(void) | |||
| 54 | unsigned long tsc, tmp; | 43 | unsigned long tsc, tmp; | 
| 55 | unsigned product[3]; /* 96-bit intermediate value */ | 44 | unsigned product[3]; /* 96-bit intermediate value */ | 
| 56 | 45 | ||
| 46 | /* cnt32_to_63() is not safe with preemption */ | ||
| 47 | preempt_disable(); | ||
| 48 | |||
| 57 | /* read the TSC value | 49 | /* read the TSC value | 
| 58 | */ | 50 | */ | 
| 59 | tsc = 0 - get_cycles(); /* get_cycles() counts down */ | 51 | tsc = get_cycles(); | 
| 60 | 52 | ||
| 61 | /* expand to 64-bits. | 53 | /* expand to 64-bits. | 
| 62 | * - sched_clock() must be called once a minute or better or the | 54 | * - sched_clock() must be called once a minute or better or the | 
| @@ -64,6 +56,8 @@ unsigned long long sched_clock(void) | |||
| 64 | */ | 56 | */ | 
| 65 | tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; | 57 | tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; | 
| 66 | 58 | ||
| 59 | preempt_enable(); | ||
| 60 | |||
| 67 | /* scale the 64-bit TSC value to a nanosecond value via a 96-bit | 61 | /* scale the 64-bit TSC value to a nanosecond value via a 96-bit | 
| 68 | * intermediate | 62 | * intermediate | 
| 69 | */ | 63 | */ | 
| @@ -90,6 +84,20 @@ static void __init mn10300_sched_clock_init(void) | |||
| 90 | __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); | 84 | __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); | 
| 91 | } | 85 | } | 
| 92 | 86 | ||
| 87 | /** | ||
| 88 | * local_timer_interrupt - Local timer interrupt handler | ||
| 89 | * | ||
| 90 | * Handle local timer interrupts for this CPU. They may have been propagated | ||
| 91 | * to this CPU from the CPU that actually gets them by way of an IPI. | ||
| 92 | */ | ||
| 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 | ||
| 93 | /* | 101 | /* | 
| 94 | * advance the kernel's time keeping clocks (xtime and jiffies) | 102 | * advance the kernel's time keeping clocks (xtime and jiffies) | 
| 95 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time | 103 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time | 
| @@ -98,27 +106,73 @@ static void __init mn10300_sched_clock_init(void) | |||
| 98 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 106 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 
| 99 | { | 107 | { | 
| 100 | unsigned tsc, elapse; | 108 | unsigned tsc, elapse; | 
| 109 | irqreturn_t ret; | ||
| 101 | 110 | ||
| 102 | write_seqlock(&xtime_lock); | 111 | write_seqlock(&xtime_lock); | 
| 103 | 112 | ||
| 104 | while (tsc = get_cycles(), | 113 | while (tsc = get_cycles(), | 
| 105 | elapse = mn10300_last_tsc - tsc, /* time elapsed since last | 114 | elapse = tsc - mn10300_last_tsc, /* time elapsed since last | 
| 106 | * tick */ | 115 | * tick */ | 
| 107 | elapse > MN10300_TSC_PER_HZ | 116 | elapse > MN10300_TSC_PER_HZ | 
| 108 | ) { | 117 | ) { | 
| 109 | mn10300_last_tsc -= MN10300_TSC_PER_HZ; | 118 | mn10300_last_tsc += MN10300_TSC_PER_HZ; | 
| 110 | 119 | ||
| 111 | /* advance the kernel's time tracking system */ | 120 | /* advance the kernel's time tracking system */ | 
| 112 | profile_tick(CPU_PROFILING); | ||
| 113 | do_timer(1); | 121 | do_timer(1); | 
| 114 | } | 122 | } | 
| 115 | 123 | ||
| 116 | write_sequnlock(&xtime_lock); | 124 | write_sequnlock(&xtime_lock); | 
| 117 | 125 | ||
| 118 | update_process_times(user_mode(get_irq_regs())); | 126 | ret = local_timer_interrupt(); | 
| 127 | #ifdef CONFIG_SMP | ||
| 128 | send_IPI_allbutself(LOCAL_TIMER_IPI); | ||
| 129 | #endif | ||
| 130 | return ret; | ||
| 131 | } | ||
| 119 | 132 | ||
| 120 | return IRQ_HANDLED; | 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; | ||
| 121 | } | 155 | } | 
| 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 | ||
| 122 | 176 | ||
| 123 | /* | 177 | /* | 
| 124 | * initialise the various timers used by the main part of the kernel | 178 | * initialise the various timers used by the main part of the kernel | 
| @@ -131,21 +185,25 @@ void __init time_init(void) | |||
| 131 | */ | 185 | */ | 
| 132 | TMPSCNT |= TMPSCNT_ENABLE; | 186 | TMPSCNT |= TMPSCNT_ENABLE; | 
| 133 | 187 | ||
| 188 | #ifdef CONFIG_GENERIC_TIME | ||
| 189 | init_clocksource(); | ||
| 190 | #else | ||
| 134 | startup_timestamp_counter(); | 191 | startup_timestamp_counter(); | 
| 192 | #endif | ||
| 135 | 193 | ||
| 136 | printk(KERN_INFO | 194 | printk(KERN_INFO | 
| 137 | "timestamp counter I/O clock running at %lu.%02lu" | 195 | "timestamp counter I/O clock running at %lu.%02lu" | 
| 138 | " (calibrated against RTC)\n", | 196 | " (calibrated against RTC)\n", | 
| 139 | MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); | 197 | MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); | 
| 140 | 198 | ||
| 141 | mn10300_last_tsc = TMTSCBC; | 199 | mn10300_last_tsc = read_timestamp_counter(); | 
| 142 | |||
| 143 | /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */ | ||
| 144 | setup_irq(TMJCIRQ, &timer_irq); | ||
| 145 | 200 | ||
| 146 | set_intr_level(TMJCIRQ, TMJCICR_LEVEL); | 201 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | 
| 147 | 202 | init_clockevents(); | |
| 148 | startup_jiffies_counter(); | 203 | #else | 
| 204 | reload_jiffies_counter(MN10300_JC_PER_HZ - 1); | ||
| 205 | setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL); | ||
| 206 | #endif | ||
| 149 | 207 | ||
| 150 | #ifdef CONFIG_MN10300_WD_TIMER | 208 | #ifdef CONFIG_MN10300_WD_TIMER | 
| 151 | /* start the watchdog timer */ | 209 | /* start the watchdog timer */ | 
| diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index 91365adba4f5..b90c3f160c77 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c | |||
| @@ -45,9 +45,6 @@ | |||
| 45 | #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" | 45 | #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" | 
| 46 | #endif | 46 | #endif | 
| 47 | 47 | ||
| 48 | struct pt_regs *__frame; /* current frame pointer */ | ||
| 49 | EXPORT_SYMBOL(__frame); | ||
| 50 | |||
| 51 | int kstack_depth_to_print = 24; | 48 | int kstack_depth_to_print = 24; | 
| 52 | 49 | ||
| 53 | spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); | 50 | spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); | 
| @@ -101,7 +98,6 @@ DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); | |||
| 101 | DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); | 98 | DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); | 
| 102 | DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); | 99 | DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); | 
| 103 | DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); | 100 | DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); | 
| 104 | DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC); | ||
| 105 | 101 | ||
| 106 | DO_ERROR(SIGTRAP, | 102 | DO_ERROR(SIGTRAP, | 
| 107 | #ifndef CONFIG_MN10300_USING_JTAG | 103 | #ifndef CONFIG_MN10300_USING_JTAG | 
| @@ -222,11 +218,14 @@ void show_registers_only(struct pt_regs *regs) | |||
| 222 | printk(KERN_EMERG "threadinfo=%p task=%p)\n", | 218 | printk(KERN_EMERG "threadinfo=%p task=%p)\n", | 
| 223 | current_thread_info(), current); | 219 | current_thread_info(), current); | 
| 224 | 220 | ||
| 225 | if ((unsigned long) current >= 0x90000000UL && | 221 | if ((unsigned long) current >= PAGE_OFFSET && | 
| 226 | (unsigned long) current < 0x94000000UL) | 222 | (unsigned long) current < (unsigned long)high_memory) | 
| 227 | printk(KERN_EMERG "Process %s (pid: %d)\n", | 223 | printk(KERN_EMERG "Process %s (pid: %d)\n", | 
| 228 | current->comm, current->pid); | 224 | current->comm, current->pid); | 
| 229 | 225 | ||
| 226 | #ifdef CONFIG_SMP | ||
| 227 | printk(KERN_EMERG "CPUID: %08x\n", CPUID); | ||
| 228 | #endif | ||
| 230 | printk(KERN_EMERG "CPUP: %04hx\n", CPUP); | 229 | printk(KERN_EMERG "CPUP: %04hx\n", CPUP); | 
| 231 | printk(KERN_EMERG "TBR: %08x\n", TBR); | 230 | printk(KERN_EMERG "TBR: %08x\n", TBR); | 
| 232 | printk(KERN_EMERG "DEAR: %08x\n", DEAR); | 231 | printk(KERN_EMERG "DEAR: %08x\n", DEAR); | 
| @@ -522,8 +521,12 @@ void __init set_intr_stub(enum exception_code code, void *handler) | |||
| 522 | { | 521 | { | 
| 523 | unsigned long addr; | 522 | unsigned long addr; | 
| 524 | u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); | 523 | u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); | 
| 524 | unsigned long flags; | ||
| 525 | 525 | ||
| 526 | addr = (unsigned long) handler - (unsigned long) vector; | 526 | addr = (unsigned long) handler - (unsigned long) vector; | 
| 527 | |||
| 528 | flags = arch_local_cli_save(); | ||
| 529 | |||
| 527 | vector[0] = 0xdc; /* JMP handler */ | 530 | vector[0] = 0xdc; /* JMP handler */ | 
| 528 | vector[1] = addr; | 531 | vector[1] = addr; | 
| 529 | vector[2] = addr >> 8; | 532 | vector[2] = addr >> 8; | 
| @@ -533,30 +536,12 @@ void __init set_intr_stub(enum exception_code code, void *handler) | |||
| 533 | vector[6] = 0xcb; | 536 | vector[6] = 0xcb; | 
| 534 | vector[7] = 0xcb; | 537 | vector[7] = 0xcb; | 
| 535 | 538 | ||
| 536 | mn10300_dcache_flush_inv(); | 539 | arch_local_irq_restore(flags); | 
| 537 | mn10300_icache_inv(); | ||
| 538 | } | ||
| 539 | |||
| 540 | /* | ||
| 541 | * set an interrupt stub to invoke the JTAG unit and then jump to a handler | ||
| 542 | */ | ||
| 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; | ||
| 557 | 540 | ||
| 541 | #ifndef CONFIG_MN10300_CACHE_SNOOP | ||
| 558 | mn10300_dcache_flush_inv(); | 542 | mn10300_dcache_flush_inv(); | 
| 559 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 8); | 543 | mn10300_icache_inv(); | 
| 544 | #endif | ||
| 560 | } | 545 | } | 
| 561 | 546 | ||
| 562 | /* | 547 | /* | 
| @@ -581,7 +566,6 @@ void __init trap_init(void) | |||
| 581 | set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); | 566 | set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); | 
| 582 | set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); | 567 | set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); | 
| 583 | set_excp_vector(EXCEP_DATINSACC, insn_acc_error); | 568 | set_excp_vector(EXCEP_DATINSACC, insn_acc_error); | 
| 584 | set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled); | ||
| 585 | set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); | 569 | set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); | 
| 586 | set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); | 570 | set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); | 
| 587 | 571 | ||
| diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c index 440a7dcbf87b..a66c6cdaf442 100644 --- a/arch/mn10300/lib/bitops.c +++ b/arch/mn10300/lib/bitops.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | /* | 15 | /* | 
| 16 | * try flipping a bit using BSET and BCLR | 16 | * try flipping a bit using BSET and BCLR | 
| 17 | */ | 17 | */ | 
| 18 | void change_bit(int nr, volatile void *addr) | 18 | void change_bit(unsigned long nr, volatile void *addr) | 
| 19 | { | 19 | { | 
| 20 | if (test_bit(nr, addr)) | 20 | if (test_bit(nr, addr)) | 
| 21 | goto try_clear_bit; | 21 | goto try_clear_bit; | 
| @@ -34,7 +34,7 @@ try_clear_bit: | |||
| 34 | /* | 34 | /* | 
| 35 | * try flipping a bit using BSET and BCLR and returning the old value | 35 | * try flipping a bit using BSET and BCLR and returning the old value | 
| 36 | */ | 36 | */ | 
| 37 | int test_and_change_bit(int nr, volatile void *addr) | 37 | int test_and_change_bit(unsigned long nr, volatile void *addr) | 
| 38 | { | 38 | { | 
| 39 | if (test_bit(nr, addr)) | 39 | if (test_bit(nr, addr)) | 
| 40 | goto try_clear_bit; | 40 | goto try_clear_bit; | 
| diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c index fdf6f710f94e..8e7ceb8ba33d 100644 --- a/arch/mn10300/lib/delay.c +++ b/arch/mn10300/lib/delay.c | |||
| @@ -38,14 +38,14 @@ EXPORT_SYMBOL(__delay); | |||
| 38 | */ | 38 | */ | 
| 39 | void __udelay(unsigned long usecs) | 39 | void __udelay(unsigned long usecs) | 
| 40 | { | 40 | { | 
| 41 | signed long ioclk, stop; | 41 | unsigned long start, stop, cnt; | 
| 42 | 42 | ||
| 43 | /* usecs * CLK / 1E6 */ | 43 | /* usecs * CLK / 1E6 */ | 
| 44 | stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000); | 44 | stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000); | 
| 45 | stop = TMTSCBC - stop; | 45 | start = TMTSCBC; | 
| 46 | 46 | ||
| 47 | do { | 47 | do { | 
| 48 | ioclk = TMTSCBC; | 48 | cnt = start - TMTSCBC; | 
| 49 | } while (stop < ioclk); | 49 | } while (cnt < stop); | 
| 50 | } | 50 | } | 
| 51 | EXPORT_SYMBOL(__udelay); | 51 | EXPORT_SYMBOL(__udelay); | 
| diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S index e138994e1667..1d27bba0cd8f 100644 --- a/arch/mn10300/lib/do_csum.S +++ b/arch/mn10300/lib/do_csum.S | |||
| @@ -10,26 +10,25 @@ | |||
| 10 | */ | 10 | */ | 
| 11 | #include <asm/cache.h> | 11 | #include <asm/cache.h> | 
| 12 | 12 | ||
| 13 | .section .text | 13 | .section .text | 
| 14 | .balign L1_CACHE_BYTES | 14 | .balign L1_CACHE_BYTES | 
| 15 | 15 | ||
| 16 | ############################################################################### | 16 | ############################################################################### | 
| 17 | # | 17 | # | 
| 18 | # unsigned int do_csum(const unsigned char *buff, size_t len) | 18 | # unsigned int do_csum(const unsigned char *buff, int len) | 
| 19 | # | 19 | # | 
| 20 | ############################################################################### | 20 | ############################################################################### | 
| 21 | .globl do_csum | 21 | .globl do_csum | 
| 22 | .type do_csum,@function | 22 | .type do_csum,@function | 
| 23 | do_csum: | 23 | do_csum: | 
| 24 | movm [d2,d3],(sp) | 24 | movm [d2,d3],(sp) | 
| 25 | mov d0,(12,sp) | ||
| 26 | mov d1,(16,sp) | ||
| 27 | mov d1,d2 # count | 25 | mov d1,d2 # count | 
| 28 | mov d0,a0 # buff | 26 | mov d0,a0 # buff | 
| 27 | mov a0,a1 | ||
| 29 | clr d1 # accumulator | 28 | clr d1 # accumulator | 
| 30 | 29 | ||
| 31 | cmp +0,d2 | 30 | cmp +0,d2 | 
| 32 | beq do_csum_done # return if zero-length buffer | 31 | ble do_csum_done # check for zero length or negative | 
| 33 | 32 | ||
| 34 | # 4-byte align the buffer pointer | 33 | # 4-byte align the buffer pointer | 
| 35 | btst +3,a0 | 34 | btst +3,a0 | 
| @@ -41,17 +40,15 @@ do_csum: | |||
| 41 | inc a0 | 40 | inc a0 | 
| 42 | asl +8,d0 | 41 | asl +8,d0 | 
| 43 | add d0,d1 | 42 | add d0,d1 | 
| 44 | addc +0,d1 | ||
| 45 | add -1,d2 | 43 | add -1,d2 | 
| 46 | do_csum_addr_not_odd: | ||
| 47 | 44 | ||
| 45 | do_csum_addr_not_odd: | ||
| 48 | cmp +2,d2 | 46 | cmp +2,d2 | 
| 49 | bcs do_csum_fewer_than_4 | 47 | bcs do_csum_fewer_than_4 | 
| 50 | btst +2,a0 | 48 | btst +2,a0 | 
| 51 | beq do_csum_now_4b_aligned | 49 | beq do_csum_now_4b_aligned | 
| 52 | movhu (a0+),d0 | 50 | movhu (a0+),d0 | 
| 53 | add d0,d1 | 51 | add d0,d1 | 
| 54 | addc +0,d1 | ||
| 55 | add -2,d2 | 52 | add -2,d2 | 
| 56 | cmp +4,d2 | 53 | cmp +4,d2 | 
| 57 | bcs do_csum_fewer_than_4 | 54 | bcs do_csum_fewer_than_4 | 
| @@ -66,20 +63,20 @@ do_csum_now_4b_aligned: | |||
| 66 | 63 | ||
| 67 | do_csum_loop: | 64 | do_csum_loop: | 
| 68 | mov (a0+),d0 | 65 | mov (a0+),d0 | 
| 69 | add d0,d1 | ||
| 70 | mov (a0+),e0 | 66 | mov (a0+),e0 | 
| 71 | addc e0,d1 | ||
| 72 | mov (a0+),e1 | 67 | mov (a0+),e1 | 
| 73 | addc e1,d1 | ||
| 74 | mov (a0+),e3 | 68 | mov (a0+),e3 | 
| 69 | add d0,d1 | ||
| 70 | addc e0,d1 | ||
| 71 | addc e1,d1 | ||
| 75 | addc e3,d1 | 72 | addc e3,d1 | 
| 76 | mov (a0+),d0 | 73 | mov (a0+),d0 | 
| 77 | addc d0,d1 | ||
| 78 | mov (a0+),e0 | 74 | mov (a0+),e0 | 
| 79 | addc e0,d1 | ||
| 80 | mov (a0+),e1 | 75 | mov (a0+),e1 | 
| 81 | addc e1,d1 | ||
| 82 | mov (a0+),e3 | 76 | mov (a0+),e3 | 
| 77 | addc d0,d1 | ||
| 78 | addc e0,d1 | ||
| 79 | addc e1,d1 | ||
| 83 | addc e3,d1 | 80 | addc e3,d1 | 
| 84 | addc +0,d1 | 81 | addc +0,d1 | 
| 85 | 82 | ||
| @@ -94,12 +91,12 @@ do_csum_remainder: | |||
| 94 | cmp +16,d2 | 91 | cmp +16,d2 | 
| 95 | bcs do_csum_fewer_than_16 | 92 | bcs do_csum_fewer_than_16 | 
| 96 | mov (a0+),d0 | 93 | mov (a0+),d0 | 
| 97 | add d0,d1 | ||
| 98 | mov (a0+),e0 | 94 | mov (a0+),e0 | 
| 99 | addc e0,d1 | ||
| 100 | mov (a0+),e1 | 95 | mov (a0+),e1 | 
| 101 | addc e1,d1 | ||
| 102 | mov (a0+),e3 | 96 | mov (a0+),e3 | 
| 97 | add d0,d1 | ||
| 98 | addc e0,d1 | ||
| 99 | addc e1,d1 | ||
| 103 | addc e3,d1 | 100 | addc e3,d1 | 
| 104 | addc +0,d1 | 101 | addc +0,d1 | 
| 105 | add -16,d2 | 102 | add -16,d2 | 
| @@ -131,9 +128,9 @@ do_csum_fewer_than_4: | |||
| 131 | xor_cmp d0,d0,+2,d2 | 128 | xor_cmp d0,d0,+2,d2 | 
| 132 | bcs do_csum_fewer_than_2 | 129 | bcs do_csum_fewer_than_2 | 
| 133 | movhu (a0+),d0 | 130 | movhu (a0+),d0 | 
| 134 | do_csum_fewer_than_2: | ||
| 135 | and +1,d2 | 131 | and +1,d2 | 
| 136 | beq do_csum_add_last_bit | 132 | beq do_csum_add_last_bit | 
| 133 | do_csum_fewer_than_2: | ||
| 137 | movbu (a0),d3 | 134 | movbu (a0),d3 | 
| 138 | add d3,d0 | 135 | add d3,d0 | 
| 139 | do_csum_add_last_bit: | 136 | do_csum_add_last_bit: | 
| @@ -142,21 +139,19 @@ do_csum_add_last_bit: | |||
| 142 | 139 | ||
| 143 | do_csum_done: | 140 | do_csum_done: | 
| 144 | # compress the checksum down to 16 bits | 141 | # compress the checksum down to 16 bits | 
| 145 | mov +0xffff0000,d2 | 142 | mov +0xffff0000,d0 | 
| 146 | and d1,d2 | 143 | and d1,d0 | 
| 147 | asl +16,d1 | 144 | asl +16,d1 | 
| 148 | add d2,d1,d0 | 145 | add d1,d0 | 
| 149 | addc +0xffff,d0 | 146 | addc +0xffff,d0 | 
| 150 | lsr +16,d0 | 147 | lsr +16,d0 | 
| 151 | 148 | ||
| 152 | # flip the halves of the word result if the buffer was oddly aligned | 149 | # flip the halves of the word result if the buffer was oddly aligned | 
| 153 | mov (12,sp),d1 | 150 | and +1,a1 | 
| 154 | and +1,d1 | ||
| 155 | beq do_csum_not_oddly_aligned | 151 | beq do_csum_not_oddly_aligned | 
| 156 | swaph d0,d0 # exchange bits 15:8 with 7:0 | 152 | swaph d0,d0 # exchange bits 15:8 with 7:0 | 
| 157 | 153 | ||
| 158 | do_csum_not_oddly_aligned: | 154 | do_csum_not_oddly_aligned: | 
| 159 | ret [d2,d3],8 | 155 | ret [d2,d3],8 | 
| 160 | 156 | ||
| 161 | do_csum_end: | 157 | .size do_csum, .-do_csum | 
| 162 | .size do_csum, do_csum_end-do_csum | ||
| diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache new file mode 100644 index 000000000000..c4fd923a55a0 --- /dev/null +++ b/arch/mn10300/mm/Kconfig.cache | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | # | ||
| 2 | # MN10300 CPU cache options | ||
| 3 | # | ||
| 4 | |||
| 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. | ||
| diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index 1557277fbc5c..203fee23f7d7 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile | |||
| @@ -2,11 +2,21 @@ | |||
| 2 | # Makefile for the MN10300-specific memory management code | 2 | # Makefile for the MN10300-specific memory management code | 
| 3 | # | 3 | # | 
| 4 | 4 | ||
| 5 | cacheflush-y := cache.o cache-mn10300.o | 5 | cache-smp-wback-$(CONFIG_MN10300_CACHE_WBACK) := cache-smp-flush.o | 
| 6 | cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.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 | ||
| 7 | 15 | ||
| 8 | cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o | 16 | cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o | 
| 9 | 17 | ||
| 10 | obj-y := \ | 18 | obj-y := \ | 
| 11 | init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \ | 19 | init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \ | 
| 12 | misalignment.o dma-alloc.o $(cacheflush-y) | 20 | misalignment.o dma-alloc.o $(cacheflush-y) | 
| 21 | |||
| 22 | obj-$(CONFIG_SMP) += tlb-smp.o | ||
| diff --git a/arch/mn10300/mm/cache-flush-by-reg.S b/arch/mn10300/mm/cache-flush-by-reg.S new file mode 100644 index 000000000000..1dcae0211671 --- /dev/null +++ b/arch/mn10300/mm/cache-flush-by-reg.S | |||
| @@ -0,0 +1,308 @@ | |||
| 1 | /* MN10300 CPU core caching routines, using indirect regs on cache controller | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sys.h> | ||
| 13 | #include <linux/linkage.h> | ||
| 14 | #include <asm/smp.h> | ||
| 15 | #include <asm/page.h> | ||
| 16 | #include <asm/cache.h> | ||
| 17 | #include <asm/irqflags.h> | ||
| 18 | |||
| 19 | .am33_2 | ||
| 20 | |||
| 21 | #ifndef CONFIG_SMP | ||
| 22 | .globl mn10300_dcache_flush | ||
| 23 | .globl mn10300_dcache_flush_page | ||
| 24 | .globl mn10300_dcache_flush_range | ||
| 25 | .globl mn10300_dcache_flush_range2 | ||
| 26 | .globl mn10300_dcache_flush_inv | ||
| 27 | .globl mn10300_dcache_flush_inv_page | ||
| 28 | .globl mn10300_dcache_flush_inv_range | ||
| 29 | .globl mn10300_dcache_flush_inv_range2 | ||
| 30 | |||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S new file mode 100644 index 000000000000..5cd6a27dd63e --- /dev/null +++ b/arch/mn10300/mm/cache-flush-by-tag.S | |||
| @@ -0,0 +1,251 @@ | |||
| 1 | /* MN10300 CPU core caching routines, using direct tag flushing | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sys.h> | ||
| 13 | #include <linux/linkage.h> | ||
| 14 | #include <asm/smp.h> | ||
| 15 | #include <asm/page.h> | ||
| 16 | #include <asm/cache.h> | ||
| 17 | #include <asm/irqflags.h> | ||
| 18 | |||
| 19 | .am33_2 | ||
| 20 | |||
| 21 | #ifndef CONFIG_SMP | ||
| 22 | .globl mn10300_dcache_flush | ||
| 23 | .globl mn10300_dcache_flush_page | ||
| 24 | .globl mn10300_dcache_flush_range | ||
| 25 | .globl mn10300_dcache_flush_range2 | ||
| 26 | .globl mn10300_dcache_flush_inv | ||
| 27 | .globl mn10300_dcache_flush_inv_page | ||
| 28 | .globl mn10300_dcache_flush_inv_range | ||
| 29 | .globl mn10300_dcache_flush_inv_range2 | ||
| 30 | |||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c new file mode 100644 index 000000000000..fdb1a9db20f0 --- /dev/null +++ b/arch/mn10300/mm/cache-flush-icache.c | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | /* Flush dcache and invalidate icache when the dcache is in writeback mode | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/mm.h> | ||
| 13 | #include <asm/cacheflush.h> | ||
| 14 | #include <asm/smp.h> | ||
| 15 | #include "cache-smp.h" | ||
| 16 | |||
| 17 | /** | ||
| 18 | * flush_icache_page - Flush a page from the dcache and invalidate the icache | ||
| 19 | * @vma: The VMA the page is part of. | ||
| 20 | * @page: The page to be flushed. | ||
| 21 | * | ||
| 22 | * Write a page back from the dcache and invalidate the icache so that we can | ||
| 23 | * run code from it that we've just written into it | ||
| 24 | */ | ||
| 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); | ||
| diff --git a/arch/mn10300/mm/cache-flush-mn10300.S b/arch/mn10300/mm/cache-flush-mn10300.S deleted file mode 100644 index c8ed1cbac107..000000000000 --- a/arch/mn10300/mm/cache-flush-mn10300.S +++ /dev/null | |||
| @@ -1,192 +0,0 @@ | |||
| 1 | /* MN10300 CPU core caching routines | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sys.h> | ||
| 13 | #include <linux/linkage.h> | ||
| 14 | #include <asm/smp.h> | ||
| 15 | #include <asm/page.h> | ||
| 16 | #include <asm/cache.h> | ||
| 17 | |||
| 18 | .am33_2 | ||
| 19 | .globl mn10300_dcache_flush | ||
| 20 | .globl mn10300_dcache_flush_page | ||
| 21 | .globl mn10300_dcache_flush_range | ||
| 22 | .globl mn10300_dcache_flush_range2 | ||
| 23 | .globl mn10300_dcache_flush_inv | ||
| 24 | .globl mn10300_dcache_flush_inv_page | ||
| 25 | .globl mn10300_dcache_flush_inv_range | ||
| 26 | .globl mn10300_dcache_flush_inv_range2 | ||
| 27 | |||
| 28 | ############################################################################### | ||
| 29 | # | ||
| 30 | # void mn10300_dcache_flush(void) | ||
| 31 | # Flush the entire data cache back to RAM | ||
| 32 | # | ||
| 33 | ############################################################################### | ||
| 34 | ALIGN | ||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S new file mode 100644 index 000000000000..c8950861ed77 --- /dev/null +++ b/arch/mn10300/mm/cache-inv-by-reg.S | |||
| @@ -0,0 +1,356 @@ | |||
| 1 | /* MN10300 CPU cache invalidation routines, using automatic purge registers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/sys.h> | ||
| 12 | #include <linux/linkage.h> | ||
| 13 | #include <asm/smp.h> | ||
| 14 | #include <asm/page.h> | ||
| 15 | #include <asm/cache.h> | ||
| 16 | #include <asm/irqflags.h> | ||
| 17 | #include <asm/cacheflush.h> | ||
| 18 | |||
| 19 | #define mn10300_local_dcache_inv_range_intr_interval \ | ||
| 20 | +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) | ||
| 21 | |||
| 22 | #if mn10300_local_dcache_inv_range_intr_interval > 0xff | ||
| 23 | #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less | ||
| 24 | #endif | ||
| 25 | |||
| 26 | .am33_2 | ||
| 27 | |||
| 28 | #ifndef CONFIG_SMP | ||
| 29 | .globl mn10300_icache_inv | ||
| 30 | .globl mn10300_icache_inv_page | ||
| 31 | .globl mn10300_icache_inv_range | ||
| 32 | .globl mn10300_icache_inv_range2 | ||
| 33 | .globl mn10300_dcache_inv | ||
| 34 | .globl mn10300_dcache_inv_page | ||
| 35 | .globl mn10300_dcache_inv_range | ||
| 36 | .globl mn10300_dcache_inv_range2 | ||
| 37 | |||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S new file mode 100644 index 000000000000..e9713b40c0ff --- /dev/null +++ b/arch/mn10300/mm/cache-inv-by-tag.S | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | /* MN10300 CPU core caching routines | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/sys.h> | ||
| 12 | #include <linux/linkage.h> | ||
| 13 | #include <asm/smp.h> | ||
| 14 | #include <asm/page.h> | ||
| 15 | #include <asm/cache.h> | ||
| 16 | #include <asm/irqflags.h> | ||
| 17 | #include <asm/cacheflush.h> | ||
| 18 | |||
| 19 | #define mn10300_local_dcache_inv_range_intr_interval \ | ||
| 20 | +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) | ||
| 21 | |||
| 22 | #if mn10300_local_dcache_inv_range_intr_interval > 0xff | ||
| 23 | #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less | ||
| 24 | #endif | ||
| 25 | |||
| 26 | .am33_2 | ||
| 27 | |||
| 28 | .globl mn10300_local_icache_inv_page | ||
| 29 | .globl mn10300_local_icache_inv_range | ||
| 30 | .globl mn10300_local_icache_inv_range2 | ||
| 31 | |||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c new file mode 100644 index 000000000000..a8933a60b2d4 --- /dev/null +++ b/arch/mn10300/mm/cache-inv-icache.c | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | /* Invalidate icache when dcache doesn't need invalidation as it's in | ||
| 2 | * write-through mode | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 5 | * Written by David Howells (dhowells@redhat.com) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public Licence | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the Licence, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/mm.h> | ||
| 14 | #include <asm/cacheflush.h> | ||
| 15 | #include <asm/smp.h> | ||
| 16 | #include "cache-smp.h" | ||
| 17 | |||
| 18 | /** | ||
| 19 | * flush_icache_page_range - Flush dcache and invalidate icache for part of a | ||
| 20 | * single page | ||
| 21 | * @start: The starting virtual address of the page part. | ||
| 22 | * @end: The ending virtual address of the page part. | ||
| 23 | * | ||
| 24 | * Invalidate the icache for part of a single page, as determined by the | ||
| 25 | * virtual addresses given. The page must be in the paged area. The dcache is | ||
| 26 | * not flushed as the cache must be in write-through mode to get here. | ||
| 27 | */ | ||
| 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); | ||
| diff --git a/arch/mn10300/mm/cache-mn10300.S b/arch/mn10300/mm/cache-mn10300.S deleted file mode 100644 index e839d0aedd69..000000000000 --- a/arch/mn10300/mm/cache-mn10300.S +++ /dev/null | |||
| @@ -1,289 +0,0 @@ | |||
| 1 | /* MN10300 CPU core caching routines | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/sys.h> | ||
| 12 | #include <linux/linkage.h> | ||
| 13 | #include <asm/smp.h> | ||
| 14 | #include <asm/page.h> | ||
| 15 | #include <asm/cache.h> | ||
| 16 | |||
| 17 | #define mn10300_dcache_inv_range_intr_interval \ | ||
| 18 | +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) | ||
| 19 | |||
| 20 | #if mn10300_dcache_inv_range_intr_interval > 0xff | ||
| 21 | #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less | ||
| 22 | #endif | ||
| 23 | |||
| 24 | .am33_2 | ||
| 25 | |||
| 26 | .globl mn10300_icache_inv | ||
| 27 | .globl mn10300_dcache_inv | ||
| 28 | .globl mn10300_dcache_inv_range | ||
| 29 | .globl mn10300_dcache_inv_range2 | ||
| 30 | .globl mn10300_dcache_inv_page | ||
| 31 | |||
| 32 | ############################################################################### | ||
| 33 | # | ||
| 34 | # void mn10300_icache_inv(void) | ||
| 35 | # Invalidate the entire icache | ||
| 36 | # | ||
| 37 | ############################################################################### | ||
| 38 | ALIGN | ||
| 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 | ||
| diff --git a/arch/mn10300/mm/cache-smp-flush.c b/arch/mn10300/mm/cache-smp-flush.c new file mode 100644 index 000000000000..fd51af5eaf70 --- /dev/null +++ b/arch/mn10300/mm/cache-smp-flush.c | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* Functions for global dcache flush when writeback caching in SMP | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/mm.h> | ||
| 12 | #include <asm/cacheflush.h> | ||
| 13 | #include "cache-smp.h" | ||
| 14 | |||
| 15 | /** | ||
| 16 | * mn10300_dcache_flush - Globally flush data cache | ||
| 17 | * | ||
| 18 | * Flush the data cache on all CPUs. | ||
| 19 | */ | ||
| 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 | } | ||
| diff --git a/arch/mn10300/mm/cache-smp-inv.c b/arch/mn10300/mm/cache-smp-inv.c new file mode 100644 index 000000000000..ff1787358c8e --- /dev/null +++ b/arch/mn10300/mm/cache-smp-inv.c | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /* Functions for global i/dcache invalidation when caching in SMP | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/mm.h> | ||
| 12 | #include <asm/cacheflush.h> | ||
| 13 | #include "cache-smp.h" | ||
| 14 | |||
| 15 | /** | ||
| 16 | * mn10300_icache_inv - Globally invalidate instruction cache | ||
| 17 | * | ||
| 18 | * Invalidate the instruction cache on all CPUs. | ||
| 19 | */ | ||
| 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 | } | ||
| diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c new file mode 100644 index 000000000000..4a6e9a4b5b27 --- /dev/null +++ b/arch/mn10300/mm/cache-smp.c | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | /* SMP global caching code | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/mm.h> | ||
| 13 | #include <linux/mman.h> | ||
| 14 | #include <linux/threads.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <asm/page.h> | ||
| 17 | #include <asm/pgtable.h> | ||
| 18 | #include <asm/processor.h> | ||
| 19 | #include <asm/cacheflush.h> | ||
| 20 | #include <asm/io.h> | ||
| 21 | #include <asm/uaccess.h> | ||
| 22 | #include <asm/smp.h> | ||
| 23 | #include "cache-smp.h" | ||
| 24 | |||
| 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 | } | ||
| diff --git a/arch/mn10300/mm/cache-smp.h b/arch/mn10300/mm/cache-smp.h new file mode 100644 index 000000000000..cb52892aa66a --- /dev/null +++ b/arch/mn10300/mm/cache-smp.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* SMP caching definitions | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | /* | ||
| 14 | * Operation requests for smp_cache_call(). | ||
| 15 | * | ||
| 16 | * One of smp_icache_ops and one of smp_dcache_ops can be OR'd together. | ||
| 17 | */ | ||
| 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 */ | ||
| diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c index 9261217e8d2c..0a1f0aa92ebc 100644 --- a/arch/mn10300/mm/cache.c +++ b/arch/mn10300/mm/cache.c | |||
| @@ -18,8 +18,13 @@ | |||
| 18 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> | 
| 19 | #include <asm/io.h> | 19 | #include <asm/io.h> | 
| 20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> | 
| 21 | #include <asm/smp.h> | ||
| 22 | #include "cache-smp.h" | ||
| 21 | 23 | ||
| 22 | EXPORT_SYMBOL(mn10300_icache_inv); | 24 | 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); | ||
| 23 | EXPORT_SYMBOL(mn10300_dcache_inv); | 28 | EXPORT_SYMBOL(mn10300_dcache_inv); | 
| 24 | EXPORT_SYMBOL(mn10300_dcache_inv_range); | 29 | EXPORT_SYMBOL(mn10300_dcache_inv_range); | 
| 25 | EXPORT_SYMBOL(mn10300_dcache_inv_range2); | 30 | EXPORT_SYMBOL(mn10300_dcache_inv_range2); | 
| @@ -37,96 +42,6 @@ EXPORT_SYMBOL(mn10300_dcache_flush_page); | |||
| 37 | #endif | 42 | #endif | 
| 38 | 43 | ||
| 39 | /* | 44 | /* | 
| 40 | * write a page back from the dcache and invalidate the icache so that we can | ||
| 41 | * run code from it that we've just written into it | ||
| 42 | */ | ||
| 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 | |||
| 129 | /* | ||
| 130 | * allow userspace to flush the instruction cache | 45 | * allow userspace to flush the instruction cache | 
| 131 | */ | 46 | */ | 
| 132 | asmlinkage long sys_cacheflush(unsigned long start, unsigned long end) | 47 | asmlinkage long sys_cacheflush(unsigned long start, unsigned long end) | 
| diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 81f153fa51b4..59c3da49d9d9 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c | |||
| @@ -39,10 +39,6 @@ void bust_spinlocks(int yes) | |||
| 39 | { | 39 | { | 
| 40 | if (yes) { | 40 | if (yes) { | 
| 41 | oops_in_progress = 1; | 41 | oops_in_progress = 1; | 
| 42 | #ifdef CONFIG_SMP | ||
| 43 | /* Many serial drivers do __global_cli() */ | ||
| 44 | global_irq_lock = 0; | ||
| 45 | #endif | ||
| 46 | } else { | 42 | } else { | 
| 47 | int loglevel_save = console_loglevel; | 43 | int loglevel_save = console_loglevel; | 
| 48 | #ifdef CONFIG_VT | 44 | #ifdef CONFIG_VT | 
| @@ -100,8 +96,6 @@ static void print_pagetable_entries(pgd_t *pgdir, unsigned long address) | |||
| 100 | } | 96 | } | 
| 101 | #endif | 97 | #endif | 
| 102 | 98 | ||
| 103 | asmlinkage void monitor_signal(struct pt_regs *); | ||
| 104 | |||
| 105 | /* | 99 | /* | 
| 106 | * This routine handles page faults. It determines the address, | 100 | * This routine handles page faults. It determines the address, | 
| 107 | * and the problem, and then passes it off to one of the appropriate | 101 | * and the problem, and then passes it off to one of the appropriate | 
| @@ -279,7 +273,6 @@ good_area: | |||
| 279 | */ | 273 | */ | 
| 280 | bad_area: | 274 | bad_area: | 
| 281 | up_read(&mm->mmap_sem); | 275 | up_read(&mm->mmap_sem); | 
| 282 | monitor_signal(regs); | ||
| 283 | 276 | ||
| 284 | /* User mode accesses just cause a SIGSEGV */ | 277 | /* User mode accesses just cause a SIGSEGV */ | 
| 285 | if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) { | 278 | if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) { | 
| @@ -292,7 +285,6 @@ bad_area: | |||
| 292 | } | 285 | } | 
| 293 | 286 | ||
| 294 | no_context: | 287 | no_context: | 
| 295 | monitor_signal(regs); | ||
| 296 | /* Are we prepared to handle this kernel fault? */ | 288 | /* Are we prepared to handle this kernel fault? */ | 
| 297 | if (fixup_exception(regs)) | 289 | if (fixup_exception(regs)) | 
| 298 | return; | 290 | return; | 
| @@ -338,14 +330,13 @@ no_context: | |||
| 338 | */ | 330 | */ | 
| 339 | out_of_memory: | 331 | out_of_memory: | 
| 340 | up_read(&mm->mmap_sem); | 332 | up_read(&mm->mmap_sem); | 
| 341 | if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR) | 333 | printk(KERN_ALERT "VM: killing process %s\n", tsk->comm); | 
| 342 | goto no_context; | 334 | if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) | 
| 343 | pagefault_out_of_memory(); | 335 | do_exit(SIGKILL); | 
| 344 | return; | 336 | goto no_context; | 
| 345 | 337 | ||
| 346 | do_sigbus: | 338 | do_sigbus: | 
| 347 | up_read(&mm->mmap_sem); | 339 | up_read(&mm->mmap_sem); | 
| 348 | monitor_signal(regs); | ||
| 349 | 340 | ||
| 350 | /* | 341 | /* | 
| 351 | * Send a sigbus, regardless of whether we were in kernel | 342 | * Send a sigbus, regardless of whether we were in kernel | 
| diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c index 6e6bc0e51521..48907cc3bdb7 100644 --- a/arch/mn10300/mm/init.c +++ b/arch/mn10300/mm/init.c | |||
| @@ -41,6 +41,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | |||
| 41 | 41 | ||
| 42 | unsigned long highstart_pfn, highend_pfn; | 42 | unsigned long highstart_pfn, highend_pfn; | 
| 43 | 43 | ||
| 44 | #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | ||
| 45 | static struct vm_struct user_iomap_vm; | ||
| 46 | #endif | ||
| 47 | |||
| 44 | /* | 48 | /* | 
| 45 | * set up paging | 49 | * set up paging | 
| 46 | */ | 50 | */ | 
| @@ -73,7 +77,24 @@ void __init paging_init(void) | |||
| 73 | /* pass the memory from the bootmem allocator to the main allocator */ | 77 | /* pass the memory from the bootmem allocator to the main allocator */ | 
| 74 | free_area_init(zones_size); | 78 | free_area_init(zones_size); | 
| 75 | 79 | ||
| 76 | __flush_tlb_all(); | 80 | #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT | 
| 81 | /* The Atomic Operation Unit registers need to be mapped to userspace | ||
| 82 | * for all processes. The following uses vm_area_register_early() to | ||
| 83 | * reserve the first page of the vmalloc area and sets the pte for that | ||
| 84 | * page. | ||
| 85 | * | ||
| 86 | * glibc hardcodes this virtual mapping, so we're pretty much stuck with | ||
| 87 | * it from now on. | ||
| 88 | */ | ||
| 89 | user_iomap_vm.flags = VM_USERMAP; | ||
| 90 | user_iomap_vm.size = 1 << PAGE_SHIFT; | ||
| 91 | vm_area_register_early(&user_iomap_vm, PAGE_SIZE); | ||
| 92 | ppte = kernel_vmalloc_ptes; | ||
| 93 | set_pte(ppte, pfn_pte(USER_ATOMIC_OPS_PAGE_ADDR >> PAGE_SHIFT, | ||
| 94 | PAGE_USERIO)); | ||
| 95 | #endif | ||
| 96 | |||
| 97 | local_flush_tlb_all(); | ||
| 77 | } | 98 | } | 
| 78 | 99 | ||
| 79 | /* | 100 | /* | 
| @@ -84,8 +105,7 @@ void __init mem_init(void) | |||
| 84 | int codesize, reservedpages, datasize, initsize; | 105 | int codesize, reservedpages, datasize, initsize; | 
| 85 | int tmp; | 106 | int tmp; | 
| 86 | 107 | ||
| 87 | if (!mem_map) | 108 | BUG_ON(!mem_map); | 
| 88 | BUG(); | ||
| 89 | 109 | ||
| 90 | #define START_PFN (contig_page_data.bdata->node_min_pfn) | 110 | #define START_PFN (contig_page_data.bdata->node_min_pfn) | 
| 91 | #define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn) | 111 | #define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn) | 
| diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c index 6dffbf97ac26..eef989c1d0c1 100644 --- a/arch/mn10300/mm/misalignment.c +++ b/arch/mn10300/mm/misalignment.c | |||
| @@ -449,8 +449,7 @@ found_opcode: | |||
| 449 | regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]); | 449 | regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]); | 
| 450 | 450 | ||
| 451 | tmp = format_tbl[pop->format].opsz; | 451 | tmp = format_tbl[pop->format].opsz; | 
| 452 | if (tmp > noc) | 452 | BUG_ON(tmp > noc); /* match was less complete than it ought to have been */ | 
| 453 | BUG(); /* match was less complete than it ought to have been */ | ||
| 454 | 453 | ||
| 455 | if (tmp < noc) { | 454 | if (tmp < noc) { | 
| 456 | tmp = noc - tmp; | 455 | tmp = noc - tmp; | 
| diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c index 36ba02191d40..a4f7d3dcc6e6 100644 --- a/arch/mn10300/mm/mmu-context.c +++ b/arch/mn10300/mm/mmu-context.c | |||
| @@ -13,40 +13,15 @@ | |||
| 13 | #include <asm/mmu_context.h> | 13 | #include <asm/mmu_context.h> | 
| 14 | #include <asm/tlbflush.h> | 14 | #include <asm/tlbflush.h> | 
| 15 | 15 | ||
| 16 | #ifdef CONFIG_MN10300_TLB_USE_PIDR | ||
| 16 | /* | 17 | /* | 
| 17 | * list of the MMU contexts last allocated on each CPU | 18 | * list of the MMU contexts last allocated on each CPU | 
| 18 | */ | 19 | */ | 
| 19 | unsigned long mmu_context_cache[NR_CPUS] = { | 20 | 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), | ||
| 21 | }; | 23 | }; | 
| 22 | 24 | #endif /* CONFIG_MN10300_TLB_USE_PIDR */ | |
| 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 | } | ||
| 50 | 25 | ||
| 51 | /* | 26 | /* | 
| 52 | * preemptively set a TLB entry | 27 | * preemptively set a TLB entry | 
| @@ -63,10 +38,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *pte | |||
| 63 | * interference from vmalloc'd regions */ | 38 | * interference from vmalloc'd regions */ | 
| 64 | local_irq_save(flags); | 39 | local_irq_save(flags); | 
| 65 | 40 | ||
| 41 | cnx = ~MMU_NO_CONTEXT; | ||
| 42 | #ifdef CONFIG_MN10300_TLB_USE_PIDR | ||
| 66 | cnx = mm_context(vma->vm_mm); | 43 | cnx = mm_context(vma->vm_mm); | 
| 44 | #endif | ||
| 67 | 45 | ||
| 68 | if (cnx != MMU_NO_CONTEXT) { | 46 | if (cnx != MMU_NO_CONTEXT) { | 
| 69 | pteu = addr | (cnx & 0x000000ffUL); | 47 | pteu = addr; | 
| 48 | #ifdef CONFIG_MN10300_TLB_USE_PIDR | ||
| 49 | pteu |= cnx & MMU_CONTEXT_TLBPID_MASK; | ||
| 50 | #endif | ||
| 70 | if (!(pte_val(pte) & _PAGE_NX)) { | 51 | if (!(pte_val(pte) & _PAGE_NX)) { | 
| 71 | IPTEU = pteu; | 52 | IPTEU = pteu; | 
| 72 | if (IPTEL & xPTEL_V) | 53 | if (IPTEL & xPTEL_V) | 
| diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c index 9c1624c9e4e9..450f7ba3f8f2 100644 --- a/arch/mn10300/mm/pgtable.c +++ b/arch/mn10300/mm/pgtable.c | |||
| @@ -59,7 +59,7 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) | |||
| 59 | * It's enough to flush this one mapping. | 59 | * It's enough to flush this one mapping. | 
| 60 | * (PGE mappings get flushed as well) | 60 | * (PGE mappings get flushed as well) | 
| 61 | */ | 61 | */ | 
| 62 | __flush_tlb_one(vaddr); | 62 | local_flush_tlb_one(vaddr); | 
| 63 | } | 63 | } | 
| 64 | 64 | ||
| 65 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | 65 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | 
| diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S index 7095147dcb8b..b9940177d81b 100644 --- a/arch/mn10300/mm/tlb-mn10300.S +++ b/arch/mn10300/mm/tlb-mn10300.S | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | ############################################################################### | 27 | ############################################################################### | 
| 28 | .type itlb_miss,@function | 28 | .type itlb_miss,@function | 
| 29 | ENTRY(itlb_miss) | 29 | ENTRY(itlb_miss) | 
| 30 | and ~EPSW_NMID,epsw | ||
| 31 | #ifdef CONFIG_GDBSTUB | 30 | #ifdef CONFIG_GDBSTUB | 
| 32 | movm [d2,d3,a2],(sp) | 31 | movm [d2,d3,a2],(sp) | 
| 33 | #else | 32 | #else | 
| @@ -38,6 +37,12 @@ ENTRY(itlb_miss) | |||
| 38 | nop | 37 | nop | 
| 39 | #endif | 38 | #endif | 
| 40 | 39 | ||
| 40 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 41 | mov (MMUCTR),d2 | ||
| 42 | mov d2,(MMUCTR) | ||
| 43 | #endif | ||
| 44 | |||
| 45 | and ~EPSW_NMID,epsw | ||
| 41 | mov (IPTEU),d3 | 46 | mov (IPTEU),d3 | 
| 42 | mov (PTBR),a2 | 47 | mov (PTBR),a2 | 
| 43 | mov d3,d2 | 48 | mov d3,d2 | 
| @@ -56,10 +61,16 @@ ENTRY(itlb_miss) | |||
| 56 | btst _PAGE_VALID,d2 | 61 | btst _PAGE_VALID,d2 | 
| 57 | beq itlb_miss_fault # jump if doesn't point to a page | 62 | beq itlb_miss_fault # jump if doesn't point to a page | 
| 58 | # (might be a swap id) | 63 | # (might be a swap id) | 
| 64 | #if ((_PAGE_ACCESSED & 0xffffff00) == 0) | ||
| 59 | bset _PAGE_ACCESSED,(0,a2) | 65 | bset _PAGE_ACCESSED,(0,a2) | 
| 60 | and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2 | 66 | #elif ((_PAGE_ACCESSED & 0xffff00ff) == 0) | 
| 67 | bset +(_PAGE_ACCESSED >> 8),(1,a2) | ||
| 68 | #else | ||
| 69 | #error "_PAGE_ACCESSED value is out of range" | ||
| 70 | #endif | ||
| 71 | and ~xPTEL2_UNUSED1,d2 | ||
| 61 | itlb_miss_set: | 72 | itlb_miss_set: | 
| 62 | mov d2,(IPTEL) # change the TLB | 73 | mov d2,(IPTEL2) # change the TLB | 
| 63 | #ifdef CONFIG_GDBSTUB | 74 | #ifdef CONFIG_GDBSTUB | 
| 64 | movm (sp),[d2,d3,a2] | 75 | movm (sp),[d2,d3,a2] | 
| 65 | #endif | 76 | #endif | 
| @@ -79,7 +90,6 @@ itlb_miss_fault: | |||
| 79 | ############################################################################### | 90 | ############################################################################### | 
| 80 | .type dtlb_miss,@function | 91 | .type dtlb_miss,@function | 
| 81 | ENTRY(dtlb_miss) | 92 | ENTRY(dtlb_miss) | 
| 82 | and ~EPSW_NMID,epsw | ||
| 83 | #ifdef CONFIG_GDBSTUB | 93 | #ifdef CONFIG_GDBSTUB | 
| 84 | movm [d2,d3,a2],(sp) | 94 | movm [d2,d3,a2],(sp) | 
| 85 | #else | 95 | #else | 
| @@ -90,6 +100,12 @@ ENTRY(dtlb_miss) | |||
| 90 | nop | 100 | nop | 
| 91 | #endif | 101 | #endif | 
| 92 | 102 | ||
| 103 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 104 | mov (MMUCTR),d2 | ||
| 105 | mov d2,(MMUCTR) | ||
| 106 | #endif | ||
| 107 | |||
| 108 | and ~EPSW_NMID,epsw | ||
| 93 | mov (DPTEU),d3 | 109 | mov (DPTEU),d3 | 
| 94 | mov (PTBR),a2 | 110 | mov (PTBR),a2 | 
| 95 | mov d3,d2 | 111 | mov d3,d2 | 
| @@ -108,10 +124,16 @@ ENTRY(dtlb_miss) | |||
| 108 | btst _PAGE_VALID,d2 | 124 | btst _PAGE_VALID,d2 | 
| 109 | beq dtlb_miss_fault # jump if doesn't point to a page | 125 | beq dtlb_miss_fault # jump if doesn't point to a page | 
| 110 | # (might be a swap id) | 126 | # (might be a swap id) | 
| 127 | #if ((_PAGE_ACCESSED & 0xffffff00) == 0) | ||
| 111 | bset _PAGE_ACCESSED,(0,a2) | 128 | bset _PAGE_ACCESSED,(0,a2) | 
| 112 | and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2 | 129 | #elif ((_PAGE_ACCESSED & 0xffff00ff) == 0) | 
| 130 | bset +(_PAGE_ACCESSED >> 8),(1,a2) | ||
| 131 | #else | ||
| 132 | #error "_PAGE_ACCESSED value is out of range" | ||
| 133 | #endif | ||
| 134 | and ~xPTEL2_UNUSED1,d2 | ||
| 113 | dtlb_miss_set: | 135 | dtlb_miss_set: | 
| 114 | mov d2,(DPTEL) # change the TLB | 136 | mov d2,(DPTEL2) # change the TLB | 
| 115 | #ifdef CONFIG_GDBSTUB | 137 | #ifdef CONFIG_GDBSTUB | 
| 116 | movm (sp),[d2,d3,a2] | 138 | movm (sp),[d2,d3,a2] | 
| 117 | #endif | 139 | #endif | 
| @@ -130,9 +152,15 @@ dtlb_miss_fault: | |||
| 130 | ############################################################################### | 152 | ############################################################################### | 
| 131 | .type itlb_aerror,@function | 153 | .type itlb_aerror,@function | 
| 132 | ENTRY(itlb_aerror) | 154 | ENTRY(itlb_aerror) | 
| 133 | and ~EPSW_NMID,epsw | ||
| 134 | add -4,sp | 155 | add -4,sp | 
| 135 | SAVE_ALL | 156 | SAVE_ALL | 
| 157 | |||
| 158 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 159 | mov (MMUCTR),d1 | ||
| 160 | mov d1,(MMUCTR) | ||
| 161 | #endif | ||
| 162 | |||
| 163 | and ~EPSW_NMID,epsw | ||
| 136 | add -4,sp # need to pass three params | 164 | add -4,sp # need to pass three params | 
| 137 | 165 | ||
| 138 | # calculate the fault code | 166 | # calculate the fault code | 
| @@ -140,15 +168,13 @@ ENTRY(itlb_aerror) | |||
| 140 | or 0x00010000,d1 # it's an instruction fetch | 168 | or 0x00010000,d1 # it's an instruction fetch | 
| 141 | 169 | ||
| 142 | # determine the page address | 170 | # determine the page address | 
| 143 | mov (IPTEU),a2 | 171 | mov (IPTEU),d0 | 
| 144 | mov a2,d0 | ||
| 145 | and PAGE_MASK,d0 | 172 | and PAGE_MASK,d0 | 
| 146 | mov d0,(12,sp) | 173 | mov d0,(12,sp) | 
| 147 | 174 | ||
| 148 | clr d0 | 175 | clr d0 | 
| 149 | mov d0,(IPTEL) | 176 | mov d0,(IPTEL2) | 
| 150 | 177 | ||
| 151 | and ~EPSW_NMID,epsw | ||
| 152 | or EPSW_IE,epsw | 178 | or EPSW_IE,epsw | 
| 153 | mov fp,d0 | 179 | mov fp,d0 | 
| 154 | call do_page_fault[],0 # do_page_fault(regs,code,addr | 180 | call do_page_fault[],0 # do_page_fault(regs,code,addr | 
| @@ -163,10 +189,16 @@ ENTRY(itlb_aerror) | |||
| 163 | ############################################################################### | 189 | ############################################################################### | 
| 164 | .type dtlb_aerror,@function | 190 | .type dtlb_aerror,@function | 
| 165 | ENTRY(dtlb_aerror) | 191 | ENTRY(dtlb_aerror) | 
| 166 | and ~EPSW_NMID,epsw | ||
| 167 | add -4,sp | 192 | add -4,sp | 
| 168 | SAVE_ALL | 193 | SAVE_ALL | 
| 194 | |||
| 195 | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | ||
| 196 | mov (MMUCTR),d1 | ||
| 197 | mov d1,(MMUCTR) | ||
| 198 | #endif | ||
| 199 | |||
| 169 | add -4,sp # need to pass three params | 200 | add -4,sp # need to pass three params | 
| 201 | and ~EPSW_NMID,epsw | ||
| 170 | 202 | ||
| 171 | # calculate the fault code | 203 | # calculate the fault code | 
| 172 | movhu (MMUFCR_DFC),d1 | 204 | movhu (MMUFCR_DFC),d1 | 
| @@ -178,9 +210,8 @@ ENTRY(dtlb_aerror) | |||
| 178 | mov d0,(12,sp) | 210 | mov d0,(12,sp) | 
| 179 | 211 | ||
| 180 | clr d0 | 212 | clr d0 | 
| 181 | mov d0,(DPTEL) | 213 | mov d0,(DPTEL2) | 
| 182 | 214 | ||
| 183 | and ~EPSW_NMID,epsw | ||
| 184 | or EPSW_IE,epsw | 215 | or EPSW_IE,epsw | 
| 185 | mov fp,d0 | 216 | mov fp,d0 | 
| 186 | call do_page_fault[],0 # do_page_fault(regs,code,addr | 217 | call do_page_fault[],0 # do_page_fault(regs,code,addr | 
| diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c new file mode 100644 index 000000000000..0b6a5ad1960e --- /dev/null +++ b/arch/mn10300/mm/tlb-smp.c | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | /* SMP TLB support routines. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006-2008 Panasonic Corporation | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | #include <linux/cpumask.h> | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/sched.h> | ||
| 24 | #include <linux/profile.h> | ||
| 25 | #include <linux/smp.h> | ||
| 26 | #include <asm/tlbflush.h> | ||
| 27 | #include <asm/system.h> | ||
| 28 | #include <asm/bitops.h> | ||
| 29 | #include <asm/processor.h> | ||
| 30 | #include <asm/bug.h> | ||
| 31 | #include <asm/exceptions.h> | ||
| 32 | #include <asm/hardirq.h> | ||
| 33 | #include <asm/fpu.h> | ||
| 34 | #include <asm/mmu_context.h> | ||
| 35 | #include <asm/thread_info.h> | ||
| 36 | #include <asm/cpu-regs.h> | ||
| 37 | #include <asm/intctl-regs.h> | ||
| 38 | |||
| 39 | /* | ||
| 40 | * For flush TLB | ||
| 41 | */ | ||
| 42 | #define FLUSH_ALL 0xffffffff | ||
| 43 | |||
| 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 | } | ||
| diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h index bdc1f9a59b4c..c1528004163c 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/cache.h +++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h | |||
| @@ -30,4 +30,13 @@ | |||
| 30 | */ | 30 | */ | 
| 31 | #define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4 | 31 | #define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4 | 
| 32 | 32 | ||
| 33 | /* | ||
| 34 | * The size of range at which it becomes more economical to just flush the | ||
| 35 | * whole cache rather than trying to flush the specified range. | ||
| 36 | */ | ||
| 37 | #define MN10300_DCACHE_FLUSH_BORDER \ | ||
| 38 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
| 39 | #define MN10300_DCACHE_FLUSH_INV_BORDER \ | ||
| 40 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
| 41 | |||
| 33 | #endif /* _ASM_PROC_CACHE_H */ | 42 | #endif /* _ASM_PROC_CACHE_H */ | 
| diff --git a/arch/mn10300/proc-mn103e010/include/proc/clock.h b/arch/mn10300/proc-mn103e010/include/proc/clock.h index aa23e147d620..704a819f1f4b 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/clock.h +++ b/arch/mn10300/proc-mn103e010/include/proc/clock.h | |||
| @@ -13,6 +13,4 @@ | |||
| 13 | 13 | ||
| 14 | #include <unit/clock.h> | 14 | #include <unit/clock.h> | 
| 15 | 15 | ||
| 16 | #define MN10300_WDCLK MN10300_IOCLK | ||
| 17 | |||
| 18 | #endif /* _ASM_PROC_CLOCK_H */ | 16 | #endif /* _ASM_PROC_CLOCK_H */ | 
| diff --git a/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h new file mode 100644 index 000000000000..d72d328d1f9c --- /dev/null +++ b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | /* MN103E010 on-board DMA controller registers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _ASM_PROC_DMACTL_REGS_H | ||
| 13 | #define _ASM_PROC_DMACTL_REGS_H | ||
| 14 | |||
| 15 | #include <asm/cpu-regs.h> | ||
| 16 | |||
| 17 | #ifdef __KERNEL__ | ||
| 18 | |||
| 19 | /* DMA registers */ | ||
| 20 | #define DMxCTR(N) __SYSREG(0xd2000000 + ((N) * 0x100), u32) /* control reg */ | ||
| 21 | #define DMxCTR_BG 0x0000001f /* transfer request source */ | ||
| 22 | #define DMxCTR_BG_SOFT 0x00000000 /* - software source */ | ||
| 23 | #define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */ | ||
| 24 | #define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */ | ||
| 25 | #define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */ | ||
| 26 | #define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */ | ||
| 27 | #define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */ | ||
| 28 | #define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */ | ||
| 29 | #define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */ | ||
| 30 | #define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */ | ||
| 31 | #define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */ | ||
| 32 | #define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */ | ||
| 33 | #define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */ | ||
| 34 | #define DMxCTR_BG_AFE 0x0000000d /* - analogue front-end interrupt source */ | ||
| 35 | #define DMxCTR_BG_ADC 0x0000000e /* - A/D conversion end interrupt source */ | ||
| 36 | #define DMxCTR_BG_IRDA 0x0000000f /* - IrDA interrupt source */ | ||
| 37 | #define DMxCTR_BG_RTC 0x00000010 /* - RTC interrupt source */ | ||
| 38 | #define DMxCTR_BG_XIRQ0 0x00000011 /* - XIRQ0 pin interrupt source */ | ||
| 39 | #define DMxCTR_BG_XIRQ1 0x00000012 /* - XIRQ1 pin interrupt source */ | ||
| 40 | #define DMxCTR_BG_XDMR0 0x00000013 /* - external request 0 source (XDMR0 pin) */ | ||
| 41 | #define DMxCTR_BG_XDMR1 0x00000014 /* - external request 1 source (XDMR1 pin) */ | ||
| 42 | #define DMxCTR_SAM 0x000000e0 /* DMA transfer src addr mode */ | ||
| 43 | #define DMxCTR_SAM_INCR 0x00000000 /* - increment */ | ||
| 44 | #define DMxCTR_SAM_DECR 0x00000020 /* - decrement */ | ||
| 45 | #define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */ | ||
| 46 | #define DMxCTR_DAM 0x00000000 /* DMA transfer dest addr mode */ | ||
| 47 | #define DMxCTR_DAM_INCR 0x00000000 /* - increment */ | ||
| 48 | #define DMxCTR_DAM_DECR 0x00000100 /* - decrement */ | ||
| 49 | #define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */ | ||
| 50 | #define DMxCTR_TM 0x00001800 /* DMA transfer mode */ | ||
| 51 | #define DMxCTR_TM_BATCH 0x00000000 /* - batch transfer */ | ||
| 52 | #define DMxCTR_TM_INTERM 0x00001000 /* - intermittent transfer */ | ||
| 53 | #define DMxCTR_UT 0x00006000 /* DMA transfer unit */ | ||
| 54 | #define DMxCTR_UT_1 0x00000000 /* - 1 byte */ | ||
| 55 | #define DMxCTR_UT_2 0x00002000 /* - 2 byte */ | ||
| 56 | #define DMxCTR_UT_4 0x00004000 /* - 4 byte */ | ||
| 57 | #define DMxCTR_UT_16 0x00006000 /* - 16 byte */ | ||
| 58 | #define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */ | ||
| 59 | #define DMxCTR_RQM 0x00060000 /* external request input source mode */ | ||
| 60 | #define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */ | ||
| 61 | #define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */ | ||
| 62 | #define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */ | ||
| 63 | #define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */ | ||
| 64 | #define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */ | ||
| 65 | #define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */ | ||
| 66 | |||
| 67 | #define DMxSRC(N) __SYSREG(0xd2000004 + ((N) * 0x100), u32) /* control reg */ | ||
| 68 | |||
| 69 | #define DMxDST(N) __SYSREG(0xd2000008 + ((N) * 0x100), u32) /* src addr reg */ | ||
| 70 | |||
| 71 | #define DMxSIZ(N) __SYSREG(0xd200000c + ((N) * 0x100), u32) /* dest addr reg */ | ||
| 72 | #define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */ | ||
| 73 | |||
| 74 | #define DMxCYC(N) __SYSREG(0xd2000010 + ((N) * 0x100), u32) /* intermittent | ||
| 75 | * size reg */ | ||
| 76 | #define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */ | ||
| 77 | |||
| 78 | #define DM0IRQ 16 /* DMA channel 0 complete IRQ */ | ||
| 79 | #define DM1IRQ 17 /* DMA channel 1 complete IRQ */ | ||
| 80 | #define DM2IRQ 18 /* DMA channel 2 complete IRQ */ | ||
| 81 | #define DM3IRQ 19 /* DMA channel 3 complete IRQ */ | ||
| 82 | |||
| 83 | #define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */ | ||
| 84 | #define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */ | ||
| 85 | #define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */ | ||
| 86 | #define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */ | ||
| 87 | |||
| 88 | #ifndef __ASSEMBLY__ | ||
| 89 | |||
| 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 */ | ||
| diff --git a/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h new file mode 100644 index 000000000000..f537801a44ba --- /dev/null +++ b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #ifndef _ASM_PROC_INTCTL_REGS_H | ||
| 2 | #define _ASM_PROC_INTCTL_REGS_H | ||
| 3 | |||
| 4 | #ifndef _ASM_INTCTL_REGS_H | ||
| 5 | # error "please don't include this file directly" | ||
| 6 | #endif | ||
| 7 | |||
| 8 | /* intr acceptance group reg */ | ||
| 9 | #define IAGR __SYSREG(0xd4000100, u16) | ||
| 10 | |||
| 11 | /* group number register */ | ||
| 12 | #define IAGR_GN 0x00fc | ||
| 13 | |||
| 14 | #define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3) | ||
| 15 | |||
| 16 | #define __SET_XIRQ_TRIGGER(X, Y, Z) \ | ||
| 17 | ({ \ | ||
| 18 | typeof(Z) x = (Z); \ | ||
| 19 | x &= ~(3 << ((X) * 2)); \ | ||
| 20 | x |= ((Y) & 3) << ((X) * 2); \ | ||
| 21 | (Z) = x; \ | ||
| 22 | }) | ||
| 23 | |||
| 24 | /* external pin intr spec reg */ | ||
| 25 | #define EXTMD __SYSREG(0xd4000200, u16) | ||
| 26 | #define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD) | ||
| 27 | #define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD) | ||
| 28 | |||
| 29 | #endif /* _ASM_PROC_INTCTL_REGS_H */ | ||
| diff --git a/arch/mn10300/proc-mn103e010/include/proc/proc.h b/arch/mn10300/proc-mn103e010/include/proc/proc.h index 22a2b93f70b7..39c4f8e7d2d3 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/proc.h +++ b/arch/mn10300/proc-mn103e010/include/proc/proc.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #ifndef _ASM_PROC_PROC_H | 12 | #ifndef _ASM_PROC_PROC_H | 
| 13 | #define _ASM_PROC_PROC_H | 13 | #define _ASM_PROC_PROC_H | 
| 14 | 14 | ||
| 15 | #define PROCESSOR_VENDOR_NAME "Matsushita" | 15 | #define PROCESSOR_VENDOR_NAME "Panasonic" | 
| 16 | #define PROCESSOR_MODEL_NAME "mn103e010" | 16 | #define PROCESSOR_MODEL_NAME "mn103e010" | 
| 17 | 17 | ||
| 18 | #endif /* _ASM_PROC_PROC_H */ | 18 | #endif /* _ASM_PROC_PROC_H */ | 
| diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c index 9a482efafa82..27b97980dca4 100644 --- a/arch/mn10300/proc-mn103e010/proc-init.c +++ b/arch/mn10300/proc-mn103e010/proc-init.c | |||
| @@ -9,7 +9,9 @@ | |||
| 9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. | 
| 10 | */ | 10 | */ | 
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> | 
| 12 | #include <asm/fpu.h> | ||
| 12 | #include <asm/rtc.h> | 13 | #include <asm/rtc.h> | 
| 14 | #include <asm/busctl-regs.h> | ||
| 13 | 15 | ||
| 14 | /* | 16 | /* | 
| 15 | * initialise the on-silicon processor peripherals | 17 | * initialise the on-silicon processor peripherals | 
| @@ -28,6 +30,7 @@ asmlinkage void __init processor_init(void) | |||
| 28 | __set_intr_stub(EXCEP_DAERROR, dtlb_aerror); | 30 | __set_intr_stub(EXCEP_DAERROR, dtlb_aerror); | 
| 29 | __set_intr_stub(EXCEP_BUSERROR, raw_bus_error); | 31 | __set_intr_stub(EXCEP_BUSERROR, raw_bus_error); | 
| 30 | __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault); | 32 | __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault); | 
| 33 | __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled); | ||
| 31 | __set_intr_stub(EXCEP_SYSCALL0, system_call); | 34 | __set_intr_stub(EXCEP_SYSCALL0, system_call); | 
| 32 | 35 | ||
| 33 | __set_intr_stub(EXCEP_NMI, nmi_handler); | 36 | __set_intr_stub(EXCEP_NMI, nmi_handler); | 
| @@ -73,3 +76,37 @@ asmlinkage void __init processor_init(void) | |||
| 73 | 76 | ||
| 74 | calibrate_clock(); | 77 | calibrate_clock(); | 
| 75 | } | 78 | } | 
| 79 | |||
| 80 | /* | ||
| 81 | * determine the memory size and base from the memory controller regs | ||
| 82 | */ | ||
| 83 | void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size) | ||
| 84 | { | ||
| 85 | unsigned long base, size; | ||
| 86 | |||
| 87 | *mem_base = 0; | ||
| 88 | *mem_size = 0; | ||
| 89 | |||
| 90 | base = SDBASE(0); | ||
| 91 | if (base & SDBASE_CE) { | ||
| 92 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
| 93 | size = ~size + 1; | ||
| 94 | base &= SDBASE_CBA; | ||
| 95 | |||
| 96 | printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); | ||
| 97 | *mem_size += size; | ||
| 98 | *mem_base = base; | ||
| 99 | } | ||
| 100 | |||
| 101 | base = SDBASE(1); | ||
| 102 | if (base & SDBASE_CE) { | ||
| 103 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
| 104 | size = ~size + 1; | ||
| 105 | base &= SDBASE_CBA; | ||
| 106 | |||
| 107 | printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); | ||
| 108 | *mem_size += size; | ||
| 109 | if (*mem_base == 0) | ||
| 110 | *mem_base = base; | ||
| 111 | } | ||
| 112 | } | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/Makefile b/arch/mn10300/proc-mn2ws0050/Makefile new file mode 100644 index 000000000000..d4ca13309a85 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the linux kernel. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-y := proc-init.o | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h new file mode 100644 index 000000000000..cafd7b5b55b4 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* Cache specification | ||
| 2 | * | ||
| 3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 7 | * Modifications: | ||
| 8 | * 13-Nov-2006 MEI Add L1_CACHE_SHIFT_MAX definition. | ||
| 9 | * 29-Jul-2008 MEI Add define for MN10300_HAS_AREAPURGE_REG. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version | ||
| 14 | * 2 of the License, or (at your option) any later version. | ||
| 15 | */ | ||
| 16 | #ifndef _ASM_PROC_CACHE_H | ||
| 17 | #define _ASM_PROC_CACHE_H | ||
| 18 | |||
| 19 | /* | ||
| 20 | * L1 cache | ||
| 21 | */ | ||
| 22 | #define L1_CACHE_NWAYS 4 /* number of ways in caches */ | ||
| 23 | #define L1_CACHE_NENTRIES 128 /* number of entries in each way */ | ||
| 24 | #define L1_CACHE_BYTES 32 /* bytes per entry */ | ||
| 25 | #define L1_CACHE_SHIFT 5 /* shift for bytes per entry */ | ||
| 26 | #define L1_CACHE_WAYDISP 0x1000 /* distance from one way to the next */ | ||
| 27 | |||
| 28 | #define L1_CACHE_TAG_VALID 0x00000001 /* cache tag valid bit */ | ||
| 29 | #define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ | ||
| 30 | #define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */ | ||
| 31 | #define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * specification of the interval between interrupt checking intervals whilst | ||
| 35 | * managing the cache with the interrupts disabled | ||
| 36 | */ | ||
| 37 | #define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4 | ||
| 38 | |||
| 39 | /* | ||
| 40 | * The size of range at which it becomes more economical to just flush the | ||
| 41 | * whole cache rather than trying to flush the specified range. | ||
| 42 | */ | ||
| 43 | #define MN10300_DCACHE_FLUSH_BORDER \ | ||
| 44 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
| 45 | #define MN10300_DCACHE_FLUSH_INV_BORDER \ | ||
| 46 | +(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES) | ||
| 47 | |||
| 48 | #endif /* _ASM_PROC_CACHE_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/clock.h b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h new file mode 100644 index 000000000000..fe4c0a4a53a2 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /* clock.h: proc-specific clocks | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 7 | * Modifications: | ||
| 8 | * 23-Feb-2007 MEI Delete define for watchdog timer. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | #ifndef _ASM_PROC_CLOCK_H | ||
| 16 | #define _ASM_PROC_CLOCK_H | ||
| 17 | |||
| 18 | #include <unit/clock.h> | ||
| 19 | |||
| 20 | #endif /* _ASM_PROC_CLOCK_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h new file mode 100644 index 000000000000..4c4319e241d1 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | /* MN2WS0050 on-board DMA controller registers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _ASM_PROC_DMACTL_REGS_H | ||
| 12 | #define _ASM_PROC_DMACTL_REGS_H | ||
| 13 | |||
| 14 | #include <asm/cpu-regs.h> | ||
| 15 | |||
| 16 | #ifdef __KERNEL__ | ||
| 17 | |||
| 18 | /* DMA registers */ | ||
| 19 | #define DMxCTR(N) __SYSREG(0xd4005000+(N*0x100), u32) /* control reg */ | ||
| 20 | #define DMxCTR_BG 0x0000001f /* transfer request source */ | ||
| 21 | #define DMxCTR_BG_SOFT 0x00000000 /* - software source */ | ||
| 22 | #define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */ | ||
| 23 | #define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */ | ||
| 24 | #define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */ | ||
| 25 | #define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */ | ||
| 26 | #define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */ | ||
| 27 | #define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */ | ||
| 28 | #define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */ | ||
| 29 | #define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */ | ||
| 30 | #define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */ | ||
| 31 | #define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */ | ||
| 32 | #define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */ | ||
| 33 | #define DMxCTR_BG_RYBY 0x0000000d /* - NAND Flash RY/BY request source */ | ||
| 34 | #define DMxCTR_BG_RMC 0x0000000e /* - remote controller output */ | ||
| 35 | #define DMxCTR_BG_XIRQ12 0x00000011 /* - XIRQ12 pin interrupt source */ | ||
| 36 | #define DMxCTR_BG_XIRQ13 0x00000012 /* - XIRQ13 pin interrupt source */ | ||
| 37 | #define DMxCTR_BG_TCK 0x00000014 /* - tick timer underflow */ | ||
| 38 | #define DMxCTR_BG_SC4TX 0x00000019 /* - serial port4 transmission */ | ||
| 39 | #define DMxCTR_BG_SC4RX 0x0000001a /* - serial port4 reception */ | ||
| 40 | #define DMxCTR_BG_SC5TX 0x0000001b /* - serial port5 transmission */ | ||
| 41 | #define DMxCTR_BG_SC5RX 0x0000001c /* - serial port5 reception */ | ||
| 42 | #define DMxCTR_BG_SC6TX 0x0000001d /* - serial port6 transmission */ | ||
| 43 | #define DMxCTR_BG_SC6RX 0x0000001e /* - serial port6 reception */ | ||
| 44 | #define DMxCTR_BG_TMSUFLOW 0x0000001f /* - timestamp timer underflow */ | ||
| 45 | #define DMxCTR_SAM 0x00000060 /* DMA transfer src addr mode */ | ||
| 46 | #define DMxCTR_SAM_INCR 0x00000000 /* - increment */ | ||
| 47 | #define DMxCTR_SAM_DECR 0x00000020 /* - decrement */ | ||
| 48 | #define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */ | ||
| 49 | #define DMxCTR_DAM 0x00000300 /* DMA transfer dest addr mode */ | ||
| 50 | #define DMxCTR_DAM_INCR 0x00000000 /* - increment */ | ||
| 51 | #define DMxCTR_DAM_DECR 0x00000100 /* - decrement */ | ||
| 52 | #define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */ | ||
| 53 | #define DMxCTR_UT 0x00006000 /* DMA transfer unit */ | ||
| 54 | #define DMxCTR_UT_1 0x00000000 /* - 1 byte */ | ||
| 55 | #define DMxCTR_UT_2 0x00002000 /* - 2 byte */ | ||
| 56 | #define DMxCTR_UT_4 0x00004000 /* - 4 byte */ | ||
| 57 | #define DMxCTR_UT_16 0x00006000 /* - 16 byte */ | ||
| 58 | #define DMxCTR_RRE 0x00008000 /* DMA round robin enable */ | ||
| 59 | #define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */ | ||
| 60 | #define DMxCTR_RQM 0x00060000 /* external request input source mode */ | ||
| 61 | #define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */ | ||
| 62 | #define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */ | ||
| 63 | #define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */ | ||
| 64 | #define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */ | ||
| 65 | #define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */ | ||
| 66 | #define DMxCTR_PERR 0x40000000 /* DMA transfer parameter error flag */ | ||
| 67 | #define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */ | ||
| 68 | |||
| 69 | #define DMxSRC(N) __SYSREG(0xd4005004+(N*0x100), u32) /* control reg */ | ||
| 70 | |||
| 71 | #define DMxDST(N) __SYSREG(0xd4005008+(N*0x100), u32) /* source addr reg */ | ||
| 72 | |||
| 73 | #define DMxSIZ(N) __SYSREG(0xd400500c+(N*0x100), u32) /* dest addr reg */ | ||
| 74 | #define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */ | ||
| 75 | |||
| 76 | #define DMxCYC(N) __SYSREG(0xd4005010+(N*0x100), u32) /* intermittent size reg */ | ||
| 77 | #define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */ | ||
| 78 | |||
| 79 | #define DM0IRQ 16 /* DMA channel 0 complete IRQ */ | ||
| 80 | #define DM1IRQ 17 /* DMA channel 1 complete IRQ */ | ||
| 81 | #define DM2IRQ 18 /* DMA channel 2 complete IRQ */ | ||
| 82 | #define DM3IRQ 19 /* DMA channel 3 complete IRQ */ | ||
| 83 | |||
| 84 | #define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */ | ||
| 85 | #define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */ | ||
| 86 | #define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */ | ||
| 87 | #define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */ | ||
| 88 | |||
| 89 | #ifndef __ASSEMBLY__ | ||
| 90 | |||
| 91 | struct mn10300_dmactl_regs { | ||
| 92 | u32 ctr; | ||
| 93 | const void *src; | ||
| 94 | void *dst; | ||
| 95 | u32 siz; | ||
| 96 | u32 cyc; | ||
| 97 | } __attribute__((aligned(0x100))); | ||
| 98 | |||
| 99 | #endif /* __ASSEMBLY__ */ | ||
| 100 | |||
| 101 | #endif /* __KERNEL__ */ | ||
| 102 | |||
| 103 | #endif /* _ASM_PROC_DMACTL_REGS_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h new file mode 100644 index 000000000000..a1e977273d19 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #ifndef _ASM_PROC_INTCTL_REGS_H | ||
| 2 | #define _ASM_PROC_INTCTL_REGS_H | ||
| 3 | |||
| 4 | #ifndef _ASM_INTCTL_REGS_H | ||
| 5 | # error "please don't include this file directly" | ||
| 6 | #endif | ||
| 7 | |||
| 8 | /* intr acceptance group reg */ | ||
| 9 | #define IAGR __SYSREG(0xd4000100, u16) | ||
| 10 | |||
| 11 | /* group number register */ | ||
| 12 | #define IAGR_GN 0x003fc | ||
| 13 | |||
| 14 | #define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3) | ||
| 15 | |||
| 16 | #define __SET_XIRQ_TRIGGER(X, Y, Z) \ | ||
| 17 | ({ \ | ||
| 18 | typeof(Z) x = (Z); \ | ||
| 19 | x &= ~(3 << ((X) * 2)); \ | ||
| 20 | x |= ((Y) & 3) << ((X) * 2); \ | ||
| 21 | (Z) = x; \ | ||
| 22 | }) | ||
| 23 | |||
| 24 | /* external pin intr spec reg */ | ||
| 25 | #define EXTMD0 __SYSREG(0xd4000200, u32) | ||
| 26 | #define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD0) | ||
| 27 | #define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD0) | ||
| 28 | |||
| 29 | #endif /* _ASM_PROC_INTCTL_REGS_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/irq.h b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h new file mode 100644 index 000000000000..37777a85ab6f --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* MN2WS0050 on-board interrupt controller registers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 7 | * Modifications: | ||
| 8 | * 13-Nov-2006 MEI Define extended IRQ number for SMP support. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _PROC_IRQ_H | ||
| 17 | #define _PROC_IRQ_H | ||
| 18 | |||
| 19 | #ifdef __KERNEL__ | ||
| 20 | |||
| 21 | #define GxICR_NUM_IRQS 163 | ||
| 22 | #ifdef CONFIG_SMP | ||
| 23 | #define GxICR_NUM_EXT_IRQS 197 | ||
| 24 | #endif /* CONFIG_SMP */ | ||
| 25 | |||
| 26 | #define GxICR_NUM_XIRQS 16 | ||
| 27 | |||
| 28 | #define XIRQ0 34 | ||
| 29 | #define XIRQ1 35 | ||
| 30 | #define XIRQ2 36 | ||
| 31 | #define XIRQ3 37 | ||
| 32 | #define XIRQ4 38 | ||
| 33 | #define XIRQ5 39 | ||
| 34 | #define XIRQ6 40 | ||
| 35 | #define XIRQ7 41 | ||
| 36 | #define XIRQ8 42 | ||
| 37 | #define XIRQ9 43 | ||
| 38 | #define XIRQ10 44 | ||
| 39 | #define XIRQ11 45 | ||
| 40 | #define XIRQ12 46 | ||
| 41 | #define XIRQ13 47 | ||
| 42 | #define XIRQ14 48 | ||
| 43 | #define XIRQ15 49 | ||
| 44 | |||
| 45 | #define XIRQ2IRQ(num) (XIRQ0 + num) | ||
| 46 | |||
| 47 | #endif /* __KERNEL__ */ | ||
| 48 | |||
| 49 | #endif /* _PROC_IRQ_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h new file mode 100644 index 000000000000..84448f3828b3 --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | /* NAND flash interface register definitions | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008-2009 Panasonic Corporation | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _PROC_NAND_REGS_H_ | ||
| 17 | #define _PROC_NAND_REGS_H_ | ||
| 18 | |||
| 19 | /* command register */ | ||
| 20 | #define FCOMMAND_0 __SYSREG(0xd8f00000, u8) /* fcommand[24:31] */ | ||
| 21 | #define FCOMMAND_1 __SYSREG(0xd8f00001, u8) /* fcommand[16:23] */ | ||
| 22 | #define FCOMMAND_2 __SYSREG(0xd8f00002, u8) /* fcommand[8:15] */ | ||
| 23 | #define FCOMMAND_3 __SYSREG(0xd8f00003, u8) /* fcommand[0:7] */ | ||
| 24 | |||
| 25 | /* for dma 16 byte trans, use FCOMMAND2 register */ | ||
| 26 | #define FCOMMAND2_0 __SYSREG(0xd8f00110, u8) /* fcommand2[24:31] */ | ||
| 27 | #define FCOMMAND2_1 __SYSREG(0xd8f00111, u8) /* fcommand2[16:23] */ | ||
| 28 | #define FCOMMAND2_2 __SYSREG(0xd8f00112, u8) /* fcommand2[8:15] */ | ||
| 29 | #define FCOMMAND2_3 __SYSREG(0xd8f00113, u8) /* fcommand2[0:7] */ | ||
| 30 | |||
| 31 | #define FCOMMAND_FIEN 0x80 /* nand flash I/F enable */ | ||
| 32 | #define FCOMMAND_BW_8BIT 0x00 /* 8bit bus width */ | ||
| 33 | #define FCOMMAND_BW_16BIT 0x40 /* 16bit bus width */ | ||
| 34 | #define FCOMMAND_BLOCKSZ_SMALL 0x00 /* small block */ | ||
| 35 | #define FCOMMAND_BLOCKSZ_LARGE 0x20 /* large block */ | ||
| 36 | #define FCOMMAND_DMASTART 0x10 /* dma start */ | ||
| 37 | #define FCOMMAND_RYBY 0x08 /* ready/busy flag */ | ||
| 38 | #define FCOMMAND_RYBYINTMSK 0x04 /* mask ready/busy interrupt */ | ||
| 39 | #define FCOMMAND_XFWP 0x02 /* write protect enable */ | ||
| 40 | #define FCOMMAND_XFCE 0x01 /* flash device disable */ | ||
| 41 | #define FCOMMAND_SEQKILL 0x10 /* stop seq-read */ | ||
| 42 | #define FCOMMAND_ANUM 0x07 /* address cycle */ | ||
| 43 | #define FCOMMAND_ANUM_NONE 0x00 /* address cycle none */ | ||
| 44 | #define FCOMMAND_ANUM_1CYC 0x01 /* address cycle 1cycle */ | ||
| 45 | #define FCOMMAND_ANUM_2CYC 0x02 /* address cycle 2cycle */ | ||
| 46 | #define FCOMMAND_ANUM_3CYC 0x03 /* address cycle 3cycle */ | ||
| 47 | #define FCOMMAND_ANUM_4CYC 0x04 /* address cycle 4cycle */ | ||
| 48 | #define FCOMMAND_ANUM_5CYC 0x05 /* address cycle 5cycle */ | ||
| 49 | #define FCOMMAND_FCMD_READ0 0x00 /* read1 command */ | ||
| 50 | #define FCOMMAND_FCMD_SEQIN 0x80 /* page program 1st command */ | ||
| 51 | #define FCOMMAND_FCMD_PAGEPROG 0x10 /* page program 2nd command */ | ||
| 52 | #define FCOMMAND_FCMD_RESET 0xff /* reset command */ | ||
| 53 | #define FCOMMAND_FCMD_ERASE1 0x60 /* erase 1st command */ | ||
| 54 | #define FCOMMAND_FCMD_ERASE2 0xd0 /* erase 2nd command */ | ||
| 55 | #define FCOMMAND_FCMD_STATUS 0x70 /* read status command */ | ||
| 56 | #define FCOMMAND_FCMD_READID 0x90 /* read id command */ | ||
| 57 | #define FCOMMAND_FCMD_READOOB 0x50 /* read3 command */ | ||
| 58 | /* address register */ | ||
| 59 | #define FADD __SYSREG(0xd8f00004, u32) | ||
| 60 | /* address register 2 */ | ||
| 61 | #define FADD2 __SYSREG(0xd8f00008, u32) | ||
| 62 | /* error judgement register */ | ||
| 63 | #define FJUDGE __SYSREG(0xd8f0000c, u32) | ||
| 64 | #define FJUDGE_NOERR 0x0 /* no error */ | ||
| 65 | #define FJUDGE_1BITERR 0x1 /* 1bit error in data area */ | ||
| 66 | #define FJUDGE_PARITYERR 0x2 /* parity error */ | ||
| 67 | #define FJUDGE_UNCORRECTABLE 0x3 /* uncorrectable error */ | ||
| 68 | #define FJUDGE_ERRJDG_MSK 0x3 /* mask of judgement result */ | ||
| 69 | /* 1st ECC store register */ | ||
| 70 | #define FECC11 __SYSREG(0xd8f00010, u32) | ||
| 71 | /* 2nd ECC store register */ | ||
| 72 | #define FECC12 __SYSREG(0xd8f00014, u32) | ||
| 73 | /* 3rd ECC store register */ | ||
| 74 | #define FECC21 __SYSREG(0xd8f00018, u32) | ||
| 75 | /* 4th ECC store register */ | ||
| 76 | #define FECC22 __SYSREG(0xd8f0001c, u32) | ||
| 77 | /* 5th ECC store register */ | ||
| 78 | #define FECC31 __SYSREG(0xd8f00020, u32) | ||
| 79 | /* 6th ECC store register */ | ||
| 80 | #define FECC32 __SYSREG(0xd8f00024, u32) | ||
| 81 | /* 7th ECC store register */ | ||
| 82 | #define FECC41 __SYSREG(0xd8f00028, u32) | ||
| 83 | /* 8th ECC store register */ | ||
| 84 | #define FECC42 __SYSREG(0xd8f0002c, u32) | ||
| 85 | /* data register */ | ||
| 86 | #define FDATA __SYSREG(0xd8f00030, u32) | ||
| 87 | /* access pulse register */ | ||
| 88 | #define FPWS __SYSREG(0xd8f00100, u32) | ||
| 89 | #define FPWS_PWS1W_2CLK 0x00000000 /* write pulse width 1clock */ | ||
| 90 | #define FPWS_PWS1W_3CLK 0x01000000 /* write pulse width 2clock */ | ||
| 91 | #define FPWS_PWS1W_4CLK 0x02000000 /* write pulse width 4clock */ | ||
| 92 | #define FPWS_PWS1W_5CLK 0x03000000 /* write pulse width 5clock */ | ||
| 93 | #define FPWS_PWS1W_6CLK 0x04000000 /* write pulse width 6clock */ | ||
| 94 | #define FPWS_PWS1W_7CLK 0x05000000 /* write pulse width 7clock */ | ||
| 95 | #define FPWS_PWS1W_8CLK 0x06000000 /* write pulse width 8clock */ | ||
| 96 | #define FPWS_PWS1R_3CLK 0x00010000 /* read pulse width 3clock */ | ||
| 97 | #define FPWS_PWS1R_4CLK 0x00020000 /* read pulse width 4clock */ | ||
| 98 | #define FPWS_PWS1R_5CLK 0x00030000 /* read pulse width 5clock */ | ||
| 99 | #define FPWS_PWS1R_6CLK 0x00040000 /* read pulse width 6clock */ | ||
| 100 | #define FPWS_PWS1R_7CLK 0x00050000 /* read pulse width 7clock */ | ||
| 101 | #define FPWS_PWS1R_8CLK 0x00060000 /* read pulse width 8clock */ | ||
| 102 | #define FPWS_PWS2W_2CLK 0x00000100 /* write pulse interval 2clock */ | ||
| 103 | #define FPWS_PWS2W_3CLK 0x00000200 /* write pulse interval 3clock */ | ||
| 104 | #define FPWS_PWS2W_4CLK 0x00000300 /* write pulse interval 4clock */ | ||
| 105 | #define FPWS_PWS2W_5CLK 0x00000400 /* write pulse interval 5clock */ | ||
| 106 | #define FPWS_PWS2W_6CLK 0x00000500 /* write pulse interval 6clock */ | ||
| 107 | #define FPWS_PWS2R_2CLK 0x00000001 /* read pulse interval 2clock */ | ||
| 108 | #define FPWS_PWS2R_3CLK 0x00000002 /* read pulse interval 3clock */ | ||
| 109 | #define FPWS_PWS2R_4CLK 0x00000003 /* read pulse interval 4clock */ | ||
| 110 | #define FPWS_PWS2R_5CLK 0x00000004 /* read pulse interval 5clock */ | ||
| 111 | #define FPWS_PWS2R_6CLK 0x00000005 /* read pulse interval 6clock */ | ||
| 112 | /* command register 2 */ | ||
| 113 | #define FCOMMAND2 __SYSREG(0xd8f00110, u32) | ||
| 114 | /* transfer frequency register */ | ||
| 115 | #define FNUM __SYSREG(0xd8f00114, u32) | ||
| 116 | #define FSDATA_ADDR 0xd8f00400 | ||
| 117 | /* active data register */ | ||
| 118 | #define FSDATA __SYSREG(FSDATA_ADDR, u32) | ||
| 119 | |||
| 120 | #endif /* _PROC_NAND_REGS_H_ */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/proc.h b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h new file mode 100644 index 000000000000..90d5cadd05bd --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* proc.h: MN2WS0050 processor description | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _ASM_PROC_PROC_H | ||
| 13 | #define _ASM_PROC_PROC_H | ||
| 14 | |||
| 15 | #define PROCESSOR_VENDOR_NAME "Panasonic" | ||
| 16 | #define PROCESSOR_MODEL_NAME "mn2ws0050" | ||
| 17 | |||
| 18 | #endif /* _ASM_PROC_PROC_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h new file mode 100644 index 000000000000..22f277fbb4de --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* MN10300/AM33v2 Microcontroller SMP registers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * Created: | ||
| 6 | * 13-Nov-2006 MEI Add extended cache and atomic operation register | ||
| 7 | * for SMP support. | ||
| 8 | * 23-Feb-2007 MEI Add define for gdbstub SMP. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _ASM_PROC_SMP_REGS_H | ||
| 17 | #define _ASM_PROC_SMP_REGS_H | ||
| 18 | |||
| 19 | #ifdef __KERNEL__ | ||
| 20 | |||
| 21 | #ifndef __ASSEMBLY__ | ||
| 22 | #include <linux/types.h> | ||
| 23 | #endif | ||
| 24 | #include <asm/cpu-regs.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Reference to the interrupt controllers of other CPUs | ||
| 28 | */ | ||
| 29 | #define CROSS_ICR_CPU_SHIFT 16 | ||
| 30 | |||
| 31 | #define CROSS_GxICR(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \ | ||
| 32 | ((X) >= 64 && (X) < 192) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u16) | ||
| 33 | #define CROSS_GxICR_u8(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \ | ||
| 34 | (((X) >= 64) && ((X) < 192)) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u8) | ||
| 35 | |||
| 36 | /* CPU ID register */ | ||
| 37 | #define CPUID __SYSREGC(0xc0000054, u32) | ||
| 38 | #define CPUID_MASK 0x00000007 /* CPU ID mask */ | ||
| 39 | |||
| 40 | /* extended cache control register */ | ||
| 41 | #define ECHCTR __SYSREG(0xc0000c20, u32) | ||
| 42 | #define ECHCTR_IBCM 0x00000001 /* instruction cache broad cast mask */ | ||
| 43 | #define ECHCTR_DBCM 0x00000002 /* data cache broad cast mask */ | ||
| 44 | #define ECHCTR_ISPM 0x00000004 /* instruction cache snoop mask */ | ||
| 45 | #define ECHCTR_DSPM 0x00000008 /* data cache snoop mask */ | ||
| 46 | |||
| 47 | #define NMIAGR __SYSREG(0xd400013c, u16) | ||
| 48 | #define NMIAGR_GN 0x03fc | ||
| 49 | |||
| 50 | #endif /* __KERNEL__ */ | ||
| 51 | #endif /* _ASM_PROC_SMP_REGS_H */ | ||
| diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c new file mode 100644 index 000000000000..c58249b9525a --- /dev/null +++ b/arch/mn10300/proc-mn2ws0050/proc-init.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* MN2WS0050 processor initialisation | ||
| 2 | * | ||
| 3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/sched.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | |||
| 17 | #include <asm/processor.h> | ||
| 18 | #include <asm/system.h> | ||
| 19 | #include <asm/uaccess.h> | ||
| 20 | #include <asm/io.h> | ||
| 21 | #include <asm/atomic.h> | ||
| 22 | #include <asm/smp.h> | ||
| 23 | #include <asm/pgalloc.h> | ||
| 24 | #include <asm/busctl-regs.h> | ||
| 25 | #include <unit/timex.h> | ||
| 26 | #include <asm/fpu.h> | ||
| 27 | #include <asm/rtc.h> | ||
| 28 | |||
| 29 | #define MEMCONF __SYSREGC(0xdf800400, u32) | ||
| 30 | |||
| 31 | /* | ||
| 32 | * initialise the on-silicon processor peripherals | ||
| 33 | */ | ||
| 34 | asmlinkage void __init processor_init(void) | ||
| 35 | { | ||
| 36 | int loop; | ||
| 37 | |||
| 38 | /* set up the exception table first */ | ||
| 39 | for (loop = 0x000; loop < 0x400; loop += 8) | ||
| 40 | __set_intr_stub(loop, __common_exception); | ||
| 41 | |||
| 42 | __set_intr_stub(EXCEP_ITLBMISS, itlb_miss); | ||
| 43 | __set_intr_stub(EXCEP_DTLBMISS, dtlb_miss); | ||
| 44 | __set_intr_stub(EXCEP_IAERROR, itlb_aerror); | ||
| 45 | __set_intr_stub(EXCEP_DAERROR, dtlb_aerror); | ||
| 46 | __set_intr_stub(EXCEP_BUSERROR, raw_bus_error); | ||
| 47 | __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault); | ||
| 48 | __set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled); | ||
| 49 | __set_intr_stub(EXCEP_SYSCALL0, system_call); | ||
| 50 | |||
| 51 | __set_intr_stub(EXCEP_NMI, nmi_handler); | ||
| 52 | __set_intr_stub(EXCEP_WDT, nmi_handler); | ||
| 53 | __set_intr_stub(EXCEP_IRQ_LEVEL0, irq_handler); | ||
| 54 | __set_intr_stub(EXCEP_IRQ_LEVEL1, irq_handler); | ||
| 55 | __set_intr_stub(EXCEP_IRQ_LEVEL2, irq_handler); | ||
| 56 | __set_intr_stub(EXCEP_IRQ_LEVEL3, irq_handler); | ||
| 57 | __set_intr_stub(EXCEP_IRQ_LEVEL4, irq_handler); | ||
| 58 | __set_intr_stub(EXCEP_IRQ_LEVEL5, irq_handler); | ||
| 59 | __set_intr_stub(EXCEP_IRQ_LEVEL6, irq_handler); | ||
| 60 | |||
| 61 | IVAR0 = EXCEP_IRQ_LEVEL0; | ||
| 62 | IVAR1 = EXCEP_IRQ_LEVEL1; | ||
| 63 | IVAR2 = EXCEP_IRQ_LEVEL2; | ||
| 64 | IVAR3 = EXCEP_IRQ_LEVEL3; | ||
| 65 | IVAR4 = EXCEP_IRQ_LEVEL4; | ||
| 66 | IVAR5 = EXCEP_IRQ_LEVEL5; | ||
| 67 | IVAR6 = EXCEP_IRQ_LEVEL6; | ||
| 68 | |||
| 69 | #ifndef CONFIG_MN10300_HAS_CACHE_SNOOP | ||
| 70 | mn10300_dcache_flush_inv(); | ||
| 71 | mn10300_icache_inv(); | ||
| 72 | #endif | ||
| 73 | |||
| 74 | /* disable all interrupts and set to priority 6 (lowest) */ | ||
| 75 | #ifdef CONFIG_SMP | ||
| 76 | for (loop = 0; loop < GxICR_NUM_IRQS; loop++) | ||
| 77 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | ||
| 78 | #else /* !CONFIG_SMP */ | ||
| 79 | for (loop = 0; loop < NR_IRQS; loop++) | ||
| 80 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | ||
| 81 | #endif /* !CONFIG_SMP */ | ||
| 82 | |||
| 83 | /* clear the timers */ | ||
| 84 | TM0MD = 0; | ||
| 85 | TM1MD = 0; | ||
| 86 | TM2MD = 0; | ||
| 87 | TM3MD = 0; | ||
| 88 | TM4MD = 0; | ||
| 89 | TM5MD = 0; | ||
| 90 | TM6MD = 0; | ||
| 91 | TM6MDA = 0; | ||
| 92 | TM6MDB = 0; | ||
| 93 | TM7MD = 0; | ||
| 94 | TM8MD = 0; | ||
| 95 | TM9MD = 0; | ||
| 96 | TM10MD = 0; | ||
| 97 | TM11MD = 0; | ||
| 98 | TM12MD = 0; | ||
| 99 | TM13MD = 0; | ||
| 100 | TM14MD = 0; | ||
| 101 | TM15MD = 0; | ||
| 102 | |||
| 103 | calibrate_clock(); | ||
| 104 | } | ||
| 105 | |||
| 106 | /* | ||
| 107 | * determine the memory size and base from the memory controller regs | ||
| 108 | */ | ||
| 109 | void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size) | ||
| 110 | { | ||
| 111 | unsigned long memconf = MEMCONF; | ||
| 112 | unsigned long size = 0; /* order: MByte */ | ||
| 113 | |||
| 114 | *mem_base = 0x90000000; /* fixed address */ | ||
| 115 | |||
| 116 | switch (memconf & 0x00000003) { | ||
| 117 | case 0x01: | ||
| 118 | size = 256 / 8; /* 256 Mbit per chip */ | ||
| 119 | break; | ||
| 120 | case 0x02: | ||
| 121 | size = 512 / 8; /* 512 Mbit per chip */ | ||
| 122 | break; | ||
| 123 | case 0x03: | ||
| 124 | size = 1024 / 8; /* 1 Gbit per chip */ | ||
| 125 | break; | ||
| 126 | default: | ||
| 127 | panic("Invalid SDRAM size"); | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | printk(KERN_INFO "DDR2-SDRAM: %luMB x 2 @%08lx\n", size, *mem_base); | ||
| 132 | |||
| 133 | *mem_size = (size * 2) << 20; | ||
| 134 | } | ||
| diff --git a/arch/mn10300/unit-asb2303/include/unit/clock.h b/arch/mn10300/unit-asb2303/include/unit/clock.h index 2a0bf79ab968..0316907a012e 100644 --- a/arch/mn10300/unit-asb2303/include/unit/clock.h +++ b/arch/mn10300/unit-asb2303/include/unit/clock.h | |||
| @@ -14,32 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ | 
| 16 | 16 | ||
| 17 | #ifdef CONFIG_MN10300_RTC | ||
| 18 | |||
| 19 | extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */ | ||
| 20 | extern unsigned long mn10300_iobclk; | ||
| 21 | extern unsigned long mn10300_tsc_per_HZ; | ||
| 22 | |||
| 23 | #define MN10300_IOCLK mn10300_ioclk | ||
| 24 | /* If this processors has a another clock, uncomment the below. */ | ||
| 25 | /* #define MN10300_IOBCLK mn10300_iobclk */ | ||
| 26 | |||
| 27 | #else /* !CONFIG_MN10300_RTC */ | ||
| 28 | |||
| 29 | #define MN10300_IOCLK 33333333UL | 17 | #define MN10300_IOCLK 33333333UL | 
| 30 | /* #define MN10300_IOBCLK 66666666UL */ | 18 | /* #define MN10300_IOBCLK 66666666UL */ | 
| 31 | 19 | ||
| 32 | #endif /* !CONFIG_MN10300_RTC */ | ||
| 33 | |||
| 34 | #define MN10300_JCCLK MN10300_IOCLK | ||
| 35 | #define MN10300_TSCCLK MN10300_IOCLK | ||
| 36 | |||
| 37 | #ifdef CONFIG_MN10300_RTC | ||
| 38 | #define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ | ||
| 39 | #else /* !CONFIG_MN10300_RTC */ | ||
| 40 | #define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ) | ||
| 41 | #endif /* !CONFIG_MN10300_RTC */ | ||
| 42 | |||
| 43 | #endif /* !__ASSEMBLY__ */ | 20 | #endif /* !__ASSEMBLY__ */ | 
| 44 | 21 | ||
| 22 | #define MN10300_WDCLK MN10300_IOCLK | ||
| 23 | |||
| 45 | #endif /* _ASM_UNIT_CLOCK_H */ | 24 | #endif /* _ASM_UNIT_CLOCK_H */ | 
| diff --git a/arch/mn10300/unit-asb2303/include/unit/serial.h b/arch/mn10300/unit-asb2303/include/unit/serial.h index 047566cd2e36..991e356bac5f 100644 --- a/arch/mn10300/unit-asb2303/include/unit/serial.h +++ b/arch/mn10300/unit-asb2303/include/unit/serial.h | |||
| @@ -22,6 +22,11 @@ | |||
| 22 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 22 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 
| 23 | 23 | ||
| 24 | /* | 24 | /* | 
| 25 | * The ASB2303 has an 18.432 MHz clock the UART | ||
| 26 | */ | ||
| 27 | #define BASE_BAUD (18432000 / 16) | ||
| 28 | |||
| 29 | /* | ||
| 25 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports | 30 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports | 
| 26 | */ | 31 | */ | 
| 27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 32 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 
| diff --git a/arch/mn10300/unit-asb2303/include/unit/timex.h b/arch/mn10300/unit-asb2303/include/unit/timex.h index f206b63c95b4..cc18fe7d8b90 100644 --- a/arch/mn10300/unit-asb2303/include/unit/timex.h +++ b/arch/mn10300/unit-asb2303/include/unit/timex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* ASB2303-specific timer specifcations | 1 | /* ASB2303-specific timer specifications | 
| 2 | * | 2 | * | 
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved. | 
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) | 
| 5 | * | 5 | * | 
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or | 
| @@ -17,67 +17,72 @@ | |||
| 17 | 17 | ||
| 18 | #include <asm/timer-regs.h> | 18 | #include <asm/timer-regs.h> | 
| 19 | #include <unit/clock.h> | 19 | #include <unit/clock.h> | 
| 20 | #include <asm/param.h> | ||
| 20 | 21 | ||
| 21 | /* | 22 | /* | 
| 22 | * jiffies counter specifications | 23 | * jiffies counter specifications | 
| 23 | */ | 24 | */ | 
| 24 | 25 | ||
| 25 | #define TMJCBR_MAX 0xffff | 26 | #define TMJCBR_MAX 0xffff | 
| 26 | #define TMJCBC TM01BC | ||
| 27 | |||
| 28 | #define TMJCMD TM01MD | ||
| 29 | #define TMJCBR TM01BR | ||
| 30 | #define TMJCIRQ TM1IRQ | 27 | #define TMJCIRQ TM1IRQ | 
| 31 | #define TMJCICR TM1ICR | 28 | #define TMJCICR TM1ICR | 
| 32 | #define TMJCICR_LEVEL GxICR_LEVEL_5 | ||
| 33 | 29 | ||
| 34 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ | 
| 35 | 31 | ||
| 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) | ||
| 37 | { | 61 | { | 
| 38 | unsigned rate; | 62 | u16 tmp; | 
| 39 | u16 md, t16; | 63 | TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8; | 
| 40 | 64 | tmp = TM01MD; | |
| 41 | /* use as little prescaling as possible to avoid losing accuracy */ | 65 | } | 
| 42 | md = TM0MD_SRC_IOCLK; | ||
| 43 | rate = MN10300_JCCLK / HZ; | ||
| 44 | |||
| 45 | if (rate > TMJCBR_MAX) { | ||
| 46 | md = TM0MD_SRC_IOCLK_8; | ||
| 47 | rate = MN10300_JCCLK / 8 / HZ; | ||
| 48 | |||
| 49 | if (rate > TMJCBR_MAX) { | ||
| 50 | md = TM0MD_SRC_IOCLK_32; | ||
| 51 | rate = MN10300_JCCLK / 32 / HZ; | ||
| 52 | |||
| 53 | if (rate > TMJCBR_MAX) | ||
| 54 | BUG(); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | 66 | ||
| 58 | TMJCBR = rate - 1; | 67 | static inline void reload_jiffies_counter(u32 cnt) | 
| 59 | t16 = TMJCBR; | 68 | { | 
| 69 | u32 tmp; | ||
| 60 | 70 | ||
| 61 | TMJCMD = | 71 | TM01BR = cnt; | 
| 62 | md | | 72 | tmp = TM01BR; | 
| 63 | TM1MD_SRC_TM0CASCADE << 8 | | ||
| 64 | TM0MD_INIT_COUNTER | | ||
| 65 | TM1MD_INIT_COUNTER << 8; | ||
| 66 | 73 | ||
| 67 | TMJCMD = | 74 | TM01MD = JC_TIMER_CLKSRC | \ | 
| 68 | md | | 75 | TM1MD_SRC_TM0CASCADE << 8 | \ | 
| 69 | TM1MD_SRC_TM0CASCADE << 8 | | 76 | TM0MD_INIT_COUNTER | \ | 
| 70 | TM0MD_COUNT_ENABLE | | 77 | TM1MD_INIT_COUNTER << 8; | 
| 71 | TM1MD_COUNT_ENABLE << 8; | ||
| 72 | 78 | ||
| 73 | t16 = TMJCMD; | ||
| 74 | 79 | ||
| 75 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | 80 | TM01MD = JC_TIMER_CLKSRC | \ | 
| 76 | t16 = TMJCICR; | 81 | TM1MD_SRC_TM0CASCADE << 8 | \ | 
| 77 | } | 82 | TM0MD_COUNT_ENABLE | \ | 
| 83 | TM1MD_COUNT_ENABLE << 8; | ||
| 78 | 84 | ||
| 79 | static inline void shutdown_jiffies_counter(void) | 85 | tmp = TM01MD; | 
| 80 | { | ||
| 81 | } | 86 | } | 
| 82 | 87 | ||
| 83 | #endif /* !__ASSEMBLY__ */ | 88 | #endif /* !__ASSEMBLY__ */ | 
| @@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void) | |||
| 94 | 99 | ||
| 95 | static inline void startup_timestamp_counter(void) | 100 | static inline void startup_timestamp_counter(void) | 
| 96 | { | 101 | { | 
| 102 | u32 t32; | ||
| 103 | |||
| 97 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 104 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 
| 98 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 105 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 
| 99 | */ | 106 | */ | 
| 100 | TM45BR = TMTSCBR_MAX; | 107 | TM45BR = TMTSCBR_MAX; | 
| 108 | t32 = TM45BR; | ||
| 101 | 109 | ||
| 102 | TM4MD = TM4MD_SRC_IOCLK; | 110 | TM4MD = TSC_TIMER_CLKSRC; | 
| 103 | TM4MD |= TM4MD_INIT_COUNTER; | 111 | TM4MD |= TM4MD_INIT_COUNTER; | 
| 104 | TM4MD &= ~TM4MD_INIT_COUNTER; | 112 | TM4MD &= ~TM4MD_INIT_COUNTER; | 
| 105 | TM4ICR = 0; | 113 | TM4ICR = 0; | 
| 114 | t32 = TM4ICR; | ||
| 106 | 115 | ||
| 107 | TM5MD = TM5MD_SRC_TM4CASCADE; | 116 | TM5MD = TM5MD_SRC_TM4CASCADE; | 
| 108 | TM5MD |= TM5MD_INIT_COUNTER; | 117 | TM5MD |= TM5MD_INIT_COUNTER; | 
| 109 | TM5MD &= ~TM5MD_INIT_COUNTER; | 118 | TM5MD &= ~TM5MD_INIT_COUNTER; | 
| 110 | TM5ICR = 0; | 119 | TM5ICR = 0; | 
| 120 | t32 = TM5ICR; | ||
| 111 | 121 | ||
| 112 | TM5MD |= TM5MD_COUNT_ENABLE; | 122 | TM5MD |= TM5MD_COUNT_ENABLE; | 
| 113 | TM4MD |= TM4MD_COUNT_ENABLE; | 123 | TM4MD |= TM4MD_COUNT_ENABLE; | 
| 124 | t32 = TM5MD; | ||
| 125 | t32 = TM4MD; | ||
| 114 | } | 126 | } | 
| 115 | 127 | ||
| 116 | static inline void shutdown_timestamp_counter(void) | 128 | static inline void shutdown_timestamp_counter(void) | 
| 117 | { | 129 | { | 
| 130 | u8 t8; | ||
| 118 | TM4MD = 0; | 131 | TM4MD = 0; | 
| 119 | TM5MD = 0; | 132 | TM5MD = 0; | 
| 133 | t8 = TM4MD; | ||
| 134 | t8 = TM5MD; | ||
| 120 | } | 135 | } | 
| 121 | 136 | ||
| 122 | /* | 137 | /* | 
| @@ -127,7 +142,7 @@ typedef unsigned long cycles_t; | |||
| 127 | 142 | ||
| 128 | static inline cycles_t read_timestamp_counter(void) | 143 | static inline cycles_t read_timestamp_counter(void) | 
| 129 | { | 144 | { | 
| 130 | return (cycles_t)TMTSCBC; | 145 | return (cycles_t)~TMTSCBC; | 
| 131 | } | 146 | } | 
| 132 | 147 | ||
| 133 | #endif /* !__ASSEMBLY__ */ | 148 | #endif /* !__ASSEMBLY__ */ | 
| diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c index 70e8cb4ea266..834a76aa551a 100644 --- a/arch/mn10300/unit-asb2303/unit-init.c +++ b/arch/mn10300/unit-asb2303/unit-init.c | |||
| @@ -31,6 +31,14 @@ asmlinkage void __init unit_init(void) | |||
| 31 | SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL); | 31 | SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL); | 
| 32 | SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL); | 32 | SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL); | 
| 33 | SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL); | 33 | SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL); | 
| 34 | |||
| 35 | #ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL | ||
| 36 | set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL)); | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #ifdef CONFIG_ETHERNET_IRQ_LEVEL | ||
| 40 | set_intr_level(XIRQ3, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL)); | ||
| 41 | #endif | ||
| 34 | } | 42 | } | 
| 35 | 43 | ||
| 36 | /* | 44 | /* | 
| @@ -51,7 +59,7 @@ void __init unit_init_IRQ(void) | |||
| 51 | switch (GET_XIRQ_TRIGGER(extnum)) { | 59 | switch (GET_XIRQ_TRIGGER(extnum)) { | 
| 52 | case XIRQ_TRIGGER_HILEVEL: | 60 | case XIRQ_TRIGGER_HILEVEL: | 
| 53 | case XIRQ_TRIGGER_LOWLEVEL: | 61 | case XIRQ_TRIGGER_LOWLEVEL: | 
| 54 | set_intr_postackable(XIRQ2IRQ(extnum)); | 62 | mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum)); | 
| 55 | break; | 63 | break; | 
| 56 | default: | 64 | default: | 
| 57 | break; | 65 | break; | 
| diff --git a/arch/mn10300/unit-asb2305/include/unit/clock.h b/arch/mn10300/unit-asb2305/include/unit/clock.h index 67be3f2eb18e..29e3425431cf 100644 --- a/arch/mn10300/unit-asb2305/include/unit/clock.h +++ b/arch/mn10300/unit-asb2305/include/unit/clock.h | |||
| @@ -14,32 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ | 
| 16 | 16 | ||
| 17 | #ifdef CONFIG_MN10300_RTC | ||
| 18 | |||
| 19 | extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */ | ||
| 20 | extern unsigned long mn10300_iobclk; | ||
| 21 | extern unsigned long mn10300_tsc_per_HZ; | ||
| 22 | |||
| 23 | #define MN10300_IOCLK mn10300_ioclk | ||
| 24 | /* If this processors has a another clock, uncomment the below. */ | ||
| 25 | /* #define MN10300_IOBCLK mn10300_iobclk */ | ||
| 26 | |||
| 27 | #else /* !CONFIG_MN10300_RTC */ | ||
| 28 | |||
| 29 | #define MN10300_IOCLK 33333333UL | 17 | #define MN10300_IOCLK 33333333UL | 
| 30 | /* #define MN10300_IOBCLK 66666666UL */ | 18 | /* #define MN10300_IOBCLK 66666666UL */ | 
| 31 | 19 | ||
| 32 | #endif /* !CONFIG_MN10300_RTC */ | ||
| 33 | |||
| 34 | #define MN10300_JCCLK MN10300_IOCLK | ||
| 35 | #define MN10300_TSCCLK MN10300_IOCLK | ||
| 36 | |||
| 37 | #ifdef CONFIG_MN10300_RTC | ||
| 38 | #define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ | ||
| 39 | #else /* !CONFIG_MN10300_RTC */ | ||
| 40 | #define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ) | ||
| 41 | #endif /* !CONFIG_MN10300_RTC */ | ||
| 42 | |||
| 43 | #endif /* !__ASSEMBLY__ */ | 20 | #endif /* !__ASSEMBLY__ */ | 
| 44 | 21 | ||
| 22 | #define MN10300_WDCLK MN10300_IOCLK | ||
| 23 | |||
| 45 | #endif /* _ASM_UNIT_CLOCK_H */ | 24 | #endif /* _ASM_UNIT_CLOCK_H */ | 
| diff --git a/arch/mn10300/unit-asb2305/include/unit/serial.h b/arch/mn10300/unit-asb2305/include/unit/serial.h index 8086cc092cec..88c08219315f 100644 --- a/arch/mn10300/unit-asb2305/include/unit/serial.h +++ b/arch/mn10300/unit-asb2305/include/unit/serial.h | |||
| @@ -21,6 +21,11 @@ | |||
| 21 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 21 | #define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */ | 
| 22 | 22 | ||
| 23 | /* | 23 | /* | 
| 24 | * The ASB2305 has an 18.432 MHz clock the UART | ||
| 25 | */ | ||
| 26 | #define BASE_BAUD (18432000 / 16) | ||
| 27 | |||
| 28 | /* | ||
| 24 | * dispose of the /dev/ttyS0 serial port | 29 | * dispose of the /dev/ttyS0 serial port | 
| 25 | */ | 30 | */ | 
| 26 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 31 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 
| diff --git a/arch/mn10300/unit-asb2305/include/unit/timex.h b/arch/mn10300/unit-asb2305/include/unit/timex.h index d1c72d59fa9f..758af30d1a16 100644 --- a/arch/mn10300/unit-asb2305/include/unit/timex.h +++ b/arch/mn10300/unit-asb2305/include/unit/timex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* ASB2305 timer specifcations | 1 | /* ASB2305-specific timer specifications | 
| 2 | * | 2 | * | 
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved. | 
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) | 
| 5 | * | 5 | * | 
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or | 
| @@ -17,67 +17,72 @@ | |||
| 17 | 17 | ||
| 18 | #include <asm/timer-regs.h> | 18 | #include <asm/timer-regs.h> | 
| 19 | #include <unit/clock.h> | 19 | #include <unit/clock.h> | 
| 20 | #include <asm/param.h> | ||
| 20 | 21 | ||
| 21 | /* | 22 | /* | 
| 22 | * jiffies counter specifications | 23 | * jiffies counter specifications | 
| 23 | */ | 24 | */ | 
| 24 | 25 | ||
| 25 | #define TMJCBR_MAX 0xffff | 26 | #define TMJCBR_MAX 0xffff | 
| 26 | #define TMJCBC TM01BC | ||
| 27 | |||
| 28 | #define TMJCMD TM01MD | ||
| 29 | #define TMJCBR TM01BR | ||
| 30 | #define TMJCIRQ TM1IRQ | 27 | #define TMJCIRQ TM1IRQ | 
| 31 | #define TMJCICR TM1ICR | 28 | #define TMJCICR TM1ICR | 
| 32 | #define TMJCICR_LEVEL GxICR_LEVEL_5 | ||
| 33 | 29 | ||
| 34 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ | 
| 35 | 31 | ||
| 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) | ||
| 37 | { | 61 | { | 
| 38 | unsigned rate; | 62 | u16 tmp; | 
| 39 | u16 md, t16; | 63 | TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8; | 
| 40 | 64 | tmp = TM01MD; | |
| 41 | /* use as little prescaling as possible to avoid losing accuracy */ | 65 | } | 
| 42 | md = TM0MD_SRC_IOCLK; | ||
| 43 | rate = MN10300_JCCLK / HZ; | ||
| 44 | |||
| 45 | if (rate > TMJCBR_MAX) { | ||
| 46 | md = TM0MD_SRC_IOCLK_8; | ||
| 47 | rate = MN10300_JCCLK / 8 / HZ; | ||
| 48 | |||
| 49 | if (rate > TMJCBR_MAX) { | ||
| 50 | md = TM0MD_SRC_IOCLK_32; | ||
| 51 | rate = MN10300_JCCLK / 32 / HZ; | ||
| 52 | |||
| 53 | if (rate > TMJCBR_MAX) | ||
| 54 | BUG(); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | 66 | ||
| 58 | TMJCBR = rate - 1; | 67 | static inline void reload_jiffies_counter(u32 cnt) | 
| 59 | t16 = TMJCBR; | 68 | { | 
| 69 | u32 tmp; | ||
| 60 | 70 | ||
| 61 | TMJCMD = | 71 | TM01BR = cnt; | 
| 62 | md | | 72 | tmp = TM01BR; | 
| 63 | TM1MD_SRC_TM0CASCADE << 8 | | ||
| 64 | TM0MD_INIT_COUNTER | | ||
| 65 | TM1MD_INIT_COUNTER << 8; | ||
| 66 | 73 | ||
| 67 | TMJCMD = | 74 | TM01MD = JC_TIMER_CLKSRC | \ | 
| 68 | md | | 75 | TM1MD_SRC_TM0CASCADE << 8 | \ | 
| 69 | TM1MD_SRC_TM0CASCADE << 8 | | 76 | TM0MD_INIT_COUNTER | \ | 
| 70 | TM0MD_COUNT_ENABLE | | 77 | TM1MD_INIT_COUNTER << 8; | 
| 71 | TM1MD_COUNT_ENABLE << 8; | ||
| 72 | 78 | ||
| 73 | t16 = TMJCMD; | ||
| 74 | 79 | ||
| 75 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | 80 | TM01MD = JC_TIMER_CLKSRC | \ | 
| 76 | t16 = TMJCICR; | 81 | TM1MD_SRC_TM0CASCADE << 8 | \ | 
| 77 | } | 82 | TM0MD_COUNT_ENABLE | \ | 
| 83 | TM1MD_COUNT_ENABLE << 8; | ||
| 78 | 84 | ||
| 79 | static inline void shutdown_jiffies_counter(void) | 85 | tmp = TM01MD; | 
| 80 | { | ||
| 81 | } | 86 | } | 
| 82 | 87 | ||
| 83 | #endif /* !__ASSEMBLY__ */ | 88 | #endif /* !__ASSEMBLY__ */ | 
| @@ -94,29 +99,39 @@ static inline void shutdown_jiffies_counter(void) | |||
| 94 | 99 | ||
| 95 | static inline void startup_timestamp_counter(void) | 100 | static inline void startup_timestamp_counter(void) | 
| 96 | { | 101 | { | 
| 102 | u32 t32; | ||
| 103 | |||
| 97 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 104 | /* set up timer 4 & 5 cascaded as a 32-bit counter to count real time | 
| 98 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 105 | * - count down from 4Gig-1 to 0 and wrap at IOCLK rate | 
| 99 | */ | 106 | */ | 
| 100 | TM45BR = TMTSCBR_MAX; | 107 | TM45BR = TMTSCBR_MAX; | 
| 108 | t32 = TM45BR; | ||
| 101 | 109 | ||
| 102 | TM4MD = TM4MD_SRC_IOCLK; | 110 | TM4MD = TSC_TIMER_CLKSRC; | 
| 103 | TM4MD |= TM4MD_INIT_COUNTER; | 111 | TM4MD |= TM4MD_INIT_COUNTER; | 
| 104 | TM4MD &= ~TM4MD_INIT_COUNTER; | 112 | TM4MD &= ~TM4MD_INIT_COUNTER; | 
| 105 | TM4ICR = 0; | 113 | TM4ICR = 0; | 
| 114 | t32 = TM4ICR; | ||
| 106 | 115 | ||
| 107 | TM5MD = TM5MD_SRC_TM4CASCADE; | 116 | TM5MD = TM5MD_SRC_TM4CASCADE; | 
| 108 | TM5MD |= TM5MD_INIT_COUNTER; | 117 | TM5MD |= TM5MD_INIT_COUNTER; | 
| 109 | TM5MD &= ~TM5MD_INIT_COUNTER; | 118 | TM5MD &= ~TM5MD_INIT_COUNTER; | 
| 110 | TM5ICR = 0; | 119 | TM5ICR = 0; | 
| 120 | t32 = TM5ICR; | ||
| 111 | 121 | ||
| 112 | TM5MD |= TM5MD_COUNT_ENABLE; | 122 | TM5MD |= TM5MD_COUNT_ENABLE; | 
| 113 | TM4MD |= TM4MD_COUNT_ENABLE; | 123 | TM4MD |= TM4MD_COUNT_ENABLE; | 
| 124 | t32 = TM5MD; | ||
| 125 | t32 = TM4MD; | ||
| 114 | } | 126 | } | 
| 115 | 127 | ||
| 116 | static inline void shutdown_timestamp_counter(void) | 128 | static inline void shutdown_timestamp_counter(void) | 
| 117 | { | 129 | { | 
| 130 | u8 t8; | ||
| 118 | TM4MD = 0; | 131 | TM4MD = 0; | 
| 119 | TM5MD = 0; | 132 | TM5MD = 0; | 
| 133 | t8 = TM4MD; | ||
| 134 | t8 = TM5MD; | ||
| 120 | } | 135 | } | 
| 121 | 136 | ||
| 122 | /* | 137 | /* | 
| @@ -127,7 +142,7 @@ typedef unsigned long cycles_t; | |||
| 127 | 142 | ||
| 128 | static inline cycles_t read_timestamp_counter(void) | 143 | static inline cycles_t read_timestamp_counter(void) | 
| 129 | { | 144 | { | 
| 130 | return (cycles_t) TMTSCBC; | 145 | return (cycles_t)~TMTSCBC; | 
| 131 | } | 146 | } | 
| 132 | 147 | ||
| 133 | #endif /* !__ASSEMBLY__ */ | 148 | #endif /* !__ASSEMBLY__ */ | 
| diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c index 45b40ac6c464..8e6763e6f250 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.c +++ b/arch/mn10300/unit-asb2305/pci-asb2305.c | |||
| @@ -93,7 +93,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
| 93 | struct pci_bus *bus; | 93 | struct pci_bus *bus; | 
| 94 | struct pci_dev *dev; | 94 | struct pci_dev *dev; | 
| 95 | int idx; | 95 | int idx; | 
| 96 | struct resource *r, *pr; | 96 | struct resource *r; | 
| 97 | 97 | ||
| 98 | /* Depth-First Search on bus tree */ | 98 | /* Depth-First Search on bus tree */ | 
| 99 | list_for_each_entry(bus, bus_list, node) { | 99 | list_for_each_entry(bus, bus_list, node) { | 
| @@ -105,10 +105,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
| 105 | r = &dev->resource[idx]; | 105 | r = &dev->resource[idx]; | 
| 106 | if (!r->flags) | 106 | if (!r->flags) | 
| 107 | continue; | 107 | continue; | 
| 108 | pr = pci_find_parent_resource(dev, r); | ||
| 109 | if (!r->start || | 108 | if (!r->start || | 
| 110 | !pr || | 109 | pci_claim_resource(dev, idx) < 0) { | 
| 111 | request_resource(pr, r) < 0) { | ||
| 112 | printk(KERN_ERR "PCI:" | 110 | printk(KERN_ERR "PCI:" | 
| 113 | " Cannot allocate resource" | 111 | " Cannot allocate resource" | 
| 114 | " region %d of bridge %s\n", | 112 | " region %d of bridge %s\n", | 
| @@ -131,7 +129,7 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 131 | struct pci_dev *dev = NULL; | 129 | struct pci_dev *dev = NULL; | 
| 132 | int idx, disabled; | 130 | int idx, disabled; | 
| 133 | u16 command; | 131 | u16 command; | 
| 134 | struct resource *r, *pr; | 132 | struct resource *r; | 
| 135 | 133 | ||
| 136 | for_each_pci_dev(dev) { | 134 | for_each_pci_dev(dev) { | 
| 137 | pci_read_config_word(dev, PCI_COMMAND, &command); | 135 | pci_read_config_word(dev, PCI_COMMAND, &command); | 
| @@ -150,8 +148,7 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 150 | " (f=%lx, d=%d, p=%d)\n", | 148 | " (f=%lx, d=%d, p=%d)\n", | 
| 151 | pci_name(dev), r->start, r->end, r->flags, | 149 | pci_name(dev), r->start, r->end, r->flags, | 
| 152 | disabled, pass); | 150 | disabled, pass); | 
| 153 | pr = pci_find_parent_resource(dev, r); | 151 | if (pci_claim_resource(dev, idx) < 0) { | 
| 154 | if (!pr || request_resource(pr, r) < 0) { | ||
| 155 | printk(KERN_ERR "PCI:" | 152 | printk(KERN_ERR "PCI:" | 
| 156 | " Cannot allocate resource" | 153 | " Cannot allocate resource" | 
| 157 | " region %d of device %s\n", | 154 | " region %d of device %s\n", | 
| @@ -184,7 +181,7 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 184 | static int __init pcibios_assign_resources(void) | 181 | static int __init pcibios_assign_resources(void) | 
| 185 | { | 182 | { | 
| 186 | struct pci_dev *dev = NULL; | 183 | struct pci_dev *dev = NULL; | 
| 187 | struct resource *r, *pr; | 184 | struct resource *r; | 
| 188 | 185 | ||
| 189 | if (!(pci_probe & PCI_ASSIGN_ROMS)) { | 186 | if (!(pci_probe & PCI_ASSIGN_ROMS)) { | 
| 190 | /* Try to use BIOS settings for ROMs, otherwise let | 187 | /* Try to use BIOS settings for ROMs, otherwise let | 
| @@ -194,8 +191,7 @@ static int __init pcibios_assign_resources(void) | |||
| 194 | r = &dev->resource[PCI_ROM_RESOURCE]; | 191 | r = &dev->resource[PCI_ROM_RESOURCE]; | 
| 195 | if (!r->flags || !r->start) | 192 | if (!r->flags || !r->start) | 
| 196 | continue; | 193 | continue; | 
| 197 | pr = pci_find_parent_resource(dev, r); | 194 | if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { | 
| 198 | if (!pr || request_resource(pr, r) < 0) { | ||
| 199 | r->end -= r->start; | 195 | r->end -= r->start; | 
| 200 | r->start = 0; | 196 | r->start = 0; | 
| 201 | } | 197 | } | 
| diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 6d8720a0a599..a4954fe82094 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c | |||
| @@ -503,7 +503,7 @@ asmlinkage void __init unit_pci_init(void) | |||
| 503 | struct pci_ops *o = &pci_direct_ampci; | 503 | struct pci_ops *o = &pci_direct_ampci; | 
| 504 | u32 x; | 504 | u32 x; | 
| 505 | 505 | ||
| 506 | set_intr_level(XIRQ1, GxICR_LEVEL_3); | 506 | set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL)); | 
| 507 | 507 | ||
| 508 | memset(&bus, 0, sizeof(bus)); | 508 | memset(&bus, 0, sizeof(bus)); | 
| 509 | 509 | ||
| diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c index a76c8e0ab90f..e1becd6b7571 100644 --- a/arch/mn10300/unit-asb2305/unit-init.c +++ b/arch/mn10300/unit-asb2305/unit-init.c | |||
| @@ -26,8 +26,10 @@ asmlinkage void __init unit_init(void) | |||
| 26 | { | 26 | { | 
| 27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 27 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | 
| 28 | /* set the 16550 interrupt line to level 3 if not being used for GDB */ | 28 | /* set the 16550 interrupt line to level 3 if not being used for GDB */ | 
| 29 | set_intr_level(XIRQ0, GxICR_LEVEL_3); | 29 | #ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL | 
| 30 | set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL)); | ||
| 30 | #endif | 31 | #endif | 
| 32 | #endif /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
| 31 | } | 33 | } | 
| 32 | 34 | ||
| 33 | /* | 35 | /* | 
| @@ -51,7 +53,7 @@ void __init unit_init_IRQ(void) | |||
| 51 | switch (GET_XIRQ_TRIGGER(extnum)) { | 53 | switch (GET_XIRQ_TRIGGER(extnum)) { | 
| 52 | case XIRQ_TRIGGER_HILEVEL: | 54 | case XIRQ_TRIGGER_HILEVEL: | 
| 53 | case XIRQ_TRIGGER_LOWLEVEL: | 55 | case XIRQ_TRIGGER_LOWLEVEL: | 
| 54 | set_intr_postackable(XIRQ2IRQ(extnum)); | 56 | mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum)); | 
| 55 | break; | 57 | break; | 
| 56 | default: | 58 | default: | 
| 57 | break; | 59 | break; | 
| diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile new file mode 100644 index 000000000000..b3263ecfc4ff --- /dev/null +++ b/arch/mn10300/unit-asb2364/Makefile | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the linux kernel. | ||
| 3 | # | ||
| 4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
| 5 | # removes any old dependencies. DON'T put your own dependencies here | ||
| 6 | # unless it's something special (ie not a .c file). | ||
| 7 | # | ||
| 8 | # Note 2! The CFLAGS definitions are now in the main makefile... | ||
| 9 | |||
| 10 | obj-y := unit-init.o leds.o irq-fpga.o | ||
| 11 | |||
| 12 | obj-$(CONFIG_SMSC911X) += smsc911x.o | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/clock.h b/arch/mn10300/unit-asb2364/include/unit/clock.h new file mode 100644 index 000000000000..d34ac9a7508b --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/clock.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* clock.h: unit-specific clocks | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * Modified by Matsushita Electric Industrial Co., Ltd. | ||
| 7 | * Modifications: | ||
| 8 | * 23-Feb-2007 MEI Add define for watchdog timer. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _ASM_UNIT_CLOCK_H | ||
| 17 | #define _ASM_UNIT_CLOCK_H | ||
| 18 | |||
| 19 | #ifndef __ASSEMBLY__ | ||
| 20 | |||
| 21 | #define MN10300_IOCLK 100000000UL /* for DDR800 */ | ||
| 22 | /*#define MN10300_IOCLK 83333333UL */ /* for DDR667 */ | ||
| 23 | #define MN10300_IOBCLK MN10300_IOCLK /* IOBCLK is equal to IOCLK */ | ||
| 24 | |||
| 25 | #endif /* !__ASSEMBLY__ */ | ||
| 26 | |||
| 27 | #define MN10300_WDCLK 27000000UL | ||
| 28 | |||
| 29 | #endif /* _ASM_UNIT_CLOCK_H */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h new file mode 100644 index 000000000000..7cf12054db65 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* ASB2364 FPGA registers | ||
| 2 | */ | ||
| 3 | |||
| 4 | #ifndef _ASM_UNIT_FPGA_REGS_H | ||
| 5 | #define _ASM_UNIT_FPGA_REGS_H | ||
| 6 | |||
| 7 | #include <asm/cpu-regs.h> | ||
| 8 | |||
| 9 | #ifdef __KERNEL__ | ||
| 10 | |||
| 11 | #define ASB2364_FPGA_REG_RESET_LAN __SYSREG(0xa9001300, u16) | ||
| 12 | #define ASB2364_FPGA_REG_RESET_UART __SYSREG(0xa9001304, u16) | ||
| 13 | #define ASB2364_FPGA_REG_RESET_I2C __SYSREG(0xa9001308, u16) | ||
| 14 | #define ASB2364_FPGA_REG_RESET_USB __SYSREG(0xa900130c, u16) | ||
| 15 | #define ASB2364_FPGA_REG_RESET_AV __SYSREG(0xa9001310, u16) | ||
| 16 | |||
| 17 | #define ASB2364_FPGA_REG_IRQ(X) __SYSREG(0xa9001590+((X)*4), u16) | ||
| 18 | #define ASB2364_FPGA_REG_IRQ_LAN ASB2364_FPGA_REG_IRQ(0) | ||
| 19 | #define ASB2364_FPGA_REG_IRQ_UART ASB2364_FPGA_REG_IRQ(1) | ||
| 20 | #define ASB2364_FPGA_REG_IRQ_I2C ASB2364_FPGA_REG_IRQ(2) | ||
| 21 | #define ASB2364_FPGA_REG_IRQ_USB ASB2364_FPGA_REG_IRQ(3) | ||
| 22 | #define ASB2364_FPGA_REG_IRQ_FPGA ASB2364_FPGA_REG_IRQ(5) | ||
| 23 | |||
| 24 | #define ASB2364_FPGA_REG_MASK(X) __SYSREG(0xa9001590+((X)*4), u16) | ||
| 25 | #define ASB2364_FPGA_REG_MASK_LAN ASB2364_FPGA_REG_MASK(0) | ||
| 26 | #define ASB2364_FPGA_REG_MASK_UART ASB2364_FPGA_REG_MASK(1) | ||
| 27 | #define ASB2364_FPGA_REG_MASK_I2C ASB2364_FPGA_REG_MASK(2) | ||
| 28 | #define ASB2364_FPGA_REG_MASK_USB ASB2364_FPGA_REG_MASK(3) | ||
| 29 | #define ASB2364_FPGA_REG_MASK_FPGA ASB2364_FPGA_REG_MASK(5) | ||
| 30 | |||
| 31 | #define ASB2364_FPGA_REG_CPLD5_SET1 __SYSREG(0xa9002500, u16) | ||
| 32 | #define ASB2364_FPGA_REG_CPLD5_SET2 __SYSREG(0xa9002504, u16) | ||
| 33 | #define ASB2364_FPGA_REG_CPLD6_SET1 __SYSREG(0xa9002600, u16) | ||
| 34 | #define ASB2364_FPGA_REG_CPLD6_SET2 __SYSREG(0xa9002604, u16) | ||
| 35 | #define ASB2364_FPGA_REG_CPLD7_SET1 __SYSREG(0xa9002700, u16) | ||
| 36 | #define ASB2364_FPGA_REG_CPLD7_SET2 __SYSREG(0xa9002704, u16) | ||
| 37 | #define ASB2364_FPGA_REG_CPLD8_SET1 __SYSREG(0xa9002800, u16) | ||
| 38 | #define ASB2364_FPGA_REG_CPLD8_SET2 __SYSREG(0xa9002804, u16) | ||
| 39 | #define ASB2364_FPGA_REG_CPLD9_SET1 __SYSREG(0xa9002900, u16) | ||
| 40 | #define ASB2364_FPGA_REG_CPLD9_SET2 __SYSREG(0xa9002904, u16) | ||
| 41 | #define ASB2364_FPGA_REG_CPLD10_SET1 __SYSREG(0xa9002a00, u16) | ||
| 42 | #define ASB2364_FPGA_REG_CPLD10_SET2 __SYSREG(0xa9002a04, u16) | ||
| 43 | |||
| 44 | #define SyncExBus() \ | ||
| 45 | do { \ | ||
| 46 | unsigned short w; \ | ||
| 47 | w = *(volatile short *)0xa9000000; \ | ||
| 48 | } while (0) | ||
| 49 | |||
| 50 | #endif /* __KERNEL__ */ | ||
| 51 | |||
| 52 | #endif /* _ASM_UNIT_FPGA_REGS_H */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/irq.h b/arch/mn10300/unit-asb2364/include/unit/irq.h new file mode 100644 index 000000000000..786148e46565 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/irq.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* ASB2364 FPGA irq numbers | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _UNIT_IRQ_H | ||
| 12 | #define _UNIT_IRQ_H | ||
| 13 | |||
| 14 | #ifndef __ASSEMBLY__ | ||
| 15 | |||
| 16 | #ifdef CONFIG_SMP | ||
| 17 | #define NR_CPU_IRQS GxICR_NUM_EXT_IRQS | ||
| 18 | #else | ||
| 19 | #define NR_CPU_IRQS GxICR_NUM_IRQS | ||
| 20 | #endif | ||
| 21 | |||
| 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 */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/leds.h b/arch/mn10300/unit-asb2364/include/unit/leds.h new file mode 100644 index 000000000000..03a3933ad323 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/leds.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* Unit-specific leds | ||
| 2 | * | ||
| 3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _ASM_UNIT_LEDS_H | ||
| 13 | #define _ASM_UNIT_LEDS_H | ||
| 14 | |||
| 15 | #include <asm/pio-regs.h> | ||
| 16 | #include <asm/cpu-regs.h> | ||
| 17 | #include <asm/exceptions.h> | ||
| 18 | |||
| 19 | #define MN10300_USE_7SEGLEDS 0 | ||
| 20 | |||
| 21 | #define ASB2364_7SEGLEDS __SYSREG(0xA9001630, u32) | ||
| 22 | |||
| 23 | /* | ||
| 24 | * use the 7-segment LEDs to indicate states | ||
| 25 | */ | ||
| 26 | |||
| 27 | #if MN10300_USE_7SEGLEDS | ||
| 28 | /* flip the 7-segment LEDs between "Gdb-" and "----" */ | ||
| 29 | #define mn10300_set_gdbleds(ONOFF) \ | ||
| 30 | do { \ | ||
| 31 | ASB2364_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f; \ | ||
| 32 | } while (0) | ||
| 33 | #else | ||
| 34 | #define mn10300_set_gdbleds(ONOFF) do {} while (0) | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #if MN10300_USE_7SEGLEDS | ||
| 38 | /* indicate double-fault by displaying "db-f" on the LEDs */ | ||
| 39 | #define mn10300_set_dbfleds \ | ||
| 40 | mov 0x43077f1d,d0 ; \ | ||
| 41 | mov d0,(ASB2364_7SEGLEDS) | ||
| 42 | #else | ||
| 43 | #define mn10300_set_dbfleds | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #ifndef __ASSEMBLY__ | ||
| 47 | extern void peripheral_leds_display_exception(enum exception_code); | ||
| 48 | extern void peripheral_leds_led_chase(void); | ||
| 49 | extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int); | ||
| 50 | extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int); | ||
| 51 | extern void debug_to_serial(const char *, int); | ||
| 52 | #endif /* __ASSEMBLY__ */ | ||
| 53 | |||
| 54 | #endif /* _ASM_UNIT_LEDS_H */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/serial.h b/arch/mn10300/unit-asb2364/include/unit/serial.h new file mode 100644 index 000000000000..7f048bbfdfd7 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/serial.h | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | /* Unit-specific 8250 serial ports | ||
| 2 | * | ||
| 3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _ASM_UNIT_SERIAL_H | ||
| 13 | #define _ASM_UNIT_SERIAL_H | ||
| 14 | |||
| 15 | #include <asm/cpu-regs.h> | ||
| 16 | #include <proc/irq.h> | ||
| 17 | #include <unit/fpga-regs.h> | ||
| 18 | #include <linux/serial_reg.h> | ||
| 19 | |||
| 20 | #define SERIAL_PORT0_BASE_ADDRESS 0xA8200000 | ||
| 21 | |||
| 22 | #define SERIAL_IRQ XIRQ1 /* single serial (TL16C550C) (Lo) */ | ||
| 23 | |||
| 24 | /* | ||
| 25 | * The ASB2364 has an 12.288 MHz clock | ||
| 26 | * for your UART. | ||
| 27 | * | ||
| 28 | * It'd be nice if someone built a serial card with a 24.576 MHz | ||
| 29 | * clock, since the 16550A is capable of handling a top speed of 1.5 | ||
| 30 | * megabits/second; but this requires the faster clock. | ||
| 31 | */ | ||
| 32 | #define BASE_BAUD (12288000 / 16) | ||
| 33 | |||
| 34 | /* | ||
| 35 | * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports | ||
| 36 | */ | ||
| 37 | #ifndef CONFIG_GDBSTUB_ON_TTYSx | ||
| 38 | |||
| 39 | #define SERIAL_PORT_DFNS \ | ||
| 40 | { \ | ||
| 41 | .baud_base = BASE_BAUD, \ | ||
| 42 | .irq = SERIAL_IRQ, \ | ||
| 43 | .flags = STD_COM_FLAGS, \ | ||
| 44 | .iomem_base = (u8 *) SERIAL_PORT0_BASE_ADDRESS, \ | ||
| 45 | .iomem_reg_shift = 1, \ | ||
| 46 | .io_type = SERIAL_IO_MEM, \ | ||
| 47 | }, | ||
| 48 | |||
| 49 | #ifndef __ASSEMBLY__ | ||
| 50 | |||
| 51 | static inline void __debug_to_serial(const char *p, int n) | ||
| 52 | { | ||
| 53 | } | ||
| 54 | |||
| 55 | #endif /* !__ASSEMBLY__ */ | ||
| 56 | |||
| 57 | #else /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
| 58 | |||
| 59 | #define SERIAL_PORT_DFNS /* stolen by gdb-stub */ | ||
| 60 | |||
| 61 | #if defined(CONFIG_GDBSTUB_ON_TTYS0) | ||
| 62 | #define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 4, u8) | ||
| 63 | #define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 4, u8) | ||
| 64 | #define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8) | ||
| 65 | #define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8) | ||
| 66 | #define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8) | ||
| 67 | #define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8) | ||
| 68 | #define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8) | ||
| 69 | #define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8) | ||
| 70 | #define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8) | ||
| 71 | #define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8) | ||
| 72 | #define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8) | ||
| 73 | #define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8) | ||
| 74 | #define GDBPORT_SERIAL_IRQ SERIAL_IRQ | ||
| 75 | |||
| 76 | #elif defined(CONFIG_GDBSTUB_ON_TTYS1) | ||
| 77 | #error The ASB2364 does not have a /dev/ttyS1 | ||
| 78 | #endif | ||
| 79 | |||
| 80 | #ifndef __ASSEMBLY__ | ||
| 81 | |||
| 82 | static inline void __debug_to_serial(const char *p, int n) | ||
| 83 | { | ||
| 84 | char ch; | ||
| 85 | |||
| 86 | #define LSR_WAIT_FOR(STATE) \ | ||
| 87 | do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE)) | ||
| 88 | #define FLOWCTL_QUERY(LINE) \ | ||
| 89 | ({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; }) | ||
| 90 | #define FLOWCTL_WAIT_FOR(LINE) \ | ||
| 91 | do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE)) | ||
| 92 | #define FLOWCTL_CLEAR(LINE) \ | ||
| 93 | do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0) | ||
| 94 | #define FLOWCTL_SET(LINE) \ | ||
| 95 | do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0) | ||
| 96 | |||
| 97 | FLOWCTL_SET(DTR); | ||
| 98 | |||
| 99 | for (; n > 0; n--) { | ||
| 100 | LSR_WAIT_FOR(THRE); | ||
| 101 | FLOWCTL_WAIT_FOR(CTS); | ||
| 102 | |||
| 103 | ch = *p++; | ||
| 104 | if (ch == 0x0a) { | ||
| 105 | GDBPORT_SERIAL_TX = 0x0d; | ||
| 106 | LSR_WAIT_FOR(THRE); | ||
| 107 | FLOWCTL_WAIT_FOR(CTS); | ||
| 108 | } | ||
| 109 | GDBPORT_SERIAL_TX = ch; | ||
| 110 | } | ||
| 111 | |||
| 112 | FLOWCTL_CLEAR(DTR); | ||
| 113 | } | ||
| 114 | |||
| 115 | #endif /* !__ASSEMBLY__ */ | ||
| 116 | |||
| 117 | #endif /* CONFIG_GDBSTUB_ON_TTYSx */ | ||
| 118 | |||
| 119 | #define SERIAL_INITIALIZE \ | ||
| 120 | do { \ | ||
| 121 | /* release reset */ \ | ||
| 122 | ASB2364_FPGA_REG_RESET_UART = 0x0001; \ | ||
| 123 | SyncExBus(); \ | ||
| 124 | } while (0) | ||
| 125 | |||
| 126 | #define SERIAL_CHECK_INTERRUPT \ | ||
| 127 | do { \ | ||
| 128 | if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) { \ | ||
| 129 | return IRQ_NONE; \ | ||
| 130 | } \ | ||
| 131 | } while (0) | ||
| 132 | |||
| 133 | #define SERIAL_CLEAR_INTERRUPT \ | ||
| 134 | do { \ | ||
| 135 | ASB2364_FPGA_REG_IRQ_UART = 0x0001; \ | ||
| 136 | SyncExBus(); \ | ||
| 137 | } while (0) | ||
| 138 | |||
| 139 | #define SERIAL_SET_INT_MASK \ | ||
| 140 | do { \ | ||
| 141 | ASB2364_FPGA_REG_MASK_UART = 0x0001; \ | ||
| 142 | SyncExBus(); \ | ||
| 143 | } while (0) | ||
| 144 | |||
| 145 | #define SERIAL_CLEAR_INT_MASK \ | ||
| 146 | do { \ | ||
| 147 | ASB2364_FPGA_REG_MASK_UART = 0x0000; \ | ||
| 148 | SyncExBus(); \ | ||
| 149 | } while (0) | ||
| 150 | |||
| 151 | #endif /* _ASM_UNIT_SERIAL_H */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/smsc911x.h b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h new file mode 100644 index 000000000000..4c1ede535fa9 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | /* Support for the SMSC911x NIC | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _ASM_UNIT_SMSC911X_H | ||
| 12 | #define _ASM_UNIT_SMSC911X_H | ||
| 13 | |||
| 14 | #include <linux/netdevice.h> | ||
| 15 | #include <proc/irq.h> | ||
| 16 | #include <unit/fpga-regs.h> | ||
| 17 | |||
| 18 | #define MN10300_USE_EXT_EEPROM | ||
| 19 | |||
| 20 | |||
| 21 | #define SMSC911X_BASE 0xA8000000UL | ||
| 22 | #define SMSC911X_BASE_END 0xA8000100UL | ||
| 23 | #define SMSC911X_IRQ FPGA_LAN_IRQ | ||
| 24 | |||
| 25 | /* | ||
| 26 | * Allow the FPGA to be initialised by the SMSC911x driver | ||
| 27 | */ | ||
| 28 | #undef SMSC_INITIALIZE | ||
| 29 | #define SMSC_INITIALIZE() \ | ||
| 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 */ | ||
| diff --git a/arch/mn10300/unit-asb2364/include/unit/timex.h b/arch/mn10300/unit-asb2364/include/unit/timex.h new file mode 100644 index 000000000000..ddb7ed010706 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/timex.h | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | /* timex.h: MN2WS0038 architecture timer specifications | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002, 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _ASM_UNIT_TIMEX_H | ||
| 12 | #define _ASM_UNIT_TIMEX_H | ||
| 13 | |||
| 14 | #ifndef __ASSEMBLY__ | ||
| 15 | #include <linux/irq.h> | ||
| 16 | #endif /* __ASSEMBLY__ */ | ||
| 17 | |||
| 18 | #include <asm/timer-regs.h> | ||
| 19 | #include <unit/clock.h> | ||
| 20 | #include <asm/param.h> | ||
| 21 | |||
| 22 | /* | ||
| 23 | * jiffies counter specifications | ||
| 24 | */ | ||
| 25 | |||
| 26 | #define TMJCBR_MAX 0xffffff /* 24bit */ | ||
| 27 | #define TMJCIRQ TMTIRQ | ||
| 28 | |||
| 29 | #ifndef __ASSEMBLY__ | ||
| 30 | |||
| 31 | #define MN10300_SRC_IOBCLK MN10300_IOBCLK | ||
| 32 | |||
| 33 | #ifndef HZ | ||
| 34 | # error HZ undeclared. | ||
| 35 | #endif /* !HZ */ | ||
| 36 | |||
| 37 | #define MN10300_JCCLK (MN10300_SRC_IOBCLK) | ||
| 38 | #define MN10300_TSCCLK (MN10300_SRC_IOBCLK) | ||
| 39 | |||
| 40 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | ||
| 41 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | ||
| 42 | |||
| 43 | /* Check bit width of MTM interval value that sets base register */ | ||
| 44 | #if (MN10300_JC_PER_HZ - 1) > TMJCBR_MAX | ||
| 45 | # error MTM tick timer interval value is overflow. | ||
| 46 | #endif | ||
| 47 | |||
| 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 */ | ||
| diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c new file mode 100644 index 000000000000..fcf29754e4d1 --- /dev/null +++ b/arch/mn10300/unit-asb2364/irq-fpga.c | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* ASB2364 FPGA interrupt multiplexing | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/irq.h> | ||
| 15 | #include <unit/fpga-regs.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * FPGA PIC operations | ||
| 19 | */ | ||
| 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 | } | ||
| diff --git a/arch/mn10300/unit-asb2364/leds.c b/arch/mn10300/unit-asb2364/leds.c new file mode 100644 index 000000000000..1ff830c372b3 --- /dev/null +++ b/arch/mn10300/unit-asb2364/leds.c | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | /* leds.c: ASB2364 peripheral 7seg LEDs x4 support | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/param.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | |||
| 16 | #include <asm/io.h> | ||
| 17 | #include <asm/processor.h> | ||
| 18 | #include <asm/intctl-regs.h> | ||
| 19 | #include <asm/rtc-regs.h> | ||
| 20 | #include <unit/leds.h> | ||
| 21 | |||
| 22 | #if MN10300_USE_7SEGLEDS | ||
| 23 | static const u8 asb2364_led_hex_tbl[16] = { | ||
| 24 | 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0, | ||
| 25 | 0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c | ||
| 26 | }; | ||
| 27 | |||
| 28 | static const u32 asb2364_led_chase_tbl[6] = { | ||
| 29 | ~0x02020202, /* top - segA */ | ||
| 30 | ~0x04040404, /* right top - segB */ | ||
| 31 | ~0x08080808, /* right bottom - segC */ | ||
| 32 | ~0x10101010, /* bottom - segD */ | ||
| 33 | ~0x20202020, /* left bottom - segE */ | ||
| 34 | ~0x40404040, /* left top - segF */ | ||
| 35 | }; | ||
| 36 | |||
| 37 | static unsigned asb2364_led_chase; | ||
| 38 | |||
| 39 | void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) | ||
| 40 | { | ||
| 41 | u32 leds; | ||
| 42 | |||
| 43 | leds = asb2364_led_hex_tbl[(val/1000) % 10]; | ||
| 44 | leds <<= 8; | ||
| 45 | leds |= asb2364_led_hex_tbl[(val/100) % 10]; | ||
| 46 | leds <<= 8; | ||
| 47 | leds |= asb2364_led_hex_tbl[(val/10) % 10]; | ||
| 48 | leds <<= 8; | ||
| 49 | leds |= asb2364_led_hex_tbl[val % 10]; | ||
| 50 | leds |= points^0x01010101; | ||
| 51 | |||
| 52 | ASB2364_7SEGLEDS = leds; | ||
| 53 | } | ||
| 54 | |||
| 55 | void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) | ||
| 56 | { | ||
| 57 | u32 leds; | ||
| 58 | |||
| 59 | leds = asb2364_led_hex_tbl[(val/1000) % 10]; | ||
| 60 | leds <<= 8; | ||
| 61 | leds |= asb2364_led_hex_tbl[(val/100) % 10]; | ||
| 62 | leds <<= 8; | ||
| 63 | leds |= asb2364_led_hex_tbl[(val/10) % 10]; | ||
| 64 | leds <<= 8; | ||
| 65 | leds |= asb2364_led_hex_tbl[val % 10]; | ||
| 66 | leds |= points^0x01010101; | ||
| 67 | |||
| 68 | ASB2364_7SEGLEDS = leds; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* display triple horizontal bar and exception code */ | ||
| 72 | void peripheral_leds_display_exception(enum exception_code code) | ||
| 73 | { | ||
| 74 | u32 leds; | ||
| 75 | |||
| 76 | leds = asb2364_led_hex_tbl[(code/0x100) % 0x10]; | ||
| 77 | leds <<= 8; | ||
| 78 | leds |= asb2364_led_hex_tbl[(code/0x10) % 0x10]; | ||
| 79 | leds <<= 8; | ||
| 80 | leds |= asb2364_led_hex_tbl[code % 0x10]; | ||
| 81 | leds |= 0x6d010101; | ||
| 82 | |||
| 83 | ASB2364_7SEGLEDS = leds; | ||
| 84 | } | ||
| 85 | |||
| 86 | void peripheral_leds_led_chase(void) | ||
| 87 | { | ||
| 88 | ASB2364_7SEGLEDS = asb2364_led_chase_tbl[asb2364_led_chase]; | ||
| 89 | asb2364_led_chase++; | ||
| 90 | if (asb2364_led_chase >= 6) | ||
| 91 | asb2364_led_chase = 0; | ||
| 92 | } | ||
| 93 | #else /* MN10300_USE_7SEGLEDS */ | ||
| 94 | void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { } | ||
| 95 | void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { } | ||
| 96 | void peripheral_leds_display_exception(enum exception_code code) { } | ||
| 97 | void peripheral_leds_led_chase(void) { } | ||
| 98 | #endif /* MN10300_USE_7SEGLEDS */ | ||
| diff --git a/arch/mn10300/unit-asb2364/smsc911x.c b/arch/mn10300/unit-asb2364/smsc911x.c new file mode 100644 index 000000000000..544a73e94c81 --- /dev/null +++ b/arch/mn10300/unit-asb2364/smsc911x.c | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* Specification for the SMSC911x NIC | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/ioport.h> | ||
| 17 | #include <linux/smsc911x.h> | ||
| 18 | #include <unit/smsc911x.h> | ||
| 19 | |||
| 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); | ||
| diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c new file mode 100644 index 000000000000..11440803db10 --- /dev/null +++ b/arch/mn10300/unit-asb2364/unit-init.c | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | /* ASB2364 initialisation | ||
| 2 | * | ||
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/param.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | |||
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/setup.h> | ||
| 20 | #include <asm/processor.h> | ||
| 21 | #include <asm/irq.h> | ||
| 22 | #include <asm/intctl-regs.h> | ||
| 23 | #include <unit/fpga-regs.h> | ||
| 24 | |||
| 25 | /* | ||
| 26 | * initialise some of the unit hardware before gdbstub is set up | ||
| 27 | */ | ||
| 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 | } | ||
| diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 86fe67fd49ba..9334539ebf75 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -1041,7 +1041,7 @@ config SMC911X | |||
| 1041 | tristate "SMSC LAN911[5678] support" | 1041 | tristate "SMSC LAN911[5678] support" | 
| 1042 | select CRC32 | 1042 | select CRC32 | 
| 1043 | select MII | 1043 | select MII | 
| 1044 | depends on ARM || SUPERH | 1044 | depends on ARM || SUPERH || MN10300 | 
| 1045 | help | 1045 | help | 
| 1046 | This is a driver for SMSC's LAN911x series of Ethernet chipsets | 1046 | This is a driver for SMSC's LAN911x series of Ethernet chipsets | 
| 1047 | including the new LAN9115, LAN9116, LAN9117, and LAN9118. | 1047 | including the new LAN9115, LAN9116, LAN9117, and LAN9118. | 
| @@ -1055,7 +1055,7 @@ config SMC911X | |||
| 1055 | 1055 | ||
| 1056 | config SMSC911X | 1056 | config SMSC911X | 
| 1057 | tristate "SMSC LAN911x/LAN921x families embedded ethernet support" | 1057 | tristate "SMSC LAN911x/LAN921x families embedded ethernet support" | 
| 1058 | depends on ARM || SUPERH || BLACKFIN || MIPS | 1058 | depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300 | 
| 1059 | select CRC32 | 1059 | select CRC32 | 
| 1060 | select MII | 1060 | select MII | 
| 1061 | select PHYLIB | 1061 | select PHYLIB | 
| @@ -1067,6 +1067,14 @@ config SMSC911X | |||
| 1067 | <file:Documentation/networking/net-modules.txt>. The module | 1067 | <file:Documentation/networking/net-modules.txt>. The module | 
| 1068 | will be called smsc911x. | 1068 | will be called smsc911x. | 
| 1069 | 1069 | ||
| 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 | |||
| 1070 | config NET_VENDOR_RACAL | 1078 | config NET_VENDOR_RACAL | 
| 1071 | bool "Racal-Interlan (Micom) NI cards" | 1079 | bool "Racal-Interlan (Micom) NI cards" | 
| 1072 | depends on ISA | 1080 | depends on ISA | 
| diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index a8e5856ce882..64bfdae5956f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
| @@ -2075,7 +2075,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
| 2075 | } else { | 2075 | } else { | 
| 2076 | /* Try reading mac address from device. if EEPROM is present | 2076 | /* Try reading mac address from device. if EEPROM is present | 
| 2077 | * it will already have been set */ | 2077 | * it will already have been set */ | 
| 2078 | smsc911x_read_mac_address(dev); | 2078 | smsc_get_mac(dev); | 
| 2079 | 2079 | ||
| 2080 | if (is_valid_ether_addr(dev->dev_addr)) { | 2080 | if (is_valid_ether_addr(dev->dev_addr)) { | 
| 2081 | /* eeprom values are valid so use them */ | 2081 | /* eeprom values are valid so use them */ | 
| @@ -2176,6 +2176,7 @@ static struct platform_driver smsc911x_driver = { | |||
| 2176 | /* Entry point for loading the module */ | 2176 | /* Entry point for loading the module */ | 
| 2177 | static int __init smsc911x_init_module(void) | 2177 | static int __init smsc911x_init_module(void) | 
| 2178 | { | 2178 | { | 
| 2179 | SMSC_INITIALIZE(); | ||
| 2179 | return platform_driver_register(&smsc911x_driver); | 2180 | return platform_driver_register(&smsc911x_driver); | 
| 2180 | } | 2181 | } | 
| 2181 | 2182 | ||
| diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h index 016360c65ce2..52f38e12a879 100644 --- a/drivers/net/smsc911x.h +++ b/drivers/net/smsc911x.h | |||
| @@ -394,4 +394,15 @@ | |||
| 394 | #define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \ | 394 | #define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \ | 
| 395 | LPA_PAUSE_ASYM) | 395 | LPA_PAUSE_ASYM) | 
| 396 | 396 | ||
| 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 | |||
| 397 | #endif /* __SMSC911X_H__ */ | 408 | #endif /* __SMSC911X_H__ */ | 
| diff --git a/include/linux/smp.h b/include/linux/smp.h index cfa2d20e35f1..6dc95cac6b3d 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
| @@ -13,9 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | extern void cpu_idle(void); | 14 | extern void cpu_idle(void); | 
| 15 | 15 | ||
| 16 | typedef void (*smp_call_func_t)(void *info); | ||
| 16 | struct call_single_data { | 17 | struct call_single_data { | 
| 17 | struct list_head list; | 18 | struct list_head list; | 
| 18 | void (*func) (void *info); | 19 | smp_call_func_t func; | 
| 19 | void *info; | 20 | void *info; | 
| 20 | u16 flags; | 21 | u16 flags; | 
| 21 | u16 priv; | 22 | u16 priv; | 
| @@ -24,8 +25,8 @@ struct call_single_data { | |||
| 24 | /* total number of cpus in this system (may exceed NR_CPUS) */ | 25 | /* total number of cpus in this system (may exceed NR_CPUS) */ | 
| 25 | extern unsigned int total_cpus; | 26 | extern unsigned int total_cpus; | 
| 26 | 27 | ||
| 27 | int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, | 28 | int smp_call_function_single(int cpuid, smp_call_func_t func, void *info, | 
| 28 | int wait); | 29 | int wait); | 
| 29 | 30 | ||
| 30 | #ifdef CONFIG_SMP | 31 | #ifdef CONFIG_SMP | 
| 31 | 32 | ||
| @@ -69,15 +70,15 @@ extern void smp_cpus_done(unsigned int max_cpus); | |||
| 69 | /* | 70 | /* | 
| 70 | * Call a function on all other processors | 71 | * Call a function on all other processors | 
| 71 | */ | 72 | */ | 
| 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); | 
| 73 | void smp_call_function_many(const struct cpumask *mask, | 74 | 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); | 
| 75 | 76 | ||
| 76 | void __smp_call_function_single(int cpuid, struct call_single_data *data, | 77 | void __smp_call_function_single(int cpuid, struct call_single_data *data, | 
| 77 | int wait); | 78 | int wait); | 
| 78 | 79 | ||
| 79 | int smp_call_function_any(const struct cpumask *mask, | 80 | 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); | 
| 81 | 82 | ||
| 82 | /* | 83 | /* | 
| 83 | * Generic and arch helpers | 84 | * Generic and arch helpers | 
| @@ -94,7 +95,7 @@ void ipi_call_unlock_irq(void); | |||
| 94 | /* | 95 | /* | 
| 95 | * Call a function on all processors | 96 | * Call a function on all processors | 
| 96 | */ | 97 | */ | 
| 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); | 
| 98 | 99 | ||
| 99 | #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ | 100 | #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ | 
| 100 | #define MSG_ALL 0x8001 | 101 | #define MSG_ALL 0x8001 | 
| @@ -122,7 +123,7 @@ static inline void smp_send_stop(void) { } | |||
| 122 | * These macros fold the SMP functionality into a single CPU system | 123 | * These macros fold the SMP functionality into a single CPU system | 
| 123 | */ | 124 | */ | 
| 124 | #define raw_smp_processor_id() 0 | 125 | #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) | 
| 126 | { | 127 | { | 
| 127 | return 0; | 128 | return 0; | 
| 128 | } | 129 | } | 
| @@ -143,7 +144,7 @@ static inline void smp_send_reschedule(int cpu) { } | |||
| 143 | static inline void init_call_single_data(void) { } | 144 | static inline void init_call_single_data(void) { } | 
| 144 | 145 | ||
| 145 | static inline int | 146 | 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, | 
| 147 | void *info, int wait) | 148 | void *info, int wait) | 
| 148 | { | 149 | { | 
| 149 | return smp_call_function_single(0, func, info, wait); | 150 | return smp_call_function_single(0, func, info, wait); | 
| diff --git a/kernel/smp.c b/kernel/smp.c index ed6aacfcb7ef..12ed8b013e2d 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
| @@ -267,7 +267,7 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_single_data, csd_data); | |||
| 267 | * | 267 | * | 
| 268 | * Returns 0 on success, else a negative status code. | 268 | * Returns 0 on success, else a negative status code. | 
| 269 | */ | 269 | */ | 
| 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, | 
| 271 | int wait) | 271 | int wait) | 
| 272 | { | 272 | { | 
| 273 | struct call_single_data d = { | 273 | struct call_single_data d = { | 
| @@ -336,7 +336,7 @@ EXPORT_SYMBOL(smp_call_function_single); | |||
| 336 | * 3) any other online cpu in @mask | 336 | * 3) any other online cpu in @mask | 
| 337 | */ | 337 | */ | 
| 338 | int smp_call_function_any(const struct cpumask *mask, | 338 | 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) | 
| 340 | { | 340 | { | 
| 341 | unsigned int cpu; | 341 | unsigned int cpu; | 
| 342 | const struct cpumask *nodemask; | 342 | const struct cpumask *nodemask; | 
| @@ -416,7 +416,7 @@ void __smp_call_function_single(int cpu, struct call_single_data *data, | |||
| 416 | * must be disabled when calling this function. | 416 | * must be disabled when calling this function. | 
| 417 | */ | 417 | */ | 
| 418 | void smp_call_function_many(const struct cpumask *mask, | 418 | 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) | 
| 420 | { | 420 | { | 
| 421 | struct call_function_data *data; | 421 | struct call_function_data *data; | 
| 422 | unsigned long flags; | 422 | unsigned long flags; | 
| @@ -500,7 +500,7 @@ EXPORT_SYMBOL(smp_call_function_many); | |||
| 500 | * You must not call this function with disabled interrupts or from a | 500 | * You must not call this function with disabled interrupts or from a | 
| 501 | * hardware interrupt handler or from a bottom half handler. | 501 | * hardware interrupt handler or from a bottom half handler. | 
| 502 | */ | 502 | */ | 
| 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) | 
| 504 | { | 504 | { | 
| 505 | preempt_disable(); | 505 | preempt_disable(); | 
| 506 | smp_call_function_many(cpu_online_mask, func, info, wait); | 506 | smp_call_function_many(cpu_online_mask, func, info, wait); | 
| diff --git a/mm/maccess.c b/mm/maccess.c index 4e348dbaecd7..e2b6f5634e0d 100644 --- a/mm/maccess.c +++ b/mm/maccess.c | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | /* | 1 | /* | 
| 2 | * Access kernel memory without faulting. | 2 | * Access kernel memory without faulting. | 
| 3 | */ | 3 | */ | 
| 4 | #include <linux/uaccess.h> | ||
| 5 | #include <linux/module.h> | 4 | #include <linux/module.h> | 
| 6 | #include <linux/mm.h> | 5 | #include <linux/mm.h> | 
| 6 | #include <linux/uaccess.h> | ||
| 7 | 7 | ||
| 8 | /** | 8 | /** | 
| 9 | * probe_kernel_read(): safely attempt to read from a location | 9 | * probe_kernel_read(): safely attempt to read from a location | 
