rtc-pl031.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * drivers/rtc/rtc-pl031.c
  3. *
  4. * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
  5. *
  6. * Author: Deepak Saxena <dsaxena@plexity.net>
  7. *
  8. * Copyright 2006 (c) MontaVista Software, Inc.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version
  13. * 2 of the License, or (at your option) any later version.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/rtc.h>
  17. #include <linux/init.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/amba/bus.h>
  20. #include <linux/io.h>
  21. /*
  22. * Register definitions
  23. */
  24. #define RTC_DR 0x00 /* Data read register */
  25. #define RTC_MR 0x04 /* Match register */
  26. #define RTC_LR 0x08 /* Data load register */
  27. #define RTC_CR 0x0c /* Control register */
  28. #define RTC_IMSC 0x10 /* Interrupt mask and set register */
  29. #define RTC_RIS 0x14 /* Raw interrupt status register */
  30. #define RTC_MIS 0x18 /* Masked interrupt status register */
  31. #define RTC_ICR 0x1c /* Interrupt clear register */
  32. struct pl031_local {
  33. struct rtc_device *rtc;
  34. void __iomem *base;
  35. };
  36. static irqreturn_t pl031_interrupt(int irq, void *dev_id)
  37. {
  38. struct rtc_device *rtc = dev_id;
  39. rtc_update_irq(rtc, 1, RTC_AF);
  40. return IRQ_HANDLED;
  41. }
  42. static int pl031_open(struct device *dev)
  43. {
  44. /*
  45. * We request IRQ in pl031_probe, so nothing to do here...
  46. */
  47. return 0;
  48. }
  49. static void pl031_release(struct device *dev)
  50. {
  51. }
  52. static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
  53. {
  54. struct pl031_local *ldata = dev_get_drvdata(dev);
  55. switch (cmd) {
  56. case RTC_AIE_OFF:
  57. __raw_writel(1, ldata->base + RTC_MIS);
  58. return 0;
  59. case RTC_AIE_ON:
  60. __raw_writel(0, ldata->base + RTC_MIS);
  61. return 0;
  62. }
  63. return -ENOIOCTLCMD;
  64. }
  65. static int pl031_read_time(struct device *dev, struct rtc_time *tm)
  66. {
  67. struct pl031_local *ldata = dev_get_drvdata(dev);
  68. rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm);
  69. return 0;
  70. }
  71. static int pl031_set_time(struct device *dev, struct rtc_time *tm)
  72. {
  73. unsigned long time;
  74. struct pl031_local *ldata = dev_get_drvdata(dev);
  75. rtc_tm_to_time(tm, &time);
  76. __raw_writel(time, ldata->base + RTC_LR);
  77. return 0;
  78. }
  79. static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
  80. {
  81. struct pl031_local *ldata = dev_get_drvdata(dev);
  82. rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time);
  83. alarm->pending = __raw_readl(ldata->base + RTC_RIS);
  84. alarm->enabled = __raw_readl(ldata->base + RTC_IMSC);
  85. return 0;
  86. }
  87. static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
  88. {
  89. struct pl031_local *ldata = dev_get_drvdata(dev);
  90. unsigned long time;
  91. rtc_tm_to_time(&alarm->time, &time);
  92. __raw_writel(time, ldata->base + RTC_MR);
  93. __raw_writel(!alarm->enabled, ldata->base + RTC_MIS);
  94. return 0;
  95. }
  96. static const struct rtc_class_ops pl031_ops = {
  97. .open = pl031_open,
  98. .release = pl031_release,
  99. .ioctl = pl031_ioctl,
  100. .read_time = pl031_read_time,
  101. .set_time = pl031_set_time,
  102. .read_alarm = pl031_read_alarm,
  103. .set_alarm = pl031_set_alarm,
  104. };
  105. static int pl031_remove(struct amba_device *adev)
  106. {
  107. struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
  108. amba_set_drvdata(adev, NULL);
  109. free_irq(adev->irq[0], ldata->rtc);
  110. rtc_device_unregister(ldata->rtc);
  111. iounmap(ldata->base);
  112. kfree(ldata);
  113. amba_release_regions(adev);
  114. return 0;
  115. }
  116. static int pl031_probe(struct amba_device *adev, void *id)
  117. {
  118. int ret;
  119. struct pl031_local *ldata;
  120. ret = amba_request_regions(adev, NULL);
  121. if (ret)
  122. goto err_req;
  123. ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL);
  124. if (!ldata) {
  125. ret = -ENOMEM;
  126. goto out;
  127. }
  128. ldata->base = ioremap(adev->res.start,
  129. adev->res.end - adev->res.start + 1);
  130. if (!ldata->base) {
  131. ret = -ENOMEM;
  132. goto out_no_remap;
  133. }
  134. amba_set_drvdata(adev, ldata);
  135. if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED,
  136. "rtc-pl031", ldata->rtc)) {
  137. ret = -EIO;
  138. goto out_no_irq;
  139. }
  140. ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops,
  141. THIS_MODULE);
  142. if (IS_ERR(ldata->rtc)) {
  143. ret = PTR_ERR(ldata->rtc);
  144. goto out_no_rtc;
  145. }
  146. return 0;
  147. out_no_rtc:
  148. free_irq(adev->irq[0], ldata->rtc);
  149. out_no_irq:
  150. iounmap(ldata->base);
  151. amba_set_drvdata(adev, NULL);
  152. out_no_remap:
  153. kfree(ldata);
  154. out:
  155. amba_release_regions(adev);
  156. err_req:
  157. return ret;
  158. }
  159. static struct amba_id pl031_ids[] __initdata = {
  160. {
  161. .id = 0x00041031,
  162. .mask = 0x000fffff, },
  163. {0, 0},
  164. };
  165. static struct amba_driver pl031_driver = {
  166. .drv = {
  167. .name = "rtc-pl031",
  168. },
  169. .id_table = pl031_ids,
  170. .probe = pl031_probe,
  171. .remove = pl031_remove,
  172. };
  173. static int __init pl031_init(void)
  174. {
  175. return amba_driver_register(&pl031_driver);
  176. }
  177. static void __exit pl031_exit(void)
  178. {
  179. amba_driver_unregister(&pl031_driver);
  180. }
  181. module_init(pl031_init);
  182. module_exit(pl031_exit);
  183. MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
  184. MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
  185. MODULE_LICENSE("GPL");