rtc.c 9.8 KB

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