time.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Copyright (C) 2000, 2001 Broadcom Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. /*
  19. * Time routines for the swarm board. We pass all the hard stuff
  20. * through to the sb1250 handling code. Only thing we really keep
  21. * track of here is what time of day we think it is. And we don't
  22. * really even do a good job of that...
  23. */
  24. #include <linux/bcd.h>
  25. #include <linux/init.h>
  26. #include <linux/time.h>
  27. #include <linux/sched.h>
  28. #include <linux/spinlock.h>
  29. #include <asm/system.h>
  30. #include <asm/addrspace.h>
  31. #include <asm/io.h>
  32. #include <asm/sibyte/sb1250.h>
  33. #include <asm/sibyte/sb1250_regs.h>
  34. #include <asm/sibyte/sb1250_smbus.h>
  35. static unsigned long long sec_bias = 0;
  36. static unsigned int usec_bias = 0;
  37. /* Xicor 1241 definitions */
  38. /*
  39. * Register bits
  40. */
  41. #define X1241REG_SR_BAT 0x80 /* currently on battery power */
  42. #define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
  43. #define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
  44. #define X1241REG_SR_RTCF 0x01 /* clock failed */
  45. #define X1241REG_BL_BP2 0x80 /* block protect 2 */
  46. #define X1241REG_BL_BP1 0x40 /* block protect 1 */
  47. #define X1241REG_BL_BP0 0x20 /* block protect 0 */
  48. #define X1241REG_BL_WD1 0x10
  49. #define X1241REG_BL_WD0 0x08
  50. #define X1241REG_HR_MIL 0x80 /* military time format */
  51. /*
  52. * Register numbers
  53. */
  54. #define X1241REG_BL 0x10 /* block protect bits */
  55. #define X1241REG_INT 0x11 /* */
  56. #define X1241REG_SC 0x30 /* Seconds */
  57. #define X1241REG_MN 0x31 /* Minutes */
  58. #define X1241REG_HR 0x32 /* Hours */
  59. #define X1241REG_DT 0x33 /* Day of month */
  60. #define X1241REG_MO 0x34 /* Month */
  61. #define X1241REG_YR 0x35 /* Year */
  62. #define X1241REG_DW 0x36 /* Day of Week */
  63. #define X1241REG_Y2K 0x37 /* Year 2K */
  64. #define X1241REG_SR 0x3F /* Status register */
  65. #define X1241_CCR_ADDRESS 0x6F
  66. #define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
  67. static int xicor_read(uint8_t addr)
  68. {
  69. while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
  70. ;
  71. bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
  72. bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
  73. bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
  74. SMB_CSR(R_SMB_START));
  75. while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
  76. ;
  77. bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
  78. SMB_CSR(R_SMB_START));
  79. while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
  80. ;
  81. if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
  82. /* Clear error bit by writing a 1 */
  83. bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
  84. return -1;
  85. }
  86. return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
  87. }
  88. static int xicor_write(uint8_t addr, int b)
  89. {
  90. while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
  91. ;
  92. bus_writeq(addr, SMB_CSR(R_SMB_CMD));
  93. bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
  94. bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
  95. SMB_CSR(R_SMB_START));
  96. while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
  97. ;
  98. if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
  99. /* Clear error bit by writing a 1 */
  100. bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
  101. return -1;
  102. } else {
  103. return 0;
  104. }
  105. }
  106. /*
  107. * In order to set the CMOS clock precisely, set_rtc_mmss has to be
  108. * called 500 ms after the second nowtime has started, because when
  109. * nowtime is written into the registers of the CMOS clock, it will
  110. * jump to the next second precisely 500 ms later. Check the Motorola
  111. * MC146818A or Dallas DS12887 data sheet for details.
  112. *
  113. * BUG: This routine does not handle hour overflow properly; it just
  114. * sets the minutes. Usually you'll only notice that after reboot!
  115. */
  116. int set_rtc_mmss(unsigned long nowtime)
  117. {
  118. int retval = 0;
  119. int real_seconds, real_minutes, cmos_minutes;
  120. cmos_minutes = xicor_read(X1241REG_MN);
  121. cmos_minutes = BCD2BIN(cmos_minutes);
  122. /*
  123. * since we're only adjusting minutes and seconds,
  124. * don't interfere with hour overflow. This avoids
  125. * messing with unknown time zones but requires your
  126. * RTC not to be off by more than 15 minutes
  127. */
  128. real_seconds = nowtime % 60;
  129. real_minutes = nowtime / 60;
  130. if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
  131. real_minutes += 30; /* correct for half hour time zone */
  132. real_minutes %= 60;
  133. /* unlock writes to the CCR */
  134. xicor_write(X1241REG_SR, X1241REG_SR_WEL);
  135. xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
  136. if (abs(real_minutes - cmos_minutes) < 30) {
  137. real_seconds = BIN2BCD(real_seconds);
  138. real_minutes = BIN2BCD(real_minutes);
  139. xicor_write(X1241REG_SC, real_seconds);
  140. xicor_write(X1241REG_MN, real_minutes);
  141. } else {
  142. printk(KERN_WARNING
  143. "set_rtc_mmss: can't update from %d to %d\n",
  144. cmos_minutes, real_minutes);
  145. retval = -1;
  146. }
  147. xicor_write(X1241REG_SR, 0);
  148. printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
  149. return retval;
  150. }
  151. static unsigned long __init get_swarm_time(void)
  152. {
  153. unsigned int year, mon, day, hour, min, sec, y2k;
  154. sec = xicor_read(X1241REG_SC);
  155. min = xicor_read(X1241REG_MN);
  156. hour = xicor_read(X1241REG_HR);
  157. if (hour & X1241REG_HR_MIL) {
  158. hour &= 0x3f;
  159. } else {
  160. if (hour & 0x20)
  161. hour = (hour & 0xf) + 0x12;
  162. }
  163. sec = BCD2BIN(sec);
  164. min = BCD2BIN(min);
  165. hour = BCD2BIN(hour);
  166. day = xicor_read(X1241REG_DT);
  167. mon = xicor_read(X1241REG_MO);
  168. year = xicor_read(X1241REG_YR);
  169. y2k = xicor_read(X1241REG_Y2K);
  170. day = BCD2BIN(day);
  171. mon = BCD2BIN(mon);
  172. year = BCD2BIN(year);
  173. y2k = BCD2BIN(y2k);
  174. year += (y2k * 100);
  175. return mktime(year, mon, day, hour, min, sec);
  176. }
  177. /*
  178. * Bring up the timer at 100 Hz.
  179. */
  180. void __init swarm_time_init(void)
  181. {
  182. unsigned int flags;
  183. int status;
  184. /* Set up the scd general purpose timer 0 to cpu 0 */
  185. sb1250_time_init();
  186. /* Establish communication with the Xicor 1241 RTC */
  187. /* XXXKW how do I share the SMBus with the I2C subsystem? */
  188. bus_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
  189. bus_writeq(0, SMB_CSR(R_SMB_CONTROL));
  190. if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
  191. printk("x1241: couldn't detect on SWARM SMBus 1\n");
  192. } else {
  193. if (status & X1241REG_SR_RTCF)
  194. printk("x1241: battery failed -- time is probably wrong\n");
  195. write_seqlock_irqsave(&xtime_lock, flags);
  196. xtime.tv_sec = get_swarm_time();
  197. xtime.tv_nsec = 0;
  198. write_sequnlock_irqrestore(&xtime_lock, flags);
  199. }
  200. }