rtc-stmp3xxx.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * Freescale STMP37XX/STMP378X Real Time Clock driver
  3. *
  4. * Copyright (c) 2007 Sigmatel, Inc.
  5. * Peter Hartley, <peter.hartley@sigmatel.com>
  6. *
  7. * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  8. * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  9. * Copyright 2011 Wolfram Sang, Pengutronix e.K.
  10. */
  11. /*
  12. * The code contained herein is licensed under the GNU General Public
  13. * License. You may obtain a copy of the GNU General Public License
  14. * Version 2 or later at the following locations:
  15. *
  16. * http://www.opensource.org/licenses/gpl-license.html
  17. * http://www.gnu.org/copyleft/gpl.html
  18. */
  19. #include <linux/kernel.h>
  20. #include <linux/module.h>
  21. #include <linux/io.h>
  22. #include <linux/init.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/rtc.h>
  26. #include <linux/slab.h>
  27. #include <linux/of_device.h>
  28. #include <linux/of.h>
  29. #include <mach/common.h>
  30. #define STMP3XXX_RTC_CTRL 0x0
  31. #define STMP3XXX_RTC_CTRL_SET 0x4
  32. #define STMP3XXX_RTC_CTRL_CLR 0x8
  33. #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001
  34. #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002
  35. #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004
  36. #define STMP3XXX_RTC_STAT 0x10
  37. #define STMP3XXX_RTC_STAT_STALE_SHIFT 16
  38. #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000
  39. #define STMP3XXX_RTC_SECONDS 0x30
  40. #define STMP3XXX_RTC_ALARM 0x40
  41. #define STMP3XXX_RTC_PERSISTENT0 0x60
  42. #define STMP3XXX_RTC_PERSISTENT0_SET 0x64
  43. #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68
  44. #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002
  45. #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004
  46. #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080
  47. struct stmp3xxx_rtc_data {
  48. struct rtc_device *rtc;
  49. void __iomem *io;
  50. int irq_alarm;
  51. };
  52. static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
  53. {
  54. /*
  55. * The datasheet doesn't say which way round the
  56. * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
  57. * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
  58. */
  59. while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
  60. (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
  61. cpu_relax();
  62. }
  63. /* Time read/write */
  64. static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
  65. {
  66. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  67. stmp3xxx_wait_time(rtc_data);
  68. rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
  69. return 0;
  70. }
  71. static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
  72. {
  73. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  74. writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
  75. stmp3xxx_wait_time(rtc_data);
  76. return 0;
  77. }
  78. /* interrupt(s) handler */
  79. static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
  80. {
  81. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
  82. u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
  83. if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
  84. writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
  85. rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
  86. rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
  87. return IRQ_HANDLED;
  88. }
  89. return IRQ_NONE;
  90. }
  91. static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
  92. {
  93. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  94. if (enabled) {
  95. writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  96. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
  97. rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
  98. writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
  99. rtc_data->io + STMP3XXX_RTC_CTRL_SET);
  100. } else {
  101. writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  102. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
  103. rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
  104. writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
  105. rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
  106. }
  107. return 0;
  108. }
  109. static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
  110. {
  111. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  112. rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
  113. return 0;
  114. }
  115. static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
  116. {
  117. unsigned long t;
  118. struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  119. rtc_tm_to_time(&alm->time, &t);
  120. writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
  121. stmp3xxx_alarm_irq_enable(dev, alm->enabled);
  122. return 0;
  123. }
  124. static struct rtc_class_ops stmp3xxx_rtc_ops = {
  125. .alarm_irq_enable =
  126. stmp3xxx_alarm_irq_enable,
  127. .read_time = stmp3xxx_rtc_gettime,
  128. .set_mmss = stmp3xxx_rtc_set_mmss,
  129. .read_alarm = stmp3xxx_rtc_read_alarm,
  130. .set_alarm = stmp3xxx_rtc_set_alarm,
  131. };
  132. static int stmp3xxx_rtc_remove(struct platform_device *pdev)
  133. {
  134. struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev);
  135. if (!rtc_data)
  136. return 0;
  137. writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
  138. rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
  139. free_irq(rtc_data->irq_alarm, &pdev->dev);
  140. rtc_device_unregister(rtc_data->rtc);
  141. platform_set_drvdata(pdev, NULL);
  142. iounmap(rtc_data->io);
  143. kfree(rtc_data);
  144. return 0;
  145. }
  146. static int stmp3xxx_rtc_probe(struct platform_device *pdev)
  147. {
  148. struct stmp3xxx_rtc_data *rtc_data;
  149. struct resource *r;
  150. int err;
  151. rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
  152. if (!rtc_data)
  153. return -ENOMEM;
  154. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  155. if (!r) {
  156. dev_err(&pdev->dev, "failed to get resource\n");
  157. err = -ENXIO;
  158. goto out_free;
  159. }
  160. rtc_data->io = ioremap(r->start, resource_size(r));
  161. if (!rtc_data->io) {
  162. dev_err(&pdev->dev, "ioremap failed\n");
  163. err = -EIO;
  164. goto out_free;
  165. }
  166. rtc_data->irq_alarm = platform_get_irq(pdev, 0);
  167. if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
  168. STMP3XXX_RTC_STAT_RTC_PRESENT)) {
  169. dev_err(&pdev->dev, "no device onboard\n");
  170. err = -ENODEV;
  171. goto out_remap;
  172. }
  173. platform_set_drvdata(pdev, rtc_data);
  174. mxs_reset_block(rtc_data->io);
  175. writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  176. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
  177. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
  178. rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
  179. writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
  180. STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
  181. rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
  182. rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
  183. &stmp3xxx_rtc_ops, THIS_MODULE);
  184. if (IS_ERR(rtc_data->rtc)) {
  185. err = PTR_ERR(rtc_data->rtc);
  186. goto out_remap;
  187. }
  188. err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0,
  189. "RTC alarm", &pdev->dev);
  190. if (err) {
  191. dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
  192. rtc_data->irq_alarm);
  193. goto out_irq_alarm;
  194. }
  195. return 0;
  196. out_irq_alarm:
  197. rtc_device_unregister(rtc_data->rtc);
  198. out_remap:
  199. platform_set_drvdata(pdev, NULL);
  200. iounmap(rtc_data->io);
  201. out_free:
  202. kfree(rtc_data);
  203. return err;
  204. }
  205. #ifdef CONFIG_PM
  206. static int stmp3xxx_rtc_suspend(struct platform_device *dev, pm_message_t state)
  207. {
  208. return 0;
  209. }
  210. static int stmp3xxx_rtc_resume(struct platform_device *dev)
  211. {
  212. struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
  213. mxs_reset_block(rtc_data->io);
  214. writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  215. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
  216. STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
  217. rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
  218. return 0;
  219. }
  220. #else
  221. #define stmp3xxx_rtc_suspend NULL
  222. #define stmp3xxx_rtc_resume NULL
  223. #endif
  224. static const struct of_device_id rtc_dt_ids[] = {
  225. { .compatible = "fsl,stmp3xxx-rtc", },
  226. { /* sentinel */ }
  227. };
  228. MODULE_DEVICE_TABLE(of, rtc_dt_ids);
  229. static struct platform_driver stmp3xxx_rtcdrv = {
  230. .probe = stmp3xxx_rtc_probe,
  231. .remove = stmp3xxx_rtc_remove,
  232. .suspend = stmp3xxx_rtc_suspend,
  233. .resume = stmp3xxx_rtc_resume,
  234. .driver = {
  235. .name = "stmp3xxx-rtc",
  236. .owner = THIS_MODULE,
  237. .of_match_table = of_match_ptr(rtc_dt_ids),
  238. },
  239. };
  240. module_platform_driver(stmp3xxx_rtcdrv);
  241. MODULE_DESCRIPTION("STMP3xxx RTC Driver");
  242. MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
  243. "Wolfram Sang <w.sang@pengutronix.de>");
  244. MODULE_LICENSE("GPL");