rtc-gemini.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Gemini OnChip RTC
  3. *
  4. * Copyright (C) 2009 Janos Laube <janos.dev@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; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Original code for older kernel 2.6.15 are form Stormlinksemi
  21. * first update from Janos Laube for > 2.6.29 kernels
  22. *
  23. * checkpatch fixes and usage off rtc-lib code
  24. * Hans Ulli Kroll <ulli.kroll@googlemail.com>
  25. */
  26. #include <linux/rtc.h>
  27. #include <linux/io.h>
  28. #include <linux/slab.h>
  29. #include <linux/platform_device.h>
  30. #include <linux/kernel.h>
  31. #include <linux/module.h>
  32. #include <mach/hardware.h>
  33. #define DRV_NAME "rtc-gemini"
  34. MODULE_DESCRIPTION("RTC driver for Gemini SoC");
  35. MODULE_ALIAS("platform:" DRV_NAME);
  36. MODULE_AUTHOR("Hans Ulli Kroll <ulli.kroll@googlemail.com>");
  37. MODULE_LICENSE("GPL");
  38. struct gemini_rtc {
  39. struct rtc_device *dev;
  40. void __iomem *base;
  41. int irq;
  42. };
  43. enum gemini_rtc_offsets {
  44. GEMINI_RTC_SECOND = 0x00,
  45. GEMINI_RTC_MINUTE = 0x04,
  46. GEMINI_RTC_HOUR = 0x08,
  47. GEMINI_RTC_DAYS = 0x0C,
  48. GEMINI_RTC_ALARM_SECOND = 0x10,
  49. GEMINI_RTC_ALARM_MINUTE = 0x14,
  50. GEMINI_RTC_ALARM_HOUR = 0x18,
  51. GEMINI_RTC_RECORD = 0x1C,
  52. GEMINI_RTC_CR = 0x20
  53. };
  54. static irqreturn_t gemini_rtc_interrupt(int irq, void *dev)
  55. {
  56. return IRQ_HANDLED;
  57. }
  58. /*
  59. * Looks like the RTC in the Gemini SoC is (totaly) broken
  60. * We can't read/write directly the time from RTC registers.
  61. * We must do some "offset" calculation to get the real time
  62. *
  63. * The register "day" seams to be fixed, and the register "hour"
  64. * has his own mind.
  65. *
  66. * Maybe we can write directly the hour and days since EPOCH
  67. * but in this case the RTC will recalucate to some (other) strange values.
  68. * If you write time to the registers you will not read the same values.
  69. *
  70. * This FIX works pretty fine and Stormlinksemi aka Cortina-Networks does
  71. * the same thing, without the rtc-lib.c calls.
  72. */
  73. static int gemini_rtc_read_time(struct device *dev, struct rtc_time *tm)
  74. {
  75. struct gemini_rtc *rtc = dev_get_drvdata(dev);
  76. unsigned int days, hour, min, sec;
  77. unsigned long offset, time;
  78. sec = readl(rtc->base + GEMINI_RTC_SECOND);
  79. min = readl(rtc->base + GEMINI_RTC_MINUTE);
  80. hour = readl(rtc->base + GEMINI_RTC_HOUR);
  81. days = readl(rtc->base + GEMINI_RTC_DAYS);
  82. offset = readl(rtc->base + GEMINI_RTC_RECORD);
  83. time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
  84. rtc_time_to_tm(time, tm);
  85. return 0;
  86. }
  87. /*
  88. * Maybe there is some hidden register to care ?
  89. * looks like register GEMINI_RTC_DAY can count
  90. * 365 days * 179 years >= 65535 (uint16)
  91. */
  92. static int gemini_rtc_set_time(struct device *dev, struct rtc_time *tm)
  93. {
  94. struct gemini_rtc *rtc = dev_get_drvdata(dev);
  95. unsigned int sec, min, hour, day;
  96. unsigned long offset, time;
  97. if (tm->tm_year >= 2148) /* EPOCH Year + 179 */
  98. return -EINVAL;
  99. rtc_tm_to_time(tm , &time);
  100. sec = readl(rtc->base + GEMINI_RTC_SECOND);
  101. min = readl(rtc->base + GEMINI_RTC_MINUTE);
  102. hour = readl(rtc->base + GEMINI_RTC_HOUR);
  103. day = readl(rtc->base + GEMINI_RTC_DAYS);
  104. offset = time - (day*86400 + hour*3600 + min*60 + sec);
  105. writel(offset, rtc->base + GEMINI_RTC_RECORD);
  106. writel(0x01, rtc->base + GEMINI_RTC_CR);
  107. return 0;
  108. }
  109. static struct rtc_class_ops gemini_rtc_ops = {
  110. .read_time = gemini_rtc_read_time,
  111. .set_time = gemini_rtc_set_time,
  112. };
  113. static int gemini_rtc_probe(struct platform_device *pdev)
  114. {
  115. struct gemini_rtc *rtc;
  116. struct device *dev = &pdev->dev;
  117. struct resource *res;
  118. int ret;
  119. rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
  120. if (unlikely(!rtc))
  121. return -ENOMEM;
  122. platform_set_drvdata(pdev, rtc);
  123. rtc->irq = platform_get_irq(pdev, 0);
  124. if (rtc->irq < 0) {
  125. ret = -rtc->irq;
  126. goto err_mem;
  127. }
  128. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  129. if (!res) {
  130. ret = -ENODEV;
  131. goto err_mem;
  132. }
  133. rtc->base = devm_ioremap(&pdev->dev, res->start,
  134. res->end - res->start + 1);
  135. ret = request_irq(rtc->irq, gemini_rtc_interrupt,
  136. IRQF_SHARED, pdev->name, dev);
  137. if (unlikely(ret))
  138. goto err_mem;
  139. rtc->dev = rtc_device_register(pdev->name, dev,
  140. &gemini_rtc_ops, THIS_MODULE);
  141. if (unlikely(IS_ERR(rtc->dev))) {
  142. ret = PTR_ERR(rtc->dev);
  143. goto err_irq;
  144. }
  145. return 0;
  146. err_irq:
  147. free_irq(rtc->irq, dev);
  148. err_mem:
  149. kfree(rtc);
  150. return ret;
  151. }
  152. static int gemini_rtc_remove(struct platform_device *pdev)
  153. {
  154. struct gemini_rtc *rtc = platform_get_drvdata(pdev);
  155. struct device *dev = &pdev->dev;
  156. free_irq(rtc->irq, dev);
  157. rtc_device_unregister(rtc->dev);
  158. platform_set_drvdata(pdev, NULL);
  159. kfree(rtc);
  160. return 0;
  161. }
  162. static struct platform_driver gemini_rtc_driver = {
  163. .driver = {
  164. .name = DRV_NAME,
  165. .owner = THIS_MODULE,
  166. },
  167. .probe = gemini_rtc_probe,
  168. .remove = gemini_rtc_remove,
  169. };
  170. static int __init gemini_rtc_init(void)
  171. {
  172. int retval;
  173. retval = platform_driver_register(&gemini_rtc_driver);
  174. if (retval == 0)
  175. pr_info(DRV_NAME ": registered successfully");
  176. return retval;
  177. }
  178. static void __exit gemini_rtc_exit(void)
  179. {
  180. platform_driver_unregister(&gemini_rtc_driver);
  181. }
  182. module_init(gemini_rtc_init);
  183. module_exit(gemini_rtc_exit);