prep_time.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  *  arch/ppc/platforms/prep_time.c
  6.  *
  7.  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  8.  *
  9.  * Adapted for PowerPC (PReP) by Gary Thomas
  10.  * Modified by Cort Dougan (cort@cs.nmt.edu).
  11.  * Copied and modified from arch/i386/kernel/time.c
  12.  */
  13. #include <linux/errno.h>
  14. #include <linux/sched.h>
  15. #include <linux/kernel.h>
  16. #include <linux/param.h>
  17. #include <linux/string.h>
  18. #include <linux/mm.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/time.h>
  21. #include <linux/timex.h>
  22. #include <linux/kernel_stat.h>
  23. #include <linux/init.h>
  24. #include <asm/sections.h>
  25. #include <asm/segment.h>
  26. #include <asm/io.h>
  27. #include <asm/processor.h>
  28. #include <asm/machdep.h>
  29. #include <asm/prep_nvram.h>
  30. #include <asm/mk48t59.h>
  31. #include <asm/time.h>
  32. extern spinlock_t rtc_lock;
  33. /*
  34.  * The motorola uses the m48t18 rtc (includes DS1643) whose registers
  35.  * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
  36.  * rtc (ds1386) which has regs at addr 0-d).  The intel gets
  37.  * past this because the bios emulates the mc146818.
  38.  *
  39.  * Why in the world did they have to use different clocks?
  40.  *
  41.  * Right now things are hacked to check which machine we're on then
  42.  * use the appropriate macro.  This is very very ugly and I should
  43.  * probably have a function that checks which machine we're on then
  44.  * does things correctly transparently or a function pointer which
  45.  * is setup at boot time to use the correct addresses.
  46.  * -- Cort
  47.  */
  48. /*
  49.  * Set the hardware clock. -- Cort
  50.  */
  51. __prep
  52. int mc146818_set_rtc_time(unsigned long nowtime)
  53. {
  54. unsigned char save_control, save_freq_select;
  55. struct rtc_time tm;
  56. spin_lock(&rtc_lock);
  57. to_tm(nowtime, &tm);
  58. /* tell the clock it's being set */
  59. save_control = CMOS_READ(RTC_CONTROL);
  60. CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
  61. /* stop and reset prescaler */
  62. save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
  63. CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
  64.         tm.tm_year = (tm.tm_year - 1900) % 100;
  65. if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  66. BIN_TO_BCD(tm.tm_sec);
  67. BIN_TO_BCD(tm.tm_min);
  68. BIN_TO_BCD(tm.tm_hour);
  69. BIN_TO_BCD(tm.tm_mon);
  70. BIN_TO_BCD(tm.tm_mday);
  71. BIN_TO_BCD(tm.tm_year);
  72. }
  73. CMOS_WRITE(tm.tm_sec,  RTC_SECONDS);
  74. CMOS_WRITE(tm.tm_min,  RTC_MINUTES);
  75. CMOS_WRITE(tm.tm_hour, RTC_HOURS);
  76. CMOS_WRITE(tm.tm_mon,  RTC_MONTH);
  77. CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
  78. CMOS_WRITE(tm.tm_year, RTC_YEAR);
  79. /* The following flags have to be released exactly in this order,
  80.  * otherwise the DS12887 (popular MC146818A clone with integrated
  81.  * battery and quartz) will not reset the oscillator and will not
  82.  * update precisely 500 ms later. You won't find this mentioned in
  83.  * the Dallas Semiconductor data sheets, but who believes data
  84.  * sheets anyway ...                           -- Markus Kuhn
  85.  */
  86. CMOS_WRITE(save_control,     RTC_CONTROL);
  87. CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
  88. spin_unlock(&rtc_lock);
  89. return 0;
  90. }
  91. __prep
  92. unsigned long mc146818_get_rtc_time(void)
  93. {
  94. unsigned int year, mon, day, hour, min, sec;
  95. int uip, i;
  96. /* The Linux interpretation of the CMOS clock register contents:
  97.  * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
  98.  * RTC registers show the second which has precisely just started.
  99.  * Let's hope other operating systems interpret the RTC the same way.
  100.  */
  101. /* Since the UIP flag is set for about 2.2 ms and the clock
  102.  * is typically written with a precision of 1 jiffy, trying
  103.  * to obtain a precision better than a few milliseconds is 
  104.  * an illusion. Only consistency is interesting, this also
  105.  * allows to use the routine for /dev/rtc without a potential
  106.  * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
  107.  */
  108. for ( i = 0; i<1000000; i++) {
  109. uip = CMOS_READ(RTC_FREQ_SELECT);
  110. sec = CMOS_READ(RTC_SECONDS);
  111. min = CMOS_READ(RTC_MINUTES);
  112. hour = CMOS_READ(RTC_HOURS);
  113. day = CMOS_READ(RTC_DAY_OF_MONTH);
  114. mon = CMOS_READ(RTC_MONTH);
  115. year = CMOS_READ(RTC_YEAR);
  116. uip |= CMOS_READ(RTC_FREQ_SELECT);
  117. if ((uip & RTC_UIP)==0) break;
  118. }
  119. if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
  120.     || RTC_ALWAYS_BCD)
  121. {
  122. BCD_TO_BIN(sec);
  123. BCD_TO_BIN(min);
  124. BCD_TO_BIN(hour);
  125. BCD_TO_BIN(day);
  126. BCD_TO_BIN(mon);
  127. BCD_TO_BIN(year);
  128. }
  129. if ((year += 1900) < 1970)
  130. year += 100;
  131. return mktime(year, mon, day, hour, min, sec);
  132. }
  133. __prep
  134. int mk48t59_set_rtc_time(unsigned long nowtime)
  135. {
  136. unsigned char save_control;
  137. struct rtc_time tm;
  138. spin_lock(&rtc_lock);
  139. to_tm(nowtime, &tm);
  140. /* tell the clock it's being written */
  141. save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
  142. ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
  143.      (save_control | MK48T59_RTC_CA_WRITE));
  144.         tm.tm_year = (tm.tm_year - 1900) % 100;
  145. BIN_TO_BCD(tm.tm_sec);
  146. BIN_TO_BCD(tm.tm_min);
  147. BIN_TO_BCD(tm.tm_hour);
  148. BIN_TO_BCD(tm.tm_mon);
  149. BIN_TO_BCD(tm.tm_mday);
  150. BIN_TO_BCD(tm.tm_year);
  151. ppc_md.nvram_write_val(MK48T59_RTC_SECONDS,      tm.tm_sec);
  152. ppc_md.nvram_write_val(MK48T59_RTC_MINUTES,      tm.tm_min);
  153. ppc_md.nvram_write_val(MK48T59_RTC_HOURS,        tm.tm_hour);
  154. ppc_md.nvram_write_val(MK48T59_RTC_MONTH,        tm.tm_mon);
  155. ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
  156. ppc_md.nvram_write_val(MK48T59_RTC_YEAR,         tm.tm_year);
  157. /* Turn off the write bit. */
  158. ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
  159. spin_unlock(&rtc_lock);
  160. return 0;
  161. }
  162. __prep
  163. unsigned long mk48t59_get_rtc_time(void)
  164. {
  165. unsigned char save_control;
  166. unsigned int year, mon, day, hour, min, sec;
  167. /* Simple: freeze the clock, read it and allow updates again */
  168. save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
  169. save_control &= ~MK48T59_RTC_CA_READ;
  170. ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
  171. /* Set the register to read the value. */
  172. ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
  173.      (save_control | MK48T59_RTC_CA_READ));
  174. sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
  175. min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
  176. hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
  177. day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
  178. mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
  179. year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
  180. /* Let the time values change again. */
  181. ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
  182. BCD_TO_BIN(sec);
  183. BCD_TO_BIN(min);
  184. BCD_TO_BIN(hour);
  185. BCD_TO_BIN(day);
  186. BCD_TO_BIN(mon);
  187. BCD_TO_BIN(year);
  188. year = year + 1900;
  189. if (year < 1970) {
  190. year += 100;
  191. }
  192. return mktime(year, mon, day, hour, min, sec);
  193. }