rtc-ds1302.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Dallas DS1302 RTC Support
  3. *
  4. * Copyright (C) 2002 David McCullough
  5. * Copyright (C) 2003 - 2007 Paul Mundt
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License version 2. See the file "COPYING" in the main directory of
  9. * this archive for more details.
  10. */
  11. #include <linux/init.h>
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/rtc.h>
  16. #include <linux/io.h>
  17. #include <linux/bcd.h>
  18. #define DRV_NAME "rtc-ds1302"
  19. #define DRV_VERSION "0.1.1"
  20. #define RTC_CMD_READ 0x81 /* Read command */
  21. #define RTC_CMD_WRITE 0x80 /* Write command */
  22. #define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */
  23. #define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */
  24. #define RTC_ADDR_YEAR 0x06 /* Address of year register */
  25. #define RTC_ADDR_DAY 0x05 /* Address of day of week register */
  26. #define RTC_ADDR_MON 0x04 /* Address of month register */
  27. #define RTC_ADDR_DATE 0x03 /* Address of day of month register */
  28. #define RTC_ADDR_HOUR 0x02 /* Address of hour register */
  29. #define RTC_ADDR_MIN 0x01 /* Address of minute register */
  30. #define RTC_ADDR_SEC 0x00 /* Address of second register */
  31. #ifdef CONFIG_SH_SECUREEDGE5410
  32. #include <asm/rtc.h>
  33. #include <mach/secureedge5410.h>
  34. #define RTC_RESET 0x1000
  35. #define RTC_IODATA 0x0800
  36. #define RTC_SCLK 0x0400
  37. #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
  38. #define get_dp() SECUREEDGE_READ_IOPORT()
  39. #define ds1302_set_tx()
  40. #define ds1302_set_rx()
  41. static inline int ds1302_hw_init(void)
  42. {
  43. return 0;
  44. }
  45. static inline void ds1302_reset(void)
  46. {
  47. set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
  48. }
  49. static inline void ds1302_clock(void)
  50. {
  51. set_dp(get_dp() | RTC_SCLK); /* clock high */
  52. set_dp(get_dp() & ~RTC_SCLK); /* clock low */
  53. }
  54. static inline void ds1302_start(void)
  55. {
  56. set_dp(get_dp() | RTC_RESET);
  57. }
  58. static inline void ds1302_stop(void)
  59. {
  60. set_dp(get_dp() & ~RTC_RESET);
  61. }
  62. static inline void ds1302_txbit(int bit)
  63. {
  64. set_dp((get_dp() & ~RTC_IODATA) | (bit ? RTC_IODATA : 0));
  65. }
  66. static inline int ds1302_rxbit(void)
  67. {
  68. return !!(get_dp() & RTC_IODATA);
  69. }
  70. #else
  71. #error "Add support for your platform"
  72. #endif
  73. static void ds1302_sendbits(unsigned int val)
  74. {
  75. int i;
  76. ds1302_set_tx();
  77. for (i = 8; (i); i--, val >>= 1) {
  78. ds1302_txbit(val & 0x1);
  79. ds1302_clock();
  80. }
  81. }
  82. static unsigned int ds1302_recvbits(void)
  83. {
  84. unsigned int val;
  85. int i;
  86. ds1302_set_rx();
  87. for (i = 0, val = 0; (i < 8); i++) {
  88. val |= (ds1302_rxbit() << i);
  89. ds1302_clock();
  90. }
  91. return val;
  92. }
  93. static unsigned int ds1302_readbyte(unsigned int addr)
  94. {
  95. unsigned int val;
  96. ds1302_reset();
  97. ds1302_start();
  98. ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
  99. val = ds1302_recvbits();
  100. ds1302_stop();
  101. return val;
  102. }
  103. static void ds1302_writebyte(unsigned int addr, unsigned int val)
  104. {
  105. ds1302_reset();
  106. ds1302_start();
  107. ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
  108. ds1302_sendbits(val);
  109. ds1302_stop();
  110. }
  111. static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
  112. {
  113. tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC));
  114. tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN));
  115. tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR));
  116. tm->tm_wday = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY));
  117. tm->tm_mday = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE));
  118. tm->tm_mon = bcd2bin(ds1302_readbyte(RTC_ADDR_MON)) - 1;
  119. tm->tm_year = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR));
  120. if (tm->tm_year < 70)
  121. tm->tm_year += 100;
  122. dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
  123. "mday=%d, mon=%d, year=%d, wday=%d\n",
  124. __func__,
  125. tm->tm_sec, tm->tm_min, tm->tm_hour,
  126. tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
  127. return rtc_valid_tm(tm);
  128. }
  129. static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
  130. {
  131. /* Stop RTC */
  132. ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
  133. ds1302_writebyte(RTC_ADDR_SEC, bin2bcd(tm->tm_sec));
  134. ds1302_writebyte(RTC_ADDR_MIN, bin2bcd(tm->tm_min));
  135. ds1302_writebyte(RTC_ADDR_HOUR, bin2bcd(tm->tm_hour));
  136. ds1302_writebyte(RTC_ADDR_DAY, bin2bcd(tm->tm_wday));
  137. ds1302_writebyte(RTC_ADDR_DATE, bin2bcd(tm->tm_mday));
  138. ds1302_writebyte(RTC_ADDR_MON, bin2bcd(tm->tm_mon + 1));
  139. ds1302_writebyte(RTC_ADDR_YEAR, bin2bcd(tm->tm_year % 100));
  140. /* Start RTC */
  141. ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
  142. return 0;
  143. }
  144. static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd,
  145. unsigned long arg)
  146. {
  147. switch (cmd) {
  148. #ifdef RTC_SET_CHARGE
  149. case RTC_SET_CHARGE:
  150. {
  151. int tcs_val;
  152. if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int)))
  153. return -EFAULT;
  154. ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf));
  155. return 0;
  156. }
  157. #endif
  158. }
  159. return -ENOIOCTLCMD;
  160. }
  161. static struct rtc_class_ops ds1302_rtc_ops = {
  162. .read_time = ds1302_rtc_read_time,
  163. .set_time = ds1302_rtc_set_time,
  164. .ioctl = ds1302_rtc_ioctl,
  165. };
  166. static int __init ds1302_rtc_probe(struct platform_device *pdev)
  167. {
  168. struct rtc_device *rtc;
  169. if (ds1302_hw_init()) {
  170. dev_err(&pdev->dev, "Failed to init communication channel");
  171. return -EINVAL;
  172. }
  173. /* Reset */
  174. ds1302_reset();
  175. /* Write a magic value to the DS1302 RAM, and see if it sticks. */
  176. ds1302_writebyte(RTC_ADDR_RAM0, 0x42);
  177. if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) {
  178. dev_err(&pdev->dev, "Failed to probe");
  179. return -ENODEV;
  180. }
  181. rtc = rtc_device_register("ds1302", &pdev->dev,
  182. &ds1302_rtc_ops, THIS_MODULE);
  183. if (IS_ERR(rtc))
  184. return PTR_ERR(rtc);
  185. platform_set_drvdata(pdev, rtc);
  186. return 0;
  187. }
  188. static int __devexit ds1302_rtc_remove(struct platform_device *pdev)
  189. {
  190. struct rtc_device *rtc = platform_get_drvdata(pdev);
  191. rtc_device_unregister(rtc);
  192. platform_set_drvdata(pdev, NULL);
  193. return 0;
  194. }
  195. static struct platform_driver ds1302_platform_driver = {
  196. .driver = {
  197. .name = DRV_NAME,
  198. .owner = THIS_MODULE,
  199. },
  200. .remove = __devexit_p(ds1302_rtc_remove),
  201. };
  202. static int __init ds1302_rtc_init(void)
  203. {
  204. return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe);
  205. }
  206. static void __exit ds1302_rtc_exit(void)
  207. {
  208. platform_driver_unregister(&ds1302_platform_driver);
  209. }
  210. module_init(ds1302_rtc_init);
  211. module_exit(ds1302_rtc_exit);
  212. MODULE_DESCRIPTION("Dallas DS1302 RTC driver");
  213. MODULE_VERSION(DRV_VERSION);
  214. MODULE_AUTHOR("Paul Mundt, David McCullough");
  215. MODULE_LICENSE("GPL v2");