rtc_ds1386.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. unsigned long flags;
  36. spin_lock_irqsave(&rtc_lock, flags);
  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 = BCD2BIN(READ_RTC(0xA)) + EPOCH;
  43. month = BCD2BIN(READ_RTC(0x9) & 0x1f);
  44. day = BCD2BIN(READ_RTC(0x8));
  45. minute = BCD2BIN(READ_RTC(0x2));
  46. second = BCD2BIN(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. spin_unlock_irqrestore(&rtc_lock, flags);
  53. /* calc hour */
  54. if (temp & 0x40) {
  55. /* 12 hour format */
  56. hour = BCD2BIN(temp & 0x1f);
  57. if (temp & 0x20) hour += 12; /* PM */
  58. } else {
  59. /* 24 hour format */
  60. hour = BCD2BIN(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. unsigned long flags;
  72. spin_lock_irqsave(&rtc_lock, flags);
  73. /* let us freeze external registers */
  74. byte = READ_RTC(0xB);
  75. byte &= 0x3f;
  76. WRITE_RTC(0xB, byte);
  77. /* convert */
  78. to_tm(t, &tm);
  79. /* check each field one by one */
  80. year = BIN2BCD(tm.tm_year - EPOCH);
  81. if (year != READ_RTC(0xA)) {
  82. WRITE_RTC(0xA, year);
  83. }
  84. temp = READ_RTC(0x9);
  85. month = BIN2BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */
  86. if (month != (temp & 0x1f)) {
  87. WRITE_RTC( 0x9,
  88. (month & 0x1f) | (temp & ~0x1f) );
  89. }
  90. day = BIN2BCD(tm.tm_mday);
  91. if (day != READ_RTC(0x8)) {
  92. WRITE_RTC(0x8, day);
  93. }
  94. temp = READ_RTC(0x4);
  95. if (temp & 0x40) {
  96. /* 12 hour format */
  97. hour = 0x40;
  98. if (tm.tm_hour > 12) {
  99. hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
  100. } else {
  101. hour |= BIN2BCD(tm.tm_hour);
  102. }
  103. } else {
  104. /* 24 hour format */
  105. hour = BIN2BCD(tm.tm_hour) & 0x3f;
  106. }
  107. if (hour != temp) WRITE_RTC(0x4, hour);
  108. minute = BIN2BCD(tm.tm_min);
  109. if (minute != READ_RTC(0x2)) {
  110. WRITE_RTC(0x2, minute);
  111. }
  112. second = BIN2BCD(tm.tm_sec);
  113. if (second != READ_RTC(0x1)) {
  114. WRITE_RTC(0x1, second);
  115. }
  116. spin_unlock_irqrestore(&rtc_lock, flags);
  117. return 0;
  118. }
  119. void
  120. rtc_ds1386_init(unsigned long base)
  121. {
  122. unsigned char byte;
  123. /* remember the base */
  124. rtc_base = base;
  125. db_assert((rtc_base & 0xe0000000) == KSEG1);
  126. /* turn on RTC if it is not on */
  127. byte = READ_RTC(0x9);
  128. if (byte & 0x80) {
  129. byte &= 0x7f;
  130. WRITE_RTC(0x9, byte);
  131. }
  132. /* enable time transfer */
  133. byte = READ_RTC(0xB);
  134. byte |= 0x80;
  135. WRITE_RTC(0xB, byte);
  136. /* set the function pointers */
  137. rtc_mips_get_time = rtc_ds1386_get_time;
  138. rtc_mips_set_time = rtc_ds1386_set_time;
  139. }