diff options
Diffstat (limited to 'arch/sh')
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 | |||
51 | config ARCH_MAY_HAVE_PC_FDC | 51 | config ARCH_MAY_HAVE_PC_FDC |
52 | bool | 52 | bool |
53 | 53 | ||
54 | config STACKTRACE_SUPPORT | ||
55 | bool | ||
56 | default y | ||
57 | |||
58 | config LOCKDEP_SUPPORT | ||
59 | bool | ||
60 | default y | ||
61 | |||
54 | source "init/Kconfig" | 62 | source "init/Kconfig" |
55 | 63 | ||
56 | menu "System type" | 64 | menu "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 | ||
230 | config 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 | |||
237 | config 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 | |||
222 | config SH_UNKNOWN | 244 | config SH_UNKNOWN |
223 | bool "BareCPU" | 245 | bool "BareCPU" |
224 | help | 246 | help |
@@ -280,12 +302,20 @@ config CF_BASE_ADDR | |||
280 | 302 | ||
281 | menu "Processor features" | 303 | menu "Processor features" |
282 | 304 | ||
283 | config CPU_LITTLE_ENDIAN | 305 | choice |
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 | |
312 | config CPU_LITTLE_ENDIAN | ||
313 | bool "Little Endian" | ||
314 | |||
315 | config CPU_BIG_ENDIAN | ||
316 | bool "Big Endian" | ||
317 | |||
318 | endchoice | ||
289 | 319 | ||
290 | config SH_FPU | 320 | config SH_FPU |
291 | bool "FPU support" | 321 | bool "FPU support" |
@@ -345,6 +375,9 @@ config CPU_HAS_MASKREG_IRQ | |||
345 | config CPU_HAS_INTC2_IRQ | 375 | config CPU_HAS_INTC2_IRQ |
346 | bool | 376 | bool |
347 | 377 | ||
378 | config CPU_HAS_IPR_IRQ | ||
379 | bool | ||
380 | |||
348 | config CPU_HAS_SR_RB | 381 | config 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 | ||
393 | config CPU_HAS_PTEA | ||
394 | bool | ||
395 | |||
360 | endmenu | 396 | endmenu |
361 | 397 | ||
362 | menu "Timer support" | 398 | menu "Timer support" |
@@ -364,10 +400,25 @@ depends on !GENERIC_TIME | |||
364 | 400 | ||
365 | config SH_TMU | 401 | config 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 | ||
408 | config 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 | |||
415 | config 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 | |||
371 | endmenu | 422 | endmenu |
372 | 423 | ||
373 | source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" | 424 | source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" |
@@ -376,19 +427,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig" | |||
376 | 427 | ||
377 | source "arch/sh/boards/renesas/r7780rp/Kconfig" | 428 | source "arch/sh/boards/renesas/r7780rp/Kconfig" |
378 | 429 | ||
430 | config 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 | |||
437 | config 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 | |||
379 | config SH_PCLK_FREQ | 455 | config 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 | ||
470 | config 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 | |||
392 | menu "CPU Frequency scaling" | 476 | menu "CPU Frequency scaling" |
393 | 477 | ||
394 | source "drivers/cpufreq/Kconfig" | 478 | source "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 | ||
508 | source "arch/sh/drivers/Kconfig" | ||
509 | |||
424 | endmenu | 510 | endmenu |
425 | 511 | ||
426 | config ISA_DMA_API | 512 | config 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 @@ | |||
1 | menu "Kernel hacking" | 1 | menu "Kernel hacking" |
2 | 2 | ||
3 | config TRACE_IRQFLAGS_SUPPORT | ||
4 | bool | ||
5 | default y | ||
6 | |||
3 | source "lib/Kconfig.debug" | 7 | source "lib/Kconfig.debug" |
4 | 8 | ||
5 | config SH_STANDARD_BIOS | 9 | config SH_STANDARD_BIOS |
@@ -17,7 +21,18 @@ config SH_STANDARD_BIOS | |||
17 | 21 | ||
18 | config EARLY_SCIF_CONSOLE | 22 | config 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 | |||
30 | config 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 | ||
22 | config EARLY_PRINTK | 37 | config 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 | |||
33 | config DEBUG_STACKOVERFLOW | 53 | config 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 | |||
17 | cflags-y := -mb | ||
18 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml | ||
19 | |||
20 | isa-y := any | 16 | isa-y := any |
21 | isa-$(CONFIG_SH_DSP) := sh | 17 | isa-$(CONFIG_SH_DSP) := sh |
22 | isa-$(CONFIG_CPU_SH2) := sh2 | 18 | isa-$(CONFIG_CPU_SH2) := sh2 |
@@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu | |||
38 | endif | 34 | endif |
39 | endif | 35 | endif |
40 | 36 | ||
41 | cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) | 37 | cflags-$(CONFIG_CPU_SH2) := -m2 |
42 | 38 | cflags-$(CONFIG_CPU_SH3) := -m3 | |
43 | cflags-$(CONFIG_CPU_SH2) += -m2 | 39 | cflags-$(CONFIG_CPU_SH4) := -m4 \ |
44 | cflags-$(CONFIG_CPU_SH3) += -m3 | ||
45 | cflags-$(CONFIG_CPU_SH4) += -m4 \ | ||
46 | $(call cc-option,-mno-implicit-fp,-m4-nofpu) | 40 | $(call cc-option,-mno-implicit-fp,-m4-nofpu) |
47 | cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) | 41 | cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,) |
42 | |||
43 | cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb | ||
44 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml | ||
45 | |||
46 | cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding | ||
48 | 47 | ||
49 | cflags-$(CONFIG_SH_DSP) += -Wa,-dsp | 48 | cflags-$(CONFIG_SH_DSP) += -Wa,-dsp |
50 | cflags-$(CONFIG_SH_KGDB) += -g | 49 | cflags-$(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 | # |
62 | KBUILD_DEFCONFIG := rts7751r2d_defconfig | 61 | KBUILD_DEFCONFIG := r7780rp_defconfig |
62 | |||
63 | KBUILD_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 | |||
109 | machdir-$(CONFIG_SH_LANDISK) := landisk | 110 | machdir-$(CONFIG_SH_LANDISK) := landisk |
110 | machdir-$(CONFIG_SH_TITAN) := titan | 111 | machdir-$(CONFIG_SH_TITAN) := titan |
111 | machdir-$(CONFIG_SH_SHMIN) := shmin | 112 | machdir-$(CONFIG_SH_SHMIN) := shmin |
113 | machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206 | ||
114 | machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619 | ||
112 | machdir-$(CONFIG_SH_UNKNOWN) := unknown | 115 | machdir-$(CONFIG_SH_UNKNOWN) := unknown |
113 | 116 | ||
114 | incdir-y := $(notdir $(machdir-y)) | 117 | incdir-y := $(notdir $(machdir-y)) |
@@ -124,6 +127,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/ | |||
124 | core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ | 127 | core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ |
125 | 128 | ||
126 | cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 | 129 | cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 |
130 | cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a | ||
127 | cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 | 131 | cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 |
128 | cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 | 132 | cpuincdir-$(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 | ||
5 | obj-y := setup.o io.o irq.o | 5 | obj-y := setup.o io.o irq.o |
6 | obj-$(CONFIG_HEARTBEAT) += led.o | 6 | |
7 | obj-$(CONFIG_HEARTBEAT) += led.o | ||
8 | obj-$(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 | |||
19 | static 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 | |||
45 | out: | ||
46 | /* Clear the switch IRQs */ | ||
47 | l |= (0x7 << 12); | ||
48 | ctrl_outw(l, PA_DBSW); | ||
49 | |||
50 | return IRQ_RETVAL(ret); | ||
51 | } | ||
52 | |||
53 | static struct resource psw_resources[] = { | ||
54 | [0] = { | ||
55 | .start = IRQ_PSW, | ||
56 | .flags = IORESOURCE_IRQ, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static 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 | |||
68 | static 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 | |||
78 | static 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 | |||
86 | static 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 | |||
96 | static 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 | |||
104 | static 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 | |||
114 | static struct platform_device *psw_devices[] = { | ||
115 | &s2_switch_device, &s3_switch_device, &s4_switch_device, | ||
116 | }; | ||
117 | |||
118 | static int __init psw_init(void) | ||
119 | { | ||
120 | return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices)); | ||
121 | } | ||
122 | module_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 | ||
47 | static 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 | |||
68 | static 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 | |||
47 | static struct platform_device *r7780rp_devices[] __initdata = { | 75 | static struct platform_device *r7780rp_devices[] __initdata = { |
48 | &m66596_usb_host_device, | 76 | &m66596_usb_host_device, |
77 | &cf_ide_device, | ||
49 | }; | 78 | }; |
50 | 79 | ||
51 | static int __init r7780rp_devices_setup(void) | 80 | static 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 | |||
5 | obj-y := setup.o io.o irq.o | ||
6 | obj-$(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 | |||
17 | static 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 | |||
26 | static inline volatile __u16 * | ||
27 | port2adr(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 | |||
35 | unsigned char se7206_inb(unsigned long port) | ||
36 | { | ||
37 | return (*port2adr(port))&0xff; | ||
38 | } | ||
39 | |||
40 | unsigned 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 | |||
49 | unsigned short se7206_inw(unsigned long port) | ||
50 | { | ||
51 | return *port2adr(port);; | ||
52 | } | ||
53 | |||
54 | unsigned int se7206_inl(unsigned long port) | ||
55 | { | ||
56 | maybebadio(port); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | void se7206_outb(unsigned char value, unsigned long port) | ||
61 | { | ||
62 | *(port2adr(port)) = value; | ||
63 | } | ||
64 | |||
65 | void se7206_outb_p(unsigned char value, unsigned long port) | ||
66 | { | ||
67 | *(port2adr(port)) = value; | ||
68 | delay(); | ||
69 | } | ||
70 | |||
71 | void se7206_outw(unsigned short value, unsigned long port) | ||
72 | { | ||
73 | *port2adr(port) = value; | ||
74 | } | ||
75 | |||
76 | void se7206_outl(unsigned int value, unsigned long port) | ||
77 | { | ||
78 | maybebadio(port); | ||
79 | } | ||
80 | |||
81 | void 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 | |||
90 | void 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 | |||
98 | void se7206_insl(unsigned long port, void *addr, unsigned long count) | ||
99 | { | ||
100 | maybebadio(port); | ||
101 | } | ||
102 | |||
103 | void 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 | |||
112 | void 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 | |||
120 | void 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 | |||
21 | static 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 | |||
51 | static 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 | |||
82 | static 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 | |||
108 | static 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 | |||
116 | static 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 | */ | ||
127 | void __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 */ | ||
20 | void 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 | |||
17 | static 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 | |||
30 | static struct platform_device smc91x_device = { | ||
31 | .name = "smc91x", | ||
32 | .id = -1, | ||
33 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
34 | .resource = smc91x_resources, | ||
35 | }; | ||
36 | |||
37 | static int __init se7206_devices_setup(void) | ||
38 | { | ||
39 | return platform_device_register(&smc91x_device); | ||
40 | } | ||
41 | |||
42 | __initcall(se7206_devices_setup); | ||
43 | |||
44 | void heartbeat_se(void); | ||
45 | |||
46 | /* | ||
47 | * The Machine Vector | ||
48 | */ | ||
49 | |||
50 | struct 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 | }; | ||
79 | ALIAS_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 | |||
5 | obj-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 | |||
19 | static 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 | |||
28 | unsigned char se7619___inb(unsigned long port) | ||
29 | { | ||
30 | badio(inb, port); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | unsigned char se7619___inb_p(unsigned long port) | ||
35 | { | ||
36 | badio(inb_p, port); | ||
37 | delay(); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | unsigned short se7619___inw(unsigned long port) | ||
42 | { | ||
43 | badio(inw, port); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | unsigned int se7619___inl(unsigned long port) | ||
48 | { | ||
49 | badio(inl, port); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void se7619___outb(unsigned char value, unsigned long port) | ||
54 | { | ||
55 | badio(outb, port); | ||
56 | } | ||
57 | |||
58 | void se7619___outb_p(unsigned char value, unsigned long port) | ||
59 | { | ||
60 | badio(outb_p, port); | ||
61 | delay(); | ||
62 | } | ||
63 | |||
64 | void se7619___outw(unsigned short value, unsigned long port) | ||
65 | { | ||
66 | badio(outw, port); | ||
67 | } | ||
68 | |||
69 | void se7619___outl(unsigned int value, unsigned long port) | ||
70 | { | ||
71 | badio(outl, port); | ||
72 | } | ||
73 | |||
74 | void se7619___insb(unsigned long port, void *addr, unsigned long count) | ||
75 | { | ||
76 | badio(inw, port); | ||
77 | } | ||
78 | |||
79 | void se7619___insw(unsigned long port, void *addr, unsigned long count) | ||
80 | { | ||
81 | badio(inw, port); | ||
82 | } | ||
83 | |||
84 | void se7619___insl(unsigned long port, void *addr, unsigned long count) | ||
85 | { | ||
86 | badio(insl, port); | ||
87 | } | ||
88 | |||
89 | void se7619___outsb(unsigned long port, const void *addr, unsigned long count) | ||
90 | { | ||
91 | badio(insl, port); | ||
92 | } | ||
93 | |||
94 | void se7619___outsw(unsigned long port, const void *addr, unsigned long count) | ||
95 | { | ||
96 | badio(insl, port); | ||
97 | } | ||
98 | |||
99 | void 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 | |||
19 | struct 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 | }; | ||
43 | ALIAS_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 | ||
10 | extern void __init pcibios_init_platform(void); | ||
11 | |||
12 | static struct ipr_data titan_ipr_map[] = { | 15 | static 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 | ||
19 | static void __init init_titan_irq(void) | 23 | static 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 | }; |
52 | ALIAS_MV(titan) | 55 | ALIAS_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]; | |||
228 | void decompress_kernel(void) | 229 | void 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 | # |
6 | CONFIG_SUPERH=y | 6 | CONFIG_SUPERH=y |
7 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 7 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
@@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y | |||
11 | CONFIG_GENERIC_IRQ_PROBE=y | 11 | CONFIG_GENERIC_IRQ_PROBE=y |
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 12 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
13 | # CONFIG_GENERIC_TIME is not set | 13 | # CONFIG_GENERIC_TIME is not set |
14 | CONFIG_STACKTRACE_SUPPORT=y | ||
15 | CONFIG_LOCKDEP_SUPPORT=y | ||
14 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | 16 | CONFIG_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 |
38 | CONFIG_IKCONFIG=y | 40 | CONFIG_IKCONFIG=y |
39 | CONFIG_IKCONFIG_PROC=y | 41 | CONFIG_IKCONFIG_PROC=y |
42 | # CONFIG_SYSFS_DEPRECATED is not set | ||
40 | # CONFIG_RELAY is not set | 43 | # CONFIG_RELAY is not set |
41 | CONFIG_INITRAMFS_SOURCE="" | 44 | CONFIG_INITRAMFS_SOURCE="" |
42 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 45 | CONFIG_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 |
167 | CONFIG_CPU_SUBTYPE_SH7780=y | 178 | CONFIG_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 | |||
181 | CONFIG_MEMORY_SIZE=0x08000000 | 193 | CONFIG_MEMORY_SIZE=0x08000000 |
182 | # CONFIG_32BIT is not set | 194 | # CONFIG_32BIT is not set |
183 | CONFIG_VSYSCALL=y | 195 | CONFIG_VSYSCALL=y |
196 | CONFIG_PAGE_SIZE_4KB=y | ||
197 | # CONFIG_PAGE_SIZE_8KB is not set | ||
198 | # CONFIG_PAGE_SIZE_64KB is not set | ||
184 | CONFIG_HUGETLB_PAGE_SIZE_64K=y | 199 | CONFIG_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 | ||
186 | CONFIG_SELECT_MEMORY_MODEL=y | 204 | CONFIG_SELECT_MEMORY_MODEL=y |
187 | CONFIG_FLATMEM_MANUAL=y | 205 | CONFIG_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 | # |
206 | CONFIG_CPU_LITTLE_ENDIAN=y | 224 | CONFIG_CPU_LITTLE_ENDIAN=y |
225 | # CONFIG_CPU_BIG_ENDIAN is not set | ||
207 | CONFIG_SH_FPU=y | 226 | CONFIG_SH_FPU=y |
208 | # CONFIG_SH_DSP is not set | 227 | # CONFIG_SH_DSP is not set |
209 | CONFIG_SH_STORE_QUEUES=y | 228 | CONFIG_SH_STORE_QUEUES=y |
210 | CONFIG_CPU_HAS_INTEVT=y | 229 | CONFIG_CPU_HAS_INTEVT=y |
211 | CONFIG_CPU_HAS_INTC2_IRQ=y | 230 | CONFIG_CPU_HAS_INTC2_IRQ=y |
212 | CONFIG_CPU_HAS_SR_RB=y | 231 | CONFIG_CPU_HAS_SR_RB=y |
232 | CONFIG_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 | # |
222 | CONFIG_SH_R7780MP=y | 242 | CONFIG_SH_R7780MP=y |
243 | CONFIG_SH_TIMER_IRQ=28 | ||
244 | CONFIG_NO_IDLE_HZ=y | ||
223 | CONFIG_SH_PCLK_FREQ=32000000 | 245 | CONFIG_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 | # | ||
265 | CONFIG_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 |
244 | CONFIG_HZ_250=y | 271 | CONFIG_HZ_250=y |
245 | # CONFIG_HZ_1000 is not set | 272 | # CONFIG_HZ_1000 is not set |
246 | CONFIG_HZ=250 | 273 | CONFIG_HZ=250 |
247 | # CONFIG_KEXEC is not set | 274 | CONFIG_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 | # |
281 | CONFIG_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 |
342 | CONFIG_TCP_CONG_CUBIC=y | 366 | CONFIG_TCP_CONG_CUBIC=y |
343 | CONFIG_DEFAULT_TCP_CONG="cubic" | 367 | CONFIG_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 |
601 | CONFIG_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 | |||
1020 | CONFIG_DNOTIFY=y | 1044 | CONFIG_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 | 1047 | CONFIG_FUSE_FS=m |
1024 | 1048 | ||
1025 | # | 1049 | # |
1026 | # CD-ROM/DVD Filesystems | 1050 | # CD-ROM/DVD Filesystems |
@@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y | |||
1052 | CONFIG_HUGETLBFS=y | 1076 | CONFIG_HUGETLBFS=y |
1053 | CONFIG_HUGETLB_PAGE=y | 1077 | CONFIG_HUGETLB_PAGE=y |
1054 | CONFIG_RAMFS=y | 1078 | CONFIG_RAMFS=y |
1055 | # CONFIG_CONFIGFS_FS is not set | 1079 | CONFIG_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 | 1180 | CONFIG_PROFILING=y |
1181 | CONFIG_OPROFILE=m | ||
1157 | 1182 | ||
1158 | # | 1183 | # |
1159 | # Kernel hacking | 1184 | # Kernel hacking |
1160 | # | 1185 | # |
1161 | # CONFIG_PRINTK_TIME is not set | 1186 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y |
1187 | CONFIG_PRINTK_TIME=y | ||
1162 | CONFIG_ENABLE_MUST_CHECK=y | 1188 | CONFIG_ENABLE_MUST_CHECK=y |
1163 | # CONFIG_MAGIC_SYSRQ is not set | 1189 | CONFIG_MAGIC_SYSRQ=y |
1164 | # CONFIG_UNUSED_SYMBOLS is not set | 1190 | # CONFIG_UNUSED_SYMBOLS is not set |
1165 | CONFIG_DEBUG_KERNEL=y | 1191 | CONFIG_DEBUG_KERNEL=y |
1166 | CONFIG_LOG_BUF_SHIFT=14 | 1192 | CONFIG_LOG_BUF_SHIFT=14 |
1167 | CONFIG_DETECT_SOFTLOCKUP=y | 1193 | CONFIG_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 |
1170 | CONFIG_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 | 1205 | CONFIG_DEBUG_BUGVERBOSE=y |
1177 | # CONFIG_DEBUG_INFO is not set | 1206 | CONFIG_DEBUG_INFO=y |
1178 | CONFIG_DEBUG_FS=y | 1207 | CONFIG_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 | 1216 | CONFIG_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 | # | ||
6 | CONFIG_SUPERH=y | ||
7 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
8 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
9 | CONFIG_GENERIC_HWEIGHT=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_GENERIC_IRQ_PROBE=y | ||
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
13 | # CONFIG_GENERIC_TIME is not set | ||
14 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
15 | |||
16 | # | ||
17 | # Code maturity level options | ||
18 | # | ||
19 | CONFIG_EXPERIMENTAL=y | ||
20 | CONFIG_BROKEN_ON_SMP=y | ||
21 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
22 | |||
23 | # | ||
24 | # General setup | ||
25 | # | ||
26 | CONFIG_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 | ||
36 | CONFIG_INITRAMFS_SOURCE="" | ||
37 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
38 | CONFIG_SYSCTL=y | ||
39 | CONFIG_EMBEDDED=y | ||
40 | CONFIG_UID16=y | ||
41 | # CONFIG_SYSCTL_SYSCALL is not set | ||
42 | CONFIG_KALLSYMS=y | ||
43 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
44 | # CONFIG_HOTPLUG is not set | ||
45 | CONFIG_PRINTK=y | ||
46 | CONFIG_BUG=y | ||
47 | CONFIG_ELF_CORE=y | ||
48 | CONFIG_BASE_FULL=y | ||
49 | # CONFIG_FUTEX is not set | ||
50 | # CONFIG_EPOLL is not set | ||
51 | CONFIG_SLAB=y | ||
52 | CONFIG_VM_EVENT_COUNTERS=y | ||
53 | CONFIG_TINY_SHMEM=y | ||
54 | CONFIG_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 | # | ||
65 | CONFIG_BLOCK=y | ||
66 | # CONFIG_LBD is not set | ||
67 | # CONFIG_LSF is not set | ||
68 | |||
69 | # | ||
70 | # IO Schedulers | ||
71 | # | ||
72 | CONFIG_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 | ||
79 | CONFIG_DEFAULT_NOOP=y | ||
80 | CONFIG_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 | ||
108 | CONFIG_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 | # | ||
115 | CONFIG_CPU_SH2=y | ||
116 | CONFIG_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 | # | ||
127 | CONFIG_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 | # | ||
173 | CONFIG_PAGE_OFFSET=0x00000000 | ||
174 | CONFIG_MEMORY_START=0x0c000000 | ||
175 | CONFIG_MEMORY_SIZE=0x02000000 | ||
176 | CONFIG_SELECT_MEMORY_MODEL=y | ||
177 | CONFIG_FLATMEM_MANUAL=y | ||
178 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
179 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
180 | CONFIG_FLATMEM=y | ||
181 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
182 | # CONFIG_SPARSEMEM_STATIC is not set | ||
183 | CONFIG_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 | # | ||
204 | CONFIG_SH_CMT=y | ||
205 | # CONFIG_SH_MTU2 is not set | ||
206 | CONFIG_SH_PCLK_FREQ=33333333 | ||
207 | CONFIG_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 | # | ||
227 | CONFIG_HZ_100=y | ||
228 | # CONFIG_HZ_250 is not set | ||
229 | # CONFIG_HZ_1000 is not set | ||
230 | CONFIG_HZ=100 | ||
231 | # CONFIG_KEXEC is not set | ||
232 | # CONFIG_SMP is not set | ||
233 | CONFIG_PREEMPT_NONE=y | ||
234 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
235 | # CONFIG_PREEMPT is not set | ||
236 | |||
237 | # | ||
238 | # Boot options | ||
239 | # | ||
240 | CONFIG_ZERO_PAGE_OFFSET=0x00001000 | ||
241 | CONFIG_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 | # | ||
261 | CONFIG_BINFMT_FLAT=y | ||
262 | CONFIG_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 | # | ||
274 | CONFIG_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 | ||
282 | CONFIG_XFRM=y | ||
283 | # CONFIG_XFRM_USER is not set | ||
284 | # CONFIG_XFRM_SUB_POLICY is not set | ||
285 | # CONFIG_NET_KEY is not set | ||
286 | CONFIG_INET=y | ||
287 | # CONFIG_IP_MULTICAST is not set | ||
288 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
289 | CONFIG_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 | ||
300 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
301 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
302 | CONFIG_INET_XFRM_MODE_BEET=y | ||
303 | # CONFIG_INET_DIAG is not set | ||
304 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
305 | CONFIG_TCP_CONG_CUBIC=y | ||
306 | CONFIG_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 | # | ||
372 | CONFIG_MTD=y | ||
373 | # CONFIG_MTD_DEBUG is not set | ||
374 | # CONFIG_MTD_CONCAT is not set | ||
375 | CONFIG_MTD_PARTITIONS=y | ||
376 | CONFIG_MTD_REDBOOT_PARTS=y | ||
377 | CONFIG_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 | # | ||
385 | CONFIG_MTD_CHAR=y | ||
386 | CONFIG_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 | # | ||
396 | CONFIG_MTD_CFI=y | ||
397 | # CONFIG_MTD_JEDECPROBE is not set | ||
398 | CONFIG_MTD_GEN_PROBE=y | ||
399 | # CONFIG_MTD_CFI_ADV_OPTIONS is not set | ||
400 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
401 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
402 | CONFIG_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 | ||
406 | CONFIG_MTD_CFI_I1=y | ||
407 | CONFIG_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 | ||
411 | CONFIG_MTD_CFI_AMDSTD=y | ||
412 | # CONFIG_MTD_CFI_STAA is not set | ||
413 | CONFIG_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 | ||
423 | CONFIG_MTD_PHYSMAP=y | ||
424 | CONFIG_MTD_PHYSMAP_START=0x20000000 | ||
425 | CONFIG_MTD_PHYSMAP_LEN=0x1000000 | ||
426 | CONFIG_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 | ||
471 | CONFIG_BLK_DEV_RAM=y | ||
472 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
473 | CONFIG_BLK_DEV_RAM_SIZE=4096 | ||
474 | CONFIG_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 | # | ||
561 | CONFIG_SERIAL_SH_SCI=y | ||
562 | CONFIG_SERIAL_SH_SCI_NR_UARTS=4 | ||
563 | CONFIG_SERIAL_SH_SCI_CONSOLE=y | ||
564 | CONFIG_SERIAL_CORE=y | ||
565 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
566 | # CONFIG_UNIX98_PTYS is not set | ||
567 | CONFIG_LEGACY_PTYS=y | ||
568 | CONFIG_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 | ||
579 | CONFIG_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 | # | ||
613 | CONFIG_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 | # | ||
633 | CONFIG_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 | # | ||
704 | CONFIG_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 | ||
714 | CONFIG_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 | # | ||
738 | CONFIG_PROC_FS=y | ||
739 | CONFIG_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 | ||
744 | CONFIG_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 | ||
758 | CONFIG_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 | ||
781 | CONFIG_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 | ||
797 | CONFIG_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 | ||
801 | CONFIG_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 | # | ||
822 | CONFIG_CRC_CCITT=y | ||
823 | # CONFIG_CRC16 is not set | ||
824 | CONFIG_CRC32=y | ||
825 | # CONFIG_LIBCRC32C is not set | ||
826 | CONFIG_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 @@ | |||
1 | menu "Additional SuperH Device Drivers" | ||
2 | |||
3 | config 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 | |||
9 | endmenu | ||
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 @@ | |||
5 | obj-$(CONFIG_PCI) += pci/ | 5 | obj-$(CONFIG_PCI) += pci/ |
6 | obj-$(CONFIG_SH_DMA) += dma/ | 6 | obj-$(CONFIG_SH_DMA) += dma/ |
7 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 7 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
8 | 8 | obj-$(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 | ||
5 | obj-y += dma-api.o dma-isa.o | 5 | obj-y += dma-api.o |
6 | obj-$(CONFIG_ISA_DMA_API) += dma-isa.o | ||
6 | obj-$(CONFIG_SYSFS) += dma-sysfs.o | 7 | obj-$(CONFIG_SYSFS) += dma-sysfs.o |
7 | obj-$(CONFIG_SH_DMA) += dma-sh.o | 8 | obj-$(CONFIG_SH_DMA) += dma-sh.o |
8 | obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o | 9 | obj-$(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 | ||
21 | DEFINE_SPINLOCK(dma_spin_lock); | 21 | DEFINE_SPINLOCK(dma_spin_lock); |
22 | static LIST_HEAD(registered_dmac_list); | 22 | static 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 | |||
57 | struct dma_info *get_dma_info(unsigned int chan) | 24 | struct 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, ®istered_dmac_list, list) { | 32 | list_for_each_entry(info, ®istered_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 | } |
42 | EXPORT_SYMBOL(get_dma_info); | ||
43 | |||
44 | struct dma_info *get_dma_info_by_name(const char *dmac_name) | ||
45 | { | ||
46 | struct dma_info *info; | ||
47 | |||
48 | list_for_each_entry(info, ®istered_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 | } | ||
57 | EXPORT_SYMBOL(get_dma_info_by_name); | ||
76 | 58 | ||
77 | static unsigned int get_nr_channels(void) | 59 | static unsigned int get_nr_channels(void) |
78 | { | 60 | { |
@@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void) | |||
91 | struct dma_channel *get_dma_channel(unsigned int chan) | 73 | struct 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 | } |
90 | EXPORT_SYMBOL(get_dma_channel); | ||
100 | 91 | ||
101 | int get_dma_residue(unsigned int chan) | 92 | int 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 | } |
102 | EXPORT_SYMBOL(get_dma_residue); | ||
111 | 103 | ||
112 | int request_dma(unsigned int chan, const char *dev_id) | 104 | static 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 | */ | ||
128 | int 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, ®istered_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 | } | ||
162 | EXPORT_SYMBOL(request_dma_bycap); | ||
163 | |||
164 | int 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 | |||
191 | int 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 | } |
213 | EXPORT_SYMBOL(request_dma); | ||
135 | 214 | ||
136 | void free_dma(unsigned int chan) | 215 | void 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 | } |
225 | EXPORT_SYMBOL(free_dma); | ||
146 | 226 | ||
147 | void dma_wait_for_completion(unsigned int chan) | 227 | void 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 | } |
241 | EXPORT_SYMBOL(dma_wait_for_completion); | ||
242 | |||
243 | int 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, ®istered_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 | } | ||
270 | EXPORT_SYMBOL(register_chan_caps); | ||
161 | 271 | ||
162 | void dma_configure_channel(unsigned int chan, unsigned long flags) | 272 | void 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 | } |
280 | EXPORT_SYMBOL(dma_configure_channel); | ||
170 | 281 | ||
171 | int dma_xfer(unsigned int chan, unsigned long from, | 282 | int 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 | } |
295 | EXPORT_SYMBOL(dma_xfer); | ||
296 | |||
297 | int 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 | } | ||
307 | EXPORT_SYMBOL(dma_extend); | ||
184 | 308 | ||
185 | #ifdef CONFIG_PROC_FS | ||
186 | static int dma_read_proc(char *buf, char **start, off_t off, | 309 | static 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 | ||
220 | int register_dmac(struct dma_info *info) | 341 | int 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 | } |
392 | EXPORT_SYMBOL(register_dmac); | ||
274 | 393 | ||
275 | void unregister_dmac(struct dma_info *info) | 394 | void 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 | } |
407 | EXPORT_SYMBOL(unregister_dmac); | ||
288 | 408 | ||
289 | static int __init dma_api_init(void) | 409 | static 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 | |||
300 | subsys_initcall(dma_api_init); | 415 | subsys_initcall(dma_api_init); |
301 | 416 | ||
302 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 417 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); |
303 | MODULE_DESCRIPTION("DMA API for SuperH"); | 418 | MODULE_DESCRIPTION("DMA API for SuperH"); |
304 | MODULE_LICENSE("GPL"); | 419 | MODULE_LICENSE("GPL"); |
305 | |||
306 | EXPORT_SYMBOL(request_dma); | ||
307 | EXPORT_SYMBOL(free_dma); | ||
308 | EXPORT_SYMBOL(register_dmac); | ||
309 | EXPORT_SYMBOL(get_dma_residue); | ||
310 | EXPORT_SYMBOL(get_dma_info); | ||
311 | EXPORT_SYMBOL(get_dma_channel); | ||
312 | EXPORT_SYMBOL(dma_xfer); | ||
313 | EXPORT_SYMBOL(dma_wait_for_completion); | ||
314 | EXPORT_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 | ||
107 | static void sh_dmac_free_dma(struct dma_channel *chan) | 101 | static 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 | ||
113 | static void | 106 | static 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 @@ | |||
21 | static struct sysdev_class dma_sysclass = { | 21 | static struct sysdev_class dma_sysclass = { |
22 | set_kset_name("dma"), | 22 | set_kset_name("dma"), |
23 | }; | 23 | }; |
24 | |||
25 | EXPORT_SYMBOL(dma_sysclass); | 24 | EXPORT_SYMBOL(dma_sysclass); |
26 | 25 | ||
27 | static ssize_t dma_show_devices(struct sys_device *dev, char *buf) | 26 | static 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 | ||
22 | static 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 | |||
22 | int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) | 30 | int __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 | |||
19 | static 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 | } | ||
26 | static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL); | ||
27 | |||
28 | static void switch_timer(unsigned long data) | ||
29 | { | ||
30 | struct push_switch *psw = (struct push_switch *)data; | ||
31 | |||
32 | schedule_work(&psw->work); | ||
33 | } | ||
34 | |||
35 | static 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 | |||
45 | static 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 | |||
89 | err_irq: | ||
90 | free_irq(irq, pdev); | ||
91 | err: | ||
92 | kfree(psw); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static 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 | |||
115 | static struct platform_driver switch_driver = { | ||
116 | .probe = switch_drv_probe, | ||
117 | .remove = switch_drv_remove, | ||
118 | .driver = { | ||
119 | .name = DRV_NAME, | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | static 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 | |||
129 | static void __exit switch_exit(void) | ||
130 | { | ||
131 | platform_driver_unregister(&switch_driver); | ||
132 | } | ||
133 | module_init(switch_init); | ||
134 | module_exit(switch_exit); | ||
135 | |||
136 | MODULE_VERSION(DRV_VERSION); | ||
137 | MODULE_AUTHOR("Paul Mundt"); | ||
138 | MODULE_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 | ||
5 | extra-y := head.o init_task.o vmlinux.lds | 5 | extra-y := head.o init_task.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := process.o signal.o entry.o traps.o irq.o \ | 7 | obj-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 | |||
21 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 21 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
22 | obj-$(CONFIG_APM) += apm.o | 22 | obj-$(CONFIG_APM) += apm.o |
23 | obj-$(CONFIG_PM) += pm.o | 23 | obj-$(CONFIG_PM) += pm.o |
24 | obj-$(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 | ||
5 | obj-y += irq/ init.o clock.o | 5 | obj-$(CONFIG_CPU_SH2) = sh2/ |
6 | 6 | obj-$(CONFIG_CPU_SH2A) = sh2a/ | |
7 | obj-$(CONFIG_CPU_SH2) += sh2/ | 7 | obj-$(CONFIG_CPU_SH3) = sh3/ |
8 | obj-$(CONFIG_CPU_SH3) += sh3/ | 8 | obj-$(CONFIG_CPU_SH4) = sh4/ |
9 | obj-$(CONFIG_CPU_SH4) += sh4/ | ||
10 | 9 | ||
11 | obj-$(CONFIG_UBC_WAKEUP) += ubc.o | 10 | obj-$(CONFIG_UBC_WAKEUP) += ubc.o |
12 | obj-$(CONFIG_SH_ADC) += adc.o | 11 | obj-$(CONFIG_SH_ADC) += adc.o |
12 | |||
13 | obj-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 | ||
198 | struct 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 | */ | ||
205 | struct 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 | |||
231 | found: | ||
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 | # |
4 | obj-y += ipr.o imask.o | 4 | obj-y += imask.o |
5 | 5 | ||
6 | obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o | ||
6 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o | 7 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o |
7 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o | 8 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o |
8 | obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o | 9 | obj-$(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 | ||
18 | static void disable_intc2_irq(unsigned int irq) | 27 | static 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 | ||
25 | static void enable_intc2_irq(unsigned int irq) | 33 | static 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 | ||
32 | static struct irq_chip intc2_irq_chip = { | 39 | static 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 | ||
27 | static void disable_ipr_irq(unsigned int irq) | 25 | static 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 | ||
35 | static void enable_ipr_irq(unsigned int irq) | 32 | static 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 | ||
43 | static struct irq_chip ipr_irq_chip = { | 39 | static 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 | } |
63 | EXPORT_SYMBOL(make_ipr_irq); | 63 | EXPORT_SYMBOL(make_ipr_irq); |
64 | 64 | ||
65 | static 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 | |||
124 | void __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) |
143 | int ipr_irq_demux(int irq) | 66 | int 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 | ||
5 | obj-y := probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | obj-$(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 | |||
21 | const static int pll1rate[]={1,2}; | ||
22 | const 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 | |||
32 | static void master_clk_init(struct clk *clk) | ||
33 | { | ||
34 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | ||
35 | } | ||
36 | |||
37 | static struct clk_ops sh7619_master_clk_ops = { | ||
38 | .init = master_clk_init, | ||
39 | }; | ||
40 | |||
41 | static 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 | |||
47 | static struct clk_ops sh7619_module_clk_ops = { | ||
48 | .recalc = module_clk_recalc, | ||
49 | }; | ||
50 | |||
51 | static void bus_clk_recalc(struct clk *clk) | ||
52 | { | ||
53 | clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | ||
54 | } | ||
55 | |||
56 | static struct clk_ops sh7619_bus_clk_ops = { | ||
57 | .recalc = bus_clk_recalc, | ||
58 | }; | ||
59 | |||
60 | static void cpu_clk_recalc(struct clk *clk) | ||
61 | { | ||
62 | clk->rate = clk->parent->rate; | ||
63 | } | ||
64 | |||
65 | static struct clk_ops sh7619_cpu_clk_ops = { | ||
66 | .recalc = cpu_clk_recalc, | ||
67 | }; | ||
68 | |||
69 | static 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 | |||
76 | void __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 */ | ||
23 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | ||
24 | OFF_R1 = 4 /* New ABI: arg5 */ | ||
25 | OFF_R2 = 8 /* New ABI: arg6 */ | ||
26 | OFF_R3 = 12 /* New ABI: syscall_nr */ | ||
27 | OFF_R4 = 16 /* New ABI: arg0 */ | ||
28 | OFF_R5 = 20 /* New ABI: arg1 */ | ||
29 | OFF_R6 = 24 /* New ABI: arg2 */ | ||
30 | OFF_R7 = 28 /* New ABI: arg3 */ | ||
31 | OFF_SP = (15*4) | ||
32 | OFF_PC = (16*4) | ||
33 | OFF_SR = (16*4+2*4) | ||
34 | OFF_TRA = (16*4+6*4) | ||
35 | |||
36 | #include <asm/entry-macros.S> | ||
37 | |||
38 | ENTRY(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 | ||
101 | 1: | ||
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 | ||
142 | 2: | ||
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 | ||
161 | 3: | ||
162 | mov.l 5f,r10 | ||
163 | jmp @r8 | ||
164 | lds r10,pr | ||
165 | |||
166 | interrupt_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 | ||
174 | 4: .long exception_handling_table | ||
175 | 5: .long ret_from_exception | ||
176 | 6: .long ret_from_irq | ||
177 | 7: .long do_IRQ | ||
178 | 8: .long do_exception_error | ||
179 | |||
180 | trap_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 | ||
197 | 1: .long syscall_exit | ||
198 | 2: .long break_point_trap_software | ||
199 | 3: .long NR_syscalls | ||
200 | 4: .long sys_call_table | ||
201 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
202 | 5: .long trace_hardirqs_on | ||
203 | #endif | ||
204 | |||
205 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
206 | /* Unwind the stack and jmp to the debug entry */ | ||
207 | debug_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 | ||
249 | 1: .long gdb_vbr_vector | ||
250 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
251 | |||
252 | ENTRY(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 | |||
262 | 1: .long do_address_error | ||
263 | |||
264 | restore_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 | ||
312 | 2: | ||
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 | ||
324 | 3: .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 | |||
340 | ENTRY(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 | ! | ||
18 | exception_entry: | ||
19 | no = 0 | ||
20 | .rept 256 | ||
21 | mov.l r0,@-sp | ||
22 | mov #no,r0 | ||
23 | bra exception_trampoline | ||
24 | and #0xff,r0 | ||
25 | no = no + 1 | ||
26 | .endr | ||
27 | exception_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 | ||
41 | ENTRY(vbr_base) | ||
42 | vector = 0 | ||
43 | .rept 256 | ||
44 | .long exception_entry + vector * 8 | ||
45 | vector = 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 | ||
18 | int __init detect_cpu_and_cache_system(void) | 18 | int __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 | |||
15 | static 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 | |||
36 | static struct platform_device sci_device = { | ||
37 | .name = "sh-sci", | ||
38 | .id = -1, | ||
39 | .dev = { | ||
40 | .platform_data = sci_platform_data, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device *sh7619_devices[] __initdata = { | ||
45 | &sci_device, | ||
46 | }; | ||
47 | |||
48 | static 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 | |||
5 | obj-y := common.o probe.o | ||
6 | |||
7 | common-y += $(addprefix ../sh2/, ex.o) | ||
8 | common-y += $(addprefix ../sh2/, entry.o) | ||
9 | |||
10 | obj-$(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 | |||
21 | const static int pll1rate[]={1,2,3,4,6,8}; | ||
22 | const 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 | |||
35 | static void master_clk_init(struct clk *clk) | ||
36 | { | ||
37 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | ||
38 | } | ||
39 | |||
40 | static struct clk_ops sh7206_master_clk_ops = { | ||
41 | .init = master_clk_init, | ||
42 | }; | ||
43 | |||
44 | static 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 | |||
50 | static struct clk_ops sh7206_module_clk_ops = { | ||
51 | .recalc = module_clk_recalc, | ||
52 | }; | ||
53 | |||
54 | static void bus_clk_recalc(struct clk *clk) | ||
55 | { | ||
56 | clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | ||
57 | } | ||
58 | |||
59 | static struct clk_ops sh7206_bus_clk_ops = { | ||
60 | .recalc = bus_clk_recalc, | ||
61 | }; | ||
62 | |||
63 | static 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 | |||
69 | static struct clk_ops sh7206_cpu_clk_ops = { | ||
70 | .recalc = cpu_clk_recalc, | ||
71 | }; | ||
72 | |||
73 | static 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 | |||
80 | void __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 | |||
17 | int __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 | |||
15 | static 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 | |||
41 | static struct platform_device sci_device = { | ||
42 | .name = "sh-sci", | ||
43 | .id = -1, | ||
44 | .dev = { | ||
45 | .platform_data = sci_platform_data, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device *sh7206_devices[] __initdata = { | ||
50 | &sci_device, | ||
51 | }; | ||
52 | |||
53 | static 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 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | # CPU subtype setup | 7 | # CPU subtype setup |
8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o | 8 | obj-$(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 | ||
25 | static void set_bus_parent(struct clk *clk) | 25 | static 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 |
132 | ENTRY(tlb_miss_load) | 115 | ENTRY(tlb_miss_load) |
@@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store) | |||
155 | 138 | ||
156 | call_dpf: | 139 | call_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 | ||
171 | 0: 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 |
179 | 1: .long MMU_TEA | 148 | 1: .long MMU_TEA |
180 | 2: .long __do_page_fault | ||
181 | 3: .long do_page_fault | 149 | 3: .long do_page_fault |
182 | 150 | ||
183 | .align 2 | 151 | .align 2 |
@@ -203,32 +171,6 @@ call_dae: | |||
203 | 2: .long do_address_error | 171 | 2: .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 | ||
212 | debug_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 | |||
221 | debug_enter: | ||
222 | #if defined(CONFIG_SH_KGDB) | ||
223 | /* Jump to kgdb, pass stacked regs as arg */ | ||
224 | debug_kernel_sw: | ||
225 | mov.l 3f, r0 | ||
226 | jmp @r0 | ||
227 | mov r15, r4 | ||
228 | .align 2 | ||
229 | 3: .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 */ |
234 | debug_kernel_fw: | 176 | debug_kernel_fw: |
@@ -269,276 +211,6 @@ debug_kernel_fw: | |||
269 | 2: .long gdb_vbr_vector | 211 | 2: .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 | ||
276 | debug_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 | ||
290 | ENTRY(exception_error) | ||
291 | ! | ||
292 | STI() | ||
293 | mov.l 2f, r0 | ||
294 | jmp @r0 | ||
295 | nop | ||
296 | |||
297 | ! | ||
298 | .align 2 | ||
299 | 1: .long break_point_trap_software | ||
300 | 2: .long do_exception_error | ||
301 | |||
302 | .align 2 | ||
303 | ret_from_exception: | ||
304 | preempt_stop() | ||
305 | ENTRY(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 | ||
317 | ENTRY(resume_kernel) | ||
318 | mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count | ||
319 | tst r0, r0 | ||
320 | bf noresched | ||
321 | need_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 | ||
345 | noresched: | ||
346 | bra restore_all | ||
347 | nop | ||
348 | |||
349 | .align 2 | ||
350 | 1: .long PREEMPT_ACTIVE | ||
351 | 2: .long schedule | ||
352 | #endif | ||
353 | |||
354 | ENTRY(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 | ||
363 | work_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 | ||
369 | work_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 | ||
378 | work_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 | ! | ||
396 | 1: | ||
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 | ||
410 | 1: .long schedule | ||
411 | 2: .long do_notify_resume | ||
412 | |||
413 | .align 2 | ||
414 | syscall_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 | ||
429 | syscall_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 | ||
481 | ret_from_fork: | ||
482 | mov.l 1f, r8 | ||
483 | jsr @r8 | ||
484 | mov r0, r4 | ||
485 | bra syscall_exit | ||
486 | nop | ||
487 | .align 2 | ||
488 | 1: .long schedule_tail | ||
489 | ! | ||
490 | ENTRY(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) | ||
510 | syscall_badsys: ! Bad syscall number | ||
511 | mov #-ENOSYS, r0 | ||
512 | bra resume_userspace | ||
513 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
514 | ! | ||
515 | 0: | ||
516 | bra debug_trap | ||
517 | nop | ||
518 | ! | ||
519 | good_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 | ! | ||
525 | syscall_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 | ! | ||
535 | syscall_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 | ||
542 | restore_all: | 214 | restore_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 |
635 | 1: .long TRA | ||
636 | 2: .long NR_syscalls | ||
637 | 3: .long sys_call_table | ||
638 | 4: .long do_syscall_trace | ||
639 | 5: .long 0x00001000 ! DSP | 309 | 5: .long 0x00001000 ! DSP |
640 | 7: .long 0x30000000 | 310 | 7: .long 0x30000000 |
641 | 9: | ||
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: | |||
661 | 2: .long ret_from_exception | 331 | 2: .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 |
665 | tlb_miss: | 359 | tlb_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 | |||
477 | 10: 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... | ||
493 | 1: .long swapper_pg_dir | ||
494 | 4: .short (PTRS_PER_PGD-1) << 2 | ||
495 | 5: .short _PAGE_PRESENT | ||
496 | 7: .long _PAGE_FLAGS_HARDWARE_MASK | ||
497 | 8: .long MMU_PTEH | ||
498 | #ifdef COUNT_EXCEPTIONS | ||
499 | 9: .long exception_count_miss | ||
500 | #endif | ||
501 | |||
502 | ! Either pgd or pte not present | ||
503 | 20: 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: | |||
826 | 2: .long 0x000080f0 ! FD=1, IMASK=15 | 673 | 2: .long 0x000080f0 ! FD=1, IMASK=15 |
827 | 3: .long 0xcfffffff ! RB=0, BL=0 | 674 | 3: .long 0xcfffffff ! RB=0, BL=0 |
828 | 4: .long exception_handling_table | 675 | 4: .long exception_handling_table |
676 | #ifdef COUNT_EXCEPTIONS | ||
677 | 5: .long exception_count_table | ||
678 | #endif | ||
829 | 679 | ||
830 | interrupt_exception: | 680 | interrupt_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 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o common.o |
6 | common-y += $(addprefix ../sh3/, entry.o) | ||
6 | 7 | ||
7 | obj-$(CONFIG_SH_FPU) += fpu.o | 8 | obj-$(CONFIG_SH_FPU) += fpu.o |
8 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 9 | obj-$(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 | ||
98 | static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) | 98 | static 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 | ||
152 | static int __init sh4202_clk_init(void) | 152 | static 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 | ||
99 | static int __init sh7780_clk_init(void) | 99 | static 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 | ||
298 | asmlinkage void | 295 | asmlinkage void |
299 | do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, | 296 | do_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 (®s)) | 302 | if (ieee_fpe_handler(regs)) |
305 | return; | 303 | return; |
306 | 304 | ||
307 | regs.pc += 2; | 305 | regs->pc += 2; |
308 | save_fpu(tsk, ®s); | 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 | ||
314 | asmlinkage void | 310 | asmlinkage void |
315 | do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, | 311 | do_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(®s); | 317 | grab_fpu(regs); |
321 | if (!user_mode(®s)) { | 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 | ||
15 | static struct plat_sci_port sci_platform_data[] = { | 17 | static 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 | |||
52 | static 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 | |||
76 | static 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 | |||
88 | static 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 */ | ||
96 | unsigned 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 */ | ||
107 | void ipr_irq_enable_irlm(void) | ||
108 | { | ||
109 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | ||
110 | } | ||
111 | |||
112 | void __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 | ||
81 | static struct intc2_data intc2_irq_table[] = { | 81 | static 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 | ||
103 | void __init init_IRQ_intc2(void) | 105 | void __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 | } |
70 | EXPORT_SYMBOL(sq_flush_range); | ||
70 | 71 | ||
71 | static inline void sq_mapping_list_add(struct sq_mapping *map) | 72 | static 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 | } |
197 | EXPORT_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 | } |
239 | EXPORT_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); | |||
402 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); | 405 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); |
403 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); | 406 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); |
404 | MODULE_LICENSE("GPL"); | 407 | MODULE_LICENSE("GPL"); |
405 | |||
406 | EXPORT_SYMBOL(sq_remap); | ||
407 | EXPORT_SYMBOL(sq_unmap); | ||
408 | EXPORT_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 | |||
73 | static struct uart_port scif_port = { | 65 | static 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 | ||
78 | static void scif_sercon_putc(int c) | 70 | static 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 | */ | ||
116 | static void scif_sercon_init(int baud) | 113 | static 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 | ||
63 | debug_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 | |||
72 | debug_enter: | ||
73 | #if defined(CONFIG_SH_KGDB) | ||
74 | /* Jump to kgdb, pass stacked regs as arg */ | ||
75 | debug_kernel_sw: | ||
76 | mov.l 3f, r0 | ||
77 | jmp @r0 | ||
78 | mov r15, r4 | ||
79 | .align 2 | ||
80 | 3: .long kgdb_handle_exception | ||
81 | #endif /* CONFIG_SH_KGDB */ | ||
82 | |||
83 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
84 | |||
85 | |||
86 | .align 2 | ||
87 | debug_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 | ||
101 | ENTRY(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 | ||
115 | 1: .long break_point_trap_software | ||
116 | 2: .long do_exception_error | ||
117 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
118 | 3: .long trace_hardirqs_on | ||
119 | #endif | ||
120 | |||
121 | .align 2 | ||
122 | ret_from_exception: | ||
123 | preempt_stop() | ||
124 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
125 | mov.l 4f, r0 | ||
126 | jsr @r0 | ||
127 | nop | ||
128 | #endif | ||
129 | ENTRY(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 | ||
141 | ENTRY(resume_kernel) | ||
142 | mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count | ||
143 | tst r0, r0 | ||
144 | bf noresched | ||
145 | need_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 | |||
180 | noresched: | ||
181 | bra __restore_all | ||
182 | nop | ||
183 | |||
184 | .align 2 | ||
185 | 1: .long PREEMPT_ACTIVE | ||
186 | 2: .long schedule | ||
187 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
188 | 3: .long trace_hardirqs_on | ||
189 | 4: .long trace_hardirqs_off | ||
190 | #endif | ||
191 | #endif | ||
192 | |||
193 | ENTRY(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 | ||
207 | work_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 | ||
213 | work_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 | ||
222 | work_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 | ! | ||
240 | 1: | ||
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 | ||
259 | 1: .long schedule | ||
260 | 2: .long do_notify_resume | ||
261 | 3: .long restore_all | ||
262 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
263 | 4: .long trace_hardirqs_on | ||
264 | 5: .long trace_hardirqs_off | ||
265 | #endif | ||
266 | |||
267 | .align 2 | ||
268 | syscall_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 | ||
288 | syscall_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 | ||
320 | 1: .long restore_all | ||
321 | |||
322 | .align 2 | ||
323 | not_syscall_tra: | ||
324 | bra debug_trap | ||
325 | nop | ||
326 | |||
327 | .align 2 | ||
328 | syscall_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 | ||
359 | ret_from_fork: | ||
360 | mov.l 1f, r8 | ||
361 | jsr @r8 | ||
362 | mov r0, r4 | ||
363 | bra syscall_exit | ||
364 | nop | ||
365 | .align 2 | ||
366 | 1: .long schedule_tail | ||
367 | ! | ||
368 | ENTRY(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 | ! | ||
399 | syscall_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 | ! | ||
409 | syscall_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) | ||
425 | 1: .long TRA | ||
426 | #endif | ||
427 | 2: .long NR_syscalls | ||
428 | 3: .long sys_call_table | ||
429 | 4: .long do_syscall_trace | ||
430 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
431 | 5: .long trace_hardirqs_on | ||
432 | 6: .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) | ||
104 | 1: .long 0x000000F0 ! IMASK=0xF | ||
105 | #else | ||
98 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF | 106 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF |
107 | #endif | ||
99 | 2: .long init_thread_union+THREAD_SIZE | 108 | 2: .long init_thread_union+THREAD_SIZE |
100 | 3: .long __bss_start | 109 | 3: .long __bss_start |
101 | 4: .long _end | 110 | 4: .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 | ||
81 | static union irq_ctx *hardirq_ctx[NR_CPUS]; | 81 | static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; |
82 | static union irq_ctx *softirq_ctx[NR_CPUS]; | 82 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | 85 | asmlinkage 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(®s); | 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 | } |
250 | EXPORT_SYMBOL(do_softirq); | 262 | EXPORT_SYMBOL(do_softirq); |
251 | #endif | 263 | #endif |
264 | |||
265 | void __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 | ||
386 | asmlinkage int sys_fork(unsigned long r4, unsigned long r5, | 386 | asmlinkage 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], ®s, 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, | |||
398 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | 399 | asmlinkage 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, ®s, 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 | */ |
419 | asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | 421 | asmlinkage 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], ®s, | 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 | */ |
430 | asmlinkage int sys_execve(char *ufilename, char **uargv, | 433 | asmlinkage 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 | ®s); | 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 | ||
475 | asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, | 479 | asmlinkage 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 | ||
493 | asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, | 495 | asmlinkage 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 |
17 | relocate_new_kernel: | 15 | relocate_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: | |||
32 | 0: | 30 | 0: |
33 | mov.l @r4+,r0 /* cmd = *ind++ */ | 31 | mov.l @r4+,r0 /* cmd = *ind++ */ |
34 | 32 | ||
35 | 1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ | 33 | 1: /* 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: | |||
92 | 10: | 90 | 10: |
93 | .long PAGE_SIZE | 91 | .long PAGE_SIZE |
94 | 11: | 92 | 11: |
95 | .long 0xa0000000 | 93 | .long P2SEG |
96 | 94 | ||
97 | relocate_new_kernel_end: | 95 | relocate_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) | |||
392 | subsys_initcall(topology_init); | 392 | subsys_initcall(topology_init); |
393 | 393 | ||
394 | static const char *cpu_name[] = { | 394 | static 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); | |||
73 | DECLARE_EXPORT(__movstr); | 73 | DECLARE_EXPORT(__movstr); |
74 | DECLARE_EXPORT(__movstrSI16); | 74 | DECLARE_EXPORT(__movstrSI16); |
75 | 75 | ||
76 | EXPORT_SYMBOL(strcpy); | ||
77 | |||
78 | #ifdef CONFIG_CPU_SH4 | 76 | #ifdef CONFIG_CPU_SH4 |
79 | DECLARE_EXPORT(__movstr_i4_even); | 77 | DECLARE_EXPORT(__movstr_i4_even); |
80 | DECLARE_EXPORT(__movstr_i4_odd); | 78 | DECLARE_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 @@ | |||
37 | asmlinkage int | 37 | asmlinkage int |
38 | sys_sigsuspend(old_sigset_t mask, | 38 | sys_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(¤t->sighand->siglock); | 43 | spin_lock_irq(¤t->sighand->siglock); |
@@ -52,7 +52,7 @@ sys_sigsuspend(old_sigset_t mask, | |||
52 | return -ERESTARTNOHAND; | 52 | return -ERESTARTNOHAND; |
53 | } | 53 | } |
54 | 54 | ||
55 | asmlinkage int | 55 | asmlinkage int |
56 | sys_sigaction(int sig, const struct old_sigaction __user *act, | 56 | sys_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, | |||
87 | asmlinkage int | 87 | asmlinkage int |
88 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 88 | sys_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 | ||
104 | struct sigframe | 110 | struct sigframe |
@@ -194,9 +200,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p | |||
194 | 200 | ||
195 | asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, | 201 | asmlinkage 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(¤t->sighand->siglock); | 224 | spin_unlock_irq(¤t->sighand->siglock); |
218 | 225 | ||
219 | if (restore_sigcontext(®s, &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 | ||
228 | asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, | 235 | asmlinkage 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(¤t->sighand->siglock); | 255 | spin_unlock_irq(¤t->sighand->siglock); |
248 | 256 | ||
249 | if (restore_sigcontext(®s, &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 | */ | ||
20 | void 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 | */ |
34 | asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, | 34 | asmlinkage 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 | ||
51 | EXPORT_SYMBOL(shm_align_mask); | 52 | EXPORT_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 | ||
139 | static inline long | 142 | static inline long |
140 | do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 143 | do_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 |
51 | void do_gettimeofday(struct timeval *tv) | 53 | void 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 | ||
180 | static 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 | |||
201 | static 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 | */ | ||
227 | void 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 | |||
246 | static 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 | |||
252 | static 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 | } | ||
264 | static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); | ||
265 | |||
266 | /* | ||
267 | * dyntick=enable|disable | ||
268 | */ | ||
269 | static char dyntick_str[4] __initdata = ""; | ||
270 | |||
271 | static 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 | |||
172 | static int __init timer_init_sysfs(void) | 281 | static 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 | } |
181 | device_initcall(timer_init_sysfs); | 305 | device_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 @@ | |||
5 | obj-y := timer.o | 5 | obj-y := timer.o |
6 | 6 | ||
7 | obj-$(CONFIG_SH_TMU) += timer-tmu.o | 7 | obj-$(CONFIG_SH_TMU) += timer-tmu.o |
8 | obj-$(CONFIG_SH_MTU2) += timer-mtu2.o | ||
9 | obj-$(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 | |||
48 | static 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 | |||
92 | static 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 | |||
115 | static 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 | |||
122 | static 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 | |||
131 | static 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 | |||
137 | static struct clk_ops cmt_clk_ops = { | ||
138 | .init = cmt_clk_init, | ||
139 | .recalc = cmt_clk_recalc, | ||
140 | }; | ||
141 | |||
142 | static struct clk cmt0_clk = { | ||
143 | .name = "cmt0_clk", | ||
144 | .ops = &cmt_clk_ops, | ||
145 | }; | ||
146 | |||
147 | static int cmt_timer_start(void) | ||
148 | { | ||
149 | ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int cmt_timer_stop(void) | ||
154 | { | ||
155 | ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static 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 | |||
184 | struct 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 | |||
193 | struct 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 | |||
51 | static 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 | |||
93 | static 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 | |||
110 | static 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 | |||
117 | static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 }; | ||
118 | |||
119 | static 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 | |||
129 | static 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 | |||
135 | static struct clk_ops mtu2_clk_ops = { | ||
136 | .init = mtu2_clk_init, | ||
137 | .recalc = mtu2_clk_recalc, | ||
138 | }; | ||
139 | |||
140 | static struct clk mtu2_clk1 = { | ||
141 | .name = "mtu2_clk1", | ||
142 | .ops = &mtu2_clk_ops, | ||
143 | }; | ||
144 | |||
145 | static int mtu2_timer_start(void) | ||
146 | { | ||
147 | ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int mtu2_timer_stop(void) | ||
152 | { | ||
153 | ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR); | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static 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 | |||
188 | struct 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 | |||
197 | struct 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 | ||
34 | static DEFINE_SPINLOCK(tmu0_lock); | ||
35 | |||
36 | static unsigned long tmu_timer_get_offset(void) | 33 | static 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) | |||
106 | static struct irqaction tmu_irq = { | 99 | static 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 | ||
105 | static 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 | ||
355 | static int handle_unaligned_notify_count = 10; | ||
356 | |||
345 | static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | 357 | static 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 | */ |
485 | asmlinkage void do_address_error(struct pt_regs *regs, | 515 | asmlinkage 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: | 562 | uspace_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 | ||
627 | asmlinkage 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 */ |
573 | extern int do_fpu_inst(unsigned short, struct pt_regs *); | 648 | extern int do_fpu_inst(unsigned short, struct pt_regs *); |
574 | extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, | 649 | extern 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 | ||
577 | asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, | 652 | asmlinkage 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, ®s); | 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(®s)) { | 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(®s); | ||
612 | force_sig(SIGILL, tsk); | 687 | force_sig(SIGILL, tsk); |
613 | die_if_no_fixup("reserved instruction", ®s, 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 | ||
659 | asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, | 734 | asmlinkage 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, ®s)) { | 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, ®s)) | 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(®s); | ||
683 | force_sig(SIGILL, tsk); | 758 | force_sig(SIGILL, tsk); |
684 | die_if_no_fixup("illegal slot instruction", ®s, error_code); | 759 | die_if_no_fixup("illegal slot instruction", regs, error_code); |
685 | } | 760 | } |
686 | 761 | ||
687 | asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, | 762 | asmlinkage 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", ®s, 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 | ||
821 | extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5, | ||
822 | unsigned long r6, unsigned long r7, | ||
823 | struct pt_regs __regs); | ||
824 | |||
744 | void __init trap_init(void) | 825 | void __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 | ||
789 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 883 | void 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 | # |
6 | config CPU_SH2 | 6 | config CPU_SH2 |
7 | select SH_WRITETHROUGH if !CPU_SH2A | ||
7 | bool | 8 | bool |
8 | select SH_WRITETHROUGH | 9 | |
10 | config CPU_SH2A | ||
11 | bool | ||
12 | select CPU_SH2 | ||
9 | 13 | ||
10 | config CPU_SH3 | 14 | config 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 | ||
20 | config CPU_SH4A | 25 | config 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 | ||
48 | config CPU_SUBTYPE_SH7619 | ||
49 | bool "Support SH7619 processor" | ||
50 | select CPU_SH2 | ||
51 | |||
52 | comment "SH-2A Processor Support" | ||
53 | |||
54 | config CPU_SUBTYPE_SH7206 | ||
55 | bool "Support SH7206 processor" | ||
56 | select CPU_SH2A | ||
57 | |||
43 | comment "SH-3 Processor Support" | 58 | comment "SH-3 Processor Support" |
44 | 59 | ||
45 | config CPU_SUBTYPE_SH7300 | 60 | config CPU_SUBTYPE_SH7300 |
@@ -89,6 +104,7 @@ comment "SH-4 Processor Support" | |||
89 | config CPU_SUBTYPE_SH7750 | 104 | config 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 | ||
108 | config CPU_SUBTYPE_SH7750S | 125 | config 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 | ||
113 | config CPU_SUBTYPE_SH7751 | 131 | config 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 | ||
125 | config CPU_SUBTYPE_SH7760 | 145 | config 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 | ||
180 | config CPU_SUBTYPE_SH7785 | ||
181 | bool "Support SH7785 processor" | ||
182 | select CPU_SH4A | ||
183 | select CPU_HAS_INTC2_IRQ | ||
184 | |||
160 | comment "SH4AL-DSP Processor Support" | 185 | comment "SH4AL-DSP Processor Support" |
161 | 186 | ||
162 | config CPU_SUBTYPE_SH73180 | 187 | config CPU_SUBTYPE_SH73180 |
@@ -216,13 +241,22 @@ config MEMORY_SIZE | |||
216 | 241 | ||
217 | config 32BIT | 242 | config 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 | ||
251 | config 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 | |||
226 | config VSYSCALL | 260 | config 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 | ||
239 | choice | 273 | choice |
274 | prompt "Kernel page size" | ||
275 | default PAGE_SIZE_4KB | ||
276 | |||
277 | config PAGE_SIZE_4KB | ||
278 | bool "4kB" | ||
279 | help | ||
280 | This is the default page size used by all SuperH CPUs. | ||
281 | |||
282 | config 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 | |||
288 | config 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 | |||
295 | endchoice | ||
296 | |||
297 | choice | ||
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 | ||
244 | config HUGETLB_PAGE_SIZE_64K | 302 | config HUGETLB_PAGE_SIZE_64K |
245 | bool "64K" | 303 | bool "64kB" |
304 | |||
305 | config HUGETLB_PAGE_SIZE_256K | ||
306 | bool "256kB" | ||
307 | depends on X2TLB | ||
246 | 308 | ||
247 | config HUGETLB_PAGE_SIZE_1MB | 309 | config HUGETLB_PAGE_SIZE_1MB |
248 | bool "1MB" | 310 | bool "1MB" |
249 | 311 | ||
312 | config HUGETLB_PAGE_SIZE_4MB | ||
313 | bool "4MB" | ||
314 | depends on X2TLB | ||
315 | |||
316 | config HUGETLB_PAGE_SIZE_64MB | ||
317 | bool "64MB" | ||
318 | depends on X2TLB | ||
319 | |||
250 | endchoice | 320 | endchoice |
251 | 321 | ||
252 | source "mm/Kconfig" | 322 | source "mm/Kconfig" |
@@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED | |||
274 | 344 | ||
275 | config SH_WRITETHROUGH | 345 | config 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 | /* | 18 | void __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 | */ | ||
24 | unsigned 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 | 32 | void __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 | |||
45 | void __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 | ||
88 | struct semaphore p3map_sem[MAX_P3_SEMAPHORES]; | 84 | struct mutex p3map_mutex[MAX_P3_MUTEXES]; |
89 | 85 | ||
90 | void __init p3_cache_init(void) | 86 | void __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 | */ |
23 | ENTRY(clear_page_slow) | 23 | ENTRY(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 | ||
55 | ENTRY(__clear_user) | 55 | ENTRY(__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 | */ |
169 | ENTRY(__clear_user_page) | 169 | ENTRY(__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 | ! |
36 | 1: mov.l @r11+,r0 | 36 | 1: 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 | ! |
100 | 1: ocbi @r9 | 100 | 1: 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 | */ |
29 | asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, | 29 | asmlinkage 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 | */ |
67 | good_area: | 113 | good_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: | |||
104 | bad_area: | 151 | bad_area: |
105 | up_read(&mm->mmap_sem); | 152 | up_read(&mm->mmap_sem); |
106 | 153 | ||
154 | bad_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 | */ | ||
193 | asmlinkage 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; | ||
259 | unlock: | ||
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 | */ |
162 | void __init paging_init(void) | 151 | void __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 | ||
228 | void __init mem_init(void) | 218 | void __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 | ||
40 | static void clear_page_dma(void *to) | 40 | static 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 | ||
24 | extern struct semaphore p3map_sem[]; | 14 | extern 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 | |||
30 | TITAN SH_TITAN | 30 | TITAN SH_TITAN |
31 | SHMIN SH_SHMIN | 31 | SHMIN SH_SHMIN |
32 | 7710VOIPGW SH_7710VOIPGW | 32 | 7710VOIPGW SH_7710VOIPGW |
33 | 7206SE SH_7206_SOLUTION_ENGINE | ||
34 | 7619SE SH_7619_SOLUTION_ENGINE | ||