1 // SPDX-License-Identifier: GPL-2.0 << 2 /* 1 /* 3 * arch/sh/kernel/time.c !! 2 * linux/arch/i386/kernel/time.c 4 * 3 * 5 * Copyright (C) 1999 Tetsuya Okada & Niibe !! 4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 6 * Copyright (C) 2000 Philipp Rumpf <prumpf@ !! 5 * 7 * Copyright (C) 2002 - 2009 Paul Mundt !! 6 * This file contains the PC-specific time handling details: 8 * Copyright (C) 2002 M. R. Brown <mrbrown@ !! 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 * 1996-05-03 Ingo Molnar >> 14 * fixed time warps in do_[slow|fast]_gettimeoffset() >> 15 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 >> 16 * "A Kernel Model for Precision Timekeeping" by Dave Mills >> 17 * 1998-09-05 (Various) >> 18 * More robust do_fast_gettimeoffset() algorithm implemented >> 19 * (works with APM, Cyrix 6x86MX and Centaur C6), >> 20 * monotonic gettimeofday() with fast_get_timeoffset(), >> 21 * drift-proof precision TSC calibration on boot >> 22 * (C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D. >> 23 * Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>; >> 24 * ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>). >> 25 * 1998-12-16 Andrea Arcangeli >> 26 * Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy >> 27 * because was not accounting lost_ticks. >> 28 * 1998-12-24 Copyright (C) 1998 Andrea Arcangeli >> 29 * Fixed a xtime SMP race (we need the xtime_lock rw spinlock to >> 30 * serialize accesses to xtime/lost_ticks). 9 */ 31 */ >> 32 >> 33 #include <linux/errno.h> >> 34 #include <linux/sched.h> 10 #include <linux/kernel.h> 35 #include <linux/kernel.h> >> 36 #include <linux/param.h> >> 37 #include <linux/string.h> >> 38 #include <linux/mm.h> >> 39 #include <linux/interrupt.h> >> 40 #include <linux/time.h> >> 41 #include <linux/delay.h> 11 #include <linux/init.h> 42 #include <linux/init.h> 12 #include <linux/profile.h> << 13 #include <linux/timex.h> << 14 #include <linux/sched.h> << 15 #include <linux/clockchips.h> << 16 #include <linux/platform_device.h> << 17 #include <linux/smp.h> 43 #include <linux/smp.h> 18 #include <linux/rtc.h> !! 44 #include <linux/module.h> 19 #include <asm/clock.h> !! 45 #include <linux/sysdev.h> 20 #include <asm/rtc.h> !! 46 #include <linux/bcd.h> 21 #include <asm/platform_early.h> !! 47 >> 48 #include <asm/io.h> >> 49 #include <asm/smp.h> >> 50 #include <asm/irq.h> >> 51 #include <asm/msr.h> >> 52 #include <asm/delay.h> >> 53 #include <asm/mpspec.h> >> 54 #include <asm/uaccess.h> >> 55 #include <asm/processor.h> >> 56 #include <asm/timer.h> >> 57 >> 58 #include "mach_time.h" >> 59 >> 60 #include <linux/timex.h> >> 61 #include <linux/config.h> >> 62 >> 63 #include <asm/hpet.h> >> 64 >> 65 #include <asm/arch_hooks.h> >> 66 >> 67 #include "io_ports.h" >> 68 >> 69 extern spinlock_t i8259A_lock; >> 70 int pit_latch_buggy; /* extern */ >> 71 >> 72 #include "do_timer.h" >> 73 >> 74 u64 jiffies_64 = INITIAL_JIFFIES; >> 75 >> 76 EXPORT_SYMBOL(jiffies_64); >> 77 >> 78 unsigned long cpu_khz; /* Detected as we calibrate the TSC */ >> 79 >> 80 extern unsigned long wall_jiffies; >> 81 >> 82 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; >> 83 >> 84 spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; >> 85 EXPORT_SYMBOL(i8253_lock); >> 86 >> 87 struct timer_opts *cur_timer = &timer_none; >> 88 >> 89 /* >> 90 * This version of gettimeofday has microsecond resolution >> 91 * and better than microsecond precision on fast x86 machines with TSC. >> 92 */ >> 93 void do_gettimeofday(struct timeval *tv) >> 94 { >> 95 unsigned long seq; >> 96 unsigned long usec, sec; >> 97 unsigned long max_ntp_tick = tick_usec - tickadj; >> 98 >> 99 do { >> 100 unsigned long lost; >> 101 >> 102 seq = read_seqbegin(&xtime_lock); >> 103 >> 104 usec = cur_timer->get_offset(); >> 105 lost = jiffies - wall_jiffies; >> 106 >> 107 /* >> 108 * If time_adjust is negative then NTP is slowing the clock >> 109 * so make sure not to go into next possible interval. >> 110 * Better to lose some accuracy than have time go backwards.. >> 111 */ >> 112 if (unlikely(time_adjust < 0)) { >> 113 usec = min(usec, max_ntp_tick); >> 114 >> 115 if (lost) >> 116 usec += lost * max_ntp_tick; >> 117 } >> 118 else if (unlikely(lost)) >> 119 usec += lost * tick_usec; >> 120 >> 121 sec = xtime.tv_sec; >> 122 usec += (xtime.tv_nsec / 1000); >> 123 } while (read_seqretry(&xtime_lock, seq)); >> 124 >> 125 while (usec >= 1000000) { >> 126 usec -= 1000000; >> 127 sec++; >> 128 } >> 129 >> 130 tv->tv_sec = sec; >> 131 tv->tv_usec = usec; >> 132 } >> 133 >> 134 EXPORT_SYMBOL(do_gettimeofday); 22 135 23 static void __init sh_late_time_init(void) !! 136 int do_settimeofday(struct timespec *tv) 24 { 137 { >> 138 time_t wtm_sec, sec = tv->tv_sec; >> 139 long wtm_nsec, nsec = tv->tv_nsec; >> 140 >> 141 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) >> 142 return -EINVAL; >> 143 >> 144 write_seqlock_irq(&xtime_lock); 25 /* 145 /* 26 * Make sure all compiled-in early tim !! 146 * This is revolting. We need to set "xtime" correctly. However, the 27 * !! 147 * value in this location is the value at the most recent update of 28 * Run probe() for two "earlytimer" de !! 148 * wall time. Discover what correction gettimeofday() would have 29 * clockevents and clocksource devices !! 149 * made, and then undo it! 30 * that only a clockevents device is a << 31 * clocksource and the jiffies clockso << 32 * instead. No error handling is neces << 33 */ 150 */ 34 sh_early_platform_driver_register_all( !! 151 nsec -= cur_timer->get_offset() * NSEC_PER_USEC; 35 sh_early_platform_driver_probe("earlyt !! 152 nsec -= (jiffies - wall_jiffies) * TICK_NSEC; >> 153 >> 154 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); >> 155 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); >> 156 >> 157 set_normalized_timespec(&xtime, sec, nsec); >> 158 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); >> 159 >> 160 time_adjust = 0; /* stop active adjtime() */ >> 161 time_status |= STA_UNSYNC; >> 162 time_maxerror = NTP_PHASE_LIMIT; >> 163 time_esterror = NTP_PHASE_LIMIT; >> 164 write_sequnlock_irq(&xtime_lock); >> 165 clock_was_set(); >> 166 return 0; >> 167 } >> 168 >> 169 EXPORT_SYMBOL(do_settimeofday); >> 170 >> 171 static int set_rtc_mmss(unsigned long nowtime) >> 172 { >> 173 int retval; >> 174 >> 175 /* gets recalled with irq locally disabled */ >> 176 spin_lock(&rtc_lock); >> 177 retval = mach_set_rtc_mmss(nowtime); >> 178 spin_unlock(&rtc_lock); >> 179 >> 180 return retval; >> 181 } >> 182 >> 183 /* last time the cmos clock got updated */ >> 184 static long last_rtc_update; >> 185 >> 186 int timer_ack; >> 187 >> 188 /* monotonic_clock(): returns # of nanoseconds passed since time_init() >> 189 * Note: This function is required to return accurate >> 190 * time even in the absence of multiple timer ticks. >> 191 */ >> 192 unsigned long long monotonic_clock(void) >> 193 { >> 194 return cur_timer->monotonic_clock(); >> 195 } >> 196 EXPORT_SYMBOL(monotonic_clock); >> 197 >> 198 >> 199 /* >> 200 * timer_interrupt() needs to keep up the real-time clock, >> 201 * as well as call the "do_timer()" routine every clocktick >> 202 */ >> 203 static inline void do_timer_interrupt(int irq, void *dev_id, >> 204 struct pt_regs *regs) >> 205 { >> 206 #ifdef CONFIG_X86_IO_APIC >> 207 if (timer_ack) { >> 208 /* >> 209 * Subtle, when I/O APICs are used we have to ack timer IRQ >> 210 * manually to reset the IRR bit for do_slow_gettimeoffset(). >> 211 * This will also deassert NMI lines for the watchdog if run >> 212 * on an 82489DX-based system. >> 213 */ >> 214 spin_lock(&i8259A_lock); >> 215 outb(0x0c, PIC_MASTER_OCW3); >> 216 /* Ack the IRQ; AEOI will end it automatically. */ >> 217 inb(PIC_MASTER_POLL); >> 218 spin_unlock(&i8259A_lock); >> 219 } >> 220 #endif >> 221 >> 222 do_timer_interrupt_hook(regs); >> 223 >> 224 /* >> 225 * If we have an externally synchronized Linux clock, then update >> 226 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be >> 227 * called as close as possible to 500 ms before the new second starts. >> 228 */ >> 229 if ((time_status & STA_UNSYNC) == 0 && >> 230 xtime.tv_sec > last_rtc_update + 660 && >> 231 (xtime.tv_nsec / 1000) >> 232 >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && >> 233 (xtime.tv_nsec / 1000) >> 234 <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) { >> 235 if (set_rtc_mmss(xtime.tv_sec) == 0) >> 236 last_rtc_update = xtime.tv_sec; >> 237 else >> 238 last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ >> 239 } >> 240 >> 241 #ifdef CONFIG_MCA >> 242 if( MCA_bus ) { >> 243 /* The PS/2 uses level-triggered interrupts. You can't >> 244 turn them off, nor would you want to (any attempt to >> 245 enable edge-triggered interrupts usually gets intercepted by a >> 246 special hardware circuit). Hence we have to acknowledge >> 247 the timer interrupt. Through some incredibly stupid >> 248 design idea, the reset for IRQ 0 is done by setting the >> 249 high bit of the PPI port B (0x61). Note that some PS/2s, >> 250 notably the 55SX, work fine if this is removed. */ >> 251 >> 252 irq = inb_p( 0x61 ); /* read the current state */ >> 253 outb_p( irq|0x80, 0x61 ); /* reset the IRQ */ >> 254 } >> 255 #endif >> 256 } >> 257 >> 258 /* >> 259 * This is the same as the above, except we _also_ save the current >> 260 * Time Stamp Counter value at the time of the timer interrupt, so that >> 261 * we later on can estimate the time of day more exactly. >> 262 */ >> 263 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) >> 264 { >> 265 /* >> 266 * Here we are in the timer irq handler. We just have irqs locally >> 267 * disabled but we don't know if the timer_bh is running on the other >> 268 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need >> 269 * the irq version of write_lock because as just said we have irq >> 270 * locally disabled. -arca >> 271 */ >> 272 write_seqlock(&xtime_lock); >> 273 >> 274 cur_timer->mark_offset(); >> 275 >> 276 do_timer_interrupt(irq, NULL, regs); >> 277 >> 278 write_sequnlock(&xtime_lock); >> 279 return IRQ_HANDLED; >> 280 } >> 281 >> 282 /* not static: needed by APM */ >> 283 unsigned long get_cmos_time(void) >> 284 { >> 285 unsigned long retval; >> 286 >> 287 spin_lock(&rtc_lock); >> 288 >> 289 retval = mach_get_cmos_time(); >> 290 >> 291 spin_unlock(&rtc_lock); >> 292 >> 293 return retval; >> 294 } >> 295 >> 296 static struct sysdev_class pit_sysclass = { >> 297 set_kset_name("pit"), >> 298 }; >> 299 >> 300 /* XXX this driverfs stuff should probably go elsewhere later -john */ >> 301 static struct sys_device device_i8253 = { >> 302 .id = 0, >> 303 .cls = &pit_sysclass, >> 304 }; >> 305 >> 306 static int time_init_device(void) >> 307 { >> 308 int error = sysdev_class_register(&pit_sysclass); >> 309 if (!error) >> 310 error = sys_device_register(&device_i8253); >> 311 return error; >> 312 } >> 313 >> 314 device_initcall(time_init_device); >> 315 >> 316 #ifdef CONFIG_HPET_TIMER >> 317 extern void (*late_time_init)(void); >> 318 /* Duplicate of time_init() below, with hpet_enable part added */ >> 319 void __init hpet_time_init(void) >> 320 { >> 321 xtime.tv_sec = get_cmos_time(); >> 322 wall_to_monotonic.tv_sec = -xtime.tv_sec; >> 323 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); >> 324 wall_to_monotonic.tv_nsec = -xtime.tv_nsec; >> 325 >> 326 if (hpet_enable() >= 0) { >> 327 printk("Using HPET for base-timer\n"); >> 328 } >> 329 >> 330 cur_timer = select_timer(); >> 331 time_init_hook(); 36 } 332 } >> 333 #endif 37 334 38 void __init time_init(void) 335 void __init time_init(void) 39 { 336 { 40 timer_probe(); !! 337 #ifdef CONFIG_HPET_TIMER >> 338 if (is_hpet_capable()) { >> 339 /* >> 340 * HPET initialization needs to do memory-mapped io. So, let >> 341 * us do a late initialization after mem_init(). >> 342 */ >> 343 late_time_init = hpet_time_init; >> 344 return; >> 345 } >> 346 #endif 41 347 42 clk_init(); !! 348 xtime.tv_sec = get_cmos_time(); >> 349 wall_to_monotonic.tv_sec = -xtime.tv_sec; >> 350 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); >> 351 wall_to_monotonic.tv_nsec = -xtime.tv_nsec; 43 352 44 late_time_init = sh_late_time_init; !! 353 cur_timer = select_timer(); >> 354 time_init_hook(); 45 } 355 } 46 356
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.