rtc-goldfish.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* drivers/rtc/rtc-goldfish.c
  3. *
  4. * Copyright (C) 2007 Google, Inc.
  5. * Copyright (C) 2017 Imagination Technologies Ltd.
  6. */
  7. #include <linux/io.h>
  8. #include <linux/module.h>
  9. #include <linux/of.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/rtc.h>
  12. #define TIMER_TIME_LOW 0x00 /* get low bits of current time */
  13. /* and update TIMER_TIME_HIGH */
  14. #define TIMER_TIME_HIGH 0x04 /* get high bits of time at last */
  15. /* TIMER_TIME_LOW read */
  16. #define TIMER_ALARM_LOW 0x08 /* set low bits of alarm and */
  17. /* activate it */
  18. #define TIMER_ALARM_HIGH 0x0c /* set high bits of next alarm */
  19. #define TIMER_IRQ_ENABLED 0x10
  20. #define TIMER_CLEAR_ALARM 0x14
  21. #define TIMER_ALARM_STATUS 0x18
  22. #define TIMER_CLEAR_INTERRUPT 0x1c
  23. struct goldfish_rtc {
  24. void __iomem *base;
  25. int irq;
  26. struct rtc_device *rtc;
  27. };
  28. static int goldfish_rtc_read_alarm(struct device *dev,
  29. struct rtc_wkalrm *alrm)
  30. {
  31. u64 rtc_alarm;
  32. u64 rtc_alarm_low;
  33. u64 rtc_alarm_high;
  34. void __iomem *base;
  35. struct goldfish_rtc *rtcdrv;
  36. rtcdrv = dev_get_drvdata(dev);
  37. base = rtcdrv->base;
  38. rtc_alarm_low = readl(base + TIMER_ALARM_LOW);
  39. rtc_alarm_high = readl(base + TIMER_ALARM_HIGH);
  40. rtc_alarm = (rtc_alarm_high << 32) | rtc_alarm_low;
  41. do_div(rtc_alarm, NSEC_PER_SEC);
  42. memset(alrm, 0, sizeof(struct rtc_wkalrm));
  43. rtc_time64_to_tm(rtc_alarm, &alrm->time);
  44. if (readl(base + TIMER_ALARM_STATUS))
  45. alrm->enabled = 1;
  46. else
  47. alrm->enabled = 0;
  48. return 0;
  49. }
  50. static int goldfish_rtc_set_alarm(struct device *dev,
  51. struct rtc_wkalrm *alrm)
  52. {
  53. struct goldfish_rtc *rtcdrv;
  54. u64 rtc_alarm64;
  55. u64 rtc_status_reg;
  56. void __iomem *base;
  57. rtcdrv = dev_get_drvdata(dev);
  58. base = rtcdrv->base;
  59. if (alrm->enabled) {
  60. rtc_alarm64 = rtc_tm_to_time64(&alrm->time) * NSEC_PER_SEC;
  61. writel((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH);
  62. writel(rtc_alarm64, base + TIMER_ALARM_LOW);
  63. writel(1, base + TIMER_IRQ_ENABLED);
  64. } else {
  65. /*
  66. * if this function was called with enabled=0
  67. * then it could mean that the application is
  68. * trying to cancel an ongoing alarm
  69. */
  70. rtc_status_reg = readl(base + TIMER_ALARM_STATUS);
  71. if (rtc_status_reg)
  72. writel(1, base + TIMER_CLEAR_ALARM);
  73. }
  74. return 0;
  75. }
  76. static int goldfish_rtc_alarm_irq_enable(struct device *dev,
  77. unsigned int enabled)
  78. {
  79. void __iomem *base;
  80. struct goldfish_rtc *rtcdrv;
  81. rtcdrv = dev_get_drvdata(dev);
  82. base = rtcdrv->base;
  83. if (enabled)
  84. writel(1, base + TIMER_IRQ_ENABLED);
  85. else
  86. writel(0, base + TIMER_IRQ_ENABLED);
  87. return 0;
  88. }
  89. static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id)
  90. {
  91. struct goldfish_rtc *rtcdrv = dev_id;
  92. void __iomem *base = rtcdrv->base;
  93. writel(1, base + TIMER_CLEAR_INTERRUPT);
  94. rtc_update_irq(rtcdrv->rtc, 1, RTC_IRQF | RTC_AF);
  95. return IRQ_HANDLED;
  96. }
  97. static int goldfish_rtc_read_time(struct device *dev, struct rtc_time *tm)
  98. {
  99. struct goldfish_rtc *rtcdrv;
  100. void __iomem *base;
  101. u64 time_high;
  102. u64 time_low;
  103. u64 time;
  104. rtcdrv = dev_get_drvdata(dev);
  105. base = rtcdrv->base;
  106. time_low = readl(base + TIMER_TIME_LOW);
  107. time_high = readl(base + TIMER_TIME_HIGH);
  108. time = (time_high << 32) | time_low;
  109. do_div(time, NSEC_PER_SEC);
  110. rtc_time64_to_tm(time, tm);
  111. return 0;
  112. }
  113. static int goldfish_rtc_set_time(struct device *dev, struct rtc_time *tm)
  114. {
  115. struct goldfish_rtc *rtcdrv;
  116. void __iomem *base;
  117. u64 now64;
  118. rtcdrv = dev_get_drvdata(dev);
  119. base = rtcdrv->base;
  120. now64 = rtc_tm_to_time64(tm) * NSEC_PER_SEC;
  121. writel((now64 >> 32), base + TIMER_TIME_HIGH);
  122. writel(now64, base + TIMER_TIME_LOW);
  123. return 0;
  124. }
  125. static const struct rtc_class_ops goldfish_rtc_ops = {
  126. .read_time = goldfish_rtc_read_time,
  127. .set_time = goldfish_rtc_set_time,
  128. .read_alarm = goldfish_rtc_read_alarm,
  129. .set_alarm = goldfish_rtc_set_alarm,
  130. .alarm_irq_enable = goldfish_rtc_alarm_irq_enable
  131. };
  132. static int goldfish_rtc_probe(struct platform_device *pdev)
  133. {
  134. struct goldfish_rtc *rtcdrv;
  135. int err;
  136. rtcdrv = devm_kzalloc(&pdev->dev, sizeof(*rtcdrv), GFP_KERNEL);
  137. if (!rtcdrv)
  138. return -ENOMEM;
  139. platform_set_drvdata(pdev, rtcdrv);
  140. rtcdrv->base = devm_platform_ioremap_resource(pdev, 0);
  141. if (IS_ERR(rtcdrv->base))
  142. return PTR_ERR(rtcdrv->base);
  143. rtcdrv->irq = platform_get_irq(pdev, 0);
  144. if (rtcdrv->irq < 0)
  145. return -ENODEV;
  146. rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev);
  147. if (IS_ERR(rtcdrv->rtc))
  148. return PTR_ERR(rtcdrv->rtc);
  149. rtcdrv->rtc->ops = &goldfish_rtc_ops;
  150. rtcdrv->rtc->range_max = U64_MAX / NSEC_PER_SEC;
  151. err = devm_request_irq(&pdev->dev, rtcdrv->irq,
  152. goldfish_rtc_interrupt,
  153. 0, pdev->name, rtcdrv);
  154. if (err)
  155. return err;
  156. return rtc_register_device(rtcdrv->rtc);
  157. }
  158. static const struct of_device_id goldfish_rtc_of_match[] = {
  159. { .compatible = "google,goldfish-rtc", },
  160. {},
  161. };
  162. MODULE_DEVICE_TABLE(of, goldfish_rtc_of_match);
  163. static struct platform_driver goldfish_rtc = {
  164. .probe = goldfish_rtc_probe,
  165. .driver = {
  166. .name = "goldfish_rtc",
  167. .of_match_table = goldfish_rtc_of_match,
  168. }
  169. };
  170. module_platform_driver(goldfish_rtc);
  171. MODULE_LICENSE("GPL v2");