rtc-nuc900.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * Copyright (c) 2008-2009 Nuvoton technology corporation.
  3. *
  4. * Wan ZongShun <mcuos.com@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation;version 2 of the License.
  9. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/slab.h>
  15. #include <linux/rtc.h>
  16. #include <linux/delay.h>
  17. #include <linux/io.h>
  18. #include <linux/bcd.h>
  19. /* RTC Control Registers */
  20. #define REG_RTC_INIR 0x00
  21. #define REG_RTC_AER 0x04
  22. #define REG_RTC_FCR 0x08
  23. #define REG_RTC_TLR 0x0C
  24. #define REG_RTC_CLR 0x10
  25. #define REG_RTC_TSSR 0x14
  26. #define REG_RTC_DWR 0x18
  27. #define REG_RTC_TAR 0x1C
  28. #define REG_RTC_CAR 0x20
  29. #define REG_RTC_LIR 0x24
  30. #define REG_RTC_RIER 0x28
  31. #define REG_RTC_RIIR 0x2C
  32. #define REG_RTC_TTR 0x30
  33. #define RTCSET 0x01
  34. #define AERRWENB 0x10000
  35. #define INIRRESET 0xa5eb1357
  36. #define AERPOWERON 0xA965
  37. #define AERPOWEROFF 0x0000
  38. #define LEAPYEAR 0x0001
  39. #define TICKENB 0x80
  40. #define TICKINTENB 0x0002
  41. #define ALARMINTENB 0x0001
  42. #define MODE24 0x0001
  43. struct nuc900_rtc {
  44. int irq_num;
  45. void __iomem *rtc_reg;
  46. struct rtc_device *rtcdev;
  47. };
  48. struct nuc900_bcd_time {
  49. int bcd_sec;
  50. int bcd_min;
  51. int bcd_hour;
  52. int bcd_mday;
  53. int bcd_mon;
  54. int bcd_year;
  55. };
  56. static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc)
  57. {
  58. struct nuc900_rtc *rtc = _rtc;
  59. unsigned long events = 0, rtc_irq;
  60. rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR);
  61. if (rtc_irq & ALARMINTENB) {
  62. rtc_irq &= ~ALARMINTENB;
  63. __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR);
  64. events |= RTC_AF | RTC_IRQF;
  65. }
  66. if (rtc_irq & TICKINTENB) {
  67. rtc_irq &= ~TICKINTENB;
  68. __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR);
  69. events |= RTC_UF | RTC_IRQF;
  70. }
  71. rtc_update_irq(rtc->rtcdev, 1, events);
  72. return IRQ_HANDLED;
  73. }
  74. static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
  75. {
  76. unsigned int timeout = 0x1000;
  77. __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR);
  78. mdelay(10);
  79. __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER);
  80. while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB)
  81. && timeout--)
  82. mdelay(1);
  83. if (!timeout)
  84. return ERR_PTR(-EPERM);
  85. return NULL;
  86. }
  87. static int nuc900_rtc_bcd2bin(unsigned int timereg,
  88. unsigned int calreg, struct rtc_time *tm)
  89. {
  90. tm->tm_mday = bcd2bin(calreg >> 0);
  91. tm->tm_mon = bcd2bin(calreg >> 8);
  92. tm->tm_year = bcd2bin(calreg >> 16) + 100;
  93. tm->tm_sec = bcd2bin(timereg >> 0);
  94. tm->tm_min = bcd2bin(timereg >> 8);
  95. tm->tm_hour = bcd2bin(timereg >> 16);
  96. return rtc_valid_tm(tm);
  97. }
  98. static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm,
  99. struct nuc900_bcd_time *gettm)
  100. {
  101. gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0;
  102. gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8;
  103. if (settm->tm_year < 100) {
  104. dev_warn(dev, "The year will be between 1970-1999, right?\n");
  105. gettm->bcd_year = bin2bcd(settm->tm_year) << 16;
  106. } else {
  107. gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16;
  108. }
  109. gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0;
  110. gettm->bcd_min = bin2bcd(settm->tm_min) << 8;
  111. gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16;
  112. }
  113. static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled)
  114. {
  115. struct nuc900_rtc *rtc = dev_get_drvdata(dev);
  116. if (enabled)
  117. __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)|
  118. (ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER);
  119. else
  120. __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)&
  121. (~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER);
  122. return 0;
  123. }
  124. static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm)
  125. {
  126. struct nuc900_rtc *rtc = dev_get_drvdata(dev);
  127. unsigned int timeval, clrval;
  128. timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR);
  129. clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR);
  130. return nuc900_rtc_bcd2bin(timeval, clrval, tm);
  131. }
  132. static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm)
  133. {
  134. struct nuc900_rtc *rtc = dev_get_drvdata(dev);
  135. struct nuc900_bcd_time gettm;
  136. unsigned long val;
  137. int *err;
  138. nuc900_rtc_bin2bcd(dev, tm, &gettm);
  139. err = check_rtc_access_enable(rtc);
  140. if (IS_ERR(err))
  141. return PTR_ERR(err);
  142. val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year;
  143. __raw_writel(val, rtc->rtc_reg + REG_RTC_CLR);
  144. val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour;
  145. __raw_writel(val, rtc->rtc_reg + REG_RTC_TLR);
  146. return 0;
  147. }
  148. static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  149. {
  150. struct nuc900_rtc *rtc = dev_get_drvdata(dev);
  151. unsigned int timeval, carval;
  152. timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR);
  153. carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR);
  154. return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time);
  155. }
  156. static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  157. {
  158. struct nuc900_rtc *rtc = dev_get_drvdata(dev);
  159. struct nuc900_bcd_time tm;
  160. unsigned long val;
  161. int *err;
  162. nuc900_rtc_bin2bcd(dev, &alrm->time, &tm);
  163. err = check_rtc_access_enable(rtc);
  164. if (IS_ERR(err))
  165. return PTR_ERR(err);
  166. val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year;
  167. __raw_writel(val, rtc->rtc_reg + REG_RTC_CAR);
  168. val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour;
  169. __raw_writel(val, rtc->rtc_reg + REG_RTC_TAR);
  170. return 0;
  171. }
  172. static const struct rtc_class_ops nuc900_rtc_ops = {
  173. .read_time = nuc900_rtc_read_time,
  174. .set_time = nuc900_rtc_set_time,
  175. .read_alarm = nuc900_rtc_read_alarm,
  176. .set_alarm = nuc900_rtc_set_alarm,
  177. .alarm_irq_enable = nuc900_alarm_irq_enable,
  178. };
  179. static int __init nuc900_rtc_probe(struct platform_device *pdev)
  180. {
  181. struct resource *res;
  182. struct nuc900_rtc *nuc900_rtc;
  183. nuc900_rtc = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_rtc),
  184. GFP_KERNEL);
  185. if (!nuc900_rtc)
  186. return -ENOMEM;
  187. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  188. nuc900_rtc->rtc_reg = devm_ioremap_resource(&pdev->dev, res);
  189. if (IS_ERR(nuc900_rtc->rtc_reg))
  190. return PTR_ERR(nuc900_rtc->rtc_reg);
  191. platform_set_drvdata(pdev, nuc900_rtc);
  192. nuc900_rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name,
  193. &nuc900_rtc_ops, THIS_MODULE);
  194. if (IS_ERR(nuc900_rtc->rtcdev)) {
  195. dev_err(&pdev->dev, "rtc device register failed\n");
  196. return PTR_ERR(nuc900_rtc->rtcdev);
  197. }
  198. __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24,
  199. nuc900_rtc->rtc_reg + REG_RTC_TSSR);
  200. nuc900_rtc->irq_num = platform_get_irq(pdev, 0);
  201. if (devm_request_irq(&pdev->dev, nuc900_rtc->irq_num,
  202. nuc900_rtc_interrupt, 0, "nuc900rtc", nuc900_rtc)) {
  203. dev_err(&pdev->dev, "NUC900 RTC request irq failed\n");
  204. return -EBUSY;
  205. }
  206. return 0;
  207. }
  208. static struct platform_driver nuc900_rtc_driver = {
  209. .driver = {
  210. .name = "nuc900-rtc",
  211. },
  212. };
  213. module_platform_driver_probe(nuc900_rtc_driver, nuc900_rtc_probe);
  214. MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
  215. MODULE_DESCRIPTION("nuc910/nuc920 RTC driver");
  216. MODULE_LICENSE("GPL");
  217. MODULE_ALIAS("platform:nuc900-rtc");