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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright 2001 MontaVista Software Inc.
  3.  * Author: jsun@mvista.com or jsun@junsun.net
  4.  *
  5.  * arch/mips/ddb5xxx/common/rtc_ds1386.c
  6.  *     low-level RTC hookups for s for Dallas 1396 chip.
  7.  *
  8.  * This program is free software; you can redistribute  it and/or modify it
  9.  * under  the terms of  the GNU General  Public License as published by the
  10.  * Free Software Foundation;  either version 2 of the  License, or (at your
  11.  * option) any later version.
  12.  */
  13. /*
  14.  * This file exports a function, rtc_ds1386_init(), which expects an
  15.  * uncached base address as the argument.  It will set the two function
  16.  * pointers expected by the MIPS generic timer code.
  17.  */
  18. #include <linux/types.h>
  19. #include <linux/time.h>
  20. #include <asm/time.h>
  21. #include <asm/addrspace.h>
  22. #include <asm/mc146818rtc.h>
  23. #include <asm/debug.h>
  24. #define EPOCH 2000
  25. #undef BCD_TO_BIN
  26. #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
  27. #undef BIN_TO_BCD
  28. #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
  29. #define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
  30. #define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
  31. static unsigned long rtc_base;
  32. static unsigned long
  33. rtc_ds1386_get_time(void)
  34. {
  35. u8 byte;
  36. u8 temp;
  37. unsigned int year, month, day, hour, minute, second;
  38. /* let us freeze external registers */
  39. byte = READ_RTC(0xB);
  40. byte &= 0x3f;
  41. WRITE_RTC(0xB, byte);
  42. /* read time data */
  43. year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH;
  44. month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f);
  45. day = BCD_TO_BIN(READ_RTC(0x8));
  46. minute = BCD_TO_BIN(READ_RTC(0x2));
  47. second = BCD_TO_BIN(READ_RTC(0x1));
  48. /* hour is special - deal with it later */
  49. temp = READ_RTC(0x4);
  50. /* enable time transfer */
  51. byte |= 0x80;
  52. WRITE_RTC(0xB, byte);
  53. /* calc hour */
  54. if (temp & 0x40) {
  55. /* 12 hour format */
  56. hour = BCD_TO_BIN(temp & 0x1f);
  57. if (temp & 0x20) hour += 12;  /* PM */
  58. } else {
  59. /* 24 hour format */
  60. hour = BCD_TO_BIN(temp & 0x3f);
  61. }
  62. return mktime(year, month, day, hour, minute, second);
  63. }
  64. static int
  65. rtc_ds1386_set_time(unsigned long t)
  66. {
  67. struct rtc_time tm;
  68. u8 byte;
  69. u8 temp;
  70. u8 year, month, day, hour, minute, second;
  71. /* let us freeze external registers */
  72. byte = READ_RTC(0xB);
  73. byte &= 0x3f;
  74. WRITE_RTC(0xB, byte);
  75. /* convert */
  76. to_tm(t, &tm);
  77. /* check each field one by one */
  78. year = BIN_TO_BCD(tm.tm_year - EPOCH);
  79. if (year != READ_RTC(0xA)) {
  80. WRITE_RTC(0xA, year);
  81. }
  82. temp = READ_RTC(0x9);
  83. month = BIN_TO_BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */
  84. if (month != (temp & 0x1f)) {
  85. WRITE_RTC( 0x9,
  86.    (month & 0x1f) | (temp & ~0x1f) );
  87. }
  88. day = BIN_TO_BCD(tm.tm_mday);
  89. if (day != READ_RTC(0x8)) {
  90. WRITE_RTC(0x8, day);
  91. }
  92. temp = READ_RTC(0x4);
  93. if (temp & 0x40) {
  94. /* 12 hour format */
  95. hour = 0x40;
  96. if (tm.tm_hour > 12) {
  97. hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f);
  98. } else {
  99. hour |= BIN_TO_BCD(tm.tm_hour);
  100. }
  101. } else {
  102. /* 24 hour format */
  103. hour = BIN_TO_BCD(tm.tm_hour) & 0x3f;
  104. }
  105. if (hour != temp) WRITE_RTC(0x4, hour);
  106. minute = BIN_TO_BCD(tm.tm_min);
  107. if (minute != READ_RTC(0x2)) {
  108. WRITE_RTC(0x2, minute);
  109. }
  110. second = BIN_TO_BCD(tm.tm_sec);
  111. if (second != READ_RTC(0x1)) {
  112. WRITE_RTC(0x1, second);
  113. }
  114. return 0;
  115. }
  116. void
  117. rtc_ds1386_init(unsigned long base)
  118. {
  119. unsigned char byte;
  120. /* remember the base */
  121. rtc_base = base;
  122. db_assert((rtc_base & 0xe0000000) == KSEG1);
  123. /* turn on RTC if it is not on */
  124. byte = READ_RTC(0x9);
  125. if (byte & 0x80) {
  126. byte &= 0x7f;
  127. WRITE_RTC(0x9, byte);
  128. }
  129. /* enable time transfer */
  130. byte = READ_RTC(0xB);
  131. byte |= 0x80;
  132. WRITE_RTC(0xB, byte);
  133. /* set the function pointers */
  134. rtc_get_time = rtc_ds1386_get_time;
  135. rtc_set_time = rtc_ds1386_set_time;
  136. }