|
@@ -3,13 +3,7 @@
|
|
|
*
|
|
|
* Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds
|
|
|
*
|
|
|
- * This file contains the PC-specific time handling details:
|
|
|
- * reading the RTC at bootup, etc..
|
|
|
- * 1994-07-02 Alan Modra
|
|
|
- * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
|
|
|
- * 1995-03-26 Markus Kuhn
|
|
|
- * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
|
|
|
- * precision CMOS clock update
|
|
|
+ * This file contains the clocksource time handling.
|
|
|
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
|
|
|
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
|
|
* 1997-01-09 Adrian Sun
|
|
@@ -21,9 +15,6 @@
|
|
|
* 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net)
|
|
|
* fixed algorithm in do_gettimeofday() for calculating the precise time
|
|
|
* from processor cycle counter (now taking lost_ticks into account)
|
|
|
- * 2000-08-13 Jan-Benedict Glaw <jbglaw@lug-owl.de>
|
|
|
- * Fixed time_init to be aware of epoches != 1900. This prevents
|
|
|
- * booting up in 2048 for me;) Code is stolen from rtc.c.
|
|
|
* 2003-06-03 R. Scott Bailey <scott.bailey@eds.com>
|
|
|
* Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM
|
|
|
*/
|
|
@@ -46,40 +37,19 @@
|
|
|
#include <asm/uaccess.h>
|
|
|
#include <asm/io.h>
|
|
|
#include <asm/hwrpb.h>
|
|
|
-#include <asm/rtc.h>
|
|
|
|
|
|
#include <linux/mc146818rtc.h>
|
|
|
#include <linux/time.h>
|
|
|
#include <linux/timex.h>
|
|
|
#include <linux/clocksource.h>
|
|
|
+#include <linux/clockchips.h>
|
|
|
|
|
|
#include "proto.h"
|
|
|
#include "irq_impl.h"
|
|
|
|
|
|
-static int set_rtc_mmss(unsigned long);
|
|
|
-
|
|
|
DEFINE_SPINLOCK(rtc_lock);
|
|
|
EXPORT_SYMBOL(rtc_lock);
|
|
|
|
|
|
-#define TICK_SIZE (tick_nsec / 1000)
|
|
|
-
|
|
|
-/*
|
|
|
- * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting
|
|
|
- * by 48 gives us 16 bits for HZ while keeping the accuracy good even
|
|
|
- * for large CPU clock rates.
|
|
|
- */
|
|
|
-#define FIX_SHIFT 48
|
|
|
-
|
|
|
-/* lump static variables together for more efficient access: */
|
|
|
-static struct {
|
|
|
- /* cycle counter last time it got invoked */
|
|
|
- __u32 last_time;
|
|
|
- /* ticks/cycle * 2^48 */
|
|
|
- unsigned long scaled_ticks_per_cycle;
|
|
|
- /* partial unused tick */
|
|
|
- unsigned long partial_tick;
|
|
|
-} state;
|
|
|
-
|
|
|
unsigned long est_cycle_freq;
|
|
|
|
|
|
#ifdef CONFIG_IRQ_WORK
|
|
@@ -108,109 +78,156 @@ static inline __u32 rpcc(void)
|
|
|
return __builtin_alpha_rpcc();
|
|
|
}
|
|
|
|
|
|
-int update_persistent_clock(struct timespec now)
|
|
|
-{
|
|
|
- return set_rtc_mmss(now.tv_sec);
|
|
|
-}
|
|
|
|
|
|
-void read_persistent_clock(struct timespec *ts)
|
|
|
+
|
|
|
+/*
|
|
|
+ * The RTC as a clock_event_device primitive.
|
|
|
+ */
|
|
|
+
|
|
|
+static DEFINE_PER_CPU(struct clock_event_device, cpu_ce);
|
|
|
+
|
|
|
+irqreturn_t
|
|
|
+rtc_timer_interrupt(int irq, void *dev)
|
|
|
{
|
|
|
- unsigned int year, mon, day, hour, min, sec, epoch;
|
|
|
-
|
|
|
- sec = CMOS_READ(RTC_SECONDS);
|
|
|
- min = CMOS_READ(RTC_MINUTES);
|
|
|
- hour = CMOS_READ(RTC_HOURS);
|
|
|
- day = CMOS_READ(RTC_DAY_OF_MONTH);
|
|
|
- mon = CMOS_READ(RTC_MONTH);
|
|
|
- year = CMOS_READ(RTC_YEAR);
|
|
|
-
|
|
|
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
|
|
- sec = bcd2bin(sec);
|
|
|
- min = bcd2bin(min);
|
|
|
- hour = bcd2bin(hour);
|
|
|
- day = bcd2bin(day);
|
|
|
- mon = bcd2bin(mon);
|
|
|
- year = bcd2bin(year);
|
|
|
- }
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
|
|
|
|
|
- /* PC-like is standard; used for year >= 70 */
|
|
|
- epoch = 1900;
|
|
|
- if (year < 20)
|
|
|
- epoch = 2000;
|
|
|
- else if (year >= 20 && year < 48)
|
|
|
- /* NT epoch */
|
|
|
- epoch = 1980;
|
|
|
- else if (year >= 48 && year < 70)
|
|
|
- /* Digital UNIX epoch */
|
|
|
- epoch = 1952;
|
|
|
+ /* Don't run the hook for UNUSED or SHUTDOWN. */
|
|
|
+ if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC))
|
|
|
+ ce->event_handler(ce);
|
|
|
|
|
|
- printk(KERN_INFO "Using epoch = %d\n", epoch);
|
|
|
+ if (test_irq_work_pending()) {
|
|
|
+ clear_irq_work_pending();
|
|
|
+ irq_work_run();
|
|
|
+ }
|
|
|
|
|
|
- if ((year += epoch) < 1970)
|
|
|
- year += 100;
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
|
|
|
- ts->tv_sec = mktime(year, mon, day, hour, min, sec);
|
|
|
- ts->tv_nsec = 0;
|
|
|
+static void
|
|
|
+rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
|
|
+{
|
|
|
+ /* The mode member of CE is updated in generic code.
|
|
|
+ Since we only support periodic events, nothing to do. */
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
|
|
|
+{
|
|
|
+ /* This hook is for oneshot mode, which we don't support. */
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+static void __init
|
|
|
+init_rtc_clockevent(void)
|
|
|
+{
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
|
|
+
|
|
|
+ *ce = (struct clock_event_device){
|
|
|
+ .name = "rtc",
|
|
|
+ .features = CLOCK_EVT_FEAT_PERIODIC,
|
|
|
+ .rating = 100,
|
|
|
+ .cpumask = cpumask_of(cpu),
|
|
|
+ .set_mode = rtc_ce_set_mode,
|
|
|
+ .set_next_event = rtc_ce_set_next_event,
|
|
|
+ };
|
|
|
|
|
|
+ clockevents_config_and_register(ce, CONFIG_HZ, 0, 0);
|
|
|
+}
|
|
|
|
|
|
+
|
|
|
/*
|
|
|
- * timer_interrupt() needs to keep up the real-time clock,
|
|
|
- * as well as call the "xtime_update()" routine every clocktick
|
|
|
+ * The QEMU clock as a clocksource primitive.
|
|
|
*/
|
|
|
-irqreturn_t timer_interrupt(int irq, void *dev)
|
|
|
+
|
|
|
+static cycle_t
|
|
|
+qemu_cs_read(struct clocksource *cs)
|
|
|
{
|
|
|
- unsigned long delta;
|
|
|
- __u32 now;
|
|
|
- long nticks;
|
|
|
+ return qemu_get_vmtime();
|
|
|
+}
|
|
|
|
|
|
-#ifndef CONFIG_SMP
|
|
|
- /* Not SMP, do kernel PC profiling here. */
|
|
|
- profile_tick(CPU_PROFILING);
|
|
|
-#endif
|
|
|
+static struct clocksource qemu_cs = {
|
|
|
+ .name = "qemu",
|
|
|
+ .rating = 400,
|
|
|
+ .read = qemu_cs_read,
|
|
|
+ .mask = CLOCKSOURCE_MASK(64),
|
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
|
+ .max_idle_ns = LONG_MAX
|
|
|
+};
|
|
|
|
|
|
- /*
|
|
|
- * Calculate how many ticks have passed since the last update,
|
|
|
- * including any previous partial leftover. Save any resulting
|
|
|
- * fraction for the next pass.
|
|
|
- */
|
|
|
- now = rpcc();
|
|
|
- delta = now - state.last_time;
|
|
|
- state.last_time = now;
|
|
|
- delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
|
|
|
- state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
|
|
|
- nticks = delta >> FIX_SHIFT;
|
|
|
|
|
|
- if (nticks)
|
|
|
- xtime_update(nticks);
|
|
|
+/*
|
|
|
+ * The QEMU alarm as a clock_event_device primitive.
|
|
|
+ */
|
|
|
|
|
|
- if (test_irq_work_pending()) {
|
|
|
- clear_irq_work_pending();
|
|
|
- irq_work_run();
|
|
|
- }
|
|
|
+static void
|
|
|
+qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
|
|
+{
|
|
|
+ /* The mode member of CE is updated for us in generic code.
|
|
|
+ Just make sure that the event is disabled. */
|
|
|
+ qemu_set_alarm_abs(0);
|
|
|
+}
|
|
|
|
|
|
-#ifndef CONFIG_SMP
|
|
|
- while (nticks--)
|
|
|
- update_process_times(user_mode(get_irq_regs()));
|
|
|
-#endif
|
|
|
+static int
|
|
|
+qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
|
|
|
+{
|
|
|
+ qemu_set_alarm_rel(evt);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
+static irqreturn_t
|
|
|
+qemu_timer_interrupt(int irq, void *dev)
|
|
|
+{
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
|
|
+
|
|
|
+ ce->event_handler(ce);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static void __init
|
|
|
+init_qemu_clockevent(void)
|
|
|
+{
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
|
|
+
|
|
|
+ *ce = (struct clock_event_device){
|
|
|
+ .name = "qemu",
|
|
|
+ .features = CLOCK_EVT_FEAT_ONESHOT,
|
|
|
+ .rating = 400,
|
|
|
+ .cpumask = cpumask_of(cpu),
|
|
|
+ .set_mode = qemu_ce_set_mode,
|
|
|
+ .set_next_event = qemu_ce_set_next_event,
|
|
|
+ };
|
|
|
+
|
|
|
+ clockevents_config_and_register(ce, NSEC_PER_SEC, 1000, LONG_MAX);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void __init
|
|
|
common_init_rtc(void)
|
|
|
{
|
|
|
- unsigned char x;
|
|
|
+ unsigned char x, sel = 0;
|
|
|
|
|
|
/* Reset periodic interrupt frequency. */
|
|
|
- x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
|
|
|
- /* Test includes known working values on various platforms
|
|
|
- where 0x26 is wrong; we refuse to change those. */
|
|
|
- if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
|
|
|
- printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
|
|
|
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
|
|
|
+#if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
|
|
|
+ x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
|
|
|
+ /* Test includes known working values on various platforms
|
|
|
+ where 0x26 is wrong; we refuse to change those. */
|
|
|
+ if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
|
|
|
+ sel = RTC_REF_CLCK_32KHZ + 6;
|
|
|
}
|
|
|
+#elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32
|
|
|
+ sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ);
|
|
|
+#else
|
|
|
+# error "Unknown HZ from arch/alpha/Kconfig"
|
|
|
+#endif
|
|
|
+ if (sel) {
|
|
|
+ printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n",
|
|
|
+ CONFIG_HZ, sel);
|
|
|
+ CMOS_WRITE(sel, RTC_FREQ_SELECT);
|
|
|
+ }
|
|
|
|
|
|
/* Turn on periodic interrupts. */
|
|
|
x = CMOS_READ(RTC_CONTROL);
|
|
@@ -233,16 +250,37 @@ common_init_rtc(void)
|
|
|
init_rtc_irq();
|
|
|
}
|
|
|
|
|
|
-unsigned int common_get_rtc_time(struct rtc_time *time)
|
|
|
-{
|
|
|
- return __get_rtc_time(time);
|
|
|
-}
|
|
|
+
|
|
|
+#ifndef CONFIG_ALPHA_WTINT
|
|
|
+/*
|
|
|
+ * The RPCC as a clocksource primitive.
|
|
|
+ *
|
|
|
+ * While we have free-running timecounters running on all CPUs, and we make
|
|
|
+ * a half-hearted attempt in init_rtc_rpcc_info to sync the timecounter
|
|
|
+ * with the wall clock, that initialization isn't kept up-to-date across
|
|
|
+ * different time counters in SMP mode. Therefore we can only use this
|
|
|
+ * method when there's only one CPU enabled.
|
|
|
+ *
|
|
|
+ * When using the WTINT PALcall, the RPCC may shift to a lower frequency,
|
|
|
+ * or stop altogether, while waiting for the interrupt. Therefore we cannot
|
|
|
+ * use this method when WTINT is in use.
|
|
|
+ */
|
|
|
|
|
|
-int common_set_rtc_time(struct rtc_time *time)
|
|
|
+static cycle_t read_rpcc(struct clocksource *cs)
|
|
|
{
|
|
|
- return __set_rtc_time(time);
|
|
|
+ return rpcc();
|
|
|
}
|
|
|
|
|
|
+static struct clocksource clocksource_rpcc = {
|
|
|
+ .name = "rpcc",
|
|
|
+ .rating = 300,
|
|
|
+ .read = read_rpcc,
|
|
|
+ .mask = CLOCKSOURCE_MASK(32),
|
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS
|
|
|
+};
|
|
|
+#endif /* ALPHA_WTINT */
|
|
|
+
|
|
|
+
|
|
|
/* Validate a computed cycle counter result against the known bounds for
|
|
|
the given processor core. There's too much brokenness in the way of
|
|
|
timing hardware for any one method to work everywhere. :-(
|
|
@@ -353,33 +391,6 @@ rpcc_after_update_in_progress(void)
|
|
|
return rpcc();
|
|
|
}
|
|
|
|
|
|
-#ifndef CONFIG_SMP
|
|
|
-/* Until and unless we figure out how to get cpu cycle counters
|
|
|
- in sync and keep them there, we can't use the rpcc. */
|
|
|
-static cycle_t read_rpcc(struct clocksource *cs)
|
|
|
-{
|
|
|
- cycle_t ret = (cycle_t)rpcc();
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static struct clocksource clocksource_rpcc = {
|
|
|
- .name = "rpcc",
|
|
|
- .rating = 300,
|
|
|
- .read = read_rpcc,
|
|
|
- .mask = CLOCKSOURCE_MASK(32),
|
|
|
- .flags = CLOCK_SOURCE_IS_CONTINUOUS
|
|
|
-};
|
|
|
-
|
|
|
-static inline void register_rpcc_clocksource(long cycle_freq)
|
|
|
-{
|
|
|
- clocksource_register_hz(&clocksource_rpcc, cycle_freq);
|
|
|
-}
|
|
|
-#else /* !CONFIG_SMP */
|
|
|
-static inline void register_rpcc_clocksource(long cycle_freq)
|
|
|
-{
|
|
|
-}
|
|
|
-#endif /* !CONFIG_SMP */
|
|
|
-
|
|
|
void __init
|
|
|
time_init(void)
|
|
|
{
|
|
@@ -387,6 +398,15 @@ time_init(void)
|
|
|
unsigned long cycle_freq, tolerance;
|
|
|
long diff;
|
|
|
|
|
|
+ if (alpha_using_qemu) {
|
|
|
+ clocksource_register_hz(&qemu_cs, NSEC_PER_SEC);
|
|
|
+ init_qemu_clockevent();
|
|
|
+
|
|
|
+ timer_irqaction.handler = qemu_timer_interrupt;
|
|
|
+ init_rtc_irq();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/* Calibrate CPU clock -- attempt #1. */
|
|
|
if (!est_cycle_freq)
|
|
|
est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
|
|
@@ -421,100 +441,25 @@ time_init(void)
|
|
|
"and unable to estimate a proper value!\n");
|
|
|
}
|
|
|
|
|
|
- /* From John Bowman <bowman@math.ualberta.ca>: allow the values
|
|
|
- to settle, as the Update-In-Progress bit going low isn't good
|
|
|
- enough on some hardware. 2ms is our guess; we haven't found
|
|
|
- bogomips yet, but this is close on a 500Mhz box. */
|
|
|
- __delay(1000000);
|
|
|
-
|
|
|
-
|
|
|
- if (HZ > (1<<16)) {
|
|
|
- extern void __you_loose (void);
|
|
|
- __you_loose();
|
|
|
- }
|
|
|
-
|
|
|
- register_rpcc_clocksource(cycle_freq);
|
|
|
-
|
|
|
- state.last_time = cc1;
|
|
|
- state.scaled_ticks_per_cycle
|
|
|
- = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
|
|
|
- state.partial_tick = 0L;
|
|
|
+ /* See above for restrictions on using clocksource_rpcc. */
|
|
|
+#ifndef CONFIG_ALPHA_WTINT
|
|
|
+ if (hwrpb->nr_processors == 1)
|
|
|
+ clocksource_register_hz(&clocksource_rpcc, cycle_freq);
|
|
|
+#endif
|
|
|
|
|
|
/* Startup the timer source. */
|
|
|
alpha_mv.init_rtc();
|
|
|
+ init_rtc_clockevent();
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
|
|
|
- * called 500 ms after the second nowtime has started, because when
|
|
|
- * nowtime is written into the registers of the CMOS clock, it will
|
|
|
- * jump to the next second precisely 500 ms later. Check the Motorola
|
|
|
- * MC146818A or Dallas DS12887 data sheet for details.
|
|
|
- *
|
|
|
- * BUG: This routine does not handle hour overflow properly; it just
|
|
|
- * sets the minutes. Usually you won't notice until after reboot!
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
-static int
|
|
|
-set_rtc_mmss(unsigned long nowtime)
|
|
|
+/* Initialize the clock_event_device for secondary cpus. */
|
|
|
+#ifdef CONFIG_SMP
|
|
|
+void __init
|
|
|
+init_clockevent(void)
|
|
|
{
|
|
|
- int retval = 0;
|
|
|
- int real_seconds, real_minutes, cmos_minutes;
|
|
|
- unsigned char save_control, save_freq_select;
|
|
|
-
|
|
|
- /* irq are locally disabled here */
|
|
|
- spin_lock(&rtc_lock);
|
|
|
- /* Tell the clock it's being set */
|
|
|
- save_control = CMOS_READ(RTC_CONTROL);
|
|
|
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
|
|
-
|
|
|
- /* Stop and reset prescaler */
|
|
|
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
|
|
|
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
|
|
-
|
|
|
- cmos_minutes = CMOS_READ(RTC_MINUTES);
|
|
|
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
|
|
|
- cmos_minutes = bcd2bin(cmos_minutes);
|
|
|
-
|
|
|
- /*
|
|
|
- * since we're only adjusting minutes and seconds,
|
|
|
- * don't interfere with hour overflow. This avoids
|
|
|
- * messing with unknown time zones but requires your
|
|
|
- * RTC not to be off by more than 15 minutes
|
|
|
- */
|
|
|
- real_seconds = nowtime % 60;
|
|
|
- real_minutes = nowtime / 60;
|
|
|
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) {
|
|
|
- /* correct for half hour time zone */
|
|
|
- real_minutes += 30;
|
|
|
- }
|
|
|
- real_minutes %= 60;
|
|
|
-
|
|
|
- if (abs(real_minutes - cmos_minutes) < 30) {
|
|
|
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
|
|
- real_seconds = bin2bcd(real_seconds);
|
|
|
- real_minutes = bin2bcd(real_minutes);
|
|
|
- }
|
|
|
- CMOS_WRITE(real_seconds,RTC_SECONDS);
|
|
|
- CMOS_WRITE(real_minutes,RTC_MINUTES);
|
|
|
- } else {
|
|
|
- printk_once(KERN_NOTICE
|
|
|
- "set_rtc_mmss: can't update from %d to %d\n",
|
|
|
- cmos_minutes, real_minutes);
|
|
|
- retval = -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* The following flags have to be released exactly in this order,
|
|
|
- * otherwise the DS12887 (popular MC146818A clone with integrated
|
|
|
- * battery and quartz) will not reset the oscillator and will not
|
|
|
- * update precisely 500 ms later. You won't find this mentioned in
|
|
|
- * the Dallas Semiconductor data sheets, but who believes data
|
|
|
- * sheets anyway ... -- Markus Kuhn
|
|
|
- */
|
|
|
- CMOS_WRITE(save_control, RTC_CONTROL);
|
|
|
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
|
|
|
- spin_unlock(&rtc_lock);
|
|
|
-
|
|
|
- return retval;
|
|
|
+ if (alpha_using_qemu)
|
|
|
+ init_qemu_clockevent();
|
|
|
+ else
|
|
|
+ init_rtc_clockevent();
|
|
|
}
|
|
|
+#endif
|