diff options
-rw-r--r-- | arch/alpha/Kconfig | 76 | ||||
-rw-r--r-- | arch/alpha/include/asm/machvec.h | 22 | ||||
-rw-r--r-- | arch/alpha/include/asm/pal.h | 71 | ||||
-rw-r--r-- | arch/alpha/include/asm/rtc.h | 11 | ||||
-rw-r--r-- | arch/alpha/include/asm/string.h | 24 | ||||
-rw-r--r-- | arch/alpha/include/uapi/asm/pal.h | 1 | ||||
-rw-r--r-- | arch/alpha/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/alpha/kernel/alpha_ksyms.c | 1 | ||||
-rw-r--r-- | arch/alpha/kernel/irq_alpha.c | 16 | ||||
-rw-r--r-- | arch/alpha/kernel/machvec_impl.h | 5 | ||||
-rw-r--r-- | arch/alpha/kernel/perf_event.c | 15 | ||||
-rw-r--r-- | arch/alpha/kernel/process.c | 17 | ||||
-rw-r--r-- | arch/alpha/kernel/proto.h | 6 | ||||
-rw-r--r-- | arch/alpha/kernel/rtc.c | 323 | ||||
-rw-r--r-- | arch/alpha/kernel/setup.c | 23 | ||||
-rw-r--r-- | arch/alpha/kernel/smp.c | 33 | ||||
-rw-r--r-- | arch/alpha/kernel/sys_jensen.c | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/sys_marvel.c | 55 | ||||
-rw-r--r-- | arch/alpha/kernel/time.c | 405 | ||||
-rw-r--r-- | arch/alpha/kernel/traps.c | 15 | ||||
-rw-r--r-- | arch/alpha/lib/csum_partial_copy.c | 10 | ||||
-rw-r--r-- | arch/alpha/lib/ev6-memset.S | 12 | ||||
-rw-r--r-- | arch/alpha/lib/memset.S | 11 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 10 |
24 files changed, 777 insertions, 388 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 135c674eaf9e..d39dc9b95a2c 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -16,8 +16,8 @@ config ALPHA | |||
16 | select ARCH_WANT_IPC_PARSE_VERSION | 16 | select ARCH_WANT_IPC_PARSE_VERSION |
17 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 17 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
18 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 18 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
19 | select GENERIC_CLOCKEVENTS | ||
19 | select GENERIC_SMP_IDLE_THREAD | 20 | select GENERIC_SMP_IDLE_THREAD |
20 | select GENERIC_CMOS_UPDATE | ||
21 | select GENERIC_STRNCPY_FROM_USER | 21 | select GENERIC_STRNCPY_FROM_USER |
22 | select GENERIC_STRNLEN_USER | 22 | select GENERIC_STRNLEN_USER |
23 | select HAVE_MOD_ARCH_SPECIFIC | 23 | select HAVE_MOD_ARCH_SPECIFIC |
@@ -488,6 +488,20 @@ config VGA_HOSE | |||
488 | which always have multiple hoses, and whose consoles support it. | 488 | which always have multiple hoses, and whose consoles support it. |
489 | 489 | ||
490 | 490 | ||
491 | config ALPHA_QEMU | ||
492 | bool "Run under QEMU emulation" | ||
493 | depends on !ALPHA_GENERIC | ||
494 | ---help--- | ||
495 | Assume the presence of special features supported by QEMU PALcode | ||
496 | that reduce the overhead of system emulation. | ||
497 | |||
498 | Generic kernels will auto-detect QEMU. But when building a | ||
499 | system-specific kernel, the assumption is that we want to | ||
500 | elimiate as many runtime tests as possible. | ||
501 | |||
502 | If unsure, say N. | ||
503 | |||
504 | |||
491 | config ALPHA_SRM | 505 | config ALPHA_SRM |
492 | bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME | 506 | bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME |
493 | depends on TTY | 507 | depends on TTY |
@@ -572,6 +586,30 @@ config NUMA | |||
572 | Access). This option is for configuring high-end multiprocessor | 586 | Access). This option is for configuring high-end multiprocessor |
573 | server machines. If in doubt, say N. | 587 | server machines. If in doubt, say N. |
574 | 588 | ||
589 | config ALPHA_WTINT | ||
590 | bool "Use WTINT" if ALPHA_SRM || ALPHA_GENERIC | ||
591 | default y if ALPHA_QEMU | ||
592 | default n if ALPHA_EV5 || ALPHA_EV56 || (ALPHA_EV4 && !ALPHA_LCA) | ||
593 | default n if !ALPHA_SRM && !ALPHA_GENERIC | ||
594 | default y if SMP | ||
595 | ---help--- | ||
596 | The Wait for Interrupt (WTINT) PALcall attempts to place the CPU | ||
597 | to sleep until the next interrupt. This may reduce the power | ||
598 | consumed, and the heat produced by the computer. However, it has | ||
599 | the side effect of making the cycle counter unreliable as a timing | ||
600 | device across the sleep. | ||
601 | |||
602 | For emulation under QEMU, definitely say Y here, as we have other | ||
603 | mechanisms for measuring time than the cycle counter. | ||
604 | |||
605 | For EV4 (but not LCA), EV5 and EV56 systems, or for systems running | ||
606 | MILO, sleep mode is not supported so you might as well say N here. | ||
607 | |||
608 | For SMP systems we cannot use the cycle counter for timing anyway, | ||
609 | so you might as well say Y here. | ||
610 | |||
611 | If unsure, say N. | ||
612 | |||
575 | config NODES_SHIFT | 613 | config NODES_SHIFT |
576 | int | 614 | int |
577 | default "7" | 615 | default "7" |
@@ -613,9 +651,41 @@ config VERBOSE_MCHECK_ON | |||
613 | 651 | ||
614 | Take the default (1) unless you want more control or more info. | 652 | Take the default (1) unless you want more control or more info. |
615 | 653 | ||
654 | choice | ||
655 | prompt "Timer interrupt frequency (HZ)?" | ||
656 | default HZ_128 if ALPHA_QEMU | ||
657 | default HZ_1200 if ALPHA_RAWHIDE | ||
658 | default HZ_1024 | ||
659 | ---help--- | ||
660 | The frequency at which timer interrupts occur. A high frequency | ||
661 | minimizes latency, whereas a low frequency minimizes overhead of | ||
662 | process accounting. The later effect is especially significant | ||
663 | when being run under QEMU. | ||
664 | |||
665 | Note that some Alpha hardware cannot change the interrupt frequency | ||
666 | of the timer. If unsure, say 1024 (or 1200 for Rawhide). | ||
667 | |||
668 | config HZ_32 | ||
669 | bool "32 Hz" | ||
670 | config HZ_64 | ||
671 | bool "64 Hz" | ||
672 | config HZ_128 | ||
673 | bool "128 Hz" | ||
674 | config HZ_256 | ||
675 | bool "256 Hz" | ||
676 | config HZ_1024 | ||
677 | bool "1024 Hz" | ||
678 | config HZ_1200 | ||
679 | bool "1200 Hz" | ||
680 | endchoice | ||
681 | |||
616 | config HZ | 682 | config HZ |
617 | int | 683 | int |
618 | default 1200 if ALPHA_RAWHIDE | 684 | default 32 if HZ_32 |
685 | default 64 if HZ_64 | ||
686 | default 128 if HZ_128 | ||
687 | default 256 if HZ_256 | ||
688 | default 1200 if HZ_1200 | ||
619 | default 1024 | 689 | default 1024 |
620 | 690 | ||
621 | source "drivers/pci/Kconfig" | 691 | source "drivers/pci/Kconfig" |
diff --git a/arch/alpha/include/asm/machvec.h b/arch/alpha/include/asm/machvec.h index 72dbf2359270..75cb3641ed2f 100644 --- a/arch/alpha/include/asm/machvec.h +++ b/arch/alpha/include/asm/machvec.h | |||
@@ -33,6 +33,7 @@ struct alpha_machine_vector | |||
33 | 33 | ||
34 | int nr_irqs; | 34 | int nr_irqs; |
35 | int rtc_port; | 35 | int rtc_port; |
36 | int rtc_boot_cpu_only; | ||
36 | unsigned int max_asn; | 37 | unsigned int max_asn; |
37 | unsigned long max_isa_dma_address; | 38 | unsigned long max_isa_dma_address; |
38 | unsigned long irq_probe_mask; | 39 | unsigned long irq_probe_mask; |
@@ -95,9 +96,6 @@ struct alpha_machine_vector | |||
95 | 96 | ||
96 | struct _alpha_agp_info *(*agp_info)(void); | 97 | struct _alpha_agp_info *(*agp_info)(void); |
97 | 98 | ||
98 | unsigned int (*rtc_get_time)(struct rtc_time *); | ||
99 | int (*rtc_set_time)(struct rtc_time *); | ||
100 | |||
101 | const char *vector_name; | 99 | const char *vector_name; |
102 | 100 | ||
103 | /* NUMA information */ | 101 | /* NUMA information */ |
@@ -126,13 +124,19 @@ extern struct alpha_machine_vector alpha_mv; | |||
126 | 124 | ||
127 | #ifdef CONFIG_ALPHA_GENERIC | 125 | #ifdef CONFIG_ALPHA_GENERIC |
128 | extern int alpha_using_srm; | 126 | extern int alpha_using_srm; |
127 | extern int alpha_using_qemu; | ||
129 | #else | 128 | #else |
130 | #ifdef CONFIG_ALPHA_SRM | 129 | # ifdef CONFIG_ALPHA_SRM |
131 | #define alpha_using_srm 1 | 130 | # define alpha_using_srm 1 |
132 | #else | 131 | # else |
133 | #define alpha_using_srm 0 | 132 | # define alpha_using_srm 0 |
134 | #endif | 133 | # endif |
134 | # ifdef CONFIG_ALPHA_QEMU | ||
135 | # define alpha_using_qemu 1 | ||
136 | # else | ||
137 | # define alpha_using_qemu 0 | ||
138 | # endif | ||
135 | #endif /* GENERIC */ | 139 | #endif /* GENERIC */ |
136 | 140 | ||
137 | #endif | 141 | #endif /* __KERNEL__ */ |
138 | #endif /* __ALPHA_MACHVEC_H */ | 142 | #endif /* __ALPHA_MACHVEC_H */ |
diff --git a/arch/alpha/include/asm/pal.h b/arch/alpha/include/asm/pal.h index 6fcd2b5b08f0..5422a47646fc 100644 --- a/arch/alpha/include/asm/pal.h +++ b/arch/alpha/include/asm/pal.h | |||
@@ -89,6 +89,7 @@ __CALL_PAL_W1(wrmces, unsigned long); | |||
89 | __CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long); | 89 | __CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long); |
90 | __CALL_PAL_W1(wrusp, unsigned long); | 90 | __CALL_PAL_W1(wrusp, unsigned long); |
91 | __CALL_PAL_W1(wrvptptr, unsigned long); | 91 | __CALL_PAL_W1(wrvptptr, unsigned long); |
92 | __CALL_PAL_RW1(wtint, unsigned long, unsigned long); | ||
92 | 93 | ||
93 | /* | 94 | /* |
94 | * TB routines.. | 95 | * TB routines.. |
@@ -111,5 +112,75 @@ __CALL_PAL_W1(wrvptptr, unsigned long); | |||
111 | #define tbiap() __tbi(-1, /* no second argument */) | 112 | #define tbiap() __tbi(-1, /* no second argument */) |
112 | #define tbia() __tbi(-2, /* no second argument */) | 113 | #define tbia() __tbi(-2, /* no second argument */) |
113 | 114 | ||
115 | /* | ||
116 | * QEMU Cserv routines.. | ||
117 | */ | ||
118 | |||
119 | static inline unsigned long | ||
120 | qemu_get_walltime(void) | ||
121 | { | ||
122 | register unsigned long v0 __asm__("$0"); | ||
123 | register unsigned long a0 __asm__("$16") = 3; | ||
124 | |||
125 | asm("call_pal %2 # cserve get_time" | ||
126 | : "=r"(v0), "+r"(a0) | ||
127 | : "i"(PAL_cserve) | ||
128 | : "$17", "$18", "$19", "$20", "$21"); | ||
129 | |||
130 | return v0; | ||
131 | } | ||
132 | |||
133 | static inline unsigned long | ||
134 | qemu_get_alarm(void) | ||
135 | { | ||
136 | register unsigned long v0 __asm__("$0"); | ||
137 | register unsigned long a0 __asm__("$16") = 4; | ||
138 | |||
139 | asm("call_pal %2 # cserve get_alarm" | ||
140 | : "=r"(v0), "+r"(a0) | ||
141 | : "i"(PAL_cserve) | ||
142 | : "$17", "$18", "$19", "$20", "$21"); | ||
143 | |||
144 | return v0; | ||
145 | } | ||
146 | |||
147 | static inline void | ||
148 | qemu_set_alarm_rel(unsigned long expire) | ||
149 | { | ||
150 | register unsigned long a0 __asm__("$16") = 5; | ||
151 | register unsigned long a1 __asm__("$17") = expire; | ||
152 | |||
153 | asm volatile("call_pal %2 # cserve set_alarm_rel" | ||
154 | : "+r"(a0), "+r"(a1) | ||
155 | : "i"(PAL_cserve) | ||
156 | : "$0", "$18", "$19", "$20", "$21"); | ||
157 | } | ||
158 | |||
159 | static inline void | ||
160 | qemu_set_alarm_abs(unsigned long expire) | ||
161 | { | ||
162 | register unsigned long a0 __asm__("$16") = 6; | ||
163 | register unsigned long a1 __asm__("$17") = expire; | ||
164 | |||
165 | asm volatile("call_pal %2 # cserve set_alarm_abs" | ||
166 | : "+r"(a0), "+r"(a1) | ||
167 | : "i"(PAL_cserve) | ||
168 | : "$0", "$18", "$19", "$20", "$21"); | ||
169 | } | ||
170 | |||
171 | static inline unsigned long | ||
172 | qemu_get_vmtime(void) | ||
173 | { | ||
174 | register unsigned long v0 __asm__("$0"); | ||
175 | register unsigned long a0 __asm__("$16") = 7; | ||
176 | |||
177 | asm("call_pal %2 # cserve get_time" | ||
178 | : "=r"(v0), "+r"(a0) | ||
179 | : "i"(PAL_cserve) | ||
180 | : "$17", "$18", "$19", "$20", "$21"); | ||
181 | |||
182 | return v0; | ||
183 | } | ||
184 | |||
114 | #endif /* !__ASSEMBLY__ */ | 185 | #endif /* !__ASSEMBLY__ */ |
115 | #endif /* __ALPHA_PAL_H */ | 186 | #endif /* __ALPHA_PAL_H */ |
diff --git a/arch/alpha/include/asm/rtc.h b/arch/alpha/include/asm/rtc.h index d70408d36677..f71c3b0ed360 100644 --- a/arch/alpha/include/asm/rtc.h +++ b/arch/alpha/include/asm/rtc.h | |||
@@ -1,12 +1 @@ | |||
1 | #ifndef _ALPHA_RTC_H | ||
2 | #define _ALPHA_RTC_H | ||
3 | |||
4 | #if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP) \ | ||
5 | || defined(CONFIG_ALPHA_GENERIC) | ||
6 | # define get_rtc_time alpha_mv.rtc_get_time | ||
7 | # define set_rtc_time alpha_mv.rtc_set_time | ||
8 | #endif | ||
9 | |||
10 | #include <asm-generic/rtc.h> | #include <asm-generic/rtc.h> | |
11 | |||
12 | #endif | ||
diff --git a/arch/alpha/include/asm/string.h b/arch/alpha/include/asm/string.h index b02b8a282940..c2911f591704 100644 --- a/arch/alpha/include/asm/string.h +++ b/arch/alpha/include/asm/string.h | |||
@@ -22,15 +22,27 @@ extern void * __memcpy(void *, const void *, size_t); | |||
22 | 22 | ||
23 | #define __HAVE_ARCH_MEMSET | 23 | #define __HAVE_ARCH_MEMSET |
24 | extern void * __constant_c_memset(void *, unsigned long, size_t); | 24 | extern void * __constant_c_memset(void *, unsigned long, size_t); |
25 | extern void * ___memset(void *, int, size_t); | ||
25 | extern void * __memset(void *, int, size_t); | 26 | extern void * __memset(void *, int, size_t); |
26 | extern void * memset(void *, int, size_t); | 27 | extern void * memset(void *, int, size_t); |
27 | 28 | ||
28 | #define memset(s, c, n) \ | 29 | /* For gcc 3.x, we cannot have the inline function named "memset" because |
29 | (__builtin_constant_p(c) \ | 30 | the __builtin_memset will attempt to resolve to the inline as well, |
30 | ? (__builtin_constant_p(n) && (c) == 0 \ | 31 | leading to a "sorry" about unimplemented recursive inlining. */ |
31 | ? __builtin_memset((s),0,(n)) \ | 32 | extern inline void *__memset(void *s, int c, size_t n) |
32 | : __constant_c_memset((s),0x0101010101010101UL*(unsigned char)(c),(n))) \ | 33 | { |
33 | : __memset((s),(c),(n))) | 34 | if (__builtin_constant_p(c)) { |
35 | if (__builtin_constant_p(n)) { | ||
36 | return __builtin_memset(s, c, n); | ||
37 | } else { | ||
38 | unsigned long c8 = (c & 0xff) * 0x0101010101010101UL; | ||
39 | return __constant_c_memset(s, c8, n); | ||
40 | } | ||
41 | } | ||
42 | return ___memset(s, c, n); | ||
43 | } | ||
44 | |||
45 | #define memset __memset | ||
34 | 46 | ||
35 | #define __HAVE_ARCH_STRCPY | 47 | #define __HAVE_ARCH_STRCPY |
36 | extern char * strcpy(char *,const char *); | 48 | extern char * strcpy(char *,const char *); |
diff --git a/arch/alpha/include/uapi/asm/pal.h b/arch/alpha/include/uapi/asm/pal.h index 3c0ce08e5f59..dfc8140b9088 100644 --- a/arch/alpha/include/uapi/asm/pal.h +++ b/arch/alpha/include/uapi/asm/pal.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define PAL_rdusp 58 | 46 | #define PAL_rdusp 58 |
47 | #define PAL_whami 60 | 47 | #define PAL_whami 60 |
48 | #define PAL_retsys 61 | 48 | #define PAL_retsys 61 |
49 | #define PAL_wtint 62 | ||
49 | #define PAL_rti 63 | 50 | #define PAL_rti 63 |
50 | 51 | ||
51 | 52 | ||
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 84ec46b38f7d..0d54650e78fc 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCI) += pci.o pci_iommu.o pci-sysfs.o | |||
16 | obj-$(CONFIG_SRM_ENV) += srm_env.o | 16 | obj-$(CONFIG_SRM_ENV) += srm_env.o |
17 | obj-$(CONFIG_MODULES) += module.o | 17 | obj-$(CONFIG_MODULES) += module.o |
18 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o | 18 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o |
19 | obj-$(CONFIG_RTC_DRV_ALPHA) += rtc.o | ||
19 | 20 | ||
20 | ifdef CONFIG_ALPHA_GENERIC | 21 | ifdef CONFIG_ALPHA_GENERIC |
21 | 22 | ||
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 89566b346c0f..f4c7ab6f43b0 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c | |||
@@ -40,6 +40,7 @@ EXPORT_SYMBOL(strrchr); | |||
40 | EXPORT_SYMBOL(memmove); | 40 | EXPORT_SYMBOL(memmove); |
41 | EXPORT_SYMBOL(__memcpy); | 41 | EXPORT_SYMBOL(__memcpy); |
42 | EXPORT_SYMBOL(__memset); | 42 | EXPORT_SYMBOL(__memset); |
43 | EXPORT_SYMBOL(___memset); | ||
43 | EXPORT_SYMBOL(__memsetw); | 44 | EXPORT_SYMBOL(__memsetw); |
44 | EXPORT_SYMBOL(__constant_c_memset); | 45 | EXPORT_SYMBOL(__constant_c_memset); |
45 | EXPORT_SYMBOL(copy_page); | 46 | EXPORT_SYMBOL(copy_page); |
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c index 28e4429596f3..1c8625cb0e25 100644 --- a/arch/alpha/kernel/irq_alpha.c +++ b/arch/alpha/kernel/irq_alpha.c | |||
@@ -66,21 +66,7 @@ do_entInt(unsigned long type, unsigned long vector, | |||
66 | break; | 66 | break; |
67 | case 1: | 67 | case 1: |
68 | old_regs = set_irq_regs(regs); | 68 | old_regs = set_irq_regs(regs); |
69 | #ifdef CONFIG_SMP | ||
70 | { | ||
71 | long cpu; | ||
72 | |||
73 | smp_percpu_timer_interrupt(regs); | ||
74 | cpu = smp_processor_id(); | ||
75 | if (cpu != boot_cpuid) { | ||
76 | kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ)); | ||
77 | } else { | ||
78 | handle_irq(RTC_IRQ); | ||
79 | } | ||
80 | } | ||
81 | #else | ||
82 | handle_irq(RTC_IRQ); | 69 | handle_irq(RTC_IRQ); |
83 | #endif | ||
84 | set_irq_regs(old_regs); | 70 | set_irq_regs(old_regs); |
85 | return; | 71 | return; |
86 | case 2: | 72 | case 2: |
@@ -228,7 +214,7 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr, | |||
228 | */ | 214 | */ |
229 | 215 | ||
230 | struct irqaction timer_irqaction = { | 216 | struct irqaction timer_irqaction = { |
231 | .handler = timer_interrupt, | 217 | .handler = rtc_timer_interrupt, |
232 | .name = "timer", | 218 | .name = "timer", |
233 | }; | 219 | }; |
234 | 220 | ||
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h index 7fa62488bd16..f54bdf658cd0 100644 --- a/arch/alpha/kernel/machvec_impl.h +++ b/arch/alpha/kernel/machvec_impl.h | |||
@@ -43,10 +43,7 @@ | |||
43 | #define CAT1(x,y) x##y | 43 | #define CAT1(x,y) x##y |
44 | #define CAT(x,y) CAT1(x,y) | 44 | #define CAT(x,y) CAT1(x,y) |
45 | 45 | ||
46 | #define DO_DEFAULT_RTC \ | 46 | #define DO_DEFAULT_RTC .rtc_port = 0x70 |
47 | .rtc_port = 0x70, \ | ||
48 | .rtc_get_time = common_get_rtc_time, \ | ||
49 | .rtc_set_time = common_set_rtc_time | ||
50 | 47 | ||
51 | #define DO_EV4_MMU \ | 48 | #define DO_EV4_MMU \ |
52 | .max_asn = EV4_MAX_ASN, \ | 49 | .max_asn = EV4_MAX_ASN, \ |
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c index d821b17047e0..c52e7f0ee5f6 100644 --- a/arch/alpha/kernel/perf_event.c +++ b/arch/alpha/kernel/perf_event.c | |||
@@ -83,6 +83,8 @@ struct alpha_pmu_t { | |||
83 | long pmc_left[3]; | 83 | long pmc_left[3]; |
84 | /* Subroutine for allocation of PMCs. Enforces constraints. */ | 84 | /* Subroutine for allocation of PMCs. Enforces constraints. */ |
85 | int (*check_constraints)(struct perf_event **, unsigned long *, int); | 85 | int (*check_constraints)(struct perf_event **, unsigned long *, int); |
86 | /* Subroutine for checking validity of a raw event for this PMU. */ | ||
87 | int (*raw_event_valid)(u64 config); | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | /* | 90 | /* |
@@ -203,6 +205,12 @@ success: | |||
203 | } | 205 | } |
204 | 206 | ||
205 | 207 | ||
208 | static int ev67_raw_event_valid(u64 config) | ||
209 | { | ||
210 | return config >= EV67_CYCLES && config < EV67_LAST_ET; | ||
211 | }; | ||
212 | |||
213 | |||
206 | static const struct alpha_pmu_t ev67_pmu = { | 214 | static const struct alpha_pmu_t ev67_pmu = { |
207 | .event_map = ev67_perfmon_event_map, | 215 | .event_map = ev67_perfmon_event_map, |
208 | .max_events = ARRAY_SIZE(ev67_perfmon_event_map), | 216 | .max_events = ARRAY_SIZE(ev67_perfmon_event_map), |
@@ -211,7 +219,8 @@ static const struct alpha_pmu_t ev67_pmu = { | |||
211 | .pmc_count_mask = {EV67_PCTR_0_COUNT_MASK, EV67_PCTR_1_COUNT_MASK, 0}, | 219 | .pmc_count_mask = {EV67_PCTR_0_COUNT_MASK, EV67_PCTR_1_COUNT_MASK, 0}, |
212 | .pmc_max_period = {(1UL<<20) - 1, (1UL<<20) - 1, 0}, | 220 | .pmc_max_period = {(1UL<<20) - 1, (1UL<<20) - 1, 0}, |
213 | .pmc_left = {16, 4, 0}, | 221 | .pmc_left = {16, 4, 0}, |
214 | .check_constraints = ev67_check_constraints | 222 | .check_constraints = ev67_check_constraints, |
223 | .raw_event_valid = ev67_raw_event_valid, | ||
215 | }; | 224 | }; |
216 | 225 | ||
217 | 226 | ||
@@ -609,7 +618,9 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
609 | } else if (attr->type == PERF_TYPE_HW_CACHE) { | 618 | } else if (attr->type == PERF_TYPE_HW_CACHE) { |
610 | return -EOPNOTSUPP; | 619 | return -EOPNOTSUPP; |
611 | } else if (attr->type == PERF_TYPE_RAW) { | 620 | } else if (attr->type == PERF_TYPE_RAW) { |
612 | ev = attr->config & 0xff; | 621 | if (!alpha_pmu->raw_event_valid(attr->config)) |
622 | return -EINVAL; | ||
623 | ev = attr->config; | ||
613 | } else { | 624 | } else { |
614 | return -EOPNOTSUPP; | 625 | return -EOPNOTSUPP; |
615 | } | 626 | } |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index f2360a74e5d5..1941a07b5811 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -46,6 +46,23 @@ | |||
46 | void (*pm_power_off)(void) = machine_power_off; | 46 | void (*pm_power_off)(void) = machine_power_off; |
47 | EXPORT_SYMBOL(pm_power_off); | 47 | EXPORT_SYMBOL(pm_power_off); |
48 | 48 | ||
49 | #ifdef CONFIG_ALPHA_WTINT | ||
50 | /* | ||
51 | * Sleep the CPU. | ||
52 | * EV6, LCA45 and QEMU know how to power down, skipping N timer interrupts. | ||
53 | */ | ||
54 | void arch_cpu_idle(void) | ||
55 | { | ||
56 | wtint(0); | ||
57 | local_irq_enable(); | ||
58 | } | ||
59 | |||
60 | void arch_cpu_idle_dead(void) | ||
61 | { | ||
62 | wtint(INT_MAX); | ||
63 | } | ||
64 | #endif /* ALPHA_WTINT */ | ||
65 | |||
49 | struct halt_info { | 66 | struct halt_info { |
50 | int mode; | 67 | int mode; |
51 | char *restart_cmd; | 68 | char *restart_cmd; |
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index d3e52d3fd592..da2d6ec9c370 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h | |||
@@ -135,17 +135,15 @@ extern void unregister_srm_console(void); | |||
135 | /* smp.c */ | 135 | /* smp.c */ |
136 | extern void setup_smp(void); | 136 | extern void setup_smp(void); |
137 | extern void handle_ipi(struct pt_regs *); | 137 | extern void handle_ipi(struct pt_regs *); |
138 | extern void smp_percpu_timer_interrupt(struct pt_regs *); | ||
139 | 138 | ||
140 | /* bios32.c */ | 139 | /* bios32.c */ |
141 | /* extern void reset_for_srm(void); */ | 140 | /* extern void reset_for_srm(void); */ |
142 | 141 | ||
143 | /* time.c */ | 142 | /* time.c */ |
144 | extern irqreturn_t timer_interrupt(int irq, void *dev); | 143 | extern irqreturn_t rtc_timer_interrupt(int irq, void *dev); |
144 | extern void init_clockevent(void); | ||
145 | extern void common_init_rtc(void); | 145 | extern void common_init_rtc(void); |
146 | extern unsigned long est_cycle_freq; | 146 | extern unsigned long est_cycle_freq; |
147 | extern unsigned int common_get_rtc_time(struct rtc_time *time); | ||
148 | extern int common_set_rtc_time(struct rtc_time *time); | ||
149 | 147 | ||
150 | /* smc37c93x.c */ | 148 | /* smc37c93x.c */ |
151 | extern void SMC93x_Init(void); | 149 | extern void SMC93x_Init(void); |
diff --git a/arch/alpha/kernel/rtc.c b/arch/alpha/kernel/rtc.c new file mode 100644 index 000000000000..c8d284d8521f --- /dev/null +++ b/arch/alpha/kernel/rtc.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | * linux/arch/alpha/kernel/rtc.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds | ||
5 | * | ||
6 | * This file contains date handling. | ||
7 | */ | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/param.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/mc146818rtc.h> | ||
14 | #include <linux/bcd.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <asm/rtc.h> | ||
19 | |||
20 | #include "proto.h" | ||
21 | |||
22 | |||
23 | /* | ||
24 | * Support for the RTC device. | ||
25 | * | ||
26 | * We don't want to use the rtc-cmos driver, because we don't want to support | ||
27 | * alarms, as that would be indistinguishable from timer interrupts. | ||
28 | * | ||
29 | * Further, generic code is really, really tied to a 1900 epoch. This is | ||
30 | * true in __get_rtc_time as well as the users of struct rtc_time e.g. | ||
31 | * rtc_tm_to_time. Thankfully all of the other epochs in use are later | ||
32 | * than 1900, and so it's easy to adjust. | ||
33 | */ | ||
34 | |||
35 | static unsigned long rtc_epoch; | ||
36 | |||
37 | static int __init | ||
38 | specifiy_epoch(char *str) | ||
39 | { | ||
40 | unsigned long epoch = simple_strtoul(str, NULL, 0); | ||
41 | if (epoch < 1900) | ||
42 | printk("Ignoring invalid user specified epoch %lu\n", epoch); | ||
43 | else | ||
44 | rtc_epoch = epoch; | ||
45 | return 1; | ||
46 | } | ||
47 | __setup("epoch=", specifiy_epoch); | ||
48 | |||
49 | static void __init | ||
50 | init_rtc_epoch(void) | ||
51 | { | ||
52 | int epoch, year, ctrl; | ||
53 | |||
54 | if (rtc_epoch != 0) { | ||
55 | /* The epoch was specified on the command-line. */ | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | /* Detect the epoch in use on this computer. */ | ||
60 | ctrl = CMOS_READ(RTC_CONTROL); | ||
61 | year = CMOS_READ(RTC_YEAR); | ||
62 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
63 | year = bcd2bin(year); | ||
64 | |||
65 | /* PC-like is standard; used for year >= 70 */ | ||
66 | epoch = 1900; | ||
67 | if (year < 20) { | ||
68 | epoch = 2000; | ||
69 | } else if (year >= 20 && year < 48) { | ||
70 | /* NT epoch */ | ||
71 | epoch = 1980; | ||
72 | } else if (year >= 48 && year < 70) { | ||
73 | /* Digital UNIX epoch */ | ||
74 | epoch = 1952; | ||
75 | } | ||
76 | rtc_epoch = epoch; | ||
77 | |||
78 | printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year); | ||
79 | } | ||
80 | |||
81 | static int | ||
82 | alpha_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
83 | { | ||
84 | __get_rtc_time(tm); | ||
85 | |||
86 | /* Adjust for non-default epochs. It's easier to depend on the | ||
87 | generic __get_rtc_time and adjust the epoch here than create | ||
88 | a copy of __get_rtc_time with the edits we need. */ | ||
89 | if (rtc_epoch != 1900) { | ||
90 | int year = tm->tm_year; | ||
91 | /* Undo the century adjustment made in __get_rtc_time. */ | ||
92 | if (year >= 100) | ||
93 | year -= 100; | ||
94 | year += rtc_epoch - 1900; | ||
95 | /* Redo the century adjustment with the epoch in place. */ | ||
96 | if (year <= 69) | ||
97 | year += 100; | ||
98 | tm->tm_year = year; | ||
99 | } | ||
100 | |||
101 | return rtc_valid_tm(tm); | ||
102 | } | ||
103 | |||
104 | static int | ||
105 | alpha_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
106 | { | ||
107 | struct rtc_time xtm; | ||
108 | |||
109 | if (rtc_epoch != 1900) { | ||
110 | xtm = *tm; | ||
111 | xtm.tm_year -= rtc_epoch - 1900; | ||
112 | tm = &xtm; | ||
113 | } | ||
114 | |||
115 | return __set_rtc_time(tm); | ||
116 | } | ||
117 | |||
118 | static int | ||
119 | alpha_rtc_set_mmss(struct device *dev, unsigned long nowtime) | ||
120 | { | ||
121 | int retval = 0; | ||
122 | int real_seconds, real_minutes, cmos_minutes; | ||
123 | unsigned char save_control, save_freq_select; | ||
124 | |||
125 | /* Note: This code only updates minutes and seconds. Comments | ||
126 | indicate this was to avoid messing with unknown time zones, | ||
127 | and with the epoch nonsense described above. In order for | ||
128 | this to work, the existing clock cannot be off by more than | ||
129 | 15 minutes. | ||
130 | |||
131 | ??? This choice is may be out of date. The x86 port does | ||
132 | not have problems with timezones, and the epoch processing has | ||
133 | now been fixed in alpha_set_rtc_time. | ||
134 | |||
135 | In either case, one can always force a full rtc update with | ||
136 | the userland hwclock program, so surely 15 minute accuracy | ||
137 | is no real burden. */ | ||
138 | |||
139 | /* In order to set the CMOS clock precisely, we have to be called | ||
140 | 500 ms after the second nowtime has started, because when | ||
141 | nowtime is written into the registers of the CMOS clock, it will | ||
142 | jump to the next second precisely 500 ms later. Check the Motorola | ||
143 | MC146818A or Dallas DS12887 data sheet for details. */ | ||
144 | |||
145 | /* irq are locally disabled here */ | ||
146 | spin_lock(&rtc_lock); | ||
147 | /* Tell the clock it's being set */ | ||
148 | save_control = CMOS_READ(RTC_CONTROL); | ||
149 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
150 | |||
151 | /* Stop and reset prescaler */ | ||
152 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
153 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
154 | |||
155 | cmos_minutes = CMOS_READ(RTC_MINUTES); | ||
156 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
157 | cmos_minutes = bcd2bin(cmos_minutes); | ||
158 | |||
159 | real_seconds = nowtime % 60; | ||
160 | real_minutes = nowtime / 60; | ||
161 | if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) { | ||
162 | /* correct for half hour time zone */ | ||
163 | real_minutes += 30; | ||
164 | } | ||
165 | real_minutes %= 60; | ||
166 | |||
167 | if (abs(real_minutes - cmos_minutes) < 30) { | ||
168 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
169 | real_seconds = bin2bcd(real_seconds); | ||
170 | real_minutes = bin2bcd(real_minutes); | ||
171 | } | ||
172 | CMOS_WRITE(real_seconds,RTC_SECONDS); | ||
173 | CMOS_WRITE(real_minutes,RTC_MINUTES); | ||
174 | } else { | ||
175 | printk_once(KERN_NOTICE | ||
176 | "set_rtc_mmss: can't update from %d to %d\n", | ||
177 | cmos_minutes, real_minutes); | ||
178 | retval = -1; | ||
179 | } | ||
180 | |||
181 | /* The following flags have to be released exactly in this order, | ||
182 | * otherwise the DS12887 (popular MC146818A clone with integrated | ||
183 | * battery and quartz) will not reset the oscillator and will not | ||
184 | * update precisely 500 ms later. You won't find this mentioned in | ||
185 | * the Dallas Semiconductor data sheets, but who believes data | ||
186 | * sheets anyway ... -- Markus Kuhn | ||
187 | */ | ||
188 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
189 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
190 | spin_unlock(&rtc_lock); | ||
191 | |||
192 | return retval; | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
197 | { | ||
198 | switch (cmd) { | ||
199 | case RTC_EPOCH_READ: | ||
200 | return put_user(rtc_epoch, (unsigned long __user *)arg); | ||
201 | case RTC_EPOCH_SET: | ||
202 | if (arg < 1900) | ||
203 | return -EINVAL; | ||
204 | rtc_epoch = arg; | ||
205 | return 0; | ||
206 | default: | ||
207 | return -ENOIOCTLCMD; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static const struct rtc_class_ops alpha_rtc_ops = { | ||
212 | .read_time = alpha_rtc_read_time, | ||
213 | .set_time = alpha_rtc_set_time, | ||
214 | .set_mmss = alpha_rtc_set_mmss, | ||
215 | .ioctl = alpha_rtc_ioctl, | ||
216 | }; | ||
217 | |||
218 | /* | ||
219 | * Similarly, except do the actual CMOS access on the boot cpu only. | ||
220 | * This requires marshalling the data across an interprocessor call. | ||
221 | */ | ||
222 | |||
223 | #if defined(CONFIG_SMP) && \ | ||
224 | (defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL)) | ||
225 | # define HAVE_REMOTE_RTC 1 | ||
226 | |||
227 | union remote_data { | ||
228 | struct rtc_time *tm; | ||
229 | unsigned long now; | ||
230 | long retval; | ||
231 | }; | ||
232 | |||
233 | static void | ||
234 | do_remote_read(void *data) | ||
235 | { | ||
236 | union remote_data *x = data; | ||
237 | x->retval = alpha_rtc_read_time(NULL, x->tm); | ||
238 | } | ||
239 | |||
240 | static int | ||
241 | remote_read_time(struct device *dev, struct rtc_time *tm) | ||
242 | { | ||
243 | union remote_data x; | ||
244 | if (smp_processor_id() != boot_cpuid) { | ||
245 | x.tm = tm; | ||
246 | smp_call_function_single(boot_cpuid, do_remote_read, &x, 1); | ||
247 | return x.retval; | ||
248 | } | ||
249 | return alpha_rtc_read_time(NULL, tm); | ||
250 | } | ||
251 | |||
252 | static void | ||
253 | do_remote_set(void *data) | ||
254 | { | ||
255 | union remote_data *x = data; | ||
256 | x->retval = alpha_rtc_set_time(NULL, x->tm); | ||
257 | } | ||
258 | |||
259 | static int | ||
260 | remote_set_time(struct device *dev, struct rtc_time *tm) | ||
261 | { | ||
262 | union remote_data x; | ||
263 | if (smp_processor_id() != boot_cpuid) { | ||
264 | x.tm = tm; | ||
265 | smp_call_function_single(boot_cpuid, do_remote_set, &x, 1); | ||
266 | return x.retval; | ||
267 | } | ||
268 | return alpha_rtc_set_time(NULL, tm); | ||
269 | } | ||
270 | |||
271 | static void | ||
272 | do_remote_mmss(void *data) | ||
273 | { | ||
274 | union remote_data *x = data; | ||
275 | x->retval = alpha_rtc_set_mmss(NULL, x->now); | ||
276 | } | ||
277 | |||
278 | static int | ||
279 | remote_set_mmss(struct device *dev, unsigned long now) | ||
280 | { | ||
281 | union remote_data x; | ||
282 | if (smp_processor_id() != boot_cpuid) { | ||
283 | x.now = now; | ||
284 | smp_call_function_single(boot_cpuid, do_remote_mmss, &x, 1); | ||
285 | return x.retval; | ||
286 | } | ||
287 | return alpha_rtc_set_mmss(NULL, now); | ||
288 | } | ||
289 | |||
290 | static const struct rtc_class_ops remote_rtc_ops = { | ||
291 | .read_time = remote_read_time, | ||
292 | .set_time = remote_set_time, | ||
293 | .set_mmss = remote_set_mmss, | ||
294 | .ioctl = alpha_rtc_ioctl, | ||
295 | }; | ||
296 | #endif | ||
297 | |||
298 | static int __init | ||
299 | alpha_rtc_init(void) | ||
300 | { | ||
301 | const struct rtc_class_ops *ops; | ||
302 | struct platform_device *pdev; | ||
303 | struct rtc_device *rtc; | ||
304 | const char *name; | ||
305 | |||
306 | init_rtc_epoch(); | ||
307 | name = "rtc-alpha"; | ||
308 | ops = &alpha_rtc_ops; | ||
309 | |||
310 | #ifdef HAVE_REMOTE_RTC | ||
311 | if (alpha_mv.rtc_boot_cpu_only) | ||
312 | ops = &remote_rtc_ops; | ||
313 | #endif | ||
314 | |||
315 | pdev = platform_device_register_simple(name, -1, NULL, 0); | ||
316 | rtc = devm_rtc_device_register(&pdev->dev, name, ops, THIS_MODULE); | ||
317 | if (IS_ERR(rtc)) | ||
318 | return PTR_ERR(rtc); | ||
319 | |||
320 | platform_set_drvdata(pdev, rtc); | ||
321 | return 0; | ||
322 | } | ||
323 | device_initcall(alpha_rtc_init); | ||
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 9e3107cc5ebb..b20af76f12c1 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c | |||
@@ -115,10 +115,17 @@ unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE; | |||
115 | 115 | ||
116 | #ifdef CONFIG_ALPHA_GENERIC | 116 | #ifdef CONFIG_ALPHA_GENERIC |
117 | struct alpha_machine_vector alpha_mv; | 117 | struct alpha_machine_vector alpha_mv; |
118 | #endif | ||
119 | |||
120 | #ifndef alpha_using_srm | ||
118 | int alpha_using_srm; | 121 | int alpha_using_srm; |
119 | EXPORT_SYMBOL(alpha_using_srm); | 122 | EXPORT_SYMBOL(alpha_using_srm); |
120 | #endif | 123 | #endif |
121 | 124 | ||
125 | #ifndef alpha_using_qemu | ||
126 | int alpha_using_qemu; | ||
127 | #endif | ||
128 | |||
122 | static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long, | 129 | static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long, |
123 | unsigned long); | 130 | unsigned long); |
124 | static struct alpha_machine_vector *get_sysvec_byname(const char *); | 131 | static struct alpha_machine_vector *get_sysvec_byname(const char *); |
@@ -529,11 +536,15 @@ setup_arch(char **cmdline_p) | |||
529 | atomic_notifier_chain_register(&panic_notifier_list, | 536 | atomic_notifier_chain_register(&panic_notifier_list, |
530 | &alpha_panic_block); | 537 | &alpha_panic_block); |
531 | 538 | ||
532 | #ifdef CONFIG_ALPHA_GENERIC | 539 | #ifndef alpha_using_srm |
533 | /* Assume that we've booted from SRM if we haven't booted from MILO. | 540 | /* Assume that we've booted from SRM if we haven't booted from MILO. |
534 | Detect the later by looking for "MILO" in the system serial nr. */ | 541 | Detect the later by looking for "MILO" in the system serial nr. */ |
535 | alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; | 542 | alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; |
536 | #endif | 543 | #endif |
544 | #ifndef alpha_using_qemu | ||
545 | /* Similarly, look for QEMU. */ | ||
546 | alpha_using_qemu = strstr((const char *)hwrpb->ssn, "QEMU") != 0; | ||
547 | #endif | ||
537 | 548 | ||
538 | /* If we are using SRM, we want to allow callbacks | 549 | /* If we are using SRM, we want to allow callbacks |
539 | as early as possible, so do this NOW, and then | 550 | as early as possible, so do this NOW, and then |
@@ -1207,6 +1218,7 @@ show_cpuinfo(struct seq_file *f, void *slot) | |||
1207 | char *systype_name; | 1218 | char *systype_name; |
1208 | char *sysvariation_name; | 1219 | char *sysvariation_name; |
1209 | int nr_processors; | 1220 | int nr_processors; |
1221 | unsigned long timer_freq; | ||
1210 | 1222 | ||
1211 | cpu_index = (unsigned) (cpu->type - 1); | 1223 | cpu_index = (unsigned) (cpu->type - 1); |
1212 | cpu_name = "Unknown"; | 1224 | cpu_name = "Unknown"; |
@@ -1218,6 +1230,12 @@ show_cpuinfo(struct seq_file *f, void *slot) | |||
1218 | 1230 | ||
1219 | nr_processors = get_nr_processors(cpu, hwrpb->nr_processors); | 1231 | nr_processors = get_nr_processors(cpu, hwrpb->nr_processors); |
1220 | 1232 | ||
1233 | #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200 | ||
1234 | timer_freq = (100UL * hwrpb->intr_freq) / 4096; | ||
1235 | #else | ||
1236 | timer_freq = 100UL * CONFIG_HZ; | ||
1237 | #endif | ||
1238 | |||
1221 | seq_printf(f, "cpu\t\t\t: Alpha\n" | 1239 | seq_printf(f, "cpu\t\t\t: Alpha\n" |
1222 | "cpu model\t\t: %s\n" | 1240 | "cpu model\t\t: %s\n" |
1223 | "cpu variation\t\t: %ld\n" | 1241 | "cpu variation\t\t: %ld\n" |
@@ -1243,8 +1261,7 @@ show_cpuinfo(struct seq_file *f, void *slot) | |||
1243 | (char*)hwrpb->ssn, | 1261 | (char*)hwrpb->ssn, |
1244 | est_cycle_freq ? : hwrpb->cycle_freq, | 1262 | est_cycle_freq ? : hwrpb->cycle_freq, |
1245 | est_cycle_freq ? "est." : "", | 1263 | est_cycle_freq ? "est." : "", |
1246 | hwrpb->intr_freq / 4096, | 1264 | timer_freq / 100, timer_freq % 100, |
1247 | (100 * hwrpb->intr_freq / 4096) % 100, | ||
1248 | hwrpb->pagesize, | 1265 | hwrpb->pagesize, |
1249 | hwrpb->pa_bits, | 1266 | hwrpb->pa_bits, |
1250 | hwrpb->max_asn, | 1267 | hwrpb->max_asn, |
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 9dbbcb3b9146..99ac36d5de4e 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c | |||
@@ -138,9 +138,11 @@ smp_callin(void) | |||
138 | 138 | ||
139 | /* Get our local ticker going. */ | 139 | /* Get our local ticker going. */ |
140 | smp_setup_percpu_timer(cpuid); | 140 | smp_setup_percpu_timer(cpuid); |
141 | init_clockevent(); | ||
141 | 142 | ||
142 | /* Call platform-specific callin, if specified */ | 143 | /* Call platform-specific callin, if specified */ |
143 | if (alpha_mv.smp_callin) alpha_mv.smp_callin(); | 144 | if (alpha_mv.smp_callin) |
145 | alpha_mv.smp_callin(); | ||
144 | 146 | ||
145 | /* All kernel threads share the same mm context. */ | 147 | /* All kernel threads share the same mm context. */ |
146 | atomic_inc(&init_mm.mm_count); | 148 | atomic_inc(&init_mm.mm_count); |
@@ -498,35 +500,6 @@ smp_cpus_done(unsigned int max_cpus) | |||
498 | ((bogosum + 2500) / (5000/HZ)) % 100); | 500 | ((bogosum + 2500) / (5000/HZ)) % 100); |
499 | } | 501 | } |
500 | 502 | ||
501 | |||
502 | void | ||
503 | smp_percpu_timer_interrupt(struct pt_regs *regs) | ||
504 | { | ||
505 | struct pt_regs *old_regs; | ||
506 | int cpu = smp_processor_id(); | ||
507 | unsigned long user = user_mode(regs); | ||
508 | struct cpuinfo_alpha *data = &cpu_data[cpu]; | ||
509 | |||
510 | old_regs = set_irq_regs(regs); | ||
511 | |||
512 | /* Record kernel PC. */ | ||
513 | profile_tick(CPU_PROFILING); | ||
514 | |||
515 | if (!--data->prof_counter) { | ||
516 | /* We need to make like a normal interrupt -- otherwise | ||
517 | timer interrupts ignore the global interrupt lock, | ||
518 | which would be a Bad Thing. */ | ||
519 | irq_enter(); | ||
520 | |||
521 | update_process_times(user); | ||
522 | |||
523 | data->prof_counter = data->prof_multiplier; | ||
524 | |||
525 | irq_exit(); | ||
526 | } | ||
527 | set_irq_regs(old_regs); | ||
528 | } | ||
529 | |||
530 | int | 503 | int |
531 | setup_profiling_timer(unsigned int multiplier) | 504 | setup_profiling_timer(unsigned int multiplier) |
532 | { | 505 | { |
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index 5a0af11b3a61..608f2a7fa0a3 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c | |||
@@ -224,8 +224,6 @@ struct alpha_machine_vector jensen_mv __initmv = { | |||
224 | .machine_check = jensen_machine_check, | 224 | .machine_check = jensen_machine_check, |
225 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, | 225 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, |
226 | .rtc_port = 0x170, | 226 | .rtc_port = 0x170, |
227 | .rtc_get_time = common_get_rtc_time, | ||
228 | .rtc_set_time = common_set_rtc_time, | ||
229 | 227 | ||
230 | .nr_irqs = 16, | 228 | .nr_irqs = 16, |
231 | .device_interrupt = jensen_device_interrupt, | 229 | .device_interrupt = jensen_device_interrupt, |
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c index c92e389ff219..f21d61fab678 100644 --- a/arch/alpha/kernel/sys_marvel.c +++ b/arch/alpha/kernel/sys_marvel.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <asm/hwrpb.h> | 22 | #include <asm/hwrpb.h> |
23 | #include <asm/tlbflush.h> | 23 | #include <asm/tlbflush.h> |
24 | #include <asm/vga.h> | 24 | #include <asm/vga.h> |
25 | #include <asm/rtc.h> | ||
26 | 25 | ||
27 | #include "proto.h" | 26 | #include "proto.h" |
28 | #include "err_impl.h" | 27 | #include "err_impl.h" |
@@ -400,57 +399,6 @@ marvel_init_rtc(void) | |||
400 | init_rtc_irq(); | 399 | init_rtc_irq(); |
401 | } | 400 | } |
402 | 401 | ||
403 | struct marvel_rtc_time { | ||
404 | struct rtc_time *time; | ||
405 | int retval; | ||
406 | }; | ||
407 | |||
408 | #ifdef CONFIG_SMP | ||
409 | static void | ||
410 | smp_get_rtc_time(void *data) | ||
411 | { | ||
412 | struct marvel_rtc_time *mrt = data; | ||
413 | mrt->retval = __get_rtc_time(mrt->time); | ||
414 | } | ||
415 | |||
416 | static void | ||
417 | smp_set_rtc_time(void *data) | ||
418 | { | ||
419 | struct marvel_rtc_time *mrt = data; | ||
420 | mrt->retval = __set_rtc_time(mrt->time); | ||
421 | } | ||
422 | #endif | ||
423 | |||
424 | static unsigned int | ||
425 | marvel_get_rtc_time(struct rtc_time *time) | ||
426 | { | ||
427 | #ifdef CONFIG_SMP | ||
428 | struct marvel_rtc_time mrt; | ||
429 | |||
430 | if (smp_processor_id() != boot_cpuid) { | ||
431 | mrt.time = time; | ||
432 | smp_call_function_single(boot_cpuid, smp_get_rtc_time, &mrt, 1); | ||
433 | return mrt.retval; | ||
434 | } | ||
435 | #endif | ||
436 | return __get_rtc_time(time); | ||
437 | } | ||
438 | |||
439 | static int | ||
440 | marvel_set_rtc_time(struct rtc_time *time) | ||
441 | { | ||
442 | #ifdef CONFIG_SMP | ||
443 | struct marvel_rtc_time mrt; | ||
444 | |||
445 | if (smp_processor_id() != boot_cpuid) { | ||
446 | mrt.time = time; | ||
447 | smp_call_function_single(boot_cpuid, smp_set_rtc_time, &mrt, 1); | ||
448 | return mrt.retval; | ||
449 | } | ||
450 | #endif | ||
451 | return __set_rtc_time(time); | ||
452 | } | ||
453 | |||
454 | static void | 402 | static void |
455 | marvel_smp_callin(void) | 403 | marvel_smp_callin(void) |
456 | { | 404 | { |
@@ -492,8 +440,7 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = { | |||
492 | .vector_name = "MARVEL/EV7", | 440 | .vector_name = "MARVEL/EV7", |
493 | DO_EV7_MMU, | 441 | DO_EV7_MMU, |
494 | .rtc_port = 0x70, | 442 | .rtc_port = 0x70, |
495 | .rtc_get_time = marvel_get_rtc_time, | 443 | .rtc_boot_cpu_only = 1, |
496 | .rtc_set_time = marvel_set_rtc_time, | ||
497 | DO_MARVEL_IO, | 444 | DO_MARVEL_IO, |
498 | .machine_check = marvel_machine_check, | 445 | .machine_check = marvel_machine_check, |
499 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, | 446 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, |
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index ea3395036556..ee39cee8064c 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c | |||
@@ -3,13 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds | 4 | * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds |
5 | * | 5 | * |
6 | * This file contains the PC-specific time handling details: | 6 | * This file contains the clocksource time handling. |
7 | * reading the RTC at bootup, etc.. | ||
8 | * 1994-07-02 Alan Modra | ||
9 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime | ||
10 | * 1995-03-26 Markus Kuhn | ||
11 | * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 | ||
12 | * precision CMOS clock update | ||
13 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | 7 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 |
14 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | 8 | * "A Kernel Model for Precision Timekeeping" by Dave Mills |
15 | * 1997-01-09 Adrian Sun | 9 | * 1997-01-09 Adrian Sun |
@@ -21,9 +15,6 @@ | |||
21 | * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) | 15 | * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) |
22 | * fixed algorithm in do_gettimeofday() for calculating the precise time | 16 | * fixed algorithm in do_gettimeofday() for calculating the precise time |
23 | * from processor cycle counter (now taking lost_ticks into account) | 17 | * from processor cycle counter (now taking lost_ticks into account) |
24 | * 2000-08-13 Jan-Benedict Glaw <jbglaw@lug-owl.de> | ||
25 | * Fixed time_init to be aware of epoches != 1900. This prevents | ||
26 | * booting up in 2048 for me;) Code is stolen from rtc.c. | ||
27 | * 2003-06-03 R. Scott Bailey <scott.bailey@eds.com> | 18 | * 2003-06-03 R. Scott Bailey <scott.bailey@eds.com> |
28 | * Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM | 19 | * Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM |
29 | */ | 20 | */ |
@@ -46,40 +37,19 @@ | |||
46 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
47 | #include <asm/io.h> | 38 | #include <asm/io.h> |
48 | #include <asm/hwrpb.h> | 39 | #include <asm/hwrpb.h> |
49 | #include <asm/rtc.h> | ||
50 | 40 | ||
51 | #include <linux/mc146818rtc.h> | 41 | #include <linux/mc146818rtc.h> |
52 | #include <linux/time.h> | 42 | #include <linux/time.h> |
53 | #include <linux/timex.h> | 43 | #include <linux/timex.h> |
54 | #include <linux/clocksource.h> | 44 | #include <linux/clocksource.h> |
45 | #include <linux/clockchips.h> | ||
55 | 46 | ||
56 | #include "proto.h" | 47 | #include "proto.h" |
57 | #include "irq_impl.h" | 48 | #include "irq_impl.h" |
58 | 49 | ||
59 | static int set_rtc_mmss(unsigned long); | ||
60 | |||
61 | DEFINE_SPINLOCK(rtc_lock); | 50 | DEFINE_SPINLOCK(rtc_lock); |
62 | EXPORT_SYMBOL(rtc_lock); | 51 | EXPORT_SYMBOL(rtc_lock); |
63 | 52 | ||
64 | #define TICK_SIZE (tick_nsec / 1000) | ||
65 | |||
66 | /* | ||
67 | * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting | ||
68 | * by 48 gives us 16 bits for HZ while keeping the accuracy good even | ||
69 | * for large CPU clock rates. | ||
70 | */ | ||
71 | #define FIX_SHIFT 48 | ||
72 | |||
73 | /* lump static variables together for more efficient access: */ | ||
74 | static struct { | ||
75 | /* cycle counter last time it got invoked */ | ||
76 | __u32 last_time; | ||
77 | /* ticks/cycle * 2^48 */ | ||
78 | unsigned long scaled_ticks_per_cycle; | ||
79 | /* partial unused tick */ | ||
80 | unsigned long partial_tick; | ||
81 | } state; | ||
82 | |||
83 | unsigned long est_cycle_freq; | 53 | unsigned long est_cycle_freq; |
84 | 54 | ||
85 | #ifdef CONFIG_IRQ_WORK | 55 | #ifdef CONFIG_IRQ_WORK |
@@ -108,109 +78,156 @@ static inline __u32 rpcc(void) | |||
108 | return __builtin_alpha_rpcc(); | 78 | return __builtin_alpha_rpcc(); |
109 | } | 79 | } |
110 | 80 | ||
111 | int update_persistent_clock(struct timespec now) | ||
112 | { | ||
113 | return set_rtc_mmss(now.tv_sec); | ||
114 | } | ||
115 | 81 | ||
116 | void read_persistent_clock(struct timespec *ts) | 82 | |
83 | /* | ||
84 | * The RTC as a clock_event_device primitive. | ||
85 | */ | ||
86 | |||
87 | static DEFINE_PER_CPU(struct clock_event_device, cpu_ce); | ||
88 | |||
89 | irqreturn_t | ||
90 | rtc_timer_interrupt(int irq, void *dev) | ||
117 | { | 91 | { |
118 | unsigned int year, mon, day, hour, min, sec, epoch; | 92 | int cpu = smp_processor_id(); |
119 | 93 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
120 | sec = CMOS_READ(RTC_SECONDS); | ||
121 | min = CMOS_READ(RTC_MINUTES); | ||
122 | hour = CMOS_READ(RTC_HOURS); | ||
123 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
124 | mon = CMOS_READ(RTC_MONTH); | ||
125 | year = CMOS_READ(RTC_YEAR); | ||
126 | |||
127 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
128 | sec = bcd2bin(sec); | ||
129 | min = bcd2bin(min); | ||
130 | hour = bcd2bin(hour); | ||
131 | day = bcd2bin(day); | ||
132 | mon = bcd2bin(mon); | ||
133 | year = bcd2bin(year); | ||
134 | } | ||
135 | 94 | ||
136 | /* PC-like is standard; used for year >= 70 */ | 95 | /* Don't run the hook for UNUSED or SHUTDOWN. */ |
137 | epoch = 1900; | 96 | if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC)) |
138 | if (year < 20) | 97 | ce->event_handler(ce); |
139 | epoch = 2000; | ||
140 | else if (year >= 20 && year < 48) | ||
141 | /* NT epoch */ | ||
142 | epoch = 1980; | ||
143 | else if (year >= 48 && year < 70) | ||
144 | /* Digital UNIX epoch */ | ||
145 | epoch = 1952; | ||
146 | 98 | ||
147 | printk(KERN_INFO "Using epoch = %d\n", epoch); | 99 | if (test_irq_work_pending()) { |
100 | clear_irq_work_pending(); | ||
101 | irq_work_run(); | ||
102 | } | ||
148 | 103 | ||
149 | if ((year += epoch) < 1970) | 104 | return IRQ_HANDLED; |
150 | year += 100; | 105 | } |
151 | 106 | ||
152 | ts->tv_sec = mktime(year, mon, day, hour, min, sec); | 107 | static void |
153 | ts->tv_nsec = 0; | 108 | rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) |
109 | { | ||
110 | /* The mode member of CE is updated in generic code. | ||
111 | Since we only support periodic events, nothing to do. */ | ||
112 | } | ||
113 | |||
114 | static int | ||
115 | rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | ||
116 | { | ||
117 | /* This hook is for oneshot mode, which we don't support. */ | ||
118 | return -EINVAL; | ||
154 | } | 119 | } |
155 | 120 | ||
121 | static void __init | ||
122 | init_rtc_clockevent(void) | ||
123 | { | ||
124 | int cpu = smp_processor_id(); | ||
125 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | ||
126 | |||
127 | *ce = (struct clock_event_device){ | ||
128 | .name = "rtc", | ||
129 | .features = CLOCK_EVT_FEAT_PERIODIC, | ||
130 | .rating = 100, | ||
131 | .cpumask = cpumask_of(cpu), | ||
132 | .set_mode = rtc_ce_set_mode, | ||
133 | .set_next_event = rtc_ce_set_next_event, | ||
134 | }; | ||
156 | 135 | ||
136 | clockevents_config_and_register(ce, CONFIG_HZ, 0, 0); | ||
137 | } | ||
157 | 138 | ||
139 | |||
158 | /* | 140 | /* |
159 | * timer_interrupt() needs to keep up the real-time clock, | 141 | * The QEMU clock as a clocksource primitive. |
160 | * as well as call the "xtime_update()" routine every clocktick | ||
161 | */ | 142 | */ |
162 | irqreturn_t timer_interrupt(int irq, void *dev) | 143 | |
144 | static cycle_t | ||
145 | qemu_cs_read(struct clocksource *cs) | ||
163 | { | 146 | { |
164 | unsigned long delta; | 147 | return qemu_get_vmtime(); |
165 | __u32 now; | 148 | } |
166 | long nticks; | ||
167 | 149 | ||
168 | #ifndef CONFIG_SMP | 150 | static struct clocksource qemu_cs = { |
169 | /* Not SMP, do kernel PC profiling here. */ | 151 | .name = "qemu", |
170 | profile_tick(CPU_PROFILING); | 152 | .rating = 400, |
171 | #endif | 153 | .read = qemu_cs_read, |
154 | .mask = CLOCKSOURCE_MASK(64), | ||
155 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
156 | .max_idle_ns = LONG_MAX | ||
157 | }; | ||
172 | 158 | ||
173 | /* | ||
174 | * Calculate how many ticks have passed since the last update, | ||
175 | * including any previous partial leftover. Save any resulting | ||
176 | * fraction for the next pass. | ||
177 | */ | ||
178 | now = rpcc(); | ||
179 | delta = now - state.last_time; | ||
180 | state.last_time = now; | ||
181 | delta = delta * state.scaled_ticks_per_cycle + state.partial_tick; | ||
182 | state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1); | ||
183 | nticks = delta >> FIX_SHIFT; | ||
184 | 159 | ||
185 | if (nticks) | 160 | /* |
186 | xtime_update(nticks); | 161 | * The QEMU alarm as a clock_event_device primitive. |
162 | */ | ||
187 | 163 | ||
188 | if (test_irq_work_pending()) { | 164 | static void |
189 | clear_irq_work_pending(); | 165 | qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) |
190 | irq_work_run(); | 166 | { |
191 | } | 167 | /* The mode member of CE is updated for us in generic code. |
168 | Just make sure that the event is disabled. */ | ||
169 | qemu_set_alarm_abs(0); | ||
170 | } | ||
192 | 171 | ||
193 | #ifndef CONFIG_SMP | 172 | static int |
194 | while (nticks--) | 173 | qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) |
195 | update_process_times(user_mode(get_irq_regs())); | 174 | { |
196 | #endif | 175 | qemu_set_alarm_rel(evt); |
176 | return 0; | ||
177 | } | ||
197 | 178 | ||
179 | static irqreturn_t | ||
180 | qemu_timer_interrupt(int irq, void *dev) | ||
181 | { | ||
182 | int cpu = smp_processor_id(); | ||
183 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | ||
184 | |||
185 | ce->event_handler(ce); | ||
198 | return IRQ_HANDLED; | 186 | return IRQ_HANDLED; |
199 | } | 187 | } |
200 | 188 | ||
189 | static void __init | ||
190 | init_qemu_clockevent(void) | ||
191 | { | ||
192 | int cpu = smp_processor_id(); | ||
193 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | ||
194 | |||
195 | *ce = (struct clock_event_device){ | ||
196 | .name = "qemu", | ||
197 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
198 | .rating = 400, | ||
199 | .cpumask = cpumask_of(cpu), | ||
200 | .set_mode = qemu_ce_set_mode, | ||
201 | .set_next_event = qemu_ce_set_next_event, | ||
202 | }; | ||
203 | |||
204 | clockevents_config_and_register(ce, NSEC_PER_SEC, 1000, LONG_MAX); | ||
205 | } | ||
206 | |||
207 | |||
201 | void __init | 208 | void __init |
202 | common_init_rtc(void) | 209 | common_init_rtc(void) |
203 | { | 210 | { |
204 | unsigned char x; | 211 | unsigned char x, sel = 0; |
205 | 212 | ||
206 | /* Reset periodic interrupt frequency. */ | 213 | /* Reset periodic interrupt frequency. */ |
207 | x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; | 214 | #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200 |
208 | /* Test includes known working values on various platforms | 215 | x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; |
209 | where 0x26 is wrong; we refuse to change those. */ | 216 | /* Test includes known working values on various platforms |
210 | if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) { | 217 | where 0x26 is wrong; we refuse to change those. */ |
211 | printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x); | 218 | if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) { |
212 | CMOS_WRITE(0x26, RTC_FREQ_SELECT); | 219 | sel = RTC_REF_CLCK_32KHZ + 6; |
213 | } | 220 | } |
221 | #elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32 | ||
222 | sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ); | ||
223 | #else | ||
224 | # error "Unknown HZ from arch/alpha/Kconfig" | ||
225 | #endif | ||
226 | if (sel) { | ||
227 | printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n", | ||
228 | CONFIG_HZ, sel); | ||
229 | CMOS_WRITE(sel, RTC_FREQ_SELECT); | ||
230 | } | ||
214 | 231 | ||
215 | /* Turn on periodic interrupts. */ | 232 | /* Turn on periodic interrupts. */ |
216 | x = CMOS_READ(RTC_CONTROL); | 233 | x = CMOS_READ(RTC_CONTROL); |
@@ -233,16 +250,37 @@ common_init_rtc(void) | |||
233 | init_rtc_irq(); | 250 | init_rtc_irq(); |
234 | } | 251 | } |
235 | 252 | ||
236 | unsigned int common_get_rtc_time(struct rtc_time *time) | 253 | |
237 | { | 254 | #ifndef CONFIG_ALPHA_WTINT |
238 | return __get_rtc_time(time); | 255 | /* |
239 | } | 256 | * The RPCC as a clocksource primitive. |
257 | * | ||
258 | * While we have free-running timecounters running on all CPUs, and we make | ||
259 | * a half-hearted attempt in init_rtc_rpcc_info to sync the timecounter | ||
260 | * with the wall clock, that initialization isn't kept up-to-date across | ||
261 | * different time counters in SMP mode. Therefore we can only use this | ||
262 | * method when there's only one CPU enabled. | ||
263 | * | ||
264 | * When using the WTINT PALcall, the RPCC may shift to a lower frequency, | ||
265 | * or stop altogether, while waiting for the interrupt. Therefore we cannot | ||
266 | * use this method when WTINT is in use. | ||
267 | */ | ||
240 | 268 | ||
241 | int common_set_rtc_time(struct rtc_time *time) | 269 | static cycle_t read_rpcc(struct clocksource *cs) |
242 | { | 270 | { |
243 | return __set_rtc_time(time); | 271 | return rpcc(); |
244 | } | 272 | } |
245 | 273 | ||
274 | static struct clocksource clocksource_rpcc = { | ||
275 | .name = "rpcc", | ||
276 | .rating = 300, | ||
277 | .read = read_rpcc, | ||
278 | .mask = CLOCKSOURCE_MASK(32), | ||
279 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | ||
280 | }; | ||
281 | #endif /* ALPHA_WTINT */ | ||
282 | |||
283 | |||
246 | /* Validate a computed cycle counter result against the known bounds for | 284 | /* Validate a computed cycle counter result against the known bounds for |
247 | the given processor core. There's too much brokenness in the way of | 285 | the given processor core. There's too much brokenness in the way of |
248 | timing hardware for any one method to work everywhere. :-( | 286 | timing hardware for any one method to work everywhere. :-( |
@@ -353,33 +391,6 @@ rpcc_after_update_in_progress(void) | |||
353 | return rpcc(); | 391 | return rpcc(); |
354 | } | 392 | } |
355 | 393 | ||
356 | #ifndef CONFIG_SMP | ||
357 | /* Until and unless we figure out how to get cpu cycle counters | ||
358 | in sync and keep them there, we can't use the rpcc. */ | ||
359 | static cycle_t read_rpcc(struct clocksource *cs) | ||
360 | { | ||
361 | cycle_t ret = (cycle_t)rpcc(); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static struct clocksource clocksource_rpcc = { | ||
366 | .name = "rpcc", | ||
367 | .rating = 300, | ||
368 | .read = read_rpcc, | ||
369 | .mask = CLOCKSOURCE_MASK(32), | ||
370 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | ||
371 | }; | ||
372 | |||
373 | static inline void register_rpcc_clocksource(long cycle_freq) | ||
374 | { | ||
375 | clocksource_register_hz(&clocksource_rpcc, cycle_freq); | ||
376 | } | ||
377 | #else /* !CONFIG_SMP */ | ||
378 | static inline void register_rpcc_clocksource(long cycle_freq) | ||
379 | { | ||
380 | } | ||
381 | #endif /* !CONFIG_SMP */ | ||
382 | |||
383 | void __init | 394 | void __init |
384 | time_init(void) | 395 | time_init(void) |
385 | { | 396 | { |
@@ -387,6 +398,15 @@ time_init(void) | |||
387 | unsigned long cycle_freq, tolerance; | 398 | unsigned long cycle_freq, tolerance; |
388 | long diff; | 399 | long diff; |
389 | 400 | ||
401 | if (alpha_using_qemu) { | ||
402 | clocksource_register_hz(&qemu_cs, NSEC_PER_SEC); | ||
403 | init_qemu_clockevent(); | ||
404 | |||
405 | timer_irqaction.handler = qemu_timer_interrupt; | ||
406 | init_rtc_irq(); | ||
407 | return; | ||
408 | } | ||
409 | |||
390 | /* Calibrate CPU clock -- attempt #1. */ | 410 | /* Calibrate CPU clock -- attempt #1. */ |
391 | if (!est_cycle_freq) | 411 | if (!est_cycle_freq) |
392 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); | 412 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); |
@@ -421,100 +441,25 @@ time_init(void) | |||
421 | "and unable to estimate a proper value!\n"); | 441 | "and unable to estimate a proper value!\n"); |
422 | } | 442 | } |
423 | 443 | ||
424 | /* From John Bowman <bowman@math.ualberta.ca>: allow the values | 444 | /* See above for restrictions on using clocksource_rpcc. */ |
425 | to settle, as the Update-In-Progress bit going low isn't good | 445 | #ifndef CONFIG_ALPHA_WTINT |
426 | enough on some hardware. 2ms is our guess; we haven't found | 446 | if (hwrpb->nr_processors == 1) |
427 | bogomips yet, but this is close on a 500Mhz box. */ | 447 | clocksource_register_hz(&clocksource_rpcc, cycle_freq); |
428 | __delay(1000000); | 448 | #endif |
429 | |||
430 | |||
431 | if (HZ > (1<<16)) { | ||
432 | extern void __you_loose (void); | ||
433 | __you_loose(); | ||
434 | } | ||
435 | |||
436 | register_rpcc_clocksource(cycle_freq); | ||
437 | |||
438 | state.last_time = cc1; | ||
439 | state.scaled_ticks_per_cycle | ||
440 | = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq; | ||
441 | state.partial_tick = 0L; | ||
442 | 449 | ||
443 | /* Startup the timer source. */ | 450 | /* Startup the timer source. */ |
444 | alpha_mv.init_rtc(); | 451 | alpha_mv.init_rtc(); |
452 | init_rtc_clockevent(); | ||
445 | } | 453 | } |
446 | 454 | ||
447 | /* | 455 | /* Initialize the clock_event_device for secondary cpus. */ |
448 | * In order to set the CMOS clock precisely, set_rtc_mmss has to be | 456 | #ifdef CONFIG_SMP |
449 | * called 500 ms after the second nowtime has started, because when | 457 | void __init |
450 | * nowtime is written into the registers of the CMOS clock, it will | 458 | init_clockevent(void) |
451 | * jump to the next second precisely 500 ms later. Check the Motorola | ||
452 | * MC146818A or Dallas DS12887 data sheet for details. | ||
453 | * | ||
454 | * BUG: This routine does not handle hour overflow properly; it just | ||
455 | * sets the minutes. Usually you won't notice until after reboot! | ||
456 | */ | ||
457 | |||
458 | |||
459 | static int | ||
460 | set_rtc_mmss(unsigned long nowtime) | ||
461 | { | 459 | { |
462 | int retval = 0; | 460 | if (alpha_using_qemu) |
463 | int real_seconds, real_minutes, cmos_minutes; | 461 | init_qemu_clockevent(); |
464 | unsigned char save_control, save_freq_select; | 462 | else |
465 | 463 | init_rtc_clockevent(); | |
466 | /* irq are locally disabled here */ | ||
467 | spin_lock(&rtc_lock); | ||
468 | /* Tell the clock it's being set */ | ||
469 | save_control = CMOS_READ(RTC_CONTROL); | ||
470 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
471 | |||
472 | /* Stop and reset prescaler */ | ||
473 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
474 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
475 | |||
476 | cmos_minutes = CMOS_READ(RTC_MINUTES); | ||
477 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
478 | cmos_minutes = bcd2bin(cmos_minutes); | ||
479 | |||
480 | /* | ||
481 | * since we're only adjusting minutes and seconds, | ||
482 | * don't interfere with hour overflow. This avoids | ||
483 | * messing with unknown time zones but requires your | ||
484 | * RTC not to be off by more than 15 minutes | ||
485 | */ | ||
486 | real_seconds = nowtime % 60; | ||
487 | real_minutes = nowtime / 60; | ||
488 | if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) { | ||
489 | /* correct for half hour time zone */ | ||
490 | real_minutes += 30; | ||
491 | } | ||
492 | real_minutes %= 60; | ||
493 | |||
494 | if (abs(real_minutes - cmos_minutes) < 30) { | ||
495 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
496 | real_seconds = bin2bcd(real_seconds); | ||
497 | real_minutes = bin2bcd(real_minutes); | ||
498 | } | ||
499 | CMOS_WRITE(real_seconds,RTC_SECONDS); | ||
500 | CMOS_WRITE(real_minutes,RTC_MINUTES); | ||
501 | } else { | ||
502 | printk_once(KERN_NOTICE | ||
503 | "set_rtc_mmss: can't update from %d to %d\n", | ||
504 | cmos_minutes, real_minutes); | ||
505 | retval = -1; | ||
506 | } | ||
507 | |||
508 | /* The following flags have to be released exactly in this order, | ||
509 | * otherwise the DS12887 (popular MC146818A clone with integrated | ||
510 | * battery and quartz) will not reset the oscillator and will not | ||
511 | * update precisely 500 ms later. You won't find this mentioned in | ||
512 | * the Dallas Semiconductor data sheets, but who believes data | ||
513 | * sheets anyway ... -- Markus Kuhn | ||
514 | */ | ||
515 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
516 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
517 | spin_unlock(&rtc_lock); | ||
518 | |||
519 | return retval; | ||
520 | } | 464 | } |
465 | #endif | ||
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index bd0665cdc840..9c4c189eb22f 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c | |||
@@ -241,6 +241,21 @@ do_entIF(unsigned long type, struct pt_regs *regs) | |||
241 | (const char *)(data[1] | (long)data[2] << 32), | 241 | (const char *)(data[1] | (long)data[2] << 32), |
242 | data[0]); | 242 | data[0]); |
243 | } | 243 | } |
244 | #ifdef CONFIG_ALPHA_WTINT | ||
245 | if (type == 4) { | ||
246 | /* If CALL_PAL WTINT is totally unsupported by the | ||
247 | PALcode, e.g. MILO, "emulate" it by overwriting | ||
248 | the insn. */ | ||
249 | unsigned int *pinsn | ||
250 | = (unsigned int *) regs->pc - 1; | ||
251 | if (*pinsn == PAL_wtint) { | ||
252 | *pinsn = 0x47e01400; /* mov 0,$0 */ | ||
253 | imb(); | ||
254 | regs->r0 = 0; | ||
255 | return; | ||
256 | } | ||
257 | } | ||
258 | #endif /* ALPHA_WTINT */ | ||
244 | die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), | 259 | die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), |
245 | regs, type, NULL); | 260 | regs, type, NULL); |
246 | } | 261 | } |
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index ffb19b7da999..ff3c10721caf 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c | |||
@@ -130,7 +130,7 @@ csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst, | |||
130 | *dst = word | tmp; | 130 | *dst = word | tmp; |
131 | checksum += carry; | 131 | checksum += carry; |
132 | } | 132 | } |
133 | if (err) *errp = err; | 133 | if (err && errp) *errp = err; |
134 | return checksum; | 134 | return checksum; |
135 | } | 135 | } |
136 | 136 | ||
@@ -185,7 +185,7 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, | |||
185 | *dst = word | tmp; | 185 | *dst = word | tmp; |
186 | checksum += carry; | 186 | checksum += carry; |
187 | } | 187 | } |
188 | if (err) *errp = err; | 188 | if (err && errp) *errp = err; |
189 | return checksum; | 189 | return checksum; |
190 | } | 190 | } |
191 | 191 | ||
@@ -242,7 +242,7 @@ csum_partial_cfu_src_aligned(const unsigned long __user *src, | |||
242 | stq_u(partial_dest | second_dest, dst); | 242 | stq_u(partial_dest | second_dest, dst); |
243 | out: | 243 | out: |
244 | checksum += carry; | 244 | checksum += carry; |
245 | if (err) *errp = err; | 245 | if (err && errp) *errp = err; |
246 | return checksum; | 246 | return checksum; |
247 | } | 247 | } |
248 | 248 | ||
@@ -325,7 +325,7 @@ csum_partial_cfu_unaligned(const unsigned long __user * src, | |||
325 | stq_u(partial_dest | word | second_dest, dst); | 325 | stq_u(partial_dest | word | second_dest, dst); |
326 | checksum += carry; | 326 | checksum += carry; |
327 | } | 327 | } |
328 | if (err) *errp = err; | 328 | if (err && errp) *errp = err; |
329 | return checksum; | 329 | return checksum; |
330 | } | 330 | } |
331 | 331 | ||
@@ -339,7 +339,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, | |||
339 | 339 | ||
340 | if (len) { | 340 | if (len) { |
341 | if (!access_ok(VERIFY_READ, src, len)) { | 341 | if (!access_ok(VERIFY_READ, src, len)) { |
342 | *errp = -EFAULT; | 342 | if (errp) *errp = -EFAULT; |
343 | memset(dst, 0, len); | 343 | memset(dst, 0, len); |
344 | return sum; | 344 | return sum; |
345 | } | 345 | } |
diff --git a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S index d8b94e1c7fca..356bb2fdd705 100644 --- a/arch/alpha/lib/ev6-memset.S +++ b/arch/alpha/lib/ev6-memset.S | |||
@@ -30,14 +30,15 @@ | |||
30 | .set noat | 30 | .set noat |
31 | .set noreorder | 31 | .set noreorder |
32 | .text | 32 | .text |
33 | .globl memset | ||
33 | .globl __memset | 34 | .globl __memset |
35 | .globl ___memset | ||
34 | .globl __memsetw | 36 | .globl __memsetw |
35 | .globl __constant_c_memset | 37 | .globl __constant_c_memset |
36 | .globl memset | ||
37 | 38 | ||
38 | .ent __memset | 39 | .ent ___memset |
39 | .align 5 | 40 | .align 5 |
40 | __memset: | 41 | ___memset: |
41 | .frame $30,0,$26,0 | 42 | .frame $30,0,$26,0 |
42 | .prologue 0 | 43 | .prologue 0 |
43 | 44 | ||
@@ -227,7 +228,7 @@ end_b: | |||
227 | nop | 228 | nop |
228 | nop | 229 | nop |
229 | ret $31,($26),1 # L0 : | 230 | ret $31,($26),1 # L0 : |
230 | .end __memset | 231 | .end ___memset |
231 | 232 | ||
232 | /* | 233 | /* |
233 | * This is the original body of code, prior to replication and | 234 | * This is the original body of code, prior to replication and |
@@ -594,4 +595,5 @@ end_w: | |||
594 | 595 | ||
595 | .end __memsetw | 596 | .end __memsetw |
596 | 597 | ||
597 | memset = __memset | 598 | memset = ___memset |
599 | __memset = ___memset | ||
diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S index 311b8cfc6914..76ccc6d1f364 100644 --- a/arch/alpha/lib/memset.S +++ b/arch/alpha/lib/memset.S | |||
@@ -19,11 +19,13 @@ | |||
19 | .text | 19 | .text |
20 | .globl memset | 20 | .globl memset |
21 | .globl __memset | 21 | .globl __memset |
22 | .globl ___memset | ||
22 | .globl __memsetw | 23 | .globl __memsetw |
23 | .globl __constant_c_memset | 24 | .globl __constant_c_memset |
24 | .ent __memset | 25 | |
26 | .ent ___memset | ||
25 | .align 5 | 27 | .align 5 |
26 | __memset: | 28 | ___memset: |
27 | .frame $30,0,$26,0 | 29 | .frame $30,0,$26,0 |
28 | .prologue 0 | 30 | .prologue 0 |
29 | 31 | ||
@@ -103,7 +105,7 @@ within_one_quad: | |||
103 | 105 | ||
104 | end: | 106 | end: |
105 | ret $31,($26),1 /* E1 */ | 107 | ret $31,($26),1 /* E1 */ |
106 | .end __memset | 108 | .end ___memset |
107 | 109 | ||
108 | .align 5 | 110 | .align 5 |
109 | .ent __memsetw | 111 | .ent __memsetw |
@@ -121,4 +123,5 @@ __memsetw: | |||
121 | 123 | ||
122 | .end __memsetw | 124 | .end __memsetw |
123 | 125 | ||
124 | memset = __memset | 126 | memset = ___memset |
127 | __memset = ___memset | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 15f166a470a7..007730222116 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -626,7 +626,7 @@ comment "Platform RTC drivers" | |||
626 | 626 | ||
627 | config RTC_DRV_CMOS | 627 | config RTC_DRV_CMOS |
628 | tristate "PC-style 'CMOS'" | 628 | tristate "PC-style 'CMOS'" |
629 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64 | 629 | depends on X86 || ARM || M32R || ATARI || PPC || MIPS || SPARC64 |
630 | default y if X86 | 630 | default y if X86 |
631 | help | 631 | help |
632 | Say "yes" here to get direct support for the real time clock | 632 | Say "yes" here to get direct support for the real time clock |
@@ -643,6 +643,14 @@ config RTC_DRV_CMOS | |||
643 | This driver can also be built as a module. If so, the module | 643 | This driver can also be built as a module. If so, the module |
644 | will be called rtc-cmos. | 644 | will be called rtc-cmos. |
645 | 645 | ||
646 | config RTC_DRV_ALPHA | ||
647 | bool "Alpha PC-style CMOS" | ||
648 | depends on ALPHA | ||
649 | default y | ||
650 | help | ||
651 | Direct support for the real-time clock found on every Alpha | ||
652 | system, specifically MC146818 compatibles. If in doubt, say Y. | ||
653 | |||
646 | config RTC_DRV_VRTC | 654 | config RTC_DRV_VRTC |
647 | tristate "Virtual RTC for Intel MID platforms" | 655 | tristate "Virtual RTC for Intel MID platforms" |
648 | depends on X86_INTEL_MID | 656 | depends on X86_INTEL_MID |