time.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/kernel/time.c
  3.  *
  4.  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  5.  *  Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 2 as
  9.  * published by the Free Software Foundation.
  10.  *
  11.  *  This file contains the ARM-specific time handling details:
  12.  *  reading the RTC at bootup, etc...
  13.  *
  14.  *  1994-07-02  Alan Modra
  15.  *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
  16.  *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
  17.  *              "A Kernel Model for Precision Timekeeping" by Dave Mills
  18.  */
  19. #include <linux/config.h>
  20. #include <linux/module.h>
  21. #include <linux/sched.h>
  22. #include <linux/kernel.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/time.h>
  25. #include <linux/init.h>
  26. #include <linux/smp.h>
  27. #include <asm/uaccess.h>
  28. #include <asm/io.h>
  29. #include <asm/irq.h>
  30. #include <linux/timex.h>
  31. #include <asm/hardware.h>
  32. extern int setup_arm_irq(int, struct irqaction *);
  33. extern rwlock_t xtime_lock;
  34. extern unsigned long wall_jiffies;
  35. /* change this if you have some constant time drift */
  36. #define USECS_PER_JIFFY (1000000/HZ)
  37. #ifndef BCD_TO_BIN
  38. #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
  39. #endif
  40. #ifndef BIN_TO_BCD
  41. #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
  42. #endif
  43. static int dummy_set_rtc(void)
  44. {
  45. return 0;
  46. }
  47. /*
  48.  * hook for setting the RTC's idea of the current time.
  49.  */
  50. int (*set_rtc)(void) = dummy_set_rtc;
  51. static unsigned long dummy_gettimeoffset(void)
  52. {
  53. return 0;
  54. }
  55. /*
  56.  * hook for getting the time offset.  Note that it is
  57.  * always called with interrupts disabled.
  58.  */
  59. unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
  60. /*
  61.  * Handle kernel profile stuff...
  62.  */
  63. static inline void do_profile(struct pt_regs *regs)
  64. {
  65. if (!user_mode(regs) &&
  66.     prof_buffer &&
  67.     current->pid) {
  68. unsigned long pc = instruction_pointer(regs);
  69. extern int _stext;
  70. pc -= (unsigned long)&_stext;
  71. pc >>= prof_shift;
  72. if (pc >= prof_len)
  73. pc = prof_len - 1;
  74. prof_buffer[pc] += 1;
  75. }
  76. }
  77. static long next_rtc_update;
  78. /*
  79.  * If we have an externally synchronized linux clock, then update
  80.  * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
  81.  * called as close as possible to 500 ms before the new second
  82.  * starts.
  83.  */
  84. static inline void do_set_rtc(void)
  85. {
  86. if (time_status & STA_UNSYNC || set_rtc == NULL)
  87. return;
  88. if (next_rtc_update &&
  89.     time_before(xtime.tv_sec, next_rtc_update))
  90. return;
  91. if (xtime.tv_usec < 50000 - (tick >> 1) &&
  92.     xtime.tv_usec >= 50000 + (tick >> 1))
  93. return;
  94. if (set_rtc())
  95. /*
  96.  * rtc update failed.  Try again in 60s
  97.  */
  98. next_rtc_update = xtime.tv_sec + 60;
  99. else
  100. next_rtc_update = xtime.tv_sec + 660;
  101. }
  102. #ifdef CONFIG_LEDS
  103. #include <asm/leds.h>
  104. static void dummy_leds_event(led_event_t evt)
  105. {
  106. }
  107. void (*leds_event)(led_event_t) = dummy_leds_event;
  108. #ifdef CONFIG_MODULES
  109. EXPORT_SYMBOL(leds_event);
  110. #endif
  111. #endif
  112. #ifdef CONFIG_LEDS_TIMER
  113. static void do_leds(void)
  114. {
  115. static unsigned int count = 50;
  116. if (--count == 0) {
  117. count = 50;
  118. leds_event(led_timer);
  119. }
  120. }
  121. #else
  122. #define do_leds()
  123. #endif
  124. void do_gettimeofday(struct timeval *tv)
  125. {
  126. unsigned long flags;
  127. unsigned long usec, sec;
  128. read_lock_irqsave(&xtime_lock, flags);
  129. usec = gettimeoffset();
  130. {
  131. unsigned long lost = jiffies - wall_jiffies;
  132. if (lost)
  133. usec += lost * USECS_PER_JIFFY;
  134. }
  135. sec = xtime.tv_sec;
  136. usec += xtime.tv_usec;
  137. read_unlock_irqrestore(&xtime_lock, flags);
  138. /* usec may have gone up a lot: be safe */
  139. while (usec >= 1000000) {
  140. usec -= 1000000;
  141. sec++;
  142. }
  143. tv->tv_sec = sec;
  144. tv->tv_usec = usec;
  145. }
  146. void do_settimeofday(struct timeval *tv)
  147. {
  148. write_lock_irq(&xtime_lock);
  149. /* This is revolting. We need to set the xtime.tv_usec
  150.  * correctly. However, the value in this location is
  151.  * is value at the last tick.
  152.  * Discover what correction gettimeofday
  153.  * would have done, and then undo it!
  154.  */
  155. tv->tv_usec -= gettimeoffset();
  156. tv->tv_usec -= (jiffies - wall_jiffies) * USECS_PER_JIFFY;
  157. while (tv->tv_usec < 0) {
  158. tv->tv_usec += 1000000;
  159. tv->tv_sec--;
  160. }
  161. xtime = *tv;
  162. time_adjust = 0; /* stop active adjtime() */
  163. time_status |= STA_UNSYNC;
  164. time_maxerror = NTP_PHASE_LIMIT;
  165. time_esterror = NTP_PHASE_LIMIT;
  166. write_unlock_irq(&xtime_lock);
  167. }
  168. static struct irqaction timer_irq = {
  169. name: "timer",
  170. };
  171. /*
  172.  * Include architecture specific code
  173.  */
  174. #include <asm/arch/time.h>
  175. /*
  176.  * This must cause the timer to start ticking.
  177.  * It doesn't have to set the current time though
  178.  * from an RTC - it can be done later once we have
  179.  * some buses initialised.
  180.  */
  181. void __init time_init(void)
  182. {
  183. xtime.tv_usec = 0;
  184. xtime.tv_sec  = 0;
  185. setup_timer();
  186. }