virtio_rtc_class.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * virtio_rtc RTC class driver
  4. *
  5. * Copyright (C) 2023 OpenSynergy GmbH
  6. * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  7. */
  8. #include <linux/math64.h>
  9. #include <linux/overflow.h>
  10. #include <linux/rtc.h>
  11. #include <linux/time64.h>
  12. #include <uapi/linux/virtio_rtc.h>
  13. #include "virtio_rtc_internal.h"
  14. /**
  15. * struct viortc_class - RTC class wrapper
  16. * @viortc: virtio_rtc device data
  17. * @rtc: RTC device
  18. * @vio_clk_id: virtio_rtc clock id
  19. * @stopped: Whether RTC ops are disallowed. Access protected by rtc_lock().
  20. */
  21. struct viortc_class {
  22. struct viortc_dev *viortc;
  23. struct rtc_device *rtc;
  24. u16 vio_clk_id;
  25. bool stopped;
  26. };
  27. /**
  28. * viortc_class_get_locked() - get RTC class wrapper, if ops allowed
  29. * @dev: virtio device
  30. *
  31. * Gets the RTC class wrapper from the virtio device, if it is available and
  32. * ops are allowed.
  33. *
  34. * Context: Caller must hold rtc_lock().
  35. * Return: RTC class wrapper if available and ops allowed, ERR_PTR otherwise.
  36. */
  37. static struct viortc_class *viortc_class_get_locked(struct device *dev)
  38. {
  39. struct viortc_class *viortc_class;
  40. viortc_class = viortc_class_from_dev(dev);
  41. if (IS_ERR(viortc_class))
  42. return viortc_class;
  43. if (viortc_class->stopped)
  44. return ERR_PTR(-EBUSY);
  45. return viortc_class;
  46. }
  47. /**
  48. * viortc_class_read_time() - RTC class op read_time
  49. * @dev: virtio device
  50. * @tm: read time
  51. *
  52. * Context: Process context.
  53. * Return: Zero on success, negative error code otherwise.
  54. */
  55. static int viortc_class_read_time(struct device *dev, struct rtc_time *tm)
  56. {
  57. struct viortc_class *viortc_class;
  58. time64_t sec;
  59. int ret;
  60. u64 ns;
  61. viortc_class = viortc_class_get_locked(dev);
  62. if (IS_ERR(viortc_class))
  63. return PTR_ERR(viortc_class);
  64. ret = viortc_read(viortc_class->viortc, viortc_class->vio_clk_id, &ns);
  65. if (ret)
  66. return ret;
  67. sec = div_u64(ns, NSEC_PER_SEC);
  68. rtc_time64_to_tm(sec, tm);
  69. return 0;
  70. }
  71. /**
  72. * viortc_class_read_alarm() - RTC class op read_alarm
  73. * @dev: virtio device
  74. * @alrm: alarm read out
  75. *
  76. * Context: Process context.
  77. * Return: Zero on success, negative error code otherwise.
  78. */
  79. static int viortc_class_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  80. {
  81. struct viortc_class *viortc_class;
  82. time64_t alarm_time_sec;
  83. u64 alarm_time_ns;
  84. bool enabled;
  85. int ret;
  86. viortc_class = viortc_class_get_locked(dev);
  87. if (IS_ERR(viortc_class))
  88. return PTR_ERR(viortc_class);
  89. ret = viortc_read_alarm(viortc_class->viortc, viortc_class->vio_clk_id,
  90. &alarm_time_ns, &enabled);
  91. if (ret)
  92. return ret;
  93. alarm_time_sec = div_u64(alarm_time_ns, NSEC_PER_SEC);
  94. rtc_time64_to_tm(alarm_time_sec, &alrm->time);
  95. alrm->enabled = enabled;
  96. return 0;
  97. }
  98. /**
  99. * viortc_class_set_alarm() - RTC class op set_alarm
  100. * @dev: virtio device
  101. * @alrm: alarm to set
  102. *
  103. * Context: Process context.
  104. * Return: Zero on success, negative error code otherwise.
  105. */
  106. static int viortc_class_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  107. {
  108. struct viortc_class *viortc_class;
  109. time64_t alarm_time_sec;
  110. u64 alarm_time_ns;
  111. viortc_class = viortc_class_get_locked(dev);
  112. if (IS_ERR(viortc_class))
  113. return PTR_ERR(viortc_class);
  114. alarm_time_sec = rtc_tm_to_time64(&alrm->time);
  115. if (alarm_time_sec < 0)
  116. return -EINVAL;
  117. if (check_mul_overflow((u64)alarm_time_sec, (u64)NSEC_PER_SEC,
  118. &alarm_time_ns))
  119. return -EINVAL;
  120. return viortc_set_alarm(viortc_class->viortc, viortc_class->vio_clk_id,
  121. alarm_time_ns, alrm->enabled);
  122. }
  123. /**
  124. * viortc_class_alarm_irq_enable() - RTC class op alarm_irq_enable
  125. * @dev: virtio device
  126. * @enabled: enable or disable alarm IRQ
  127. *
  128. * Context: Process context.
  129. * Return: Zero on success, negative error code otherwise.
  130. */
  131. static int viortc_class_alarm_irq_enable(struct device *dev,
  132. unsigned int enabled)
  133. {
  134. struct viortc_class *viortc_class;
  135. viortc_class = viortc_class_get_locked(dev);
  136. if (IS_ERR(viortc_class))
  137. return PTR_ERR(viortc_class);
  138. return viortc_set_alarm_enabled(viortc_class->viortc,
  139. viortc_class->vio_clk_id, enabled);
  140. }
  141. static const struct rtc_class_ops viortc_class_ops = {
  142. .read_time = viortc_class_read_time,
  143. .read_alarm = viortc_class_read_alarm,
  144. .set_alarm = viortc_class_set_alarm,
  145. .alarm_irq_enable = viortc_class_alarm_irq_enable,
  146. };
  147. /**
  148. * viortc_class_alarm() - propagate alarm notification as alarm interrupt
  149. * @viortc_class: RTC class wrapper
  150. * @vio_clk_id: virtio_rtc clock id
  151. *
  152. * Context: Any context.
  153. */
  154. void viortc_class_alarm(struct viortc_class *viortc_class, u16 vio_clk_id)
  155. {
  156. if (vio_clk_id != viortc_class->vio_clk_id) {
  157. dev_warn_ratelimited(&viortc_class->rtc->dev,
  158. "ignoring alarm for clock id %d, expected id %d\n",
  159. vio_clk_id, viortc_class->vio_clk_id);
  160. return;
  161. }
  162. rtc_update_irq(viortc_class->rtc, 1, RTC_AF | RTC_IRQF);
  163. }
  164. /**
  165. * viortc_class_stop() - disallow RTC class ops
  166. * @viortc_class: RTC class wrapper
  167. *
  168. * Context: Process context. Caller must NOT hold rtc_lock().
  169. */
  170. void viortc_class_stop(struct viortc_class *viortc_class)
  171. {
  172. rtc_lock(viortc_class->rtc);
  173. viortc_class->stopped = true;
  174. rtc_unlock(viortc_class->rtc);
  175. }
  176. /**
  177. * viortc_class_register() - register RTC class device
  178. * @viortc_class: RTC class wrapper
  179. *
  180. * Context: Process context.
  181. * Return: Zero on success, negative error code otherwise.
  182. */
  183. int viortc_class_register(struct viortc_class *viortc_class)
  184. {
  185. return devm_rtc_register_device(viortc_class->rtc);
  186. }
  187. /**
  188. * viortc_class_init() - init RTC class wrapper and device
  189. * @viortc: device data
  190. * @vio_clk_id: virtio_rtc clock id
  191. * @have_alarm: have alarm feature
  192. * @parent_dev: virtio device
  193. *
  194. * Context: Process context.
  195. * Return: RTC class wrapper on success, ERR_PTR otherwise.
  196. */
  197. struct viortc_class *viortc_class_init(struct viortc_dev *viortc,
  198. u16 vio_clk_id, bool have_alarm,
  199. struct device *parent_dev)
  200. {
  201. struct viortc_class *viortc_class;
  202. struct rtc_device *rtc;
  203. viortc_class =
  204. devm_kzalloc(parent_dev, sizeof(*viortc_class), GFP_KERNEL);
  205. if (!viortc_class)
  206. return ERR_PTR(-ENOMEM);
  207. rtc = devm_rtc_allocate_device(parent_dev);
  208. if (IS_ERR(rtc))
  209. return ERR_CAST(rtc);
  210. viortc_class->viortc = viortc;
  211. viortc_class->rtc = rtc;
  212. viortc_class->vio_clk_id = vio_clk_id;
  213. if (!have_alarm)
  214. clear_bit(RTC_FEATURE_ALARM, rtc->features);
  215. clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
  216. rtc->ops = &viortc_class_ops;
  217. rtc->range_max = div_u64(U64_MAX, NSEC_PER_SEC);
  218. return viortc_class;
  219. }