diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
| commit | bb799d3b980eb803ca2da4a4eefbd9308f8d988a (patch) | |
| tree | 69fbe0cd6d47b23a50f5e1d87bf7489532fae149 /arch/alpha/kernel/time.c | |
| parent | 919fc6e34831d1c2b58bfb5ae261dc3facc9b269 (diff) | |
| parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) | |
Merge tag 'v3.13-rc4' into core/locking
Merge Linux 3.13-rc4, to refresh this rather old tree with the latest fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/alpha/kernel/time.c')
| -rw-r--r-- | arch/alpha/kernel/time.c | 405 |
1 files changed, 175 insertions, 230 deletions
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 | ||
