diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-19 19:23:26 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-19 19:23:26 -0400 |
commit | f2783c15007468c14972e2617db51e9affc7fad9 (patch) | |
tree | 6c8f57ee8e5cdaeb810a3ccf7f697576a7df7615 | |
parent | 03f88e9f7145b03fd0d855918d54a3bf5342ac5e (diff) |
powerpc: Merge time.c and asm/time.h.
We now use the merged time.c for both 32-bit and 64-bit compilation
with ARCH=powerpc, and for ARCH=ppc64, but not for ARCH=ppc32.
This removes setup_default_decr (folds its function into time_init)
and moves wakeup_decrementer into time.c. This also makes an
asm-powerpc/rtc.h.
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 27 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c (renamed from arch/ppc64/kernel/time.c) | 497 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/cpufreq.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/time.c | 28 | ||||
-rw-r--r-- | arch/ppc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/time.c | 9 | ||||
-rw-r--r-- | arch/ppc64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/pmac_time.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/setup.c | 9 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu.c | 11 | ||||
-rw-r--r-- | include/asm-powerpc/irq.h | 2 | ||||
-rw-r--r-- | include/asm-powerpc/rtc.h | 80 | ||||
-rw-r--r-- | include/asm-powerpc/time.h | 212 | ||||
-rw-r--r-- | include/asm-ppc64/time.h | 124 |
17 files changed, 650 insertions, 378 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 5c5d2b5f3ca2..b347ac320252 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -29,7 +29,7 @@ extra-$(CONFIG_PPC64) += entry_64.o | |||
29 | extra-$(CONFIG_PPC_FPU) += fpu.o | 29 | extra-$(CONFIG_PPC_FPU) += fpu.o |
30 | extra-y += vmlinux.lds | 30 | extra-y += vmlinux.lds |
31 | 31 | ||
32 | obj-y += process.o init_task.o \ | 32 | obj-y += process.o init_task.o time.o \ |
33 | prom.o systbl.o traps.o | 33 | prom.o systbl.o traps.o |
34 | obj-$(CONFIG_PPC32) += entry_32.o idle_6xx.o setup_32.o misc_32.o | 34 | obj-$(CONFIG_PPC32) += entry_32.o idle_6xx.o setup_32.o misc_32.o |
35 | obj-$(CONFIG_PPC64) += setup_64.o misc_64.o | 35 | obj-$(CONFIG_PPC64) += setup_64.o misc_64.o |
@@ -44,7 +44,7 @@ endif | |||
44 | 44 | ||
45 | else | 45 | else |
46 | # stuff used from here for ARCH=ppc or ARCH=ppc64 | 46 | # stuff used from here for ARCH=ppc or ARCH=ppc64 |
47 | obj-$(CONFIG_PPC64) += traps.o process.o init_task.o | 47 | obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o |
48 | 48 | ||
49 | fpux-$(CONFIG_PPC32) += fpu.o | 49 | fpux-$(CONFIG_PPC32) += fpu.o |
50 | extra-$(CONFIG_PPC_FPU) += $(fpux-y) | 50 | extra-$(CONFIG_PPC_FPU) += $(fpux-y) |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 0b0e908b5065..303229b090b8 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -36,6 +36,33 @@ _GLOBAL(__delay) | |||
36 | blr | 36 | blr |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * This returns the high 64 bits of the product of two 64-bit numbers. | ||
40 | */ | ||
41 | _GLOBAL(mulhdu) | ||
42 | cmpwi r6,0 | ||
43 | cmpwi cr1,r3,0 | ||
44 | mr r10,r4 | ||
45 | mulhwu r4,r4,r5 | ||
46 | beq 1f | ||
47 | mulhwu r0,r10,r6 | ||
48 | mullw r7,r10,r5 | ||
49 | addc r7,r0,r7 | ||
50 | addze r4,r4 | ||
51 | 1: beqlr cr1 /* all done if high part of A is 0 */ | ||
52 | mr r10,r3 | ||
53 | mullw r9,r3,r5 | ||
54 | mulhwu r3,r3,r5 | ||
55 | beq 2f | ||
56 | mullw r0,r10,r6 | ||
57 | mulhwu r8,r10,r6 | ||
58 | addc r7,r0,r7 | ||
59 | adde r4,r4,r8 | ||
60 | addze r3,r3 | ||
61 | 2: addc r4,r4,r9 | ||
62 | addze r3,r3 | ||
63 | blr | ||
64 | |||
65 | /* | ||
39 | * Returns (address we're running at) - (address we were linked at) | 66 | * Returns (address we're running at) - (address we were linked at) |
40 | * for use before the text and data are mapped to KERNELBASE. | 67 | * for use before the text and data are mapped to KERNELBASE. |
41 | */ | 68 | */ |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 010554e5fe48..40c9e67e1b28 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -260,7 +260,6 @@ EXPORT_SYMBOL(__res); | |||
260 | #ifdef CONFIG_PPC32 | 260 | #ifdef CONFIG_PPC32 |
261 | EXPORT_SYMBOL(next_mmu_context); | 261 | EXPORT_SYMBOL(next_mmu_context); |
262 | EXPORT_SYMBOL(set_context); | 262 | EXPORT_SYMBOL(set_context); |
263 | EXPORT_SYMBOL(disarm_decr); | ||
264 | #endif | 263 | #endif |
265 | 264 | ||
266 | #ifdef CONFIG_PPC_STD_MMU_32 | 265 | #ifdef CONFIG_PPC_STD_MMU_32 |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4fcf67575cbb..6f29614c3581 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -1083,15 +1083,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg) | |||
1083 | printk("[terminate]%04x %s\n", src, msg); | 1083 | printk("[terminate]%04x %s\n", src, msg); |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | /* This should only be called on processor 0 during calibrate decr */ | ||
1087 | void __init setup_default_decr(void) | ||
1088 | { | ||
1089 | struct paca_struct *lpaca = get_paca(); | ||
1090 | |||
1091 | lpaca->default_decr = tb_ticks_per_jiffy; | ||
1092 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; | ||
1093 | } | ||
1094 | |||
1095 | #ifndef CONFIG_PPC_ISERIES | 1086 | #ifndef CONFIG_PPC_ISERIES |
1096 | /* | 1087 | /* |
1097 | * This function can be used by platforms to "find" legacy serial ports. | 1088 | * This function can be used by platforms to "find" legacy serial ports. |
diff --git a/arch/ppc64/kernel/time.c b/arch/powerpc/kernel/time.c index 7f63755eddfd..d1608473075f 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * | ||
3 | * Common time routines among all ppc machines. | 2 | * Common time routines among all ppc machines. |
4 | * | 3 | * |
5 | * Written by Cort Dougan (cort@cs.nmt.edu) to merge | 4 | * Written by Cort Dougan (cort@cs.nmt.edu) to merge |
@@ -44,29 +43,32 @@ | |||
44 | #include <linux/interrupt.h> | 43 | #include <linux/interrupt.h> |
45 | #include <linux/timex.h> | 44 | #include <linux/timex.h> |
46 | #include <linux/kernel_stat.h> | 45 | #include <linux/kernel_stat.h> |
47 | #include <linux/mc146818rtc.h> | ||
48 | #include <linux/time.h> | 46 | #include <linux/time.h> |
49 | #include <linux/init.h> | 47 | #include <linux/init.h> |
50 | #include <linux/profile.h> | 48 | #include <linux/profile.h> |
51 | #include <linux/cpu.h> | 49 | #include <linux/cpu.h> |
52 | #include <linux/security.h> | 50 | #include <linux/security.h> |
51 | #include <linux/percpu.h> | ||
52 | #include <linux/rtc.h> | ||
53 | 53 | ||
54 | #include <asm/io.h> | 54 | #include <asm/io.h> |
55 | #include <asm/processor.h> | 55 | #include <asm/processor.h> |
56 | #include <asm/nvram.h> | 56 | #include <asm/nvram.h> |
57 | #include <asm/cache.h> | 57 | #include <asm/cache.h> |
58 | #include <asm/machdep.h> | 58 | #include <asm/machdep.h> |
59 | #ifdef CONFIG_PPC_ISERIES | ||
60 | #include <asm/iSeries/ItLpQueue.h> | ||
61 | #include <asm/iSeries/HvCallXm.h> | ||
62 | #endif | ||
63 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
64 | #include <asm/time.h> | 60 | #include <asm/time.h> |
65 | #include <asm/ppcdebug.h> | ||
66 | #include <asm/prom.h> | 61 | #include <asm/prom.h> |
67 | #include <asm/sections.h> | 62 | #include <asm/irq.h> |
63 | #include <asm/div64.h> | ||
64 | #ifdef CONFIG_PPC64 | ||
68 | #include <asm/systemcfg.h> | 65 | #include <asm/systemcfg.h> |
69 | #include <asm/firmware.h> | 66 | #include <asm/firmware.h> |
67 | #endif | ||
68 | #ifdef CONFIG_PPC_ISERIES | ||
69 | #include <asm/iSeries/ItLpQueue.h> | ||
70 | #include <asm/iSeries/HvCallXm.h> | ||
71 | #endif | ||
70 | 72 | ||
71 | u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; | 73 | u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; |
72 | 74 | ||
@@ -81,27 +83,37 @@ unsigned long iSeries_recal_tb = 0; | |||
81 | static unsigned long first_settimeofday = 1; | 83 | static unsigned long first_settimeofday = 1; |
82 | #endif | 84 | #endif |
83 | 85 | ||
86 | /* The decrementer counts down by 128 every 128ns on a 601. */ | ||
87 | #define DECREMENTER_COUNT_601 (1000000000 / HZ) | ||
88 | |||
84 | #define XSEC_PER_SEC (1024*1024) | 89 | #define XSEC_PER_SEC (1024*1024) |
85 | 90 | ||
91 | #ifdef CONFIG_PPC64 | ||
92 | #define SCALE_XSEC(xsec, max) (((xsec) * max) / XSEC_PER_SEC) | ||
93 | #else | ||
94 | /* compute ((xsec << 12) * max) >> 32 */ | ||
95 | #define SCALE_XSEC(xsec, max) mulhwu((xsec) << 12, max) | ||
96 | #endif | ||
97 | |||
86 | unsigned long tb_ticks_per_jiffy; | 98 | unsigned long tb_ticks_per_jiffy; |
87 | unsigned long tb_ticks_per_usec = 100; /* sane default */ | 99 | unsigned long tb_ticks_per_usec = 100; /* sane default */ |
88 | EXPORT_SYMBOL(tb_ticks_per_usec); | 100 | EXPORT_SYMBOL(tb_ticks_per_usec); |
89 | unsigned long tb_ticks_per_sec; | 101 | unsigned long tb_ticks_per_sec; |
90 | unsigned long tb_to_xs; | 102 | u64 tb_to_xs; |
91 | unsigned tb_to_us; | 103 | unsigned tb_to_us; |
92 | unsigned long processor_freq; | 104 | unsigned long processor_freq; |
93 | DEFINE_SPINLOCK(rtc_lock); | 105 | DEFINE_SPINLOCK(rtc_lock); |
94 | EXPORT_SYMBOL_GPL(rtc_lock); | 106 | EXPORT_SYMBOL_GPL(rtc_lock); |
95 | 107 | ||
96 | unsigned long tb_to_ns_scale; | 108 | u64 tb_to_ns_scale; |
97 | unsigned long tb_to_ns_shift; | 109 | unsigned tb_to_ns_shift; |
98 | 110 | ||
99 | struct gettimeofday_struct do_gtod; | 111 | struct gettimeofday_struct do_gtod; |
100 | 112 | ||
101 | extern unsigned long wall_jiffies; | 113 | extern unsigned long wall_jiffies; |
102 | extern int smp_tb_synchronized; | ||
103 | 114 | ||
104 | extern struct timezone sys_tz; | 115 | extern struct timezone sys_tz; |
116 | static long timezone_offset; | ||
105 | 117 | ||
106 | void ppc_adjtimex(void); | 118 | void ppc_adjtimex(void); |
107 | 119 | ||
@@ -110,6 +122,10 @@ static unsigned adjusting_time = 0; | |||
110 | unsigned long ppc_proc_freq; | 122 | unsigned long ppc_proc_freq; |
111 | unsigned long ppc_tb_freq; | 123 | unsigned long ppc_tb_freq; |
112 | 124 | ||
125 | #ifdef CONFIG_PPC32 /* XXX for now */ | ||
126 | #define boot_cpuid 0 | ||
127 | #endif | ||
128 | |||
113 | static __inline__ void timer_check_rtc(void) | 129 | static __inline__ void timer_check_rtc(void) |
114 | { | 130 | { |
115 | /* | 131 | /* |
@@ -129,30 +145,30 @@ static __inline__ void timer_check_rtc(void) | |||
129 | * seconds like on Intel to avoid problems with non UTC clocks. | 145 | * seconds like on Intel to avoid problems with non UTC clocks. |
130 | */ | 146 | */ |
131 | if (ntp_synced() && | 147 | if (ntp_synced() && |
132 | xtime.tv_sec - last_rtc_update >= 659 && | 148 | xtime.tv_sec - last_rtc_update >= 659 && |
133 | abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ && | 149 | abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ && |
134 | jiffies - wall_jiffies == 1) { | 150 | jiffies - wall_jiffies == 1) { |
135 | struct rtc_time tm; | 151 | struct rtc_time tm; |
136 | to_tm(xtime.tv_sec+1, &tm); | 152 | to_tm(xtime.tv_sec + 1 + timezone_offset, &tm); |
137 | tm.tm_year -= 1900; | 153 | tm.tm_year -= 1900; |
138 | tm.tm_mon -= 1; | 154 | tm.tm_mon -= 1; |
139 | if (ppc_md.set_rtc_time(&tm) == 0) | 155 | if (ppc_md.set_rtc_time(&tm) == 0) |
140 | last_rtc_update = xtime.tv_sec+1; | 156 | last_rtc_update = xtime.tv_sec + 1; |
141 | else | 157 | else |
142 | /* Try again one minute later */ | 158 | /* Try again one minute later */ |
143 | last_rtc_update += 60; | 159 | last_rtc_update += 60; |
144 | } | 160 | } |
145 | } | 161 | } |
146 | 162 | ||
147 | /* | 163 | /* |
148 | * This version of gettimeofday has microsecond resolution. | 164 | * This version of gettimeofday has microsecond resolution. |
149 | */ | 165 | */ |
150 | static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val) | 166 | static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val) |
151 | { | 167 | { |
152 | unsigned long sec, usec, tb_ticks; | 168 | unsigned long sec, usec; |
153 | unsigned long xsec, tb_xsec; | 169 | u64 tb_ticks, xsec; |
154 | struct gettimeofday_vars * temp_varp; | 170 | struct gettimeofday_vars *temp_varp; |
155 | unsigned long temp_tb_to_xs, temp_stamp_xsec; | 171 | u64 temp_tb_to_xs, temp_stamp_xsec; |
156 | 172 | ||
157 | /* | 173 | /* |
158 | * These calculations are faster (gets rid of divides) | 174 | * These calculations are faster (gets rid of divides) |
@@ -164,11 +180,10 @@ static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val) | |||
164 | tb_ticks = tb_val - temp_varp->tb_orig_stamp; | 180 | tb_ticks = tb_val - temp_varp->tb_orig_stamp; |
165 | temp_tb_to_xs = temp_varp->tb_to_xs; | 181 | temp_tb_to_xs = temp_varp->tb_to_xs; |
166 | temp_stamp_xsec = temp_varp->stamp_xsec; | 182 | temp_stamp_xsec = temp_varp->stamp_xsec; |
167 | tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs ); | 183 | xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs); |
168 | xsec = temp_stamp_xsec + tb_xsec; | ||
169 | sec = xsec / XSEC_PER_SEC; | 184 | sec = xsec / XSEC_PER_SEC; |
170 | xsec -= sec * XSEC_PER_SEC; | 185 | usec = (unsigned long)xsec & (XSEC_PER_SEC - 1); |
171 | usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC; | 186 | usec = SCALE_XSEC(usec, 1000000); |
172 | 187 | ||
173 | tv->tv_sec = sec; | 188 | tv->tv_sec = sec; |
174 | tv->tv_usec = usec; | 189 | tv->tv_usec = usec; |
@@ -185,6 +200,8 @@ EXPORT_SYMBOL(do_gettimeofday); | |||
185 | 200 | ||
186 | static inline void timer_sync_xtime(unsigned long cur_tb) | 201 | static inline void timer_sync_xtime(unsigned long cur_tb) |
187 | { | 202 | { |
203 | #ifdef CONFIG_PPC64 | ||
204 | /* why do we do this? */ | ||
188 | struct timeval my_tv; | 205 | struct timeval my_tv; |
189 | 206 | ||
190 | __do_gettimeofday(&my_tv, cur_tb); | 207 | __do_gettimeofday(&my_tv, cur_tb); |
@@ -193,47 +210,74 @@ static inline void timer_sync_xtime(unsigned long cur_tb) | |||
193 | xtime.tv_sec = my_tv.tv_sec; | 210 | xtime.tv_sec = my_tv.tv_sec; |
194 | xtime.tv_nsec = my_tv.tv_usec * 1000; | 211 | xtime.tv_nsec = my_tv.tv_usec * 1000; |
195 | } | 212 | } |
213 | #endif | ||
196 | } | 214 | } |
197 | 215 | ||
198 | /* | 216 | /* |
199 | * When the timebase - tb_orig_stamp gets too big, we do a manipulation | 217 | * There are two copies of tb_to_xs and stamp_xsec so that no |
200 | * between tb_orig_stamp and stamp_xsec. The goal here is to keep the | 218 | * lock is needed to access and use these values in |
201 | * difference tb - tb_orig_stamp small enough to always fit inside a | 219 | * do_gettimeofday. We alternate the copies and as long as a |
202 | * 32 bits number. This is a requirement of our fast 32 bits userland | 220 | * reasonable time elapses between changes, there will never |
203 | * implementation in the vdso. If we "miss" a call to this function | 221 | * be inconsistent values. ntpd has a minimum of one minute |
204 | * (interrupt latency, CPU locked in a spinlock, ...) and we end up | 222 | * between updates. |
205 | * with a too big difference, then the vdso will fallback to calling | ||
206 | * the syscall | ||
207 | */ | 223 | */ |
208 | static __inline__ void timer_recalc_offset(unsigned long cur_tb) | 224 | static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, |
225 | unsigned int new_tb_to_xs) | ||
209 | { | 226 | { |
210 | struct gettimeofday_vars * temp_varp; | ||
211 | unsigned temp_idx; | 227 | unsigned temp_idx; |
212 | unsigned long offset, new_stamp_xsec, new_tb_orig_stamp; | 228 | struct gettimeofday_vars *temp_varp; |
213 | |||
214 | if (((cur_tb - do_gtod.varp->tb_orig_stamp) & 0x80000000u) == 0) | ||
215 | return; | ||
216 | 229 | ||
217 | temp_idx = (do_gtod.var_idx == 0); | 230 | temp_idx = (do_gtod.var_idx == 0); |
218 | temp_varp = &do_gtod.vars[temp_idx]; | 231 | temp_varp = &do_gtod.vars[temp_idx]; |
219 | 232 | ||
220 | new_tb_orig_stamp = cur_tb; | 233 | temp_varp->tb_to_xs = new_tb_to_xs; |
221 | offset = new_tb_orig_stamp - do_gtod.varp->tb_orig_stamp; | 234 | temp_varp->tb_orig_stamp = new_tb_stamp; |
222 | new_stamp_xsec = do_gtod.varp->stamp_xsec + mulhdu(offset, do_gtod.varp->tb_to_xs); | ||
223 | |||
224 | temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs; | ||
225 | temp_varp->tb_orig_stamp = new_tb_orig_stamp; | ||
226 | temp_varp->stamp_xsec = new_stamp_xsec; | 235 | temp_varp->stamp_xsec = new_stamp_xsec; |
227 | smp_mb(); | 236 | smp_mb(); |
228 | do_gtod.varp = temp_varp; | 237 | do_gtod.varp = temp_varp; |
229 | do_gtod.var_idx = temp_idx; | 238 | do_gtod.var_idx = temp_idx; |
230 | 239 | ||
240 | #ifdef CONFIG_PPC64 | ||
241 | /* | ||
242 | * tb_update_count is used to allow the userspace gettimeofday code | ||
243 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
244 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
245 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
246 | * the two values of tb_update_count match and are even then the | ||
247 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
248 | * loops back and reads them again until this criteria is met. | ||
249 | */ | ||
231 | ++(systemcfg->tb_update_count); | 250 | ++(systemcfg->tb_update_count); |
232 | smp_wmb(); | 251 | smp_wmb(); |
233 | systemcfg->tb_orig_stamp = new_tb_orig_stamp; | 252 | systemcfg->tb_orig_stamp = new_tb_stamp; |
234 | systemcfg->stamp_xsec = new_stamp_xsec; | 253 | systemcfg->stamp_xsec = new_stamp_xsec; |
254 | systemcfg->tb_to_xs = new_tb_to_xs; | ||
235 | smp_wmb(); | 255 | smp_wmb(); |
236 | ++(systemcfg->tb_update_count); | 256 | ++(systemcfg->tb_update_count); |
257 | #endif | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * When the timebase - tb_orig_stamp gets too big, we do a manipulation | ||
262 | * between tb_orig_stamp and stamp_xsec. The goal here is to keep the | ||
263 | * difference tb - tb_orig_stamp small enough to always fit inside a | ||
264 | * 32 bits number. This is a requirement of our fast 32 bits userland | ||
265 | * implementation in the vdso. If we "miss" a call to this function | ||
266 | * (interrupt latency, CPU locked in a spinlock, ...) and we end up | ||
267 | * with a too big difference, then the vdso will fallback to calling | ||
268 | * the syscall | ||
269 | */ | ||
270 | static __inline__ void timer_recalc_offset(u64 cur_tb) | ||
271 | { | ||
272 | unsigned long offset; | ||
273 | u64 new_stamp_xsec; | ||
274 | |||
275 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; | ||
276 | if ((offset & 0x80000000u) == 0) | ||
277 | return; | ||
278 | new_stamp_xsec = do_gtod.varp->stamp_xsec | ||
279 | + mulhdu(offset, do_gtod.varp->tb_to_xs); | ||
280 | update_gtod(cur_tb, new_stamp_xsec, do_gtod.varp->tb_to_xs); | ||
237 | } | 281 | } |
238 | 282 | ||
239 | #ifdef CONFIG_SMP | 283 | #ifdef CONFIG_SMP |
@@ -313,7 +357,14 @@ static void iSeries_tb_recal(void) | |||
313 | * call will not be needed) | 357 | * call will not be needed) |
314 | */ | 358 | */ |
315 | 359 | ||
316 | unsigned long tb_last_stamp __cacheline_aligned_in_smp; | 360 | u64 tb_last_stamp __cacheline_aligned_in_smp; |
361 | |||
362 | /* | ||
363 | * Note that on ppc32 this only stores the bottom 32 bits of | ||
364 | * the timebase value, but that's enough to tell when a jiffy | ||
365 | * has passed. | ||
366 | */ | ||
367 | DEFINE_PER_CPU(unsigned long, last_jiffy); | ||
317 | 368 | ||
318 | /* | 369 | /* |
319 | * timer_interrupt - gets called when the decrementer overflows, | 370 | * timer_interrupt - gets called when the decrementer overflows, |
@@ -322,17 +373,30 @@ unsigned long tb_last_stamp __cacheline_aligned_in_smp; | |||
322 | void timer_interrupt(struct pt_regs * regs) | 373 | void timer_interrupt(struct pt_regs * regs) |
323 | { | 374 | { |
324 | int next_dec; | 375 | int next_dec; |
325 | unsigned long cur_tb; | 376 | int cpu = smp_processor_id(); |
326 | struct paca_struct *lpaca = get_paca(); | 377 | unsigned long ticks; |
327 | unsigned long cpu = smp_processor_id(); | 378 | |
379 | #ifdef CONFIG_PPC32 | ||
380 | if (atomic_read(&ppc_n_lost_interrupts) != 0) | ||
381 | do_IRQ(regs); | ||
382 | #endif | ||
328 | 383 | ||
329 | irq_enter(); | 384 | irq_enter(); |
330 | 385 | ||
331 | profile_tick(CPU_PROFILING, regs); | 386 | profile_tick(CPU_PROFILING, regs); |
332 | 387 | ||
333 | lpaca->lppaca.int_dword.fields.decr_int = 0; | 388 | #ifdef CONFIG_PPC_ISERIES |
389 | get_paca()->lppaca.int_dword.fields.decr_int = 0; | ||
390 | #endif | ||
391 | |||
392 | while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) | ||
393 | >= tb_ticks_per_jiffy) { | ||
394 | /* Update last_jiffy */ | ||
395 | per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy; | ||
396 | /* Handle RTCL overflow on 601 */ | ||
397 | if (__USE_RTC() && per_cpu(last_jiffy, cpu) >= 1000000000) | ||
398 | per_cpu(last_jiffy, cpu) -= 1000000000; | ||
334 | 399 | ||
335 | while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) { | ||
336 | /* | 400 | /* |
337 | * We cannot disable the decrementer, so in the period | 401 | * We cannot disable the decrementer, so in the period |
338 | * between this cpu's being marked offline in cpu_online_map | 402 | * between this cpu's being marked offline in cpu_online_map |
@@ -342,27 +406,26 @@ void timer_interrupt(struct pt_regs * regs) | |||
342 | */ | 406 | */ |
343 | if (!cpu_is_offline(cpu)) | 407 | if (!cpu_is_offline(cpu)) |
344 | update_process_times(user_mode(regs)); | 408 | update_process_times(user_mode(regs)); |
409 | |||
345 | /* | 410 | /* |
346 | * No need to check whether cpu is offline here; boot_cpuid | 411 | * No need to check whether cpu is offline here; boot_cpuid |
347 | * should have been fixed up by now. | 412 | * should have been fixed up by now. |
348 | */ | 413 | */ |
349 | if (cpu == boot_cpuid) { | 414 | if (cpu != boot_cpuid) |
350 | write_seqlock(&xtime_lock); | 415 | continue; |
351 | tb_last_stamp = lpaca->next_jiffy_update_tb; | 416 | |
352 | timer_recalc_offset(lpaca->next_jiffy_update_tb); | 417 | write_seqlock(&xtime_lock); |
353 | do_timer(regs); | 418 | tb_last_stamp += tb_ticks_per_jiffy; |
354 | timer_sync_xtime(lpaca->next_jiffy_update_tb); | 419 | timer_recalc_offset(tb_last_stamp); |
355 | timer_check_rtc(); | 420 | do_timer(regs); |
356 | write_sequnlock(&xtime_lock); | 421 | timer_sync_xtime(tb_last_stamp); |
357 | if ( adjusting_time && (time_adjust == 0) ) | 422 | timer_check_rtc(); |
358 | ppc_adjtimex(); | 423 | write_sequnlock(&xtime_lock); |
359 | } | 424 | if (adjusting_time && (time_adjust == 0)) |
360 | lpaca->next_jiffy_update_tb += tb_ticks_per_jiffy; | 425 | ppc_adjtimex(); |
361 | } | 426 | } |
362 | 427 | ||
363 | next_dec = lpaca->next_jiffy_update_tb - cur_tb; | 428 | next_dec = tb_ticks_per_jiffy - ticks; |
364 | if (next_dec > lpaca->default_decr) | ||
365 | next_dec = lpaca->default_decr; | ||
366 | set_dec(next_dec); | 429 | set_dec(next_dec); |
367 | 430 | ||
368 | #ifdef CONFIG_PPC_ISERIES | 431 | #ifdef CONFIG_PPC_ISERIES |
@@ -370,15 +433,47 @@ void timer_interrupt(struct pt_regs * regs) | |||
370 | process_hvlpevents(regs); | 433 | process_hvlpevents(regs); |
371 | #endif | 434 | #endif |
372 | 435 | ||
436 | #ifdef CONFIG_PPC64 | ||
373 | /* collect purr register values often, for accurate calculations */ | 437 | /* collect purr register values often, for accurate calculations */ |
374 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 438 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
375 | struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); | 439 | struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); |
376 | cu->current_tb = mfspr(SPRN_PURR); | 440 | cu->current_tb = mfspr(SPRN_PURR); |
377 | } | 441 | } |
442 | #endif | ||
378 | 443 | ||
379 | irq_exit(); | 444 | irq_exit(); |
380 | } | 445 | } |
381 | 446 | ||
447 | void wakeup_decrementer(void) | ||
448 | { | ||
449 | int i; | ||
450 | |||
451 | set_dec(tb_ticks_per_jiffy); | ||
452 | /* | ||
453 | * We don't expect this to be called on a machine with a 601, | ||
454 | * so using get_tbl is fine. | ||
455 | */ | ||
456 | tb_last_stamp = get_tb(); | ||
457 | for_each_cpu(i) | ||
458 | per_cpu(last_jiffy, i) = tb_last_stamp; | ||
459 | } | ||
460 | |||
461 | #ifdef CONFIG_SMPxxx | ||
462 | void __init smp_space_timers(unsigned int max_cpus) | ||
463 | { | ||
464 | int i; | ||
465 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | ||
466 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | ||
467 | |||
468 | for_each_cpu(i) { | ||
469 | if (i != boot_cpuid) { | ||
470 | previous_tb += offset; | ||
471 | per_cpu(last_jiffy, i) = previous_tb; | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | #endif | ||
476 | |||
382 | /* | 477 | /* |
383 | * Scheduler clock - returns current time in nanosec units. | 478 | * Scheduler clock - returns current time in nanosec units. |
384 | * | 479 | * |
@@ -396,23 +491,24 @@ int do_settimeofday(struct timespec *tv) | |||
396 | time_t wtm_sec, new_sec = tv->tv_sec; | 491 | time_t wtm_sec, new_sec = tv->tv_sec; |
397 | long wtm_nsec, new_nsec = tv->tv_nsec; | 492 | long wtm_nsec, new_nsec = tv->tv_nsec; |
398 | unsigned long flags; | 493 | unsigned long flags; |
399 | unsigned long delta_xsec; | ||
400 | long int tb_delta; | 494 | long int tb_delta; |
401 | unsigned long new_xsec; | 495 | u64 new_xsec; |
402 | 496 | ||
403 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 497 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) |
404 | return -EINVAL; | 498 | return -EINVAL; |
405 | 499 | ||
406 | write_seqlock_irqsave(&xtime_lock, flags); | 500 | write_seqlock_irqsave(&xtime_lock, flags); |
407 | /* Updating the RTC is not the job of this code. If the time is | 501 | |
408 | * stepped under NTP, the RTC will be update after STA_UNSYNC | 502 | /* |
409 | * is cleared. Tool like clock/hwclock either copy the RTC | 503 | * Updating the RTC is not the job of this code. If the time is |
504 | * stepped under NTP, the RTC will be updated after STA_UNSYNC | ||
505 | * is cleared. Tools like clock/hwclock either copy the RTC | ||
410 | * to the system time, in which case there is no point in writing | 506 | * to the system time, in which case there is no point in writing |
411 | * to the RTC again, or write to the RTC but then they don't call | 507 | * to the RTC again, or write to the RTC but then they don't call |
412 | * settimeofday to perform this operation. | 508 | * settimeofday to perform this operation. |
413 | */ | 509 | */ |
414 | #ifdef CONFIG_PPC_ISERIES | 510 | #ifdef CONFIG_PPC_ISERIES |
415 | if ( first_settimeofday ) { | 511 | if (first_settimeofday) { |
416 | iSeries_tb_recal(); | 512 | iSeries_tb_recal(); |
417 | first_settimeofday = 0; | 513 | first_settimeofday = 0; |
418 | } | 514 | } |
@@ -420,7 +516,7 @@ int do_settimeofday(struct timespec *tv) | |||
420 | tb_delta = tb_ticks_since(tb_last_stamp); | 516 | tb_delta = tb_ticks_since(tb_last_stamp); |
421 | tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; | 517 | tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; |
422 | 518 | ||
423 | new_nsec -= tb_delta / tb_ticks_per_usec / 1000; | 519 | new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta); |
424 | 520 | ||
425 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); | 521 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); |
426 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); | 522 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); |
@@ -435,28 +531,15 @@ int do_settimeofday(struct timespec *tv) | |||
435 | 531 | ||
436 | ntp_clear(); | 532 | ntp_clear(); |
437 | 533 | ||
438 | delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp), | 534 | new_xsec = (u64)new_nsec * XSEC_PER_SEC; |
439 | do_gtod.varp->tb_to_xs ); | 535 | do_div(new_xsec, NSEC_PER_SEC); |
440 | 536 | new_xsec += (u64)new_sec * XSEC_PER_SEC; | |
441 | new_xsec = (new_nsec * XSEC_PER_SEC) / NSEC_PER_SEC; | 537 | update_gtod(tb_last_stamp, new_xsec, do_gtod.varp->tb_to_xs); |
442 | new_xsec += new_sec * XSEC_PER_SEC; | ||
443 | if ( new_xsec > delta_xsec ) { | ||
444 | do_gtod.varp->stamp_xsec = new_xsec - delta_xsec; | ||
445 | systemcfg->stamp_xsec = new_xsec - delta_xsec; | ||
446 | } | ||
447 | else { | ||
448 | /* This is only for the case where the user is setting the time | ||
449 | * way back to a time such that the boot time would have been | ||
450 | * before 1970 ... eg. we booted ten days ago, and we are setting | ||
451 | * the time to Jan 5, 1970 */ | ||
452 | do_gtod.varp->stamp_xsec = new_xsec; | ||
453 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; | ||
454 | systemcfg->stamp_xsec = new_xsec; | ||
455 | systemcfg->tb_orig_stamp = tb_last_stamp; | ||
456 | } | ||
457 | 538 | ||
539 | #ifdef CONFIG_PPC64 | ||
458 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; | 540 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; |
459 | systemcfg->tz_dsttime = sys_tz.tz_dsttime; | 541 | systemcfg->tz_dsttime = sys_tz.tz_dsttime; |
542 | #endif | ||
460 | 543 | ||
461 | write_sequnlock_irqrestore(&xtime_lock, flags); | 544 | write_sequnlock_irqrestore(&xtime_lock, flags); |
462 | clock_was_set(); | 545 | clock_was_set(); |
@@ -520,21 +603,40 @@ void __init generic_calibrate_decr(void) | |||
520 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); | 603 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); |
521 | div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres); | 604 | div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres); |
522 | tb_to_xs = divres.result_low; | 605 | tb_to_xs = divres.result_low; |
523 | |||
524 | setup_default_decr(); | ||
525 | } | 606 | } |
526 | #endif | 607 | #endif |
527 | 608 | ||
609 | unsigned long get_boot_time(void) | ||
610 | { | ||
611 | struct rtc_time tm; | ||
612 | |||
613 | if (ppc_md.get_boot_time) | ||
614 | return ppc_md.get_boot_time(); | ||
615 | if (!ppc_md.get_rtc_time) | ||
616 | return 0; | ||
617 | ppc_md.get_rtc_time(&tm); | ||
618 | return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, | ||
619 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
620 | } | ||
621 | |||
622 | /* This function is only called on the boot processor */ | ||
528 | void __init time_init(void) | 623 | void __init time_init(void) |
529 | { | 624 | { |
530 | /* This function is only called on the boot processor */ | ||
531 | unsigned long flags; | 625 | unsigned long flags; |
532 | struct rtc_time tm; | 626 | unsigned long tm = 0; |
533 | struct div_result res; | 627 | struct div_result res; |
534 | unsigned long scale, shift; | 628 | u64 scale; |
629 | unsigned shift; | ||
630 | |||
631 | if (ppc_md.time_init != NULL) | ||
632 | timezone_offset = ppc_md.time_init(); | ||
535 | 633 | ||
536 | ppc_md.calibrate_decr(); | 634 | ppc_md.calibrate_decr(); |
537 | 635 | ||
636 | #ifdef CONFIG_PPC64 | ||
637 | get_paca()->default_decr = tb_ticks_per_jiffy; | ||
638 | #endif | ||
639 | |||
538 | /* | 640 | /* |
539 | * Compute scale factor for sched_clock. | 641 | * Compute scale factor for sched_clock. |
540 | * The calibrate_decr() function has set tb_ticks_per_sec, | 642 | * The calibrate_decr() function has set tb_ticks_per_sec, |
@@ -557,29 +659,37 @@ void __init time_init(void) | |||
557 | #ifdef CONFIG_PPC_ISERIES | 659 | #ifdef CONFIG_PPC_ISERIES |
558 | if (!piranha_simulator) | 660 | if (!piranha_simulator) |
559 | #endif | 661 | #endif |
560 | ppc_md.get_boot_time(&tm); | 662 | tm = get_boot_time(); |
561 | 663 | ||
562 | write_seqlock_irqsave(&xtime_lock, flags); | 664 | write_seqlock_irqsave(&xtime_lock, flags); |
563 | xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | 665 | xtime.tv_sec = tm; |
564 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 666 | xtime.tv_nsec = 0; |
565 | tb_last_stamp = get_tb(); | 667 | tb_last_stamp = get_tb(); |
566 | do_gtod.varp = &do_gtod.vars[0]; | 668 | do_gtod.varp = &do_gtod.vars[0]; |
567 | do_gtod.var_idx = 0; | 669 | do_gtod.var_idx = 0; |
568 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; | 670 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; |
569 | get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy; | 671 | __get_cpu_var(last_jiffy) = tb_last_stamp; |
570 | do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 672 | do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; |
571 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 673 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
572 | do_gtod.varp->tb_to_xs = tb_to_xs; | 674 | do_gtod.varp->tb_to_xs = tb_to_xs; |
573 | do_gtod.tb_to_us = tb_to_us; | 675 | do_gtod.tb_to_us = tb_to_us; |
676 | #ifdef CONFIG_PPC64 | ||
574 | systemcfg->tb_orig_stamp = tb_last_stamp; | 677 | systemcfg->tb_orig_stamp = tb_last_stamp; |
575 | systemcfg->tb_update_count = 0; | 678 | systemcfg->tb_update_count = 0; |
576 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 679 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; |
577 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 680 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; |
578 | systemcfg->tb_to_xs = tb_to_xs; | 681 | systemcfg->tb_to_xs = tb_to_xs; |
682 | #endif | ||
579 | 683 | ||
580 | time_freq = 0; | 684 | time_freq = 0; |
581 | 685 | ||
582 | xtime.tv_nsec = 0; | 686 | /* If platform provided a timezone (pmac), we correct the time */ |
687 | if (timezone_offset) { | ||
688 | sys_tz.tz_minuteswest = -timezone_offset / 60; | ||
689 | sys_tz.tz_dsttime = 0; | ||
690 | xtime.tv_sec -= timezone_offset; | ||
691 | } | ||
692 | |||
583 | last_rtc_update = xtime.tv_sec; | 693 | last_rtc_update = xtime.tv_sec; |
584 | set_normalized_timespec(&wall_to_monotonic, | 694 | set_normalized_timespec(&wall_to_monotonic, |
585 | -xtime.tv_sec, -xtime.tv_nsec); | 695 | -xtime.tv_sec, -xtime.tv_nsec); |
@@ -602,25 +712,28 @@ void __init time_init(void) | |||
602 | 712 | ||
603 | void ppc_adjtimex(void) | 713 | void ppc_adjtimex(void) |
604 | { | 714 | { |
605 | unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec; | 715 | #ifdef CONFIG_PPC64 |
716 | unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, | ||
717 | new_tb_to_xs, new_xsec, new_stamp_xsec; | ||
606 | unsigned long tb_ticks_per_sec_delta; | 718 | unsigned long tb_ticks_per_sec_delta; |
607 | long delta_freq, ltemp; | 719 | long delta_freq, ltemp; |
608 | struct div_result divres; | 720 | struct div_result divres; |
609 | unsigned long flags; | 721 | unsigned long flags; |
610 | struct gettimeofday_vars * temp_varp; | ||
611 | unsigned temp_idx; | ||
612 | long singleshot_ppm = 0; | 722 | long singleshot_ppm = 0; |
613 | 723 | ||
614 | /* Compute parts per million frequency adjustment to accomplish the time adjustment | 724 | /* |
615 | implied by time_offset to be applied over the elapsed time indicated by time_constant. | 725 | * Compute parts per million frequency adjustment to |
616 | Use SHIFT_USEC to get it into the same units as time_freq. */ | 726 | * accomplish the time adjustment implied by time_offset to be |
727 | * applied over the elapsed time indicated by time_constant. | ||
728 | * Use SHIFT_USEC to get it into the same units as | ||
729 | * time_freq. | ||
730 | */ | ||
617 | if ( time_offset < 0 ) { | 731 | if ( time_offset < 0 ) { |
618 | ltemp = -time_offset; | 732 | ltemp = -time_offset; |
619 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; | 733 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; |
620 | ltemp >>= SHIFT_KG + time_constant; | 734 | ltemp >>= SHIFT_KG + time_constant; |
621 | ltemp = -ltemp; | 735 | ltemp = -ltemp; |
622 | } | 736 | } else { |
623 | else { | ||
624 | ltemp = time_offset; | 737 | ltemp = time_offset; |
625 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; | 738 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; |
626 | ltemp >>= SHIFT_KG + time_constant; | 739 | ltemp >>= SHIFT_KG + time_constant; |
@@ -637,7 +750,10 @@ void ppc_adjtimex(void) | |||
637 | 750 | ||
638 | adjusting_time = 1; | 751 | adjusting_time = 1; |
639 | 752 | ||
640 | /* Compute parts per million frequency adjustment to match time_adjust */ | 753 | /* |
754 | * Compute parts per million frequency adjustment | ||
755 | * to match time_adjust | ||
756 | */ | ||
641 | singleshot_ppm = tickadj * HZ; | 757 | singleshot_ppm = tickadj * HZ; |
642 | /* | 758 | /* |
643 | * The adjustment should be tickadj*HZ to match the code in | 759 | * The adjustment should be tickadj*HZ to match the code in |
@@ -645,7 +761,7 @@ void ppc_adjtimex(void) | |||
645 | * large. 3/4 of tickadj*HZ seems about right | 761 | * large. 3/4 of tickadj*HZ seems about right |
646 | */ | 762 | */ |
647 | singleshot_ppm -= singleshot_ppm / 4; | 763 | singleshot_ppm -= singleshot_ppm / 4; |
648 | /* Use SHIFT_USEC to get it into the same units as time_freq */ | 764 | /* Use SHIFT_USEC to get it into the same units as time_freq */ |
649 | singleshot_ppm <<= SHIFT_USEC; | 765 | singleshot_ppm <<= SHIFT_USEC; |
650 | if ( time_adjust < 0 ) | 766 | if ( time_adjust < 0 ) |
651 | singleshot_ppm = -singleshot_ppm; | 767 | singleshot_ppm = -singleshot_ppm; |
@@ -661,7 +777,10 @@ void ppc_adjtimex(void) | |||
661 | /* Add up all of the frequency adjustments */ | 777 | /* Add up all of the frequency adjustments */ |
662 | delta_freq = time_freq + ltemp + singleshot_ppm; | 778 | delta_freq = time_freq + ltemp + singleshot_ppm; |
663 | 779 | ||
664 | /* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */ | 780 | /* |
781 | * Compute a new value for tb_ticks_per_sec based on | ||
782 | * the frequency adjustment | ||
783 | */ | ||
665 | den = 1000000 * (1 << (SHIFT_USEC - 8)); | 784 | den = 1000000 * (1 << (SHIFT_USEC - 8)); |
666 | if ( delta_freq < 0 ) { | 785 | if ( delta_freq < 0 ) { |
667 | tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den; | 786 | tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den; |
@@ -676,61 +795,37 @@ void ppc_adjtimex(void) | |||
676 | printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm); | 795 | printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm); |
677 | printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec); | 796 | printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec); |
678 | #endif | 797 | #endif |
679 | 798 | ||
680 | /* Compute a new value of tb_to_xs (used to convert tb to microseconds and a new value of | 799 | /* |
681 | stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp. This | 800 | * Compute a new value of tb_to_xs (used to convert tb to |
682 | new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs) | 801 | * microseconds) and a new value of stamp_xsec which is the |
683 | which guarantees that the current time remains the same */ | 802 | * time (in 1/2^20 second units) corresponding to |
803 | * tb_orig_stamp. This new value of stamp_xsec compensates | ||
804 | * for the change in frequency (implied by the new tb_to_xs) | ||
805 | * which guarantees that the current time remains the same. | ||
806 | */ | ||
684 | write_seqlock_irqsave( &xtime_lock, flags ); | 807 | write_seqlock_irqsave( &xtime_lock, flags ); |
685 | tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp; | 808 | tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp; |
686 | div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres ); | 809 | div128_by_32(1024*1024, 0, new_tb_ticks_per_sec, &divres); |
687 | new_tb_to_xs = divres.result_low; | 810 | new_tb_to_xs = divres.result_low; |
688 | new_xsec = mulhdu( tb_ticks, new_tb_to_xs ); | 811 | new_xsec = mulhdu(tb_ticks, new_tb_to_xs); |
689 | 812 | ||
690 | old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs ); | 813 | old_xsec = mulhdu(tb_ticks, do_gtod.varp->tb_to_xs); |
691 | new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec; | 814 | new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec; |
692 | 815 | ||
693 | /* There are two copies of tb_to_xs and stamp_xsec so that no lock is needed to access and use these | 816 | update_gtod(do_gtod.varp->tb_orig_stamp, new_stamp_xsec, new_tb_to_xs); |
694 | values in do_gettimeofday. We alternate the copies and as long as a reasonable time elapses between | ||
695 | changes, there will never be inconsistent values. ntpd has a minimum of one minute between updates */ | ||
696 | |||
697 | temp_idx = (do_gtod.var_idx == 0); | ||
698 | temp_varp = &do_gtod.vars[temp_idx]; | ||
699 | |||
700 | temp_varp->tb_to_xs = new_tb_to_xs; | ||
701 | temp_varp->stamp_xsec = new_stamp_xsec; | ||
702 | temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp; | ||
703 | smp_mb(); | ||
704 | do_gtod.varp = temp_varp; | ||
705 | do_gtod.var_idx = temp_idx; | ||
706 | |||
707 | /* | ||
708 | * tb_update_count is used to allow the problem state gettimeofday code | ||
709 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
710 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
711 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
712 | * the two values of tb_update_count match and are even then the | ||
713 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
714 | * loops back and reads them again until this criteria is met. | ||
715 | */ | ||
716 | ++(systemcfg->tb_update_count); | ||
717 | smp_wmb(); | ||
718 | systemcfg->tb_to_xs = new_tb_to_xs; | ||
719 | systemcfg->stamp_xsec = new_stamp_xsec; | ||
720 | smp_wmb(); | ||
721 | ++(systemcfg->tb_update_count); | ||
722 | 817 | ||
723 | write_sequnlock_irqrestore( &xtime_lock, flags ); | 818 | write_sequnlock_irqrestore( &xtime_lock, flags ); |
724 | 819 | #endif /* CONFIG_PPC64 */ | |
725 | } | 820 | } |
726 | 821 | ||
727 | 822 | ||
728 | #define TICK_SIZE tick | ||
729 | #define FEBRUARY 2 | 823 | #define FEBRUARY 2 |
730 | #define STARTOFTIME 1970 | 824 | #define STARTOFTIME 1970 |
731 | #define SECDAY 86400L | 825 | #define SECDAY 86400L |
732 | #define SECYR (SECDAY * 365) | 826 | #define SECYR (SECDAY * 365) |
733 | #define leapyear(year) ((year) % 4 == 0) | 827 | #define leapyear(year) ((year) % 4 == 0 && \ |
828 | ((year) % 100 != 0 || (year) % 400 == 0)) | ||
734 | #define days_in_year(a) (leapyear(a) ? 366 : 365) | 829 | #define days_in_year(a) (leapyear(a) ? 366 : 365) |
735 | #define days_in_month(a) (month_days[(a) - 1]) | 830 | #define days_in_month(a) (month_days[(a) - 1]) |
736 | 831 | ||
@@ -748,37 +843,25 @@ void GregorianDay(struct rtc_time * tm) | |||
748 | int day; | 843 | int day; |
749 | int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | 844 | int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; |
750 | 845 | ||
751 | lastYear=tm->tm_year-1; | 846 | lastYear = tm->tm_year - 1; |
752 | 847 | ||
753 | /* | 848 | /* |
754 | * Number of leap corrections to apply up to end of last year | 849 | * Number of leap corrections to apply up to end of last year |
755 | */ | 850 | */ |
756 | leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; | 851 | leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400; |
757 | 852 | ||
758 | /* | 853 | /* |
759 | * This year is a leap year if it is divisible by 4 except when it is | 854 | * This year is a leap year if it is divisible by 4 except when it is |
760 | * divisible by 100 unless it is divisible by 400 | 855 | * divisible by 100 unless it is divisible by 400 |
761 | * | 856 | * |
762 | * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be | 857 | * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was |
763 | */ | 858 | */ |
764 | if((tm->tm_year%4==0) && | 859 | day = tm->tm_mon > 2 && leapyear(tm->tm_year); |
765 | ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && | ||
766 | (tm->tm_mon>2)) | ||
767 | { | ||
768 | /* | ||
769 | * We are past Feb. 29 in a leap year | ||
770 | */ | ||
771 | day=1; | ||
772 | } | ||
773 | else | ||
774 | { | ||
775 | day=0; | ||
776 | } | ||
777 | 860 | ||
778 | day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + | 861 | day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + |
779 | tm->tm_mday; | 862 | tm->tm_mday; |
780 | 863 | ||
781 | tm->tm_wday=day%7; | 864 | tm->tm_wday = day % 7; |
782 | } | 865 | } |
783 | 866 | ||
784 | void to_tm(int tim, struct rtc_time * tm) | 867 | void to_tm(int tim, struct rtc_time * tm) |
@@ -824,14 +907,16 @@ void to_tm(int tim, struct rtc_time * tm) | |||
824 | * oscillators and the precision with which the timebase frequency | 907 | * oscillators and the precision with which the timebase frequency |
825 | * is measured but does not harm. | 908 | * is measured but does not harm. |
826 | */ | 909 | */ |
827 | unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) { | 910 | unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) |
911 | { | ||
828 | unsigned mlt=0, tmp, err; | 912 | unsigned mlt=0, tmp, err; |
829 | /* No concern for performance, it's done once: use a stupid | 913 | /* No concern for performance, it's done once: use a stupid |
830 | * but safe and compact method to find the multiplier. | 914 | * but safe and compact method to find the multiplier. |
831 | */ | 915 | */ |
832 | 916 | ||
833 | for (tmp = 1U<<31; tmp != 0; tmp >>= 1) { | 917 | for (tmp = 1U<<31; tmp != 0; tmp >>= 1) { |
834 | if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp; | 918 | if (mulhwu(inscale, mlt|tmp) < outscale) |
919 | mlt |= tmp; | ||
835 | } | 920 | } |
836 | 921 | ||
837 | /* We might still be off by 1 for the best approximation. | 922 | /* We might still be off by 1 for the best approximation. |
@@ -841,39 +926,53 @@ unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) { | |||
841 | * some might have been forgotten in the test however. | 926 | * some might have been forgotten in the test however. |
842 | */ | 927 | */ |
843 | 928 | ||
844 | err = inscale*(mlt+1); | 929 | err = inscale * (mlt+1); |
845 | if (err <= inscale/2) mlt++; | 930 | if (err <= inscale/2) |
931 | mlt++; | ||
846 | return mlt; | 932 | return mlt; |
847 | } | 933 | } |
848 | 934 | ||
849 | /* | 935 | /* |
850 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit | 936 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit |
851 | * result. | 937 | * result. |
852 | */ | 938 | */ |
853 | 939 | void div128_by_32(u64 dividend_high, u64 dividend_low, | |
854 | void div128_by_32( unsigned long dividend_high, unsigned long dividend_low, | 940 | unsigned divisor, struct div_result *dr) |
855 | unsigned divisor, struct div_result *dr ) | ||
856 | { | 941 | { |
857 | unsigned long a,b,c,d, w,x,y,z, ra,rb,rc; | 942 | unsigned long a, b, c, d; |
943 | unsigned long w, x, y, z; | ||
944 | u64 ra, rb, rc; | ||
858 | 945 | ||
859 | a = dividend_high >> 32; | 946 | a = dividend_high >> 32; |
860 | b = dividend_high & 0xffffffff; | 947 | b = dividend_high & 0xffffffff; |
861 | c = dividend_low >> 32; | 948 | c = dividend_low >> 32; |
862 | d = dividend_low & 0xffffffff; | 949 | d = dividend_low & 0xffffffff; |
863 | 950 | ||
864 | w = a/divisor; | 951 | w = a / divisor; |
865 | ra = (a - (w * divisor)) << 32; | 952 | ra = ((u64)(a - (w * divisor)) << 32) + b; |
953 | |||
954 | #ifdef CONFIG_PPC64 | ||
955 | x = ra / divisor; | ||
956 | rb = ((ra - (x * divisor)) << 32) + c; | ||
866 | 957 | ||
867 | x = (ra + b)/divisor; | 958 | y = rb / divisor; |
868 | rb = ((ra + b) - (x * divisor)) << 32; | 959 | rc = ((rb - (y * divisor)) << 32) + d; |
869 | 960 | ||
870 | y = (rb + c)/divisor; | 961 | z = rc / divisor; |
871 | rc = ((rb + b) - (y * divisor)) << 32; | 962 | #else |
963 | /* for 32-bit, use do_div from div64.h */ | ||
964 | rb = ((u64) do_div(ra, divisor) << 32) + c; | ||
965 | x = ra; | ||
872 | 966 | ||
873 | z = (rc + d)/divisor; | 967 | rc = ((u64) do_div(rb, divisor) << 32) + d; |
968 | y = rb; | ||
969 | |||
970 | do_div(rc, divisor); | ||
971 | z = rc; | ||
972 | #endif | ||
874 | 973 | ||
875 | dr->result_high = (w << 32) + x; | 974 | dr->result_high = ((u64)w << 32) + x; |
876 | dr->result_low = (y << 32) + z; | 975 | dr->result_low = ((u64)y << 32) + z; |
877 | 976 | ||
878 | } | 977 | } |
879 | 978 | ||
diff --git a/arch/powerpc/platforms/powermac/cpufreq.c b/arch/powerpc/platforms/powermac/cpufreq.c index bcd9224f3f90..c47f8b69725c 100644 --- a/arch/powerpc/platforms/powermac/cpufreq.c +++ b/arch/powerpc/platforms/powermac/cpufreq.c | |||
@@ -110,15 +110,6 @@ static inline void local_delay(unsigned long ms) | |||
110 | msleep(ms); | 110 | msleep(ms); |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline void wakeup_decrementer(void) | ||
114 | { | ||
115 | set_dec(tb_ticks_per_jiffy); | ||
116 | /* No currently-supported powerbook has a 601, | ||
117 | * so use get_tbl, not native | ||
118 | */ | ||
119 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
120 | } | ||
121 | |||
122 | #ifdef DEBUG_FREQ | 113 | #ifdef DEBUG_FREQ |
123 | static inline void debug_calc_bogomips(void) | 114 | static inline void debug_calc_bogomips(void) |
124 | { | 115 | { |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 3ee6d8aa14c4..eb9969b52f96 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * | 6 | * |
7 | * Paul Mackerras August 1996. | 7 | * Paul Mackerras August 1996. |
8 | * Copyright (C) 1996 Paul Mackerras. | 8 | * Copyright (C) 1996 Paul Mackerras. |
9 | * Copyright (C) 2003-2005 Benjamin Herrenschmidt. | ||
10 | * | ||
9 | */ | 11 | */ |
10 | #include <linux/config.h> | 12 | #include <linux/config.h> |
11 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
@@ -19,7 +21,9 @@ | |||
19 | #include <linux/adb.h> | 21 | #include <linux/adb.h> |
20 | #include <linux/cuda.h> | 22 | #include <linux/cuda.h> |
21 | #include <linux/pmu.h> | 23 | #include <linux/pmu.h> |
24 | #include <linux/interrupt.h> | ||
22 | #include <linux/hardirq.h> | 25 | #include <linux/hardirq.h> |
26 | #include <linux/rtc.h> | ||
23 | 27 | ||
24 | #include <asm/sections.h> | 28 | #include <asm/sections.h> |
25 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
@@ -30,6 +34,14 @@ | |||
30 | #include <asm/time.h> | 34 | #include <asm/time.h> |
31 | #include <asm/nvram.h> | 35 | #include <asm/nvram.h> |
32 | 36 | ||
37 | #undef DEBUG | ||
38 | |||
39 | #ifdef DEBUG | ||
40 | #define DBG(x...) printk(x) | ||
41 | #else | ||
42 | #define DBG(x...) | ||
43 | #endif | ||
44 | |||
33 | /* Apparently the RTC stores seconds since 1 Jan 1904 */ | 45 | /* Apparently the RTC stores seconds since 1 Jan 1904 */ |
34 | #define RTC_OFFSET 2082844800 | 46 | #define RTC_OFFSET 2082844800 |
35 | 47 | ||
@@ -54,10 +66,7 @@ | |||
54 | /* Bits in IFR and IER */ | 66 | /* Bits in IFR and IER */ |
55 | #define T1_INT 0x40 /* Timer 1 interrupt */ | 67 | #define T1_INT 0x40 /* Timer 1 interrupt */ |
56 | 68 | ||
57 | extern struct timezone sys_tz; | 69 | long __init pmac_time_init(void) |
58 | |||
59 | long __init | ||
60 | pmac_time_init(void) | ||
61 | { | 70 | { |
62 | #ifdef CONFIG_NVRAM | 71 | #ifdef CONFIG_NVRAM |
63 | s32 delta = 0; | 72 | s32 delta = 0; |
@@ -210,7 +219,7 @@ via_calibrate_decr(void) | |||
210 | tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); | 219 | tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); |
211 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); | 220 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); |
212 | 221 | ||
213 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", | 222 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %lu (%u ticks)\n", |
214 | tb_ticks_per_jiffy, dstart - dend); | 223 | tb_ticks_per_jiffy, dstart - dend); |
215 | 224 | ||
216 | iounmap(via); | 225 | iounmap(via); |
@@ -228,6 +237,7 @@ time_sleep_notify(struct pmu_sleep_notifier *self, int when) | |||
228 | static unsigned long time_diff; | 237 | static unsigned long time_diff; |
229 | unsigned long flags; | 238 | unsigned long flags; |
230 | unsigned long seq; | 239 | unsigned long seq; |
240 | struct timespec tv; | ||
231 | 241 | ||
232 | switch (when) { | 242 | switch (when) { |
233 | case PBOOK_SLEEP_NOW: | 243 | case PBOOK_SLEEP_NOW: |
@@ -237,11 +247,9 @@ time_sleep_notify(struct pmu_sleep_notifier *self, int when) | |||
237 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | 247 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); |
238 | break; | 248 | break; |
239 | case PBOOK_WAKE: | 249 | case PBOOK_WAKE: |
240 | write_seqlock_irqsave(&xtime_lock, flags); | 250 | tv.tv_sec = pmac_get_boot_time() + time_diff; |
241 | xtime.tv_sec = pmac_get_rtc_time() + time_diff; | 251 | tv.tv_nsec = 0; |
242 | xtime.tv_nsec = 0; | 252 | do_settimeofday(&tv); |
243 | last_rtc_update = xtime.tv_sec; | ||
244 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
245 | break; | 253 | break; |
246 | } | 254 | } |
247 | return PBOOK_SLEEP_OK; | 255 | return PBOOK_SLEEP_OK; |
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 5a742c7b0509..ccbc442c9ed3 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile | |||
@@ -37,7 +37,7 @@ endif | |||
37 | # These are here while we do the architecture merge | 37 | # These are here while we do the architecture merge |
38 | 38 | ||
39 | else | 39 | else |
40 | obj-y := irq.o idle.o time.o \ | 40 | obj-y := irq.o idle.o \ |
41 | align.o perfmon.o | 41 | align.o perfmon.o |
42 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | 42 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o |
43 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 43 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o |
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 22d7fd1e0aea..76f44ce4772e 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c | |||
@@ -121,6 +121,15 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
121 | EXPORT_SYMBOL(profile_pc); | 121 | EXPORT_SYMBOL(profile_pc); |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | void wakeup_decrementer(void) | ||
125 | { | ||
126 | set_dec(tb_ticks_per_jiffy); | ||
127 | /* No currently-supported powerbook has a 601, | ||
128 | * so use get_tbl, not native | ||
129 | */ | ||
130 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
131 | } | ||
132 | |||
124 | /* | 133 | /* |
125 | * timer_interrupt - gets called when the decrementer overflows, | 134 | * timer_interrupt - gets called when the decrementer overflows, |
126 | * with interrupts disabled. | 135 | * with interrupts disabled. |
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 8c9012f0ce6a..18f477fa1df2 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -12,7 +12,7 @@ obj-y := setup.o entry.o misc.o prom.o | |||
12 | endif | 12 | endif |
13 | 13 | ||
14 | obj-y += irq.o idle.o dma.o \ | 14 | obj-y += irq.o idle.o dma.o \ |
15 | time.o signal.o \ | 15 | signal.o \ |
16 | align.o bitops.o pacaData.o \ | 16 | align.o bitops.o pacaData.o \ |
17 | udbg.o ioctl32.o \ | 17 | udbg.o ioctl32.o \ |
18 | rtc.o \ | 18 | rtc.o \ |
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c index c89bfefbbecd..56f335115916 100644 --- a/arch/ppc64/kernel/pmac_time.c +++ b/arch/ppc64/kernel/pmac_time.c | |||
@@ -180,7 +180,5 @@ void __init pmac_calibrate_decr(void) | |||
180 | if (fp == 0) | 180 | if (fp == 0) |
181 | panic("can't get cpu processor frequency"); | 181 | panic("can't get cpu processor frequency"); |
182 | ppc_proc_freq = *fp; | 182 | ppc_proc_freq = *fp; |
183 | |||
184 | setup_default_decr(); | ||
185 | } | 183 | } |
186 | 184 | ||
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index 776b55b45e1b..3e6c1547b718 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c | |||
@@ -1083,15 +1083,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg) | |||
1083 | printk("[terminate]%04x %s\n", src, msg); | 1083 | printk("[terminate]%04x %s\n", src, msg); |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | /* This should only be called on processor 0 during calibrate decr */ | ||
1087 | void __init setup_default_decr(void) | ||
1088 | { | ||
1089 | struct paca_struct *lpaca = get_paca(); | ||
1090 | |||
1091 | lpaca->default_decr = tb_ticks_per_jiffy; | ||
1092 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; | ||
1093 | } | ||
1094 | |||
1095 | #ifndef CONFIG_PPC_ISERIES | 1086 | #ifndef CONFIG_PPC_ISERIES |
1096 | /* | 1087 | /* |
1097 | * This function can be used by platforms to "find" legacy serial ports. | 1088 | * This function can be used by platforms to "find" legacy serial ports. |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 503461884528..91920a1140fa 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -588,17 +588,6 @@ pmu_get_model(void) | |||
588 | return pmu_kind; | 588 | return pmu_kind; |
589 | } | 589 | } |
590 | 590 | ||
591 | #ifndef CONFIG_PPC64 | ||
592 | static inline void wakeup_decrementer(void) | ||
593 | { | ||
594 | set_dec(tb_ticks_per_jiffy); | ||
595 | /* No currently-supported powerbook has a 601, | ||
596 | * so use get_tbl, not native | ||
597 | */ | ||
598 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
599 | } | ||
600 | #endif | ||
601 | |||
602 | static void pmu_set_server_mode(int server_mode) | 591 | static void pmu_set_server_mode(int server_mode) |
603 | { | 592 | { |
604 | struct adb_request req; | 593 | struct adb_request req; |
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 980393a16be2..07c2b3fc4c66 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h | |||
@@ -496,5 +496,7 @@ extern int call_handle_IRQ_event(int irq, struct pt_regs *regs, | |||
496 | 496 | ||
497 | #endif /* CONFIG_IRQSTACKS */ | 497 | #endif /* CONFIG_IRQSTACKS */ |
498 | 498 | ||
499 | extern void do_IRQ(struct pt_regs *regs); | ||
500 | |||
499 | #endif /* _ASM_IRQ_H */ | 501 | #endif /* _ASM_IRQ_H */ |
500 | #endif /* __KERNEL__ */ | 502 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/rtc.h b/include/asm-powerpc/rtc.h new file mode 100644 index 000000000000..d38f2a077db2 --- /dev/null +++ b/include/asm-powerpc/rtc.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Real-time clock definitions and interfaces | ||
3 | * | ||
4 | * Author: Tom Rini <trini@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | * Based on: | ||
12 | * include/asm-m68k/rtc.h | ||
13 | * | ||
14 | * Copyright Richard Zidlicky | ||
15 | * implementation details for genrtc/q40rtc driver | ||
16 | * | ||
17 | * And the old drivers/macintosh/rtc.c which was heavily based on: | ||
18 | * Linux/SPARC Real Time Clock Driver | ||
19 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
20 | * | ||
21 | * With additional work by Paul Mackerras and Franz Sirl. | ||
22 | */ | ||
23 | |||
24 | #ifndef __ASM_POWERPC_RTC_H__ | ||
25 | #define __ASM_POWERPC_RTC_H__ | ||
26 | |||
27 | #ifdef __KERNEL__ | ||
28 | |||
29 | #include <linux/rtc.h> | ||
30 | |||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/time.h> | ||
33 | |||
34 | #define RTC_PIE 0x40 /* periodic interrupt enable */ | ||
35 | #define RTC_AIE 0x20 /* alarm interrupt enable */ | ||
36 | #define RTC_UIE 0x10 /* update-finished interrupt enable */ | ||
37 | |||
38 | /* some dummy definitions */ | ||
39 | #define RTC_BATT_BAD 0x100 /* battery bad */ | ||
40 | #define RTC_SQWE 0x08 /* enable square-wave output */ | ||
41 | #define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | ||
42 | #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | ||
43 | #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | ||
44 | |||
45 | static inline unsigned int get_rtc_time(struct rtc_time *time) | ||
46 | { | ||
47 | if (ppc_md.get_rtc_time) | ||
48 | ppc_md.get_rtc_time(time); | ||
49 | return RTC_24H; | ||
50 | } | ||
51 | |||
52 | /* Set the current date and time in the real time clock. */ | ||
53 | static inline int set_rtc_time(struct rtc_time *time) | ||
54 | { | ||
55 | if (ppc_md.get_rtc_time) { | ||
56 | ppc_md.set_rtc_time(time); | ||
57 | return 0; | ||
58 | } | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | static inline unsigned int get_rtc_ss(void) | ||
63 | { | ||
64 | struct rtc_time h; | ||
65 | |||
66 | get_rtc_time(&h); | ||
67 | return h.tm_sec; | ||
68 | } | ||
69 | |||
70 | static inline int get_rtc_pll(struct rtc_pll_info *pll) | ||
71 | { | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | static inline int set_rtc_pll(struct rtc_pll_info *pll) | ||
75 | { | ||
76 | return -EINVAL; | ||
77 | } | ||
78 | |||
79 | #endif /* __KERNEL__ */ | ||
80 | #endif /* __ASM_POWERPC_RTC_H__ */ | ||
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h new file mode 100644 index 000000000000..4eecc38f7092 --- /dev/null +++ b/include/asm-powerpc/time.h | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Common time prototypes and such for all ppc machines. | ||
3 | * | ||
4 | * Written by Cort Dougan (cort@cs.nmt.edu) to merge | ||
5 | * Paul Mackerras' version and mine for PReP and Pmac. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef __POWERPC_TIME_H | ||
14 | #define __POWERPC_TIME_H | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/percpu.h> | ||
20 | |||
21 | #include <asm/processor.h> | ||
22 | #ifdef CONFIG_PPC64 | ||
23 | #include <asm/paca.h> | ||
24 | #include <asm/iSeries/HvCall.h> | ||
25 | #endif | ||
26 | |||
27 | /* time.c */ | ||
28 | extern unsigned long tb_ticks_per_jiffy; | ||
29 | extern unsigned long tb_ticks_per_usec; | ||
30 | extern unsigned long tb_ticks_per_sec; | ||
31 | extern u64 tb_to_xs; | ||
32 | extern unsigned tb_to_us; | ||
33 | extern u64 tb_last_stamp; | ||
34 | |||
35 | DECLARE_PER_CPU(unsigned long, last_jiffy); | ||
36 | |||
37 | struct rtc_time; | ||
38 | extern void to_tm(int tim, struct rtc_time * tm); | ||
39 | extern time_t last_rtc_update; | ||
40 | |||
41 | extern void generic_calibrate_decr(void); | ||
42 | extern void wakeup_decrementer(void); | ||
43 | |||
44 | /* Some sane defaults: 125 MHz timebase, 1GHz processor */ | ||
45 | extern unsigned long ppc_proc_freq; | ||
46 | #define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8) | ||
47 | extern unsigned long ppc_tb_freq; | ||
48 | #define DEFAULT_TB_FREQ 125000000UL | ||
49 | |||
50 | /* | ||
51 | * By putting all of this stuff into a single struct we | ||
52 | * reduce the number of cache lines touched by do_gettimeofday. | ||
53 | * Both by collecting all of the data in one cache line and | ||
54 | * by touching only one TOC entry on ppc64. | ||
55 | */ | ||
56 | struct gettimeofday_vars { | ||
57 | u64 tb_to_xs; | ||
58 | u64 stamp_xsec; | ||
59 | u64 tb_orig_stamp; | ||
60 | }; | ||
61 | |||
62 | struct gettimeofday_struct { | ||
63 | unsigned long tb_ticks_per_sec; | ||
64 | struct gettimeofday_vars vars[2]; | ||
65 | struct gettimeofday_vars * volatile varp; | ||
66 | unsigned var_idx; | ||
67 | unsigned tb_to_us; | ||
68 | }; | ||
69 | |||
70 | struct div_result { | ||
71 | u64 result_high; | ||
72 | u64 result_low; | ||
73 | }; | ||
74 | |||
75 | /* Accessor functions for the timebase (RTC on 601) registers. */ | ||
76 | /* If one day CONFIG_POWER is added just define __USE_RTC as 1 */ | ||
77 | #ifdef CONFIG_6xx | ||
78 | #define __USE_RTC() cpu_has_feature(CPU_FTR_USE_TB) | ||
79 | #else | ||
80 | #define __USE_RTC() 0 | ||
81 | #endif | ||
82 | |||
83 | /* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */ | ||
84 | static inline unsigned long get_tbl(void) | ||
85 | { | ||
86 | unsigned long tbl; | ||
87 | |||
88 | #if defined(CONFIG_403GCX) | ||
89 | asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); | ||
90 | #else | ||
91 | asm volatile("mftb %0" : "=r" (tbl)); | ||
92 | #endif | ||
93 | return tbl; | ||
94 | } | ||
95 | |||
96 | static inline unsigned int get_tbu(void) | ||
97 | { | ||
98 | unsigned int tbu; | ||
99 | |||
100 | #if defined(CONFIG_403GCX) | ||
101 | asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); | ||
102 | #else | ||
103 | asm volatile("mftbu %0" : "=r" (tbu)); | ||
104 | #endif | ||
105 | return tbu; | ||
106 | } | ||
107 | |||
108 | static inline unsigned int get_rtcl(void) | ||
109 | { | ||
110 | unsigned int rtcl; | ||
111 | |||
112 | asm volatile("mfrtcl %0" : "=r" (rtcl)); | ||
113 | return rtcl; | ||
114 | } | ||
115 | |||
116 | #ifdef CONFIG_PPC64 | ||
117 | static inline u64 get_tb(void) | ||
118 | { | ||
119 | return mftb(); | ||
120 | } | ||
121 | #else | ||
122 | static inline u64 get_tb(void) | ||
123 | { | ||
124 | unsigned int tbhi, tblo, tbhi2; | ||
125 | |||
126 | do { | ||
127 | tbhi = get_tbu(); | ||
128 | tblo = get_tbl(); | ||
129 | tbhi2 = get_tbu(); | ||
130 | } while (tbhi != tbhi2); | ||
131 | |||
132 | return ((u64)tbhi << 32) | tblo; | ||
133 | } | ||
134 | #endif | ||
135 | |||
136 | static inline void set_tb(unsigned int upper, unsigned int lower) | ||
137 | { | ||
138 | mtspr(SPRN_TBWL, 0); | ||
139 | mtspr(SPRN_TBWU, upper); | ||
140 | mtspr(SPRN_TBWL, lower); | ||
141 | } | ||
142 | |||
143 | /* Accessor functions for the decrementer register. | ||
144 | * The 4xx doesn't even have a decrementer. I tried to use the | ||
145 | * generic timer interrupt code, which seems OK, with the 4xx PIT | ||
146 | * in auto-reload mode. The problem is PIT stops counting when it | ||
147 | * hits zero. If it would wrap, we could use it just like a decrementer. | ||
148 | */ | ||
149 | static inline unsigned int get_dec(void) | ||
150 | { | ||
151 | #if defined(CONFIG_40x) | ||
152 | return (mfspr(SPRN_PIT)); | ||
153 | #else | ||
154 | return (mfspr(SPRN_DEC)); | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | static inline void set_dec(int val) | ||
159 | { | ||
160 | #if defined(CONFIG_40x) | ||
161 | return; /* Have to let it auto-reload */ | ||
162 | #elif defined(CONFIG_8xx_CPU6) | ||
163 | set_dec_cpu6(val); | ||
164 | #else | ||
165 | #ifdef CONFIG_PPC_ISERIES | ||
166 | struct paca_struct *lpaca = get_paca(); | ||
167 | int cur_dec; | ||
168 | |||
169 | if (lpaca->lppaca.shared_proc) { | ||
170 | lpaca->lppaca.virtual_decr = val; | ||
171 | cur_dec = get_dec(); | ||
172 | if (cur_dec > val) | ||
173 | HvCall_setVirtualDecr(); | ||
174 | } else | ||
175 | #endif | ||
176 | mtspr(SPRN_DEC, val); | ||
177 | #endif /* not 40x or 8xx_CPU6 */ | ||
178 | } | ||
179 | |||
180 | static inline unsigned long tb_ticks_since(unsigned long tstamp) | ||
181 | { | ||
182 | if (__USE_RTC()) { | ||
183 | int delta = get_rtcl() - (unsigned int) tstamp; | ||
184 | return delta < 0 ? delta + 1000000000 : delta; | ||
185 | } | ||
186 | return get_tbl() - tstamp; | ||
187 | } | ||
188 | |||
189 | #define mulhwu(x,y) \ | ||
190 | ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) | ||
191 | |||
192 | #ifdef CONFIG_PPC64 | ||
193 | #define mulhdu(x,y) \ | ||
194 | ({unsigned long z; asm ("mulhdu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) | ||
195 | #else | ||
196 | extern u64 mulhdu(u64, u64); | ||
197 | #endif | ||
198 | |||
199 | unsigned mulhwu_scale_factor(unsigned, unsigned); | ||
200 | void div128_by_32(u64 dividend_high, u64 dividend_low, | ||
201 | unsigned divisor, struct div_result *dr); | ||
202 | |||
203 | /* Used to store Processor Utilization register (purr) values */ | ||
204 | |||
205 | struct cpu_usage { | ||
206 | u64 current_tb; /* Holds the current purr register values */ | ||
207 | }; | ||
208 | |||
209 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); | ||
210 | |||
211 | #endif /* __KERNEL__ */ | ||
212 | #endif /* __PPC64_TIME_H */ | ||
diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h deleted file mode 100644 index c6c762cad8b0..000000000000 --- a/include/asm-ppc64/time.h +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | /* | ||
2 | * Common time prototypes and such for all ppc machines. | ||
3 | * | ||
4 | * Written by Cort Dougan (cort@cs.nmt.edu) to merge | ||
5 | * Paul Mackerras' version and mine for PReP and Pmac. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PPC64_TIME_H | ||
14 | #define __PPC64_TIME_H | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/mc146818rtc.h> | ||
20 | |||
21 | #include <asm/processor.h> | ||
22 | #include <asm/paca.h> | ||
23 | #include <asm/iSeries/HvCall.h> | ||
24 | |||
25 | /* time.c */ | ||
26 | extern unsigned long tb_ticks_per_jiffy; | ||
27 | extern unsigned long tb_ticks_per_usec; | ||
28 | extern unsigned long tb_ticks_per_sec; | ||
29 | extern unsigned long tb_to_xs; | ||
30 | extern unsigned tb_to_us; | ||
31 | extern unsigned long tb_last_stamp; | ||
32 | |||
33 | struct rtc_time; | ||
34 | extern void to_tm(int tim, struct rtc_time * tm); | ||
35 | extern time_t last_rtc_update; | ||
36 | |||
37 | void generic_calibrate_decr(void); | ||
38 | void setup_default_decr(void); | ||
39 | |||
40 | /* Some sane defaults: 125 MHz timebase, 1GHz processor */ | ||
41 | extern unsigned long ppc_proc_freq; | ||
42 | #define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8) | ||
43 | extern unsigned long ppc_tb_freq; | ||
44 | #define DEFAULT_TB_FREQ 125000000UL | ||
45 | |||
46 | /* | ||
47 | * By putting all of this stuff into a single struct we | ||
48 | * reduce the number of cache lines touched by do_gettimeofday. | ||
49 | * Both by collecting all of the data in one cache line and | ||
50 | * by touching only one TOC entry | ||
51 | */ | ||
52 | struct gettimeofday_vars { | ||
53 | unsigned long tb_to_xs; | ||
54 | unsigned long stamp_xsec; | ||
55 | unsigned long tb_orig_stamp; | ||
56 | }; | ||
57 | |||
58 | struct gettimeofday_struct { | ||
59 | unsigned long tb_ticks_per_sec; | ||
60 | struct gettimeofday_vars vars[2]; | ||
61 | struct gettimeofday_vars * volatile varp; | ||
62 | unsigned var_idx; | ||
63 | unsigned tb_to_us; | ||
64 | }; | ||
65 | |||
66 | struct div_result { | ||
67 | unsigned long result_high; | ||
68 | unsigned long result_low; | ||
69 | }; | ||
70 | |||
71 | int via_calibrate_decr(void); | ||
72 | |||
73 | static __inline__ unsigned long get_tb(void) | ||
74 | { | ||
75 | return mftb(); | ||
76 | } | ||
77 | |||
78 | /* Accessor functions for the decrementer register. */ | ||
79 | static __inline__ unsigned int get_dec(void) | ||
80 | { | ||
81 | return (mfspr(SPRN_DEC)); | ||
82 | } | ||
83 | |||
84 | static __inline__ void set_dec(int val) | ||
85 | { | ||
86 | #ifdef CONFIG_PPC_ISERIES | ||
87 | struct paca_struct *lpaca = get_paca(); | ||
88 | int cur_dec; | ||
89 | |||
90 | if (lpaca->lppaca.shared_proc) { | ||
91 | lpaca->lppaca.virtual_decr = val; | ||
92 | cur_dec = get_dec(); | ||
93 | if (cur_dec > val) | ||
94 | HvCall_setVirtualDecr(); | ||
95 | } else | ||
96 | #endif | ||
97 | mtspr(SPRN_DEC, val); | ||
98 | } | ||
99 | |||
100 | static inline unsigned long tb_ticks_since(unsigned long tstamp) | ||
101 | { | ||
102 | return get_tb() - tstamp; | ||
103 | } | ||
104 | |||
105 | #define mulhwu(x,y) \ | ||
106 | ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) | ||
107 | #define mulhdu(x,y) \ | ||
108 | ({unsigned long z; asm ("mulhdu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) | ||
109 | |||
110 | |||
111 | unsigned mulhwu_scale_factor(unsigned, unsigned); | ||
112 | void div128_by_32( unsigned long dividend_high, unsigned long dividend_low, | ||
113 | unsigned divisor, struct div_result *dr ); | ||
114 | |||
115 | /* Used to store Processor Utilization register (purr) values */ | ||
116 | |||
117 | struct cpu_usage { | ||
118 | u64 current_tb; /* Holds the current purr register values */ | ||
119 | }; | ||
120 | |||
121 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); | ||
122 | |||
123 | #endif /* __KERNEL__ */ | ||
124 | #endif /* __PPC64_TIME_H */ | ||