11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/alpha/kernel/time.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds 51da177e4SLinus Torvalds * 685d0b3a5SRichard Henderson * This file contains the clocksource time handling. 71da177e4SLinus Torvalds * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 81da177e4SLinus Torvalds * "A Kernel Model for Precision Timekeeping" by Dave Mills 91da177e4SLinus Torvalds * 1997-01-09 Adrian Sun 101da177e4SLinus Torvalds * use interval timer if CONFIG_RTC=y 111da177e4SLinus Torvalds * 1997-10-29 John Bowman (bowman@math.ualberta.ca) 121da177e4SLinus Torvalds * fixed tick loss calculation in timer_interrupt 131da177e4SLinus Torvalds * (round system clock to nearest tick instead of truncating) 141da177e4SLinus Torvalds * fixed algorithm in time_init for getting time from CMOS clock 151da177e4SLinus Torvalds * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) 161da177e4SLinus Torvalds * fixed algorithm in do_gettimeofday() for calculating the precise time 171da177e4SLinus Torvalds * from processor cycle counter (now taking lost_ticks into account) 181da177e4SLinus Torvalds * 2003-06-03 R. Scott Bailey <scott.bailey@eds.com> 191da177e4SLinus Torvalds * Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds #include <linux/errno.h> 221da177e4SLinus Torvalds #include <linux/module.h> 231da177e4SLinus Torvalds #include <linux/sched.h> 241da177e4SLinus Torvalds #include <linux/kernel.h> 251da177e4SLinus Torvalds #include <linux/param.h> 261da177e4SLinus Torvalds #include <linux/string.h> 271da177e4SLinus Torvalds #include <linux/mm.h> 281da177e4SLinus Torvalds #include <linux/delay.h> 291da177e4SLinus Torvalds #include <linux/ioport.h> 301da177e4SLinus Torvalds #include <linux/irq.h> 311da177e4SLinus Torvalds #include <linux/interrupt.h> 321da177e4SLinus Torvalds #include <linux/init.h> 331da177e4SLinus Torvalds #include <linux/bcd.h> 341da177e4SLinus Torvalds #include <linux/profile.h> 35e360adbeSPeter Zijlstra #include <linux/irq_work.h> 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #include <asm/uaccess.h> 381da177e4SLinus Torvalds #include <asm/io.h> 391da177e4SLinus Torvalds #include <asm/hwrpb.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <linux/mc146818rtc.h> 421da177e4SLinus Torvalds #include <linux/time.h> 431da177e4SLinus Torvalds #include <linux/timex.h> 449ce34c8fSJohn Stultz #include <linux/clocksource.h> 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #include "proto.h" 471da177e4SLinus Torvalds #include "irq_impl.h" 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds DEFINE_SPINLOCK(rtc_lock); 50cff52dafSAl Viro EXPORT_SYMBOL(rtc_lock); 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds #define TICK_SIZE (tick_nsec / 1000) 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds /* 551da177e4SLinus Torvalds * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting 561da177e4SLinus Torvalds * by 48 gives us 16 bits for HZ while keeping the accuracy good even 571da177e4SLinus Torvalds * for large CPU clock rates. 581da177e4SLinus Torvalds */ 591da177e4SLinus Torvalds #define FIX_SHIFT 48 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds /* lump static variables together for more efficient access: */ 621da177e4SLinus Torvalds static struct { 631da177e4SLinus Torvalds /* cycle counter last time it got invoked */ 641da177e4SLinus Torvalds __u32 last_time; 651da177e4SLinus Torvalds /* ticks/cycle * 2^48 */ 661da177e4SLinus Torvalds unsigned long scaled_ticks_per_cycle; 671da177e4SLinus Torvalds /* partial unused tick */ 681da177e4SLinus Torvalds unsigned long partial_tick; 691da177e4SLinus Torvalds } state; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds unsigned long est_cycle_freq; 721da177e4SLinus Torvalds 73e360adbeSPeter Zijlstra #ifdef CONFIG_IRQ_WORK 74979f8671SMichael Cree 75e360adbeSPeter Zijlstra DEFINE_PER_CPU(u8, irq_work_pending); 76979f8671SMichael Cree 77e360adbeSPeter Zijlstra #define set_irq_work_pending_flag() __get_cpu_var(irq_work_pending) = 1 78e360adbeSPeter Zijlstra #define test_irq_work_pending() __get_cpu_var(irq_work_pending) 79e360adbeSPeter Zijlstra #define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0 80979f8671SMichael Cree 810f933625SPeter Zijlstra void arch_irq_work_raise(void) 82979f8671SMichael Cree { 83e360adbeSPeter Zijlstra set_irq_work_pending_flag(); 84979f8671SMichael Cree } 85979f8671SMichael Cree 86e360adbeSPeter Zijlstra #else /* CONFIG_IRQ_WORK */ 87979f8671SMichael Cree 88e360adbeSPeter Zijlstra #define test_irq_work_pending() 0 89e360adbeSPeter Zijlstra #define clear_irq_work_pending() 90979f8671SMichael Cree 91e360adbeSPeter Zijlstra #endif /* CONFIG_IRQ_WORK */ 92979f8671SMichael Cree 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds static inline __u32 rpcc(void) 951da177e4SLinus Torvalds { 9691531b05SRichard Henderson return __builtin_alpha_rpcc(); 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds /* 1001da177e4SLinus Torvalds * timer_interrupt() needs to keep up the real-time clock, 1011340f3e0STorben Hohn * as well as call the "xtime_update()" routine every clocktick 1021da177e4SLinus Torvalds */ 1038774cb81SAl Viro irqreturn_t timer_interrupt(int irq, void *dev) 1041da177e4SLinus Torvalds { 1051da177e4SLinus Torvalds unsigned long delta; 1061da177e4SLinus Torvalds __u32 now; 1071da177e4SLinus Torvalds long nticks; 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds #ifndef CONFIG_SMP 1101da177e4SLinus Torvalds /* Not SMP, do kernel PC profiling here. */ 1118774cb81SAl Viro profile_tick(CPU_PROFILING); 1121da177e4SLinus Torvalds #endif 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* 1151da177e4SLinus Torvalds * Calculate how many ticks have passed since the last update, 1161da177e4SLinus Torvalds * including any previous partial leftover. Save any resulting 1171da177e4SLinus Torvalds * fraction for the next pass. 1181da177e4SLinus Torvalds */ 1191da177e4SLinus Torvalds now = rpcc(); 1201da177e4SLinus Torvalds delta = now - state.last_time; 1211da177e4SLinus Torvalds state.last_time = now; 1221da177e4SLinus Torvalds delta = delta * state.scaled_ticks_per_cycle + state.partial_tick; 1231da177e4SLinus Torvalds state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1); 1241da177e4SLinus Torvalds nticks = delta >> FIX_SHIFT; 1251da177e4SLinus Torvalds 126aa02cd2dSPeter Zijlstra if (nticks) 1271340f3e0STorben Hohn xtime_update(nticks); 128aa02cd2dSPeter Zijlstra 129e360adbeSPeter Zijlstra if (test_irq_work_pending()) { 130e360adbeSPeter Zijlstra clear_irq_work_pending(); 131e360adbeSPeter Zijlstra irq_work_run(); 132979f8671SMichael Cree } 133979f8671SMichael Cree 134bdc8b891SMichael Cree #ifndef CONFIG_SMP 135bdc8b891SMichael Cree while (nticks--) 136bdc8b891SMichael Cree update_process_times(user_mode(get_irq_regs())); 137bdc8b891SMichael Cree #endif 138bdc8b891SMichael Cree 1391da177e4SLinus Torvalds return IRQ_HANDLED; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 142ebaf4fc1SSam Ravnborg void __init 1431da177e4SLinus Torvalds common_init_rtc(void) 1441da177e4SLinus Torvalds { 145fddd87d6SRichard Henderson unsigned char x, sel = 0; 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds /* Reset periodic interrupt frequency. */ 148fddd87d6SRichard Henderson #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200 1491da177e4SLinus Torvalds x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; 1501da177e4SLinus Torvalds /* Test includes known working values on various platforms 1511da177e4SLinus Torvalds where 0x26 is wrong; we refuse to change those. */ 1521da177e4SLinus Torvalds if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) { 153fddd87d6SRichard Henderson sel = RTC_REF_CLCK_32KHZ + 6; 154fddd87d6SRichard Henderson } 155fddd87d6SRichard Henderson #elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32 156fddd87d6SRichard Henderson sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ); 157fddd87d6SRichard Henderson #else 158fddd87d6SRichard Henderson # error "Unknown HZ from arch/alpha/Kconfig" 159fddd87d6SRichard Henderson #endif 160fddd87d6SRichard Henderson if (sel) { 161fddd87d6SRichard Henderson printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n", 162fddd87d6SRichard Henderson CONFIG_HZ, sel); 163fddd87d6SRichard Henderson CMOS_WRITE(sel, RTC_FREQ_SELECT); 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* Turn on periodic interrupts. */ 1671da177e4SLinus Torvalds x = CMOS_READ(RTC_CONTROL); 1681da177e4SLinus Torvalds if (!(x & RTC_PIE)) { 1691da177e4SLinus Torvalds printk("Turning on RTC interrupts.\n"); 1701da177e4SLinus Torvalds x |= RTC_PIE; 1711da177e4SLinus Torvalds x &= ~(RTC_AIE | RTC_UIE); 1721da177e4SLinus Torvalds CMOS_WRITE(x, RTC_CONTROL); 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds (void) CMOS_READ(RTC_INTR_FLAGS); 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds outb(0x36, 0x43); /* pit counter 0: system timer */ 1771da177e4SLinus Torvalds outb(0x00, 0x40); 1781da177e4SLinus Torvalds outb(0x00, 0x40); 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds outb(0xb6, 0x43); /* pit counter 2: speaker */ 1811da177e4SLinus Torvalds outb(0x31, 0x42); 1821da177e4SLinus Torvalds outb(0x13, 0x42); 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds init_rtc_irq(); 1851da177e4SLinus Torvalds } 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds /* Validate a computed cycle counter result against the known bounds for 1881da177e4SLinus Torvalds the given processor core. There's too much brokenness in the way of 1891da177e4SLinus Torvalds timing hardware for any one method to work everywhere. :-( 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds Return 0 if the result cannot be trusted, otherwise return the argument. */ 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds static unsigned long __init 1941da177e4SLinus Torvalds validate_cc_value(unsigned long cc) 1951da177e4SLinus Torvalds { 1961da177e4SLinus Torvalds static struct bounds { 1971da177e4SLinus Torvalds unsigned int min, max; 1981da177e4SLinus Torvalds } cpu_hz[] __initdata = { 1991da177e4SLinus Torvalds [EV3_CPU] = { 50000000, 200000000 }, /* guess */ 2001da177e4SLinus Torvalds [EV4_CPU] = { 100000000, 300000000 }, 2011da177e4SLinus Torvalds [LCA4_CPU] = { 100000000, 300000000 }, /* guess */ 2021da177e4SLinus Torvalds [EV45_CPU] = { 200000000, 300000000 }, 2031da177e4SLinus Torvalds [EV5_CPU] = { 250000000, 433000000 }, 2041da177e4SLinus Torvalds [EV56_CPU] = { 333000000, 667000000 }, 2051da177e4SLinus Torvalds [PCA56_CPU] = { 400000000, 600000000 }, /* guess */ 2061da177e4SLinus Torvalds [PCA57_CPU] = { 500000000, 600000000 }, /* guess */ 2071da177e4SLinus Torvalds [EV6_CPU] = { 466000000, 600000000 }, 2081da177e4SLinus Torvalds [EV67_CPU] = { 600000000, 750000000 }, 2091da177e4SLinus Torvalds [EV68AL_CPU] = { 750000000, 940000000 }, 2101da177e4SLinus Torvalds [EV68CB_CPU] = { 1000000000, 1333333333 }, 2111da177e4SLinus Torvalds /* None of the following are shipping as of 2001-11-01. */ 2121da177e4SLinus Torvalds [EV68CX_CPU] = { 1000000000, 1700000000 }, /* guess */ 2131da177e4SLinus Torvalds [EV69_CPU] = { 1000000000, 1700000000 }, /* guess */ 2141da177e4SLinus Torvalds [EV7_CPU] = { 800000000, 1400000000 }, /* guess */ 2151da177e4SLinus Torvalds [EV79_CPU] = { 1000000000, 2000000000 }, /* guess */ 2161da177e4SLinus Torvalds }; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds /* Allow for some drift in the crystal. 10MHz is more than enough. */ 2191da177e4SLinus Torvalds const unsigned int deviation = 10000000; 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds struct percpu_struct *cpu; 2221da177e4SLinus Torvalds unsigned int index; 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds cpu = (struct percpu_struct *)((char*)hwrpb + hwrpb->processor_offset); 2251da177e4SLinus Torvalds index = cpu->type & 0xffffffff; 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds /* If index out of bounds, no way to validate. */ 22825c8716cSTobias Klauser if (index >= ARRAY_SIZE(cpu_hz)) 2291da177e4SLinus Torvalds return cc; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* If index contains no data, no way to validate. */ 2321da177e4SLinus Torvalds if (cpu_hz[index].max == 0) 2331da177e4SLinus Torvalds return cc; 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds if (cc < cpu_hz[index].min - deviation 2361da177e4SLinus Torvalds || cc > cpu_hz[index].max + deviation) 2371da177e4SLinus Torvalds return 0; 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds return cc; 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* 2441da177e4SLinus Torvalds * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from 2451da177e4SLinus Torvalds * arch/i386/time.c. 2461da177e4SLinus Torvalds */ 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds #define CALIBRATE_LATCH 0xffff 2491da177e4SLinus Torvalds #define TIMEOUT_COUNT 0x100000 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds static unsigned long __init 2521da177e4SLinus Torvalds calibrate_cc_with_pit(void) 2531da177e4SLinus Torvalds { 2541da177e4SLinus Torvalds int cc, count = 0; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds /* Set the Gate high, disable speaker */ 2571da177e4SLinus Torvalds outb((inb(0x61) & ~0x02) | 0x01, 0x61); 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds /* 2601da177e4SLinus Torvalds * Now let's take care of CTC channel 2 2611da177e4SLinus Torvalds * 2621da177e4SLinus Torvalds * Set the Gate high, program CTC channel 2 for mode 0, 2631da177e4SLinus Torvalds * (interrupt on terminal count mode), binary count, 2641da177e4SLinus Torvalds * load 5 * LATCH count, (LSB and MSB) to begin countdown. 2651da177e4SLinus Torvalds */ 2661da177e4SLinus Torvalds outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ 2671da177e4SLinus Torvalds outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ 2681da177e4SLinus Torvalds outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds cc = rpcc(); 2711da177e4SLinus Torvalds do { 2721da177e4SLinus Torvalds count++; 2731da177e4SLinus Torvalds } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT); 2741da177e4SLinus Torvalds cc = rpcc() - cc; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds /* Error: ECTCNEVERSET or ECPUTOOFAST. */ 2771da177e4SLinus Torvalds if (count <= 1 || count == TIMEOUT_COUNT) 2781da177e4SLinus Torvalds return 0; 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* The Linux interpretation of the CMOS clock register contents: 2841da177e4SLinus Torvalds When the Update-In-Progress (UIP) flag goes from 1 to 0, the 2851da177e4SLinus Torvalds RTC registers show the second which has precisely just started. 2861da177e4SLinus Torvalds Let's hope other operating systems interpret the RTC the same way. */ 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds static unsigned long __init 2891da177e4SLinus Torvalds rpcc_after_update_in_progress(void) 2901da177e4SLinus Torvalds { 2911da177e4SLinus Torvalds do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); 2921da177e4SLinus Torvalds do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds return rpcc(); 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 2979ce34c8fSJohn Stultz #ifndef CONFIG_SMP 2989ce34c8fSJohn Stultz /* Until and unless we figure out how to get cpu cycle counters 2999ce34c8fSJohn Stultz in sync and keep them there, we can't use the rpcc. */ 3009ce34c8fSJohn Stultz static cycle_t read_rpcc(struct clocksource *cs) 3019ce34c8fSJohn Stultz { 3029ce34c8fSJohn Stultz cycle_t ret = (cycle_t)rpcc(); 3039ce34c8fSJohn Stultz return ret; 3049ce34c8fSJohn Stultz } 3059ce34c8fSJohn Stultz 3069ce34c8fSJohn Stultz static struct clocksource clocksource_rpcc = { 3079ce34c8fSJohn Stultz .name = "rpcc", 3089ce34c8fSJohn Stultz .rating = 300, 3099ce34c8fSJohn Stultz .read = read_rpcc, 3109ce34c8fSJohn Stultz .mask = CLOCKSOURCE_MASK(32), 3119ce34c8fSJohn Stultz .flags = CLOCK_SOURCE_IS_CONTINUOUS 3129ce34c8fSJohn Stultz }; 3139ce34c8fSJohn Stultz 3149ce34c8fSJohn Stultz static inline void register_rpcc_clocksource(long cycle_freq) 3159ce34c8fSJohn Stultz { 316f550806aSJohn Stultz clocksource_register_hz(&clocksource_rpcc, cycle_freq); 3179ce34c8fSJohn Stultz } 3189ce34c8fSJohn Stultz #else /* !CONFIG_SMP */ 3199ce34c8fSJohn Stultz static inline void register_rpcc_clocksource(long cycle_freq) 3209ce34c8fSJohn Stultz { 3219ce34c8fSJohn Stultz } 3229ce34c8fSJohn Stultz #endif /* !CONFIG_SMP */ 3239ce34c8fSJohn Stultz 3241da177e4SLinus Torvalds void __init 3251da177e4SLinus Torvalds time_init(void) 3261da177e4SLinus Torvalds { 3271e871be1SJohn Stultz unsigned int cc1, cc2; 3281da177e4SLinus Torvalds unsigned long cycle_freq, tolerance; 3291da177e4SLinus Torvalds long diff; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds /* Calibrate CPU clock -- attempt #1. */ 3321da177e4SLinus Torvalds if (!est_cycle_freq) 3331da177e4SLinus Torvalds est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); 3341da177e4SLinus Torvalds 3354c2e6f6aSMatt Mackall cc1 = rpcc(); 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds /* Calibrate CPU clock -- attempt #2. */ 3381da177e4SLinus Torvalds if (!est_cycle_freq) { 3394c2e6f6aSMatt Mackall cc1 = rpcc_after_update_in_progress(); 3401da177e4SLinus Torvalds cc2 = rpcc_after_update_in_progress(); 3411da177e4SLinus Torvalds est_cycle_freq = validate_cc_value(cc2 - cc1); 3421da177e4SLinus Torvalds cc1 = cc2; 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds cycle_freq = hwrpb->cycle_freq; 3461da177e4SLinus Torvalds if (est_cycle_freq) { 3471da177e4SLinus Torvalds /* If the given value is within 250 PPM of what we calculated, 3481da177e4SLinus Torvalds accept it. Otherwise, use what we found. */ 3491da177e4SLinus Torvalds tolerance = cycle_freq / 4000; 3501da177e4SLinus Torvalds diff = cycle_freq - est_cycle_freq; 3511da177e4SLinus Torvalds if (diff < 0) 3521da177e4SLinus Torvalds diff = -diff; 3531da177e4SLinus Torvalds if ((unsigned long)diff > tolerance) { 3541da177e4SLinus Torvalds cycle_freq = est_cycle_freq; 3551da177e4SLinus Torvalds printk("HWRPB cycle frequency bogus. " 3561da177e4SLinus Torvalds "Estimated %lu Hz\n", cycle_freq); 3571da177e4SLinus Torvalds } else { 3581da177e4SLinus Torvalds est_cycle_freq = 0; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds } else if (! validate_cc_value (cycle_freq)) { 3611da177e4SLinus Torvalds printk("HWRPB cycle frequency bogus, " 3621da177e4SLinus Torvalds "and unable to estimate a proper value!\n"); 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds /* From John Bowman <bowman@math.ualberta.ca>: allow the values 3661da177e4SLinus Torvalds to settle, as the Update-In-Progress bit going low isn't good 3671da177e4SLinus Torvalds enough on some hardware. 2ms is our guess; we haven't found 3681da177e4SLinus Torvalds bogomips yet, but this is close on a 500Mhz box. */ 3691da177e4SLinus Torvalds __delay(1000000); 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds if (HZ > (1<<16)) { 3731da177e4SLinus Torvalds extern void __you_loose (void); 3741da177e4SLinus Torvalds __you_loose(); 3751da177e4SLinus Torvalds } 3761da177e4SLinus Torvalds 3779ce34c8fSJohn Stultz register_rpcc_clocksource(cycle_freq); 3789ce34c8fSJohn Stultz 3791da177e4SLinus Torvalds state.last_time = cc1; 3801da177e4SLinus Torvalds state.scaled_ticks_per_cycle 3811da177e4SLinus Torvalds = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq; 3821da177e4SLinus Torvalds state.partial_tick = 0L; 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds /* Startup the timer source. */ 3851da177e4SLinus Torvalds alpha_mv.init_rtc(); 3861da177e4SLinus Torvalds } 387