diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 16:08:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 16:08:20 -0400 |
commit | d84c4124c4b6611301b402e8611b7e36de3bd351 (patch) | |
tree | d83cfaabfb901755d85074815ad948028dc7b03f /arch/sh | |
parent | 932c37c375cca25175f9b6acee4c75d7a96d985f (diff) | |
parent | a3cf4ea8729a5d448742fd5a0a003827c9f25cb6 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6:
sh: Fix stacktrace simplification fallout.
sh: SH7760 DMABRG support.
sh: clockevent/clocksource/hrtimers/nohz TMU support.
sh: Truncate MAX_ACTIVE_REGIONS for the common case.
rtc: rtc-sh: Fix rtc_dev pointer for rtc_update_irq().
sh: Convert to common die chain.
sh: Wire up utimensat syscall.
sh: landisk mv_nr_irqs definition.
sh: Fixup ndelay() xloops calculation for alternate HZ.
sh: Add 32-bit opcode feature CPU flag.
sh: Fix PC adjustments for varying opcode length.
sh: Support for SH-2A 32-bit opcodes.
sh: Kill off redundant __div64_32 symbol export.
sh: Share exception vector table for SH-3/4.
sh: Always define TRAPA_BUG_OPCODE.
sh: __GFP_REPEAT for pte allocations, too.
rtc: rtc-sh: Fix up dev_dbg() warnings.
sh: generic quicklist support.
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/Kconfig | 29 | ||||
-rw-r--r-- | arch/sh/boards/landisk/setup.c | 1 | ||||
-rw-r--r-- | arch/sh/drivers/Makefile | 3 | ||||
-rw-r--r-- | arch/sh/drivers/dma/Kconfig | 20 | ||||
-rw-r--r-- | arch/sh/drivers/dma/Makefile | 4 | ||||
-rw-r--r-- | arch/sh/drivers/dma/dmabrg.c | 196 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/Makefile | 5 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/opcode_helper.c | 55 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/probe.c | 1 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/ex.S | 13 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/Makefile | 6 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/ex.S | 62 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/fpu.c | 3 | ||||
-rw-r--r-- | arch/sh/kernel/process.c | 16 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/sh_ksyms.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/signal.c | 13 | ||||
-rw-r--r-- | arch/sh/kernel/stacktrace.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/syscalls.S | 1 | ||||
-rw-r--r-- | arch/sh/kernel/time.c | 172 | ||||
-rw-r--r-- | arch/sh/kernel/timers/timer-tmu.c | 182 | ||||
-rw-r--r-- | arch/sh/kernel/traps.c | 20 | ||||
-rw-r--r-- | arch/sh/lib/delay.c | 5 | ||||
-rw-r--r-- | arch/sh/mm/Kconfig | 7 | ||||
-rw-r--r-- | arch/sh/mm/fault.c | 2 | ||||
-rw-r--r-- | arch/sh/mm/init.c | 2 |
26 files changed, 495 insertions, 329 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d74eb120a9c6..038179ecf6a9 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -52,6 +52,9 @@ config GENERIC_IOMAP | |||
52 | config GENERIC_TIME | 52 | config GENERIC_TIME |
53 | def_bool n | 53 | def_bool n |
54 | 54 | ||
55 | config GENERIC_CLOCKEVENTS | ||
56 | def_bool n | ||
57 | |||
55 | config SYS_SUPPORTS_APM_EMULATION | 58 | config SYS_SUPPORTS_APM_EMULATION |
56 | bool | 59 | bool |
57 | 60 | ||
@@ -436,11 +439,11 @@ endmenu | |||
436 | 439 | ||
437 | menu "Timer and clock configuration" | 440 | menu "Timer and clock configuration" |
438 | 441 | ||
439 | if !GENERIC_TIME | ||
440 | |||
441 | config SH_TMU | 442 | config SH_TMU |
442 | bool "TMU timer support" | 443 | bool "TMU timer support" |
443 | depends on CPU_SH3 || CPU_SH4 | 444 | depends on CPU_SH3 || CPU_SH4 |
445 | select GENERIC_TIME | ||
446 | select GENERIC_CLOCKEVENTS | ||
444 | default y | 447 | default y |
445 | help | 448 | help |
446 | This enables the use of the TMU as the system timer. | 449 | This enables the use of the TMU as the system timer. |
@@ -459,8 +462,6 @@ config SH_MTU2 | |||
459 | help | 462 | help |
460 | This enables the use of the MTU2 as the system timer. | 463 | This enables the use of the MTU2 as the system timer. |
461 | 464 | ||
462 | endif | ||
463 | |||
464 | config SH_TIMER_IRQ | 465 | config SH_TIMER_IRQ |
465 | int | 466 | int |
466 | default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 | 467 | default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 |
@@ -468,24 +469,6 @@ config SH_TIMER_IRQ | |||
468 | default "140" if CPU_SUBTYPE_SH7206 | 469 | default "140" if CPU_SUBTYPE_SH7206 |
469 | default "16" | 470 | default "16" |
470 | 471 | ||
471 | config NO_IDLE_HZ | ||
472 | bool "Dynamic tick timer" | ||
473 | help | ||
474 | Select this option if you want to disable continuous timer ticks | ||
475 | and have them programmed to occur as required. This option saves | ||
476 | power as the system can remain in idle state for longer. | ||
477 | |||
478 | By default dynamic tick is disabled during the boot, and can be | ||
479 | manually enabled with: | ||
480 | |||
481 | echo 1 > /sys/devices/system/timer/timer0/dyn_tick | ||
482 | |||
483 | Alternatively, if you want dynamic tick automatically enabled | ||
484 | during boot, pass "dyntick=enable" via the kernel command string. | ||
485 | |||
486 | Please note that dynamic tick may affect the accuracy of | ||
487 | timekeeping on some platforms depending on the implementation. | ||
488 | |||
489 | config SH_PCLK_FREQ | 472 | config SH_PCLK_FREQ |
490 | int "Peripheral clock frequency (in Hz)" | 473 | int "Peripheral clock frequency (in Hz)" |
491 | default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 | 474 | default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 |
@@ -509,6 +492,8 @@ config SH_CLK_MD | |||
509 | help | 492 | help |
510 | MD2 - MD0 pin setting. | 493 | MD2 - MD0 pin setting. |
511 | 494 | ||
495 | source "kernel/time/Kconfig" | ||
496 | |||
512 | endmenu | 497 | endmenu |
513 | 498 | ||
514 | menu "CPU Frequency scaling" | 499 | menu "CPU Frequency scaling" |
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c index a83a5d9587bb..4058b4f50d44 100644 --- a/arch/sh/boards/landisk/setup.c +++ b/arch/sh/boards/landisk/setup.c | |||
@@ -93,6 +93,7 @@ static void __init landisk_setup(char **cmdline_p) | |||
93 | */ | 93 | */ |
94 | struct sh_machine_vector mv_landisk __initmv = { | 94 | struct sh_machine_vector mv_landisk __initmv = { |
95 | .mv_name = "LANDISK", | 95 | .mv_name = "LANDISK", |
96 | .mv_nr_irqs = 72, | ||
96 | .mv_setup = landisk_setup, | 97 | .mv_setup = landisk_setup, |
97 | .mv_init_irq = init_landisk_IRQ, | 98 | .mv_init_irq = init_landisk_IRQ, |
98 | }; | 99 | }; |
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile index 6cb92676c5fc..e13f06bebd92 100644 --- a/arch/sh/drivers/Makefile +++ b/arch/sh/drivers/Makefile | |||
@@ -2,8 +2,9 @@ | |||
2 | # Makefile for the Linux SuperH-specific device drivers. | 2 | # Makefile for the Linux SuperH-specific device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += dma/ | ||
6 | |||
5 | obj-$(CONFIG_PCI) += pci/ | 7 | obj-$(CONFIG_PCI) += pci/ |
6 | obj-$(CONFIG_SH_DMA) += dma/ | ||
7 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 8 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
8 | obj-$(CONFIG_PUSH_SWITCH) += push-switch.o | 9 | obj-$(CONFIG_PUSH_SWITCH) += push-switch.o |
9 | obj-$(CONFIG_HEARTBEAT) += heartbeat.o | 10 | obj-$(CONFIG_HEARTBEAT) += heartbeat.o |
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index defc13c37d48..99935f9daf4b 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig | |||
@@ -1,12 +1,12 @@ | |||
1 | menu "DMA support" | 1 | menu "DMA support" |
2 | 2 | ||
3 | config SH_DMA | 3 | config SH_DMA_API |
4 | bool "DMA controller (DMAC) support" | 4 | bool |
5 | help | ||
6 | Selecting this option will provide same API as PC's Direct Memory | ||
7 | Access Controller(8237A) for SuperH DMAC. | ||
8 | 5 | ||
9 | If unsure, say N. | 6 | config SH_DMA |
7 | bool "SuperH on-chip DMA controller (DMAC) support" | ||
8 | select SH_DMA_API | ||
9 | default n | ||
10 | 10 | ||
11 | config NR_ONCHIP_DMA_CHANNELS | 11 | config NR_ONCHIP_DMA_CHANNELS |
12 | depends on SH_DMA | 12 | depends on SH_DMA |
@@ -53,4 +53,12 @@ config DMA_PAGE_OPS_CHANNEL | |||
53 | in case channel 3 is unavailable. On the SH4, channels 1,2, and 3 | 53 | in case channel 3 is unavailable. On the SH4, channels 1,2, and 3 |
54 | are dual-address capable. | 54 | are dual-address capable. |
55 | 55 | ||
56 | config SH_DMABRG | ||
57 | bool "SH7760 DMABRG support" | ||
58 | depends on CPU_SUBTYPE_SH7760 | ||
59 | help | ||
60 | The DMABRG does data transfers from main memory to Audio/USB units | ||
61 | of the SH7760. | ||
62 | Say Y if you want to use Audio/USB DMA on your SH7760 board. | ||
63 | |||
56 | endmenu | 64 | endmenu |
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile index db1295d32268..1ac812d24488 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 | 5 | obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o |
6 | obj-$(CONFIG_ISA_DMA_API) += dma-isa.o | 6 | obj-$(CONFIG_ISA_DMA_API) += dma-isa.o |
7 | obj-$(CONFIG_SYSFS) += dma-sysfs.o | ||
8 | obj-$(CONFIG_SH_DMA) += dma-sh.o | 7 | obj-$(CONFIG_SH_DMA) += dma-sh.o |
9 | obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o | 8 | obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o |
9 | obj-$(CONFIG_SH_DMABRG) += dmabrg.o | ||
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c new file mode 100644 index 000000000000..9d0a29370f21 --- /dev/null +++ b/arch/sh/drivers/dma/dmabrg.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * SH7760 DMABRG IRQ handling | ||
3 | * | ||
4 | * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com> | ||
5 | * licensed under the GPLv2. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <asm/dma.h> | ||
12 | #include <asm/dmabrg.h> | ||
13 | #include <asm/io.h> | ||
14 | |||
15 | /* | ||
16 | * The DMABRG is a special DMA unit within the SH7760. It does transfers | ||
17 | * from USB-SRAM/Audio units to main memory (and also the LCDC; but that | ||
18 | * part is sensibly placed in the LCDC registers and requires no irqs) | ||
19 | * It has 3 IRQ lines which trigger 10 events, and works independently | ||
20 | * from the traditional SH DMAC (although it blocks usage of DMAC 0) | ||
21 | * | ||
22 | * BRGIRQID | component | dir | meaning | source | ||
23 | * ----------------------------------------------------- | ||
24 | * 0 | USB-DMA | ... | xfer done | DMABRGI1 | ||
25 | * 1 | USB-UAE | ... | USB addr err.| DMABRGI0 | ||
26 | * 2 | HAC0/SSI0 | play| all done | DMABRGI1 | ||
27 | * 3 | HAC0/SSI0 | play| half done | DMABRGI2 | ||
28 | * 4 | HAC0/SSI0 | rec | all done | DMABRGI1 | ||
29 | * 5 | HAC0/SSI0 | rec | half done | DMABRGI2 | ||
30 | * 6 | HAC1/SSI1 | play| all done | DMABRGI1 | ||
31 | * 7 | HAC1/SSI1 | play| half done | DMABRGI2 | ||
32 | * 8 | HAC1/SSI1 | rec | all done | DMABRGI1 | ||
33 | * 9 | HAC1/SSI1 | rec | half done | DMABRGI2 | ||
34 | * | ||
35 | * all can be enabled/disabled in the DMABRGCR register, | ||
36 | * as well as checked if they occured. | ||
37 | * | ||
38 | * DMABRGI0 services USB DMA Address errors, but it still must be | ||
39 | * enabled/acked in the DMABRGCR register. USB-DMA complete indicator | ||
40 | * is grouped together with the audio buffer end indicators, too bad... | ||
41 | * | ||
42 | * DMABRGCR: Bits 31-24: audio-dma ENABLE flags, | ||
43 | * Bits 23-16: audio-dma STATUS flags, | ||
44 | * Bits 9-8: USB error/xfer ENABLE, | ||
45 | * Bits 1-0: USB error/xfer STATUS. | ||
46 | * Ack an IRQ by writing 0 to the STATUS flag. | ||
47 | * Mask IRQ by writing 0 to ENABLE flag. | ||
48 | * | ||
49 | * Usage is almost like with any other IRQ: | ||
50 | * dmabrg_request_irq(BRGIRQID, handler, data) | ||
51 | * dmabrg_free_irq(BRGIRQID) | ||
52 | * | ||
53 | * handler prototype: void brgirqhandler(void *data) | ||
54 | */ | ||
55 | |||
56 | #define DMARSRA 0xfe090000 | ||
57 | #define DMAOR 0xffa00040 | ||
58 | #define DMACHCR0 0xffa0000c | ||
59 | #define DMABRGCR 0xfe3c0000 | ||
60 | |||
61 | #define DMAOR_BRG 0x0000c000 | ||
62 | #define DMAOR_DMEN 0x00000001 | ||
63 | |||
64 | #define DMABRGI0 68 | ||
65 | #define DMABRGI1 69 | ||
66 | #define DMABRGI2 70 | ||
67 | |||
68 | struct dmabrg_handler { | ||
69 | void (*handler)(void *); | ||
70 | void *data; | ||
71 | } *dmabrg_handlers; | ||
72 | |||
73 | static inline void dmabrg_call_handler(int i) | ||
74 | { | ||
75 | dmabrg_handlers[i].handler(dmabrg_handlers[i].data); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * main DMABRG irq handler. It acks irqs and then | ||
80 | * handles every set and unmasked bit sequentially. | ||
81 | * No locking and no validity checks; it should be | ||
82 | * as fast as possible (audio!) | ||
83 | */ | ||
84 | static irqreturn_t dmabrg_irq(int irq, void *data) | ||
85 | { | ||
86 | unsigned long dcr; | ||
87 | unsigned int i; | ||
88 | |||
89 | dcr = ctrl_inl(DMABRGCR); | ||
90 | ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */ | ||
91 | dcr &= dcr >> 8; /* ignore masked */ | ||
92 | |||
93 | /* USB stuff, get it out of the way first */ | ||
94 | if (dcr & 1) | ||
95 | dmabrg_call_handler(DMABRGIRQ_USBDMA); | ||
96 | if (dcr & 2) | ||
97 | dmabrg_call_handler(DMABRGIRQ_USBDMAERR); | ||
98 | |||
99 | /* Audio */ | ||
100 | dcr >>= 16; | ||
101 | while (dcr) { | ||
102 | i = __ffs(dcr); | ||
103 | dcr &= dcr - 1; | ||
104 | dmabrg_call_handler(i + DMABRGIRQ_A0TXF); | ||
105 | } | ||
106 | return IRQ_HANDLED; | ||
107 | } | ||
108 | |||
109 | static void dmabrg_disable_irq(unsigned int dmairq) | ||
110 | { | ||
111 | unsigned long dcr; | ||
112 | dcr = ctrl_inl(DMABRGCR); | ||
113 | dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); | ||
114 | ctrl_outl(dcr, DMABRGCR); | ||
115 | } | ||
116 | |||
117 | static void dmabrg_enable_irq(unsigned int dmairq) | ||
118 | { | ||
119 | unsigned long dcr; | ||
120 | dcr = ctrl_inl(DMABRGCR); | ||
121 | dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); | ||
122 | ctrl_outl(dcr, DMABRGCR); | ||
123 | } | ||
124 | |||
125 | int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*), | ||
126 | void *data) | ||
127 | { | ||
128 | if ((dmairq > 9) || !handler) | ||
129 | return -ENOENT; | ||
130 | if (dmabrg_handlers[dmairq].handler) | ||
131 | return -EBUSY; | ||
132 | |||
133 | dmabrg_handlers[dmairq].handler = handler; | ||
134 | dmabrg_handlers[dmairq].data = data; | ||
135 | |||
136 | dmabrg_enable_irq(dmairq); | ||
137 | return 0; | ||
138 | } | ||
139 | EXPORT_SYMBOL_GPL(dmabrg_request_irq); | ||
140 | |||
141 | void dmabrg_free_irq(unsigned int dmairq) | ||
142 | { | ||
143 | if (likely(dmairq < 10)) { | ||
144 | dmabrg_disable_irq(dmairq); | ||
145 | dmabrg_handlers[dmairq].handler = NULL; | ||
146 | dmabrg_handlers[dmairq].data = NULL; | ||
147 | } | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(dmabrg_free_irq); | ||
150 | |||
151 | static int __init dmabrg_init(void) | ||
152 | { | ||
153 | unsigned long or; | ||
154 | int ret; | ||
155 | |||
156 | dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler), | ||
157 | GFP_KERNEL); | ||
158 | if (!dmabrg_handlers) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | #ifdef CONFIG_SH_DMA | ||
162 | /* request DMAC channel 0 before anyone else can get it */ | ||
163 | ret = request_dma(0, "DMAC 0 (DMABRG)"); | ||
164 | if (ret < 0) | ||
165 | printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n"); | ||
166 | #endif | ||
167 | |||
168 | ctrl_outl(0, DMABRGCR); | ||
169 | ctrl_outl(0, DMACHCR0); | ||
170 | ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */ | ||
171 | |||
172 | /* enable DMABRG mode, enable the DMAC */ | ||
173 | or = ctrl_inl(DMAOR); | ||
174 | ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR); | ||
175 | |||
176 | ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED, | ||
177 | "DMABRG USB address error", NULL); | ||
178 | if (ret) | ||
179 | goto out0; | ||
180 | |||
181 | ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED, | ||
182 | "DMABRG Transfer End", NULL); | ||
183 | if (ret) | ||
184 | goto out1; | ||
185 | |||
186 | ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED, | ||
187 | "DMABRG Transfer Half", NULL); | ||
188 | if (ret == 0) | ||
189 | return ret; | ||
190 | |||
191 | free_irq(DMABRGI1, 0); | ||
192 | out1: free_irq(DMABRGI0, 0); | ||
193 | out0: kfree(dmabrg_handlers); | ||
194 | return ret; | ||
195 | } | ||
196 | subsys_initcall(dmabrg_init); | ||
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile index 350972ae9410..965fa2572b23 100644 --- a/arch/sh/kernel/cpu/sh2a/Makefile +++ b/arch/sh/kernel/cpu/sh2a/Makefile | |||
@@ -2,9 +2,8 @@ | |||
2 | # Makefile for the Linux/SuperH SH-2A backends. | 2 | # Makefile for the Linux/SuperH SH-2A backends. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := common.o probe.o | 5 | obj-y := common.o probe.o opcode_helper.o |
6 | 6 | ||
7 | common-y += $(addprefix ../sh2/, ex.o) | 7 | common-y += $(addprefix ../sh2/, ex.o entry.o) |
8 | common-y += $(addprefix ../sh2/, entry.o) | ||
9 | 8 | ||
10 | obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o | 9 | obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o |
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c new file mode 100644 index 000000000000..9704b7926d8b --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/opcode_helper.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2a/opcode_helper.c | ||
3 | * | ||
4 | * Helper for the SH-2A 32-bit opcodes. | ||
5 | * | ||
6 | * Copyright (C) 2007 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/kernel.h> | ||
13 | #include <asm/system.h> | ||
14 | |||
15 | /* | ||
16 | * Instructions on SH are generally fixed at 16-bits, however, SH-2A | ||
17 | * introduces some 32-bit instructions. Since there are no real | ||
18 | * constraints on their use (and they can be mixed and matched), we need | ||
19 | * to check the instruction encoding to work out if it's a true 32-bit | ||
20 | * instruction or not. | ||
21 | * | ||
22 | * Presently, 32-bit opcodes have only slight variations in what the | ||
23 | * actual encoding looks like in the first-half of the instruction, which | ||
24 | * makes it fairly straightforward to differentiate from the 16-bit ones. | ||
25 | * | ||
26 | * First 16-bits of encoding Used by | ||
27 | * | ||
28 | * 0011nnnnmmmm0001 mov.b, mov.w, mov.l, fmov.d, | ||
29 | * fmov.s, movu.b, movu.w | ||
30 | * | ||
31 | * 0011nnnn0iii1001 bclr.b, bld.b, bset.b, bst.b, band.b, | ||
32 | * bandnot.b, bldnot.b, bor.b, bornot.b, | ||
33 | * bxor.b | ||
34 | * | ||
35 | * 0000nnnniiii0000 movi20 | ||
36 | * 0000nnnniiii0001 movi20s | ||
37 | */ | ||
38 | unsigned int instruction_size(unsigned int insn) | ||
39 | { | ||
40 | /* Look for the common cases */ | ||
41 | switch ((insn & 0xf00f)) { | ||
42 | case 0x0000: /* movi20 */ | ||
43 | case 0x0001: /* movi20s */ | ||
44 | case 0x3001: /* 32-bit mov/fmov/movu variants */ | ||
45 | return 4; | ||
46 | } | ||
47 | |||
48 | /* And the special cases.. */ | ||
49 | switch ((insn & 0xf08f)) { | ||
50 | case 0x3009: /* 32-bit b*.b bit operations */ | ||
51 | return 4; | ||
52 | } | ||
53 | |||
54 | return 2; | ||
55 | } | ||
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 426f6db01fc6..f455c3509789 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c | |||
@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void) | |||
18 | { | 18 | { |
19 | /* Just SH7206 for now .. */ | 19 | /* Just SH7206 for now .. */ |
20 | current_cpu_data.type = CPU_SH7206; | 20 | current_cpu_data.type = CPU_SH7206; |
21 | current_cpu_data.flags |= CPU_HAS_OP32; | ||
21 | 22 | ||
22 | current_cpu_data.dcache.ways = 4; | 23 | current_cpu_data.dcache.ways = 4; |
23 | current_cpu_data.dcache.way_incr = (1 << 11); | 24 | current_cpu_data.dcache.way_incr = (1 << 11); |
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index ba3082d640b5..2b2a9e02fb75 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sh/kernel/cpu/sh3/ex.S | 2 | * arch/sh/kernel/cpu/sh3/ex.S |
3 | * | 3 | * |
4 | * The SH-3 exception vector table. | 4 | * The SH-3 and SH-4 exception vector table. |
5 | 5 | ||
6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
7 | * Copyright (C) 2003 - 2006 Paul Mundt | 7 | * Copyright (C) 2003 - 2006 Paul Mundt |
@@ -9,7 +9,6 @@ | |||
9 | * This file is subject to the terms and conditions of the GNU General Public | 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 | 10 | * License. See the file "COPYING" in the main directory of this archive |
11 | * for more details. | 11 | * for more details. |
12 | * | ||
13 | */ | 12 | */ |
14 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
15 | 14 | ||
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table) | |||
36 | .long exception_error ! address error load | 35 | .long exception_error ! address error load |
37 | .long exception_error ! address error store /* 100 */ | 36 | .long exception_error ! address error store /* 100 */ |
38 | #endif | 37 | #endif |
39 | .long exception_error ! fpu_exception /* 120 */ | 38 | #if defined(CONFIG_SH_FPU) |
40 | .long exception_error /* 140 */ | 39 | .long do_fpu_error /* 120 */ |
40 | #else | ||
41 | .long exception_error /* 120 */ | ||
42 | #endif | ||
43 | .long exception_error /* 140 */ | ||
41 | .long system_call ! Unconditional Trap /* 160 */ | 44 | .long system_call ! Unconditional Trap /* 160 */ |
42 | .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ | 45 | .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ |
43 | .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ | 46 | .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ |
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap) | |||
55 | * away offsets can be manually inserted in to their appropriate | 58 | * away offsets can be manually inserted in to their appropriate |
56 | * location via set_exception_table_{evt,vec}(). | 59 | * location via set_exception_table_{evt,vec}(). |
57 | */ | 60 | */ |
58 | .balign 4096,0,4096 | 61 | .balign 4096,0,4096 |
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 19ca68c71884..8add10bd8268 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile | |||
@@ -2,10 +2,10 @@ | |||
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 common.o | 5 | obj-y := probe.o common.o |
6 | common-y += $(addprefix ../sh3/, entry.o) | 6 | common-y += $(addprefix ../sh3/, entry.o ex.o) |
7 | 7 | ||
8 | obj-$(CONFIG_SH_FPU) += fpu.o | 8 | obj-$(CONFIG_SH_FPU) += fpu.o |
9 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 9 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o |
10 | 10 | ||
11 | # CPU subtype setup | 11 | # CPU subtype setup |
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S deleted file mode 100644 index ac8ab57413cc..000000000000 --- a/arch/sh/kernel/cpu/sh4/ex.S +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh4/ex.S | ||
3 | * | ||
4 | * The SH-4 exception vector table. | ||
5 | |||
6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | ||
7 | * Copyright (C) 2003 - 2006 Paul Mundt | ||
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 | |||
16 | .align 2 | ||
17 | .data | ||
18 | |||
19 | ENTRY(exception_handling_table) | ||
20 | .long exception_error /* 000 */ | ||
21 | .long exception_error | ||
22 | #if defined(CONFIG_MMU) | ||
23 | .long tlb_miss_load /* 040 */ | ||
24 | .long tlb_miss_store | ||
25 | .long initial_page_write | ||
26 | .long tlb_protection_violation_load | ||
27 | .long tlb_protection_violation_store | ||
28 | .long address_error_load | ||
29 | .long address_error_store /* 100 */ | ||
30 | #else | ||
31 | .long exception_error ! tlb miss load /* 040 */ | ||
32 | .long exception_error ! tlb miss store | ||
33 | .long exception_error ! initial page write | ||
34 | .long exception_error ! tlb prot violation load | ||
35 | .long exception_error ! tlb prot violation store | ||
36 | .long exception_error ! address error load | ||
37 | .long exception_error ! address error store /* 100 */ | ||
38 | #endif | ||
39 | #if defined(CONFIG_SH_FPU) | ||
40 | .long do_fpu_error /* 120 */ | ||
41 | #else | ||
42 | .long exception_error /* 120 */ | ||
43 | #endif | ||
44 | .long exception_error /* 140 */ | ||
45 | .long system_call ! Unconditional Trap /* 160 */ | ||
46 | .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ | ||
47 | .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ | ||
48 | ENTRY(nmi_slot) | ||
49 | #if defined (CONFIG_KGDB_NMI) | ||
50 | .long debug_enter /* 1C0 */ ! Allow trap to debugger | ||
51 | #else | ||
52 | .long exception_none /* 1C0 */ ! Not implemented yet | ||
53 | #endif | ||
54 | ENTRY(user_break_point_trap) | ||
55 | .long break_point_trap /* 1E0 */ | ||
56 | |||
57 | /* | ||
58 | * Pad the remainder of the table out, exceptions residing in far | ||
59 | * away offsets can be manually inserted in to their appropriate | ||
60 | * location via set_exception_table_{evt,vec}(). | ||
61 | */ | ||
62 | .balign 4096,0,4096 | ||
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index 7624677f6628..d61dd599169f 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/signal.h> | 17 | #include <linux/signal.h> |
18 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
19 | #include <asm/system.h> | ||
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
20 | 21 | ||
21 | /* The PR (precision) bit in the FP Status Register must be clear when | 22 | /* The PR (precision) bit in the FP Status Register must be clear when |
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
265 | nextpc = regs->pr; | 266 | nextpc = regs->pr; |
266 | finsn = *(unsigned short *) (regs->pc + 2); | 267 | finsn = *(unsigned short *) (regs->pc + 2); |
267 | } else { | 268 | } else { |
268 | nextpc = regs->pc + 2; | 269 | nextpc = regs->pc + instruction_size(insn); |
269 | finsn = insn; | 270 | finsn = insn; |
270 | } | 271 | } |
271 | 272 | ||
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 329b3f3051de..6b4f5748d0be 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c | |||
@@ -15,9 +15,12 @@ | |||
15 | #include <linux/pm.h> | 15 | #include <linux/pm.h> |
16 | #include <linux/kallsyms.h> | 16 | #include <linux/kallsyms.h> |
17 | #include <linux/kexec.h> | 17 | #include <linux/kexec.h> |
18 | #include <asm/kdebug.h> | 18 | #include <linux/kdebug.h> |
19 | #include <linux/tick.h> | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include <asm/mmu_context.h> | 21 | #include <asm/mmu_context.h> |
22 | #include <asm/pgalloc.h> | ||
23 | #include <asm/system.h> | ||
21 | #include <asm/ubc.h> | 24 | #include <asm/ubc.h> |
22 | 25 | ||
23 | static int hlt_counter; | 26 | static int hlt_counter; |
@@ -58,12 +61,15 @@ void cpu_idle(void) | |||
58 | if (!idle) | 61 | if (!idle) |
59 | idle = default_idle; | 62 | idle = default_idle; |
60 | 63 | ||
64 | tick_nohz_stop_sched_tick(); | ||
61 | while (!need_resched()) | 65 | while (!need_resched()) |
62 | idle(); | 66 | idle(); |
67 | tick_nohz_restart_sched_tick(); | ||
63 | 68 | ||
64 | preempt_enable_no_resched(); | 69 | preempt_enable_no_resched(); |
65 | schedule(); | 70 | schedule(); |
66 | preempt_disable(); | 71 | preempt_disable(); |
72 | check_pgt_cache(); | ||
67 | } | 73 | } |
68 | } | 74 | } |
69 | 75 | ||
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5, | |||
495 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | 501 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
496 | 502 | ||
497 | /* Rewind */ | 503 | /* Rewind */ |
498 | regs->pc -= 2; | 504 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); |
499 | 505 | ||
500 | if (notify_die(DIE_TRAP, regs, regs->tra & 0xff, | 506 | if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff, |
501 | SIGTRAP) == NOTIFY_STOP) | 507 | SIGTRAP) == NOTIFY_STOP) |
502 | return; | 508 | return; |
503 | 509 | ||
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5, | |||
514 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | 520 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
515 | 521 | ||
516 | /* Rewind */ | 522 | /* Rewind */ |
517 | regs->pc -= 2; | 523 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); |
518 | 524 | ||
519 | if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff, | 525 | if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, |
520 | SIGTRAP) == NOTIFY_STOP) | 526 | SIGTRAP) == NOTIFY_STOP) |
521 | return; | 527 | return; |
522 | 528 | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 477d2a854fc4..c27729135935 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c) | |||
431 | /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ | 431 | /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ |
432 | static const char *cpu_flags[] = { | 432 | static const char *cpu_flags[] = { |
433 | "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", | 433 | "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", |
434 | "ptea", "llsc", "l2", NULL | 434 | "ptea", "llsc", "l2", "op32", NULL |
435 | }; | 435 | }; |
436 | 436 | ||
437 | static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) | 437 | static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) |
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index fa91641c1f62..c1cfcb9f047c 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c | |||
@@ -58,8 +58,6 @@ EXPORT_SYMBOL(__udelay); | |||
58 | EXPORT_SYMBOL(__ndelay); | 58 | EXPORT_SYMBOL(__ndelay); |
59 | EXPORT_SYMBOL(__const_udelay); | 59 | EXPORT_SYMBOL(__const_udelay); |
60 | 60 | ||
61 | EXPORT_SYMBOL(__div64_32); | ||
62 | |||
63 | #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) | 61 | #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) |
64 | 62 | ||
65 | /* These symbols are generated by the compiler itself */ | 63 | /* These symbols are generated by the compiler itself */ |
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index eb0191c374b6..b32c35a7c0a3 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/personality.h> | 23 | #include <linux/personality.h> |
24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | 26 | #include <asm/system.h> | |
27 | #include <asm/ucontext.h> | 27 | #include <asm/ucontext.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
@@ -500,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
500 | } | 500 | } |
501 | /* fallthrough */ | 501 | /* fallthrough */ |
502 | case -ERESTARTNOINTR: | 502 | case -ERESTARTNOINTR: |
503 | regs->pc -= 2; | 503 | regs->pc -= instruction_size( |
504 | ctrl_inw(regs->pc - 4)); | ||
505 | break; | ||
504 | } | 506 | } |
505 | } else { | 507 | } else { |
506 | /* gUSA handling */ | 508 | /* gUSA handling */ |
@@ -516,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
516 | regs->regs[15] = regs->regs[1]; | 518 | regs->regs[15] = regs->regs[1]; |
517 | if (regs->pc < regs->regs[0]) | 519 | if (regs->pc < regs->regs[0]) |
518 | /* Go to rewind point #1 */ | 520 | /* Go to rewind point #1 */ |
519 | regs->pc = regs->regs[0] + offset - 2; | 521 | regs->pc = regs->regs[0] + offset - |
522 | instruction_size(ctrl_inw(regs->pc-4)); | ||
520 | } | 523 | } |
521 | #ifdef CONFIG_PREEMPT | 524 | #ifdef CONFIG_PREEMPT |
522 | local_irq_restore(flags); | 525 | local_irq_restore(flags); |
@@ -600,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
600 | regs->regs[0] == -ERESTARTSYS || | 603 | regs->regs[0] == -ERESTARTSYS || |
601 | regs->regs[0] == -ERESTARTNOINTR) { | 604 | regs->regs[0] == -ERESTARTNOINTR) { |
602 | regs->regs[0] = save_r0; | 605 | regs->regs[0] = save_r0; |
603 | regs->pc -= 2; | 606 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); |
604 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { | 607 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { |
605 | regs->pc -= 2; | 608 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); |
606 | regs->regs[3] = __NR_restart_syscall; | 609 | regs->regs[3] = __NR_restart_syscall; |
607 | } | 610 | } |
608 | } | 611 | } |
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index 4bdd2f83535d..d41e561be20e 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c | |||
@@ -17,7 +17,7 @@ | |||
17 | /* | 17 | /* |
18 | * Save stack-backtrace addresses into a stack_trace buffer. | 18 | * Save stack-backtrace addresses into a stack_trace buffer. |
19 | */ | 19 | */ |
20 | void save_stack_trace(struct stack_trace *trace, struct task_struct *task) | 20 | void save_stack_trace(struct stack_trace *trace) |
21 | { | 21 | { |
22 | unsigned long *sp = (unsigned long *)current_stack_pointer; | 22 | unsigned long *sp = (unsigned long *)current_stack_pointer; |
23 | 23 | ||
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S index 38fc8cd3ea3a..4357d1a6358f 100644 --- a/arch/sh/kernel/syscalls.S +++ b/arch/sh/kernel/syscalls.S | |||
@@ -354,3 +354,4 @@ ENTRY(sys_call_table) | |||
354 | .long sys_move_pages | 354 | .long sys_move_pages |
355 | .long sys_getcpu | 355 | .long sys_getcpu |
356 | .long sys_epoll_pwait | 356 | .long sys_epoll_pwait |
357 | .long sys_utimensat /* 320 */ | ||
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index d47e775962e9..a3a67d151e52 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka | 4 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka |
5 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | 5 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> |
6 | * Copyright (C) 2002 - 2006 Paul Mundt | 6 | * Copyright (C) 2002 - 2007 Paul Mundt |
7 | * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> | 7 | * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> |
8 | * | 8 | * |
9 | * Some code taken from i386 version. | 9 | * Some code taken from i386 version. |
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/profile.h> | 15 | #include <linux/profile.h> |
16 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/clockchips.h> | ||
18 | #include <asm/clock.h> | 19 | #include <asm/clock.h> |
19 | #include <asm/rtc.h> | 20 | #include <asm/rtc.h> |
20 | #include <asm/timer.h> | 21 | #include <asm/timer.h> |
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs) | |||
38 | return 0; | 39 | return 0; |
39 | } | 40 | } |
40 | 41 | ||
42 | /* | ||
43 | * Null high precision timer functions for systems lacking one. | ||
44 | */ | ||
45 | static cycle_t null_hpt_read(void) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | |||
41 | void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; | 50 | void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; |
42 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; | 51 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; |
43 | 52 | ||
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv) | |||
101 | EXPORT_SYMBOL(do_settimeofday); | 110 | EXPORT_SYMBOL(do_settimeofday); |
102 | #endif /* !CONFIG_GENERIC_TIME */ | 111 | #endif /* !CONFIG_GENERIC_TIME */ |
103 | 112 | ||
113 | #ifndef CONFIG_GENERIC_CLOCKEVENTS | ||
104 | /* last time the RTC clock got updated */ | 114 | /* last time the RTC clock got updated */ |
105 | static long last_rtc_update; | 115 | static long last_rtc_update; |
106 | 116 | ||
@@ -138,6 +148,7 @@ void handle_timer_tick(void) | |||
138 | last_rtc_update = xtime.tv_sec - 600; | 148 | last_rtc_update = xtime.tv_sec - 600; |
139 | } | 149 | } |
140 | } | 150 | } |
151 | #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ | ||
141 | 152 | ||
142 | #ifdef CONFIG_PM | 153 | #ifdef CONFIG_PM |
143 | int timer_suspend(struct sys_device *dev, pm_message_t state) | 154 | int timer_suspend(struct sys_device *dev, pm_message_t state) |
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = { | |||
168 | .resume = timer_resume, | 179 | .resume = timer_resume, |
169 | }; | 180 | }; |
170 | 181 | ||
171 | #ifdef CONFIG_NO_IDLE_HZ | 182 | static int __init timer_init_sysfs(void) |
172 | static int timer_dyn_tick_enable(void) | ||
173 | { | 183 | { |
174 | struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; | 184 | int ret = sysdev_class_register(&timer_sysclass); |
175 | unsigned long flags; | 185 | if (ret != 0) |
176 | int ret = -ENODEV; | 186 | return ret; |
177 | |||
178 | if (dyn_tick) { | ||
179 | spin_lock_irqsave(&dyn_tick->lock, flags); | ||
180 | ret = 0; | ||
181 | if (!(dyn_tick->state & DYN_TICK_ENABLED)) { | ||
182 | ret = dyn_tick->enable(); | ||
183 | |||
184 | if (ret == 0) | ||
185 | dyn_tick->state |= DYN_TICK_ENABLED; | ||
186 | } | ||
187 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
188 | } | ||
189 | 187 | ||
190 | return ret; | 188 | sys_timer->dev.cls = &timer_sysclass; |
189 | return sysdev_register(&sys_timer->dev); | ||
191 | } | 190 | } |
191 | device_initcall(timer_init_sysfs); | ||
192 | 192 | ||
193 | static int timer_dyn_tick_disable(void) | 193 | void (*board_time_init)(void); |
194 | { | ||
195 | struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; | ||
196 | unsigned long flags; | ||
197 | int ret = -ENODEV; | ||
198 | |||
199 | if (dyn_tick) { | ||
200 | spin_lock_irqsave(&dyn_tick->lock, flags); | ||
201 | ret = 0; | ||
202 | if (dyn_tick->state & DYN_TICK_ENABLED) { | ||
203 | ret = dyn_tick->disable(); | ||
204 | |||
205 | if (ret == 0) | ||
206 | dyn_tick->state &= ~DYN_TICK_ENABLED; | ||
207 | } | ||
208 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
209 | } | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | 194 | ||
214 | /* | 195 | /* |
215 | * Reprogram the system timer for at least the calculated time interval. | 196 | * Shamelessly based on the MIPS and Sparc64 work. |
216 | * This function should be called from the idle thread with IRQs disabled, | ||
217 | * immediately before sleeping. | ||
218 | */ | 197 | */ |
219 | void timer_dyn_reprogram(void) | 198 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; |
220 | { | 199 | unsigned long sh_hpt_frequency = 0; |
221 | struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; | 200 | |
222 | unsigned long next, seq, flags; | 201 | #define NSEC_PER_CYC_SHIFT 10 |
223 | 202 | ||
224 | if (!dyn_tick) | 203 | struct clocksource clocksource_sh = { |
225 | return; | 204 | .name = "SuperH", |
226 | 205 | .rating = 200, | |
227 | spin_lock_irqsave(&dyn_tick->lock, flags); | 206 | .mask = CLOCKSOURCE_MASK(32), |
228 | if (dyn_tick->state & DYN_TICK_ENABLED) { | 207 | .read = null_hpt_read, |
229 | next = next_timer_interrupt(); | 208 | .shift = 16, |
230 | do { | 209 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
231 | seq = read_seqbegin(&xtime_lock); | 210 | }; |
232 | dyn_tick->reprogram(next - jiffies); | ||
233 | } while (read_seqretry(&xtime_lock, seq)); | ||
234 | } | ||
235 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
236 | } | ||
237 | 211 | ||
238 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | 212 | static void __init init_sh_clocksource(void) |
239 | { | 213 | { |
240 | return sprintf(buf, "%i\n", | 214 | if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) |
241 | (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); | 215 | return; |
242 | } | ||
243 | 216 | ||
244 | static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, | 217 | clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, |
245 | size_t count) | 218 | clocksource_sh.shift); |
246 | { | ||
247 | unsigned int enable = simple_strtoul(buf, NULL, 2); | ||
248 | 219 | ||
249 | if (enable) | 220 | timer_ticks_per_nsec_quotient = |
250 | timer_dyn_tick_enable(); | 221 | clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); |
251 | else | ||
252 | timer_dyn_tick_disable(); | ||
253 | 222 | ||
254 | return count; | 223 | clocksource_register(&clocksource_sh); |
255 | } | 224 | } |
256 | static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); | ||
257 | 225 | ||
258 | /* | 226 | #ifdef CONFIG_GENERIC_TIME |
259 | * dyntick=enable|disable | 227 | unsigned long long sched_clock(void) |
260 | */ | ||
261 | static char dyntick_str[4] __initdata = ""; | ||
262 | |||
263 | static int __init dyntick_setup(char *str) | ||
264 | { | 228 | { |
265 | if (str) | 229 | unsigned long long ticks = clocksource_sh.read(); |
266 | strlcpy(dyntick_str, str, sizeof(dyntick_str)); | 230 | return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; |
267 | return 1; | ||
268 | } | 231 | } |
269 | |||
270 | __setup("dyntick=", dyntick_setup); | ||
271 | #endif | ||
272 | |||
273 | static int __init timer_init_sysfs(void) | ||
274 | { | ||
275 | int ret = sysdev_class_register(&timer_sysclass); | ||
276 | if (ret != 0) | ||
277 | return ret; | ||
278 | |||
279 | sys_timer->dev.cls = &timer_sysclass; | ||
280 | ret = sysdev_register(&sys_timer->dev); | ||
281 | |||
282 | #ifdef CONFIG_NO_IDLE_HZ | ||
283 | if (ret == 0 && sys_timer->dyn_tick) { | ||
284 | ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick); | ||
285 | |||
286 | /* | ||
287 | * Turn on dynamic tick after calibrate delay | ||
288 | * for correct bogomips | ||
289 | */ | ||
290 | if (ret == 0 && dyntick_str[0] == 'e') | ||
291 | ret = timer_dyn_tick_enable(); | ||
292 | } | ||
293 | #endif | 232 | #endif |
294 | 233 | ||
295 | return ret; | ||
296 | } | ||
297 | device_initcall(timer_init_sysfs); | ||
298 | |||
299 | void (*board_time_init)(void); | ||
300 | |||
301 | void __init time_init(void) | 234 | void __init time_init(void) |
302 | { | 235 | { |
303 | if (board_time_init) | 236 | if (board_time_init) |
@@ -316,10 +249,15 @@ void __init time_init(void) | |||
316 | sys_timer = get_sys_timer(); | 249 | sys_timer = get_sys_timer(); |
317 | printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); | 250 | printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); |
318 | 251 | ||
319 | #ifdef CONFIG_NO_IDLE_HZ | 252 | if (sys_timer->ops->read) |
320 | if (sys_timer->dyn_tick) | 253 | clocksource_sh.read = sys_timer->ops->read; |
321 | spin_lock_init(&sys_timer->dyn_tick->lock); | 254 | |
322 | #endif | 255 | init_sh_clocksource(); |
256 | |||
257 | if (sh_hpt_frequency) | ||
258 | printk("Using %lu.%03lu MHz high precision timer.\n", | ||
259 | ((sh_hpt_frequency + 500) / 1000) / 1000, | ||
260 | ((sh_hpt_frequency + 500) / 1000) % 1000); | ||
323 | 261 | ||
324 | #if defined(CONFIG_SH_KGDB) | 262 | #if defined(CONFIG_SH_KGDB) |
325 | /* | 263 | /* |
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index d9e3151c891e..2d997e2a5b6c 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support | 2 | * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Paul Mundt | 4 | * Copyright (C) 2005 - 2007 Paul Mundt |
5 | * | 5 | * |
6 | * TMU handling code hacked out of arch/sh/kernel/time.c | 6 | * TMU handling code hacked out of arch/sh/kernel/time.c |
7 | * | 7 | * |
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/seqlock.h> | 20 | #include <linux/seqlock.h> |
21 | #include <linux/clockchips.h> | ||
21 | #include <asm/timer.h> | 22 | #include <asm/timer.h> |
22 | #include <asm/rtc.h> | 23 | #include <asm/rtc.h> |
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
@@ -25,56 +26,75 @@ | |||
25 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
26 | 27 | ||
27 | #define TMU_TOCR_INIT 0x00 | 28 | #define TMU_TOCR_INIT 0x00 |
28 | #define TMU0_TCR_INIT 0x0020 | 29 | #define TMU_TCR_INIT 0x0020 |
29 | #define TMU_TSTR_INIT 1 | ||
30 | 30 | ||
31 | #define TMU0_TCR_CALIB 0x0000 | 31 | static int tmu_timer_start(void) |
32 | { | ||
33 | ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR); | ||
34 | return 0; | ||
35 | } | ||
32 | 36 | ||
33 | static unsigned long tmu_timer_get_offset(void) | 37 | static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload) |
34 | { | 38 | { |
35 | int count; | 39 | ctrl_outl(interval, TMU0_TCNT); |
36 | static int count_p = 0x7fffffff; /* for the first call after boot */ | ||
37 | static unsigned long jiffies_p = 0; | ||
38 | 40 | ||
39 | /* | 41 | /* |
40 | * cache volatile jiffies temporarily; we have IRQs turned off. | 42 | * TCNT reloads from TCOR on underflow, clear it if we don't |
43 | * intend to auto-reload | ||
41 | */ | 44 | */ |
42 | unsigned long jiffies_t; | 45 | if (reload) |
46 | ctrl_outl(interval, TMU0_TCOR); | ||
47 | else | ||
48 | ctrl_outl(0, TMU0_TCOR); | ||
43 | 49 | ||
44 | /* timer count may underflow right here */ | 50 | tmu_timer_start(); |
45 | count = ctrl_inl(TMU0_TCNT); /* read the latched count */ | 51 | } |
46 | 52 | ||
47 | jiffies_t = jiffies; | 53 | static int tmu_timer_stop(void) |
54 | { | ||
55 | ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR); | ||
56 | return 0; | ||
57 | } | ||
48 | 58 | ||
49 | /* | 59 | static cycle_t tmu_timer_read(void) |
50 | * avoiding timer inconsistencies (they are rare, but they happen)... | 60 | { |
51 | * there is one kind of problem that must be avoided here: | 61 | return ~ctrl_inl(TMU1_TCNT); |
52 | * 1. the timer counter underflows | 62 | } |
53 | */ | 63 | |
64 | static int tmu_set_next_event(unsigned long cycles, | ||
65 | struct clock_event_device *evt) | ||
66 | { | ||
67 | tmu0_timer_set_interval(cycles, 1); | ||
68 | return 0; | ||
69 | } | ||
54 | 70 | ||
55 | if (jiffies_t == jiffies_p) { | 71 | static void tmu_set_mode(enum clock_event_mode mode, |
56 | if (count > count_p) { | 72 | struct clock_event_device *evt) |
57 | /* the nutcase */ | 73 | { |
58 | if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ | 74 | switch (mode) { |
59 | count -= LATCH; | 75 | case CLOCK_EVT_MODE_PERIODIC: |
60 | } else { | 76 | ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR); |
61 | printk("%s (): hardware timer problem?\n", | 77 | break; |
62 | __FUNCTION__); | 78 | case CLOCK_EVT_MODE_ONESHOT: |
63 | } | 79 | ctrl_outl(0, TMU0_TCOR); |
64 | } | 80 | break; |
65 | } else | 81 | case CLOCK_EVT_MODE_UNUSED: |
66 | jiffies_p = jiffies_t; | 82 | case CLOCK_EVT_MODE_SHUTDOWN: |
67 | 83 | break; | |
68 | count_p = count; | 84 | } |
69 | |||
70 | count = ((LATCH-1) - count) * TICK_SIZE; | ||
71 | count = (count + LATCH/2) / LATCH; | ||
72 | |||
73 | return count; | ||
74 | } | 85 | } |
75 | 86 | ||
87 | static struct clock_event_device tmu0_clockevent = { | ||
88 | .name = "tmu0", | ||
89 | .shift = 32, | ||
90 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
91 | .set_mode = tmu_set_mode, | ||
92 | .set_next_event = tmu_set_next_event, | ||
93 | }; | ||
94 | |||
76 | static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) | 95 | static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) |
77 | { | 96 | { |
97 | struct clock_event_device *evt = &tmu0_clockevent; | ||
78 | unsigned long timer_status; | 98 | unsigned long timer_status; |
79 | 99 | ||
80 | /* Clear UNF bit */ | 100 | /* Clear UNF bit */ |
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) | |||
82 | timer_status &= ~0x100; | 102 | timer_status &= ~0x100; |
83 | ctrl_outw(timer_status, TMU0_TCR); | 103 | ctrl_outw(timer_status, TMU0_TCR); |
84 | 104 | ||
85 | /* | 105 | evt->event_handler(evt); |
86 | * Here we are in the timer irq handler. We just have irqs locally | ||
87 | * disabled but we don't know if the timer_bh is running on the other | ||
88 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
89 | * the irq version of write_lock because as just said we have irq | ||
90 | * locally disabled. -arca | ||
91 | */ | ||
92 | write_seqlock(&xtime_lock); | ||
93 | handle_timer_tick(); | ||
94 | write_sequnlock(&xtime_lock); | ||
95 | 106 | ||
96 | return IRQ_HANDLED; | 107 | return IRQ_HANDLED; |
97 | } | 108 | } |
98 | 109 | ||
99 | static struct irqaction tmu_irq = { | 110 | static struct irqaction tmu0_irq = { |
100 | .name = "timer", | 111 | .name = "periodic timer", |
101 | .handler = tmu_timer_interrupt, | 112 | .handler = tmu_timer_interrupt, |
102 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 113 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
103 | .mask = CPU_MASK_NONE, | 114 | .mask = CPU_MASK_NONE, |
104 | }; | 115 | }; |
105 | 116 | ||
106 | static void tmu_clk_init(struct clk *clk) | 117 | static void tmu0_clk_init(struct clk *clk) |
107 | { | 118 | { |
108 | u8 divisor = TMU0_TCR_INIT & 0x7; | 119 | u8 divisor = TMU_TCR_INIT & 0x7; |
109 | ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); | 120 | ctrl_outw(TMU_TCR_INIT, TMU0_TCR); |
110 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); | 121 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); |
111 | } | 122 | } |
112 | 123 | ||
113 | static void tmu_clk_recalc(struct clk *clk) | 124 | static void tmu0_clk_recalc(struct clk *clk) |
114 | { | 125 | { |
115 | u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; | 126 | u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; |
116 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); | 127 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); |
117 | } | 128 | } |
118 | 129 | ||
119 | static struct clk_ops tmu_clk_ops = { | 130 | static struct clk_ops tmu0_clk_ops = { |
120 | .init = tmu_clk_init, | 131 | .init = tmu0_clk_init, |
121 | .recalc = tmu_clk_recalc, | 132 | .recalc = tmu0_clk_recalc, |
122 | }; | 133 | }; |
123 | 134 | ||
124 | static struct clk tmu0_clk = { | 135 | static struct clk tmu0_clk = { |
125 | .name = "tmu0_clk", | 136 | .name = "tmu0_clk", |
126 | .ops = &tmu_clk_ops, | 137 | .ops = &tmu0_clk_ops, |
127 | }; | 138 | }; |
128 | 139 | ||
129 | static int tmu_timer_start(void) | 140 | static void tmu1_clk_init(struct clk *clk) |
130 | { | 141 | { |
131 | ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); | 142 | u8 divisor = TMU_TCR_INIT & 0x7; |
132 | return 0; | 143 | ctrl_outw(divisor, TMU1_TCR); |
144 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); | ||
133 | } | 145 | } |
134 | 146 | ||
135 | static int tmu_timer_stop(void) | 147 | static void tmu1_clk_recalc(struct clk *clk) |
136 | { | 148 | { |
137 | ctrl_outb(0, TMU_TSTR); | 149 | u8 divisor = ctrl_inw(TMU1_TCR) & 0x7; |
138 | return 0; | 150 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); |
139 | } | 151 | } |
140 | 152 | ||
153 | static struct clk_ops tmu1_clk_ops = { | ||
154 | .init = tmu1_clk_init, | ||
155 | .recalc = tmu1_clk_recalc, | ||
156 | }; | ||
157 | |||
158 | static struct clk tmu1_clk = { | ||
159 | .name = "tmu1_clk", | ||
160 | .ops = &tmu1_clk_ops, | ||
161 | }; | ||
162 | |||
141 | static int tmu_timer_init(void) | 163 | static int tmu_timer_init(void) |
142 | { | 164 | { |
143 | unsigned long interval; | 165 | unsigned long interval; |
166 | unsigned long frequency; | ||
144 | 167 | ||
145 | setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); | 168 | setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq); |
146 | 169 | ||
147 | tmu0_clk.parent = clk_get(NULL, "module_clk"); | 170 | tmu0_clk.parent = clk_get(NULL, "module_clk"); |
171 | tmu1_clk.parent = clk_get(NULL, "module_clk"); | ||
148 | 172 | ||
149 | /* Start TMU0 */ | ||
150 | tmu_timer_stop(); | 173 | tmu_timer_stop(); |
174 | |||
151 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ | 175 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ |
152 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ | 176 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ |
153 | !defined(CONFIG_CPU_SUBTYPE_SH7785) | 177 | !defined(CONFIG_CPU_SUBTYPE_SH7785) |
@@ -155,15 +179,29 @@ static int tmu_timer_init(void) | |||
155 | #endif | 179 | #endif |
156 | 180 | ||
157 | clk_register(&tmu0_clk); | 181 | clk_register(&tmu0_clk); |
182 | clk_register(&tmu1_clk); | ||
158 | clk_enable(&tmu0_clk); | 183 | clk_enable(&tmu0_clk); |
184 | clk_enable(&tmu1_clk); | ||
159 | 185 | ||
160 | interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; | 186 | frequency = clk_get_rate(&tmu0_clk); |
161 | printk(KERN_INFO "Interval = %ld\n", interval); | 187 | interval = (frequency + HZ / 2) / HZ; |
162 | 188 | ||
163 | ctrl_outl(interval, TMU0_TCOR); | 189 | sh_hpt_frequency = clk_get_rate(&tmu1_clk); |
164 | ctrl_outl(interval, TMU0_TCNT); | 190 | ctrl_outl(~0, TMU1_TCNT); |
191 | ctrl_outl(~0, TMU1_TCOR); | ||
165 | 192 | ||
166 | tmu_timer_start(); | 193 | tmu0_timer_set_interval(interval, 1); |
194 | |||
195 | tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC, | ||
196 | tmu0_clockevent.shift); | ||
197 | tmu0_clockevent.max_delta_ns = | ||
198 | clockevent_delta2ns(-1, &tmu0_clockevent); | ||
199 | tmu0_clockevent.min_delta_ns = | ||
200 | clockevent_delta2ns(1, &tmu0_clockevent); | ||
201 | |||
202 | tmu0_clockevent.cpumask = cpumask_of_cpu(0); | ||
203 | |||
204 | clockevents_register_device(&tmu0_clockevent); | ||
167 | 205 | ||
168 | return 0; | 206 | return 0; |
169 | } | 207 | } |
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = { | |||
172 | .init = tmu_timer_init, | 210 | .init = tmu_timer_init, |
173 | .start = tmu_timer_start, | 211 | .start = tmu_timer_start, |
174 | .stop = tmu_timer_stop, | 212 | .stop = tmu_timer_stop, |
175 | #ifndef CONFIG_GENERIC_TIME | 213 | .read = tmu_timer_read, |
176 | .get_offset = tmu_timer_get_offset, | ||
177 | #endif | ||
178 | }; | 214 | }; |
179 | 215 | ||
180 | struct sys_timer tmu_timer = { | 216 | struct sys_timer tmu_timer = { |
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 7b40f0ff3dfc..3a197649cd83 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -20,10 +20,10 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
22 | #include <linux/debug_locks.h> | 22 | #include <linux/debug_locks.h> |
23 | #include <linux/kdebug.h> | ||
23 | #include <linux/limits.h> | 24 | #include <linux/limits.h> |
24 | #include <asm/system.h> | 25 | #include <asm/system.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/kdebug.h> | ||
27 | 27 | ||
28 | #ifdef CONFIG_SH_KGDB | 28 | #ifdef CONFIG_SH_KGDB |
29 | #include <asm/kgdb.h> | 29 | #include <asm/kgdb.h> |
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top) | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | ATOMIC_NOTIFIER_HEAD(shdie_chain); | ||
80 | |||
81 | int register_die_notifier(struct notifier_block *nb) | ||
82 | { | ||
83 | return atomic_notifier_chain_register(&shdie_chain, nb); | ||
84 | } | ||
85 | EXPORT_SYMBOL(register_die_notifier); | ||
86 | |||
87 | int unregister_die_notifier(struct notifier_block *nb) | ||
88 | { | ||
89 | return atomic_notifier_chain_unregister(&shdie_chain, nb); | ||
90 | } | ||
91 | EXPORT_SYMBOL(unregister_die_notifier); | ||
92 | |||
93 | static DEFINE_SPINLOCK(die_lock); | 79 | static DEFINE_SPINLOCK(die_lock); |
94 | 80 | ||
95 | void die(const char * str, struct pt_regs * regs, long err) | 81 | void die(const char * str, struct pt_regs * regs, long err) |
@@ -505,7 +491,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
505 | simple: | 491 | simple: |
506 | ret = handle_unaligned_ins(instruction,regs); | 492 | ret = handle_unaligned_ins(instruction,regs); |
507 | if (ret==0) | 493 | if (ret==0) |
508 | regs->pc += 2; | 494 | regs->pc += instruction_size(instruction); |
509 | return ret; | 495 | return ret; |
510 | } | 496 | } |
511 | #endif /* CONFIG_CPU_SH2A */ | 497 | #endif /* CONFIG_CPU_SH2A */ |
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, | |||
682 | 668 | ||
683 | err = do_fpu_inst(inst, regs); | 669 | err = do_fpu_inst(inst, regs); |
684 | if (!err) { | 670 | if (!err) { |
685 | regs->pc += 2; | 671 | regs->pc += instruction_size(inst); |
686 | return; | 672 | return; |
687 | } | 673 | } |
688 | /* not a FPU inst. */ | 674 | /* not a FPU inst. */ |
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c index 351714694d6d..f3ddd2133e6f 100644 --- a/arch/sh/lib/delay.c +++ b/arch/sh/lib/delay.c | |||
@@ -24,9 +24,10 @@ inline void __const_udelay(unsigned long xloops) | |||
24 | __asm__("dmulu.l %0, %2\n\t" | 24 | __asm__("dmulu.l %0, %2\n\t" |
25 | "sts mach, %0" | 25 | "sts mach, %0" |
26 | : "=r" (xloops) | 26 | : "=r" (xloops) |
27 | : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy) | 27 | : "0" (xloops), |
28 | "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) | ||
28 | : "macl", "mach"); | 29 | : "macl", "mach"); |
29 | __delay(xloops * HZ); | 30 | __delay(xloops); |
30 | } | 31 | } |
31 | 32 | ||
32 | void __udelay(unsigned long usecs) | 33 | void __udelay(unsigned long usecs) |
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 12f3d394dc28..253346d7b316 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig | |||
@@ -218,6 +218,9 @@ endmenu | |||
218 | 218 | ||
219 | menu "Memory management options" | 219 | menu "Memory management options" |
220 | 220 | ||
221 | config QUICKLIST | ||
222 | def_bool y | ||
223 | |||
221 | config MMU | 224 | config MMU |
222 | bool "Support for memory management hardware" | 225 | bool "Support for memory management hardware" |
223 | depends on !CPU_SH2 | 226 | depends on !CPU_SH2 |
@@ -300,6 +303,10 @@ config NODES_SHIFT | |||
300 | config ARCH_FLATMEM_ENABLE | 303 | config ARCH_FLATMEM_ENABLE |
301 | def_bool y | 304 | def_bool y |
302 | 305 | ||
306 | config MAX_ACTIVE_REGIONS | ||
307 | int | ||
308 | default "1" | ||
309 | |||
303 | config ARCH_POPULATES_NODE_MAP | 310 | config ARCH_POPULATES_NODE_MAP |
304 | def_bool y | 311 | def_bool y |
305 | 312 | ||
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 0ecc117cade4..9207da67ff8a 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/hardirq.h> | 16 | #include <linux/hardirq.h> |
17 | #include <linux/kprobes.h> | 17 | #include <linux/kprobes.h> |
18 | #include <asm/kdebug.h> | 18 | #include <linux/kdebug.h> |
19 | #include <asm/system.h> | 19 | #include <asm/system.h> |
20 | #include <asm/mmu_context.h> | 20 | #include <asm/mmu_context.h> |
21 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 4d030988b368..8fe223a890ed 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c | |||
@@ -67,6 +67,8 @@ void show_mem(void) | |||
67 | printk("%d slab pages\n", slab); | 67 | printk("%d slab pages\n", slab); |
68 | printk("%d pages shared\n", shared); | 68 | printk("%d pages shared\n", shared); |
69 | printk("%d pages swap cached\n", cached); | 69 | printk("%d pages swap cached\n", cached); |
70 | printk(KERN_INFO "Total of %ld pages in page table cache\n", | ||
71 | quicklist_total_size()); | ||
70 | } | 72 | } |
71 | 73 | ||
72 | #ifdef CONFIG_MMU | 74 | #ifdef CONFIG_MMU |