root/arch/mips/kernel/time.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_slow_gettimeoffset
  2. do_gettimeofday
  3. do_settimeofday
  4. set_rtc_mmss
  5. timer_interrupt
  6. mktime
  7. time_init

   1 /*
   2  *  linux/arch/mips/kernel/time.c
   3  *
   4  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
   5  *
   6  * This file contains the time handling details for PC-style clocks as
   7  * found in some MIPS systems.
   8  */
   9 #include <linux/errno.h>
  10 #include <linux/sched.h>
  11 #include <linux/kernel.h>
  12 #include <linux/param.h>
  13 #include <linux/string.h>
  14 #include <linux/mm.h>
  15 
  16 #include <asm/segment.h>
  17 #include <asm/io.h>
  18 
  19 #include <linux/mc146818rtc.h>
  20 #include <linux/timex.h>
  21 
  22 #define TIMER_IRQ 0
  23 
  24 /* This function must be called with interrupts disabled 
  25  * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
  26  * 
  27  * However, the pc-audio speaker driver changes the divisor so that
  28  * it gets interrupted rather more often - it loads 64 into the
  29  * counter rather than 11932! This has an adverse impact on
  30  * do_gettimeoffset() -- it stops working! What is also not
  31  * good is that the interval that our timer function gets called
  32  * is no longer 10.0002 ms, but 9.9767 ms. To get around this
  33  * would require using a different timing source. Maybe someone
  34  * could use the RTC - I know that this can interrupt at frequencies
  35  * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
  36  * it so that at startup, the timer code in sched.c would select
  37  * using either the RTC or the 8253 timer. The decision would be
  38  * based on whether there was any other device around that needed
  39  * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
  40  * and then do some jiggery to have a version of do_timer that 
  41  * advanced the clock by 1/1024 s. Every time that reached over 1/100
  42  * of a second, then do all the old code. If the time was kept correct
  43  * then do_gettimeoffset could just return 0 - there is no low order
  44  * divider that can be accessed.
  45  *
  46  * Ideally, you would be able to use the RTC for the speaker driver,
  47  * but it appears that the speaker driver really needs interrupt more
  48  * often than every 120 us or so.
  49  *
  50  * Anyway, this needs more thought....          pjsg (1993-08-28)
  51  * 
  52  * If you are really that interested, you should be reading
  53  * comp.protocols.time.ntp!
  54  */
  55 
  56 #define TICK_SIZE tick
  57 
  58 static unsigned long do_slow_gettimeoffset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         int count;
  61         unsigned long offset = 0;
  62 
  63         /* timer count may underflow right here */
  64         outb_p(0x00, 0x43);     /* latch the count ASAP */
  65         count = inb_p(0x40);    /* read the latched count */
  66         count |= inb(0x40) << 8;
  67         /* we know probability of underflow is always MUCH less than 1% */
  68         if (count > (LATCH - LATCH/100)) {
  69                 /* check for pending timer interrupt */
  70                 outb_p(0x0a, 0x20);
  71                 if (inb(0x20) & 1)
  72                         offset = TICK_SIZE;
  73         }
  74         count = ((LATCH-1) - count) * TICK_SIZE;
  75         count = (count + LATCH/2) / LATCH;
  76         return offset + count;
  77 }
  78 
  79 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
  80 
  81 /*
  82  * This version of gettimeofday has near microsecond resolution.
  83  */
  84 void do_gettimeofday(struct timeval *tv)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         unsigned long flags;
  87 
  88         save_flags(flags);
  89         cli();
  90         *tv = xtime;
  91         tv->tv_usec += do_gettimeoffset();
  92         if (tv->tv_usec >= 1000000) {
  93                 tv->tv_usec -= 1000000;
  94                 tv->tv_sec++;
  95         }
  96         restore_flags(flags);
  97 }
  98 
  99 void do_settimeofday(struct timeval *tv)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         cli();
 102         /* This is revolting. We need to set the xtime.tv_usec
 103          * correctly. However, the value in this location is
 104          * is value at the last tick.
 105          * Discover what correction gettimeofday
 106          * would have done, and then undo it!
 107          */
 108         tv->tv_usec -= do_gettimeoffset();
 109 
 110         if (tv->tv_usec < 0) {
 111                 tv->tv_usec += 1000000;
 112                 tv->tv_sec--;
 113         }
 114 
 115         xtime = *tv;
 116         time_state = TIME_BAD;
 117         time_maxerror = 0x70000000;
 118         time_esterror = 0x70000000;
 119         sti();
 120 }
 121 
 122 /*
 123  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
 124  * called 500 ms after the second nowtime has started, because when
 125  * nowtime is written into the registers of the CMOS clock, it will
 126  * jump to the next second precisely 500 ms later. Check the Motorola
 127  * MC146818A or Dallas DS12887 data sheet for details.
 128  */
 129 static int set_rtc_mmss(unsigned long nowtime)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         int retval = 0;
 132         int real_seconds, real_minutes, cmos_minutes;
 133         unsigned char save_control, save_freq_select;
 134 
 135         save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
 136         CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 137 
 138         save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
 139         CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 140 
 141         cmos_minutes = CMOS_READ(RTC_MINUTES);
 142         if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 143                 BCD_TO_BIN(cmos_minutes);
 144 
 145         /*
 146          * since we're only adjusting minutes and seconds,
 147          * don't interfere with hour overflow. This avoids
 148          * messing with unknown time zones but requires your
 149          * RTC not to be off by more than 15 minutes
 150          */
 151         real_seconds = nowtime % 60;
 152         real_minutes = nowtime / 60;
 153         if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
 154                 real_minutes += 30;             /* correct for half hour time zone */
 155         real_minutes %= 60;
 156 
 157         if (abs(real_minutes - cmos_minutes) < 30) {
 158                 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
 159                         BIN_TO_BCD(real_seconds);
 160                         BIN_TO_BCD(real_minutes);
 161                 }
 162                 CMOS_WRITE(real_seconds,RTC_SECONDS);
 163                 CMOS_WRITE(real_minutes,RTC_MINUTES);
 164         } else
 165                 retval = -1;
 166 
 167         /* The following flags have to be released exactly in this order,
 168          * otherwise the DS12887 (popular MC146818A clone with integrated
 169          * battery and crystal) will not reset the oscillator and will not
 170          * update precisely 500 ms later. You won't find this mentioned in
 171          * the Dallas Semiconductor data sheets, but who believes data
 172          * sheets anyway ...                           -- Markus Kuhn
 173          */
 174         CMOS_WRITE(save_control, RTC_CONTROL);
 175         CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 176 
 177         return retval;
 178 }
 179 
 180 /* last time the cmos clock got updated */
 181 static long last_rtc_update = 0;
 182 
 183 /*
 184  * timer_interrupt() needs to keep up the real-time clock,
 185  * as well as call the "do_timer()" routine every clocktick
 186  */
 187 static void timer_interrupt(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189         do_timer(regs);
 190 
 191         /*
 192          * If we have an externally synchronized Linux clock, then update
 193          * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
 194          * called as close as possible to 500 ms before the new second starts.
 195          */
 196         if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
 197             xtime.tv_usec > 500000 - (tick >> 1) &&
 198             xtime.tv_usec < 500000 + (tick >> 1))
 199           if (set_rtc_mmss(xtime.tv_sec) == 0)
 200             last_rtc_update = xtime.tv_sec;
 201           else
 202             last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 203         /* As we return to user mode fire off the other CPU schedulers.. this is 
 204            basically because we don't yet share IRQ's around. This message is
 205            rigged to be safe on the 386 - basically its a hack, so don't look
 206            closely for now.. */
 207         smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
 208 }
 209 
 210 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 211  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 212  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 213  *
 214  * [For the Julian calendar (which was used in Russia before 1917,
 215  * Britain & colonies before 1752, anywhere else before 1582,
 216  * and is still in use by some communities) leave out the
 217  * -year/100+year/400 terms, and add 10.]
 218  *
 219  * This algorithm was first published by Gauss (I think).
 220  *
 221  * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 222  * machines were long is 32-bit! (However, as time_t is signed, we
 223  * will already get problems at other places on 2038-01-19 03:14:08)
 224  */
 225 static inline unsigned long mktime(unsigned int year, unsigned int mon,
     /* [previous][next][first][last][top][bottom][index][help] */
 226         unsigned int day, unsigned int hour,
 227         unsigned int min, unsigned int sec)
 228 {
 229         if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
 230                 mon += 12;      /* Puts Feb last since it has leap day */
 231                 year -= 1;
 232         }
 233         return (((
 234             (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
 235               year*365 - 719499
 236             )*24 + hour /* now have hours */
 237            )*60 + min /* now have minutes */
 238           )*60 + sec; /* finally seconds */
 239 }
 240 
 241 void time_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 242 {
 243         void (*irq_handler)(int, struct pt_regs *);
 244         unsigned int year, mon, day, hour, min, sec;
 245         int i;
 246 
 247         /* The Linux interpretation of the CMOS clock register contents:
 248          * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
 249          * RTC registers show the second which has precisely just started.
 250          * Let's hope other operating systems interpret the RTC the same way.
 251          */
 252         /* read RTC exactly on falling edge of update flag */
 253         for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
 254                 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
 255                         break;
 256         for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
 257                 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
 258                         break;
 259         do { /* Isn't this overkill ? UIP above should guarantee consistency */
 260                 sec = CMOS_READ(RTC_SECONDS);
 261                 min = CMOS_READ(RTC_MINUTES);
 262                 hour = CMOS_READ(RTC_HOURS);
 263                 day = CMOS_READ(RTC_DAY_OF_MONTH);
 264                 mon = CMOS_READ(RTC_MONTH);
 265                 year = CMOS_READ(RTC_YEAR);
 266         } while (sec != CMOS_READ(RTC_SECONDS));
 267         if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 268           {
 269             BCD_TO_BIN(sec);
 270             BCD_TO_BIN(min);
 271             BCD_TO_BIN(hour);
 272             BCD_TO_BIN(day);
 273             BCD_TO_BIN(mon);
 274             BCD_TO_BIN(year);
 275           }
 276         if ((year += 1900) < 1970)
 277                 year += 100;
 278         xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 279         xtime.tv_usec = 0;
 280 
 281         /* FIXME: If we have the CPU hardware time counters, use them */
 282         irq_handler = timer_interrupt;  
 283 
 284         if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
 285                 panic("Could not allocate timer IRQ!");
 286 }

/* [previous][next][first][last][top][bottom][index][help] */