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

嵌入式Linux

开发平台:

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/ddb5xxx/debug.h>
  23. #define EPOCH 2000
  24. #undef BCD_TO_BIN
  25. #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
  26. #undef BIN_TO_BCD
  27. #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
  28. #define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
  29. #define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
  30. static unsigned long rtc_base;
  31. static unsigned long
  32. rtc_ds1386_get_time(void)
  33. {
  34. u8 byte;
  35. u8 temp;
  36. unsigned int year, month, day, hour, minute, second;
  37. /* let us freeze external registers */
  38. byte = READ_RTC(0xB);
  39. byte &= 0x3f;
  40. WRITE_RTC(0xB, byte);
  41. /* read time data */
  42. year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH;
  43. month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f);
  44. day = BCD_TO_BIN(READ_RTC(0x8));
  45. minute = BCD_TO_BIN(READ_RTC(0x2));
  46. second = BCD_TO_BIN(READ_RTC(0x1));
  47. /* hour is special - deal with it later */
  48. temp = READ_RTC(0x4);
  49. /* enable time transfer */
  50. byte |= 0x80;
  51. WRITE_RTC(0xB, byte);
  52. /* calc hour */
  53. if (temp & 0x40) {
  54. /* 12 hour format */
  55. hour = BCD_TO_BIN(temp & 0x1f);
  56. if (temp & 0x20) hour += 12;  /* PM */
  57. } else {
  58. /* 24 hour format */
  59. hour = BCD_TO_BIN(temp & 0x3f);
  60. }
  61. return mktime(year, month, day, hour, minute, second);
  62. }
  63. static int 
  64. rtc_ds1386_set_time(unsigned long t)
  65. {
  66. struct rtc_time tm;
  67. u8 byte;
  68. u8 temp;
  69. u8 year, month, day, hour, minute, second;
  70. /* let us freeze external registers */
  71. byte = READ_RTC(0xB);
  72. byte &= 0x3f;
  73. WRITE_RTC(0xB, byte);
  74. /* convert */
  75. to_tm(t, &tm);
  76. /* check each field one by one */
  77. year = BIN_TO_BCD(tm.tm_year - EPOCH);
  78. if (year != READ_RTC(0xA)) {
  79. WRITE_RTC(0xA, year);
  80. }
  81. temp = READ_RTC(0x9);
  82. month = BIN_TO_BCD(tm.tm_mon);
  83. if (month != (temp & 0x1f)) {
  84. WRITE_RTC( 0x9,
  85.    (month & 0x1f) | (temp & ~0x1f) );
  86. }
  87. day = BIN_TO_BCD(tm.tm_mday);
  88. if (day != READ_RTC(0x8)) {
  89. WRITE_RTC(0x8, day);
  90. }
  91. temp = READ_RTC(0x4);
  92. if (temp & 0x40) {
  93. /* 12 hour format */
  94. hour = 0x40;
  95. if (tm.tm_hour > 12) {
  96. hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f);
  97. } else {
  98. hour |= BIN_TO_BCD(tm.tm_hour);
  99. }
  100. } else {
  101. /* 24 hour format */
  102. hour = BIN_TO_BCD(tm.tm_hour) & 0x3f;
  103. }
  104. if (hour != temp) WRITE_RTC(0x4, hour);
  105. minute = BIN_TO_BCD(tm.tm_min);
  106. if (minute != READ_RTC(0x2)) {
  107. WRITE_RTC(0x2, minute);
  108. }
  109. second = BIN_TO_BCD(tm.tm_sec);
  110. if (second != READ_RTC(0x1)) {
  111. WRITE_RTC(0x1, second);
  112. }
  113. return 0;
  114. }
  115. void
  116. rtc_ds1386_init(unsigned long base)
  117. {
  118. unsigned char byte;
  119. /* remember the base */
  120. rtc_base = base;
  121. MIPS_ASSERT((rtc_base & 0xe0000000) == KSEG1);
  122. /* turn on RTC if it is not on */
  123. byte = READ_RTC(0x9);
  124. if (byte & 0x80) {
  125. byte &= 0x7f;
  126. WRITE_RTC(0x9, byte);
  127. }
  128. /* enable time transfer */
  129. byte = READ_RTC(0xB);
  130. byte |= 0x80;
  131. WRITE_RTC(0xB, byte);
  132. /* set the function pointers */
  133. rtc_get_time = rtc_ds1386_get_time;
  134. rtc_set_time = rtc_ds1386_set_time;
  135. }