rtc_ds1386.c 3.4 KB

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