rtc_rx5c348.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * RTC routines for RICOH Rx5C348 SPI chip.
  3. * Copyright (C) 2000-2001 Toshiba Corporation
  4. *
  5. * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
  6. * terms of the GNU General Public License version 2. This program is
  7. * licensed "as is" without any warranty of any kind, whether express
  8. * or implied.
  9. *
  10. * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
  11. */
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/string.h>
  15. #include <linux/rtc.h>
  16. #include <linux/time.h>
  17. #include <asm/time.h>
  18. #include <asm/tx4938/spi.h>
  19. #define EPOCH 2000
  20. /* registers */
  21. #define Rx5C348_REG_SECOND 0
  22. #define Rx5C348_REG_MINUTE 1
  23. #define Rx5C348_REG_HOUR 2
  24. #define Rx5C348_REG_WEEK 3
  25. #define Rx5C348_REG_DAY 4
  26. #define Rx5C348_REG_MONTH 5
  27. #define Rx5C348_REG_YEAR 6
  28. #define Rx5C348_REG_ADJUST 7
  29. #define Rx5C348_REG_ALARM_W_MIN 8
  30. #define Rx5C348_REG_ALARM_W_HOUR 9
  31. #define Rx5C348_REG_ALARM_W_WEEK 10
  32. #define Rx5C348_REG_ALARM_D_MIN 11
  33. #define Rx5C348_REG_ALARM_D_HOUR 12
  34. #define Rx5C348_REG_CTL1 14
  35. #define Rx5C348_REG_CTL2 15
  36. /* register bits */
  37. #define Rx5C348_BIT_PM 0x20 /* REG_HOUR */
  38. #define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */
  39. #define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */
  40. #define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */
  41. /* commands */
  42. #define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */
  43. #define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */
  44. #define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */
  45. #define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */
  46. static struct spi_dev_desc srtc_dev_desc = {
  47. .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */
  48. .tcss = 31,
  49. .tcsh = 1,
  50. .tcsr = 62,
  51. /* 31us for Tcss (62us for Tcsr) is required for carry operation) */
  52. .byteorder = 1, /* MSB-First */
  53. .polarity = 0, /* High-Active */
  54. .phase = 1, /* Shift-Then-Sample */
  55. };
  56. static int srtc_chipid;
  57. static int srtc_24h;
  58. static inline int
  59. spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
  60. {
  61. unsigned char *inbufs[1], *outbufs[1];
  62. unsigned int incounts[2], outcounts[2];
  63. inbufs[0] = inbuf;
  64. incounts[0] = count;
  65. incounts[1] = 0;
  66. outbufs[0] = outbuf;
  67. outcounts[0] = count;
  68. outcounts[1] = 0;
  69. return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
  70. inbufs, incounts, outbufs, outcounts, 0);
  71. }
  72. /*
  73. * Conversion between binary and BCD.
  74. */
  75. #ifndef BCD_TO_BIN
  76. #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
  77. #endif
  78. #ifndef BIN_TO_BCD
  79. #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
  80. #endif
  81. /* RTC-dependent code for time.c */
  82. static int
  83. rtc_rx5c348_set_time(unsigned long t)
  84. {
  85. unsigned char inbuf[8];
  86. struct rtc_time tm;
  87. u8 year, month, day, hour, minute, second, century;
  88. /* convert */
  89. to_tm(t, &tm);
  90. year = tm.tm_year % 100;
  91. month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */
  92. day = tm.tm_mday;
  93. hour = tm.tm_hour;
  94. minute = tm.tm_min;
  95. second = tm.tm_sec;
  96. century = tm.tm_year / 100;
  97. inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
  98. BIN_TO_BCD(second);
  99. inbuf[1] = second;
  100. BIN_TO_BCD(minute);
  101. inbuf[2] = minute;
  102. if (srtc_24h) {
  103. BIN_TO_BCD(hour);
  104. inbuf[3] = hour;
  105. } else {
  106. /* hour 0 is AM12, noon is PM12 */
  107. inbuf[3] = 0;
  108. if (hour >= 12)
  109. inbuf[3] = Rx5C348_BIT_PM;
  110. hour = (hour + 11) % 12 + 1;
  111. BIN_TO_BCD(hour);
  112. inbuf[3] |= hour;
  113. }
  114. inbuf[4] = 0; /* ignore week */
  115. BIN_TO_BCD(day);
  116. inbuf[5] = day;
  117. BIN_TO_BCD(month);
  118. inbuf[6] = month;
  119. if (century >= 20)
  120. inbuf[6] |= Rx5C348_BIT_Y2K;
  121. BIN_TO_BCD(year);
  122. inbuf[7] = year;
  123. /* write in one transfer to avoid data inconsistency */
  124. return spi_rtc_io(inbuf, NULL, 8);
  125. }
  126. static unsigned long
  127. rtc_rx5c348_get_time(void)
  128. {
  129. unsigned char inbuf[8], outbuf[8];
  130. unsigned int year, month, day, hour, minute, second;
  131. inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
  132. memset(inbuf + 1, 0, 7);
  133. /* read in one transfer to avoid data inconsistency */
  134. if (spi_rtc_io(inbuf, outbuf, 8))
  135. return 0;
  136. second = outbuf[1];
  137. BCD_TO_BIN(second);
  138. minute = outbuf[2];
  139. BCD_TO_BIN(minute);
  140. if (srtc_24h) {
  141. hour = outbuf[3];
  142. BCD_TO_BIN(hour);
  143. } else {
  144. hour = outbuf[3] & ~Rx5C348_BIT_PM;
  145. BCD_TO_BIN(hour);
  146. hour %= 12;
  147. if (outbuf[3] & Rx5C348_BIT_PM)
  148. hour += 12;
  149. }
  150. day = outbuf[5];
  151. BCD_TO_BIN(day);
  152. month = outbuf[6] & ~Rx5C348_BIT_Y2K;
  153. BCD_TO_BIN(month);
  154. year = outbuf[7];
  155. BCD_TO_BIN(year);
  156. year += EPOCH;
  157. return mktime(year, month, day, hour, minute, second);
  158. }
  159. void __init
  160. rtc_rx5c348_init(int chipid)
  161. {
  162. unsigned char inbuf[2], outbuf[2];
  163. srtc_chipid = chipid;
  164. /* turn on RTC if it is not on */
  165. inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
  166. inbuf[1] = 0;
  167. spi_rtc_io(inbuf, outbuf, 2);
  168. if (outbuf[1] & Rx5C348_BIT_XSTP) {
  169. inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
  170. inbuf[1] = 0;
  171. spi_rtc_io(inbuf, NULL, 2);
  172. }
  173. inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
  174. inbuf[1] = 0;
  175. spi_rtc_io(inbuf, outbuf, 2);
  176. if (outbuf[1] & Rx5C348_BIT_24H)
  177. srtc_24h = 1;
  178. /* set the function pointers */
  179. rtc_mips_get_time = rtc_rx5c348_get_time;
  180. rtc_mips_set_time = rtc_rx5c348_set_time;
  181. }