virtio_rtc_ptp.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Expose virtio_rtc clocks as PTP clocks.
  4. *
  5. * Copyright (C) 2022-2023 OpenSynergy GmbH
  6. * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  7. *
  8. * Derived from ptp_kvm_common.c, virtual PTP 1588 clock for use with KVM
  9. * guests.
  10. *
  11. * Copyright (C) 2017 Red Hat Inc.
  12. */
  13. #include <linux/device.h>
  14. #include <linux/err.h>
  15. #include <linux/ptp_clock_kernel.h>
  16. #include <uapi/linux/virtio_rtc.h>
  17. #include "virtio_rtc_internal.h"
  18. /**
  19. * struct viortc_ptp_clock - PTP clock abstraction
  20. * @ptp_clock: PTP clock handle for unregistering
  21. * @viortc: virtio_rtc device data
  22. * @ptp_info: PTP clock description
  23. * @vio_clk_id: virtio_rtc clock id
  24. * @have_cross: device supports crosststamp with available HW counter
  25. */
  26. struct viortc_ptp_clock {
  27. struct ptp_clock *ptp_clock;
  28. struct viortc_dev *viortc;
  29. struct ptp_clock_info ptp_info;
  30. u16 vio_clk_id;
  31. bool have_cross;
  32. };
  33. /**
  34. * struct viortc_ptp_cross_ctx - context for get_device_system_crosststamp()
  35. * @device_time: device clock reading
  36. * @system_counterval: HW counter value at device_time
  37. *
  38. * Provides the already obtained crosststamp to get_device_system_crosststamp().
  39. */
  40. struct viortc_ptp_cross_ctx {
  41. ktime_t device_time;
  42. struct system_counterval_t system_counterval;
  43. };
  44. /* Weak function in case get_device_system_crosststamp() is not supported */
  45. int __weak viortc_hw_xtstamp_params(u8 *hw_counter, enum clocksource_ids *cs_id)
  46. {
  47. return -EOPNOTSUPP;
  48. }
  49. /**
  50. * viortc_ptp_get_time_fn() - callback for get_device_system_crosststamp()
  51. * @device_time: device clock reading
  52. * @system_counterval: HW counter value at device_time
  53. * @ctx: context with already obtained crosststamp
  54. *
  55. * Return: zero (success).
  56. */
  57. static int viortc_ptp_get_time_fn(ktime_t *device_time,
  58. struct system_counterval_t *system_counterval,
  59. void *ctx)
  60. {
  61. struct viortc_ptp_cross_ctx *vio_ctx = ctx;
  62. *device_time = vio_ctx->device_time;
  63. *system_counterval = vio_ctx->system_counterval;
  64. return 0;
  65. }
  66. /**
  67. * viortc_ptp_do_xtstamp() - get crosststamp from device
  68. * @vio_ptp: virtio_rtc PTP clock
  69. * @hw_counter: virtio_rtc HW counter type
  70. * @cs_id: clocksource id corresponding to hw_counter
  71. * @ctx: context for get_device_system_crosststamp()
  72. *
  73. * Reads HW-specific crosststamp from device.
  74. *
  75. * Context: Process context.
  76. * Return: Zero on success, negative error code otherwise.
  77. */
  78. static int viortc_ptp_do_xtstamp(struct viortc_ptp_clock *vio_ptp,
  79. u8 hw_counter, enum clocksource_ids cs_id,
  80. struct viortc_ptp_cross_ctx *ctx)
  81. {
  82. u64 max_ns, ns;
  83. int ret;
  84. ctx->system_counterval.cs_id = cs_id;
  85. ret = viortc_read_cross(vio_ptp->viortc, vio_ptp->vio_clk_id,
  86. hw_counter, &ns,
  87. &ctx->system_counterval.cycles);
  88. if (ret)
  89. return ret;
  90. max_ns = (u64)ktime_to_ns(KTIME_MAX);
  91. if (ns > max_ns)
  92. return -EINVAL;
  93. ctx->device_time = ns_to_ktime(ns);
  94. return 0;
  95. }
  96. /*
  97. * PTP clock operations
  98. */
  99. /**
  100. * viortc_ptp_getcrosststamp() - PTP clock getcrosststamp op
  101. * @ptp: PTP clock info
  102. * @xtstamp: crosststamp
  103. *
  104. * Context: Process context.
  105. * Return: Zero on success, negative error code otherwise.
  106. */
  107. static int viortc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
  108. struct system_device_crosststamp *xtstamp)
  109. {
  110. struct viortc_ptp_clock *vio_ptp =
  111. container_of(ptp, struct viortc_ptp_clock, ptp_info);
  112. struct system_time_snapshot history_begin;
  113. struct viortc_ptp_cross_ctx ctx;
  114. enum clocksource_ids cs_id;
  115. u8 hw_counter;
  116. int ret;
  117. if (!vio_ptp->have_cross)
  118. return -EOPNOTSUPP;
  119. ret = viortc_hw_xtstamp_params(&hw_counter, &cs_id);
  120. if (ret)
  121. return ret;
  122. ktime_get_snapshot(&history_begin);
  123. if (history_begin.cs_id != cs_id)
  124. return -EOPNOTSUPP;
  125. /*
  126. * Getting the timestamp can take many milliseconds with a slow Virtio
  127. * device. This is too long for viortc_ptp_get_time_fn() passed to
  128. * get_device_system_crosststamp(), which has to usually return before
  129. * the timekeeper seqcount increases (every tick or so).
  130. *
  131. * So, get the actual cross-timestamp first.
  132. */
  133. ret = viortc_ptp_do_xtstamp(vio_ptp, hw_counter, cs_id, &ctx);
  134. if (ret)
  135. return ret;
  136. ret = get_device_system_crosststamp(viortc_ptp_get_time_fn, &ctx,
  137. &history_begin, xtstamp);
  138. if (ret)
  139. pr_debug("%s: get_device_system_crosststamp() returned %d\n",
  140. __func__, ret);
  141. return ret;
  142. }
  143. /* viortc_ptp_adjfine() - unsupported PTP clock adjfine op */
  144. static int viortc_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
  145. {
  146. return -EOPNOTSUPP;
  147. }
  148. /* viortc_ptp_adjtime() - unsupported PTP clock adjtime op */
  149. static int viortc_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
  150. {
  151. return -EOPNOTSUPP;
  152. }
  153. /* viortc_ptp_settime64() - unsupported PTP clock settime64 op */
  154. static int viortc_ptp_settime64(struct ptp_clock_info *ptp,
  155. const struct timespec64 *ts)
  156. {
  157. return -EOPNOTSUPP;
  158. }
  159. /*
  160. * viortc_ptp_gettimex64() - PTP clock gettimex64 op
  161. *
  162. * Context: Process context.
  163. */
  164. static int viortc_ptp_gettimex64(struct ptp_clock_info *ptp,
  165. struct timespec64 *ts,
  166. struct ptp_system_timestamp *sts)
  167. {
  168. struct viortc_ptp_clock *vio_ptp =
  169. container_of(ptp, struct viortc_ptp_clock, ptp_info);
  170. int ret;
  171. u64 ns;
  172. ptp_read_system_prets(sts);
  173. ret = viortc_read(vio_ptp->viortc, vio_ptp->vio_clk_id, &ns);
  174. ptp_read_system_postts(sts);
  175. if (ret)
  176. return ret;
  177. if (ns > (u64)S64_MAX)
  178. return -EINVAL;
  179. *ts = ns_to_timespec64((s64)ns);
  180. return 0;
  181. }
  182. /* viortc_ptp_enable() - unsupported PTP clock enable op */
  183. static int viortc_ptp_enable(struct ptp_clock_info *ptp,
  184. struct ptp_clock_request *rq, int on)
  185. {
  186. return -EOPNOTSUPP;
  187. }
  188. /*
  189. * viortc_ptp_info_template - ptp_clock_info template
  190. *
  191. * The .name member will be set for individual virtio_rtc PTP clocks.
  192. *
  193. * The .getcrosststamp member will be cleared for PTP clocks not supporting
  194. * crosststamp.
  195. */
  196. static const struct ptp_clock_info viortc_ptp_info_template = {
  197. .owner = THIS_MODULE,
  198. /* .name is set according to clock type */
  199. .adjfine = viortc_ptp_adjfine,
  200. .adjtime = viortc_ptp_adjtime,
  201. .gettimex64 = viortc_ptp_gettimex64,
  202. .settime64 = viortc_ptp_settime64,
  203. .enable = viortc_ptp_enable,
  204. .getcrosststamp = viortc_ptp_getcrosststamp,
  205. };
  206. /**
  207. * viortc_ptp_unregister() - PTP clock unregistering wrapper
  208. * @vio_ptp: virtio_rtc PTP clock
  209. * @parent_dev: parent device of PTP clock
  210. *
  211. * Return: Zero on success, negative error code otherwise.
  212. */
  213. int viortc_ptp_unregister(struct viortc_ptp_clock *vio_ptp,
  214. struct device *parent_dev)
  215. {
  216. int ret = ptp_clock_unregister(vio_ptp->ptp_clock);
  217. if (!ret)
  218. devm_kfree(parent_dev, vio_ptp);
  219. return ret;
  220. }
  221. /**
  222. * viortc_ptp_get_cross_cap() - get xtstamp support info from device
  223. * @viortc: virtio_rtc device data
  224. * @vio_ptp: virtio_rtc PTP clock abstraction
  225. *
  226. * Context: Process context.
  227. * Return: Zero on success, negative error code otherwise.
  228. */
  229. static int viortc_ptp_get_cross_cap(struct viortc_dev *viortc,
  230. struct viortc_ptp_clock *vio_ptp)
  231. {
  232. enum clocksource_ids cs_id;
  233. bool xtstamp_supported;
  234. u8 hw_counter;
  235. int ret;
  236. ret = viortc_hw_xtstamp_params(&hw_counter, &cs_id);
  237. if (ret) {
  238. vio_ptp->have_cross = false;
  239. return 0;
  240. }
  241. ret = viortc_cross_cap(viortc, vio_ptp->vio_clk_id, hw_counter,
  242. &xtstamp_supported);
  243. if (ret)
  244. return ret;
  245. vio_ptp->have_cross = xtstamp_supported;
  246. return 0;
  247. }
  248. /**
  249. * viortc_ptp_register() - prepare and register PTP clock
  250. * @viortc: virtio_rtc device data
  251. * @parent_dev: parent device for PTP clock
  252. * @vio_clk_id: id of virtio_rtc clock which backs PTP clock
  253. * @ptp_clock_name: PTP clock name
  254. *
  255. * Context: Process context.
  256. * Return: Pointer on success, ERR_PTR() otherwise; NULL if PTP clock support
  257. * not available.
  258. */
  259. struct viortc_ptp_clock *viortc_ptp_register(struct viortc_dev *viortc,
  260. struct device *parent_dev,
  261. u16 vio_clk_id,
  262. const char *ptp_clock_name)
  263. {
  264. struct viortc_ptp_clock *vio_ptp;
  265. struct ptp_clock *ptp_clock;
  266. ssize_t len;
  267. int ret;
  268. vio_ptp = devm_kzalloc(parent_dev, sizeof(*vio_ptp), GFP_KERNEL);
  269. if (!vio_ptp)
  270. return ERR_PTR(-ENOMEM);
  271. vio_ptp->viortc = viortc;
  272. vio_ptp->vio_clk_id = vio_clk_id;
  273. vio_ptp->ptp_info = viortc_ptp_info_template;
  274. len = strscpy(vio_ptp->ptp_info.name, ptp_clock_name,
  275. sizeof(vio_ptp->ptp_info.name));
  276. if (len < 0) {
  277. ret = len;
  278. goto err_free_dev;
  279. }
  280. ret = viortc_ptp_get_cross_cap(viortc, vio_ptp);
  281. if (ret)
  282. goto err_free_dev;
  283. if (!vio_ptp->have_cross)
  284. vio_ptp->ptp_info.getcrosststamp = NULL;
  285. ptp_clock = ptp_clock_register(&vio_ptp->ptp_info, parent_dev);
  286. if (IS_ERR(ptp_clock))
  287. goto err_on_register;
  288. vio_ptp->ptp_clock = ptp_clock;
  289. return vio_ptp;
  290. err_on_register:
  291. ret = PTR_ERR(ptp_clock);
  292. err_free_dev:
  293. devm_kfree(parent_dev, vio_ptp);
  294. return ERR_PTR(ret);
  295. }