root/arch/sparc/kernel/time.c

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

DEFINITIONS

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

   1 /* $Id: time.c,v 1.4 1995/11/25 03:29:31 davem Exp $
   2  * linux/arch/sparc/kernel/time.c
   3  *
   4  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5  *
   6  * This file handles the Sparc specific time handling details.
   7  */
   8 #include <linux/errno.h>
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 #include <linux/param.h>
  12 #include <linux/string.h>
  13 #include <linux/mm.h>
  14 #include <linux/timex.h>
  15 
  16 #include <asm/oplib.h>
  17 #include <asm/segment.h>
  18 #include <asm/timer.h>
  19 #include <asm/mostek.h>
  20 
  21 #define TIMER_IRQ  10    /* Also at level 14, but we ignore that one. */
  22 
  23 static int set_rtc_mmss(unsigned long);
  24 
  25 /*
  26  * timer_interrupt() needs to keep up the real-time clock,
  27  * as well as call the "do_timer()" routine every clocktick
  28  */
  29 void timer_interrupt(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         /* last time the cmos clock got updated */
  32         static long last_rtc_update=0;
  33         volatile unsigned int clear_intr;
  34 
  35         /* First, clear the interrupt. */
  36         clear_intr = *master_l10_limit;
  37 
  38         do_timer(regs);
  39 
  40         /* XXX I don't know if this is right for the Sparc yet. XXX */
  41         if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
  42             xtime.tv_usec > 500000 - (tick >> 1) &&
  43             xtime.tv_usec < 500000 + (tick >> 1))
  44           if (set_rtc_mmss(xtime.tv_sec) == 0)
  45             last_rtc_update = xtime.tv_sec;
  46           else
  47             last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
  48 }
  49 
  50 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  51  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  52  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  53  *
  54  * [For the Julian calendar (which was used in Russia before 1917,
  55  * Britain & colonies before 1752, anywhere else before 1582,
  56  * and is still in use by some communities) leave out the
  57  * -year/100+year/400 terms, and add 10.]
  58  *
  59  * This algorithm was first published by Gauss (I think).
  60  *
  61  * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  62  * machines were long is 32-bit! (However, as time_t is signed, we
  63  * will already get problems at other places on 2038-01-19 03:14:08)
  64  */
  65 static inline unsigned long mktime(unsigned int year, unsigned int mon,
     /* [previous][next][first][last][top][bottom][index][help] */
  66         unsigned int day, unsigned int hour,
  67         unsigned int min, unsigned int sec)
  68 {
  69         if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
  70                 mon += 12;      /* Puts Feb last since it has leap day */
  71                 year -= 1;
  72         }
  73         return (((
  74             (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
  75               year*365 - 719499
  76             )*24 + hour /* now have hours */
  77            )*60 + min /* now have minutes */
  78           )*60 + sec; /* finally seconds */
  79 }
  80 
  81 #ifndef BCD_TO_BIN
  82 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
  83 #endif
  84 
  85 #ifndef BIN_TO_BCD
  86 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
  87 #endif
  88 
  89 void time_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         unsigned int year, mon, day, hour, min, sec;
  92         struct mostek48t02 *mregs;
  93 
  94         request_irq(TIMER_IRQ, timer_interrupt, SA_INTERRUPT, "timer");
  95         mregs = mstk48t02_regs;
  96         if(!mregs) {
  97                 prom_printf("Something wrong, clock regs not mapped yet.\n");
  98                 prom_halt();
  99         }               
 100         mregs->creg |= MSTK_CREG_READ;
 101         sec = BCD_TO_BIN(mregs->sec);
 102         min = BCD_TO_BIN(mregs->min);
 103         hour = BCD_TO_BIN(mregs->hour);
 104         day = BCD_TO_BIN(mregs->dom);
 105         mon = BCD_TO_BIN(mregs->mnth);
 106         year = (BCD_TO_BIN(mregs->yr) + MSTK_YR_ZERO);
 107         xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 108         xtime.tv_usec = 0;
 109         mregs->creg &= ~MSTK_CREG_READ;
 110         return;
 111 }
 112 /* Nothing fancy on the Sparc yet. */
 113 void do_gettimeofday(struct timeval *tv)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         unsigned long flags;
 116 
 117         save_flags(flags);
 118         cli();
 119         *tv = xtime;
 120         restore_flags(flags);
 121 }
 122 
 123 void do_settimeofday(struct timeval *tv)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         cli();
 126         xtime = *tv;
 127         time_state = TIME_BAD;
 128         time_maxerror = 0x70000000;
 129         time_esterror = 0x70000000;
 130         sti();
 131 }
 132 
 133 static int set_rtc_mmss(unsigned long nowtime)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135         int retval = 0;
 136         int real_seconds, real_minutes, mostek_minutes;
 137         struct mostek48t02 *mregs = mstk48t02_regs;
 138 
 139         if(!mregs)
 140                 retval = -1;
 141         else {
 142                 mregs->creg |= MSTK_CREG_READ;
 143                 mostek_minutes = BCD_TO_BIN(mregs->min);
 144                 mregs->creg &= ~MSTK_CREG_READ;
 145 
 146                 real_seconds = nowtime % 60;
 147                 real_minutes = nowtime / 60;
 148                 if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
 149                         real_minutes += 30;
 150                 real_minutes %= 60;
 151                 if (abs(real_minutes - mostek_minutes) < 30) {
 152                         mregs->creg |= MSTK_CREG_WRITE;
 153                         mregs->sec = real_seconds;
 154                         mregs->min = real_minutes;
 155                         mregs->creg &= ~MSTK_CREG_WRITE;
 156                 } else
 157                         retval = -1;
 158         }
 159 
 160         return retval;
 161 }

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