rtc.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /****************************************************************************/
  2. /*
  3. * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code
  4. *
  5. * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
  6. * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
  7. *
  8. * The SecureEdge5410 can have one of 2 real time clocks, the SH
  9. * built in version or the preferred external DS1302. Here we work out
  10. * each to see what we have and then run with it.
  11. */
  12. /****************************************************************************/
  13. #include <linux/init.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/time.h>
  17. #include <linux/rtc.h>
  18. #include <linux/mc146818rtc.h>
  19. #include <asm/io.h>
  20. static int use_ds1302;
  21. /****************************************************************************/
  22. /*
  23. * we need to implement a DS1302 driver here that can operate in
  24. * conjunction with the builtin rtc driver which is already quite friendly
  25. */
  26. /*****************************************************************************/
  27. #define RTC_CMD_READ 0x81 /* Read command */
  28. #define RTC_CMD_WRITE 0x80 /* Write command */
  29. #define RTC_ADDR_YEAR 0x06 /* Address of year register */
  30. #define RTC_ADDR_DAY 0x05 /* Address of day of week register */
  31. #define RTC_ADDR_MON 0x04 /* Address of month register */
  32. #define RTC_ADDR_DATE 0x03 /* Address of day of month register */
  33. #define RTC_ADDR_HOUR 0x02 /* Address of hour register */
  34. #define RTC_ADDR_MIN 0x01 /* Address of minute register */
  35. #define RTC_ADDR_SEC 0x00 /* Address of second register */
  36. #define RTC_RESET 0x1000
  37. #define RTC_IODATA 0x0800
  38. #define RTC_SCLK 0x0400
  39. #define set_dirp(x)
  40. #define get_dirp(x) 0
  41. #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
  42. #define get_dp(x) SECUREEDGE_READ_IOPORT()
  43. static void ds1302_sendbits(unsigned int val)
  44. {
  45. int i;
  46. for (i = 8; (i); i--, val >>= 1) {
  47. set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
  48. set_dp(get_dp() | RTC_SCLK); // clock high
  49. set_dp(get_dp() & ~RTC_SCLK); // clock low
  50. }
  51. }
  52. static unsigned int ds1302_recvbits(void)
  53. {
  54. unsigned int val;
  55. int i;
  56. for (i = 0, val = 0; (i < 8); i++) {
  57. val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
  58. set_dp(get_dp() | RTC_SCLK); // clock high
  59. set_dp(get_dp() & ~RTC_SCLK); // clock low
  60. }
  61. return(val);
  62. }
  63. static unsigned int ds1302_readbyte(unsigned int addr)
  64. {
  65. unsigned int val;
  66. unsigned long flags;
  67. local_irq_save(flags);
  68. set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
  69. set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
  70. set_dp(get_dp() | RTC_RESET);
  71. ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
  72. set_dirp(get_dirp() & ~RTC_IODATA);
  73. val = ds1302_recvbits();
  74. set_dp(get_dp() & ~RTC_RESET);
  75. local_irq_restore(flags);
  76. return(val);
  77. }
  78. static void ds1302_writebyte(unsigned int addr, unsigned int val)
  79. {
  80. unsigned long flags;
  81. local_irq_save(flags);
  82. set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
  83. set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
  84. set_dp(get_dp() | RTC_RESET);
  85. ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
  86. ds1302_sendbits(val);
  87. set_dp(get_dp() & ~RTC_RESET);
  88. local_irq_restore(flags);
  89. }
  90. static void ds1302_reset(void)
  91. {
  92. unsigned long flags;
  93. /* Hardware dependant reset/init */
  94. local_irq_save(flags);
  95. set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
  96. set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
  97. local_irq_restore(flags);
  98. }
  99. /*****************************************************************************/
  100. static inline int bcd2int(int val)
  101. {
  102. return((((val & 0xf0) >> 4) * 10) + (val & 0xf));
  103. }
  104. static inline int int2bcd(int val)
  105. {
  106. return(((val / 10) << 4) + (val % 10));
  107. }
  108. /*****************************************************************************/
  109. /*
  110. * Write and Read some RAM in the DS1302, if it works assume it's there
  111. * Otherwise use the SH4 internal RTC
  112. */
  113. void snapgear_rtc_gettimeofday(struct timespec *);
  114. int snapgear_rtc_settimeofday(const time_t);
  115. void __init secureedge5410_rtc_init(void)
  116. {
  117. unsigned char *test = "snapgear";
  118. int i;
  119. ds1302_reset();
  120. use_ds1302 = 1;
  121. for (i = 0; test[i]; i++)
  122. ds1302_writebyte(32 + i, test[i]);
  123. for (i = 0; test[i]; i++)
  124. if (ds1302_readbyte(32 + i) != test[i]) {
  125. use_ds1302 = 0;
  126. break;
  127. }
  128. if (use_ds1302) {
  129. rtc_sh_get_time = snapgear_rtc_gettimeofday;
  130. rtc_sh_set_time = snapgear_rtc_settimeofday;
  131. }
  132. printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
  133. }
  134. /****************************************************************************/
  135. /*
  136. * our generic interface that chooses the correct code to use
  137. */
  138. void snapgear_rtc_gettimeofday(struct timespec *ts)
  139. {
  140. unsigned int sec, min, hr, day, mon, yr;
  141. if (!use_ds1302)
  142. return;
  143. sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
  144. min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
  145. hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR));
  146. day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE));
  147. mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON));
  148. yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR));
  149. bad_time:
  150. if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
  151. hr > 23 || min > 59 || sec > 59) {
  152. printk(KERN_ERR
  153. "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n");
  154. ds1302_writebyte(RTC_ADDR_MIN, min = 0);
  155. ds1302_writebyte(RTC_ADDR_HOUR, hr = 0);
  156. ds1302_writebyte(RTC_ADDR_DAY, 7);
  157. ds1302_writebyte(RTC_ADDR_DATE, day = 1);
  158. ds1302_writebyte(RTC_ADDR_MON, mon = 1);
  159. ds1302_writebyte(RTC_ADDR_YEAR, yr = 0);
  160. ds1302_writebyte(RTC_ADDR_SEC, sec = 0);
  161. }
  162. ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec);
  163. if (ts->tv_sec < 0) {
  164. #if 0
  165. printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec);
  166. #endif
  167. yr = 100;
  168. goto bad_time;
  169. }
  170. ts->tv_nsec = 0;
  171. }
  172. int snapgear_rtc_settimeofday(const time_t secs)
  173. {
  174. int retval = 0;
  175. int real_seconds, real_minutes, cmos_minutes;
  176. unsigned long nowtime;
  177. if (!use_ds1302)
  178. return 0;
  179. /*
  180. * This is called direct from the kernel timer handling code.
  181. * It is supposed to synchronize the kernel clock to the RTC.
  182. */
  183. nowtime = secs;
  184. /* STOP RTC */
  185. ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
  186. cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
  187. /*
  188. * since we're only adjusting minutes and seconds,
  189. * don't interfere with hour overflow. This avoids
  190. * messing with unknown time zones but requires your
  191. * RTC not to be off by more than 15 minutes
  192. */
  193. real_seconds = nowtime % 60;
  194. real_minutes = nowtime / 60;
  195. if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
  196. real_minutes += 30; /* correct for half hour time zone */
  197. real_minutes %= 60;
  198. if (abs(real_minutes - cmos_minutes) < 30) {
  199. ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes));
  200. ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds));
  201. } else {
  202. printk(KERN_WARNING
  203. "SnapGear RTC: can't update from %d to %d\n",
  204. cmos_minutes, real_minutes);
  205. retval = -1;
  206. }
  207. /* START RTC */
  208. ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
  209. return(0);
  210. }
  211. unsigned char secureedge5410_cmos_read(int addr)
  212. {
  213. unsigned char val = 0;
  214. if (!use_ds1302)
  215. return(__CMOS_READ(addr, w));
  216. switch(addr) {
  217. case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break;
  218. case RTC_SECONDS_ALARM: break;
  219. case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break;
  220. case RTC_MINUTES_ALARM: break;
  221. case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break;
  222. case RTC_HOURS_ALARM: break;
  223. case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break;
  224. case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break;
  225. case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break;
  226. case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break;
  227. case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
  228. case RTC_REG_B: /* RTC_CONTROL */ break;
  229. case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
  230. case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break;
  231. default: break;
  232. }
  233. return(val);
  234. }
  235. void secureedge5410_cmos_write(unsigned char val, int addr)
  236. {
  237. if (!use_ds1302) {
  238. __CMOS_WRITE(val, addr, w);
  239. return;
  240. }
  241. switch(addr) {
  242. case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break;
  243. case RTC_SECONDS_ALARM: break;
  244. case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break;
  245. case RTC_MINUTES_ALARM: break;
  246. case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break;
  247. case RTC_HOURS_ALARM: break;
  248. case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break;
  249. case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break;
  250. case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break;
  251. case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break;
  252. case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
  253. case RTC_REG_B: /* RTC_CONTROL */ break;
  254. case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
  255. case RTC_REG_D: /* RTC_VALID */ break;
  256. default: break;
  257. }
  258. }