linux/arch/cris/kernel/time.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/cris/kernel/time.c
   3 *
   4 *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
   5 *  Copyright (C) 1999, 2000, 2001 Axis Communications AB
   6 *
   7 * 1994-07-02    Alan Modra
   8 *      fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
   9 * 1995-03-26    Markus Kuhn
  10 *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
  11 *      precision CMOS clock update
  12 * 1996-05-03    Ingo Molnar
  13 *      fixed time warps in do_[slow|fast]_gettimeoffset()
  14 * 1997-09-10   Updated NTP code according to technical memorandum Jan '96
  15 *              "A Kernel Model for Precision Timekeeping" by Dave Mills
  16 *
  17 * Linux/CRIS specific code:
  18 *
  19 * Authors:    Bjorn Wesen
  20 *             Johan Adolfsson
  21 *
  22 */
  23
  24#include <asm/rtc.h>
  25#include <linux/errno.h>
  26#include <linux/module.h>
  27#include <linux/param.h>
  28#include <linux/jiffies.h>
  29#include <linux/bcd.h>
  30#include <linux/timex.h>
  31#include <linux/init.h>
  32#include <linux/profile.h>
  33#include <linux/sched.h>        /* just for sched_clock() - funny that */
  34
  35int have_rtc;  /* used to remember if we have an RTC or not */;
  36
  37#define TICK_SIZE tick
  38
  39extern unsigned long loops_per_jiffy; /* init/main.c */
  40unsigned long loops_per_usec;
  41
  42
  43#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
  44extern unsigned long do_slow_gettimeoffset(void);
  45static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
  46
  47u32 arch_gettimeoffset(void)
  48{
  49       return do_gettimeoffset() * 1000;
  50}
  51#endif
  52
  53/*
  54 * BUG: This routine does not handle hour overflow properly; it just
  55 *      sets the minutes. Usually you'll only notice that after reboot!
  56 */
  57
  58int set_rtc_mmss(unsigned long nowtime)
  59{
  60        int retval = 0;
  61        int real_seconds, real_minutes, cmos_minutes;
  62
  63        printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime);
  64
  65        if(!have_rtc)
  66                return 0;
  67
  68        cmos_minutes = CMOS_READ(RTC_MINUTES);
  69        cmos_minutes = bcd2bin(cmos_minutes);
  70
  71        /*
  72         * since we're only adjusting minutes and seconds,
  73         * don't interfere with hour overflow. This avoids
  74         * messing with unknown time zones but requires your
  75         * RTC not to be off by more than 15 minutes
  76         */
  77        real_seconds = nowtime % 60;
  78        real_minutes = nowtime / 60;
  79        if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
  80                real_minutes += 30;             /* correct for half hour time zone */
  81        real_minutes %= 60;
  82
  83        if (abs(real_minutes - cmos_minutes) < 30) {
  84                real_seconds = bin2bcd(real_seconds);
  85                real_minutes = bin2bcd(real_minutes);
  86                CMOS_WRITE(real_seconds,RTC_SECONDS);
  87                CMOS_WRITE(real_minutes,RTC_MINUTES);
  88        } else {
  89                printk_once(KERN_NOTICE
  90                       "set_rtc_mmss: can't update from %d to %d\n",
  91                       cmos_minutes, real_minutes);
  92                retval = -1;
  93        }
  94
  95        return retval;
  96}
  97
  98/* grab the time from the RTC chip */
  99
 100unsigned long
 101get_cmos_time(void)
 102{
 103        unsigned int year, mon, day, hour, min, sec;
 104        if(!have_rtc)
 105                return 0;
 106
 107        sec = CMOS_READ(RTC_SECONDS);
 108        min = CMOS_READ(RTC_MINUTES);
 109        hour = CMOS_READ(RTC_HOURS);
 110        day = CMOS_READ(RTC_DAY_OF_MONTH);
 111        mon = CMOS_READ(RTC_MONTH);
 112        year = CMOS_READ(RTC_YEAR);
 113
 114        sec = bcd2bin(sec);
 115        min = bcd2bin(min);
 116        hour = bcd2bin(hour);
 117        day = bcd2bin(day);
 118        mon = bcd2bin(mon);
 119        year = bcd2bin(year);
 120
 121        if ((year += 1900) < 1970)
 122                year += 100;
 123
 124        return mktime(year, mon, day, hour, min, sec);
 125}
 126
 127
 128int update_persistent_clock(struct timespec now)
 129{
 130        return set_rtc_mmss(now.tv_sec);
 131}
 132
 133void read_persistent_clock(struct timespec *ts)
 134{
 135        ts->tv_sec = get_cmos_time();
 136        ts->tv_nsec = 0;
 137}
 138
 139
 140extern void cris_profile_sample(struct pt_regs* regs);
 141
 142void
 143cris_do_profile(struct pt_regs* regs)
 144{
 145
 146#ifdef CONFIG_SYSTEM_PROFILER
 147        cris_profile_sample(regs);
 148#endif
 149
 150#ifdef CONFIG_PROFILING
 151        profile_tick(CPU_PROFILING);
 152#endif
 153}
 154
 155unsigned long long sched_clock(void)
 156{
 157        return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) +
 158                get_ns_in_jiffie();
 159}
 160
 161static int
 162__init init_udelay(void)
 163{
 164        loops_per_usec = (loops_per_jiffy * HZ) / 1000000;
 165        return 0;
 166}
 167
 168__initcall(init_udelay);
 169