aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-12-07 15:48:15 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-12-07 15:48:15 -0500
commit34161db6b14d984fb9b06c735b7b42f8803f6851 (patch)
tree99656278b6697f1cde5b05894b7c0ee22c63a00e /arch/sh
parent5847e1f4d058677c5e46dc6c3e3c70e8855ea3ba (diff)
parent620034c84d1d939717bdfbe02c51a3fee43541c3 (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/ into merge_linus
Conflicts: include/linux/sunrpc/xprt.h net/sunrpc/xprtsock.c Fix up conflicts with the workqueue changes.
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/Kconfig100
-rw-r--r--arch/sh/Kconfig.debug22
-rw-r--r--arch/sh/Makefile26
-rw-r--r--arch/sh/boards/renesas/r7780rp/Makefile4
-rw-r--r--arch/sh/boards/renesas/r7780rp/irq.c1
-rw-r--r--arch/sh/boards/renesas/r7780rp/psw.c122
-rw-r--r--arch/sh/boards/renesas/r7780rp/setup.c29
-rw-r--r--arch/sh/boards/se/7206/Makefile7
-rw-r--r--arch/sh/boards/se/7206/io.c123
-rw-r--r--arch/sh/boards/se/7206/irq.c139
-rw-r--r--arch/sh/boards/se/7206/led.c57
-rw-r--r--arch/sh/boards/se/7206/setup.c79
-rw-r--r--arch/sh/boards/se/7619/Makefile5
-rw-r--r--arch/sh/boards/se/7619/io.c102
-rw-r--r--arch/sh/boards/se/7619/setup.c43
-rw-r--r--arch/sh/boards/titan/setup.c27
-rw-r--r--arch/sh/boot/compressed/misc.c3
-rw-r--r--arch/sh/configs/r7780rp_defconfig69
-rw-r--r--arch/sh/configs/se7206_defconfig826
-rw-r--r--arch/sh/drivers/Kconfig9
-rw-r--r--arch/sh/drivers/Makefile2
-rw-r--r--arch/sh/drivers/dma/Makefile4
-rw-r--r--arch/sh/drivers/dma/dma-api.c274
-rw-r--r--arch/sh/drivers/dma/dma-sh.c9
-rw-r--r--arch/sh/drivers/dma/dma-sysfs.c23
-rw-r--r--arch/sh/drivers/pci/ops-titan.c24
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c14
-rw-r--r--arch/sh/drivers/push-switch.c138
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/cpu/Makefile11
-rw-r--r--arch/sh/kernel/cpu/clock.c27
-rw-r--r--arch/sh/kernel/cpu/init.c2
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile3
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c5
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c25
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c93
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh2/clock-sh7619.c81
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S341
-rw-r--r--arch/sh/kernel/cpu/sh2/ex.S46
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c16
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c53
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile10
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7206.c85
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c58
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7709.c2
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S (renamed from arch/sh/kernel/entry.S)546
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c4
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh7780.c2
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c25
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c19
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c70
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7780.c36
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c11
-rw-r--r--arch/sh/kernel/early_printk.c44
-rw-r--r--arch/sh/kernel/entry-common.S433
-rw-r--r--arch/sh/kernel/head.S17
-rw-r--r--arch/sh/kernel/irq.c55
-rw-r--r--arch/sh/kernel/process.c32
-rw-r--r--arch/sh/kernel/relocate_kernel.S14
-rw-r--r--arch/sh/kernel/setup.c2
-rw-r--r--arch/sh/kernel/sh_ksyms.c2
-rw-r--r--arch/sh/kernel/signal.c36
-rw-r--r--arch/sh/kernel/stacktrace.c43
-rw-r--r--arch/sh/kernel/sys_sh.c7
-rw-r--r--arch/sh/kernel/time.c139
-rw-r--r--arch/sh/kernel/timers/Makefile2
-rw-r--r--arch/sh/kernel/timers/timer-cmt.c196
-rw-r--r--arch/sh/kernel/timers/timer-mtu2.c200
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c13
-rw-r--r--arch/sh/kernel/timers/timer.c6
-rw-r--r--arch/sh/kernel/traps.c200
-rw-r--r--arch/sh/mm/Kconfig77
-rw-r--r--arch/sh/mm/cache-sh2.c69
-rw-r--r--arch/sh/mm/cache-sh4.c18
-rw-r--r--arch/sh/mm/clear_page.S18
-rw-r--r--arch/sh/mm/copy_page.S16
-rw-r--r--arch/sh/mm/fault.c161
-rw-r--r--arch/sh/mm/init.c45
-rw-r--r--arch/sh/mm/ioremap.c4
-rw-r--r--arch/sh/mm/pg-dma.c2
-rw-r--r--arch/sh/mm/pg-sh4.c35
-rw-r--r--arch/sh/tools/mach-types2
86 files changed, 4741 insertions, 1049 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index bffc7e176970..d83d64af31f2 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -51,6 +51,14 @@ config GENERIC_TIME
51config ARCH_MAY_HAVE_PC_FDC 51config ARCH_MAY_HAVE_PC_FDC
52 bool 52 bool
53 53
54config STACKTRACE_SUPPORT
55 bool
56 default y
57
58config LOCKDEP_SUPPORT
59 bool
60 default y
61
54source "init/Kconfig" 62source "init/Kconfig"
55 63
56menu "System type" 64menu "System type"
@@ -219,6 +227,20 @@ config SH_SHMIN
219 help 227 help
220 Select SHMIN if configuring for the SHMIN board. 228 Select SHMIN if configuring for the SHMIN board.
221 229
230config SH_7206_SOLUTION_ENGINE
231 bool "SolutionEngine7206"
232 select CPU_SUBTYPE_SH7206
233 help
234 Select 7206 SolutionEngine if configuring for a Hitachi SH7206
235 evaluation board.
236
237config SH_7619_SOLUTION_ENGINE
238 bool "SolutionEngine7619"
239 select CPU_SUBTYPE_SH7619
240 help
241 Select 7619 SolutionEngine if configuring for a Hitachi SH7619
242 evaluation board.
243
222config SH_UNKNOWN 244config SH_UNKNOWN
223 bool "BareCPU" 245 bool "BareCPU"
224 help 246 help
@@ -280,12 +302,20 @@ config CF_BASE_ADDR
280 302
281menu "Processor features" 303menu "Processor features"
282 304
283config CPU_LITTLE_ENDIAN 305choice
284 bool "Little Endian" 306 prompt "Endianess selection"
307 default CPU_LITTLE_ENDIAN
285 help 308 help
286 Some SuperH machines can be configured for either little or big 309 Some SuperH machines can be configured for either little or big
287 endian byte order. These modes require different kernels. Say Y if 310 endian byte order. These modes require different kernels.
288 your machine is little endian, N if it's a big endian machine. 311
312config CPU_LITTLE_ENDIAN
313 bool "Little Endian"
314
315config CPU_BIG_ENDIAN
316 bool "Big Endian"
317
318endchoice
289 319
290config SH_FPU 320config SH_FPU
291 bool "FPU support" 321 bool "FPU support"
@@ -345,6 +375,9 @@ config CPU_HAS_MASKREG_IRQ
345config CPU_HAS_INTC2_IRQ 375config CPU_HAS_INTC2_IRQ
346 bool 376 bool
347 377
378config CPU_HAS_IPR_IRQ
379 bool
380
348config CPU_HAS_SR_RB 381config CPU_HAS_SR_RB
349 bool "CPU has SR.RB" 382 bool "CPU has SR.RB"
350 depends on CPU_SH3 || CPU_SH4 383 depends on CPU_SH3 || CPU_SH4
@@ -357,6 +390,9 @@ config CPU_HAS_SR_RB
357 See <file:Documentation/sh/register-banks.txt> for further 390 See <file:Documentation/sh/register-banks.txt> for further
358 information on SR.RB and register banking in the kernel in general. 391 information on SR.RB and register banking in the kernel in general.
359 392
393config CPU_HAS_PTEA
394 bool
395
360endmenu 396endmenu
361 397
362menu "Timer support" 398menu "Timer support"
@@ -364,10 +400,25 @@ depends on !GENERIC_TIME
364 400
365config SH_TMU 401config SH_TMU
366 bool "TMU timer support" 402 bool "TMU timer support"
403 depends on CPU_SH3 || CPU_SH4
367 default y 404 default y
368 help 405 help
369 This enables the use of the TMU as the system timer. 406 This enables the use of the TMU as the system timer.
370 407
408config SH_CMT
409 bool "CMT timer support"
410 depends on CPU_SH2
411 default y
412 help
413 This enables the use of the CMT as the system timer.
414
415config SH_MTU2
416 bool "MTU2 timer support"
417 depends on CPU_SH2A
418 default n
419 help
420 This enables the use of the MTU2 as the system timer.
421
371endmenu 422endmenu
372 423
373source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" 424source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
@@ -376,19 +427,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
376 427
377source "arch/sh/boards/renesas/r7780rp/Kconfig" 428source "arch/sh/boards/renesas/r7780rp/Kconfig"
378 429
430config SH_TIMER_IRQ
431 int
432 default "28" if CPU_SUBTYPE_SH7780
433 default "86" if CPU_SUBTYPE_SH7619
434 default "140" if CPU_SUBTYPE_SH7206
435 default "16"
436
437config NO_IDLE_HZ
438 bool "Dynamic tick timer"
439 help
440 Select this option if you want to disable continuous timer ticks
441 and have them programmed to occur as required. This option saves
442 power as the system can remain in idle state for longer.
443
444 By default dynamic tick is disabled during the boot, and can be
445 manually enabled with:
446
447 echo 1 > /sys/devices/system/timer/timer0/dyn_tick
448
449 Alternatively, if you want dynamic tick automatically enabled
450 during boot, pass "dyntick=enable" via the kernel command string.
451
452 Please note that dynamic tick may affect the accuracy of
453 timekeeping on some platforms depending on the implementation.
454
379config SH_PCLK_FREQ 455config SH_PCLK_FREQ
380 int "Peripheral clock frequency (in Hz)" 456 int "Peripheral clock frequency (in Hz)"
457 default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
458 default "31250000" if CPU_SUBTYPE_SH7619
459 default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
460 CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
461 CPU_SUBTYPE_SH7206
381 default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 462 default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
382 default "60000000" if CPU_SUBTYPE_SH7751 463 default "60000000" if CPU_SUBTYPE_SH7751
383 default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
384 CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705
385 default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
386 default "66000000" if CPU_SUBTYPE_SH4_202 464 default "66000000" if CPU_SUBTYPE_SH4_202
387 help 465 help
388 This option is used to specify the peripheral clock frequency. 466 This option is used to specify the peripheral clock frequency.
389 This is necessary for determining the reference clock value on 467 This is necessary for determining the reference clock value on
390 platforms lacking an RTC. 468 platforms lacking an RTC.
391 469
470config SH_CLK_MD
471 int "CPU Mode Pin Setting"
472 depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
473 help
474 MD2 - MD0 Setting.
475
392menu "CPU Frequency scaling" 476menu "CPU Frequency scaling"
393 477
394source "drivers/cpufreq/Kconfig" 478source "drivers/cpufreq/Kconfig"
@@ -421,6 +505,8 @@ config HEARTBEAT
421 behavior is platform-dependent, but normally the flash frequency is 505 behavior is platform-dependent, but normally the flash frequency is
422 a hyperbolic function of the 5-minute load average. 506 a hyperbolic function of the 5-minute load average.
423 507
508source "arch/sh/drivers/Kconfig"
509
424endmenu 510endmenu
425 511
426config ISA_DMA_API 512config ISA_DMA_API
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 48479e014dac..66a25ef4ef1b 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -1,5 +1,9 @@
1menu "Kernel hacking" 1menu "Kernel hacking"
2 2
3config TRACE_IRQFLAGS_SUPPORT
4 bool
5 default y
6
3source "lib/Kconfig.debug" 7source "lib/Kconfig.debug"
4 8
5config SH_STANDARD_BIOS 9config SH_STANDARD_BIOS
@@ -17,7 +21,18 @@ config SH_STANDARD_BIOS
17 21
18config EARLY_SCIF_CONSOLE 22config EARLY_SCIF_CONSOLE
19 bool "Use early SCIF console" 23 bool "Use early SCIF console"
20 depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS 24 help
25 This enables an early console using a fixed SCIF port. This can
26 be used by platforms that are either not running the SH
27 standard BIOS, or do not wish to use the BIOS callbacks for the
28 serial I/O.
29
30config EARLY_SCIF_CONSOLE_PORT
31 hex "SCIF port for early console"
32 depends on EARLY_SCIF_CONSOLE
33 default "0xffe00000" if CPU_SUBTYPE_SH7780
34 default "0xfffe9800" if CPU_SUBTYPE_SH72060
35 default "0xffe80000" if CPU_SH4
21 36
22config EARLY_PRINTK 37config EARLY_PRINTK
23 bool "Early printk support" 38 bool "Early printk support"
@@ -30,6 +45,11 @@ config EARLY_PRINTK
30 when the kernel may crash or hang before the serial console is 45 when the kernel may crash or hang before the serial console is
31 initialised. If unsure, say N. 46 initialised. If unsure, say N.
32 47
48 On devices that are running SH-IPL and want to keep the port
49 initialization consistent while not using the BIOS callbacks,
50 select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
51 the kernel command line option to toggle back and forth.
52
33config DEBUG_STACKOVERFLOW 53config DEBUG_STACKOVERFLOW
34 bool "Check for stack overflows" 54 bool "Check for stack overflows"
35 depends on DEBUG_KERNEL 55 depends on DEBUG_KERNEL
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 26d62ff51a64..d10bba5e1074 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -13,10 +13,6 @@
13# for "archclean" and "archdep" for cleaning up and making dependencies for 13# for "archclean" and "archdep" for cleaning up and making dependencies for
14# this architecture 14# this architecture
15# 15#
16
17cflags-y := -mb
18cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
19
20isa-y := any 16isa-y := any
21isa-$(CONFIG_SH_DSP) := sh 17isa-$(CONFIG_SH_DSP) := sh
22isa-$(CONFIG_CPU_SH2) := sh2 18isa-$(CONFIG_CPU_SH2) := sh2
@@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu
38endif 34endif
39endif 35endif
40 36
41cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) 37cflags-$(CONFIG_CPU_SH2) := -m2
42 38cflags-$(CONFIG_CPU_SH3) := -m3
43cflags-$(CONFIG_CPU_SH2) += -m2 39cflags-$(CONFIG_CPU_SH4) := -m4 \
44cflags-$(CONFIG_CPU_SH3) += -m3
45cflags-$(CONFIG_CPU_SH4) += -m4 \
46 $(call cc-option,-mno-implicit-fp,-m4-nofpu) 40 $(call cc-option,-mno-implicit-fp,-m4-nofpu)
47cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) 41cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,)
42
43cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb
44cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
45
46cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
48 47
49cflags-$(CONFIG_SH_DSP) += -Wa,-dsp 48cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
50cflags-$(CONFIG_SH_KGDB) += -g 49cflags-$(CONFIG_SH_KGDB) += -g
@@ -59,7 +58,9 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
59# never be used by anyone. Use a board-specific defconfig that has a 58# never be used by anyone. Use a board-specific defconfig that has a
60# reasonable chance of being current instead. 59# reasonable chance of being current instead.
61# 60#
62KBUILD_DEFCONFIG := rts7751r2d_defconfig 61KBUILD_DEFCONFIG := r7780rp_defconfig
62
63KBUILD_IMAGE := arch/sh/boot/zImage
63 64
64# 65#
65# Choosing incompatible machines durings configuration will result in 66# Choosing incompatible machines durings configuration will result in
@@ -109,6 +110,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
109machdir-$(CONFIG_SH_LANDISK) := landisk 110machdir-$(CONFIG_SH_LANDISK) := landisk
110machdir-$(CONFIG_SH_TITAN) := titan 111machdir-$(CONFIG_SH_TITAN) := titan
111machdir-$(CONFIG_SH_SHMIN) := shmin 112machdir-$(CONFIG_SH_SHMIN) := shmin
113machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206
114machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619
112machdir-$(CONFIG_SH_UNKNOWN) := unknown 115machdir-$(CONFIG_SH_UNKNOWN) := unknown
113 116
114incdir-y := $(notdir $(machdir-y)) 117incdir-y := $(notdir $(machdir-y))
@@ -124,6 +127,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/
124core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ 127core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/
125 128
126cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 129cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2
130cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a
127cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 131cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3
128cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 132cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4
129 133
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
index f1776d027978..574b0316ed56 100644
--- a/arch/sh/boards/renesas/r7780rp/Makefile
+++ b/arch/sh/boards/renesas/r7780rp/Makefile
@@ -3,4 +3,6 @@
3# 3#
4 4
5obj-y := setup.o io.o irq.o 5obj-y := setup.o io.o irq.o
6obj-$(CONFIG_HEARTBEAT) += led.o 6
7obj-$(CONFIG_HEARTBEAT) += led.o
8obj-$(CONFIG_PUSH_SWITCH) += psw.o
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
index aa15ec5bc69e..cc381e197783 100644
--- a/arch/sh/boards/renesas/r7780rp/irq.c
+++ b/arch/sh/boards/renesas/r7780rp/irq.c
@@ -10,6 +10,7 @@
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/irq.h> 12#include <linux/irq.h>
13#include <linux/interrupt.h>
13#include <linux/io.h> 14#include <linux/io.h>
14#include <asm/r7780rp.h> 15#include <asm/r7780rp.h>
15 16
diff --git a/arch/sh/boards/renesas/r7780rp/psw.c b/arch/sh/boards/renesas/r7780rp/psw.c
new file mode 100644
index 000000000000..c844dfa5d58d
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/psw.c
@@ -0,0 +1,122 @@
1/*
2 * arch/sh/boards/renesas/r7780rp/psw.c
3 *
4 * push switch support for RDBRP-1/RDBREVRP-1 debug boards.
5 *
6 * Copyright (C) 2006 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/io.h>
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/platform_device.h>
16#include <asm/mach/r7780rp.h>
17#include <asm/push-switch.h>
18
19static irqreturn_t psw_irq_handler(int irq, void *arg)
20{
21 struct platform_device *pdev = arg;
22 struct push_switch *psw = platform_get_drvdata(pdev);
23 struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
24 unsigned int l, mask;
25 int ret = 0;
26
27 l = ctrl_inw(PA_DBSW);
28
29 /* Nothing to do if there's no state change */
30 if (psw->state) {
31 ret = 1;
32 goto out;
33 }
34
35 mask = l & 0x70;
36 /* Figure out who raised it */
37 if (mask & (1 << psw_info->bit)) {
38 psw->state = !!(mask & (1 << psw_info->bit));
39 if (psw->state) /* debounce */
40 mod_timer(&psw->debounce, jiffies + 50);
41
42 ret = 1;
43 }
44
45out:
46 /* Clear the switch IRQs */
47 l |= (0x7 << 12);
48 ctrl_outw(l, PA_DBSW);
49
50 return IRQ_RETVAL(ret);
51}
52
53static struct resource psw_resources[] = {
54 [0] = {
55 .start = IRQ_PSW,
56 .flags = IORESOURCE_IRQ,
57 },
58};
59
60static struct push_switch_platform_info s2_platform_data = {
61 .name = "s2",
62 .bit = 6,
63 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
64 IRQF_SHARED,
65 .irq_handler = psw_irq_handler,
66};
67
68static struct platform_device s2_switch_device = {
69 .name = "push-switch",
70 .id = 0,
71 .num_resources = ARRAY_SIZE(psw_resources),
72 .resource = psw_resources,
73 .dev = {
74 .platform_data = &s2_platform_data,
75 },
76};
77
78static struct push_switch_platform_info s3_platform_data = {
79 .name = "s3",
80 .bit = 5,
81 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
82 IRQF_SHARED,
83 .irq_handler = psw_irq_handler,
84};
85
86static struct platform_device s3_switch_device = {
87 .name = "push-switch",
88 .id = 1,
89 .num_resources = ARRAY_SIZE(psw_resources),
90 .resource = psw_resources,
91 .dev = {
92 .platform_data = &s3_platform_data,
93 },
94};
95
96static struct push_switch_platform_info s4_platform_data = {
97 .name = "s4",
98 .bit = 4,
99 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
100 IRQF_SHARED,
101 .irq_handler = psw_irq_handler,
102};
103
104static struct platform_device s4_switch_device = {
105 .name = "push-switch",
106 .id = 2,
107 .num_resources = ARRAY_SIZE(psw_resources),
108 .resource = psw_resources,
109 .dev = {
110 .platform_data = &s4_platform_data,
111 },
112};
113
114static struct platform_device *psw_devices[] = {
115 &s2_switch_device, &s3_switch_device, &s4_switch_device,
116};
117
118static int __init psw_init(void)
119{
120 return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
121}
122module_init(psw_init);
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index c331caeb694b..9f89c8de9db9 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -44,8 +44,37 @@ static struct platform_device m66596_usb_host_device = {
44 .resource = m66596_usb_host_resources, 44 .resource = m66596_usb_host_resources,
45}; 45};
46 46
47static struct resource cf_ide_resources[] = {
48 [0] = {
49 .start = 0x1f0,
50 .end = 0x1f0 + 8,
51 .flags = IORESOURCE_IO,
52 },
53 [1] = {
54 .start = 0x1f0 + 0x206,
55 .end = 0x1f0 + 8 + 0x206 + 8,
56 .flags = IORESOURCE_IO,
57 },
58 [2] = {
59#ifdef CONFIG_SH_R7780MP
60 .start = 1,
61#else
62 .start = 4,
63#endif
64 .flags = IORESOURCE_IRQ,
65 },
66};
67
68static struct platform_device cf_ide_device = {
69 .name = "pata_platform",
70 .id = -1,
71 .num_resources = ARRAY_SIZE(cf_ide_resources),
72 .resource = cf_ide_resources,
73};
74
47static struct platform_device *r7780rp_devices[] __initdata = { 75static struct platform_device *r7780rp_devices[] __initdata = {
48 &m66596_usb_host_device, 76 &m66596_usb_host_device,
77 &cf_ide_device,
49}; 78};
50 79
51static int __init r7780rp_devices_setup(void) 80static int __init r7780rp_devices_setup(void)
diff --git a/arch/sh/boards/se/7206/Makefile b/arch/sh/boards/se/7206/Makefile
new file mode 100644
index 000000000000..63950f4f2453
--- /dev/null
+++ b/arch/sh/boards/se/7206/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the 7206 SolutionEngine specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o
6obj-$(CONFIG_HEARTBEAT) += led.o
7
diff --git a/arch/sh/boards/se/7206/io.c b/arch/sh/boards/se/7206/io.c
new file mode 100644
index 000000000000..b557273e0cbe
--- /dev/null
+++ b/arch/sh/boards/se/7206/io.c
@@ -0,0 +1,123 @@
1/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
2 *
3 * linux/arch/sh/boards/se/7206/io.c
4 *
5 * Copyright (C) 2006 Yoshinori Sato
6 *
7 * I/O routine for Hitachi 7206 SolutionEngine.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/io.h>
14#include <asm/se7206.h>
15
16
17static inline void delay(void)
18{
19 ctrl_inw(0x20000000); /* P2 ROM Area */
20}
21
22/* MS7750 requires special versions of in*, out* routines, since
23 PC-like io ports are located at upper half byte of 16-bit word which
24 can be accessed only with 16-bit wide. */
25
26static inline volatile __u16 *
27port2adr(unsigned int port)
28{
29 if (port >= 0x2000)
30 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
31 else if (port >= 0x300 || port < 0x310)
32 return (volatile __u16 *) (PA_SMSC + (port - 0x300));
33}
34
35unsigned char se7206_inb(unsigned long port)
36{
37 return (*port2adr(port))&0xff;
38}
39
40unsigned char se7206_inb_p(unsigned long port)
41{
42 unsigned long v;
43
44 v = (*port2adr(port))&0xff;
45 delay();
46 return v;
47}
48
49unsigned short se7206_inw(unsigned long port)
50{
51 return *port2adr(port);;
52}
53
54unsigned int se7206_inl(unsigned long port)
55{
56 maybebadio(port);
57 return 0;
58}
59
60void se7206_outb(unsigned char value, unsigned long port)
61{
62 *(port2adr(port)) = value;
63}
64
65void se7206_outb_p(unsigned char value, unsigned long port)
66{
67 *(port2adr(port)) = value;
68 delay();
69}
70
71void se7206_outw(unsigned short value, unsigned long port)
72{
73 *port2adr(port) = value;
74}
75
76void se7206_outl(unsigned int value, unsigned long port)
77{
78 maybebadio(port);
79}
80
81void se7206_insb(unsigned long port, void *addr, unsigned long count)
82{
83 volatile __u16 *p = port2adr(port);
84 __u8 *ap = addr;
85
86 while (count--)
87 *ap++ = *p;
88}
89
90void se7206_insw(unsigned long port, void *addr, unsigned long count)
91{
92 volatile __u16 *p = port2adr(port);
93 __u16 *ap = addr;
94 while (count--)
95 *ap++ = *p;
96}
97
98void se7206_insl(unsigned long port, void *addr, unsigned long count)
99{
100 maybebadio(port);
101}
102
103void se7206_outsb(unsigned long port, const void *addr, unsigned long count)
104{
105 volatile __u16 *p = port2adr(port);
106 const __u8 *ap = addr;
107
108 while (count--)
109 *p = *ap++;
110}
111
112void se7206_outsw(unsigned long port, const void *addr, unsigned long count)
113{
114 volatile __u16 *p = port2adr(port);
115 const __u16 *ap = addr;
116 while (count--)
117 *p = *ap++;
118}
119
120void se7206_outsl(unsigned long port, const void *addr, unsigned long count)
121{
122 maybebadio(port);
123}
diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c
new file mode 100644
index 000000000000..3fb0c5f5b23a
--- /dev/null
+++ b/arch/sh/boards/se/7206/irq.c
@@ -0,0 +1,139 @@
1/*
2 * linux/arch/sh/boards/se/7206/irq.c
3 *
4 * Copyright (C) 2005,2006 Yoshinori Sato
5 *
6 * Hitachi SolutionEngine Support.
7 *
8 */
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/io.h>
12#include <linux/irq.h>
13#include <asm/se7206.h>
14
15#define INTSTS0 0x31800000
16#define INTSTS1 0x31800002
17#define INTMSK0 0x31800004
18#define INTMSK1 0x31800006
19#define INTSEL 0x31800008
20
21static void disable_se7206_irq(unsigned int irq)
22{
23 unsigned short val;
24 unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
25 unsigned short msk0,msk1;
26
27 /* Set the priority in IPR to 0 */
28 val = ctrl_inw(INTC_IPR01);
29 val &= mask;
30 ctrl_outw(val, INTC_IPR01);
31 /* FPGA mask set */
32 msk0 = ctrl_inw(INTMSK0);
33 msk1 = ctrl_inw(INTMSK1);
34
35 switch (irq) {
36 case IRQ0_IRQ:
37 msk0 |= 0x0010;
38 break;
39 case IRQ1_IRQ:
40 msk0 |= 0x000f;
41 break;
42 case IRQ2_IRQ:
43 msk0 |= 0x0f00;
44 msk1 |= 0x00ff;
45 break;
46 }
47 ctrl_outw(msk0, INTMSK0);
48 ctrl_outw(msk1, INTMSK1);
49}
50
51static void enable_se7206_irq(unsigned int irq)
52{
53 unsigned short val;
54 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
55 unsigned short msk0,msk1;
56
57 /* Set priority in IPR back to original value */
58 val = ctrl_inw(INTC_IPR01);
59 val |= value;
60 ctrl_outw(val, INTC_IPR01);
61
62 /* FPGA mask reset */
63 msk0 = ctrl_inw(INTMSK0);
64 msk1 = ctrl_inw(INTMSK1);
65
66 switch (irq) {
67 case IRQ0_IRQ:
68 msk0 &= ~0x0010;
69 break;
70 case IRQ1_IRQ:
71 msk0 &= ~0x000f;
72 break;
73 case IRQ2_IRQ:
74 msk0 &= ~0x0f00;
75 msk1 &= ~0x00ff;
76 break;
77 }
78 ctrl_outw(msk0, INTMSK0);
79 ctrl_outw(msk1, INTMSK1);
80}
81
82static void eoi_se7206_irq(unsigned int irq)
83{
84 unsigned short sts0,sts1;
85
86 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
87 enable_se7206_irq(irq);
88 /* FPGA isr clear */
89 sts0 = ctrl_inw(INTSTS0);
90 sts1 = ctrl_inw(INTSTS1);
91
92 switch (irq) {
93 case IRQ0_IRQ:
94 sts0 &= ~0x0010;
95 break;
96 case IRQ1_IRQ:
97 sts0 &= ~0x000f;
98 break;
99 case IRQ2_IRQ:
100 sts0 &= ~0x0f00;
101 sts1 &= ~0x00ff;
102 break;
103 }
104 ctrl_outw(sts0, INTSTS0);
105 ctrl_outw(sts1, INTSTS1);
106}
107
108static struct irq_chip se7206_irq_chip __read_mostly = {
109 .name = "SE7206-FPGA-IRQ",
110 .mask = disable_se7206_irq,
111 .unmask = enable_se7206_irq,
112 .mask_ack = disable_se7206_irq,
113 .eoi = eoi_se7206_irq,
114};
115
116static void make_se7206_irq(unsigned int irq)
117{
118 disable_irq_nosync(irq);
119 set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
120 handle_level_irq, "level");
121 disable_se7206_irq(irq);
122}
123
124/*
125 * Initialize IRQ setting
126 */
127void __init init_se7206_IRQ(void)
128{
129 make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
130 make_se7206_irq(IRQ1_IRQ); /* ATA */
131 make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
132 ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
133
134 /* FPGA System register setup*/
135 ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
136 ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
137 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
138 ctrl_outw(0x0001,INTSEL);
139}
diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c
new file mode 100644
index 000000000000..ef794601ab86
--- /dev/null
+++ b/arch/sh/boards/se/7206/led.c
@@ -0,0 +1,57 @@
1/*
2 * linux/arch/sh/kernel/led_se.c
3 *
4 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains Solution Engine specific LED code.
10 */
11
12#include <linux/config.h>
13#include <asm/se7206.h>
14
15#ifdef CONFIG_HEARTBEAT
16
17#include <linux/sched.h>
18
19/* Cycle the LED's in the clasic Knightrider/Sun pattern */
20void heartbeat_se(void)
21{
22 static unsigned int cnt = 0, period = 0;
23 volatile unsigned short* p = (volatile unsigned short*)PA_LED;
24 static unsigned bit = 0, up = 1;
25
26 cnt += 1;
27 if (cnt < period) {
28 return;
29 }
30
31 cnt = 0;
32
33 /* Go through the points (roughly!):
34 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
35 */
36 period = 110 - ( (300<<FSHIFT)/
37 ((avenrun[0]/5) + (3<<FSHIFT)) );
38
39 if (up) {
40 if (bit == 7) {
41 bit--;
42 up=0;
43 } else {
44 bit ++;
45 }
46 } else {
47 if (bit == 0) {
48 bit++;
49 up=1;
50 } else {
51 bit--;
52 }
53 }
54 *p = 1<<(bit+8);
55
56}
57#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
new file mode 100644
index 000000000000..0f42e91a3238
--- /dev/null
+++ b/arch/sh/boards/se/7206/setup.c
@@ -0,0 +1,79 @@
1/*
2 *
3 * linux/arch/sh/boards/se/7206/setup.c
4 *
5 * Copyright (C) 2006 Yoshinori Sato
6 *
7 * Hitachi 7206 SolutionEngine Support.
8 *
9 */
10
11#include <linux/init.h>
12#include <linux/platform_device.h>
13#include <asm/se7206.h>
14#include <asm/io.h>
15#include <asm/machvec.h>
16
17static struct resource smc91x_resources[] = {
18 [0] = {
19 .start = 0x300,
20 .end = 0x300 + 0x020 - 1,
21 .flags = IORESOURCE_MEM,
22 },
23 [1] = {
24 .start = 64,
25 .end = 64,
26 .flags = IORESOURCE_IRQ,
27 },
28};
29
30static struct platform_device smc91x_device = {
31 .name = "smc91x",
32 .id = -1,
33 .num_resources = ARRAY_SIZE(smc91x_resources),
34 .resource = smc91x_resources,
35};
36
37static int __init se7206_devices_setup(void)
38{
39 return platform_device_register(&smc91x_device);
40}
41
42__initcall(se7206_devices_setup);
43
44void heartbeat_se(void);
45
46/*
47 * The Machine Vector
48 */
49
50struct sh_machine_vector mv_se __initmv = {
51 .mv_name = "SolutionEngine",
52 .mv_nr_irqs = 256,
53 .mv_inb = se7206_inb,
54 .mv_inw = se7206_inw,
55 .mv_inl = se7206_inl,
56 .mv_outb = se7206_outb,
57 .mv_outw = se7206_outw,
58 .mv_outl = se7206_outl,
59
60 .mv_inb_p = se7206_inb_p,
61 .mv_inw_p = se7206_inw,
62 .mv_inl_p = se7206_inl,
63 .mv_outb_p = se7206_outb_p,
64 .mv_outw_p = se7206_outw,
65 .mv_outl_p = se7206_outl,
66
67 .mv_insb = se7206_insb,
68 .mv_insw = se7206_insw,
69 .mv_insl = se7206_insl,
70 .mv_outsb = se7206_outsb,
71 .mv_outsw = se7206_outsw,
72 .mv_outsl = se7206_outsl,
73
74 .mv_init_irq = init_se7206_IRQ,
75#ifdef CONFIG_HEARTBEAT
76 .mv_heartbeat = heartbeat_se,
77#endif
78};
79ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile
new file mode 100644
index 000000000000..3666eca8a658
--- /dev/null
+++ b/arch/sh/boards/se/7619/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the 7619 SolutionEngine specific parts of the kernel
3#
4
5obj-y := setup.o io.o
diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c
new file mode 100644
index 000000000000..176f1f39cd9d
--- /dev/null
+++ b/arch/sh/boards/se/7619/io.c
@@ -0,0 +1,102 @@
1/*
2 *
3 * linux/arch/sh/boards/se/7619/io.c
4 *
5 * Copyright (C) 2006 Yoshinori Sato
6 *
7 * I/O routine for Hitachi 7619 SolutionEngine.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/io.h>
14#include <asm/se7619.h>
15#include <asm/irq.h>
16
17/* FIXME: M3A-ZAB7 Compact Flash Slot support */
18
19static inline void delay(void)
20{
21 ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */
22}
23
24#define badio(name,port) \
25 printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
26 #name, (port), (__u32) __builtin_return_address(0))
27
28unsigned char se7619___inb(unsigned long port)
29{
30 badio(inb, port);
31 return 0;
32}
33
34unsigned char se7619___inb_p(unsigned long port)
35{
36 badio(inb_p, port);
37 delay();
38 return 0;
39}
40
41unsigned short se7619___inw(unsigned long port)
42{
43 badio(inw, port);
44 return 0;
45}
46
47unsigned int se7619___inl(unsigned long port)
48{
49 badio(inl, port);
50 return 0;
51}
52
53void se7619___outb(unsigned char value, unsigned long port)
54{
55 badio(outb, port);
56}
57
58void se7619___outb_p(unsigned char value, unsigned long port)
59{
60 badio(outb_p, port);
61 delay();
62}
63
64void se7619___outw(unsigned short value, unsigned long port)
65{
66 badio(outw, port);
67}
68
69void se7619___outl(unsigned int value, unsigned long port)
70{
71 badio(outl, port);
72}
73
74void se7619___insb(unsigned long port, void *addr, unsigned long count)
75{
76 badio(inw, port);
77}
78
79void se7619___insw(unsigned long port, void *addr, unsigned long count)
80{
81 badio(inw, port);
82}
83
84void se7619___insl(unsigned long port, void *addr, unsigned long count)
85{
86 badio(insl, port);
87}
88
89void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
90{
91 badio(insl, port);
92}
93
94void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
95{
96 badio(insl, port);
97}
98
99void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
100{
101 badio(outsw, port);
102}
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
new file mode 100644
index 000000000000..e627b26de0d0
--- /dev/null
+++ b/arch/sh/boards/se/7619/setup.c
@@ -0,0 +1,43 @@
1/*
2 * arch/sh/boards/se/7619/setup.c
3 *
4 * Copyright (C) 2006 Yoshinori Sato
5 *
6 * Hitachi SH7619 SolutionEngine Support.
7 */
8
9#include <linux/init.h>
10#include <linux/platform_device.h>
11#include <asm/io.h>
12#include <asm/se7619.h>
13#include <asm/machvec.h>
14
15/*
16 * The Machine Vector
17 */
18
19struct sh_machine_vector mv_se __initmv = {
20 .mv_name = "SolutionEngine",
21 .mv_nr_irqs = 108,
22 .mv_inb = se7619___inb,
23 .mv_inw = se7619___inw,
24 .mv_inl = se7619___inl,
25 .mv_outb = se7619___outb,
26 .mv_outw = se7619___outw,
27 .mv_outl = se7619___outl,
28
29 .mv_inb_p = se7619___inb_p,
30 .mv_inw_p = se7619___inw,
31 .mv_inl_p = se7619___inl,
32 .mv_outb_p = se7619___outb_p,
33 .mv_outw_p = se7619___outw,
34 .mv_outl_p = se7619___outl,
35
36 .mv_insb = se7619___insb,
37 .mv_insw = se7619___insw,
38 .mv_insl = se7619___insl,
39 .mv_outsb = se7619___outsb,
40 .mv_outsw = se7619___outsw,
41 .mv_outsl = se7619___outsl,
42};
43ALIAS_MV(se)
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
index a6046d93758b..6bcd939bfaed 100644
--- a/arch/sh/boards/titan/setup.c
+++ b/arch/sh/boards/titan/setup.c
@@ -1,26 +1,30 @@
1/* 1/*
2 * Setup for Titan 2 * arch/sh/boards/titan/setup.c - Setup for Titan
3 *
4 * Copyright (C) 2006 Jamie Lenehan
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
3 */ 9 */
4
5#include <linux/init.h> 10#include <linux/init.h>
6#include <asm/irq.h> 11#include <linux/irq.h>
7#include <asm/titan.h> 12#include <asm/titan.h>
8#include <asm/io.h> 13#include <asm/io.h>
9 14
10extern void __init pcibios_init_platform(void);
11
12static struct ipr_data titan_ipr_map[] = { 15static struct ipr_data titan_ipr_map[] = {
13 { TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, 16 /* IRQ, IPR idx, shift, prio */
14 { TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, 17 { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */
15 { TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, 18 { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */
16 { TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, 19 { TITAN_IRQ_MPCIA, 3, 4, 8 }, /* mPCI A (top) */
20 { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */
17}; 21};
18 22
19static void __init init_titan_irq(void) 23static void __init init_titan_irq(void)
20{ 24{
21 /* enable individual interrupt mode for externals */ 25 /* enable individual interrupt mode for externals */
22 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); 26 ipr_irq_enable_irlm();
23 27 /* register ipr irqs */
24 make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); 28 make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
25} 29}
26 30
@@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = {
47 .mv_ioport_map = titan_ioport_map, 51 .mv_ioport_map = titan_ioport_map,
48 52
49 .mv_init_irq = init_titan_irq, 53 .mv_init_irq = init_titan_irq,
50 .mv_init_pci = pcibios_init_platform,
51}; 54};
52ALIAS_MV(titan) 55ALIAS_MV(titan)
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
index f2fed5ce5cc3..35452d85b7f7 100644
--- a/arch/sh/boot/compressed/misc.c
+++ b/arch/sh/boot/compressed/misc.c
@@ -12,6 +12,7 @@
12 */ 12 */
13 13
14#include <asm/uaccess.h> 14#include <asm/uaccess.h>
15#include <asm/addrspace.h>
15#ifdef CONFIG_SH_STANDARD_BIOS 16#ifdef CONFIG_SH_STANDARD_BIOS
16#include <asm/sh_bios.h> 17#include <asm/sh_bios.h>
17#endif 18#endif
@@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE];
228void decompress_kernel(void) 229void decompress_kernel(void)
229{ 230{
230 output_data = 0; 231 output_data = 0;
231 output_ptr = (unsigned long)&_text+0x20001000; 232 output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
232 free_mem_ptr = (unsigned long)&_end; 233 free_mem_ptr = (unsigned long)&_end;
233 free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; 234 free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
234 235
diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig
index 34e2046c3213..2b75b4896ba5 100644
--- a/arch/sh/configs/r7780rp_defconfig
+++ b/arch/sh/configs/r7780rp_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc3 3# Linux kernel version: 2.6.19
4# Tue Oct 31 12:32:06 2006 4# Wed Dec 6 11:59:38 2006
5# 5#
6CONFIG_SUPERH=y 6CONFIG_SUPERH=y
7CONFIG_RWSEM_GENERIC_SPINLOCK=y 7CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y
11CONFIG_GENERIC_IRQ_PROBE=y 11CONFIG_GENERIC_IRQ_PROBE=y
12CONFIG_GENERIC_CALIBRATE_DELAY=y 12CONFIG_GENERIC_CALIBRATE_DELAY=y
13# CONFIG_GENERIC_TIME is not set 13# CONFIG_GENERIC_TIME is not set
14CONFIG_STACKTRACE_SUPPORT=y
15CONFIG_LOCKDEP_SUPPORT=y
14CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 16CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
15 17
16# 18#
@@ -37,6 +39,7 @@ CONFIG_BSD_PROCESS_ACCT=y
37# CONFIG_AUDIT is not set 39# CONFIG_AUDIT is not set
38CONFIG_IKCONFIG=y 40CONFIG_IKCONFIG=y
39CONFIG_IKCONFIG_PROC=y 41CONFIG_IKCONFIG_PROC=y
42# CONFIG_SYSFS_DEPRECATED is not set
40# CONFIG_RELAY is not set 43# CONFIG_RELAY is not set
41CONFIG_INITRAMFS_SOURCE="" 44CONFIG_INITRAMFS_SOURCE=""
42CONFIG_CC_OPTIMIZE_FOR_SIZE=y 45CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -118,6 +121,8 @@ CONFIG_SH_R7780RP=y
118# CONFIG_SH_LANDISK is not set 121# CONFIG_SH_LANDISK is not set
119# CONFIG_SH_TITAN is not set 122# CONFIG_SH_TITAN is not set
120# CONFIG_SH_SHMIN is not set 123# CONFIG_SH_SHMIN is not set
124# CONFIG_SH_7206_SOLUTION_ENGINE is not set
125# CONFIG_SH_7619_SOLUTION_ENGINE is not set
121# CONFIG_SH_UNKNOWN is not set 126# CONFIG_SH_UNKNOWN is not set
122 127
123# 128#
@@ -130,6 +135,12 @@ CONFIG_CPU_SH4A=y
130# SH-2 Processor Support 135# SH-2 Processor Support
131# 136#
132# CONFIG_CPU_SUBTYPE_SH7604 is not set 137# CONFIG_CPU_SUBTYPE_SH7604 is not set
138# CONFIG_CPU_SUBTYPE_SH7619 is not set
139
140#
141# SH-2A Processor Support
142#
143# CONFIG_CPU_SUBTYPE_SH7206 is not set
133 144
134# 145#
135# SH-3 Processor Support 146# SH-3 Processor Support
@@ -165,6 +176,7 @@ CONFIG_CPU_SH4A=y
165# 176#
166# CONFIG_CPU_SUBTYPE_SH7770 is not set 177# CONFIG_CPU_SUBTYPE_SH7770 is not set
167CONFIG_CPU_SUBTYPE_SH7780=y 178CONFIG_CPU_SUBTYPE_SH7780=y
179# CONFIG_CPU_SUBTYPE_SH7785 is not set
168 180
169# 181#
170# SH4AL-DSP Processor Support 182# SH4AL-DSP Processor Support
@@ -181,8 +193,14 @@ CONFIG_MEMORY_START=0x08000000
181CONFIG_MEMORY_SIZE=0x08000000 193CONFIG_MEMORY_SIZE=0x08000000
182# CONFIG_32BIT is not set 194# CONFIG_32BIT is not set
183CONFIG_VSYSCALL=y 195CONFIG_VSYSCALL=y
196CONFIG_PAGE_SIZE_4KB=y
197# CONFIG_PAGE_SIZE_8KB is not set
198# CONFIG_PAGE_SIZE_64KB is not set
184CONFIG_HUGETLB_PAGE_SIZE_64K=y 199CONFIG_HUGETLB_PAGE_SIZE_64K=y
200# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
185# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set 201# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
202# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
203# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
186CONFIG_SELECT_MEMORY_MODEL=y 204CONFIG_SELECT_MEMORY_MODEL=y
187CONFIG_FLATMEM_MANUAL=y 205CONFIG_FLATMEM_MANUAL=y
188# CONFIG_DISCONTIGMEM_MANUAL is not set 206# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,12 +222,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
204# Processor features 222# Processor features
205# 223#
206CONFIG_CPU_LITTLE_ENDIAN=y 224CONFIG_CPU_LITTLE_ENDIAN=y
225# CONFIG_CPU_BIG_ENDIAN is not set
207CONFIG_SH_FPU=y 226CONFIG_SH_FPU=y
208# CONFIG_SH_DSP is not set 227# CONFIG_SH_DSP is not set
209CONFIG_SH_STORE_QUEUES=y 228CONFIG_SH_STORE_QUEUES=y
210CONFIG_CPU_HAS_INTEVT=y 229CONFIG_CPU_HAS_INTEVT=y
211CONFIG_CPU_HAS_INTC2_IRQ=y 230CONFIG_CPU_HAS_INTC2_IRQ=y
212CONFIG_CPU_HAS_SR_RB=y 231CONFIG_CPU_HAS_SR_RB=y
232CONFIG_CPU_HAS_PTEA=y
213 233
214# 234#
215# Timer support 235# Timer support
@@ -220,6 +240,8 @@ CONFIG_SH_TMU=y
220# R7780RP options 240# R7780RP options
221# 241#
222CONFIG_SH_R7780MP=y 242CONFIG_SH_R7780MP=y
243CONFIG_SH_TIMER_IRQ=28
244CONFIG_NO_IDLE_HZ=y
223CONFIG_SH_PCLK_FREQ=32000000 245CONFIG_SH_PCLK_FREQ=32000000
224 246
225# 247#
@@ -238,13 +260,18 @@ CONFIG_SH_PCLK_FREQ=32000000
238# CONFIG_HD6446X_SERIES is not set 260# CONFIG_HD6446X_SERIES is not set
239 261
240# 262#
263# Additional SuperH Device Drivers
264#
265CONFIG_PUSH_SWITCH=y
266
267#
241# Kernel features 268# Kernel features
242# 269#
243# CONFIG_HZ_100 is not set 270# CONFIG_HZ_100 is not set
244CONFIG_HZ_250=y 271CONFIG_HZ_250=y
245# CONFIG_HZ_1000 is not set 272# CONFIG_HZ_1000 is not set
246CONFIG_HZ=250 273CONFIG_HZ=250
247# CONFIG_KEXEC is not set 274CONFIG_KEXEC=y
248# CONFIG_SMP is not set 275# CONFIG_SMP is not set
249# CONFIG_PREEMPT_NONE is not set 276# CONFIG_PREEMPT_NONE is not set
250# CONFIG_PREEMPT_VOLUNTARY is not set 277# CONFIG_PREEMPT_VOLUNTARY is not set
@@ -278,10 +305,7 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
278# 305#
279# PCI Hotplug Support 306# PCI Hotplug Support
280# 307#
281CONFIG_HOTPLUG_PCI=y 308# CONFIG_HOTPLUG_PCI is not set
282# CONFIG_HOTPLUG_PCI_FAKE is not set
283# CONFIG_HOTPLUG_PCI_CPCI is not set
284# CONFIG_HOTPLUG_PCI_SHPC is not set
285 309
286# 310#
287# Executable file formats 311# Executable file formats
@@ -341,6 +365,7 @@ CONFIG_INET_TCP_DIAG=y
341# CONFIG_TCP_CONG_ADVANCED is not set 365# CONFIG_TCP_CONG_ADVANCED is not set
342CONFIG_TCP_CONG_CUBIC=y 366CONFIG_TCP_CONG_CUBIC=y
343CONFIG_DEFAULT_TCP_CONG="cubic" 367CONFIG_DEFAULT_TCP_CONG="cubic"
368# CONFIG_TCP_MD5SIG is not set
344# CONFIG_IPV6 is not set 369# CONFIG_IPV6 is not set
345# CONFIG_INET6_XFRM_TUNNEL is not set 370# CONFIG_INET6_XFRM_TUNNEL is not set
346# CONFIG_INET6_TUNNEL is not set 371# CONFIG_INET6_TUNNEL is not set
@@ -556,6 +581,7 @@ CONFIG_SATA_SIL=y
556# CONFIG_PATA_IT821X is not set 581# CONFIG_PATA_IT821X is not set
557# CONFIG_PATA_JMICRON is not set 582# CONFIG_PATA_JMICRON is not set
558# CONFIG_PATA_TRIFLEX is not set 583# CONFIG_PATA_TRIFLEX is not set
584# CONFIG_PATA_MARVELL is not set
559# CONFIG_PATA_MPIIX is not set 585# CONFIG_PATA_MPIIX is not set
560# CONFIG_PATA_OLDPIIX is not set 586# CONFIG_PATA_OLDPIIX is not set
561# CONFIG_PATA_NETCELL is not set 587# CONFIG_PATA_NETCELL is not set
@@ -572,6 +598,7 @@ CONFIG_SATA_SIL=y
572# CONFIG_PATA_SIS is not set 598# CONFIG_PATA_SIS is not set
573# CONFIG_PATA_VIA is not set 599# CONFIG_PATA_VIA is not set
574# CONFIG_PATA_WINBOND is not set 600# CONFIG_PATA_WINBOND is not set
601CONFIG_PATA_PLATFORM=y
575 602
576# 603#
577# Multi-device support (RAID and LVM) 604# Multi-device support (RAID and LVM)
@@ -688,6 +715,7 @@ CONFIG_R8169=y
688# CONFIG_IXGB is not set 715# CONFIG_IXGB is not set
689# CONFIG_S2IO is not set 716# CONFIG_S2IO is not set
690# CONFIG_MYRI10GE is not set 717# CONFIG_MYRI10GE is not set
718# CONFIG_NETXEN_NIC is not set
691 719
692# 720#
693# Token Ring devices 721# Token Ring devices
@@ -830,10 +858,6 @@ CONFIG_HW_RANDOM=y
830# CONFIG_DTLK is not set 858# CONFIG_DTLK is not set
831# CONFIG_R3964 is not set 859# CONFIG_R3964 is not set
832# CONFIG_APPLICOM is not set 860# CONFIG_APPLICOM is not set
833
834#
835# Ftape, the floppy tape device driver
836#
837# CONFIG_DRM is not set 861# CONFIG_DRM is not set
838# CONFIG_RAW_DRIVER is not set 862# CONFIG_RAW_DRIVER is not set
839 863
@@ -1020,7 +1044,7 @@ CONFIG_INOTIFY_USER=y
1020CONFIG_DNOTIFY=y 1044CONFIG_DNOTIFY=y
1021# CONFIG_AUTOFS_FS is not set 1045# CONFIG_AUTOFS_FS is not set
1022# CONFIG_AUTOFS4_FS is not set 1046# CONFIG_AUTOFS4_FS is not set
1023# CONFIG_FUSE_FS is not set 1047CONFIG_FUSE_FS=m
1024 1048
1025# 1049#
1026# CD-ROM/DVD Filesystems 1050# CD-ROM/DVD Filesystems
@@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y
1052CONFIG_HUGETLBFS=y 1076CONFIG_HUGETLBFS=y
1053CONFIG_HUGETLB_PAGE=y 1077CONFIG_HUGETLB_PAGE=y
1054CONFIG_RAMFS=y 1078CONFIG_RAMFS=y
1055# CONFIG_CONFIGFS_FS is not set 1079CONFIG_CONFIGFS_FS=m
1056 1080
1057# 1081#
1058# Miscellaneous filesystems 1082# Miscellaneous filesystems
@@ -1153,28 +1177,33 @@ CONFIG_NLS_ISO8859_1=y
1153# 1177#
1154# Profiling support 1178# Profiling support
1155# 1179#
1156# CONFIG_PROFILING is not set 1180CONFIG_PROFILING=y
1181CONFIG_OPROFILE=m
1157 1182
1158# 1183#
1159# Kernel hacking 1184# Kernel hacking
1160# 1185#
1161# CONFIG_PRINTK_TIME is not set 1186CONFIG_TRACE_IRQFLAGS_SUPPORT=y
1187CONFIG_PRINTK_TIME=y
1162CONFIG_ENABLE_MUST_CHECK=y 1188CONFIG_ENABLE_MUST_CHECK=y
1163# CONFIG_MAGIC_SYSRQ is not set 1189CONFIG_MAGIC_SYSRQ=y
1164# CONFIG_UNUSED_SYMBOLS is not set 1190# CONFIG_UNUSED_SYMBOLS is not set
1165CONFIG_DEBUG_KERNEL=y 1191CONFIG_DEBUG_KERNEL=y
1166CONFIG_LOG_BUF_SHIFT=14 1192CONFIG_LOG_BUF_SHIFT=14
1167CONFIG_DETECT_SOFTLOCKUP=y 1193CONFIG_DETECT_SOFTLOCKUP=y
1168# CONFIG_SCHEDSTATS is not set 1194# CONFIG_SCHEDSTATS is not set
1169# CONFIG_DEBUG_SLAB is not set 1195# CONFIG_DEBUG_SLAB is not set
1170CONFIG_DEBUG_SPINLOCK=y 1196# CONFIG_DEBUG_PREEMPT is not set
1197# CONFIG_DEBUG_SPINLOCK is not set
1171# CONFIG_DEBUG_MUTEXES is not set 1198# CONFIG_DEBUG_MUTEXES is not set
1172# CONFIG_DEBUG_RWSEMS is not set 1199# CONFIG_DEBUG_RWSEMS is not set
1200# CONFIG_DEBUG_LOCK_ALLOC is not set
1201# CONFIG_PROVE_LOCKING is not set
1173# CONFIG_DEBUG_SPINLOCK_SLEEP is not set 1202# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
1174# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set 1203# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
1175# CONFIG_DEBUG_KOBJECT is not set 1204# CONFIG_DEBUG_KOBJECT is not set
1176# CONFIG_DEBUG_BUGVERBOSE is not set 1205CONFIG_DEBUG_BUGVERBOSE=y
1177# CONFIG_DEBUG_INFO is not set 1206CONFIG_DEBUG_INFO=y
1178CONFIG_DEBUG_FS=y 1207CONFIG_DEBUG_FS=y
1179# CONFIG_DEBUG_VM is not set 1208# CONFIG_DEBUG_VM is not set
1180# CONFIG_DEBUG_LIST is not set 1209# CONFIG_DEBUG_LIST is not set
@@ -1184,7 +1213,7 @@ CONFIG_FORCED_INLINING=y
1184# CONFIG_RCU_TORTURE_TEST is not set 1213# CONFIG_RCU_TORTURE_TEST is not set
1185# CONFIG_SH_STANDARD_BIOS is not set 1214# CONFIG_SH_STANDARD_BIOS is not set
1186# CONFIG_EARLY_SCIF_CONSOLE is not set 1215# CONFIG_EARLY_SCIF_CONSOLE is not set
1187# CONFIG_DEBUG_STACKOVERFLOW is not set 1216CONFIG_DEBUG_STACKOVERFLOW=y
1188# CONFIG_DEBUG_STACK_USAGE is not set 1217# CONFIG_DEBUG_STACK_USAGE is not set
1189# CONFIG_4KSTACKS is not set 1218# CONFIG_4KSTACKS is not set
1190# CONFIG_KGDB is not set 1219# CONFIG_KGDB is not set
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
new file mode 100644
index 000000000000..36cec0b6e7c1
--- /dev/null
+++ b/arch/sh/configs/se7206_defconfig
@@ -0,0 +1,826 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc4
4# Sun Nov 5 16:20:10 2006
5#
6CONFIG_SUPERH=y
7CONFIG_RWSEM_GENERIC_SPINLOCK=y
8CONFIG_GENERIC_FIND_NEXT_BIT=y
9CONFIG_GENERIC_HWEIGHT=y
10CONFIG_GENERIC_HARDIRQS=y
11CONFIG_GENERIC_IRQ_PROBE=y
12CONFIG_GENERIC_CALIBRATE_DELAY=y
13# CONFIG_GENERIC_TIME is not set
14CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
15
16#
17# Code maturity level options
18#
19CONFIG_EXPERIMENTAL=y
20CONFIG_BROKEN_ON_SMP=y
21CONFIG_INIT_ENV_ARG_LIMIT=32
22
23#
24# General setup
25#
26CONFIG_LOCALVERSION=""
27# CONFIG_LOCALVERSION_AUTO is not set
28# CONFIG_SYSVIPC is not set
29# CONFIG_POSIX_MQUEUE is not set
30# CONFIG_BSD_PROCESS_ACCT is not set
31# CONFIG_TASKSTATS is not set
32# CONFIG_UTS_NS is not set
33# CONFIG_AUDIT is not set
34# CONFIG_IKCONFIG is not set
35# CONFIG_RELAY is not set
36CONFIG_INITRAMFS_SOURCE=""
37# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
38CONFIG_SYSCTL=y
39CONFIG_EMBEDDED=y
40CONFIG_UID16=y
41# CONFIG_SYSCTL_SYSCALL is not set
42CONFIG_KALLSYMS=y
43# CONFIG_KALLSYMS_EXTRA_PASS is not set
44# CONFIG_HOTPLUG is not set
45CONFIG_PRINTK=y
46CONFIG_BUG=y
47CONFIG_ELF_CORE=y
48CONFIG_BASE_FULL=y
49# CONFIG_FUTEX is not set
50# CONFIG_EPOLL is not set
51CONFIG_SLAB=y
52CONFIG_VM_EVENT_COUNTERS=y
53CONFIG_TINY_SHMEM=y
54CONFIG_BASE_SMALL=0
55# CONFIG_SLOB is not set
56
57#
58# Loadable module support
59#
60# CONFIG_MODULES is not set
61
62#
63# Block layer
64#
65CONFIG_BLOCK=y
66# CONFIG_LBD is not set
67# CONFIG_LSF is not set
68
69#
70# IO Schedulers
71#
72CONFIG_IOSCHED_NOOP=y
73# CONFIG_IOSCHED_AS is not set
74# CONFIG_IOSCHED_DEADLINE is not set
75# CONFIG_IOSCHED_CFQ is not set
76# CONFIG_DEFAULT_AS is not set
77# CONFIG_DEFAULT_DEADLINE is not set
78# CONFIG_DEFAULT_CFQ is not set
79CONFIG_DEFAULT_NOOP=y
80CONFIG_DEFAULT_IOSCHED="noop"
81
82#
83# System type
84#
85# CONFIG_SH_SOLUTION_ENGINE is not set
86# CONFIG_SH_7751_SOLUTION_ENGINE is not set
87# CONFIG_SH_7300_SOLUTION_ENGINE is not set
88# CONFIG_SH_7343_SOLUTION_ENGINE is not set
89# CONFIG_SH_73180_SOLUTION_ENGINE is not set
90# CONFIG_SH_7751_SYSTEMH is not set
91# CONFIG_SH_HP6XX is not set
92# CONFIG_SH_EC3104 is not set
93# CONFIG_SH_SATURN is not set
94# CONFIG_SH_DREAMCAST is not set
95# CONFIG_SH_BIGSUR is not set
96# CONFIG_SH_MPC1211 is not set
97# CONFIG_SH_SH03 is not set
98# CONFIG_SH_SECUREEDGE5410 is not set
99# CONFIG_SH_HS7751RVOIP is not set
100# CONFIG_SH_7710VOIPGW is not set
101# CONFIG_SH_RTS7751R2D is not set
102# CONFIG_SH_R7780RP is not set
103# CONFIG_SH_EDOSK7705 is not set
104# CONFIG_SH_SH4202_MICRODEV is not set
105# CONFIG_SH_LANDISK is not set
106# CONFIG_SH_TITAN is not set
107# CONFIG_SH_SHMIN is not set
108CONFIG_SH_7206_SOLUTION_ENGINE=y
109# CONFIG_SH_7619_SOLUTION_ENGINE is not set
110# CONFIG_SH_UNKNOWN is not set
111
112#
113# Processor selection
114#
115CONFIG_CPU_SH2=y
116CONFIG_CPU_SH2A=y
117
118#
119# SH-2 Processor Support
120#
121# CONFIG_CPU_SUBTYPE_SH7604 is not set
122# CONFIG_CPU_SUBTYPE_SH7619 is not set
123
124#
125# SH-2A Processor Support
126#
127CONFIG_CPU_SUBTYPE_SH7206=y
128
129#
130# SH-3 Processor Support
131#
132# CONFIG_CPU_SUBTYPE_SH7300 is not set
133# CONFIG_CPU_SUBTYPE_SH7705 is not set
134# CONFIG_CPU_SUBTYPE_SH7706 is not set
135# CONFIG_CPU_SUBTYPE_SH7707 is not set
136# CONFIG_CPU_SUBTYPE_SH7708 is not set
137# CONFIG_CPU_SUBTYPE_SH7709 is not set
138# CONFIG_CPU_SUBTYPE_SH7710 is not set
139
140#
141# SH-4 Processor Support
142#
143# CONFIG_CPU_SUBTYPE_SH7750 is not set
144# CONFIG_CPU_SUBTYPE_SH7091 is not set
145# CONFIG_CPU_SUBTYPE_SH7750R is not set
146# CONFIG_CPU_SUBTYPE_SH7750S is not set
147# CONFIG_CPU_SUBTYPE_SH7751 is not set
148# CONFIG_CPU_SUBTYPE_SH7751R is not set
149# CONFIG_CPU_SUBTYPE_SH7760 is not set
150# CONFIG_CPU_SUBTYPE_SH4_202 is not set
151
152#
153# ST40 Processor Support
154#
155# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
156# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
157
158#
159# SH-4A Processor Support
160#
161# CONFIG_CPU_SUBTYPE_SH7770 is not set
162# CONFIG_CPU_SUBTYPE_SH7780 is not set
163
164#
165# SH4AL-DSP Processor Support
166#
167# CONFIG_CPU_SUBTYPE_SH73180 is not set
168# CONFIG_CPU_SUBTYPE_SH7343 is not set
169
170#
171# Memory management options
172#
173CONFIG_PAGE_OFFSET=0x00000000
174CONFIG_MEMORY_START=0x0c000000
175CONFIG_MEMORY_SIZE=0x02000000
176CONFIG_SELECT_MEMORY_MODEL=y
177CONFIG_FLATMEM_MANUAL=y
178# CONFIG_DISCONTIGMEM_MANUAL is not set
179# CONFIG_SPARSEMEM_MANUAL is not set
180CONFIG_FLATMEM=y
181CONFIG_FLAT_NODE_MEM_MAP=y
182# CONFIG_SPARSEMEM_STATIC is not set
183CONFIG_SPLIT_PTLOCK_CPUS=4
184# CONFIG_RESOURCES_64BIT is not set
185
186#
187# Cache configuration
188#
189# CONFIG_SH_DIRECT_MAPPED is not set
190# CONFIG_SH_WRITETHROUGH is not set
191# CONFIG_SH_OCRAM is not set
192
193#
194# Processor features
195#
196# CONFIG_CPU_LITTLE_ENDIAN is not set
197# CONFIG_SH_FPU is not set
198# CONFIG_SH_FPU_EMU is not set
199# CONFIG_SH_DSP is not set
200
201#
202# Timer support
203#
204CONFIG_SH_CMT=y
205# CONFIG_SH_MTU2 is not set
206CONFIG_SH_PCLK_FREQ=33333333
207CONFIG_SH_CLK_MD=6
208
209#
210# CPU Frequency scaling
211#
212# CONFIG_CPU_FREQ is not set
213
214#
215# DMA support
216#
217# CONFIG_SH_DMA is not set
218
219#
220# Companion Chips
221#
222# CONFIG_HD6446X_SERIES is not set
223
224#
225# Kernel features
226#
227CONFIG_HZ_100=y
228# CONFIG_HZ_250 is not set
229# CONFIG_HZ_1000 is not set
230CONFIG_HZ=100
231# CONFIG_KEXEC is not set
232# CONFIG_SMP is not set
233CONFIG_PREEMPT_NONE=y
234# CONFIG_PREEMPT_VOLUNTARY is not set
235# CONFIG_PREEMPT is not set
236
237#
238# Boot options
239#
240CONFIG_ZERO_PAGE_OFFSET=0x00001000
241CONFIG_BOOT_LINK_OFFSET=0x00800000
242# CONFIG_UBC_WAKEUP is not set
243# CONFIG_CMDLINE_BOOL is not set
244
245#
246# Bus options
247#
248# CONFIG_PCI is not set
249
250#
251# PCCARD (PCMCIA/CardBus) support
252#
253
254#
255# PCI Hotplug Support
256#
257
258#
259# Executable file formats
260#
261CONFIG_BINFMT_FLAT=y
262CONFIG_BINFMT_ZFLAT=y
263# CONFIG_BINFMT_SHARED_FLAT is not set
264# CONFIG_BINFMT_MISC is not set
265
266#
267# Power management options (EXPERIMENTAL)
268#
269# CONFIG_PM is not set
270
271#
272# Networking
273#
274CONFIG_NET=y
275
276#
277# Networking options
278#
279# CONFIG_NETDEBUG is not set
280# CONFIG_PACKET is not set
281# CONFIG_UNIX is not set
282CONFIG_XFRM=y
283# CONFIG_XFRM_USER is not set
284# CONFIG_XFRM_SUB_POLICY is not set
285# CONFIG_NET_KEY is not set
286CONFIG_INET=y
287# CONFIG_IP_MULTICAST is not set
288# CONFIG_IP_ADVANCED_ROUTER is not set
289CONFIG_IP_FIB_HASH=y
290# CONFIG_IP_PNP is not set
291# CONFIG_NET_IPIP is not set
292# CONFIG_NET_IPGRE is not set
293# CONFIG_ARPD is not set
294# CONFIG_SYN_COOKIES is not set
295# CONFIG_INET_AH is not set
296# CONFIG_INET_ESP is not set
297# CONFIG_INET_IPCOMP is not set
298# CONFIG_INET_XFRM_TUNNEL is not set
299# CONFIG_INET_TUNNEL is not set
300CONFIG_INET_XFRM_MODE_TRANSPORT=y
301CONFIG_INET_XFRM_MODE_TUNNEL=y
302CONFIG_INET_XFRM_MODE_BEET=y
303# CONFIG_INET_DIAG is not set
304# CONFIG_TCP_CONG_ADVANCED is not set
305CONFIG_TCP_CONG_CUBIC=y
306CONFIG_DEFAULT_TCP_CONG="cubic"
307# CONFIG_IPV6 is not set
308# CONFIG_INET6_XFRM_TUNNEL is not set
309# CONFIG_INET6_TUNNEL is not set
310# CONFIG_NETWORK_SECMARK is not set
311# CONFIG_NETFILTER is not set
312
313#
314# DCCP Configuration (EXPERIMENTAL)
315#
316# CONFIG_IP_DCCP is not set
317
318#
319# SCTP Configuration (EXPERIMENTAL)
320#
321# CONFIG_IP_SCTP is not set
322
323#
324# TIPC Configuration (EXPERIMENTAL)
325#
326# CONFIG_TIPC is not set
327# CONFIG_ATM is not set
328# CONFIG_BRIDGE is not set
329# CONFIG_VLAN_8021Q is not set
330# CONFIG_DECNET is not set
331# CONFIG_LLC2 is not set
332# CONFIG_IPX is not set
333# CONFIG_ATALK is not set
334# CONFIG_X25 is not set
335# CONFIG_LAPB is not set
336# CONFIG_ECONET is not set
337# CONFIG_WAN_ROUTER is not set
338
339#
340# QoS and/or fair queueing
341#
342# CONFIG_NET_SCHED is not set
343
344#
345# Network testing
346#
347# CONFIG_NET_PKTGEN is not set
348# CONFIG_HAMRADIO is not set
349# CONFIG_IRDA is not set
350# CONFIG_BT is not set
351# CONFIG_IEEE80211 is not set
352
353#
354# Device Drivers
355#
356
357#
358# Generic Driver Options
359#
360# CONFIG_STANDALONE is not set
361# CONFIG_PREVENT_FIRMWARE_BUILD is not set
362# CONFIG_SYS_HYPERVISOR is not set
363
364#
365# Connector - unified userspace <-> kernelspace linker
366#
367# CONFIG_CONNECTOR is not set
368
369#
370# Memory Technology Devices (MTD)
371#
372CONFIG_MTD=y
373# CONFIG_MTD_DEBUG is not set
374# CONFIG_MTD_CONCAT is not set
375CONFIG_MTD_PARTITIONS=y
376CONFIG_MTD_REDBOOT_PARTS=y
377CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
378# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
379# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
380# CONFIG_MTD_CMDLINE_PARTS is not set
381
382#
383# User Modules And Translation Layers
384#
385CONFIG_MTD_CHAR=y
386CONFIG_MTD_BLOCK=y
387# CONFIG_FTL is not set
388# CONFIG_NFTL is not set
389# CONFIG_INFTL is not set
390# CONFIG_RFD_FTL is not set
391# CONFIG_SSFDC is not set
392
393#
394# RAM/ROM/Flash chip drivers
395#
396CONFIG_MTD_CFI=y
397# CONFIG_MTD_JEDECPROBE is not set
398CONFIG_MTD_GEN_PROBE=y
399# CONFIG_MTD_CFI_ADV_OPTIONS is not set
400CONFIG_MTD_MAP_BANK_WIDTH_1=y
401CONFIG_MTD_MAP_BANK_WIDTH_2=y
402CONFIG_MTD_MAP_BANK_WIDTH_4=y
403# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
404# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
405# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
406CONFIG_MTD_CFI_I1=y
407CONFIG_MTD_CFI_I2=y
408# CONFIG_MTD_CFI_I4 is not set
409# CONFIG_MTD_CFI_I8 is not set
410# CONFIG_MTD_CFI_INTELEXT is not set
411CONFIG_MTD_CFI_AMDSTD=y
412# CONFIG_MTD_CFI_STAA is not set
413CONFIG_MTD_CFI_UTIL=y
414# CONFIG_MTD_RAM is not set
415# CONFIG_MTD_ROM is not set
416# CONFIG_MTD_ABSENT is not set
417# CONFIG_MTD_OBSOLETE_CHIPS is not set
418
419#
420# Mapping drivers for chip access
421#
422# CONFIG_MTD_COMPLEX_MAPPINGS is not set
423CONFIG_MTD_PHYSMAP=y
424CONFIG_MTD_PHYSMAP_START=0x20000000
425CONFIG_MTD_PHYSMAP_LEN=0x1000000
426CONFIG_MTD_PHYSMAP_BANKWIDTH=4
427# CONFIG_MTD_SOLUTIONENGINE is not set
428# CONFIG_MTD_UCLINUX is not set
429# CONFIG_MTD_PLATRAM is not set
430
431#
432# Self-contained MTD device drivers
433#
434# CONFIG_MTD_SLRAM is not set
435# CONFIG_MTD_PHRAM is not set
436# CONFIG_MTD_MTDRAM is not set
437# CONFIG_MTD_BLOCK2MTD is not set
438
439#
440# Disk-On-Chip Device Drivers
441#
442# CONFIG_MTD_DOC2000 is not set
443# CONFIG_MTD_DOC2001 is not set
444# CONFIG_MTD_DOC2001PLUS is not set
445
446#
447# NAND Flash Device Drivers
448#
449# CONFIG_MTD_NAND is not set
450
451#
452# OneNAND Flash Device Drivers
453#
454# CONFIG_MTD_ONENAND is not set
455
456#
457# Parallel port support
458#
459# CONFIG_PARPORT is not set
460
461#
462# Plug and Play support
463#
464
465#
466# Block devices
467#
468# CONFIG_BLK_DEV_COW_COMMON is not set
469# CONFIG_BLK_DEV_LOOP is not set
470# CONFIG_BLK_DEV_NBD is not set
471CONFIG_BLK_DEV_RAM=y
472CONFIG_BLK_DEV_RAM_COUNT=16
473CONFIG_BLK_DEV_RAM_SIZE=4096
474CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
475# CONFIG_BLK_DEV_INITRD is not set
476# CONFIG_CDROM_PKTCDVD is not set
477# CONFIG_ATA_OVER_ETH is not set
478
479#
480# Misc devices
481#
482# CONFIG_TIFM_CORE is not set
483
484#
485# ATA/ATAPI/MFM/RLL support
486#
487# CONFIG_IDE is not set
488
489#
490# SCSI device support
491#
492# CONFIG_RAID_ATTRS is not set
493# CONFIG_SCSI is not set
494# CONFIG_SCSI_NETLINK is not set
495
496#
497# Serial ATA (prod) and Parallel ATA (experimental) drivers
498#
499# CONFIG_ATA is not set
500
501#
502# Multi-device support (RAID and LVM)
503#
504# CONFIG_MD is not set
505
506#
507# Fusion MPT device support
508#
509# CONFIG_FUSION is not set
510
511#
512# IEEE 1394 (FireWire) support
513#
514
515#
516# I2O device support
517#
518
519#
520# Network device support
521#
522# CONFIG_NETDEVICES is not set
523# CONFIG_NETPOLL is not set
524# CONFIG_NET_POLL_CONTROLLER is not set
525
526#
527# ISDN subsystem
528#
529# CONFIG_ISDN is not set
530
531#
532# Telephony Support
533#
534# CONFIG_PHONE is not set
535
536#
537# Input device support
538#
539# CONFIG_INPUT is not set
540
541#
542# Hardware I/O ports
543#
544# CONFIG_SERIO is not set
545# CONFIG_GAMEPORT is not set
546
547#
548# Character devices
549#
550# CONFIG_VT is not set
551# CONFIG_SERIAL_NONSTANDARD is not set
552
553#
554# Serial drivers
555#
556# CONFIG_SERIAL_8250 is not set
557
558#
559# Non-8250 serial port support
560#
561CONFIG_SERIAL_SH_SCI=y
562CONFIG_SERIAL_SH_SCI_NR_UARTS=4
563CONFIG_SERIAL_SH_SCI_CONSOLE=y
564CONFIG_SERIAL_CORE=y
565CONFIG_SERIAL_CORE_CONSOLE=y
566# CONFIG_UNIX98_PTYS is not set
567CONFIG_LEGACY_PTYS=y
568CONFIG_LEGACY_PTY_COUNT=256
569
570#
571# IPMI
572#
573# CONFIG_IPMI_HANDLER is not set
574
575#
576# Watchdog Cards
577#
578# CONFIG_WATCHDOG is not set
579CONFIG_HW_RANDOM=y
580# CONFIG_GEN_RTC is not set
581# CONFIG_DTLK is not set
582# CONFIG_R3964 is not set
583
584#
585# Ftape, the floppy tape device driver
586#
587# CONFIG_RAW_DRIVER is not set
588
589#
590# TPM devices
591#
592# CONFIG_TCG_TPM is not set
593
594#
595# I2C support
596#
597# CONFIG_I2C is not set
598
599#
600# SPI support
601#
602# CONFIG_SPI is not set
603# CONFIG_SPI_MASTER is not set
604
605#
606# Dallas's 1-wire bus
607#
608# CONFIG_W1 is not set
609
610#
611# Hardware Monitoring support
612#
613CONFIG_HWMON=y
614# CONFIG_HWMON_VID is not set
615# CONFIG_SENSORS_ABITUGURU is not set
616# CONFIG_SENSORS_F71805F is not set
617# CONFIG_SENSORS_VT1211 is not set
618# CONFIG_HWMON_DEBUG_CHIP is not set
619
620#
621# Multimedia devices
622#
623# CONFIG_VIDEO_DEV is not set
624
625#
626# Digital Video Broadcasting Devices
627#
628# CONFIG_DVB is not set
629
630#
631# Graphics support
632#
633CONFIG_FIRMWARE_EDID=y
634# CONFIG_FB is not set
635
636#
637# Sound
638#
639# CONFIG_SOUND is not set
640
641#
642# USB support
643#
644# CONFIG_USB_ARCH_HAS_HCD is not set
645# CONFIG_USB_ARCH_HAS_OHCI is not set
646# CONFIG_USB_ARCH_HAS_EHCI is not set
647
648#
649# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
650#
651
652#
653# USB Gadget Support
654#
655# CONFIG_USB_GADGET is not set
656
657#
658# MMC/SD Card support
659#
660# CONFIG_MMC is not set
661
662#
663# LED devices
664#
665# CONFIG_NEW_LEDS is not set
666
667#
668# LED drivers
669#
670
671#
672# LED Triggers
673#
674
675#
676# InfiniBand support
677#
678
679#
680# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
681#
682
683#
684# Real Time Clock
685#
686# CONFIG_RTC_CLASS is not set
687
688#
689# DMA Engine support
690#
691# CONFIG_DMA_ENGINE is not set
692
693#
694# DMA Clients
695#
696
697#
698# DMA Devices
699#
700
701#
702# File systems
703#
704CONFIG_EXT2_FS=y
705# CONFIG_EXT2_FS_XATTR is not set
706# CONFIG_EXT3_FS is not set
707# CONFIG_EXT4DEV_FS is not set
708# CONFIG_REISERFS_FS is not set
709# CONFIG_JFS_FS is not set
710# CONFIG_FS_POSIX_ACL is not set
711# CONFIG_XFS_FS is not set
712# CONFIG_GFS2_FS is not set
713# CONFIG_MINIX_FS is not set
714CONFIG_ROMFS_FS=y
715# CONFIG_INOTIFY is not set
716# CONFIG_QUOTA is not set
717# CONFIG_DNOTIFY is not set
718# CONFIG_AUTOFS_FS is not set
719# CONFIG_AUTOFS4_FS is not set
720# CONFIG_FUSE_FS is not set
721
722#
723# CD-ROM/DVD Filesystems
724#
725# CONFIG_ISO9660_FS is not set
726# CONFIG_UDF_FS is not set
727
728#
729# DOS/FAT/NT Filesystems
730#
731# CONFIG_MSDOS_FS is not set
732# CONFIG_VFAT_FS is not set
733# CONFIG_NTFS_FS is not set
734
735#
736# Pseudo filesystems
737#
738CONFIG_PROC_FS=y
739CONFIG_PROC_SYSCTL=y
740# CONFIG_SYSFS is not set
741# CONFIG_TMPFS is not set
742# CONFIG_HUGETLBFS is not set
743# CONFIG_HUGETLB_PAGE is not set
744CONFIG_RAMFS=y
745
746#
747# Miscellaneous filesystems
748#
749# CONFIG_ADFS_FS is not set
750# CONFIG_AFFS_FS is not set
751# CONFIG_HFS_FS is not set
752# CONFIG_HFSPLUS_FS is not set
753# CONFIG_BEFS_FS is not set
754# CONFIG_BFS_FS is not set
755# CONFIG_EFS_FS is not set
756# CONFIG_JFFS_FS is not set
757# CONFIG_JFFS2_FS is not set
758CONFIG_CRAMFS=y
759# CONFIG_VXFS_FS is not set
760# CONFIG_HPFS_FS is not set
761# CONFIG_QNX4FS_FS is not set
762# CONFIG_SYSV_FS is not set
763# CONFIG_UFS_FS is not set
764
765#
766# Network File Systems
767#
768# CONFIG_NFS_FS is not set
769# CONFIG_NFSD is not set
770# CONFIG_SMB_FS is not set
771# CONFIG_CIFS is not set
772# CONFIG_NCP_FS is not set
773# CONFIG_CODA_FS is not set
774# CONFIG_AFS_FS is not set
775# CONFIG_9P_FS is not set
776
777#
778# Partition Types
779#
780# CONFIG_PARTITION_ADVANCED is not set
781CONFIG_MSDOS_PARTITION=y
782
783#
784# Native Language Support
785#
786# CONFIG_NLS is not set
787
788#
789# Profiling support
790#
791# CONFIG_PROFILING is not set
792
793#
794# Kernel hacking
795#
796# CONFIG_PRINTK_TIME is not set
797CONFIG_ENABLE_MUST_CHECK=y
798# CONFIG_MAGIC_SYSRQ is not set
799# CONFIG_UNUSED_SYMBOLS is not set
800# CONFIG_DEBUG_KERNEL is not set
801CONFIG_LOG_BUF_SHIFT=14
802# CONFIG_DEBUG_BUGVERBOSE is not set
803# CONFIG_UNWIND_INFO is not set
804# CONFIG_HEADERS_CHECK is not set
805# CONFIG_SH_STANDARD_BIOS is not set
806# CONFIG_EARLY_SCIF_CONSOLE is not set
807# CONFIG_KGDB is not set
808
809#
810# Security options
811#
812# CONFIG_KEYS is not set
813
814#
815# Cryptographic options
816#
817# CONFIG_CRYPTO is not set
818
819#
820# Library routines
821#
822CONFIG_CRC_CCITT=y
823# CONFIG_CRC16 is not set
824CONFIG_CRC32=y
825# CONFIG_LIBCRC32C is not set
826CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/drivers/Kconfig b/arch/sh/drivers/Kconfig
new file mode 100644
index 000000000000..c54c758e6243
--- /dev/null
+++ b/arch/sh/drivers/Kconfig
@@ -0,0 +1,9 @@
1menu "Additional SuperH Device Drivers"
2
3config PUSH_SWITCH
4 tristate "Push switch support"
5 help
6 This enables support for the push switch framework, a simple
7 framework that allows for sysfs driven switch status reporting.
8
9endmenu
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index 338c3729d270..bf18dbfb6787 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -5,4 +5,4 @@
5obj-$(CONFIG_PCI) += pci/ 5obj-$(CONFIG_PCI) += pci/
6obj-$(CONFIG_SH_DMA) += dma/ 6obj-$(CONFIG_SH_DMA) += dma/
7obj-$(CONFIG_SUPERHYWAY) += superhyway/ 7obj-$(CONFIG_SUPERHYWAY) += superhyway/
8 8obj-$(CONFIG_PUSH_SWITCH) += push-switch.o
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile
index 065d4c90970e..db1295d32268 100644
--- a/arch/sh/drivers/dma/Makefile
+++ b/arch/sh/drivers/dma/Makefile
@@ -2,8 +2,8 @@
2# Makefile for the SuperH DMA specific kernel interface routines under Linux. 2# Makefile for the SuperH DMA specific kernel interface routines under Linux.
3# 3#
4 4
5obj-y += dma-api.o dma-isa.o 5obj-y += dma-api.o
6obj-$(CONFIG_ISA_DMA_API) += dma-isa.o
6obj-$(CONFIG_SYSFS) += dma-sysfs.o 7obj-$(CONFIG_SYSFS) += dma-sysfs.o
7obj-$(CONFIG_SH_DMA) += dma-sh.o 8obj-$(CONFIG_SH_DMA) += dma-sh.o
8obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o 9obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o
9
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 47c3e837599b..e062067edd24 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -11,61 +11,27 @@
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/spinlock.h> 14#include <linux/spinlock.h>
16#include <linux/proc_fs.h> 15#include <linux/proc_fs.h>
17#include <linux/list.h> 16#include <linux/list.h>
18#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/mm.h>
19#include <asm/dma.h> 19#include <asm/dma.h>
20 20
21DEFINE_SPINLOCK(dma_spin_lock); 21DEFINE_SPINLOCK(dma_spin_lock);
22static LIST_HEAD(registered_dmac_list); 22static LIST_HEAD(registered_dmac_list);
23 23
24/*
25 * A brief note about the reasons for this API as it stands.
26 *
27 * For starters, the old ISA DMA API didn't work for us for a number of
28 * reasons, for one, the vast majority of channels on the SH DMAC are
29 * dual-address mode only, and both the new and the old DMA APIs are after the
30 * concept of managing a DMA buffer, which doesn't overly fit this model very
31 * well. In addition to which, the new API is largely geared at IOMMUs and
32 * GARTs, and doesn't even support the channel notion very well.
33 *
34 * The other thing that's a marginal issue, is the sheer number of random DMA
35 * engines that are present (ie, in boards like the Dreamcast), some of which
36 * cascade off of the SH DMAC, and others do not. As such, there was a real
37 * need for a scalable subsystem that could deal with both single and
38 * dual-address mode usage, in addition to interoperating with cascaded DMACs.
39 *
40 * There really isn't any reason why this needs to be SH specific, though I'm
41 * not aware of too many other processors (with the exception of some MIPS)
42 * that have the same concept of a dual address mode, or any real desire to
43 * actually make use of the DMAC even if such a subsystem were exposed
44 * elsewhere.
45 *
46 * The idea for this was derived from the ARM port, which acted as an excellent
47 * reference when trying to address these issues.
48 *
49 * It should also be noted that the decision to add Yet Another DMA API(tm) to
50 * the kernel wasn't made easily, and was only decided upon after conferring
51 * with jejb with regards to the state of the old and new APIs as they applied
52 * to these circumstances. Philip Blundell was also a great help in figuring
53 * out some single-address mode DMA semantics that were otherwise rather
54 * confusing.
55 */
56
57struct dma_info *get_dma_info(unsigned int chan) 24struct dma_info *get_dma_info(unsigned int chan)
58{ 25{
59 struct dma_info *info; 26 struct dma_info *info;
60 unsigned int total = 0;
61 27
62 /* 28 /*
63 * Look for each DMAC's range to determine who the owner of 29 * Look for each DMAC's range to determine who the owner of
64 * the channel is. 30 * the channel is.
65 */ 31 */
66 list_for_each_entry(info, &registered_dmac_list, list) { 32 list_for_each_entry(info, &registered_dmac_list, list) {
67 total += info->nr_channels; 33 if ((chan < info->first_channel_nr) ||
68 if (chan > total) 34 (chan >= info->first_channel_nr + info->nr_channels))
69 continue; 35 continue;
70 36
71 return info; 37 return info;
@@ -73,6 +39,22 @@ struct dma_info *get_dma_info(unsigned int chan)
73 39
74 return NULL; 40 return NULL;
75} 41}
42EXPORT_SYMBOL(get_dma_info);
43
44struct dma_info *get_dma_info_by_name(const char *dmac_name)
45{
46 struct dma_info *info;
47
48 list_for_each_entry(info, &registered_dmac_list, list) {
49 if (dmac_name && (strcmp(dmac_name, info->name) != 0))
50 continue;
51 else
52 return info;
53 }
54
55 return NULL;
56}
57EXPORT_SYMBOL(get_dma_info_by_name);
76 58
77static unsigned int get_nr_channels(void) 59static unsigned int get_nr_channels(void)
78{ 60{
@@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void)
91struct dma_channel *get_dma_channel(unsigned int chan) 73struct dma_channel *get_dma_channel(unsigned int chan)
92{ 74{
93 struct dma_info *info = get_dma_info(chan); 75 struct dma_info *info = get_dma_info(chan);
76 struct dma_channel *channel;
77 int i;
94 78
95 if (!info) 79 if (unlikely(!info))
96 return ERR_PTR(-EINVAL); 80 return ERR_PTR(-EINVAL);
97 81
98 return info->channels + chan; 82 for (i = 0; i < info->nr_channels; i++) {
83 channel = &info->channels[i];
84 if (channel->chan == chan)
85 return channel;
86 }
87
88 return NULL;
99} 89}
90EXPORT_SYMBOL(get_dma_channel);
100 91
101int get_dma_residue(unsigned int chan) 92int get_dma_residue(unsigned int chan)
102{ 93{
103 struct dma_info *info = get_dma_info(chan); 94 struct dma_info *info = get_dma_info(chan);
104 struct dma_channel *channel = &info->channels[chan]; 95 struct dma_channel *channel = get_dma_channel(chan);
105 96
106 if (info->ops->get_residue) 97 if (info->ops->get_residue)
107 return info->ops->get_residue(channel); 98 return info->ops->get_residue(channel);
108 99
109 return 0; 100 return 0;
110} 101}
102EXPORT_SYMBOL(get_dma_residue);
111 103
112int request_dma(unsigned int chan, const char *dev_id) 104static int search_cap(const char **haystack, const char *needle)
113{ 105{
114 struct dma_info *info = get_dma_info(chan); 106 const char **p;
115 struct dma_channel *channel = &info->channels[chan]; 107
108 for (p = haystack; *p; p++)
109 if (strcmp(*p, needle) == 0)
110 return 1;
111
112 return 0;
113}
114
115/**
116 * request_dma_bycap - Allocate a DMA channel based on its capabilities
117 * @dmac: List of DMA controllers to search
118 * @caps: List of capabilites
119 *
120 * Search all channels of all DMA controllers to find a channel which
121 * matches the requested capabilities. The result is the channel
122 * number if a match is found, or %-ENODEV if no match is found.
123 *
124 * Note that not all DMA controllers export capabilities, in which
125 * case they can never be allocated using this API, and so
126 * request_dma() must be used specifying the channel number.
127 */
128int request_dma_bycap(const char **dmac, const char **caps, const char *dev_id)
129{
130 unsigned int found = 0;
131 struct dma_info *info;
132 const char **p;
133 int i;
134
135 BUG_ON(!dmac || !caps);
136
137 list_for_each_entry(info, &registered_dmac_list, list)
138 if (strcmp(*dmac, info->name) == 0) {
139 found = 1;
140 break;
141 }
142
143 if (!found)
144 return -ENODEV;
145
146 for (i = 0; i < info->nr_channels; i++) {
147 struct dma_channel *channel = &info->channels[i];
148
149 if (unlikely(!channel->caps))
150 continue;
151
152 for (p = caps; *p; p++) {
153 if (!search_cap(channel->caps, *p))
154 break;
155 if (request_dma(channel->chan, dev_id) == 0)
156 return channel->chan;
157 }
158 }
159
160 return -EINVAL;
161}
162EXPORT_SYMBOL(request_dma_bycap);
163
164int dmac_search_free_channel(const char *dev_id)
165{
166 struct dma_channel *channel = { 0 };
167 struct dma_info *info = get_dma_info(0);
168 int i;
169
170 for (i = 0; i < info->nr_channels; i++) {
171 channel = &info->channels[i];
172 if (unlikely(!channel))
173 return -ENODEV;
174
175 if (atomic_read(&channel->busy) == 0)
176 break;
177 }
116 178
117 down(&channel->sem); 179 if (info->ops->request) {
180 int result = info->ops->request(channel);
181 if (result)
182 return result;
118 183
119 if (!info->ops || chan >= MAX_DMA_CHANNELS) { 184 atomic_set(&channel->busy, 1);
120 up(&channel->sem); 185 return channel->chan;
121 return -EINVAL;
122 } 186 }
123 187
124 atomic_set(&channel->busy, 1); 188 return -ENOSYS;
189}
190
191int request_dma(unsigned int chan, const char *dev_id)
192{
193 struct dma_channel *channel = { 0 };
194 struct dma_info *info = get_dma_info(chan);
195 int result;
196
197 channel = get_dma_channel(chan);
198 if (atomic_xchg(&channel->busy, 1))
199 return -EBUSY;
125 200
126 strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id)); 201 strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
127 202
128 up(&channel->sem); 203 if (info->ops->request) {
204 result = info->ops->request(channel);
205 if (result)
206 atomic_set(&channel->busy, 0);
129 207
130 if (info->ops->request) 208 return result;
131 return info->ops->request(channel); 209 }
132 210
133 return 0; 211 return 0;
134} 212}
213EXPORT_SYMBOL(request_dma);
135 214
136void free_dma(unsigned int chan) 215void free_dma(unsigned int chan)
137{ 216{
138 struct dma_info *info = get_dma_info(chan); 217 struct dma_info *info = get_dma_info(chan);
139 struct dma_channel *channel = &info->channels[chan]; 218 struct dma_channel *channel = get_dma_channel(chan);
140 219
141 if (info->ops->free) 220 if (info->ops->free)
142 info->ops->free(channel); 221 info->ops->free(channel);
143 222
144 atomic_set(&channel->busy, 0); 223 atomic_set(&channel->busy, 0);
145} 224}
225EXPORT_SYMBOL(free_dma);
146 226
147void dma_wait_for_completion(unsigned int chan) 227void dma_wait_for_completion(unsigned int chan)
148{ 228{
149 struct dma_info *info = get_dma_info(chan); 229 struct dma_info *info = get_dma_info(chan);
150 struct dma_channel *channel = &info->channels[chan]; 230 struct dma_channel *channel = get_dma_channel(chan);
151 231
152 if (channel->flags & DMA_TEI_CAPABLE) { 232 if (channel->flags & DMA_TEI_CAPABLE) {
153 wait_event(channel->wait_queue, 233 wait_event(channel->wait_queue,
@@ -158,21 +238,52 @@ void dma_wait_for_completion(unsigned int chan)
158 while (info->ops->get_residue(channel)) 238 while (info->ops->get_residue(channel))
159 cpu_relax(); 239 cpu_relax();
160} 240}
241EXPORT_SYMBOL(dma_wait_for_completion);
242
243int register_chan_caps(const char *dmac, struct dma_chan_caps *caps)
244{
245 struct dma_info *info;
246 unsigned int found = 0;
247 int i;
248
249 list_for_each_entry(info, &registered_dmac_list, list)
250 if (strcmp(dmac, info->name) == 0) {
251 found = 1;
252 break;
253 }
254
255 if (unlikely(!found))
256 return -ENODEV;
257
258 for (i = 0; i < info->nr_channels; i++, caps++) {
259 struct dma_channel *channel;
260
261 if ((info->first_channel_nr + i) != caps->ch_num)
262 return -EINVAL;
263
264 channel = &info->channels[i];
265 channel->caps = caps->caplist;
266 }
267
268 return 0;
269}
270EXPORT_SYMBOL(register_chan_caps);
161 271
162void dma_configure_channel(unsigned int chan, unsigned long flags) 272void dma_configure_channel(unsigned int chan, unsigned long flags)
163{ 273{
164 struct dma_info *info = get_dma_info(chan); 274 struct dma_info *info = get_dma_info(chan);
165 struct dma_channel *channel = &info->channels[chan]; 275 struct dma_channel *channel = get_dma_channel(chan);
166 276
167 if (info->ops->configure) 277 if (info->ops->configure)
168 info->ops->configure(channel, flags); 278 info->ops->configure(channel, flags);
169} 279}
280EXPORT_SYMBOL(dma_configure_channel);
170 281
171int dma_xfer(unsigned int chan, unsigned long from, 282int dma_xfer(unsigned int chan, unsigned long from,
172 unsigned long to, size_t size, unsigned int mode) 283 unsigned long to, size_t size, unsigned int mode)
173{ 284{
174 struct dma_info *info = get_dma_info(chan); 285 struct dma_info *info = get_dma_info(chan);
175 struct dma_channel *channel = &info->channels[chan]; 286 struct dma_channel *channel = get_dma_channel(chan);
176 287
177 channel->sar = from; 288 channel->sar = from;
178 channel->dar = to; 289 channel->dar = to;
@@ -181,8 +292,20 @@ int dma_xfer(unsigned int chan, unsigned long from,
181 292
182 return info->ops->xfer(channel); 293 return info->ops->xfer(channel);
183} 294}
295EXPORT_SYMBOL(dma_xfer);
296
297int dma_extend(unsigned int chan, unsigned long op, void *param)
298{
299 struct dma_info *info = get_dma_info(chan);
300 struct dma_channel *channel = get_dma_channel(chan);
301
302 if (info->ops->extend)
303 return info->ops->extend(channel, op, param);
304
305 return -ENOSYS;
306}
307EXPORT_SYMBOL(dma_extend);
184 308
185#ifdef CONFIG_PROC_FS
186static int dma_read_proc(char *buf, char **start, off_t off, 309static int dma_read_proc(char *buf, char **start, off_t off,
187 int len, int *eof, void *data) 310 int len, int *eof, void *data)
188{ 311{
@@ -214,8 +337,6 @@ static int dma_read_proc(char *buf, char **start, off_t off,
214 337
215 return p - buf; 338 return p - buf;
216} 339}
217#endif
218
219 340
220int register_dmac(struct dma_info *info) 341int register_dmac(struct dma_info *info)
221{ 342{
@@ -224,8 +345,7 @@ int register_dmac(struct dma_info *info)
224 INIT_LIST_HEAD(&info->list); 345 INIT_LIST_HEAD(&info->list);
225 346
226 printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n", 347 printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
227 info->name, info->nr_channels, 348 info->name, info->nr_channels, info->nr_channels > 1 ? "s" : "");
228 info->nr_channels > 1 ? "s" : "");
229 349
230 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); 350 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
231 351
@@ -242,28 +362,26 @@ int register_dmac(struct dma_info *info)
242 362
243 size = sizeof(struct dma_channel) * info->nr_channels; 363 size = sizeof(struct dma_channel) * info->nr_channels;
244 364
245 info->channels = kmalloc(size, GFP_KERNEL); 365 info->channels = kzalloc(size, GFP_KERNEL);
246 if (!info->channels) 366 if (!info->channels)
247 return -ENOMEM; 367 return -ENOMEM;
248
249 memset(info->channels, 0, size);
250 } 368 }
251 369
252 total_channels = get_nr_channels(); 370 total_channels = get_nr_channels();
253 for (i = 0; i < info->nr_channels; i++) { 371 for (i = 0; i < info->nr_channels; i++) {
254 struct dma_channel *chan = info->channels + i; 372 struct dma_channel *chan = &info->channels[i];
373
374 atomic_set(&chan->busy, 0);
255 375
256 chan->chan = i; 376 chan->chan = info->first_channel_nr + i;
257 chan->vchan = i + total_channels; 377 chan->vchan = info->first_channel_nr + i + total_channels;
258 378
259 memcpy(chan->dev_id, "Unused", 7); 379 memcpy(chan->dev_id, "Unused", 7);
260 380
261 if (info->flags & DMAC_CHANNELS_TEI_CAPABLE) 381 if (info->flags & DMAC_CHANNELS_TEI_CAPABLE)
262 chan->flags |= DMA_TEI_CAPABLE; 382 chan->flags |= DMA_TEI_CAPABLE;
263 383
264 init_MUTEX(&chan->sem);
265 init_waitqueue_head(&chan->wait_queue); 384 init_waitqueue_head(&chan->wait_queue);
266
267 dma_create_sysfs_files(chan, info); 385 dma_create_sysfs_files(chan, info);
268 } 386 }
269 387
@@ -271,6 +389,7 @@ int register_dmac(struct dma_info *info)
271 389
272 return 0; 390 return 0;
273} 391}
392EXPORT_SYMBOL(register_dmac);
274 393
275void unregister_dmac(struct dma_info *info) 394void unregister_dmac(struct dma_info *info)
276{ 395{
@@ -285,31 +404,16 @@ void unregister_dmac(struct dma_info *info)
285 list_del(&info->list); 404 list_del(&info->list);
286 platform_device_unregister(info->pdev); 405 platform_device_unregister(info->pdev);
287} 406}
407EXPORT_SYMBOL(unregister_dmac);
288 408
289static int __init dma_api_init(void) 409static int __init dma_api_init(void)
290{ 410{
291 printk("DMA: Registering DMA API.\n"); 411 printk(KERN_NOTICE "DMA: Registering DMA API.\n");
292
293#ifdef CONFIG_PROC_FS
294 create_proc_read_entry("dma", 0, 0, dma_read_proc, 0); 412 create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
295#endif
296
297 return 0; 413 return 0;
298} 414}
299
300subsys_initcall(dma_api_init); 415subsys_initcall(dma_api_init);
301 416
302MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); 417MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
303MODULE_DESCRIPTION("DMA API for SuperH"); 418MODULE_DESCRIPTION("DMA API for SuperH");
304MODULE_LICENSE("GPL"); 419MODULE_LICENSE("GPL");
305
306EXPORT_SYMBOL(request_dma);
307EXPORT_SYMBOL(free_dma);
308EXPORT_SYMBOL(register_dmac);
309EXPORT_SYMBOL(get_dma_residue);
310EXPORT_SYMBOL(get_dma_info);
311EXPORT_SYMBOL(get_dma_channel);
312EXPORT_SYMBOL(dma_xfer);
313EXPORT_SYMBOL(dma_wait_for_completion);
314EXPORT_SYMBOL(dma_configure_channel);
315
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index 660786013350..f63721ed86c2 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -94,20 +94,13 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
94 if (unlikely(!chan->flags & DMA_TEI_CAPABLE)) 94 if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
95 return 0; 95 return 0;
96 96
97 chan->name = kzalloc(32, GFP_KERNEL);
98 if (unlikely(chan->name == NULL))
99 return -ENOMEM;
100 snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
101 chan->chan);
102
103 return request_irq(get_dmte_irq(chan->chan), dma_tei, 97 return request_irq(get_dmte_irq(chan->chan), dma_tei,
104 IRQF_DISABLED, chan->name, chan); 98 IRQF_DISABLED, chan->dev_id, chan);
105} 99}
106 100
107static void sh_dmac_free_dma(struct dma_channel *chan) 101static void sh_dmac_free_dma(struct dma_channel *chan)
108{ 102{
109 free_irq(get_dmte_irq(chan->chan), chan); 103 free_irq(get_dmte_irq(chan->chan), chan);
110 kfree(chan->name);
111} 104}
112 105
113static void 106static void
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 29b8ef9873d1..eebcd4768bbf 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * sysfs interface for SH DMA API 4 * sysfs interface for SH DMA API
5 * 5 *
6 * Copyright (C) 2004, 2005 Paul Mundt 6 * Copyright (C) 2004 - 2006 Paul Mundt
7 * 7 *
8 * This file is subject to the terms and conditions of the GNU General Public 8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive 9 * License. See the file "COPYING" in the main directory of this archive
@@ -21,7 +21,6 @@
21static struct sysdev_class dma_sysclass = { 21static struct sysdev_class dma_sysclass = {
22 set_kset_name("dma"), 22 set_kset_name("dma"),
23}; 23};
24
25EXPORT_SYMBOL(dma_sysclass); 24EXPORT_SYMBOL(dma_sysclass);
26 25
27static ssize_t dma_show_devices(struct sys_device *dev, char *buf) 26static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
@@ -31,7 +30,10 @@ static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
31 30
32 for (i = 0; i < MAX_DMA_CHANNELS; i++) { 31 for (i = 0; i < MAX_DMA_CHANNELS; i++) {
33 struct dma_info *info = get_dma_info(i); 32 struct dma_info *info = get_dma_info(i);
34 struct dma_channel *channel = &info->channels[i]; 33 struct dma_channel *channel = get_dma_channel(i);
34
35 if (unlikely(!info) || !channel)
36 continue;
35 37
36 len += sprintf(buf + len, "%2d: %14s %s\n", 38 len += sprintf(buf + len, "%2d: %14s %s\n",
37 channel->chan, info->name, 39 channel->chan, info->name,
@@ -125,11 +127,16 @@ int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
125 if (ret) 127 if (ret)
126 return ret; 128 return ret;
127 129
128 sysdev_create_file(dev, &attr_dev_id); 130 ret |= sysdev_create_file(dev, &attr_dev_id);
129 sysdev_create_file(dev, &attr_count); 131 ret |= sysdev_create_file(dev, &attr_count);
130 sysdev_create_file(dev, &attr_mode); 132 ret |= sysdev_create_file(dev, &attr_mode);
131 sysdev_create_file(dev, &attr_flags); 133 ret |= sysdev_create_file(dev, &attr_flags);
132 sysdev_create_file(dev, &attr_config); 134 ret |= sysdev_create_file(dev, &attr_config);
135
136 if (unlikely(ret)) {
137 dev_err(&info->pdev->dev, "Failed creating attrs\n");
138 return ret;
139 }
133 140
134 snprintf(name, sizeof(name), "dma%d", chan->chan); 141 snprintf(name, sizeof(name), "dma%d", chan->chan);
135 return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); 142 return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name);
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c
index cd56d53375e7..ac8ee2312cd8 100644
--- a/arch/sh/drivers/pci/ops-titan.c
+++ b/arch/sh/drivers/pci/ops-titan.c
@@ -15,25 +15,21 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <asm/io.h> 18#include <linux/io.h>
19#include <asm/titan.h> 19#include <asm/titan.h>
20#include "pci-sh4.h" 20#include "pci-sh4.h"
21 21
22static char titan_irq_tab[] __initdata = {
23 TITAN_IRQ_WAN,
24 TITAN_IRQ_LAN,
25 TITAN_IRQ_MPCIA,
26 TITAN_IRQ_MPCIB,
27 TITAN_IRQ_USB,
28};
29
22int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) 30int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
23{ 31{
24 int irq = -1; 32 int irq = titan_irq_tab[slot];
25
26 switch (slot) {
27 case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */
28 case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */
29 case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */
30 case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */
31 case 4: irq = TITAN_IRQ_USB; break; /* USB */
32 default:
33 printk(KERN_INFO "PCI: Bad IRQ mapping "
34 "request for slot %d\n", slot);
35 return -1;
36 }
37 33
38 printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n", 34 printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
39 slot, pin - 1 + 'A', irq); 35 slot, pin - 1 + 'A', irq);
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index d6e635296534..602b644c35ad 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -22,6 +22,20 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include "pci-sh4.h" 23#include "pci-sh4.h"
24 24
25#define INTC_BASE 0xffd00000
26#define INTC_ICR0 (INTC_BASE+0x0)
27#define INTC_ICR1 (INTC_BASE+0x1c)
28#define INTC_INTPRI (INTC_BASE+0x10)
29#define INTC_INTREQ (INTC_BASE+0x24)
30#define INTC_INTMSK0 (INTC_BASE+0x44)
31#define INTC_INTMSK1 (INTC_BASE+0x48)
32#define INTC_INTMSK2 (INTC_BASE+0x40080)
33#define INTC_INTMSKCLR0 (INTC_BASE+0x64)
34#define INTC_INTMSKCLR1 (INTC_BASE+0x68)
35#define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
36#define INTC_INT2MSKR (INTC_BASE+0x40038)
37#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
38
25/* 39/*
26 * Initialization. Try all known PCI access methods. Note that we support 40 * Initialization. Try all known PCI access methods. Note that we support
27 * using both PCI BIOS and direct access: in such cases, we use I/O ports 41 * using both PCI BIOS and direct access: in such cases, we use I/O ports
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
new file mode 100644
index 000000000000..f2b9157c314f
--- /dev/null
+++ b/arch/sh/drivers/push-switch.c
@@ -0,0 +1,138 @@
1/*
2 * Generic push-switch framework
3 *
4 * Copyright (C) 2006 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/interrupt.h>
13#include <linux/platform_device.h>
14#include <asm/push-switch.h>
15
16#define DRV_NAME "push-switch"
17#define DRV_VERSION "0.1.0"
18
19static ssize_t switch_show(struct device *dev,
20 struct device_attribute *attr,
21 char *buf)
22{
23 struct push_switch_platform_info *psw_info = dev->platform_data;
24 return sprintf(buf, "%s\n", psw_info->name);
25}
26static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL);
27
28static void switch_timer(unsigned long data)
29{
30 struct push_switch *psw = (struct push_switch *)data;
31
32 schedule_work(&psw->work);
33}
34
35static void switch_work_handler(void *data)
36{
37 struct platform_device *pdev = data;
38 struct push_switch *psw = platform_get_drvdata(pdev);
39
40 psw->state = 0;
41
42 kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
43}
44
45static int switch_drv_probe(struct platform_device *pdev)
46{
47 struct push_switch_platform_info *psw_info;
48 struct push_switch *psw;
49 int ret, irq;
50
51 psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
52 if (unlikely(!psw))
53 return -ENOMEM;
54
55 irq = platform_get_irq(pdev, 0);
56 if (unlikely(irq < 0)) {
57 ret = -ENODEV;
58 goto err;
59 }
60
61 psw_info = pdev->dev.platform_data;
62 BUG_ON(!psw_info);
63
64 ret = request_irq(irq, psw_info->irq_handler,
65 IRQF_DISABLED | psw_info->irq_flags,
66 psw_info->name ? psw_info->name : DRV_NAME, pdev);
67 if (unlikely(ret < 0))
68 goto err;
69
70 if (psw_info->name) {
71 ret = device_create_file(&pdev->dev, &dev_attr_switch);
72 if (unlikely(ret)) {
73 dev_err(&pdev->dev, "Failed creating device attrs\n");
74 ret = -EINVAL;
75 goto err_irq;
76 }
77 }
78
79 INIT_WORK(&psw->work, switch_work_handler, pdev);
80 init_timer(&psw->debounce);
81
82 psw->debounce.function = switch_timer;
83 psw->debounce.data = (unsigned long)psw;
84
85 platform_set_drvdata(pdev, psw);
86
87 return 0;
88
89err_irq:
90 free_irq(irq, pdev);
91err:
92 kfree(psw);
93 return ret;
94}
95
96static int switch_drv_remove(struct platform_device *pdev)
97{
98 struct push_switch *psw = platform_get_drvdata(pdev);
99 struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
100 int irq = platform_get_irq(pdev, 0);
101
102 if (psw_info->name)
103 device_remove_file(&pdev->dev, &dev_attr_switch);
104
105 platform_set_drvdata(pdev, NULL);
106 flush_scheduled_work();
107 del_timer_sync(&psw->debounce);
108 free_irq(irq, pdev);
109
110 kfree(psw);
111
112 return 0;
113}
114
115static struct platform_driver switch_driver = {
116 .probe = switch_drv_probe,
117 .remove = switch_drv_remove,
118 .driver = {
119 .name = DRV_NAME,
120 },
121};
122
123static int __init switch_init(void)
124{
125 printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
126 return platform_driver_register(&switch_driver);
127}
128
129static void __exit switch_exit(void)
130{
131 platform_driver_unregister(&switch_driver);
132}
133module_init(switch_init);
134module_exit(switch_exit);
135
136MODULE_VERSION(DRV_VERSION);
137MODULE_AUTHOR("Paul Mundt");
138MODULE_LICENSE("GPLv2");
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 5da88a43d350..99c7e5249f7a 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -4,7 +4,7 @@
4 4
5extra-y := head.o init_task.o vmlinux.lds 5extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := process.o signal.o entry.o traps.o irq.o \ 7obj-y := process.o signal.o traps.o irq.o \
8 ptrace.o setup.o time.o sys_sh.o semaphore.o \ 8 ptrace.o setup.o time.o sys_sh.o semaphore.o \
9 io.o io_generic.o sh_ksyms.o syscalls.o 9 io.o io_generic.o sh_ksyms.o syscalls.o
10 10
@@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
22obj-$(CONFIG_APM) += apm.o 22obj-$(CONFIG_APM) += apm.o
23obj-$(CONFIG_PM) += pm.o 23obj-$(CONFIG_PM) += pm.o
24obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index fb5dac069382..0582e6712b79 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -2,11 +2,12 @@
2# Makefile for the Linux/SuperH CPU-specifc backends. 2# Makefile for the Linux/SuperH CPU-specifc backends.
3# 3#
4 4
5obj-y += irq/ init.o clock.o 5obj-$(CONFIG_CPU_SH2) = sh2/
6 6obj-$(CONFIG_CPU_SH2A) = sh2a/
7obj-$(CONFIG_CPU_SH2) += sh2/ 7obj-$(CONFIG_CPU_SH3) = sh3/
8obj-$(CONFIG_CPU_SH3) += sh3/ 8obj-$(CONFIG_CPU_SH4) = sh4/
9obj-$(CONFIG_CPU_SH4) += sh4/
10 9
11obj-$(CONFIG_UBC_WAKEUP) += ubc.o 10obj-$(CONFIG_UBC_WAKEUP) += ubc.o
12obj-$(CONFIG_SH_ADC) += adc.o 11obj-$(CONFIG_SH_ADC) += adc.o
12
13obj-y += irq/ init.o clock.o
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 51ec64cdf348..abb586b12565 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -5,9 +5,11 @@
5 * 5 *
6 * This clock framework is derived from the OMAP version by: 6 * This clock framework is derived from the OMAP version by:
7 * 7 *
8 * Copyright (C) 2004 Nokia Corporation 8 * Copyright (C) 2004 - 2005 Nokia Corporation
9 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 9 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
10 * 10 *
11 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
12 *
11 * This file is subject to the terms and conditions of the GNU General Public 13 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive 14 * License. See the file "COPYING" in the main directory of this archive
13 * for more details. 15 * for more details.
@@ -20,6 +22,7 @@
20#include <linux/kref.h> 22#include <linux/kref.h>
21#include <linux/seq_file.h> 23#include <linux/seq_file.h>
22#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/platform_device.h>
23#include <asm/clock.h> 26#include <asm/clock.h>
24#include <asm/timer.h> 27#include <asm/timer.h>
25 28
@@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk)
195 propagate_rate(clk); 198 propagate_rate(clk);
196} 199}
197 200
198struct clk *clk_get(const char *id) 201/*
202 * Returns a clock. Note that we first try to use device id on the bus
203 * and clock name. If this fails, we try to use clock name only.
204 */
205struct clk *clk_get(struct device *dev, const char *id)
199{ 206{
200 struct clk *p, *clk = ERR_PTR(-ENOENT); 207 struct clk *p, *clk = ERR_PTR(-ENOENT);
208 int idno;
209
210 if (dev == NULL || dev->bus != &platform_bus_type)
211 idno = -1;
212 else
213 idno = to_platform_device(dev)->id;
201 214
202 mutex_lock(&clock_list_sem); 215 mutex_lock(&clock_list_sem);
203 list_for_each_entry(p, &clock_list, node) { 216 list_for_each_entry(p, &clock_list, node) {
217 if (p->id == idno &&
218 strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
219 clk = p;
220 goto found;
221 }
222 }
223
224 list_for_each_entry(p, &clock_list, node) {
204 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 225 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
205 clk = p; 226 clk = p;
206 break; 227 break;
207 } 228 }
208 } 229 }
230
231found:
209 mutex_unlock(&clock_list_sem); 232 mutex_unlock(&clock_list_sem);
210 233
211 return clk; 234 return clk;
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index bfb90eb0b7a6..48121766e8d2 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -68,12 +68,14 @@ static void __init cache_init(void)
68 68
69 waysize = cpu_data->dcache.sets; 69 waysize = cpu_data->dcache.sets;
70 70
71#ifdef CCR_CACHE_ORA
71 /* 72 /*
72 * If the OC is already in RAM mode, we only have 73 * If the OC is already in RAM mode, we only have
73 * half of the entries to flush.. 74 * half of the entries to flush..
74 */ 75 */
75 if (ccr & CCR_CACHE_ORA) 76 if (ccr & CCR_CACHE_ORA)
76 waysize >>= 1; 77 waysize >>= 1;
78#endif
77 79
78 waysize <<= cpu_data->dcache.entry_shift; 80 waysize <<= cpu_data->dcache.entry_shift;
79 81
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index 1c034c283f59..0049d217561a 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -1,8 +1,9 @@
1# 1#
2# Makefile for the Linux/SuperH CPU-specifc IRQ handlers. 2# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
3# 3#
4obj-y += ipr.o imask.o 4obj-y += imask.o
5 5
6obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
6obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o 7obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
7obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o 8obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
8obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o 9obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c
index a33ae3e0a5a5..301b505c4278 100644
--- a/arch/sh/kernel/cpu/irq/imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip)
53{ 53{
54 unsigned long __dummy; 54 unsigned long __dummy;
55 55
56 asm volatile("ldc %2, r6_bank\n\t" 56 asm volatile(
57#ifdef CONFIG_CPU_HAS_SR_RB
58 "ldc %2, r6_bank\n\t"
59#endif
57 "stc sr, %0\n\t" 60 "stc sr, %0\n\t"
58 "and #0xf0, %0\n\t" 61 "and #0xf0, %0\n\t"
59 "shlr2 %0\n\t" 62 "shlr2 %0\n\t"
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index 74ca576a7ce5..74defe76a058 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -11,22 +11,29 @@
11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. 11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
12 */ 12 */
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/irq.h> 14#include <linux/interrupt.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <asm/system.h> 16
17#if defined(CONFIG_CPU_SUBTYPE_SH7760)
18#define INTC2_BASE 0xfe080000
19#define INTC2_INTMSK (INTC2_BASE + 0x40)
20#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
21#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
22#define INTC2_BASE 0xffd40000
23#define INTC2_INTMSK (INTC2_BASE + 0x38)
24#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
25#endif
17 26
18static void disable_intc2_irq(unsigned int irq) 27static void disable_intc2_irq(unsigned int irq)
19{ 28{
20 struct intc2_data *p = get_irq_chip_data(irq); 29 struct intc2_data *p = get_irq_chip_data(irq);
21 ctrl_outl(1 << p->msk_shift, 30 ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
22 INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
23} 31}
24 32
25static void enable_intc2_irq(unsigned int irq) 33static void enable_intc2_irq(unsigned int irq)
26{ 34{
27 struct intc2_data *p = get_irq_chip_data(irq); 35 struct intc2_data *p = get_irq_chip_data(irq);
28 ctrl_outl(1 << p->msk_shift, 36 ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
29 INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
30} 37}
31 38
32static struct irq_chip intc2_irq_chip = { 39static struct irq_chip intc2_irq_chip = {
@@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
61 /* Set the priority level */ 68 /* Set the priority level */
62 local_irq_save(flags); 69 local_irq_save(flags);
63 70
64 ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + 71 ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
65 p->ipr_offset);
66 ipr &= ~(0xf << p->ipr_shift); 72 ipr &= ~(0xf << p->ipr_shift);
67 ipr |= p->priority << p->ipr_shift; 73 ipr |= p->priority << p->ipr_shift;
68 ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + 74 ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
69 p->ipr_offset);
70 75
71 local_irq_restore(flags); 76 local_irq_restore(flags);
72 77
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index a0089563cbfc..35eb5751a3aa 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -19,25 +19,21 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <asm/system.h> 22#include <linux/io.h>
23#include <asm/io.h> 23#include <linux/interrupt.h>
24#include <asm/machvec.h>
25
26 24
27static void disable_ipr_irq(unsigned int irq) 25static void disable_ipr_irq(unsigned int irq)
28{ 26{
29 struct ipr_data *p = get_irq_chip_data(irq); 27 struct ipr_data *p = get_irq_chip_data(irq);
30 int shift = p->shift*4;
31 /* Set the priority in IPR to 0 */ 28 /* Set the priority in IPR to 0 */
32 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); 29 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
33} 30}
34 31
35static void enable_ipr_irq(unsigned int irq) 32static void enable_ipr_irq(unsigned int irq)
36{ 33{
37 struct ipr_data *p = get_irq_chip_data(irq); 34 struct ipr_data *p = get_irq_chip_data(irq);
38 int shift = p->shift*4;
39 /* Set priority in IPR back to original value */ 35 /* Set priority in IPR back to original value */
40 ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); 36 ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
41} 37}
42 38
43static struct irq_chip ipr_irq_chip = { 39static struct irq_chip ipr_irq_chip = {
@@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
53 49
54 for (i = 0; i < nr_irqs; i++) { 50 for (i = 0; i < nr_irqs; i++) {
55 unsigned int irq = table[i].irq; 51 unsigned int irq = table[i].irq;
52 table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
53 /* could the IPR index be mapped, if not we ignore this */
54 if (table[i].addr == 0)
55 continue;
56 disable_irq_nosync(irq); 56 disable_irq_nosync(irq);
57 set_irq_chip_and_handler_name(irq, &ipr_irq_chip, 57 set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
58 handle_level_irq, "level"); 58 handle_level_irq, "level");
@@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
62} 62}
63EXPORT_SYMBOL(make_ipr_irq); 63EXPORT_SYMBOL(make_ipr_irq);
64 64
65static struct ipr_data sys_ipr_map[] = {
66#ifndef CONFIG_CPU_SUBTYPE_SH7780
67 { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
68 { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY },
69#ifdef RTC_IRQ
70 { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY },
71#endif
72#ifdef SCI_ERI_IRQ
73 { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
74 { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
75 { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
76#endif
77#ifdef SCIF1_ERI_IRQ
78 { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
79 { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
80 { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
81 { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
82#endif
83#if defined(CONFIG_CPU_SUBTYPE_SH7300)
84 { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
85 { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
86 { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
87 { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
88#endif
89#ifdef SCIF_ERI_IRQ
90 { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
91 { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
92 { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
93 { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
94#endif
95#ifdef IRDA_ERI_IRQ
96 { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
97 { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
98 { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
99 { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
100#endif
101#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
102 defined(CONFIG_CPU_SUBTYPE_SH7706) || \
103 defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
104 /*
105 * Initialize the Interrupt Controller (INTC)
106 * registers to their power on values
107 */
108
109 /*
110 * Enable external irq (INTC IRQ mode).
111 * You should set corresponding bits of PFC to "00"
112 * to enable these interrupts.
113 */
114 { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY },
115 { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY },
116 { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY },
117 { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY },
118 { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY },
119 { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY },
120#endif
121#endif
122};
123
124void __init init_IRQ(void)
125{
126 make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map));
127
128#ifdef CONFIG_CPU_HAS_PINT_IRQ
129 init_IRQ_pint();
130#endif
131
132#ifdef CONFIG_CPU_HAS_INTC2_IRQ
133 init_IRQ_intc2();
134#endif
135 /* Perform the machine specific initialisation */
136 if (sh_mv.mv_init_irq != NULL)
137 sh_mv.mv_init_irq();
138
139 irq_ctx_init(smp_processor_id());
140}
141
142#if !defined(CONFIG_CPU_HAS_PINT_IRQ) 65#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
143int ipr_irq_demux(int irq) 66int ipr_irq_demux(int irq)
144{ 67{
diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile
index 389353fba608..f0f059acfcfb 100644
--- a/arch/sh/kernel/cpu/sh2/Makefile
+++ b/arch/sh/kernel/cpu/sh2/Makefile
@@ -2,5 +2,6 @@
2# Makefile for the Linux/SuperH SH-2 backends. 2# Makefile for the Linux/SuperH SH-2 backends.
3# 3#
4 4
5obj-y := probe.o 5obj-y := ex.o probe.o entry.o
6 6
7obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
new file mode 100644
index 000000000000..d0440b269702
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -0,0 +1,81 @@
1/*
2 * arch/sh/kernel/cpu/sh2/clock-sh7619.c
3 *
4 * SH7619 support for the clock framework
5 *
6 * Copyright (C) 2006 Yoshinori Sato
7 *
8 * Based on clock-sh4.c
9 * Copyright (C) 2005 Paul Mundt
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <asm/clock.h>
18#include <asm/freq.h>
19#include <asm/io.h>
20
21const static int pll1rate[]={1,2};
22const static int pfc_divisors[]={1,2,0,4};
23
24#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
25#define PLL2 (4)
26#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
27#define PLL2 (2)
28#else
29#error "Illigal Clock Mode!"
30#endif
31
32static void master_clk_init(struct clk *clk)
33{
34 clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
35}
36
37static struct clk_ops sh7619_master_clk_ops = {
38 .init = master_clk_init,
39};
40
41static void module_clk_recalc(struct clk *clk)
42{
43 int idx = (ctrl_inw(FREQCR) & 0x0007);
44 clk->rate = clk->parent->rate / pfc_divisors[idx];
45}
46
47static struct clk_ops sh7619_module_clk_ops = {
48 .recalc = module_clk_recalc,
49};
50
51static void bus_clk_recalc(struct clk *clk)
52{
53 clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
54}
55
56static struct clk_ops sh7619_bus_clk_ops = {
57 .recalc = bus_clk_recalc,
58};
59
60static void cpu_clk_recalc(struct clk *clk)
61{
62 clk->rate = clk->parent->rate;
63}
64
65static struct clk_ops sh7619_cpu_clk_ops = {
66 .recalc = cpu_clk_recalc,
67};
68
69static struct clk_ops *sh7619_clk_ops[] = {
70 &sh7619_master_clk_ops,
71 &sh7619_module_clk_ops,
72 &sh7619_bus_clk_ops,
73 &sh7619_cpu_clk_ops,
74};
75
76void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
77{
78 if (idx < ARRAY_SIZE(sh7619_clk_ops))
79 *ops = sh7619_clk_ops[idx];
80}
81
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
new file mode 100644
index 000000000000..34d51b3745ea
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -0,0 +1,341 @@
1/*
2 * arch/sh/kernel/cpu/sh2/entry.S
3 *
4 * The SH-2 exception entry
5 *
6 * Copyright (C) 2005,2006 Yoshinori Sato
7 * Copyright (C) 2005 AXE,Inc.
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13
14#include <linux/linkage.h>
15#include <asm/asm-offsets.h>
16#include <asm/thread_info.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/unistd.h>
19#include <asm/errno.h>
20#include <asm/page.h>
21
22/* Offsets to the stack */
23OFF_R0 = 0 /* Return value. New ABI also arg4 */
24OFF_R1 = 4 /* New ABI: arg5 */
25OFF_R2 = 8 /* New ABI: arg6 */
26OFF_R3 = 12 /* New ABI: syscall_nr */
27OFF_R4 = 16 /* New ABI: arg0 */
28OFF_R5 = 20 /* New ABI: arg1 */
29OFF_R6 = 24 /* New ABI: arg2 */
30OFF_R7 = 28 /* New ABI: arg3 */
31OFF_SP = (15*4)
32OFF_PC = (16*4)
33OFF_SR = (16*4+2*4)
34OFF_TRA = (16*4+6*4)
35
36#include <asm/entry-macros.S>
37
38ENTRY(exception_handler)
39 ! already saved r0/r1
40 mov.l r2,@-sp
41 mov.l r3,@-sp
42 mov r0,r1
43 cli
44 mov.l $cpu_mode,r2
45 mov.l @r2,r0
46 mov.l @(5*4,r15),r3 ! previous SR
47 shll2 r3 ! set "S" flag
48 rotl r0 ! T <- "S" flag
49 rotl r0 ! "S" flag is LSB
50 rotcr r3 ! T -> r3:b30
51 shlr r3
52 shlr r0
53 bt/s 1f
54 mov.l r3,@(5*4,r15) ! copy cpu mode to SR
55 ! switch to kernel mode
56 mov #1,r0
57 rotr r0
58 rotr r0
59 mov.l r0,@r2 ! enter kernel mode
60 mov.l $current_thread_info,r2
61 mov.l @r2,r2
62 mov #0x20,r0
63 shll8 r0
64 add r2,r0
65 mov r15,r2 ! r2 = user stack top
66 mov r0,r15 ! switch kernel stack
67 add #-4,r15 ! dummy
68 mov.l r1,@-r15 ! TRA
69 sts.l macl, @-r15
70 sts.l mach, @-r15
71 stc.l gbr, @-r15
72 mov.l @(4*4,r2),r0
73 mov.l @(5*4,r2),r1
74 mov.l r1,@-r15 ! original SR
75 sts.l pr,@-r15
76 mov.l r0,@-r15 ! original PC
77 mov r2,r3
78 add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
79 mov.l r3,@-r15 ! original SP
80 mov.l r14,@-r15
81 mov.l r13,@-r15
82 mov.l r12,@-r15
83 mov.l r11,@-r15
84 mov.l r10,@-r15
85 mov.l r9,@-r15
86 mov.l r8,@-r15
87 mov.l r7,@-r15
88 mov.l r6,@-r15
89 mov.l r5,@-r15
90 mov.l r4,@-r15
91 mov r2,r8 ! copy user -> kernel stack
92 mov.l @r8+,r3
93 mov.l r3,@-r15
94 mov.l @r8+,r2
95 mov.l r2,@-r15
96 mov.l @r8+,r1
97 mov.l r1,@-r15
98 mov.l @r8+,r0
99 bra 2f
100 mov.l r0,@-r15
1011:
102 ! in kernel exception
103 mov #(22-4-4-1)*4+4,r0
104 mov r15,r2
105 sub r0,r15
106 mov.l @r2+,r0 ! old R3
107 mov.l r0,@-r15
108 mov.l @r2+,r0 ! old R2
109 mov.l r0,@-r15
110 mov.l @r2+,r0 ! old R1
111 mov.l r0,@-r15
112 mov.l @r2+,r0 ! old R0
113 mov.l r0,@-r15
114 mov.l @r2+,r3 ! old PC
115 mov.l @r2+,r0 ! old SR
116 add #-4,r2 ! exception frame stub (sr)
117 mov.l r1,@-r2 ! TRA
118 sts.l macl, @-r2
119 sts.l mach, @-r2
120 stc.l gbr, @-r2
121 mov.l r0,@-r2 ! save old SR
122 sts.l pr,@-r2
123 mov.l r3,@-r2 ! save old PC
124 mov r2,r0
125 add #8*4,r0
126 mov.l r0,@-r2 ! save old SP
127 mov.l r14,@-r2
128 mov.l r13,@-r2
129 mov.l r12,@-r2
130 mov.l r11,@-r2
131 mov.l r10,@-r2
132 mov.l r9,@-r2
133 mov.l r8,@-r2
134 mov.l r7,@-r2
135 mov.l r6,@-r2
136 mov.l r5,@-r2
137 mov.l r4,@-r2
138 mov.l @(OFF_R0,r15),r0
139 mov.l @(OFF_R1,r15),r1
140 mov.l @(OFF_R2,r15),r2
141 mov.l @(OFF_R3,r15),r3
1422:
143 mov #OFF_TRA,r8
144 add r15,r8
145 mov.l @r8,r9
146 mov #64,r8
147 cmp/hs r8,r9
148 bt interrupt_entry ! vec >= 64 is interrupt
149 mov #32,r8
150 cmp/hs r8,r9
151 bt trap_entry ! 64 > vec >= 32 is trap
152 mov.l 4f,r8
153 mov r9,r4
154 shll2 r9
155 add r9,r8
156 mov.l @r8,r8
157 mov #0,r9
158 cmp/eq r9,r8
159 bf 3f
160 mov.l 8f,r8 ! unhandled exception
1613:
162 mov.l 5f,r10
163 jmp @r8
164 lds r10,pr
165
166interrupt_entry:
167 mov r9,r4
168 mov.l 6f,r9
169 mov.l 7f,r8
170 jmp @r8
171 lds r9,pr
172
173 .align 2
1744: .long exception_handling_table
1755: .long ret_from_exception
1766: .long ret_from_irq
1777: .long do_IRQ
1788: .long do_exception_error
179
180trap_entry:
181 add #-0x10,r9
182 shll2 r9 ! TRA
183 mov #OFF_TRA,r8
184 add r15,r8
185 mov.l r9,@r8
186 mov r9,r8
187#ifdef CONFIG_TRACE_IRQFLAGS
188 mov.l 5f, r9
189 jsr @r9
190 nop
191#endif
192 sti
193 bra system_call
194 nop
195
196 .align 2
1971: .long syscall_exit
1982: .long break_point_trap_software
1993: .long NR_syscalls
2004: .long sys_call_table
201#ifdef CONFIG_TRACE_IRQFLAGS
2025: .long trace_hardirqs_on
203#endif
204
205#if defined(CONFIG_SH_STANDARD_BIOS)
206 /* Unwind the stack and jmp to the debug entry */
207debug_kernel_fw:
208 mov r15,r0
209 add #(22-4)*4-4,r0
210 ldc.l @r0+,gbr
211 lds.l @r0+,mach
212 lds.l @r0+,macl
213 mov r15,r0
214 mov.l @(OFF_SP,r0),r1
215 mov #OFF_SR,r2
216 mov.l @(r0,r2),r3
217 mov.l r3,@-r1
218 mov #OFF_SP,r2
219 mov.l @(r0,r2),r3
220 mov.l r3,@-r1
221 mov r15,r0
222 add #(22-4)*4-8,r0
223 mov.l 1f,r2
224 mov.l @r2,r2
225 stc sr,r3
226 mov.l r2,@r0
227 mov.l r3,@r0
228 mov.l r1,@(8,r0)
229 mov.l @r15+, r0
230 mov.l @r15+, r1
231 mov.l @r15+, r2
232 mov.l @r15+, r3
233 mov.l @r15+, r4
234 mov.l @r15+, r5
235 mov.l @r15+, r6
236 mov.l @r15+, r7
237 mov.l @r15+, r8
238 mov.l @r15+, r9
239 mov.l @r15+, r10
240 mov.l @r15+, r11
241 mov.l @r15+, r12
242 mov.l @r15+, r13
243 mov.l @r15+, r14
244 add #8,r15
245 lds.l @r15+, pr
246 rte
247 mov.l @r15+,r15
248 .align 2
2491: .long gdb_vbr_vector
250#endif /* CONFIG_SH_STANDARD_BIOS */
251
252ENTRY(address_error_handler)
253 mov r15,r4 ! regs
254 add #4,r4
255 mov #OFF_PC,r0
256 mov.l @(r0,r15),r6 ! pc
257 mov.l 1f,r0
258 jmp @r0
259 mov #0,r5 ! writeaccess is unknown
260 .align 2
261
2621: .long do_address_error
263
264restore_all:
265 cli
266#ifdef CONFIG_TRACE_IRQFLAGS
267 mov.l 3f, r0
268 jsr @r0
269 nop
270#endif
271 mov r15,r0
272 mov.l $cpu_mode,r2
273 mov #OFF_SR,r3
274 mov.l @(r0,r3),r1
275 mov.l r1,@r2
276 shll2 r1 ! clear MD bit
277 shlr2 r1
278 mov.l @(OFF_SP,r0),r2
279 add #-8,r2
280 mov.l r2,@(OFF_SP,r0) ! point exception frame top
281 mov.l r1,@(4,r2) ! set sr
282 mov #OFF_PC,r3
283 mov.l @(r0,r3),r1
284 mov.l r1,@r2 ! set pc
285 add #4*16+4,r0
286 lds.l @r0+,pr
287 add #4,r0 ! skip sr
288 ldc.l @r0+,gbr
289 lds.l @r0+,mach
290 lds.l @r0+,macl
291 get_current_thread_info r0, r1
292 mov.l $current_thread_info,r1
293 mov.l r0,@r1
294 mov.l @r15+,r0
295 mov.l @r15+,r1
296 mov.l @r15+,r2
297 mov.l @r15+,r3
298 mov.l @r15+,r4
299 mov.l @r15+,r5
300 mov.l @r15+,r6
301 mov.l @r15+,r7
302 mov.l @r15+,r8
303 mov.l @r15+,r9
304 mov.l @r15+,r10
305 mov.l @r15+,r11
306 mov.l @r15+,r12
307 mov.l @r15+,r13
308 mov.l @r15+,r14
309 mov.l @r15,r15
310 rte
311 nop
3122:
313 mov.l 1f,r8
314 mov.l 2f,r9
315 jmp @r9
316 lds r8,pr
317
318 .align 2
319$current_thread_info:
320 .long __current_thread_info
321$cpu_mode:
322 .long __cpu_mode
323#ifdef CONFIG_TRACE_IRQFLAGS
3243: .long trace_hardirqs_off
325#endif
326
327! common exception handler
328#include "../../entry-common.S"
329
330 .data
331! cpu operation mode
332! bit30 = MD (compatible SH3/4)
333__cpu_mode:
334 .long 0x40000000
335
336 .section .bss
337__current_thread_info:
338 .long 0
339
340ENTRY(exception_handling_table)
341 .space 4*32
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S
new file mode 100644
index 000000000000..6d285af7846c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/ex.S
@@ -0,0 +1,46 @@
1/*
2 * arch/sh/kernel/cpu/sh2/ex.S
3 *
4 * The SH-2 exception vector table
5 *
6 * Copyright (C) 2005 Yoshinori Sato
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/linkage.h>
14
15!
16! convert Exception Vector to Exception Number
17!
18exception_entry:
19no = 0
20 .rept 256
21 mov.l r0,@-sp
22 mov #no,r0
23 bra exception_trampoline
24 and #0xff,r0
25no = no + 1
26 .endr
27exception_trampoline:
28 mov.l r1,@-sp
29 mov.l $exception_handler,r1
30 jmp @r1
31
32 .align 2
33$exception_entry:
34 .long exception_entry
35$exception_handler:
36 .long exception_handler
37!
38! Exception Vector Base
39!
40 .align 2
41ENTRY(vbr_base)
42vector = 0
43 .rept 256
44 .long exception_entry + vector * 8
45vector = vector + 1
46 .endr
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index f17a2a0d588e..ba527d9b5024 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -17,17 +17,23 @@
17 17
18int __init detect_cpu_and_cache_system(void) 18int __init detect_cpu_and_cache_system(void)
19{ 19{
20 /* 20#if defined(CONFIG_CPU_SUBTYPE_SH7604)
21 * For now, assume SH7604 .. fix this later.
22 */
23 cpu_data->type = CPU_SH7604; 21 cpu_data->type = CPU_SH7604;
24 cpu_data->dcache.ways = 4; 22 cpu_data->dcache.ways = 4;
25 cpu_data->dcache.way_shift = 6; 23 cpu_data->dcache.way_incr = (1<<10);
26 cpu_data->dcache.sets = 64; 24 cpu_data->dcache.sets = 64;
27 cpu_data->dcache.entry_shift = 4; 25 cpu_data->dcache.entry_shift = 4;
28 cpu_data->dcache.linesz = L1_CACHE_BYTES; 26 cpu_data->dcache.linesz = L1_CACHE_BYTES;
29 cpu_data->dcache.flags = 0; 27 cpu_data->dcache.flags = 0;
30 28#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
29 cpu_data->type = CPU_SH7619;
30 cpu_data->dcache.ways = 4;
31 cpu_data->dcache.way_incr = (1<<12);
32 cpu_data->dcache.sets = 256;
33 cpu_data->dcache.entry_shift = 4;
34 cpu_data->dcache.linesz = L1_CACHE_BYTES;
35 cpu_data->dcache.flags = 0;
36#endif
31 /* 37 /*
32 * SH-2 doesn't have separate caches 38 * SH-2 doesn't have separate caches
33 */ 39 */
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
new file mode 100644
index 000000000000..82c2d905152f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -0,0 +1,53 @@
1/*
2 * SH7619 Setup
3 *
4 * Copyright (C) 2006 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <asm/sci.h>
14
15static struct plat_sci_port sci_platform_data[] = {
16 {
17 .mapbase = 0xf8400000,
18 .flags = UPF_BOOT_AUTOCONF,
19 .type = PORT_SCIF,
20 .irqs = { 88, 89, 91, 90},
21 }, {
22 .mapbase = 0xf8410000,
23 .flags = UPF_BOOT_AUTOCONF,
24 .type = PORT_SCIF,
25 .irqs = { 92, 93, 95, 94},
26 }, {
27 .mapbase = 0xf8420000,
28 .flags = UPF_BOOT_AUTOCONF,
29 .type = PORT_SCIF,
30 .irqs = { 96, 97, 99, 98},
31 }, {
32 .flags = 0,
33 }
34};
35
36static struct platform_device sci_device = {
37 .name = "sh-sci",
38 .id = -1,
39 .dev = {
40 .platform_data = sci_platform_data,
41 },
42};
43
44static struct platform_device *sh7619_devices[] __initdata = {
45 &sci_device,
46};
47
48static int __init sh7619_devices_setup(void)
49{
50 return platform_add_devices(sh7619_devices,
51 ARRAY_SIZE(sh7619_devices));
52}
53__initcall(sh7619_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
new file mode 100644
index 000000000000..350972ae9410
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the Linux/SuperH SH-2A backends.
3#
4
5obj-y := common.o probe.o
6
7common-y += $(addprefix ../sh2/, ex.o)
8common-y += $(addprefix ../sh2/, entry.o)
9
10obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
new file mode 100644
index 000000000000..a9ad309c6a33
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -0,0 +1,85 @@
1/*
2 * arch/sh/kernel/cpu/sh2a/clock-sh7206.c
3 *
4 * SH7206 support for the clock framework
5 *
6 * Copyright (C) 2006 Yoshinori Sato
7 *
8 * Based on clock-sh4.c
9 * Copyright (C) 2005 Paul Mundt
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <asm/clock.h>
18#include <asm/freq.h>
19#include <asm/io.h>
20
21const static int pll1rate[]={1,2,3,4,6,8};
22const static int pfc_divisors[]={1,2,3,4,6,8,12};
23#define ifc_divisors pfc_divisors
24
25#if (CONFIG_SH_CLK_MD == 2)
26#define PLL2 (4)
27#elif (CONFIG_SH_CLK_MD == 6)
28#define PLL2 (2)
29#elif (CONFIG_SH_CLK_MD == 7)
30#define PLL2 (1)
31#else
32#error "Illigal Clock Mode!"
33#endif
34
35static void master_clk_init(struct clk *clk)
36{
37 clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
38}
39
40static struct clk_ops sh7206_master_clk_ops = {
41 .init = master_clk_init,
42};
43
44static void module_clk_recalc(struct clk *clk)
45{
46 int idx = (ctrl_inw(FREQCR) & 0x0007);
47 clk->rate = clk->parent->rate / pfc_divisors[idx];
48}
49
50static struct clk_ops sh7206_module_clk_ops = {
51 .recalc = module_clk_recalc,
52};
53
54static void bus_clk_recalc(struct clk *clk)
55{
56 clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
57}
58
59static struct clk_ops sh7206_bus_clk_ops = {
60 .recalc = bus_clk_recalc,
61};
62
63static void cpu_clk_recalc(struct clk *clk)
64{
65 int idx = (ctrl_inw(FREQCR) & 0x0007);
66 clk->rate = clk->parent->rate / ifc_divisors[idx];
67}
68
69static struct clk_ops sh7206_cpu_clk_ops = {
70 .recalc = cpu_clk_recalc,
71};
72
73static struct clk_ops *sh7206_clk_ops[] = {
74 &sh7206_master_clk_ops,
75 &sh7206_module_clk_ops,
76 &sh7206_bus_clk_ops,
77 &sh7206_cpu_clk_ops,
78};
79
80void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
81{
82 if (idx < ARRAY_SIZE(sh7206_clk_ops))
83 *ops = sh7206_clk_ops[idx];
84}
85
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
new file mode 100644
index 000000000000..87c6c0542089
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -0,0 +1,39 @@
1/*
2 * arch/sh/kernel/cpu/sh2a/probe.c
3 *
4 * CPU Subtype Probing for SH-2A.
5 *
6 * Copyright (C) 2004, 2005 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/init.h>
14#include <asm/processor.h>
15#include <asm/cache.h>
16
17int __init detect_cpu_and_cache_system(void)
18{
19 /* Just SH7206 for now .. */
20 cpu_data->type = CPU_SH7206;
21
22 cpu_data->dcache.ways = 4;
23 cpu_data->dcache.way_incr = (1 << 11);
24 cpu_data->dcache.sets = 128;
25 cpu_data->dcache.entry_shift = 4;
26 cpu_data->dcache.linesz = L1_CACHE_BYTES;
27 cpu_data->dcache.flags = 0;
28
29 /*
30 * The icache is the same as the dcache as far as this setup is
31 * concerned. The only real difference in hardware is that the icache
32 * lacks the U bit that the dcache has, none of this has any bearing
33 * on the cache info.
34 */
35 cpu_data->icache = cpu_data->dcache;
36
37 return 0;
38}
39
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
new file mode 100644
index 000000000000..cdfeef49e62e
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -0,0 +1,58 @@
1/*
2 * SH7206 Setup
3 *
4 * Copyright (C) 2006 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <asm/sci.h>
14
15static struct plat_sci_port sci_platform_data[] = {
16 {
17 .mapbase = 0xfffe8000,
18 .flags = UPF_BOOT_AUTOCONF,
19 .type = PORT_SCIF,
20 .irqs = { 240, 241, 242, 243},
21 }, {
22 .mapbase = 0xfffe8800,
23 .flags = UPF_BOOT_AUTOCONF,
24 .type = PORT_SCIF,
25 .irqs = { 244, 245, 246, 247},
26 }, {
27 .mapbase = 0xfffe9000,
28 .flags = UPF_BOOT_AUTOCONF,
29 .type = PORT_SCIF,
30 .irqs = { 248, 249, 250, 251},
31 }, {
32 .mapbase = 0xfffe9800,
33 .flags = UPF_BOOT_AUTOCONF,
34 .type = PORT_SCIF,
35 .irqs = { 252, 253, 254, 255},
36 }, {
37 .flags = 0,
38 }
39};
40
41static struct platform_device sci_device = {
42 .name = "sh-sci",
43 .id = -1,
44 .dev = {
45 .platform_data = sci_platform_data,
46 },
47};
48
49static struct platform_device *sh7206_devices[] __initdata = {
50 &sci_device,
51};
52
53static int __init sh7206_devices_setup(void)
54{
55 return platform_add_devices(sh7206_devices,
56 ARRAY_SIZE(sh7206_devices));
57}
58__initcall(sh7206_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index 58d3815695ff..83905e4e4387 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the Linux/SuperH SH-3 backends. 2# Makefile for the Linux/SuperH SH-3 backends.
3# 3#
4 4
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o entry.o
6 6
7# CPU subtype setup 7# CPU subtype setup
8obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o 8obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
index 10461a745e5f..b791a29fdb62 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
@@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
24 24
25static void set_bus_parent(struct clk *clk) 25static void set_bus_parent(struct clk *clk)
26{ 26{
27 struct clk *bus_clk = clk_get("bus_clk"); 27 struct clk *bus_clk = clk_get(NULL, "bus_clk");
28 clk->parent = bus_clk; 28 clk->parent = bus_clk;
29 clk_put(bus_clk); 29 clk_put(bus_clk);
30} 30}
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 39aaefb2d83f..8c0dc2700c69 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/sh/entry.S 2 * arch/sh/kernel/entry.S
3 * 3 *
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
5 * Copyright (C) 2003 - 2006 Paul Mundt 5 * Copyright (C) 2003 - 2006 Paul Mundt
@@ -7,15 +7,16 @@
7 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive 8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details. 9 * for more details.
10 *
11 */ 10 */
12#include <linux/sys.h> 11#include <linux/sys.h>
13#include <linux/errno.h> 12#include <linux/errno.h>
14#include <linux/linkage.h> 13#include <linux/linkage.h>
15#include <asm/asm-offsets.h> 14#include <asm/asm-offsets.h>
16#include <asm/thread_info.h> 15#include <asm/thread_info.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/unistd.h> 16#include <asm/unistd.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/pgtable.h>
19#include <asm/page.h>
19 20
20! NOTE: 21! NOTE:
21! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address 22! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -81,6 +82,8 @@ OFF_TRA = (16*4+6*4)
81#define k_g_imask r6_bank /* r6_bank1 */ 82#define k_g_imask r6_bank /* r6_bank1 */
82#define current r7 /* r7_bank1 */ 83#define current r7 /* r7_bank1 */
83 84
85#include <asm/entry-macros.S>
86
84/* 87/*
85 * Kernel mode register usage: 88 * Kernel mode register usage:
86 * k0 scratch 89 * k0 scratch
@@ -107,26 +110,6 @@ OFF_TRA = (16*4+6*4)
107! this first version depends *much* on C implementation. 110! this first version depends *much* on C implementation.
108! 111!
109 112
110#define CLI() \
111 stc sr, r0; \
112 or #0xf0, r0; \
113 ldc r0, sr
114
115#define STI() \
116 mov.l __INV_IMASK, r11; \
117 stc sr, r10; \
118 and r11, r10; \
119 stc k_g_imask, r11; \
120 or r11, r10; \
121 ldc r10, sr
122
123#if defined(CONFIG_PREEMPT)
124# define preempt_stop() CLI()
125#else
126# define preempt_stop()
127# define resume_kernel restore_all
128#endif
129
130#if defined(CONFIG_MMU) 113#if defined(CONFIG_MMU)
131 .align 2 114 .align 2
132ENTRY(tlb_miss_load) 115ENTRY(tlb_miss_load)
@@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store)
155 138
156call_dpf: 139call_dpf:
157 mov.l 1f, r0 140 mov.l 1f, r0
158 mov r5, r8 141 mov.l @r0, r6 ! address
159 mov.l @r0, r6
160 mov r6, r9
161 mov.l 2f, r0
162 sts pr, r10
163 jsr @r0
164 mov r15, r4
165 !
166 tst r0, r0
167 bf/s 0f
168 lds r10, pr
169 rts
170 nop
1710: STI()
172 mov.l 3f, r0 142 mov.l 3f, r0
173 mov r9, r6 143
174 mov r8, r5
175 jmp @r0 144 jmp @r0
176 mov r15, r4 145 mov r15, r4 ! regs
177 146
178 .align 2 147 .align 2
1791: .long MMU_TEA 1481: .long MMU_TEA
1802: .long __do_page_fault
1813: .long do_page_fault 1493: .long do_page_fault
182 150
183 .align 2 151 .align 2
@@ -203,32 +171,6 @@ call_dae:
2032: .long do_address_error 1712: .long do_address_error
204#endif /* CONFIG_MMU */ 172#endif /* CONFIG_MMU */
205 173
206#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
207! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
208! If both are configured, handle the debug traps (breakpoints) in SW,
209! but still allow BIOS traps to FW.
210
211 .align 2
212debug_kernel:
213#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
214 /* Force BIOS call to FW (debug_trap put TRA in r8) */
215 mov r8,r0
216 shlr2 r0
217 cmp/eq #0x3f,r0
218 bt debug_kernel_fw
219#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
220
221debug_enter:
222#if defined(CONFIG_SH_KGDB)
223 /* Jump to kgdb, pass stacked regs as arg */
224debug_kernel_sw:
225 mov.l 3f, r0
226 jmp @r0
227 mov r15, r4
228 .align 2
2293: .long kgdb_handle_exception
230#endif /* CONFIG_SH_KGDB */
231
232#if defined(CONFIG_SH_STANDARD_BIOS) 174#if defined(CONFIG_SH_STANDARD_BIOS)
233 /* Unwind the stack and jmp to the debug entry */ 175 /* Unwind the stack and jmp to the debug entry */
234debug_kernel_fw: 176debug_kernel_fw:
@@ -269,276 +211,6 @@ debug_kernel_fw:
2692: .long gdb_vbr_vector 2112: .long gdb_vbr_vector
270#endif /* CONFIG_SH_STANDARD_BIOS */ 212#endif /* CONFIG_SH_STANDARD_BIOS */
271 213
272#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
273
274
275 .align 2
276debug_trap:
277#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
278 mov #OFF_SR, r0
279 mov.l @(r0,r15), r0 ! get status register
280 shll r0
281 shll r0 ! kernel space?
282 bt/s debug_kernel
283#endif
284 mov.l @r15, r0 ! Restore R0 value
285 mov.l 1f, r8
286 jmp @r8
287 nop
288
289 .align 2
290ENTRY(exception_error)
291 !
292 STI()
293 mov.l 2f, r0
294 jmp @r0
295 nop
296
297!
298 .align 2
2991: .long break_point_trap_software
3002: .long do_exception_error
301
302 .align 2
303ret_from_exception:
304 preempt_stop()
305ENTRY(ret_from_irq)
306 !
307 mov #OFF_SR, r0
308 mov.l @(r0,r15), r0 ! get status register
309 shll r0
310 shll r0 ! kernel space?
311 bt/s resume_kernel ! Yes, it's from kernel, go back soon
312 GET_THREAD_INFO(r8)
313
314#ifdef CONFIG_PREEMPT
315 bra resume_userspace
316 nop
317ENTRY(resume_kernel)
318 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
319 tst r0, r0
320 bf noresched
321need_resched:
322 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
323 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
324 bt noresched
325
326 mov #OFF_SR, r0
327 mov.l @(r0,r15), r0 ! get status register
328 and #0xf0, r0 ! interrupts off (exception path)?
329 cmp/eq #0xf0, r0
330 bt noresched
331
332 mov.l 1f, r0
333 mov.l r0, @(TI_PRE_COUNT,r8)
334
335 STI()
336 mov.l 2f, r0
337 jsr @r0
338 nop
339 mov #0, r0
340 mov.l r0, @(TI_PRE_COUNT,r8)
341 CLI()
342
343 bra need_resched
344 nop
345noresched:
346 bra restore_all
347 nop
348
349 .align 2
3501: .long PREEMPT_ACTIVE
3512: .long schedule
352#endif
353
354ENTRY(resume_userspace)
355 ! r8: current_thread_info
356 CLI()
357 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
358 tst #_TIF_WORK_MASK, r0
359 bt/s restore_all
360 tst #_TIF_NEED_RESCHED, r0
361
362 .align 2
363work_pending:
364 ! r0: current_thread_info->flags
365 ! r8: current_thread_info
366 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
367 bf/s work_resched
368 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
369work_notifysig:
370 bt/s restore_all
371 mov r15, r4
372 mov r12, r5 ! set arg1(save_r0)
373 mov r0, r6
374 mov.l 2f, r1
375 mova restore_all, r0
376 jmp @r1
377 lds r0, pr
378work_resched:
379#ifndef CONFIG_PREEMPT
380 ! gUSA handling
381 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
382 mov r0, r1
383 shll r0
384 bf/s 1f
385 shll r0
386 bf/s 1f
387 mov #OFF_PC, r0
388 ! SP >= 0xc0000000 : gUSA mark
389 mov.l @(r0,r15), r2 ! get user space PC (program counter)
390 mov.l @(OFF_R0,r15), r3 ! end point
391 cmp/hs r3, r2 ! r2 >= r3?
392 bt 1f
393 add r3, r1 ! rewind point #2
394 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
395 !
3961:
397#endif
398 mov.l 1f, r1
399 jsr @r1 ! schedule
400 nop
401 CLI()
402 !
403 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
404 tst #_TIF_WORK_MASK, r0
405 bt restore_all
406 bra work_pending
407 tst #_TIF_NEED_RESCHED, r0
408
409 .align 2
4101: .long schedule
4112: .long do_notify_resume
412
413 .align 2
414syscall_exit_work:
415 ! r0: current_thread_info->flags
416 ! r8: current_thread_info
417 tst #_TIF_SYSCALL_TRACE, r0
418 bt/s work_pending
419 tst #_TIF_NEED_RESCHED, r0
420 STI()
421 ! XXX setup arguments...
422 mov.l 4f, r0 ! do_syscall_trace
423 jsr @r0
424 nop
425 bra resume_userspace
426 nop
427
428 .align 2
429syscall_trace_entry:
430 ! Yes it is traced.
431 ! XXX setup arguments...
432 mov.l 4f, r11 ! Call do_syscall_trace which notifies
433 jsr @r11 ! superior (will chomp R[0-7])
434 nop
435 ! Reload R0-R4 from kernel stack, where the
436 ! parent may have modified them using
437 ! ptrace(POKEUSR). (Note that R0-R2 are
438 ! used by the system call handler directly
439 ! from the kernel stack anyway, so don't need
440 ! to be reloaded here.) This allows the parent
441 ! to rewrite system calls and args on the fly.
442 mov.l @(OFF_R4,r15), r4 ! arg0
443 mov.l @(OFF_R5,r15), r5
444 mov.l @(OFF_R6,r15), r6
445 mov.l @(OFF_R7,r15), r7 ! arg3
446 mov.l @(OFF_R3,r15), r3 ! syscall_nr
447 ! Arrange for do_syscall_trace to be called
448 ! again as the system call returns.
449 mov.l 2f, r10 ! Number of syscalls
450 cmp/hs r10, r3
451 bf syscall_call
452 mov #-ENOSYS, r0
453 bra syscall_exit
454 mov.l r0, @(OFF_R0,r15) ! Return value
455
456/*
457 * Syscall interface:
458 *
459 * Syscall #: R3
460 * Arguments #0 to #3: R4--R7
461 * Arguments #4 to #6: R0, R1, R2
462 * TRA: (number of arguments + 0x10) x 4
463 *
464 * This code also handles delegating other traps to the BIOS/gdb stub
465 * according to:
466 *
467 * Trap number
468 * (TRA>>2) Purpose
469 * -------- -------
470 * 0x0-0xf old syscall ABI
471 * 0x10-0x1f new syscall ABI
472 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
473 *
474 * Note: When we're first called, the TRA value must be shifted
475 * right 2 bits in order to get the value that was used as the "trapa"
476 * argument.
477 */
478
479 .align 2
480 .globl ret_from_fork
481ret_from_fork:
482 mov.l 1f, r8
483 jsr @r8
484 mov r0, r4
485 bra syscall_exit
486 nop
487 .align 2
4881: .long schedule_tail
489 !
490ENTRY(system_call)
491 mov.l 1f, r9
492 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
493 !
494 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
495 mov #0x7f, r9
496 cmp/hi r9, r8
497 bt/s 0f
498 mov #OFF_TRA, r9
499 add r15, r9
500 !
501 mov.l r8, @r9 ! set TRA value to tra
502 STI()
503 ! Call the system call handler through the table.
504 ! First check for bad syscall number
505 mov r3, r9
506 mov.l 2f, r8 ! Number of syscalls
507 cmp/hs r8, r9
508 bf/s good_system_call
509 GET_THREAD_INFO(r8)
510syscall_badsys: ! Bad syscall number
511 mov #-ENOSYS, r0
512 bra resume_userspace
513 mov.l r0, @(OFF_R0,r15) ! Return value
514 !
5150:
516 bra debug_trap
517 nop
518 !
519good_system_call: ! Good syscall number
520 mov.l @(TI_FLAGS,r8), r8
521 mov #_TIF_SYSCALL_TRACE, r10
522 tst r10, r8
523 bf syscall_trace_entry
524 !
525syscall_call:
526 shll2 r9 ! x4
527 mov.l 3f, r8 ! Load the address of sys_call_table
528 add r8, r9
529 mov.l @r9, r8
530 jsr @r8 ! jump to specific syscall handler
531 nop
532 mov.l @(OFF_R0,r15), r12 ! save r0
533 mov.l r0, @(OFF_R0,r15) ! save the return value
534 !
535syscall_exit:
536 CLI()
537 !
538 GET_THREAD_INFO(r8)
539 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
540 tst #_TIF_ALLWORK_MASK, r0
541 bf syscall_exit_work
542restore_all: 214restore_all:
543 mov.l @r15+, r0 215 mov.l @r15+, r0
544 mov.l @r15+, r1 216 mov.l @r15+, r1
@@ -606,7 +278,9 @@ skip_restore:
606 ! 278 !
607 ! Calculate new SR value 279 ! Calculate new SR value
608 mov k3, k2 ! original SR value 280 mov k3, k2 ! original SR value
609 mov.l 9f, k1 281 mov #0xf0, k1
282 extu.b k1, k1
283 not k1, k1
610 and k1, k2 ! Mask orignal SR value 284 and k1, k2 ! Mask orignal SR value
611 ! 285 !
612 mov k3, k0 ! Calculate IMASK-bits 286 mov k3, k0 ! Calculate IMASK-bits
@@ -632,16 +306,12 @@ skip_restore:
632 nop 306 nop
633 307
634 .align 2 308 .align 2
6351: .long TRA
6362: .long NR_syscalls
6373: .long sys_call_table
6384: .long do_syscall_trace
6395: .long 0x00001000 ! DSP 3095: .long 0x00001000 ! DSP
6407: .long 0x30000000 3107: .long 0x30000000
6419:
642__INV_IMASK:
643 .long 0xffffff0f ! ~(IMASK)
644 311
312! common exception handler
313#include "../../entry-common.S"
314
645! Exception Vector Base 315! Exception Vector Base
646! 316!
647! Should be aligned page boundary. 317! Should be aligned page boundary.
@@ -661,9 +331,176 @@ general_exception:
6612: .long ret_from_exception 3312: .long ret_from_exception
662! 332!
663! 333!
334
335/* This code makes some assumptions to improve performance.
336 * Make sure they are stil true. */
337#if PTRS_PER_PGD != PTRS_PER_PTE
338#error PGD and PTE sizes don't match
339#endif
340
341/* gas doesn't flag impossible values for mov #immediate as an error */
342#if (_PAGE_PRESENT >> 2) > 0x7f
343#error cannot load PAGE_PRESENT as an immediate
344#endif
345#if _PAGE_DIRTY > 0x7f
346#error cannot load PAGE_DIRTY as an immediate
347#endif
348#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
349#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
350#endif
351
352#if defined(CONFIG_CPU_SH4)
353#define ldmmupteh(r) mov.l 8f, r
354#else
355#define ldmmupteh(r) mov #MMU_PTEH, r
356#endif
357
664 .balign 1024,0,1024 358 .balign 1024,0,1024
665tlb_miss: 359tlb_miss:
666 mov.l 1f, k2 360#ifdef COUNT_EXCEPTIONS
361 ! Increment the counts
362 mov.l 9f, k1
363 mov.l @k1, k2
364 add #1, k2
365 mov.l k2, @k1
366#endif
367
368 ! k0 scratch
369 ! k1 pgd and pte pointers
370 ! k2 faulting address
371 ! k3 pgd and pte index masks
372 ! k4 shift
373
374 ! Load up the pgd entry (k1)
375
376 ldmmupteh(k0) ! 9 LS (latency=2) MMU_PTEH
377
378 mov.w 4f, k3 ! 8 LS (latency=2) (PTRS_PER_PGD-1) << 2
379 mov #-(PGDIR_SHIFT-2), k4 ! 6 EX
380
381 mov.l @(MMU_TEA-MMU_PTEH,k0), k2 ! 18 LS (latency=2)
382
383 mov.l @(MMU_TTB-MMU_PTEH,k0), k1 ! 18 LS (latency=2)
384
385 mov k2, k0 ! 5 MT (latency=0)
386 shld k4, k0 ! 99 EX
387
388 and k3, k0 ! 78 EX
389
390 mov.l @(k0, k1), k1 ! 21 LS (latency=2)
391 mov #-(PAGE_SHIFT-2), k4 ! 6 EX
392
393 ! Load up the pte entry (k2)
394
395 mov k2, k0 ! 5 MT (latency=0)
396 shld k4, k0 ! 99 EX
397
398 tst k1, k1 ! 86 MT
399
400 bt 20f ! 110 BR
401
402 and k3, k0 ! 78 EX
403 mov.w 5f, k4 ! 8 LS (latency=2) _PAGE_PRESENT
404
405 mov.l @(k0, k1), k2 ! 21 LS (latency=2)
406 add k0, k1 ! 49 EX
407
408#ifdef CONFIG_CPU_HAS_PTEA
409 ! Test the entry for present and _PAGE_ACCESSED
410
411 mov #-28, k3 ! 6 EX
412 mov k2, k0 ! 5 MT (latency=0)
413
414 tst k4, k2 ! 68 MT
415 shld k3, k0 ! 99 EX
416
417 bt 20f ! 110 BR
418
419 ! Set PTEA register
420 ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
421 !
422 ! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
423
424 and #0xe, k0 ! 79 EX
425
426 mov k0, k3 ! 5 MT (latency=0)
427 mov k2, k0 ! 5 MT (latency=0)
428
429 and #1, k0 ! 79 EX
430
431 or k0, k3 ! 82 EX
432
433 ldmmupteh(k0) ! 9 LS (latency=2)
434 shll2 k4 ! 101 EX _PAGE_ACCESSED
435
436 tst k4, k2 ! 68 MT
437
438 mov.l k3, @(MMU_PTEA-MMU_PTEH,k0) ! 27 LS
439
440 mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
441
442 ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
443#else
444
445 ! Test the entry for present and _PAGE_ACCESSED
446
447 mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
448 tst k4, k2 ! 68 MT
449
450 shll2 k4 ! 101 EX _PAGE_ACCESSED
451 ldmmupteh(k0) ! 9 LS (latency=2)
452
453 bt 20f ! 110 BR
454 tst k4, k2 ! 68 MT
455
456 ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
457
458#endif
459
460 ! Set up the entry
461
462 and k2, k3 ! 78 EX
463 bt/s 10f ! 108 BR
464
465 mov.l k3, @(MMU_PTEL-MMU_PTEH,k0) ! 27 LS
466
467 ldtlb ! 128 CO
468
469 ! At least one instruction between ldtlb and rte
470 nop ! 119 NOP
471
472 rte ! 126 CO
473
474 nop ! 119 NOP
475
476
47710: or k4, k2 ! 82 EX
478
479 ldtlb ! 128 CO
480
481 ! At least one instruction between ldtlb and rte
482 mov.l k2, @k1 ! 27 LS
483
484 rte ! 126 CO
485
486 ! Note we cannot execute mov here, because it is executed after
487 ! restoring SSR, so would be executed in user space.
488 nop ! 119 NOP
489
490
491 .align 5
492 ! Once cache line if possible...
4931: .long swapper_pg_dir
4944: .short (PTRS_PER_PGD-1) << 2
4955: .short _PAGE_PRESENT
4967: .long _PAGE_FLAGS_HARDWARE_MASK
4978: .long MMU_PTEH
498#ifdef COUNT_EXCEPTIONS
4999: .long exception_count_miss
500#endif
501
502 ! Either pgd or pte not present
50320: mov.l 1f, k2
667 mov.l 4f, k3 504 mov.l 4f, k3
668 bra handle_exception 505 bra handle_exception
669 mov.l @k2, k2 506 mov.l @k2, k2
@@ -710,8 +547,9 @@ ENTRY(handle_exception)
710 bt/s 1f ! It's a kernel to kernel transition. 547 bt/s 1f ! It's a kernel to kernel transition.
711 mov r15, k0 ! save original stack to k0 548 mov r15, k0 ! save original stack to k0
712 /* User space to kernel */ 549 /* User space to kernel */
713 mov #(THREAD_SIZE >> 8), k1 550 mov #(THREAD_SIZE >> 10), k1
714 shll8 k1 ! k1 := THREAD_SIZE 551 shll8 k1 ! k1 := THREAD_SIZE
552 shll2 k1
715 add current, k1 553 add current, k1
716 mov k1, r15 ! change to kernel stack 554 mov k1, r15 ! change to kernel stack
717 ! 555 !
@@ -761,7 +599,7 @@ skip_save:
761 ! Save the user registers on the stack. 599 ! Save the user registers on the stack.
762 mov.l k2, @-r15 ! EXPEVT 600 mov.l k2, @-r15 ! EXPEVT
763 601
764 mov #-1, k4 602 mov #-1, k4
765 mov.l k4, @-r15 ! set TRA (default: -1) 603 mov.l k4, @-r15 ! set TRA (default: -1)
766 ! 604 !
767 sts.l macl, @-r15 605 sts.l macl, @-r15
@@ -813,6 +651,15 @@ skip_save:
813 bf interrupt_exception 651 bf interrupt_exception
814 shlr2 r8 652 shlr2 r8
815 shlr r8 653 shlr r8
654
655#ifdef COUNT_EXCEPTIONS
656 mov.l 5f, r9
657 add r8, r9
658 mov.l @r9, r10
659 add #1, r10
660 mov.l r10, @r9
661#endif
662
816 mov.l 4f, r9 663 mov.l 4f, r9
817 add r8, r9 664 add r8, r9
818 mov.l @r9, r9 665 mov.l @r9, r9
@@ -826,6 +673,9 @@ skip_save:
8262: .long 0x000080f0 ! FD=1, IMASK=15 6732: .long 0x000080f0 ! FD=1, IMASK=15
8273: .long 0xcfffffff ! RB=0, BL=0 6743: .long 0xcfffffff ! RB=0, BL=0
8284: .long exception_handling_table 6754: .long exception_handling_table
676#ifdef COUNT_EXCEPTIONS
6775: .long exception_count_table
678#endif
829 679
830interrupt_exception: 680interrupt_exception:
831 mov.l 1f, r9 681 mov.l 1f, r9
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 8dbf3895ece7..6e415baf04b4 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -2,7 +2,8 @@
2# Makefile for the Linux/SuperH SH-4 backends. 2# Makefile for the Linux/SuperH SH-4 backends.
3# 3#
4 4
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o common.o
6common-y += $(addprefix ../sh3/, entry.o)
6 7
7obj-$(CONFIG_SH_FPU) += fpu.o 8obj-$(CONFIG_SH_FPU) += fpu.o
8obj-$(CONFIG_SH_STORE_QUEUES) += sq.o 9obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index bfdf5fe8d948..fa2019aabd74 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk)
97 97
98static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) 98static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
99{ 99{
100 struct clk *bclk = clk_get("bus_clk"); 100 struct clk *bclk = clk_get(NULL, "bus_clk");
101 unsigned long bclk_rate = clk_get_rate(bclk); 101 unsigned long bclk_rate = clk_get_rate(bclk);
102 102
103 clk_put(bclk); 103 clk_put(bclk);
@@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = {
151 151
152static int __init sh4202_clk_init(void) 152static int __init sh4202_clk_init(void)
153{ 153{
154 struct clk *clk = clk_get("master_clk"); 154 struct clk *clk = clk_get(NULL, "master_clk");
155 int i; 155 int i;
156 156
157 for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { 157 for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c
index 93ad367342c9..9e6a216750c8 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c
@@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = {
98 98
99static int __init sh7780_clk_init(void) 99static int __init sh7780_clk_init(void)
100{ 100{
101 struct clk *clk = clk_get("master_clk"); 101 struct clk *clk = clk_get(NULL, "master_clk");
102 int i; 102 int i;
103 103
104 for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { 104 for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index f486c07e10e2..7624677f6628 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs)
282 grab_fpu(regs); 282 grab_fpu(regs);
283 restore_fpu(tsk); 283 restore_fpu(tsk);
284 set_tsk_thread_flag(tsk, TIF_USEDFPU); 284 set_tsk_thread_flag(tsk, TIF_USEDFPU);
285 } else { 285 } else
286 tsk->thread.trap_no = 11;
287 tsk->thread.error_code = 0;
288 force_sig(SIGFPE, tsk); 286 force_sig(SIGFPE, tsk);
289 }
290 287
291 regs->pc = nextpc; 288 regs->pc = nextpc;
292 return 1; 289 return 1;
@@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs)
296} 293}
297 294
298asmlinkage void 295asmlinkage void
299do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, 296do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
300 struct pt_regs regs) 297 unsigned long r7, struct pt_regs __regs)
301{ 298{
299 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
302 struct task_struct *tsk = current; 300 struct task_struct *tsk = current;
303 301
304 if (ieee_fpe_handler (&regs)) 302 if (ieee_fpe_handler(regs))
305 return; 303 return;
306 304
307 regs.pc += 2; 305 regs->pc += 2;
308 save_fpu(tsk, &regs); 306 save_fpu(tsk, regs);
309 tsk->thread.trap_no = 11;
310 tsk->thread.error_code = 0;
311 force_sig(SIGFPE, tsk); 307 force_sig(SIGFPE, tsk);
312} 308}
313 309
314asmlinkage void 310asmlinkage void
315do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, 311do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
316 unsigned long r7, struct pt_regs regs) 312 unsigned long r7, struct pt_regs __regs)
317{ 313{
314 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
318 struct task_struct *tsk = current; 315 struct task_struct *tsk = current;
319 316
320 grab_fpu(&regs); 317 grab_fpu(regs);
321 if (!user_mode(&regs)) { 318 if (!user_mode(regs)) {
322 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); 319 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
323 return; 320 return;
324 } 321 }
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index c294de1e14a3..afe0f1b1c030 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void)
79 case 0x205: 79 case 0x205:
80 cpu_data->type = CPU_SH7750; 80 cpu_data->type = CPU_SH7750;
81 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 81 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
82 CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; 82 CPU_HAS_PERF_COUNTER;
83 break; 83 break;
84 case 0x206: 84 case 0x206:
85 cpu_data->type = CPU_SH7750S; 85 cpu_data->type = CPU_SH7750S;
86 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 86 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
87 CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; 87 CPU_HAS_PERF_COUNTER;
88 break; 88 break;
89 case 0x1100: 89 case 0x1100:
90 cpu_data->type = CPU_SH7751; 90 cpu_data->type = CPU_SH7751;
91 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 91 cpu_data->flags |= CPU_HAS_FPU;
92 break; 92 break;
93 case 0x2000: 93 case 0x2000:
94 cpu_data->type = CPU_SH73180; 94 cpu_data->type = CPU_SH73180;
@@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void)
126 break; 126 break;
127 case 0x8000: 127 case 0x8000:
128 cpu_data->type = CPU_ST40RA; 128 cpu_data->type = CPU_ST40RA;
129 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 129 cpu_data->flags |= CPU_HAS_FPU;
130 break; 130 break;
131 case 0x8100: 131 case 0x8100:
132 cpu_data->type = CPU_ST40GX1; 132 cpu_data->type = CPU_ST40GX1;
133 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 133 cpu_data->flags |= CPU_HAS_FPU;
134 break; 134 break;
135 case 0x700: 135 case 0x700:
136 cpu_data->type = CPU_SH4_501; 136 cpu_data->type = CPU_SH4_501;
137 cpu_data->icache.ways = 2; 137 cpu_data->icache.ways = 2;
138 cpu_data->dcache.ways = 2; 138 cpu_data->dcache.ways = 2;
139 cpu_data->flags |= CPU_HAS_PTEA;
140 break; 139 break;
141 case 0x600: 140 case 0x600:
142 cpu_data->type = CPU_SH4_202; 141 cpu_data->type = CPU_SH4_202;
143 cpu_data->icache.ways = 2; 142 cpu_data->icache.ways = 2;
144 cpu_data->dcache.ways = 2; 143 cpu_data->dcache.ways = 2;
145 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 144 cpu_data->flags |= CPU_HAS_FPU;
146 break; 145 break;
147 case 0x500 ... 0x501: 146 case 0x500 ... 0x501:
148 switch (prr) { 147 switch (prr) {
@@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void)
160 cpu_data->icache.ways = 2; 159 cpu_data->icache.ways = 2;
161 cpu_data->dcache.ways = 2; 160 cpu_data->dcache.ways = 2;
162 161
163 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 162 cpu_data->flags |= CPU_HAS_FPU;
164 163
165 break; 164 break;
166 default: 165 default:
@@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void)
173 cpu_data->dcache.ways = 1; 172 cpu_data->dcache.ways = 1;
174#endif 173#endif
175 174
175#ifdef CONFIG_CPU_HAS_PTEA
176 cpu_data->flags |= CPU_HAS_PTEA;
177#endif
178
176 /* 179 /*
177 * On anything that's not a direct-mapped cache, look to the CVR 180 * On anything that's not a direct-mapped cache, look to the CVR
178 * for I/D-cache specifics. 181 * for I/D-cache specifics.
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 50812d57c1c1..bbcb06f18b04 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -2,6 +2,7 @@
2 * SH7750/SH7751 Setup 2 * SH7750/SH7751 Setup
3 * 3 *
4 * Copyright (C) 2006 Paul Mundt 4 * Copyright (C) 2006 Paul Mundt
5 * Copyright (C) 2006 Jamie Lenehan
5 * 6 *
6 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive 8 * License. See the file "COPYING" in the main directory of this archive
@@ -10,6 +11,7 @@
10#include <linux/platform_device.h> 11#include <linux/platform_device.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/serial.h> 13#include <linux/serial.h>
14#include <linux/io.h>
13#include <asm/sci.h> 15#include <asm/sci.h>
14 16
15static struct plat_sci_port sci_platform_data[] = { 17static struct plat_sci_port sci_platform_data[] = {
@@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void)
46 ARRAY_SIZE(sh7750_devices)); 48 ARRAY_SIZE(sh7750_devices));
47} 49}
48__initcall(sh7750_devices_setup); 50__initcall(sh7750_devices_setup);
51
52static struct ipr_data sh7750_ipr_map[] = {
53 /* IRQ, IPR-idx, shift, priority */
54 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
55 { 17, 0, 12, 2 }, /* TMU1 TUNI */
56 { 18, 0, 4, 2 }, /* TMU2 TUNI */
57 { 19, 0, 4, 2 }, /* TMU2 TIPCI */
58 { 27, 1, 12, 2 }, /* WDT ITI */
59 { 20, 0, 0, 2 }, /* RTC ATI (alarm) */
60 { 21, 0, 0, 2 }, /* RTC PRI (period) */
61 { 22, 0, 0, 2 }, /* RTC CUI (carry) */
62 { 23, 1, 4, 3 }, /* SCI ERI */
63 { 24, 1, 4, 3 }, /* SCI RXI */
64 { 25, 1, 4, 3 }, /* SCI TXI */
65 { 40, 2, 4, 3 }, /* SCIF ERI */
66 { 41, 2, 4, 3 }, /* SCIF RXI */
67 { 42, 2, 4, 3 }, /* SCIF BRI */
68 { 43, 2, 4, 3 }, /* SCIF TXI */
69 { 34, 2, 8, 7 }, /* DMAC DMTE0 */
70 { 35, 2, 8, 7 }, /* DMAC DMTE1 */
71 { 36, 2, 8, 7 }, /* DMAC DMTE2 */
72 { 37, 2, 8, 7 }, /* DMAC DMTE3 */
73 { 28, 2, 8, 7 }, /* DMAC DMAE */
74};
75
76static struct ipr_data sh7751_ipr_map[] = {
77 { 44, 2, 8, 7 }, /* DMAC DMTE4 */
78 { 45, 2, 8, 7 }, /* DMAC DMTE5 */
79 { 46, 2, 8, 7 }, /* DMAC DMTE6 */
80 { 47, 2, 8, 7 }, /* DMAC DMTE7 */
81 /* The following use INTC_INPRI00 for masking, which is a 32-bit
82 register, not a 16-bit register like the IPRx registers, so it
83 would need special support */
84 /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
85 /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
86};
87
88static unsigned long ipr_offsets[] = {
89 0xffd00004UL, /* 0: IPRA */
90 0xffd00008UL, /* 1: IPRB */
91 0xffd0000cUL, /* 2: IPRC */
92 0xffd00010UL, /* 3: IPRD */
93};
94
95/* given the IPR index return the address of the IPR register */
96unsigned int map_ipridx_to_addr(int idx)
97{
98 if (idx >= ARRAY_SIZE(ipr_offsets))
99 return 0;
100 return ipr_offsets[idx];
101}
102
103#define INTC_ICR 0xffd00000UL
104#define INTC_ICR_IRLM (1<<7)
105
106/* enable individual interrupt mode for external interupts */
107void ipr_irq_enable_irlm(void)
108{
109 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
110}
111
112void __init init_IRQ_ipr()
113{
114 make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
115#ifdef CONFIG_CPU_SUBTYPE_SH7751
116 make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
117#endif
118}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
index 814ddb226531..9aeaa2ddaa28 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
@@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void)
79__initcall(sh7780_devices_setup); 79__initcall(sh7780_devices_setup);
80 80
81static struct intc2_data intc2_irq_table[] = { 81static struct intc2_data intc2_irq_table[] = {
82 { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, 82 { 28, 0, 24, 0, 0, 2 }, /* TMU0 */
83 { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
84 { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
85 { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
86 { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
87 { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
88 { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
89 { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
90 83
91 { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 84 { 21, 1, 0, 0, 2, 2 },
92 { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 85 { 22, 1, 1, 0, 2, 2 },
93 { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 86 { 23, 1, 2, 0, 2, 2 },
94 { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
95 87
96 { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, 88 { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */
97 { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, 89 { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */
98 { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, 90 { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */
99 { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, 91 { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */
100 { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, 92
93 { 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */
94 { 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */
95 { 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */
96 { 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */
97
98 { 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */
99 { 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */
100 { 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */
101 { 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */
102 { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */
101}; 103};
102 104
103void __init init_IRQ_intc2(void) 105void __init init_IRQ_intc2(void)
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 7bcc73f9b8df..55f43506995a 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -19,7 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <asm/io.h> 22#include <linux/io.h>
23#include <asm/page.h> 23#include <asm/page.h>
24#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
25#include <asm/cpu/sq.h> 25#include <asm/cpu/sq.h>
@@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len)
67 /* Wait for completion */ 67 /* Wait for completion */
68 store_queue_barrier(); 68 store_queue_barrier();
69} 69}
70EXPORT_SYMBOL(sq_flush_range);
70 71
71static inline void sq_mapping_list_add(struct sq_mapping *map) 72static inline void sq_mapping_list_add(struct sq_mapping *map)
72{ 73{
@@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
166 map->size = size; 167 map->size = size;
167 map->name = name; 168 map->name = name;
168 169
169 page = bitmap_find_free_region(sq_bitmap, 0x04000000, 170 page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT,
170 get_order(map->size)); 171 get_order(map->size));
171 if (unlikely(page < 0)) { 172 if (unlikely(page < 0)) {
172 ret = -ENOSPC; 173 ret = -ENOSPC;
@@ -193,6 +194,7 @@ out:
193 kmem_cache_free(sq_cache, map); 194 kmem_cache_free(sq_cache, map);
194 return ret; 195 return ret;
195} 196}
197EXPORT_SYMBOL(sq_remap);
196 198
197/** 199/**
198 * sq_unmap - Unmap a Store Queue allocation 200 * sq_unmap - Unmap a Store Queue allocation
@@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr)
234 236
235 kmem_cache_free(sq_cache, map); 237 kmem_cache_free(sq_cache, map);
236} 238}
239EXPORT_SYMBOL(sq_unmap);
237 240
238/* 241/*
239 * Needlessly complex sysfs interface. Unfortunately it doesn't seem like 242 * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
@@ -402,7 +405,3 @@ module_exit(sq_api_exit);
402MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); 405MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
403MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); 406MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
404MODULE_LICENSE("GPL"); 407MODULE_LICENSE("GPL");
405
406EXPORT_SYMBOL(sq_remap);
407EXPORT_SYMBOL(sq_unmap);
408EXPORT_SYMBOL(sq_flush_range);
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index a00022722e9e..60340823798a 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -12,7 +12,7 @@
12#include <linux/console.h> 12#include <linux/console.h>
13#include <linux/tty.h> 13#include <linux/tty.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <asm/io.h> 15#include <linux/io.h>
16 16
17#ifdef CONFIG_SH_STANDARD_BIOS 17#ifdef CONFIG_SH_STANDARD_BIOS
18#include <asm/sh_bios.h> 18#include <asm/sh_bios.h>
@@ -62,17 +62,9 @@ static struct console bios_console = {
62#include <linux/serial_core.h> 62#include <linux/serial_core.h>
63#include "../../../drivers/serial/sh-sci.h" 63#include "../../../drivers/serial/sh-sci.h"
64 64
65#ifdef CONFIG_CPU_SH4
66#define SCIF_REG 0xffe80000
67#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
68#define SCIF_REG 0xfffe9800
69#else
70#error "Undefined SCIF for this subtype"
71#endif
72
73static struct uart_port scif_port = { 65static struct uart_port scif_port = {
74 .mapbase = SCIF_REG, 66 .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
75 .membase = (char __iomem *)SCIF_REG, 67 .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
76}; 68};
77 69
78static void scif_sercon_putc(int c) 70static void scif_sercon_putc(int c)
@@ -113,23 +105,29 @@ static struct console scif_console = {
113 .index = -1, 105 .index = -1,
114}; 106};
115 107
108#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
109/*
110 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
111 * devices that aren't using sh-ipl+g.
112 */
116static void scif_sercon_init(int baud) 113static void scif_sercon_init(int baud)
117{ 114{
118 ctrl_outw(0, SCIF_REG + 8); 115 ctrl_outw(0, scif_port.mapbase + 8);
119 ctrl_outw(0, SCIF_REG); 116 ctrl_outw(0, scif_port.mapbase);
120 117
121 /* Set baud rate */ 118 /* Set baud rate */
122 ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / 119 ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
123 (32 * baud) - 1, SCIF_REG + 4); 120 (32 * baud) - 1, scif_port.mapbase + 4);
124 121
125 ctrl_outw(12, SCIF_REG + 24); 122 ctrl_outw(12, scif_port.mapbase + 24);
126 ctrl_outw(8, SCIF_REG + 24); 123 ctrl_outw(8, scif_port.mapbase + 24);
127 ctrl_outw(0, SCIF_REG + 32); 124 ctrl_outw(0, scif_port.mapbase + 32);
128 ctrl_outw(0x60, SCIF_REG + 16); 125 ctrl_outw(0x60, scif_port.mapbase + 16);
129 ctrl_outw(0, SCIF_REG + 36); 126 ctrl_outw(0, scif_port.mapbase + 36);
130 ctrl_outw(0x30, SCIF_REG + 8); 127 ctrl_outw(0x30, scif_port.mapbase + 8);
131} 128}
132#endif 129#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
130#endif /* CONFIG_EARLY_SCIF_CONSOLE */
133 131
134/* 132/*
135 * Setup a default console, if more than one is compiled in, rely on the 133 * Setup a default console, if more than one is compiled in, rely on the
@@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt)
168 if (!strncmp(buf, "serial", 6)) { 166 if (!strncmp(buf, "serial", 6)) {
169 early_console = &scif_console; 167 early_console = &scif_console;
170 168
171#ifdef CONFIG_CPU_SH4 169#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
172 scif_sercon_init(115200); 170 scif_sercon_init(115200);
173#endif 171#endif
174 } 172 }
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
new file mode 100644
index 000000000000..29136a35d7c7
--- /dev/null
+++ b/arch/sh/kernel/entry-common.S
@@ -0,0 +1,433 @@
1/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
2 *
3 * linux/arch/sh/entry.S
4 *
5 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
6 * Copyright (C) 2003 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 *
12 */
13
14! NOTE:
15! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
16! to be jumped is too far, but it causes illegal slot exception.
17
18/*
19 * entry.S contains the system-call and fault low-level handling routines.
20 * This also contains the timer-interrupt handler, as well as all interrupts
21 * and faults that can result in a task-switch.
22 *
23 * NOTE: This code handles signal-recognition, which happens every time
24 * after a timer-interrupt and after each system call.
25 *
26 * NOTE: This code uses a convention that instructions in the delay slot
27 * of a transfer-control instruction are indented by an extra space, thus:
28 *
29 * jmp @k0 ! control-transfer instruction
30 * ldc k1, ssr ! delay slot
31 *
32 * Stack layout in 'ret_from_syscall':
33 * ptrace needs to have all regs on the stack.
34 * if the order here is changed, it needs to be
35 * updated in ptrace.c and ptrace.h
36 *
37 * r0
38 * ...
39 * r15 = stack pointer
40 * spc
41 * pr
42 * ssr
43 * gbr
44 * mach
45 * macl
46 * syscall #
47 *
48 */
49
50#if defined(CONFIG_PREEMPT)
51# define preempt_stop() cli
52#else
53# define preempt_stop()
54# define resume_kernel __restore_all
55#endif
56
57#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
58! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
59! If both are configured, handle the debug traps (breakpoints) in SW,
60! but still allow BIOS traps to FW.
61
62 .align 2
63debug_kernel:
64#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
65 /* Force BIOS call to FW (debug_trap put TRA in r8) */
66 mov r8,r0
67 shlr2 r0
68 cmp/eq #0x3f,r0
69 bt debug_kernel_fw
70#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
71
72debug_enter:
73#if defined(CONFIG_SH_KGDB)
74 /* Jump to kgdb, pass stacked regs as arg */
75debug_kernel_sw:
76 mov.l 3f, r0
77 jmp @r0
78 mov r15, r4
79 .align 2
803: .long kgdb_handle_exception
81#endif /* CONFIG_SH_KGDB */
82
83#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
84
85
86 .align 2
87debug_trap:
88#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
89 mov #OFF_SR, r0
90 mov.l @(r0,r15), r0 ! get status register
91 shll r0
92 shll r0 ! kernel space?
93 bt/s debug_kernel
94#endif
95 mov.l @r15, r0 ! Restore R0 value
96 mov.l 1f, r8
97 jmp @r8
98 nop
99
100 .align 2
101ENTRY(exception_error)
102 !
103#ifdef CONFIG_TRACE_IRQFLAGS
104 mov.l 3f, r0
105 jsr @r0
106 nop
107#endif
108 sti
109 mov.l 2f, r0
110 jmp @r0
111 nop
112
113!
114 .align 2
1151: .long break_point_trap_software
1162: .long do_exception_error
117#ifdef CONFIG_TRACE_IRQFLAGS
1183: .long trace_hardirqs_on
119#endif
120
121 .align 2
122ret_from_exception:
123 preempt_stop()
124#ifdef CONFIG_TRACE_IRQFLAGS
125 mov.l 4f, r0
126 jsr @r0
127 nop
128#endif
129ENTRY(ret_from_irq)
130 !
131 mov #OFF_SR, r0
132 mov.l @(r0,r15), r0 ! get status register
133 shll r0
134 shll r0 ! kernel space?
135 get_current_thread_info r8, r0
136 bt resume_kernel ! Yes, it's from kernel, go back soon
137
138#ifdef CONFIG_PREEMPT
139 bra resume_userspace
140 nop
141ENTRY(resume_kernel)
142 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
143 tst r0, r0
144 bf noresched
145need_resched:
146 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
147 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
148 bt noresched
149
150 mov #OFF_SR, r0
151 mov.l @(r0,r15), r0 ! get status register
152 and #0xf0, r0 ! interrupts off (exception path)?
153 cmp/eq #0xf0, r0
154 bt noresched
155
156 mov.l 1f, r0
157 mov.l r0, @(TI_PRE_COUNT,r8)
158
159#ifdef CONFIG_TRACE_IRQFLAGS
160 mov.l 3f, r0
161 jsr @r0
162 nop
163#endif
164 sti
165 mov.l 2f, r0
166 jsr @r0
167 nop
168 mov #0, r0
169 mov.l r0, @(TI_PRE_COUNT,r8)
170 cli
171#ifdef CONFIG_TRACE_IRQFLAGS
172 mov.l 4f, r0
173 jsr @r0
174 nop
175#endif
176
177 bra need_resched
178 nop
179
180noresched:
181 bra __restore_all
182 nop
183
184 .align 2
1851: .long PREEMPT_ACTIVE
1862: .long schedule
187#ifdef CONFIG_TRACE_IRQFLAGS
1883: .long trace_hardirqs_on
1894: .long trace_hardirqs_off
190#endif
191#endif
192
193ENTRY(resume_userspace)
194 ! r8: current_thread_info
195 cli
196#ifdef CONFIG_TRACE_IRQFLAGS
197 mov.l 5f, r0
198 jsr @r0
199 nop
200#endif
201 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
202 tst #_TIF_WORK_MASK, r0
203 bt/s __restore_all
204 tst #_TIF_NEED_RESCHED, r0
205
206 .align 2
207work_pending:
208 ! r0: current_thread_info->flags
209 ! r8: current_thread_info
210 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
211 bf/s work_resched
212 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
213work_notifysig:
214 bt/s __restore_all
215 mov r15, r4
216 mov r12, r5 ! set arg1(save_r0)
217 mov r0, r6
218 mov.l 2f, r1
219 mov.l 3f, r0
220 jmp @r1
221 lds r0, pr
222work_resched:
223#ifndef CONFIG_PREEMPT
224 ! gUSA handling
225 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
226 mov r0, r1
227 shll r0
228 bf/s 1f
229 shll r0
230 bf/s 1f
231 mov #OFF_PC, r0
232 ! SP >= 0xc0000000 : gUSA mark
233 mov.l @(r0,r15), r2 ! get user space PC (program counter)
234 mov.l @(OFF_R0,r15), r3 ! end point
235 cmp/hs r3, r2 ! r2 >= r3?
236 bt 1f
237 add r3, r1 ! rewind point #2
238 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
239 !
2401:
241#endif
242 mov.l 1f, r1
243 jsr @r1 ! schedule
244 nop
245 cli
246#ifdef CONFIG_TRACE_IRQFLAGS
247 mov.l 5f, r0
248 jsr @r0
249 nop
250#endif
251 !
252 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
253 tst #_TIF_WORK_MASK, r0
254 bt __restore_all
255 bra work_pending
256 tst #_TIF_NEED_RESCHED, r0
257
258 .align 2
2591: .long schedule
2602: .long do_notify_resume
2613: .long restore_all
262#ifdef CONFIG_TRACE_IRQFLAGS
2634: .long trace_hardirqs_on
2645: .long trace_hardirqs_off
265#endif
266
267 .align 2
268syscall_exit_work:
269 ! r0: current_thread_info->flags
270 ! r8: current_thread_info
271 tst #_TIF_SYSCALL_TRACE, r0
272 bt/s work_pending
273 tst #_TIF_NEED_RESCHED, r0
274#ifdef CONFIG_TRACE_IRQFLAGS
275 mov.l 5f, r0
276 jsr @r0
277 nop
278#endif
279 sti
280 ! XXX setup arguments...
281 mov.l 4f, r0 ! do_syscall_trace
282 jsr @r0
283 nop
284 bra resume_userspace
285 nop
286
287 .align 2
288syscall_trace_entry:
289 ! Yes it is traced.
290 ! XXX setup arguments...
291 mov.l 4f, r11 ! Call do_syscall_trace which notifies
292 jsr @r11 ! superior (will chomp R[0-7])
293 nop
294 ! Reload R0-R4 from kernel stack, where the
295 ! parent may have modified them using
296 ! ptrace(POKEUSR). (Note that R0-R2 are
297 ! used by the system call handler directly
298 ! from the kernel stack anyway, so don't need
299 ! to be reloaded here.) This allows the parent
300 ! to rewrite system calls and args on the fly.
301 mov.l @(OFF_R4,r15), r4 ! arg0
302 mov.l @(OFF_R5,r15), r5
303 mov.l @(OFF_R6,r15), r6
304 mov.l @(OFF_R7,r15), r7 ! arg3
305 mov.l @(OFF_R3,r15), r3 ! syscall_nr
306 !
307 mov.l 2f, r10 ! Number of syscalls
308 cmp/hs r10, r3
309 bf syscall_call
310 mov #-ENOSYS, r0
311 bra syscall_exit
312 mov.l r0, @(OFF_R0,r15) ! Return value
313
314__restore_all:
315 mov.l 1f, r0
316 jmp @r0
317 nop
318
319 .align 2
3201: .long restore_all
321
322 .align 2
323not_syscall_tra:
324 bra debug_trap
325 nop
326
327 .align 2
328syscall_badsys: ! Bad syscall number
329 mov #-ENOSYS, r0
330 bra resume_userspace
331 mov.l r0, @(OFF_R0,r15) ! Return value
332
333
334/*
335 * Syscall interface:
336 *
337 * Syscall #: R3
338 * Arguments #0 to #3: R4--R7
339 * Arguments #4 to #6: R0, R1, R2
340 * TRA: (number of arguments + 0x10) x 4
341 *
342 * This code also handles delegating other traps to the BIOS/gdb stub
343 * according to:
344 *
345 * Trap number
346 * (TRA>>2) Purpose
347 * -------- -------
348 * 0x0-0xf old syscall ABI
349 * 0x10-0x1f new syscall ABI
350 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
351 *
352 * Note: When we're first called, the TRA value must be shifted
353 * right 2 bits in order to get the value that was used as the "trapa"
354 * argument.
355 */
356
357 .align 2
358 .globl ret_from_fork
359ret_from_fork:
360 mov.l 1f, r8
361 jsr @r8
362 mov r0, r4
363 bra syscall_exit
364 nop
365 .align 2
3661: .long schedule_tail
367 !
368ENTRY(system_call)
369#if !defined(CONFIG_CPU_SH2)
370 mov.l 1f, r9
371 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
372#endif
373 !
374 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
375 mov #0x7f, r9
376 cmp/hi r9, r8
377 bt/s not_syscall_tra
378 mov #OFF_TRA, r9
379 add r15, r9
380 mov.l r8, @r9 ! set TRA value to tra
381#ifdef CONFIG_TRACE_IRQFLAGS
382 mov.l 5f, r10
383 jsr @r10
384 nop
385#endif
386 sti
387
388 !
389 get_current_thread_info r8, r10
390 mov.l @(TI_FLAGS,r8), r8
391 mov #_TIF_SYSCALL_TRACE, r10
392 tst r10, r8
393 bf syscall_trace_entry
394 !
395 mov.l 2f, r8 ! Number of syscalls
396 cmp/hs r8, r3
397 bt syscall_badsys
398 !
399syscall_call:
400 shll2 r3 ! x4
401 mov.l 3f, r8 ! Load the address of sys_call_table
402 add r8, r3
403 mov.l @r3, r8
404 jsr @r8 ! jump to specific syscall handler
405 nop
406 mov.l @(OFF_R0,r15), r12 ! save r0
407 mov.l r0, @(OFF_R0,r15) ! save the return value
408 !
409syscall_exit:
410 cli
411#ifdef CONFIG_TRACE_IRQFLAGS
412 mov.l 6f, r0
413 jsr @r0
414 nop
415#endif
416 !
417 get_current_thread_info r8, r0
418 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
419 tst #_TIF_ALLWORK_MASK, r0
420 bf syscall_exit_work
421 bra __restore_all
422 nop
423 .align 2
424#if !defined(CONFIG_CPU_SH2)
4251: .long TRA
426#endif
4272: .long NR_syscalls
4283: .long sys_call_table
4294: .long do_syscall_trace
430#ifdef CONFIG_TRACE_IRQFLAGS
4315: .long trace_hardirqs_on
4326: .long trace_hardirqs_off
433#endif
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index f5f53d14f245..6aca4bc6ec5d 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -33,7 +33,7 @@ ENTRY(empty_zero_page)
33 .long 0x00360000 /* INITRD_START */ 33 .long 0x00360000 /* INITRD_START */
34 .long 0x000a0000 /* INITRD_SIZE */ 34 .long 0x000a0000 /* INITRD_SIZE */
35 .long 0 35 .long 0
36 .balign 4096,0,4096 36 .balign PAGE_SIZE,0,PAGE_SIZE
37 37
38 .text 38 .text
39/* 39/*
@@ -53,8 +53,10 @@ ENTRY(_stext)
53 ldc r0, sr 53 ldc r0, sr
54 ! Initialize global interrupt mask 54 ! Initialize global interrupt mask
55 mov #0, r0 55 mov #0, r0
56#ifdef CONFIG_CPU_HAS_SR_RB
56 ldc r0, r6_bank 57 ldc r0, r6_bank
57 58#endif
59
58 /* 60 /*
59 * Prefetch if possible to reduce cache miss penalty. 61 * Prefetch if possible to reduce cache miss penalty.
60 * 62 *
@@ -68,11 +70,14 @@ ENTRY(_stext)
68 ! 70 !
69 mov.l 2f, r0 71 mov.l 2f, r0
70 mov r0, r15 ! Set initial r15 (stack pointer) 72 mov r0, r15 ! Set initial r15 (stack pointer)
71 mov #(THREAD_SIZE >> 8), r1 73 mov #(THREAD_SIZE >> 10), r1
72 shll8 r1 ! r1 = THREAD_SIZE 74 shll8 r1 ! r1 = THREAD_SIZE
75 shll2 r1
73 sub r1, r0 ! 76 sub r1, r0 !
77#ifdef CONFIG_CPU_HAS_SR_RB
74 ldc r0, r7_bank ! ... and initial thread_info 78 ldc r0, r7_bank ! ... and initial thread_info
75 79#endif
80
76 ! Clear BSS area 81 ! Clear BSS area
77 mov.l 3f, r1 82 mov.l 3f, r1
78 add #4, r1 83 add #4, r1
@@ -95,7 +100,11 @@ ENTRY(_stext)
95 nop 100 nop
96 101
97 .balign 4 102 .balign 4
103#if defined(CONFIG_CPU_SH2)
1041: .long 0x000000F0 ! IMASK=0xF
105#else
981: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 1061: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
107#endif
992: .long init_thread_union+THREAD_SIZE 1082: .long init_thread_union+THREAD_SIZE
1003: .long __bss_start 1093: .long __bss_start
1014: .long _end 1104: .long _end
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 944128ce9706..67be2b6e8cd1 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -12,7 +12,7 @@
12#include <linux/kernel_stat.h> 12#include <linux/kernel_stat.h>
13#include <linux/seq_file.h> 13#include <linux/seq_file.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <asm/irq.h> 15#include <linux/irq.h>
16#include <asm/processor.h> 16#include <asm/processor.h>
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18#include <asm/thread_info.h> 18#include <asm/thread_info.h>
@@ -78,15 +78,16 @@ union irq_ctx {
78 u32 stack[THREAD_SIZE/sizeof(u32)]; 78 u32 stack[THREAD_SIZE/sizeof(u32)];
79}; 79};
80 80
81static union irq_ctx *hardirq_ctx[NR_CPUS]; 81static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
82static union irq_ctx *softirq_ctx[NR_CPUS]; 82static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
83#endif 83#endif
84 84
85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, 85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
86 unsigned long r6, unsigned long r7, 86 unsigned long r6, unsigned long r7,
87 struct pt_regs regs) 87 struct pt_regs __regs)
88{ 88{
89 struct pt_regs *old_regs = set_irq_regs(&regs); 89 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
90 struct pt_regs *old_regs = set_irq_regs(regs);
90 int irq; 91 int irq;
91#ifdef CONFIG_4KSTACKS 92#ifdef CONFIG_4KSTACKS
92 union irq_ctx *curctx, *irqctx; 93 union irq_ctx *curctx, *irqctx;
@@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
111#endif 112#endif
112 113
113#ifdef CONFIG_CPU_HAS_INTEVT 114#ifdef CONFIG_CPU_HAS_INTEVT
114 irq = (ctrl_inl(INTEVT) >> 5) - 16; 115 irq = evt2irq(ctrl_inl(INTEVT));
115#else 116#else
116 irq = r4; 117 irq = r4;
117#endif 118#endif
@@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
135 irqctx->tinfo.task = curctx->tinfo.task; 136 irqctx->tinfo.task = curctx->tinfo.task;
136 irqctx->tinfo.previous_sp = current_stack_pointer; 137 irqctx->tinfo.previous_sp = current_stack_pointer;
137 138
139 /*
140 * Copy the softirq bits in preempt_count so that the
141 * softirq checks work in the hardirq context.
142 */
143 irqctx->tinfo.preempt_count =
144 (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
145 (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
146
138 __asm__ __volatile__ ( 147 __asm__ __volatile__ (
139 "mov %0, r4 \n" 148 "mov %0, r4 \n"
140 "mov r15, r9 \n" 149 "mov r15, r8 \n"
141 "jsr @%1 \n" 150 "jsr @%1 \n"
142 /* swith to the irq stack */ 151 /* swith to the irq stack */
143 " mov %2, r15 \n" 152 " mov %2, r15 \n"
144 /* restore the stack (ring zero) */ 153 /* restore the stack (ring zero) */
145 "mov r9, r15 \n" 154 "mov r8, r15 \n"
146 : /* no outputs */ 155 : /* no outputs */
147 : "r" (irq), "r" (generic_handle_irq), "r" (isp) 156 : "r" (irq), "r" (generic_handle_irq), "r" (isp)
148 /* XXX: A somewhat excessive clobber list? -PFM */
149 : "memory", "r0", "r1", "r2", "r3", "r4", 157 : "memory", "r0", "r1", "r2", "r3", "r4",
150 "r5", "r6", "r7", "r8", "t", "pr" 158 "r5", "r6", "r7", "r8", "t", "pr"
151 ); 159 );
@@ -193,7 +201,7 @@ void irq_ctx_init(int cpu)
193 irqctx->tinfo.task = NULL; 201 irqctx->tinfo.task = NULL;
194 irqctx->tinfo.exec_domain = NULL; 202 irqctx->tinfo.exec_domain = NULL;
195 irqctx->tinfo.cpu = cpu; 203 irqctx->tinfo.cpu = cpu;
196 irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; 204 irqctx->tinfo.preempt_count = 0;
197 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); 205 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
198 206
199 softirq_ctx[cpu] = irqctx; 207 softirq_ctx[cpu] = irqctx;
@@ -239,13 +247,38 @@ asmlinkage void do_softirq(void)
239 "mov r9, r15 \n" 247 "mov r9, r15 \n"
240 : /* no outputs */ 248 : /* no outputs */
241 : "r" (__do_softirq), "r" (isp) 249 : "r" (__do_softirq), "r" (isp)
242 /* XXX: A somewhat excessive clobber list? -PFM */
243 : "memory", "r0", "r1", "r2", "r3", "r4", 250 : "memory", "r0", "r1", "r2", "r3", "r4",
244 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" 251 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
245 ); 252 );
253
254 /*
255 * Shouldnt happen, we returned above if in_interrupt():
256 */
257 WARN_ON_ONCE(softirq_count());
246 } 258 }
247 259
248 local_irq_restore(flags); 260 local_irq_restore(flags);
249} 261}
250EXPORT_SYMBOL(do_softirq); 262EXPORT_SYMBOL(do_softirq);
251#endif 263#endif
264
265void __init init_IRQ(void)
266{
267#ifdef CONFIG_CPU_HAS_PINT_IRQ
268 init_IRQ_pint();
269#endif
270
271#ifdef CONFIG_CPU_HAS_INTC2_IRQ
272 init_IRQ_intc2();
273#endif
274
275#ifdef CONFIG_CPU_HAS_IPR_IRQ
276 init_IRQ_ipr();
277#endif
278
279 /* Perform the machine specific initialisation */
280 if (sh_mv.mv_init_irq)
281 sh_mv.mv_init_irq();
282
283 irq_ctx_init(smp_processor_id());
284}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index a52b13ac6b7f..f3e2631be144 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -385,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
385 385
386asmlinkage int sys_fork(unsigned long r4, unsigned long r5, 386asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
387 unsigned long r6, unsigned long r7, 387 unsigned long r6, unsigned long r7,
388 struct pt_regs regs) 388 struct pt_regs __regs)
389{ 389{
390 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
390#ifdef CONFIG_MMU 391#ifdef CONFIG_MMU
391 return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL); 392 return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
392#else 393#else
393 /* fork almost works, enough to trick you into looking elsewhere :-( */ 394 /* fork almost works, enough to trick you into looking elsewhere :-( */
394 return -EINVAL; 395 return -EINVAL;
@@ -398,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
398asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 399asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
399 unsigned long parent_tidptr, 400 unsigned long parent_tidptr,
400 unsigned long child_tidptr, 401 unsigned long child_tidptr,
401 struct pt_regs regs) 402 struct pt_regs __regs)
402{ 403{
404 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
403 if (!newsp) 405 if (!newsp)
404 newsp = regs.regs[15]; 406 newsp = regs->regs[15];
405 return do_fork(clone_flags, newsp, &regs, 0, 407 return do_fork(clone_flags, newsp, regs, 0,
406 (int __user *)parent_tidptr, (int __user *)child_tidptr); 408 (int __user *)parent_tidptr, (int __user *)child_tidptr);
407} 409}
408 410
@@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
418 */ 420 */
419asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, 421asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
420 unsigned long r6, unsigned long r7, 422 unsigned long r6, unsigned long r7,
421 struct pt_regs regs) 423 struct pt_regs __regs)
422{ 424{
423 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 425 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
426 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
424 0, NULL, NULL); 427 0, NULL, NULL);
425} 428}
426 429
@@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
429 */ 432 */
430asmlinkage int sys_execve(char *ufilename, char **uargv, 433asmlinkage int sys_execve(char *ufilename, char **uargv,
431 char **uenvp, unsigned long r7, 434 char **uenvp, unsigned long r7,
432 struct pt_regs regs) 435 struct pt_regs __regs)
433{ 436{
437 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
434 int error; 438 int error;
435 char *filename; 439 char *filename;
436 440
@@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
442 error = do_execve(filename, 446 error = do_execve(filename,
443 (char __user * __user *)uargv, 447 (char __user * __user *)uargv,
444 (char __user * __user *)uenvp, 448 (char __user * __user *)uenvp,
445 &regs); 449 regs);
446 if (error == 0) { 450 if (error == 0) {
447 task_lock(current); 451 task_lock(current);
448 current->ptrace &= ~PT_DTRACE; 452 current->ptrace &= ~PT_DTRACE;
@@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_struct *p)
472 return pc; 476 return pc;
473} 477}
474 478
475asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, 479asmlinkage void break_point_trap(void)
476 unsigned long r6, unsigned long r7,
477 struct pt_regs regs)
478{ 480{
479 /* Clear tracing. */ 481 /* Clear tracing. */
480#if defined(CONFIG_CPU_SH4A) 482#if defined(CONFIG_CPU_SH4A)
@@ -492,8 +494,10 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
492 494
493asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, 495asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
494 unsigned long r6, unsigned long r7, 496 unsigned long r6, unsigned long r7,
495 struct pt_regs regs) 497 struct pt_regs __regs)
496{ 498{
497 regs.pc -= 2; 499 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
500
501 regs->pc -= 2;
498 force_sig(SIGTRAP, current); 502 force_sig(SIGTRAP, current);
499} 503}
diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S
index 8221b37c9773..c66cb3209db5 100644
--- a/arch/sh/kernel/relocate_kernel.S
+++ b/arch/sh/kernel/relocate_kernel.S
@@ -7,11 +7,9 @@
7 * This source code is licensed under the GNU General Public License, 7 * This source code is licensed under the GNU General Public License,
8 * Version 2. See the file COPYING for more details. 8 * Version 2. See the file COPYING for more details.
9 */ 9 */
10
11#include <linux/linkage.h> 10#include <linux/linkage.h>
12 11#include <asm/addrspace.h>
13#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ 12#include <asm/page.h>
14
15 13
16 .globl relocate_new_kernel 14 .globl relocate_new_kernel
17relocate_new_kernel: 15relocate_new_kernel:
@@ -20,8 +18,8 @@ relocate_new_kernel:
20 /* r6 = start_address */ 18 /* r6 = start_address */
21 /* r7 = vbr_reg */ 19 /* r7 = vbr_reg */
22 20
23 mov.l 10f,r8 /* 4096 */ 21 mov.l 10f,r8 /* PAGE_SIZE */
24 mov.l 11f,r9 /* 0xa0000000 */ 22 mov.l 11f,r9 /* P2SEG */
25 23
26 /* stack setting */ 24 /* stack setting */
27 add r8,r5 25 add r8,r5
@@ -32,7 +30,7 @@ relocate_new_kernel:
320: 300:
33 mov.l @r4+,r0 /* cmd = *ind++ */ 31 mov.l @r4+,r0 /* cmd = *ind++ */
34 32
351: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ 331: /* addr = (cmd | P2SEG) & 0xfffffff0 */
36 mov r0,r2 34 mov r0,r2
37 or r9,r2 35 or r9,r2
38 mov #-16,r1 36 mov #-16,r1
@@ -92,7 +90,7 @@ relocate_new_kernel:
9210: 9010:
93 .long PAGE_SIZE 91 .long PAGE_SIZE
9411: 9211:
95 .long 0xa0000000 93 .long P2SEG
96 94
97relocate_new_kernel_end: 95relocate_new_kernel_end:
98 96
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 36d86f9ac38a..696ca75752d9 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -392,6 +392,7 @@ static int __init topology_init(void)
392subsys_initcall(topology_init); 392subsys_initcall(topology_init);
393 393
394static const char *cpu_name[] = { 394static const char *cpu_name[] = {
395 [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
395 [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", 396 [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
396 [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", 397 [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
397 [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", 398 [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
@@ -404,6 +405,7 @@ static const char *cpu_name[] = {
404 [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", 405 [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
405 [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", 406 [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
406 [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", 407 [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
408 [CPU_SH7785] = "SH7785",
407 [CPU_SH_NONE] = "Unknown" 409 [CPU_SH_NONE] = "Unknown"
408}; 410};
409 411
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 8a2fd19dc9eb..c706f3bfd897 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -73,8 +73,6 @@ DECLARE_EXPORT(__lshrdi3);
73DECLARE_EXPORT(__movstr); 73DECLARE_EXPORT(__movstr);
74DECLARE_EXPORT(__movstrSI16); 74DECLARE_EXPORT(__movstrSI16);
75 75
76EXPORT_SYMBOL(strcpy);
77
78#ifdef CONFIG_CPU_SH4 76#ifdef CONFIG_CPU_SH4
79DECLARE_EXPORT(__movstr_i4_even); 77DECLARE_EXPORT(__movstr_i4_even);
80DECLARE_EXPORT(__movstr_i4_odd); 78DECLARE_EXPORT(__movstr_i4_odd);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 5213f5bc6ce0..50d7c4993bef 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -37,7 +37,7 @@
37asmlinkage int 37asmlinkage int
38sys_sigsuspend(old_sigset_t mask, 38sys_sigsuspend(old_sigset_t mask,
39 unsigned long r5, unsigned long r6, unsigned long r7, 39 unsigned long r5, unsigned long r6, unsigned long r7,
40 struct pt_regs regs) 40 struct pt_regs __regs)
41{ 41{
42 mask &= _BLOCKABLE; 42 mask &= _BLOCKABLE;
43 spin_lock_irq(&current->sighand->siglock); 43 spin_lock_irq(&current->sighand->siglock);
@@ -52,7 +52,7 @@ sys_sigsuspend(old_sigset_t mask,
52 return -ERESTARTNOHAND; 52 return -ERESTARTNOHAND;
53} 53}
54 54
55asmlinkage int 55asmlinkage int
56sys_sigaction(int sig, const struct old_sigaction __user *act, 56sys_sigaction(int sig, const struct old_sigaction __user *act,
57 struct old_sigaction __user *oact) 57 struct old_sigaction __user *oact)
58{ 58{
@@ -87,9 +87,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
87asmlinkage int 87asmlinkage int
88sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 88sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
89 unsigned long r6, unsigned long r7, 89 unsigned long r6, unsigned long r7,
90 struct pt_regs regs) 90 struct pt_regs __regs)
91{ 91{
92 return do_sigaltstack(uss, uoss, regs.regs[15]); 92 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
93
94 return do_sigaltstack(uss, uoss, regs->regs[15]);
93} 95}
94 96
95 97
@@ -98,7 +100,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
98 */ 100 */
99 101
100#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ 102#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
101#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ 103#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
104#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */
105#else
106#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */
107#endif
102#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ 108#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
103 109
104struct sigframe 110struct sigframe
@@ -194,9 +200,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
194 200
195asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, 201asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
196 unsigned long r6, unsigned long r7, 202 unsigned long r6, unsigned long r7,
197 struct pt_regs regs) 203 struct pt_regs __regs)
198{ 204{
199 struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; 205 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
206 struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15];
200 sigset_t set; 207 sigset_t set;
201 int r0; 208 int r0;
202 209
@@ -216,7 +223,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
216 recalc_sigpending(); 223 recalc_sigpending();
217 spin_unlock_irq(&current->sighand->siglock); 224 spin_unlock_irq(&current->sighand->siglock);
218 225
219 if (restore_sigcontext(&regs, &frame->sc, &r0)) 226 if (restore_sigcontext(regs, &frame->sc, &r0))
220 goto badframe; 227 goto badframe;
221 return r0; 228 return r0;
222 229
@@ -227,9 +234,10 @@ badframe:
227 234
228asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, 235asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
229 unsigned long r6, unsigned long r7, 236 unsigned long r6, unsigned long r7,
230 struct pt_regs regs) 237 struct pt_regs __regs)
231{ 238{
232 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; 239 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
240 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
233 sigset_t set; 241 sigset_t set;
234 stack_t st; 242 stack_t st;
235 int r0; 243 int r0;
@@ -246,14 +254,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
246 recalc_sigpending(); 254 recalc_sigpending();
247 spin_unlock_irq(&current->sighand->siglock); 255 spin_unlock_irq(&current->sighand->siglock);
248 256
249 if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0)) 257 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
250 goto badframe; 258 goto badframe;
251 259
252 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) 260 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
253 goto badframe; 261 goto badframe;
254 /* It is more difficult to avoid calling this function than to 262 /* It is more difficult to avoid calling this function than to
255 call it and ignore errors. */ 263 call it and ignore errors. */
256 do_sigaltstack(&st, NULL, regs.regs[15]); 264 do_sigaltstack(&st, NULL, regs->regs[15]);
257 265
258 return r0; 266 return r0;
259 267
@@ -350,7 +358,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
350 } else { 358 } else {
351 /* Generate return code (system call to sigreturn) */ 359 /* Generate return code (system call to sigreturn) */
352 err |= __put_user(MOVW(7), &frame->retcode[0]); 360 err |= __put_user(MOVW(7), &frame->retcode[0]);
353 err |= __put_user(TRAP16, &frame->retcode[1]); 361 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
354 err |= __put_user(OR_R0_R0, &frame->retcode[2]); 362 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
355 err |= __put_user(OR_R0_R0, &frame->retcode[3]); 363 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
356 err |= __put_user(OR_R0_R0, &frame->retcode[4]); 364 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
@@ -430,7 +438,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
430 } else { 438 } else {
431 /* Generate return code (system call to rt_sigreturn) */ 439 /* Generate return code (system call to rt_sigreturn) */
432 err |= __put_user(MOVW(7), &frame->retcode[0]); 440 err |= __put_user(MOVW(7), &frame->retcode[0]);
433 err |= __put_user(TRAP16, &frame->retcode[1]); 441 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
434 err |= __put_user(OR_R0_R0, &frame->retcode[2]); 442 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
435 err |= __put_user(OR_R0_R0, &frame->retcode[3]); 443 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
436 err |= __put_user(OR_R0_R0, &frame->retcode[4]); 444 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
new file mode 100644
index 000000000000..0d5268afe80f
--- /dev/null
+++ b/arch/sh/kernel/stacktrace.c
@@ -0,0 +1,43 @@
1/*
2 * arch/sh/kernel/stacktrace.c
3 *
4 * Stack trace management functions
5 *
6 * Copyright (C) 2006 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/sched.h>
13#include <linux/stacktrace.h>
14#include <linux/thread_info.h>
15#include <asm/ptrace.h>
16
17/*
18 * Save stack-backtrace addresses into a stack_trace buffer.
19 */
20void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
21{
22 unsigned long *sp;
23
24 if (!task)
25 task = current;
26 if (task == current)
27 sp = (unsigned long *)current_stack_pointer;
28 else
29 sp = (unsigned long *)task->thread.sp;
30
31 while (!kstack_end(sp)) {
32 unsigned long addr = *sp++;
33
34 if (__kernel_text_address(addr)) {
35 if (trace->skip > 0)
36 trace->skip--;
37 else
38 trace->entries[trace->nr_entries++] = addr;
39 if (trace->nr_entries >= trace->max_entries)
40 break;
41 }
42 }
43}
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 8fde95001c34..5083b6ed4b39 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -33,14 +33,15 @@
33 */ 33 */
34asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, 34asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
35 unsigned long r6, unsigned long r7, 35 unsigned long r6, unsigned long r7,
36 struct pt_regs regs) 36 struct pt_regs __regs)
37{ 37{
38 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
38 int fd[2]; 39 int fd[2];
39 int error; 40 int error;
40 41
41 error = do_pipe(fd); 42 error = do_pipe(fd);
42 if (!error) { 43 if (!error) {
43 regs.regs[1] = fd[1]; 44 regs->regs[1] = fd[1];
44 return fd[0]; 45 return fd[0];
45 } 46 }
46 return error; 47 return error;
@@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
50 51
51EXPORT_SYMBOL(shm_align_mask); 52EXPORT_SYMBOL(shm_align_mask);
52 53
54#ifdef CONFIG_MMU
53/* 55/*
54 * To avoid cache aliases, we map the shared page with same color. 56 * To avoid cache aliases, we map the shared page with same color.
55 */ 57 */
@@ -135,6 +137,7 @@ full_search:
135 addr = COLOUR_ALIGN(addr, pgoff); 137 addr = COLOUR_ALIGN(addr, pgoff);
136 } 138 }
137} 139}
140#endif /* CONFIG_MMU */
138 141
139static inline long 142static inline long
140do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 143do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 57e708d7b52d..c206c9504c4b 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -13,6 +13,8 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/profile.h> 15#include <linux/profile.h>
16#include <linux/timex.h>
17#include <linux/sched.h>
16#include <asm/clock.h> 18#include <asm/clock.h>
17#include <asm/rtc.h> 19#include <asm/rtc.h>
18#include <asm/timer.h> 20#include <asm/timer.h>
@@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void)
50#ifndef CONFIG_GENERIC_TIME 52#ifndef CONFIG_GENERIC_TIME
51void do_gettimeofday(struct timeval *tv) 53void do_gettimeofday(struct timeval *tv)
52{ 54{
55 unsigned long flags;
53 unsigned long seq; 56 unsigned long seq;
54 unsigned long usec, sec; 57 unsigned long usec, sec;
55 58
56 do { 59 do {
57 seq = read_seqbegin(&xtime_lock); 60 /*
61 * Turn off IRQs when grabbing xtime_lock, so that
62 * the sys_timer get_offset code doesn't have to handle it.
63 */
64 seq = read_seqbegin_irqsave(&xtime_lock, flags);
58 usec = get_timer_offset(); 65 usec = get_timer_offset();
59 sec = xtime.tv_sec; 66 sec = xtime.tv_sec;
60 usec += xtime.tv_nsec / 1000; 67 usec += xtime.tv_nsec / NSEC_PER_USEC;
61 } while (read_seqretry(&xtime_lock, seq)); 68 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
62 69
63 while (usec >= 1000000) { 70 while (usec >= 1000000) {
64 usec -= 1000000; 71 usec -= 1000000;
@@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
85 * wall time. Discover what correction gettimeofday() would have 92 * wall time. Discover what correction gettimeofday() would have
86 * made, and then undo it! 93 * made, and then undo it!
87 */ 94 */
88 nsec -= 1000 * get_timer_offset(); 95 nsec -= get_timer_offset() * NSEC_PER_USEC;
89 96
90 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 97 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
91 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 98 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = {
169 .resume = timer_resume, 176 .resume = timer_resume,
170}; 177};
171 178
179#ifdef CONFIG_NO_IDLE_HZ
180static int timer_dyn_tick_enable(void)
181{
182 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
183 unsigned long flags;
184 int ret = -ENODEV;
185
186 if (dyn_tick) {
187 spin_lock_irqsave(&dyn_tick->lock, flags);
188 ret = 0;
189 if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
190 ret = dyn_tick->enable();
191
192 if (ret == 0)
193 dyn_tick->state |= DYN_TICK_ENABLED;
194 }
195 spin_unlock_irqrestore(&dyn_tick->lock, flags);
196 }
197
198 return ret;
199}
200
201static int timer_dyn_tick_disable(void)
202{
203 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
204 unsigned long flags;
205 int ret = -ENODEV;
206
207 if (dyn_tick) {
208 spin_lock_irqsave(&dyn_tick->lock, flags);
209 ret = 0;
210 if (dyn_tick->state & DYN_TICK_ENABLED) {
211 ret = dyn_tick->disable();
212
213 if (ret == 0)
214 dyn_tick->state &= ~DYN_TICK_ENABLED;
215 }
216 spin_unlock_irqrestore(&dyn_tick->lock, flags);
217 }
218
219 return ret;
220}
221
222/*
223 * Reprogram the system timer for at least the calculated time interval.
224 * This function should be called from the idle thread with IRQs disabled,
225 * immediately before sleeping.
226 */
227void timer_dyn_reprogram(void)
228{
229 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
230 unsigned long next, seq, flags;
231
232 if (!dyn_tick)
233 return;
234
235 spin_lock_irqsave(&dyn_tick->lock, flags);
236 if (dyn_tick->state & DYN_TICK_ENABLED) {
237 next = next_timer_interrupt();
238 do {
239 seq = read_seqbegin(&xtime_lock);
240 dyn_tick->reprogram(next - jiffies);
241 } while (read_seqretry(&xtime_lock, seq));
242 }
243 spin_unlock_irqrestore(&dyn_tick->lock, flags);
244}
245
246static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
247{
248 return sprintf(buf, "%i\n",
249 (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
250}
251
252static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
253 size_t count)
254{
255 unsigned int enable = simple_strtoul(buf, NULL, 2);
256
257 if (enable)
258 timer_dyn_tick_enable();
259 else
260 timer_dyn_tick_disable();
261
262 return count;
263}
264static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
265
266/*
267 * dyntick=enable|disable
268 */
269static char dyntick_str[4] __initdata = "";
270
271static int __init dyntick_setup(char *str)
272{
273 if (str)
274 strlcpy(dyntick_str, str, sizeof(dyntick_str));
275 return 1;
276}
277
278__setup("dyntick=", dyntick_setup);
279#endif
280
172static int __init timer_init_sysfs(void) 281static int __init timer_init_sysfs(void)
173{ 282{
174 int ret = sysdev_class_register(&timer_sysclass); 283 int ret = sysdev_class_register(&timer_sysclass);
@@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void)
176 return ret; 285 return ret;
177 286
178 sys_timer->dev.cls = &timer_sysclass; 287 sys_timer->dev.cls = &timer_sysclass;
179 return sysdev_register(&sys_timer->dev); 288 ret = sysdev_register(&sys_timer->dev);
289
290#ifdef CONFIG_NO_IDLE_HZ
291 if (ret == 0 && sys_timer->dyn_tick) {
292 ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
293
294 /*
295 * Turn on dynamic tick after calibrate delay
296 * for correct bogomips
297 */
298 if (ret == 0 && dyntick_str[0] == 'e')
299 ret = timer_dyn_tick_enable();
300 }
301#endif
302
303 return ret;
180} 304}
181device_initcall(timer_init_sysfs); 305device_initcall(timer_init_sysfs);
182 306
@@ -200,6 +324,11 @@ void __init time_init(void)
200 sys_timer = get_sys_timer(); 324 sys_timer = get_sys_timer();
201 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); 325 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
202 326
327#ifdef CONFIG_NO_IDLE_HZ
328 if (sys_timer->dyn_tick)
329 spin_lock_init(&sys_timer->dyn_tick->lock);
330#endif
331
203#if defined(CONFIG_SH_KGDB) 332#if defined(CONFIG_SH_KGDB)
204 /* 333 /*
205 * Set up kgdb as requested. We do it here because the serial 334 * Set up kgdb as requested. We do it here because the serial
diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile
index 151a6a304cec..bcf244ff6a12 100644
--- a/arch/sh/kernel/timers/Makefile
+++ b/arch/sh/kernel/timers/Makefile
@@ -5,4 +5,6 @@
5obj-y := timer.o 5obj-y := timer.o
6 6
7obj-$(CONFIG_SH_TMU) += timer-tmu.o 7obj-$(CONFIG_SH_TMU) += timer-tmu.o
8obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
9obj-$(CONFIG_SH_CMT) += timer-cmt.o
8 10
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c
new file mode 100644
index 000000000000..a574b93a4e7b
--- /dev/null
+++ b/arch/sh/kernel/timers/timer-cmt.c
@@ -0,0 +1,196 @@
1/*
2 * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
3 *
4 * Copyright (C) 2005 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/interrupt.h>
14#include <linux/seqlock.h>
15#include <asm/timer.h>
16#include <asm/rtc.h>
17#include <asm/io.h>
18#include <asm/irq.h>
19#include <asm/clock.h>
20
21#if defined(CONFIG_CPU_SUBTYPE_SH7619)
22#define CMT_CMSTR 0xf84a0070
23#define CMT_CMCSR_0 0xf84a0072
24#define CMT_CMCNT_0 0xf84a0074
25#define CMT_CMCOR_0 0xf84a0076
26#define CMT_CMCSR_1 0xf84a0078
27#define CMT_CMCNT_1 0xf84a007a
28#define CMT_CMCOR_1 0xf84a007c
29
30#define STBCR3 0xf80a0000
31#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
32#define CMT_CMCSR_INIT 0x0040
33#define CMT_CMCSR_CALIB 0x0000
34#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
35#define CMT_CMSTR 0xfffec000
36#define CMT_CMCSR_0 0xfffec002
37#define CMT_CMCNT_0 0xfffec004
38#define CMT_CMCOR_0 0xfffec006
39
40#define STBCR4 0xfffe040c
41#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
42#define CMT_CMCSR_INIT 0x0040
43#define CMT_CMCSR_CALIB 0x0000
44#else
45#error "Unknown CPU SUBTYPE"
46#endif
47
48static unsigned long cmt_timer_get_offset(void)
49{
50 int count;
51 static unsigned short count_p = 0xffff; /* for the first call after boot */
52 static unsigned long jiffies_p = 0;
53
54 /*
55 * cache volatile jiffies temporarily; we have IRQs turned off.
56 */
57 unsigned long jiffies_t;
58
59 /* timer count may underflow right here */
60 count = ctrl_inw(CMT_CMCOR_0);
61 count -= ctrl_inw(CMT_CMCNT_0);
62
63 jiffies_t = jiffies;
64
65 /*
66 * avoiding timer inconsistencies (they are rare, but they happen)...
67 * there is one kind of problem that must be avoided here:
68 * 1. the timer counter underflows
69 */
70
71 if (jiffies_t == jiffies_p) {
72 if (count > count_p) {
73 /* the nutcase */
74 if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
75 count -= LATCH;
76 } else {
77 printk("%s (): hardware timer problem?\n",
78 __FUNCTION__);
79 }
80 }
81 } else
82 jiffies_p = jiffies_t;
83
84 count_p = count;
85
86 count = ((LATCH-1) - count) * TICK_SIZE;
87 count = (count + LATCH/2) / LATCH;
88
89 return count;
90}
91
92static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
93{
94 unsigned long timer_status;
95
96 /* Clear CMF bit */
97 timer_status = ctrl_inw(CMT_CMCSR_0);
98 timer_status &= ~0x80;
99 ctrl_outw(timer_status, CMT_CMCSR_0);
100
101 /*
102 * Here we are in the timer irq handler. We just have irqs locally
103 * disabled but we don't know if the timer_bh is running on the other
104 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
105 * the irq version of write_lock because as just said we have irq
106 * locally disabled. -arca
107 */
108 write_seqlock(&xtime_lock);
109 handle_timer_tick();
110 write_sequnlock(&xtime_lock);
111
112 return IRQ_HANDLED;
113}
114
115static struct irqaction cmt_irq = {
116 .name = "timer",
117 .handler = cmt_timer_interrupt,
118 .flags = IRQF_DISABLED | IRQF_TIMER,
119 .mask = CPU_MASK_NONE,
120};
121
122static void cmt_clk_init(struct clk *clk)
123{
124 u8 divisor = CMT_CMCSR_INIT & 0x3;
125 ctrl_inw(CMT_CMCSR_0);
126 ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
127 clk->parent = clk_get(NULL, "module_clk");
128 clk->rate = clk->parent->rate / (8 << (divisor << 1));
129}
130
131static void cmt_clk_recalc(struct clk *clk)
132{
133 u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
134 clk->rate = clk->parent->rate / (8 << (divisor << 1));
135}
136
137static struct clk_ops cmt_clk_ops = {
138 .init = cmt_clk_init,
139 .recalc = cmt_clk_recalc,
140};
141
142static struct clk cmt0_clk = {
143 .name = "cmt0_clk",
144 .ops = &cmt_clk_ops,
145};
146
147static int cmt_timer_start(void)
148{
149 ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
150 return 0;
151}
152
153static int cmt_timer_stop(void)
154{
155 ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
156 return 0;
157}
158
159static int cmt_timer_init(void)
160{
161 unsigned long interval;
162
163 cmt_clock_enable();
164
165 setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
166
167 cmt0_clk.parent = clk_get(NULL, "module_clk");
168
169 cmt_timer_stop();
170
171 interval = cmt0_clk.parent->rate / 8 / HZ;
172 printk(KERN_INFO "Interval = %ld\n", interval);
173
174 ctrl_outw(interval, CMT_CMCOR_0);
175
176 clk_register(&cmt0_clk);
177 clk_enable(&cmt0_clk);
178
179 cmt_timer_start();
180
181 return 0;
182}
183
184struct sys_timer_ops cmt_timer_ops = {
185 .init = cmt_timer_init,
186 .start = cmt_timer_start,
187 .stop = cmt_timer_stop,
188#ifndef CONFIG_GENERIC_TIME
189 .get_offset = cmt_timer_get_offset,
190#endif
191};
192
193struct sys_timer cmt_timer = {
194 .name = "cmt",
195 .ops = &cmt_timer_ops,
196};
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
new file mode 100644
index 000000000000..fffcd1c09873
--- /dev/null
+++ b/arch/sh/kernel/timers/timer-mtu2.c
@@ -0,0 +1,200 @@
1/*
2 * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
3 *
4 * Copyright (C) 2005 Paul Mundt
5 *
6 * Based off of arch/sh/kernel/timers/timer-tmu.c
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/seqlock.h>
16#include <asm/timer.h>
17#include <asm/io.h>
18#include <asm/irq.h>
19#include <asm/clock.h>
20
21/*
22 * We use channel 1 for our lowly system timer. Channel 2 would be the other
23 * likely candidate, but we leave it alone as it has higher divisors that
24 * would be of more use to other more interesting applications.
25 *
26 * TODO: Presently we only implement a 16-bit single-channel system timer.
27 * However, we can implement channel cascade if we go the overflow route and
28 * get away with using 2 MTU2 channels as a 32-bit timer.
29 */
30#define MTU2_TSTR 0xfffe4280
31#define MTU2_TCR_1 0xfffe4380
32#define MTU2_TMDR_1 0xfffe4381
33#define MTU2_TIOR_1 0xfffe4382
34#define MTU2_TIER_1 0xfffe4384
35#define MTU2_TSR_1 0xfffe4385
36#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */
37#define MTU2_TGRA_1 0xfffe438a
38
39#define STBCR3 0xfffe0408
40
41#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */
42
43#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */
44
45#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */
46
47#define MTU2_TCR_INIT 0x22
48
49#define MTU2_TCR_CALIB 0x00
50
51static unsigned long mtu2_timer_get_offset(void)
52{
53 int count;
54 static int count_p = 0x7fff; /* for the first call after boot */
55 static unsigned long jiffies_p = 0;
56
57 /*
58 * cache volatile jiffies temporarily; we have IRQs turned off.
59 */
60 unsigned long jiffies_t;
61
62 /* timer count may underflow right here */
63 count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */
64
65 jiffies_t = jiffies;
66
67 /*
68 * avoiding timer inconsistencies (they are rare, but they happen)...
69 * there is one kind of problem that must be avoided here:
70 * 1. the timer counter underflows
71 */
72
73 if (jiffies_t == jiffies_p) {
74 if (count > count_p) {
75 if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
76 count -= LATCH;
77 } else {
78 printk("%s (): hardware timer problem?\n",
79 __FUNCTION__);
80 }
81 }
82 } else
83 jiffies_p = jiffies_t;
84
85 count_p = count;
86
87 count = ((LATCH-1) - count) * TICK_SIZE;
88 count = (count + LATCH/2) / LATCH;
89
90 return count;
91}
92
93static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
94{
95 unsigned long timer_status;
96
97 /* Clear TGFA bit */
98 timer_status = ctrl_inb(MTU2_TSR_1);
99 timer_status &= ~MTU2_TSR_TGFA;
100 ctrl_outb(timer_status, MTU2_TSR_1);
101
102 /* Do timer tick */
103 write_seqlock(&xtime_lock);
104 handle_timer_tick();
105 write_sequnlock(&xtime_lock);
106
107 return IRQ_HANDLED;
108}
109
110static struct irqaction mtu2_irq = {
111 .name = "timer",
112 .handler = mtu2_timer_interrupt,
113 .flags = IRQF_DISABLED | IRQF_TIMER,
114 .mask = CPU_MASK_NONE,
115};
116
117static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
118
119static void mtu2_clk_init(struct clk *clk)
120{
121 u8 idx = MTU2_TCR_INIT & 0x7;
122
123 clk->rate = clk->parent->rate / divisors[idx];
124 /* Start TCNT counting */
125 ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
126
127}
128
129static void mtu2_clk_recalc(struct clk *clk)
130{
131 u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
132 clk->rate = clk->parent->rate / divisors[idx];
133}
134
135static struct clk_ops mtu2_clk_ops = {
136 .init = mtu2_clk_init,
137 .recalc = mtu2_clk_recalc,
138};
139
140static struct clk mtu2_clk1 = {
141 .name = "mtu2_clk1",
142 .ops = &mtu2_clk_ops,
143};
144
145static int mtu2_timer_start(void)
146{
147 ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
148 return 0;
149}
150
151static int mtu2_timer_stop(void)
152{
153 ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
154 return 0;
155}
156
157static int mtu2_timer_init(void)
158{
159 u8 tmp;
160 unsigned long interval;
161
162 setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
163
164 mtu2_clk1.parent = clk_get(NULL, "module_clk");
165
166 ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
167
168 /* Normal operation */
169 ctrl_outb(0, MTU2_TMDR_1);
170 ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
171 ctrl_outb(0x01, MTU2_TIOR_1);
172
173 /* Enable underflow interrupt */
174 ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
175
176 interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
177 printk(KERN_INFO "Interval = %ld\n", interval);
178
179 ctrl_outw(interval, MTU2_TGRA_1);
180 ctrl_outw(0, MTU2_TCNT_1);
181
182 clk_register(&mtu2_clk1);
183 clk_enable(&mtu2_clk1);
184
185 return 0;
186}
187
188struct sys_timer_ops mtu2_timer_ops = {
189 .init = mtu2_timer_init,
190 .start = mtu2_timer_start,
191 .stop = mtu2_timer_stop,
192#ifndef CONFIG_GENERIC_TIME
193 .get_offset = mtu2_timer_get_offset,
194#endif
195};
196
197struct sys_timer mtu2_timer = {
198 .name = "mtu2",
199 .ops = &mtu2_timer_ops,
200};
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 24927015dc31..e060e71d0785 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -17,7 +17,6 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/spinlock.h>
21#include <linux/seqlock.h> 20#include <linux/seqlock.h>
22#include <asm/timer.h> 21#include <asm/timer.h>
23#include <asm/rtc.h> 22#include <asm/rtc.h>
@@ -31,13 +30,9 @@
31 30
32#define TMU0_TCR_CALIB 0x0000 31#define TMU0_TCR_CALIB 0x0000
33 32
34static DEFINE_SPINLOCK(tmu0_lock);
35
36static unsigned long tmu_timer_get_offset(void) 33static unsigned long tmu_timer_get_offset(void)
37{ 34{
38 int count; 35 int count;
39 unsigned long flags;
40
41 static int count_p = 0x7fffffff; /* for the first call after boot */ 36 static int count_p = 0x7fffffff; /* for the first call after boot */
42 static unsigned long jiffies_p = 0; 37 static unsigned long jiffies_p = 0;
43 38
@@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void)
46 */ 41 */
47 unsigned long jiffies_t; 42 unsigned long jiffies_t;
48 43
49 spin_lock_irqsave(&tmu0_lock, flags);
50 /* timer count may underflow right here */ 44 /* timer count may underflow right here */
51 count = ctrl_inl(TMU0_TCNT); /* read the latched count */ 45 count = ctrl_inl(TMU0_TCNT); /* read the latched count */
52 46
@@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void)
72 jiffies_p = jiffies_t; 66 jiffies_p = jiffies_t;
73 67
74 count_p = count; 68 count_p = count;
75 spin_unlock_irqrestore(&tmu0_lock, flags);
76 69
77 count = ((LATCH-1) - count) * TICK_SIZE; 70 count = ((LATCH-1) - count) * TICK_SIZE;
78 count = (count + LATCH/2) / LATCH; 71 count = (count + LATCH/2) / LATCH;
@@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
106static struct irqaction tmu_irq = { 99static struct irqaction tmu_irq = {
107 .name = "timer", 100 .name = "timer",
108 .handler = tmu_timer_interrupt, 101 .handler = tmu_timer_interrupt,
109 .flags = IRQF_DISABLED, 102 .flags = IRQF_DISABLED | IRQF_TIMER,
110 .mask = CPU_MASK_NONE, 103 .mask = CPU_MASK_NONE,
111}; 104};
112 105
@@ -149,9 +142,9 @@ static int tmu_timer_init(void)
149{ 142{
150 unsigned long interval; 143 unsigned long interval;
151 144
152 setup_irq(TIMER_IRQ, &tmu_irq); 145 setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
153 146
154 tmu0_clk.parent = clk_get("module_clk"); 147 tmu0_clk.parent = clk_get(NULL, "module_clk");
155 148
156 /* Start TMU0 */ 149 /* Start TMU0 */
157 tmu_timer_stop(); 150 tmu_timer_stop();
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index dc1f631053a8..a6bcc913d25e 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -17,6 +17,12 @@ static struct sys_timer *sys_timers[] __initdata = {
17#ifdef CONFIG_SH_TMU 17#ifdef CONFIG_SH_TMU
18 &tmu_timer, 18 &tmu_timer,
19#endif 19#endif
20#ifdef CONFIG_SH_MTU2
21 &mtu2_timer,
22#endif
23#ifdef CONFIG_SH_CMT
24 &cmt_timer,
25#endif
20 NULL, 26 NULL,
21}; 27};
22 28
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 53dfa55f3156..3762d9dc2046 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -18,13 +18,14 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/kallsyms.h> 19#include <linux/kallsyms.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/debug_locks.h>
21#include <asm/system.h> 22#include <asm/system.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
24#ifdef CONFIG_SH_KGDB 25#ifdef CONFIG_SH_KGDB
25#include <asm/kgdb.h> 26#include <asm/kgdb.h>
26#define CHK_REMOTE_DEBUG(regs) \ 27#define CHK_REMOTE_DEBUG(regs) \
27{ \ 28{ \
28 if (kgdb_debug_hook && !user_mode(regs))\ 29 if (kgdb_debug_hook && !user_mode(regs))\
29 (*kgdb_debug_hook)(regs); \ 30 (*kgdb_debug_hook)(regs); \
30} 31}
@@ -33,8 +34,13 @@
33#endif 34#endif
34 35
35#ifdef CONFIG_CPU_SH2 36#ifdef CONFIG_CPU_SH2
36#define TRAP_RESERVED_INST 4 37# define TRAP_RESERVED_INST 4
37#define TRAP_ILLEGAL_SLOT_INST 6 38# define TRAP_ILLEGAL_SLOT_INST 6
39# define TRAP_ADDRESS_ERROR 9
40# ifdef CONFIG_CPU_SH2A
41# define TRAP_DIVZERO_ERROR 17
42# define TRAP_DIVOVF_ERROR 18
43# endif
38#else 44#else
39#define TRAP_RESERVED_INST 12 45#define TRAP_RESERVED_INST 12
40#define TRAP_ILLEGAL_SLOT_INST 13 46#define TRAP_ILLEGAL_SLOT_INST 13
@@ -88,7 +94,7 @@ void die(const char * str, struct pt_regs * regs, long err)
88 94
89 if (!user_mode(regs) || in_interrupt()) 95 if (!user_mode(regs) || in_interrupt())
90 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + 96 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
91 (unsigned long)task_stack_page(current)); 97 (unsigned long)task_stack_page(current));
92 98
93 bust_spinlocks(0); 99 bust_spinlocks(0);
94 spin_unlock_irq(&die_lock); 100 spin_unlock_irq(&die_lock);
@@ -102,8 +108,6 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
102 die(str, regs, err); 108 die(str, regs, err);
103} 109}
104 110
105static int handle_unaligned_notify_count = 10;
106
107/* 111/*
108 * try and fix up kernelspace address errors 112 * try and fix up kernelspace address errors
109 * - userspace errors just cause EFAULT to be returned, resulting in SEGV 113 * - userspace errors just cause EFAULT to be returned, resulting in SEGV
@@ -198,7 +202,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
198 if (copy_to_user(dst,src,4)) 202 if (copy_to_user(dst,src,4))
199 goto fetch_fault; 203 goto fetch_fault;
200 ret = 0; 204 ret = 0;
201 break; 205 break;
202 206
203 case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ 207 case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
204 if (instruction & 4) 208 if (instruction & 4)
@@ -222,7 +226,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
222 if (copy_from_user(dst,src,4)) 226 if (copy_from_user(dst,src,4))
223 goto fetch_fault; 227 goto fetch_fault;
224 ret = 0; 228 ret = 0;
225 break; 229 break;
226 230
227 case 6: /* mov.[bwl] from memory, possibly with post-increment */ 231 case 6: /* mov.[bwl] from memory, possibly with post-increment */
228 src = (unsigned char*) *rm; 232 src = (unsigned char*) *rm;
@@ -230,7 +234,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
230 *rm += count; 234 *rm += count;
231 dst = (unsigned char*) rn; 235 dst = (unsigned char*) rn;
232 *(unsigned long*)dst = 0; 236 *(unsigned long*)dst = 0;
233 237
234#ifdef __LITTLE_ENDIAN__ 238#ifdef __LITTLE_ENDIAN__
235 if (copy_from_user(dst, src, count)) 239 if (copy_from_user(dst, src, count))
236 goto fetch_fault; 240 goto fetch_fault;
@@ -241,7 +245,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
241 } 245 }
242#else 246#else
243 dst += 4-count; 247 dst += 4-count;
244 248
245 if (copy_from_user(dst, src, count)) 249 if (copy_from_user(dst, src, count))
246 goto fetch_fault; 250 goto fetch_fault;
247 251
@@ -320,7 +324,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
320 return -EFAULT; 324 return -EFAULT;
321 325
322 /* kernel */ 326 /* kernel */
323 die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); 327 die("delay-slot-insn faulting in handle_unaligned_delayslot",
328 regs, 0);
324 } 329 }
325 330
326 return handle_unaligned_ins(instruction,regs); 331 return handle_unaligned_ins(instruction,regs);
@@ -342,6 +347,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
342#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) 347#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
343#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) 348#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
344 349
350/*
351 * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
352 * opcodes..
353 */
354#ifndef CONFIG_CPU_SH2A
355static int handle_unaligned_notify_count = 10;
356
345static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) 357static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
346{ 358{
347 u_int rm; 359 u_int rm;
@@ -354,7 +366,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
354 if (user_mode(regs) && handle_unaligned_notify_count>0) { 366 if (user_mode(regs) && handle_unaligned_notify_count>0) {
355 handle_unaligned_notify_count--; 367 handle_unaligned_notify_count--;
356 368
357 printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", 369 printk(KERN_NOTICE "Fixing up unaligned userspace access "
370 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
358 current->comm,current->pid,(u16*)regs->pc,instruction); 371 current->comm,current->pid,(u16*)regs->pc,instruction);
359 } 372 }
360 373
@@ -478,32 +491,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
478 regs->pc += 2; 491 regs->pc += 2;
479 return ret; 492 return ret;
480} 493}
494#endif /* CONFIG_CPU_SH2A */
495
496#ifdef CONFIG_CPU_HAS_SR_RB
497#define lookup_exception_vector(x) \
498 __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x)))
499#else
500#define lookup_exception_vector(x) \
501 __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x)))
502#endif
481 503
482/* 504/*
483 * Handle various address error exceptions 505 * Handle various address error exceptions:
506 * - instruction address error:
507 * misaligned PC
508 * PC >= 0x80000000 in user mode
509 * - data address error (read and write)
510 * misaligned data access
511 * access to >= 0x80000000 is user mode
512 * Unfortuntaly we can't distinguish between instruction address error
513 * and data address errors caused by read acceses.
484 */ 514 */
485asmlinkage void do_address_error(struct pt_regs *regs, 515asmlinkage void do_address_error(struct pt_regs *regs,
486 unsigned long writeaccess, 516 unsigned long writeaccess,
487 unsigned long address) 517 unsigned long address)
488{ 518{
489 unsigned long error_code; 519 unsigned long error_code = 0;
490 mm_segment_t oldfs; 520 mm_segment_t oldfs;
521 siginfo_t info;
522#ifndef CONFIG_CPU_SH2A
491 u16 instruction; 523 u16 instruction;
492 int tmp; 524 int tmp;
525#endif
493 526
494 asm volatile("stc r2_bank,%0": "=r" (error_code)); 527 /* Intentional ifdef */
528#ifdef CONFIG_CPU_HAS_SR_RB
529 lookup_exception_vector(error_code);
530#endif
495 531
496 oldfs = get_fs(); 532 oldfs = get_fs();
497 533
498 if (user_mode(regs)) { 534 if (user_mode(regs)) {
535 int si_code = BUS_ADRERR;
536
499 local_irq_enable(); 537 local_irq_enable();
500 current->thread.error_code = error_code;
501 current->thread.trap_no = (writeaccess) ? 8 : 7;
502 538
503 /* bad PC is not something we can fix */ 539 /* bad PC is not something we can fix */
504 if (regs->pc & 1) 540 if (regs->pc & 1) {
541 si_code = BUS_ADRALN;
505 goto uspace_segv; 542 goto uspace_segv;
543 }
506 544
545#ifndef CONFIG_CPU_SH2A
507 set_fs(USER_DS); 546 set_fs(USER_DS);
508 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { 547 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
509 /* Argh. Fault on the instruction itself. 548 /* Argh. Fault on the instruction itself.
@@ -518,14 +557,23 @@ asmlinkage void do_address_error(struct pt_regs *regs,
518 557
519 if (tmp==0) 558 if (tmp==0)
520 return; /* sorted */ 559 return; /* sorted */
560#endif
521 561
522 uspace_segv: 562uspace_segv:
523 printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); 563 printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
524 force_sig(SIGSEGV, current); 564 "access (PC %lx PR %lx)\n", current->comm, regs->pc,
565 regs->pr);
566
567 info.si_signo = SIGBUS;
568 info.si_errno = 0;
569 info.si_code = si_code;
570 info.si_addr = (void *) address;
571 force_sig_info(SIGBUS, &info, current);
525 } else { 572 } else {
526 if (regs->pc & 1) 573 if (regs->pc & 1)
527 die("unaligned program counter", regs, error_code); 574 die("unaligned program counter", regs, error_code);
528 575
576#ifndef CONFIG_CPU_SH2A
529 set_fs(KERNEL_DS); 577 set_fs(KERNEL_DS);
530 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { 578 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
531 /* Argh. Fault on the instruction itself. 579 /* Argh. Fault on the instruction itself.
@@ -537,6 +585,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
537 585
538 handle_unaligned_access(instruction, regs); 586 handle_unaligned_access(instruction, regs);
539 set_fs(oldfs); 587 set_fs(oldfs);
588#else
589 printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
590 "access\n", current->comm);
591
592 force_sig(SIGSEGV, current);
593#endif
540 } 594 }
541} 595}
542 596
@@ -548,7 +602,7 @@ int is_dsp_inst(struct pt_regs *regs)
548{ 602{
549 unsigned short inst; 603 unsigned short inst;
550 604
551 /* 605 /*
552 * Safe guard if DSP mode is already enabled or we're lacking 606 * Safe guard if DSP mode is already enabled or we're lacking
553 * the DSP altogether. 607 * the DSP altogether.
554 */ 608 */
@@ -569,27 +623,49 @@ int is_dsp_inst(struct pt_regs *regs)
569#define is_dsp_inst(regs) (0) 623#define is_dsp_inst(regs) (0)
570#endif /* CONFIG_SH_DSP */ 624#endif /* CONFIG_SH_DSP */
571 625
626#ifdef CONFIG_CPU_SH2A
627asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
628 unsigned long r6, unsigned long r7,
629 struct pt_regs __regs)
630{
631 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
632 siginfo_t info;
633
634 switch (r4) {
635 case TRAP_DIVZERO_ERROR:
636 info.si_code = FPE_INTDIV;
637 break;
638 case TRAP_DIVOVF_ERROR:
639 info.si_code = FPE_INTOVF;
640 break;
641 }
642
643 force_sig_info(SIGFPE, &info, current);
644}
645#endif
646
572/* arch/sh/kernel/cpu/sh4/fpu.c */ 647/* arch/sh/kernel/cpu/sh4/fpu.c */
573extern int do_fpu_inst(unsigned short, struct pt_regs *); 648extern int do_fpu_inst(unsigned short, struct pt_regs *);
574extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, 649extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
575 unsigned long r6, unsigned long r7, struct pt_regs regs); 650 unsigned long r6, unsigned long r7, struct pt_regs __regs);
576 651
577asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, 652asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
578 unsigned long r6, unsigned long r7, 653 unsigned long r6, unsigned long r7,
579 struct pt_regs regs) 654 struct pt_regs __regs)
580{ 655{
656 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
581 unsigned long error_code; 657 unsigned long error_code;
582 struct task_struct *tsk = current; 658 struct task_struct *tsk = current;
583 659
584#ifdef CONFIG_SH_FPU_EMU 660#ifdef CONFIG_SH_FPU_EMU
585 unsigned short inst; 661 unsigned short inst = 0;
586 int err; 662 int err;
587 663
588 get_user(inst, (unsigned short*)regs.pc); 664 get_user(inst, (unsigned short*)regs->pc);
589 665
590 err = do_fpu_inst(inst, &regs); 666 err = do_fpu_inst(inst, regs);
591 if (!err) { 667 if (!err) {
592 regs.pc += 2; 668 regs->pc += 2;
593 return; 669 return;
594 } 670 }
595 /* not a FPU inst. */ 671 /* not a FPU inst. */
@@ -597,20 +673,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
597 673
598#ifdef CONFIG_SH_DSP 674#ifdef CONFIG_SH_DSP
599 /* Check if it's a DSP instruction */ 675 /* Check if it's a DSP instruction */
600 if (is_dsp_inst(&regs)) { 676 if (is_dsp_inst(regs)) {
601 /* Enable DSP mode, and restart instruction. */ 677 /* Enable DSP mode, and restart instruction. */
602 regs.sr |= SR_DSP; 678 regs->sr |= SR_DSP;
603 return; 679 return;
604 } 680 }
605#endif 681#endif
606 682
607 asm volatile("stc r2_bank, %0": "=r" (error_code)); 683 lookup_exception_vector(error_code);
684
608 local_irq_enable(); 685 local_irq_enable();
609 tsk->thread.error_code = error_code; 686 CHK_REMOTE_DEBUG(regs);
610 tsk->thread.trap_no = TRAP_RESERVED_INST;
611 CHK_REMOTE_DEBUG(&regs);
612 force_sig(SIGILL, tsk); 687 force_sig(SIGILL, tsk);
613 die_if_no_fixup("reserved instruction", &regs, error_code); 688 die_if_no_fixup("reserved instruction", regs, error_code);
614} 689}
615 690
616#ifdef CONFIG_SH_FPU_EMU 691#ifdef CONFIG_SH_FPU_EMU
@@ -658,39 +733,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs)
658 733
659asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, 734asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
660 unsigned long r6, unsigned long r7, 735 unsigned long r6, unsigned long r7,
661 struct pt_regs regs) 736 struct pt_regs __regs)
662{ 737{
738 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
663 unsigned long error_code; 739 unsigned long error_code;
664 struct task_struct *tsk = current; 740 struct task_struct *tsk = current;
665#ifdef CONFIG_SH_FPU_EMU 741#ifdef CONFIG_SH_FPU_EMU
666 unsigned short inst; 742 unsigned short inst = 0;
667 743
668 get_user(inst, (unsigned short *)regs.pc + 1); 744 get_user(inst, (unsigned short *)regs->pc + 1);
669 if (!do_fpu_inst(inst, &regs)) { 745 if (!do_fpu_inst(inst, regs)) {
670 get_user(inst, (unsigned short *)regs.pc); 746 get_user(inst, (unsigned short *)regs->pc);
671 if (!emulate_branch(inst, &regs)) 747 if (!emulate_branch(inst, regs))
672 return; 748 return;
673 /* fault in branch.*/ 749 /* fault in branch.*/
674 } 750 }
675 /* not a FPU inst. */ 751 /* not a FPU inst. */
676#endif 752#endif
677 753
678 asm volatile("stc r2_bank, %0": "=r" (error_code)); 754 lookup_exception_vector(error_code);
755
679 local_irq_enable(); 756 local_irq_enable();
680 tsk->thread.error_code = error_code; 757 CHK_REMOTE_DEBUG(regs);
681 tsk->thread.trap_no = TRAP_RESERVED_INST;
682 CHK_REMOTE_DEBUG(&regs);
683 force_sig(SIGILL, tsk); 758 force_sig(SIGILL, tsk);
684 die_if_no_fixup("illegal slot instruction", &regs, error_code); 759 die_if_no_fixup("illegal slot instruction", regs, error_code);
685} 760}
686 761
687asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, 762asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
688 unsigned long r6, unsigned long r7, 763 unsigned long r6, unsigned long r7,
689 struct pt_regs regs) 764 struct pt_regs __regs)
690{ 765{
766 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
691 long ex; 767 long ex;
692 asm volatile("stc r2_bank, %0" : "=r" (ex)); 768
693 die_if_kernel("exception", &regs, ex); 769 lookup_exception_vector(ex);
770 die_if_kernel("exception", regs, ex);
694} 771}
695 772
696#if defined(CONFIG_SH_STANDARD_BIOS) 773#if defined(CONFIG_SH_STANDARD_BIOS)
@@ -735,12 +812,16 @@ void *set_exception_table_vec(unsigned int vec, void *handler)
735{ 812{
736 extern void *exception_handling_table[]; 813 extern void *exception_handling_table[];
737 void *old_handler; 814 void *old_handler;
738 815
739 old_handler = exception_handling_table[vec]; 816 old_handler = exception_handling_table[vec];
740 exception_handling_table[vec] = handler; 817 exception_handling_table[vec] = handler;
741 return old_handler; 818 return old_handler;
742} 819}
743 820
821extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5,
822 unsigned long r6, unsigned long r7,
823 struct pt_regs __regs);
824
744void __init trap_init(void) 825void __init trap_init(void)
745{ 826{
746 set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); 827 set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
@@ -759,7 +840,15 @@ void __init trap_init(void)
759 set_exception_table_evt(0x800, do_fpu_state_restore); 840 set_exception_table_evt(0x800, do_fpu_state_restore);
760 set_exception_table_evt(0x820, do_fpu_state_restore); 841 set_exception_table_evt(0x820, do_fpu_state_restore);
761#endif 842#endif
762 843
844#ifdef CONFIG_CPU_SH2
845 set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler);
846#endif
847#ifdef CONFIG_CPU_SH2A
848 set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
849 set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
850#endif
851
763 /* Setup VBR for boot cpu */ 852 /* Setup VBR for boot cpu */
764 per_cpu_trap_init(); 853 per_cpu_trap_init();
765} 854}
@@ -784,6 +873,11 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
784 } 873 }
785 874
786 printk("\n"); 875 printk("\n");
876
877 if (!tsk)
878 tsk = current;
879
880 debug_show_held_locks(tsk);
787} 881}
788 882
789void show_stack(struct task_struct *tsk, unsigned long *sp) 883void show_stack(struct task_struct *tsk, unsigned long *sp)
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 9dd606464d23..4e0362f50384 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -4,8 +4,12 @@ menu "Processor selection"
4# Processor families 4# Processor families
5# 5#
6config CPU_SH2 6config CPU_SH2
7 select SH_WRITETHROUGH if !CPU_SH2A
7 bool 8 bool
8 select SH_WRITETHROUGH 9
10config CPU_SH2A
11 bool
12 select CPU_SH2
9 13
10config CPU_SH3 14config CPU_SH3
11 bool 15 bool
@@ -16,6 +20,7 @@ config CPU_SH4
16 bool 20 bool
17 select CPU_HAS_INTEVT 21 select CPU_HAS_INTEVT
18 select CPU_HAS_SR_RB 22 select CPU_HAS_SR_RB
23 select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
19 24
20config CPU_SH4A 25config CPU_SH4A
21 bool 26 bool
@@ -40,6 +45,16 @@ config CPU_SUBTYPE_SH7604
40 bool "Support SH7604 processor" 45 bool "Support SH7604 processor"
41 select CPU_SH2 46 select CPU_SH2
42 47
48config CPU_SUBTYPE_SH7619
49 bool "Support SH7619 processor"
50 select CPU_SH2
51
52comment "SH-2A Processor Support"
53
54config CPU_SUBTYPE_SH7206
55 bool "Support SH7206 processor"
56 select CPU_SH2A
57
43comment "SH-3 Processor Support" 58comment "SH-3 Processor Support"
44 59
45config CPU_SUBTYPE_SH7300 60config CPU_SUBTYPE_SH7300
@@ -89,6 +104,7 @@ comment "SH-4 Processor Support"
89config CPU_SUBTYPE_SH7750 104config CPU_SUBTYPE_SH7750
90 bool "Support SH7750 processor" 105 bool "Support SH7750 processor"
91 select CPU_SH4 106 select CPU_SH4
107 select CPU_HAS_IPR_IRQ
92 help 108 help
93 Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. 109 Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
94 110
@@ -104,15 +120,18 @@ config CPU_SUBTYPE_SH7750R
104 bool "Support SH7750R processor" 120 bool "Support SH7750R processor"
105 select CPU_SH4 121 select CPU_SH4
106 select CPU_SUBTYPE_SH7750 122 select CPU_SUBTYPE_SH7750
123 select CPU_HAS_IPR_IRQ
107 124
108config CPU_SUBTYPE_SH7750S 125config CPU_SUBTYPE_SH7750S
109 bool "Support SH7750S processor" 126 bool "Support SH7750S processor"
110 select CPU_SH4 127 select CPU_SH4
111 select CPU_SUBTYPE_SH7750 128 select CPU_SUBTYPE_SH7750
129 select CPU_HAS_IPR_IRQ
112 130
113config CPU_SUBTYPE_SH7751 131config CPU_SUBTYPE_SH7751
114 bool "Support SH7751 processor" 132 bool "Support SH7751 processor"
115 select CPU_SH4 133 select CPU_SH4
134 select CPU_HAS_IPR_IRQ
116 help 135 help
117 Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, 136 Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
118 or if you have a HD6417751R CPU. 137 or if you have a HD6417751R CPU.
@@ -121,6 +140,7 @@ config CPU_SUBTYPE_SH7751R
121 bool "Support SH7751R processor" 140 bool "Support SH7751R processor"
122 select CPU_SH4 141 select CPU_SH4
123 select CPU_SUBTYPE_SH7751 142 select CPU_SUBTYPE_SH7751
143 select CPU_HAS_IPR_IRQ
124 144
125config CPU_SUBTYPE_SH7760 145config CPU_SUBTYPE_SH7760
126 bool "Support SH7760 processor" 146 bool "Support SH7760 processor"
@@ -157,6 +177,11 @@ config CPU_SUBTYPE_SH7780
157 select CPU_SH4A 177 select CPU_SH4A
158 select CPU_HAS_INTC2_IRQ 178 select CPU_HAS_INTC2_IRQ
159 179
180config CPU_SUBTYPE_SH7785
181 bool "Support SH7785 processor"
182 select CPU_SH4A
183 select CPU_HAS_INTC2_IRQ
184
160comment "SH4AL-DSP Processor Support" 185comment "SH4AL-DSP Processor Support"
161 186
162config CPU_SUBTYPE_SH73180 187config CPU_SUBTYPE_SH73180
@@ -216,13 +241,22 @@ config MEMORY_SIZE
216 241
217config 32BIT 242config 32BIT
218 bool "Support 32-bit physical addressing through PMB" 243 bool "Support 32-bit physical addressing through PMB"
219 depends on CPU_SH4A && MMU 244 depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
220 default y 245 default y
221 help 246 help
222 If you say Y here, physical addressing will be extended to 247 If you say Y here, physical addressing will be extended to
223 32-bits through the SH-4A PMB. If this is not set, legacy 248 32-bits through the SH-4A PMB. If this is not set, legacy
224 29-bit physical addressing will be used. 249 29-bit physical addressing will be used.
225 250
251config X2TLB
252 bool "Enable extended TLB mode"
253 depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
254 help
255 Selecting this option will enable the extended mode of the SH-X2
256 TLB. For legacy SH-X behaviour and interoperability, say N. For
257 all of the fun new features and a willingless to submit bug reports,
258 say Y.
259
226config VSYSCALL 260config VSYSCALL
227 bool "Support vsyscall page" 261 bool "Support vsyscall page"
228 depends on MMU 262 depends on MMU
@@ -237,16 +271,52 @@ config VSYSCALL
237 (the default value) say Y. 271 (the default value) say Y.
238 272
239choice 273choice
274 prompt "Kernel page size"
275 default PAGE_SIZE_4KB
276
277config PAGE_SIZE_4KB
278 bool "4kB"
279 help
280 This is the default page size used by all SuperH CPUs.
281
282config PAGE_SIZE_8KB
283 bool "8kB"
284 depends on EXPERIMENTAL && X2TLB
285 help
286 This enables 8kB pages as supported by SH-X2 and later MMUs.
287
288config PAGE_SIZE_64KB
289 bool "64kB"
290 depends on EXPERIMENTAL && CPU_SH4
291 help
292 This enables support for 64kB pages, possible on all SH-4
293 CPUs and later. Highly experimental, not recommended.
294
295endchoice
296
297choice
240 prompt "HugeTLB page size" 298 prompt "HugeTLB page size"
241 depends on HUGETLB_PAGE && CPU_SH4 && MMU 299 depends on HUGETLB_PAGE && CPU_SH4 && MMU
242 default HUGETLB_PAGE_SIZE_64K 300 default HUGETLB_PAGE_SIZE_64K
243 301
244config HUGETLB_PAGE_SIZE_64K 302config HUGETLB_PAGE_SIZE_64K
245 bool "64K" 303 bool "64kB"
304
305config HUGETLB_PAGE_SIZE_256K
306 bool "256kB"
307 depends on X2TLB
246 308
247config HUGETLB_PAGE_SIZE_1MB 309config HUGETLB_PAGE_SIZE_1MB
248 bool "1MB" 310 bool "1MB"
249 311
312config HUGETLB_PAGE_SIZE_4MB
313 bool "4MB"
314 depends on X2TLB
315
316config HUGETLB_PAGE_SIZE_64MB
317 bool "64MB"
318 depends on X2TLB
319
250endchoice 320endchoice
251 321
252source "mm/Kconfig" 322source "mm/Kconfig"
@@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED
274 344
275config SH_WRITETHROUGH 345config SH_WRITETHROUGH
276 bool "Use write-through caching" 346 bool "Use write-through caching"
277 default y if CPU_SH2
278 help 347 help
279 Selecting this option will configure the caches in write-through 348 Selecting this option will configure the caches in write-through
280 mode, as opposed to the default write-back configuration. 349 mode, as opposed to the default write-back configuration.
diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c
index 2689cb24ea2b..6614033f6be9 100644
--- a/arch/sh/mm/cache-sh2.c
+++ b/arch/sh/mm/cache-sh2.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Released under the terms of the GNU GPL v2.0. 6 * Released under the terms of the GNU GPL v2.0.
7 */ 7 */
8
8#include <linux/init.h> 9#include <linux/init.h>
9#include <linux/mm.h> 10#include <linux/mm.h>
10 11
@@ -14,37 +15,43 @@
14#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
15#include <asm/io.h> 16#include <asm/io.h>
16 17
17/* 18void __flush_wback_region(void *start, int size)
18 * Calculate the OC address and set the way bit on the SH-2.
19 *
20 * We must have already jump_to_P2()'ed prior to calling this
21 * function, since we rely on CCR manipulation to do the
22 * Right Thing(tm).
23 */
24unsigned long __get_oc_addr(unsigned long set, unsigned long way)
25{ 19{
26 unsigned long ccr; 20 unsigned long v;
27 21 unsigned long begin, end;
28 /* 22
29 * On SH-2 the way bit isn't tracked in the address field 23 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
30 * if we're doing address array access .. instead, we need 24 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
31 * to manually switch out the way in the CCR. 25 & ~(L1_CACHE_BYTES-1);
32 */ 26 for (v = begin; v < end; v+=L1_CACHE_BYTES) {
33 ccr = ctrl_inl(CCR); 27 /* FIXME cache purge */
34 ccr &= ~0x00c0; 28 ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
35 ccr |= way << cpu_data->dcache.way_shift; 29 }
36 30}
37 /* 31
38 * Despite the number of sets being halved, we end up losing 32void __flush_purge_region(void *start, int size)
39 * the first 2 ways to OCRAM instead of the last 2 (if we're 33{
40 * 4-way). As a result, forcibly setting the W1 bit handily 34 unsigned long v;
41 * bumps us up 2 ways. 35 unsigned long begin, end;
42 */ 36
43 if (ccr & CCR_CACHE_ORA) 37 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
44 ccr |= 1 << (cpu_data->dcache.way_shift + 1); 38 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
45 39 & ~(L1_CACHE_BYTES-1);
46 ctrl_outl(ccr, CCR); 40 for (v = begin; v < end; v+=L1_CACHE_BYTES) {
47 41 ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
48 return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); 42 }
43}
44
45void __flush_invalidate_region(void *start, int size)
46{
47 unsigned long v;
48 unsigned long begin, end;
49
50 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
51 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
52 & ~(L1_CACHE_BYTES-1);
53 for (v = begin; v < end; v+=L1_CACHE_BYTES) {
54 ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
55 }
49} 56}
50 57
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index e48cc22724d9..ae531affccbd 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -11,12 +11,8 @@
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/mm.h> 13#include <linux/mm.h>
14#include <asm/addrspace.h> 14#include <linux/io.h>
15#include <asm/pgtable.h> 15#include <linux/mutex.h>
16#include <asm/processor.h>
17#include <asm/cache.h>
18#include <asm/io.h>
19#include <asm/pgalloc.h>
20#include <asm/mmu_context.h> 16#include <asm/mmu_context.h>
21#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
22 18
@@ -83,9 +79,9 @@ static void __init emit_cache_params(void)
83 */ 79 */
84 80
85/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */ 81/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
86#define MAX_P3_SEMAPHORES 16 82#define MAX_P3_MUTEXES 16
87 83
88struct semaphore p3map_sem[MAX_P3_SEMAPHORES]; 84struct mutex p3map_mutex[MAX_P3_MUTEXES];
89 85
90void __init p3_cache_init(void) 86void __init p3_cache_init(void)
91{ 87{
@@ -115,7 +111,7 @@ void __init p3_cache_init(void)
115 panic("%s failed.", __FUNCTION__); 111 panic("%s failed.", __FUNCTION__);
116 112
117 for (i = 0; i < cpu_data->dcache.n_aliases; i++) 113 for (i = 0; i < cpu_data->dcache.n_aliases; i++)
118 sema_init(&p3map_sem[i], 1); 114 mutex_init(&p3map_mutex[i]);
119} 115}
120 116
121/* 117/*
@@ -229,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start,
229 */ 225 */
230 if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) || 226 if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
231 (start < CACHE_OC_ADDRESS_ARRAY)) 227 (start < CACHE_OC_ADDRESS_ARRAY))
232 exec_offset = 0x20000000; 228 exec_offset = 0x20000000;
233 229
234 local_irq_save(flags); 230 local_irq_save(flags);
235 __flush_cache_4096(start | SH_CACHE_ASSOC, 231 __flush_cache_4096(start | SH_CACHE_ASSOC,
@@ -250,7 +246,7 @@ void flush_dcache_page(struct page *page)
250 246
251 /* Loop all the D-cache */ 247 /* Loop all the D-cache */
252 n = cpu_data->dcache.n_aliases; 248 n = cpu_data->dcache.n_aliases;
253 for (i = 0; i < n; i++, addr += PAGE_SIZE) 249 for (i = 0; i < n; i++, addr += 4096)
254 flush_cache_4096(addr, phys); 250 flush_cache_4096(addr, phys);
255 } 251 }
256 252
diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S
index 7b96425ae270..8a706131e521 100644
--- a/arch/sh/mm/clear_page.S
+++ b/arch/sh/mm/clear_page.S
@@ -1,12 +1,12 @@
1/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $ 1/*
2 *
3 * __clear_user_page, __clear_user, clear_page implementation of SuperH 2 * __clear_user_page, __clear_user, clear_page implementation of SuperH
4 * 3 *
5 * Copyright (C) 2001 Kaz Kojima 4 * Copyright (C) 2001 Kaz Kojima
6 * Copyright (C) 2001, 2002 Niibe Yutaka 5 * Copyright (C) 2001, 2002 Niibe Yutaka
7 * 6 * Copyright (C) 2006 Paul Mundt
8 */ 7 */
9#include <linux/linkage.h> 8#include <linux/linkage.h>
9#include <asm/page.h>
10 10
11/* 11/*
12 * clear_page_slow 12 * clear_page_slow
@@ -18,11 +18,11 @@
18/* 18/*
19 * r0 --- scratch 19 * r0 --- scratch
20 * r4 --- to 20 * r4 --- to
21 * r5 --- to + 4096 21 * r5 --- to + PAGE_SIZE
22 */ 22 */
23ENTRY(clear_page_slow) 23ENTRY(clear_page_slow)
24 mov r4,r5 24 mov r4,r5
25 mov.w .Llimit,r0 25 mov.l .Llimit,r0
26 add r0,r5 26 add r0,r5
27 mov #0,r0 27 mov #0,r0
28 ! 28 !
@@ -50,7 +50,7 @@ ENTRY(clear_page_slow)
50 ! 50 !
51 rts 51 rts
52 nop 52 nop
53.Llimit: .word (4096-28) 53.Llimit: .long (PAGE_SIZE-28)
54 54
55ENTRY(__clear_user) 55ENTRY(__clear_user)
56 ! 56 !
@@ -164,10 +164,10 @@ ENTRY(__clear_user)
164 * r0 --- scratch 164 * r0 --- scratch
165 * r4 --- to 165 * r4 --- to
166 * r5 --- orig_to 166 * r5 --- orig_to
167 * r6 --- to + 4096 167 * r6 --- to + PAGE_SIZE
168 */ 168 */
169ENTRY(__clear_user_page) 169ENTRY(__clear_user_page)
170 mov.w .L4096,r0 170 mov.l .Lpsz,r0
171 mov r4,r6 171 mov r4,r6
172 add r0,r6 172 add r0,r6
173 mov #0,r0 173 mov #0,r0
@@ -191,7 +191,7 @@ ENTRY(__clear_user_page)
191 ! 191 !
192 rts 192 rts
193 nop 193 nop
194.L4096: .word 4096 194.Lpsz: .long PAGE_SIZE
195 195
196#endif 196#endif
197 197
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S
index 1addffe117c3..397c94c97315 100644
--- a/arch/sh/mm/copy_page.S
+++ b/arch/sh/mm/copy_page.S
@@ -1,12 +1,12 @@
1/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $ 1/*
2 *
3 * copy_page, __copy_user_page, __copy_user implementation of SuperH 2 * copy_page, __copy_user_page, __copy_user implementation of SuperH
4 * 3 *
5 * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima 4 * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima
6 * Copyright (C) 2002 Toshinobu Sugioka 5 * Copyright (C) 2002 Toshinobu Sugioka
7 * 6 * Copyright (C) 2006 Paul Mundt
8 */ 7 */
9#include <linux/linkage.h> 8#include <linux/linkage.h>
9#include <asm/page.h>
10 10
11/* 11/*
12 * copy_page_slow 12 * copy_page_slow
@@ -18,7 +18,7 @@
18 18
19/* 19/*
20 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 20 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
21 * r8 --- from + 4096 21 * r8 --- from + PAGE_SIZE
22 * r9 --- not used 22 * r9 --- not used
23 * r10 --- to 23 * r10 --- to
24 * r11 --- from 24 * r11 --- from
@@ -30,7 +30,7 @@ ENTRY(copy_page_slow)
30 mov r4,r10 30 mov r4,r10
31 mov r5,r11 31 mov r5,r11
32 mov r5,r8 32 mov r5,r8
33 mov.w .L4096,r0 33 mov.l .Lpsz,r0
34 add r0,r8 34 add r0,r8
35 ! 35 !
361: mov.l @r11+,r0 361: mov.l @r11+,r0
@@ -80,7 +80,7 @@ ENTRY(copy_page_slow)
80 80
81/* 81/*
82 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 82 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
83 * r8 --- from + 4096 83 * r8 --- from + PAGE_SIZE
84 * r9 --- orig_to 84 * r9 --- orig_to
85 * r10 --- to 85 * r10 --- to
86 * r11 --- from 86 * r11 --- from
@@ -94,7 +94,7 @@ ENTRY(__copy_user_page)
94 mov r5,r11 94 mov r5,r11
95 mov r6,r9 95 mov r6,r9
96 mov r5,r8 96 mov r5,r8
97 mov.w .L4096,r0 97 mov.l .Lpsz,r0
98 add r0,r8 98 add r0,r8
99 ! 99 !
1001: ocbi @r9 1001: ocbi @r9
@@ -129,7 +129,7 @@ ENTRY(__copy_user_page)
129 rts 129 rts
130 nop 130 nop
131#endif 131#endif
132.L4096: .word 4096 132.Lpsz: .long PAGE_SIZE
133/* 133/*
134 * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); 134 * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
135 * Return the number of bytes NOT copied 135 * Return the number of bytes NOT copied
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 68663b8f99ae..716ebf568af2 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -26,13 +26,19 @@ extern void die(const char *,struct pt_regs *,long);
26 * and the problem, and then passes it off to one of the appropriate 26 * and the problem, and then passes it off to one of the appropriate
27 * routines. 27 * routines.
28 */ 28 */
29asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, 29asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
30 unsigned long address) 30 unsigned long writeaccess,
31 unsigned long address)
31{ 32{
32 struct task_struct *tsk; 33 struct task_struct *tsk;
33 struct mm_struct *mm; 34 struct mm_struct *mm;
34 struct vm_area_struct * vma; 35 struct vm_area_struct * vma;
35 unsigned long page; 36 unsigned long page;
37 int si_code;
38 siginfo_t info;
39
40 trace_hardirqs_on();
41 local_irq_enable();
36 42
37#ifdef CONFIG_SH_KGDB 43#ifdef CONFIG_SH_KGDB
38 if (kgdb_nofault && kgdb_bus_err_hook) 44 if (kgdb_nofault && kgdb_bus_err_hook)
@@ -41,6 +47,46 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
41 47
42 tsk = current; 48 tsk = current;
43 mm = tsk->mm; 49 mm = tsk->mm;
50 si_code = SEGV_MAPERR;
51
52 if (unlikely(address >= TASK_SIZE)) {
53 /*
54 * Synchronize this task's top level page-table
55 * with the 'reference' page table.
56 *
57 * Do _not_ use "tsk" here. We might be inside
58 * an interrupt in the middle of a task switch..
59 */
60 int offset = pgd_index(address);
61 pgd_t *pgd, *pgd_k;
62 pud_t *pud, *pud_k;
63 pmd_t *pmd, *pmd_k;
64
65 pgd = get_TTB() + offset;
66 pgd_k = swapper_pg_dir + offset;
67
68 /* This will never happen with the folded page table. */
69 if (!pgd_present(*pgd)) {
70 if (!pgd_present(*pgd_k))
71 goto bad_area_nosemaphore;
72 set_pgd(pgd, *pgd_k);
73 return;
74 }
75
76 pud = pud_offset(pgd, address);
77 pud_k = pud_offset(pgd_k, address);
78 if (pud_present(*pud) || !pud_present(*pud_k))
79 goto bad_area_nosemaphore;
80 set_pud(pud, *pud_k);
81
82 pmd = pmd_offset(pud, address);
83 pmd_k = pmd_offset(pud_k, address);
84 if (pmd_present(*pmd) || !pmd_present(*pmd_k))
85 goto bad_area_nosemaphore;
86 set_pmd(pmd, *pmd_k);
87
88 return;
89 }
44 90
45 /* 91 /*
46 * If we're in an interrupt or have no user 92 * If we're in an interrupt or have no user
@@ -65,6 +111,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
65 * we can handle it.. 111 * we can handle it..
66 */ 112 */
67good_area: 113good_area:
114 si_code = SEGV_ACCERR;
68 if (writeaccess) { 115 if (writeaccess) {
69 if (!(vma->vm_flags & VM_WRITE)) 116 if (!(vma->vm_flags & VM_WRITE))
70 goto bad_area; 117 goto bad_area;
@@ -104,10 +151,13 @@ survive:
104bad_area: 151bad_area:
105 up_read(&mm->mmap_sem); 152 up_read(&mm->mmap_sem);
106 153
154bad_area_nosemaphore:
107 if (user_mode(regs)) { 155 if (user_mode(regs)) {
108 tsk->thread.address = address; 156 info.si_signo = SIGSEGV;
109 tsk->thread.error_code = writeaccess; 157 info.si_errno = 0;
110 force_sig(SIGSEGV, tsk); 158 info.si_code = si_code;
159 info.si_addr = (void *) address;
160 force_sig_info(SIGSEGV, &info, tsk);
111 return; 161 return;
112 } 162 }
113 163
@@ -127,11 +177,9 @@ no_context:
127 printk(KERN_ALERT "Unable to handle kernel paging request"); 177 printk(KERN_ALERT "Unable to handle kernel paging request");
128 printk(" at virtual address %08lx\n", address); 178 printk(" at virtual address %08lx\n", address);
129 printk(KERN_ALERT "pc = %08lx\n", regs->pc); 179 printk(KERN_ALERT "pc = %08lx\n", regs->pc);
130 asm volatile("mov.l %1, %0" 180 page = (unsigned long)get_TTB();
131 : "=r" (page)
132 : "m" (__m(MMU_TTB)));
133 if (page) { 181 if (page) {
134 page = ((unsigned long *) page)[address >> 22]; 182 page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
135 printk(KERN_ALERT "*pde = %08lx\n", page); 183 printk(KERN_ALERT "*pde = %08lx\n", page);
136 if (page & _PAGE_PRESENT) { 184 if (page & _PAGE_PRESENT) {
137 page &= PAGE_MASK; 185 page &= PAGE_MASK;
@@ -166,98 +214,13 @@ do_sigbus:
166 * Send a sigbus, regardless of whether we were in kernel 214 * Send a sigbus, regardless of whether we were in kernel
167 * or user mode. 215 * or user mode.
168 */ 216 */
169 tsk->thread.address = address; 217 info.si_signo = SIGBUS;
170 tsk->thread.error_code = writeaccess; 218 info.si_errno = 0;
171 tsk->thread.trap_no = 14; 219 info.si_code = BUS_ADRERR;
172 force_sig(SIGBUS, tsk); 220 info.si_addr = (void *)address;
221 force_sig_info(SIGBUS, &info, tsk);
173 222
174 /* Kernel mode? Handle exceptions or die */ 223 /* Kernel mode? Handle exceptions or die */
175 if (!user_mode(regs)) 224 if (!user_mode(regs))
176 goto no_context; 225 goto no_context;
177} 226}
178
179#ifdef CONFIG_SH_STORE_QUEUES
180/*
181 * This is a special case for the SH-4 store queues, as pages for this
182 * space still need to be faulted in before it's possible to flush the
183 * store queue cache for writeout to the remapped region.
184 */
185#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000)
186#else
187#define P3_ADDR_MAX P4SEG
188#endif
189
190/*
191 * Called with interrupts disabled.
192 */
193asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
194 unsigned long writeaccess,
195 unsigned long address)
196{
197 pgd_t *pgd;
198 pud_t *pud;
199 pmd_t *pmd;
200 pte_t *pte;
201 pte_t entry;
202 struct mm_struct *mm = current->mm;
203 spinlock_t *ptl;
204 int ret = 1;
205
206#ifdef CONFIG_SH_KGDB
207 if (kgdb_nofault && kgdb_bus_err_hook)
208 kgdb_bus_err_hook();
209#endif
210
211 /*
212 * We don't take page faults for P1, P2, and parts of P4, these
213 * are always mapped, whether it be due to legacy behaviour in
214 * 29-bit mode, or due to PMB configuration in 32-bit mode.
215 */
216 if (address >= P3SEG && address < P3_ADDR_MAX) {
217 pgd = pgd_offset_k(address);
218 mm = NULL;
219 } else {
220 if (unlikely(address >= TASK_SIZE || !mm))
221 return 1;
222
223 pgd = pgd_offset(mm, address);
224 }
225
226 pud = pud_offset(pgd, address);
227 if (pud_none_or_clear_bad(pud))
228 return 1;
229 pmd = pmd_offset(pud, address);
230 if (pmd_none_or_clear_bad(pmd))
231 return 1;
232
233 if (mm)
234 pte = pte_offset_map_lock(mm, pmd, address, &ptl);
235 else
236 pte = pte_offset_kernel(pmd, address);
237
238 entry = *pte;
239 if (unlikely(pte_none(entry) || pte_not_present(entry)))
240 goto unlock;
241 if (unlikely(writeaccess && !pte_write(entry)))
242 goto unlock;
243
244 if (writeaccess)
245 entry = pte_mkdirty(entry);
246 entry = pte_mkyoung(entry);
247
248#ifdef CONFIG_CPU_SH4
249 /*
250 * ITLB is not affected by "ldtlb" instruction.
251 * So, we need to flush the entry by ourselves.
252 */
253 __flush_tlb_page(get_asid(), address & PAGE_MASK);
254#endif
255
256 set_pte(pte, entry);
257 update_mmu_cache(NULL, address, entry);
258 ret = 0;
259unlock:
260 if (mm)
261 pte_unmap_unlock(pte, ptl);
262 return ret;
263}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 7154d1ce9785..59f4cc18235b 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
84 pmd_t *pmd; 84 pmd_t *pmd;
85 pte_t *pte; 85 pte_t *pte;
86 86
87 pgd = swapper_pg_dir + pgd_index(addr); 87 pgd = pgd_offset_k(addr);
88 if (pgd_none(*pgd)) { 88 if (pgd_none(*pgd)) {
89 pgd_ERROR(*pgd); 89 pgd_ERROR(*pgd);
90 return; 90 return;
91 } 91 }
92 92
93 pud = pud_offset(pgd, addr); 93 pud = pud_alloc(NULL, pgd, addr);
94 if (pud_none(*pud)) { 94 if (unlikely(!pud)) {
95 pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); 95 pud_ERROR(*pud);
96 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); 96 return;
97 if (pmd != pmd_offset(pud, 0)) {
98 pud_ERROR(*pud);
99 return;
100 }
101 } 97 }
102 98
103 pmd = pmd_offset(pud, addr); 99 pmd = pmd_alloc(NULL, pud, addr);
104 if (pmd_none(*pmd)) { 100 if (unlikely(!pmd)) {
105 pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); 101 pmd_ERROR(*pmd);
106 set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); 102 return;
107 if (pte != pte_offset_kernel(pmd, 0)) {
108 pmd_ERROR(*pmd);
109 return;
110 }
111 } 103 }
112 104
113 pte = pte_offset_kernel(pmd, addr); 105 pte = pte_offset_kernel(pmd, addr);
@@ -155,9 +147,6 @@ extern char __init_begin, __init_end;
155 147
156/* 148/*
157 * paging_init() sets up the page tables 149 * paging_init() sets up the page tables
158 *
159 * This routines also unmaps the page at virtual kernel address 0, so
160 * that we can trap those pesky NULL-reference errors in the kernel.
161 */ 150 */
162void __init paging_init(void) 151void __init paging_init(void)
163{ 152{
@@ -180,14 +169,11 @@ void __init paging_init(void)
180 */ 169 */
181 { 170 {
182 unsigned long max_dma, low, start_pfn; 171 unsigned long max_dma, low, start_pfn;
183 pgd_t *pg_dir;
184 int i;
185
186 /* We don't need kernel mapping as hardware support that. */
187 pg_dir = swapper_pg_dir;
188 172
189 for (i = 0; i < PTRS_PER_PGD; i++) 173 /* We don't need to map the kernel through the TLB, as
190 pgd_val(pg_dir[i]) = 0; 174 * it is permanatly mapped using P1. So clear the
175 * entire pgd. */
176 memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
191 177
192 /* Turn on the MMU */ 178 /* Turn on the MMU */
193 enable_mmu(); 179 enable_mmu();
@@ -206,6 +192,10 @@ void __init paging_init(void)
206 } 192 }
207 } 193 }
208 194
195 /* Set an initial value for the MMU.TTB so we don't have to
196 * check for a null value. */
197 set_TTB(swapper_pg_dir);
198
209#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) 199#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
210 /* 200 /*
211 * If we don't have CONFIG_MMU set and the processor in question 201 * If we don't have CONFIG_MMU set and the processor in question
@@ -227,7 +217,6 @@ static struct kcore_list kcore_mem, kcore_vmalloc;
227 217
228void __init mem_init(void) 218void __init mem_init(void)
229{ 219{
230 extern unsigned long empty_zero_page[1024];
231 int codesize, reservedpages, datasize, initsize; 220 int codesize, reservedpages, datasize, initsize;
232 int tmp; 221 int tmp;
233 extern unsigned long memory_start; 222 extern unsigned long memory_start;
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index a9fe80cfc233..11d54c149821 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -28,9 +28,7 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address,
28{ 28{
29 unsigned long end; 29 unsigned long end;
30 unsigned long pfn; 30 unsigned long pfn;
31 pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | 31 pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
32 _PAGE_DIRTY | _PAGE_ACCESSED |
33 _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
34 32
35 address &= ~PMD_MASK; 33 address &= ~PMD_MASK;
36 end = address + size; 34 end = address + size;
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
index 1406d2e348ca..bb23679369d6 100644
--- a/arch/sh/mm/pg-dma.c
+++ b/arch/sh/mm/pg-dma.c
@@ -39,8 +39,6 @@ static void copy_page_dma(void *to, void *from)
39 39
40static void clear_page_dma(void *to) 40static void clear_page_dma(void *to)
41{ 41{
42 extern unsigned long empty_zero_page[1024];
43
44 /* 42 /*
45 * We get invoked quite early on, if the DMAC hasn't been initialized 43 * We get invoked quite early on, if the DMAC hasn't been initialized
46 * yet, fall back on the slow manual implementation. 44 * yet, fall back on the slow manual implementation.
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 07371ed7a313..3f98d2a4f936 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -6,22 +6,12 @@
6 * 6 *
7 * Released under the terms of the GNU GPL v2.0. 7 * Released under the terms of the GNU GPL v2.0.
8 */ 8 */
9#include <linux/init.h>
10#include <linux/mman.h>
11#include <linux/mm.h> 9#include <linux/mm.h>
12#include <linux/threads.h> 10#include <linux/mutex.h>
13#include <asm/addrspace.h>
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include <asm/processor.h>
17#include <asm/cache.h>
18#include <asm/io.h>
19#include <asm/uaccess.h>
20#include <asm/pgalloc.h>
21#include <asm/mmu_context.h> 11#include <asm/mmu_context.h>
22#include <asm/cacheflush.h> 12#include <asm/cacheflush.h>
23 13
24extern struct semaphore p3map_sem[]; 14extern struct mutex p3map_mutex[];
25 15
26#define CACHE_ALIAS (cpu_data->dcache.alias_mask) 16#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
27 17
@@ -37,10 +27,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
37 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 27 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
38 clear_page(to); 28 clear_page(to);
39 else { 29 else {
40 pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
41 _PAGE_RW | _PAGE_CACHABLE |
42 _PAGE_DIRTY | _PAGE_ACCESSED |
43 _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
44 unsigned long phys_addr = PHYSADDR(to); 30 unsigned long phys_addr = PHYSADDR(to);
45 unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); 31 unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
46 pgd_t *pgd = pgd_offset_k(p3_addr); 32 pgd_t *pgd = pgd_offset_k(p3_addr);
@@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
50 pte_t entry; 36 pte_t entry;
51 unsigned long flags; 37 unsigned long flags;
52 38
53 entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); 39 entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
54 down(&p3map_sem[(address & CACHE_ALIAS)>>12]); 40 mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
55 set_pte(pte, entry); 41 set_pte(pte, entry);
56 local_irq_save(flags); 42 local_irq_save(flags);
57 __flush_tlb_page(get_asid(), p3_addr); 43 __flush_tlb_page(get_asid(), p3_addr);
@@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
59 update_mmu_cache(NULL, p3_addr, entry); 45 update_mmu_cache(NULL, p3_addr, entry);
60 __clear_user_page((void *)p3_addr, to); 46 __clear_user_page((void *)p3_addr, to);
61 pte_clear(&init_mm, p3_addr, pte); 47 pte_clear(&init_mm, p3_addr, pte);
62 up(&p3map_sem[(address & CACHE_ALIAS)>>12]); 48 mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
63 } 49 }
64} 50}
65 51
@@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from, unsigned long address,
77 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 63 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
78 copy_page(to, from); 64 copy_page(to, from);
79 else { 65 else {
80 pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
81 _PAGE_RW | _PAGE_CACHABLE |
82 _PAGE_DIRTY | _PAGE_ACCESSED |
83 _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
84 unsigned long phys_addr = PHYSADDR(to); 66 unsigned long phys_addr = PHYSADDR(to);
85 unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); 67 unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
86 pgd_t *pgd = pgd_offset_k(p3_addr); 68 pgd_t *pgd = pgd_offset_k(p3_addr);
@@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from, unsigned long address,
90 pte_t entry; 72 pte_t entry;
91 unsigned long flags; 73 unsigned long flags;
92 74
93 entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); 75 entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
94 down(&p3map_sem[(address & CACHE_ALIAS)>>12]); 76 mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
95 set_pte(pte, entry); 77 set_pte(pte, entry);
96 local_irq_save(flags); 78 local_irq_save(flags);
97 __flush_tlb_page(get_asid(), p3_addr); 79 __flush_tlb_page(get_asid(), p3_addr);
@@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from, unsigned long address,
99 update_mmu_cache(NULL, p3_addr, entry); 81 update_mmu_cache(NULL, p3_addr, entry);
100 __copy_user_page((void *)p3_addr, from, to); 82 __copy_user_page((void *)p3_addr, from, to);
101 pte_clear(&init_mm, p3_addr, pte); 83 pte_clear(&init_mm, p3_addr, pte);
102 up(&p3map_sem[(address & CACHE_ALIAS)>>12]); 84 mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
103 } 85 }
104} 86}
105 87
@@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t
122 } 104 }
123 return pte; 105 return pte;
124} 106}
125
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index ac57638977ee..0571755e9a84 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -30,3 +30,5 @@ R7780MP SH_R7780MP
30TITAN SH_TITAN 30TITAN SH_TITAN
31SHMIN SH_SHMIN 31SHMIN SH_SHMIN
327710VOIPGW SH_7710VOIPGW 327710VOIPGW SH_7710VOIPGW
337206SE SH_7206_SOLUTION_ENGINE
347619SE SH_7619_SOLUTION_ENGINE