stmmac_ptp.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*******************************************************************************
  3. PTP 1588 clock using the STMMAC.
  4. Copyright (C) 2013 Vayavya Labs Pvt Ltd
  5. Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
  6. *******************************************************************************/
  7. #include "stmmac.h"
  8. #include "stmmac_ptp.h"
  9. #include "dwmac4.h"
  10. /**
  11. * stmmac_adjust_freq
  12. *
  13. * @ptp: pointer to ptp_clock_info structure
  14. * @scaled_ppm: desired period change in scaled parts per million
  15. *
  16. * Description: this function will adjust the frequency of hardware clock.
  17. *
  18. * Scaled parts per million is ppm with a 16-bit binary fractional field.
  19. */
  20. static int stmmac_adjust_freq(struct ptp_clock_info *ptp, long scaled_ppm)
  21. {
  22. struct stmmac_priv *priv =
  23. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  24. unsigned long flags;
  25. u32 addend;
  26. addend = adjust_by_scaled_ppm(priv->default_addend, scaled_ppm);
  27. write_lock_irqsave(&priv->ptp_lock, flags);
  28. stmmac_config_addend(priv, priv->ptpaddr, addend);
  29. write_unlock_irqrestore(&priv->ptp_lock, flags);
  30. return 0;
  31. }
  32. /**
  33. * stmmac_adjust_time
  34. *
  35. * @ptp: pointer to ptp_clock_info structure
  36. * @delta: desired change in nanoseconds
  37. *
  38. * Description: this function will shift/adjust the hardware clock time.
  39. */
  40. static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
  41. {
  42. struct stmmac_priv *priv =
  43. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  44. unsigned long flags;
  45. u32 sec, nsec;
  46. u32 quotient, reminder;
  47. int neg_adj = 0;
  48. bool xmac, est_rst = false;
  49. int ret;
  50. xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
  51. if (delta < 0) {
  52. neg_adj = 1;
  53. delta = -delta;
  54. }
  55. quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
  56. sec = quotient;
  57. nsec = reminder;
  58. /* If EST is enabled, disabled it before adjust ptp time. */
  59. if (priv->est && priv->est->enable) {
  60. est_rst = true;
  61. mutex_lock(&priv->est_lock);
  62. priv->est->enable = false;
  63. stmmac_est_configure(priv, priv, priv->est,
  64. priv->plat->clk_ptp_rate);
  65. mutex_unlock(&priv->est_lock);
  66. }
  67. write_lock_irqsave(&priv->ptp_lock, flags);
  68. stmmac_adjust_systime(priv, priv->ptpaddr, sec, nsec, neg_adj, xmac);
  69. write_unlock_irqrestore(&priv->ptp_lock, flags);
  70. /* Calculate new basetime and re-configured EST after PTP time adjust. */
  71. if (est_rst) {
  72. struct timespec64 current_time, time;
  73. ktime_t current_time_ns, basetime;
  74. u64 cycle_time;
  75. mutex_lock(&priv->est_lock);
  76. priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, &current_time);
  77. current_time_ns = timespec64_to_ktime(current_time);
  78. time.tv_nsec = priv->est->btr_reserve[0];
  79. time.tv_sec = priv->est->btr_reserve[1];
  80. basetime = timespec64_to_ktime(time);
  81. cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC +
  82. priv->est->ctr[0];
  83. time = stmmac_calc_tas_basetime(basetime,
  84. current_time_ns,
  85. cycle_time);
  86. priv->est->btr[0] = (u32)time.tv_nsec;
  87. priv->est->btr[1] = (u32)time.tv_sec;
  88. priv->est->enable = true;
  89. ret = stmmac_est_configure(priv, priv, priv->est,
  90. priv->plat->clk_ptp_rate);
  91. mutex_unlock(&priv->est_lock);
  92. if (ret)
  93. netdev_err(priv->dev, "failed to configure EST\n");
  94. }
  95. return 0;
  96. }
  97. /**
  98. * stmmac_get_time
  99. *
  100. * @ptp: pointer to ptp_clock_info structure
  101. * @ts: pointer to hold time/result
  102. *
  103. * Description: this function will read the current time from the
  104. * hardware clock and store it in @ts.
  105. */
  106. static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
  107. {
  108. struct stmmac_priv *priv =
  109. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  110. unsigned long flags;
  111. u64 ns = 0;
  112. read_lock_irqsave(&priv->ptp_lock, flags);
  113. stmmac_get_systime(priv, priv->ptpaddr, &ns);
  114. read_unlock_irqrestore(&priv->ptp_lock, flags);
  115. *ts = ns_to_timespec64(ns);
  116. return 0;
  117. }
  118. /**
  119. * stmmac_set_time
  120. *
  121. * @ptp: pointer to ptp_clock_info structure
  122. * @ts: time value to set
  123. *
  124. * Description: this function will set the current time on the
  125. * hardware clock.
  126. */
  127. static int stmmac_set_time(struct ptp_clock_info *ptp,
  128. const struct timespec64 *ts)
  129. {
  130. struct stmmac_priv *priv =
  131. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  132. unsigned long flags;
  133. write_lock_irqsave(&priv->ptp_lock, flags);
  134. stmmac_init_systime(priv, priv->ptpaddr, ts->tv_sec, ts->tv_nsec);
  135. write_unlock_irqrestore(&priv->ptp_lock, flags);
  136. return 0;
  137. }
  138. static int stmmac_enable(struct ptp_clock_info *ptp,
  139. struct ptp_clock_request *rq, int on)
  140. {
  141. struct stmmac_priv *priv =
  142. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  143. void __iomem *ptpaddr = priv->ptpaddr;
  144. struct stmmac_pps_cfg *cfg;
  145. int ret = -EOPNOTSUPP;
  146. unsigned long flags;
  147. u32 acr_value;
  148. switch (rq->type) {
  149. case PTP_CLK_REQ_PEROUT:
  150. /* Reject requests with unsupported flags */
  151. if (rq->perout.flags)
  152. return -EOPNOTSUPP;
  153. cfg = &priv->pps[rq->perout.index];
  154. cfg->start.tv_sec = rq->perout.start.sec;
  155. cfg->start.tv_nsec = rq->perout.start.nsec;
  156. cfg->period.tv_sec = rq->perout.period.sec;
  157. cfg->period.tv_nsec = rq->perout.period.nsec;
  158. write_lock_irqsave(&priv->ptp_lock, flags);
  159. ret = stmmac_flex_pps_config(priv, priv->ioaddr,
  160. rq->perout.index, cfg, on,
  161. priv->sub_second_inc,
  162. priv->systime_flags);
  163. write_unlock_irqrestore(&priv->ptp_lock, flags);
  164. break;
  165. case PTP_CLK_REQ_EXTTS: {
  166. u8 channel;
  167. mutex_lock(&priv->aux_ts_lock);
  168. acr_value = readl(ptpaddr + PTP_ACR);
  169. channel = ilog2(FIELD_GET(PTP_ACR_MASK, acr_value));
  170. acr_value &= ~PTP_ACR_MASK;
  171. if (on) {
  172. if (FIELD_GET(PTP_ACR_MASK, acr_value)) {
  173. netdev_err(priv->dev,
  174. "Cannot enable auxiliary snapshot %d as auxiliary snapshot %d is already enabled",
  175. rq->extts.index, channel);
  176. mutex_unlock(&priv->aux_ts_lock);
  177. return -EBUSY;
  178. }
  179. priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN;
  180. /* Enable External snapshot trigger */
  181. acr_value |= PTP_ACR_ATSEN(rq->extts.index);
  182. acr_value |= PTP_ACR_ATSFC;
  183. } else {
  184. priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN;
  185. }
  186. netdev_dbg(priv->dev, "Auxiliary Snapshot %d %s.\n",
  187. rq->extts.index, on ? "enabled" : "disabled");
  188. writel(acr_value, ptpaddr + PTP_ACR);
  189. mutex_unlock(&priv->aux_ts_lock);
  190. /* wait for auxts fifo clear to finish */
  191. ret = readl_poll_timeout(ptpaddr + PTP_ACR, acr_value,
  192. !(acr_value & PTP_ACR_ATSFC),
  193. 10, 10000);
  194. break;
  195. }
  196. default:
  197. break;
  198. }
  199. return ret;
  200. }
  201. /**
  202. * stmmac_get_syncdevicetime
  203. * @device: current device time
  204. * @system: system counter value read synchronously with device time
  205. * @ctx: context provided by timekeeping code
  206. * Description: Read device and system clock simultaneously and return the
  207. * corrected clock values in ns.
  208. **/
  209. static int stmmac_get_syncdevicetime(ktime_t *device,
  210. struct system_counterval_t *system,
  211. void *ctx)
  212. {
  213. struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
  214. if (priv->plat->crosststamp)
  215. return priv->plat->crosststamp(device, system, ctx);
  216. else
  217. return -EOPNOTSUPP;
  218. }
  219. static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
  220. struct system_device_crosststamp *xtstamp)
  221. {
  222. struct stmmac_priv *priv =
  223. container_of(ptp, struct stmmac_priv, ptp_clock_ops);
  224. return get_device_system_crosststamp(stmmac_get_syncdevicetime,
  225. priv, NULL, xtstamp);
  226. }
  227. /* structure describing a PTP hardware clock */
  228. static struct ptp_clock_info stmmac_ptp_clock_ops = {
  229. .owner = THIS_MODULE,
  230. .name = "stmmac ptp",
  231. .max_adj = 62500000,
  232. .n_alarm = 0,
  233. .n_ext_ts = 0, /* will be overwritten in stmmac_ptp_register */
  234. .n_per_out = 0, /* will be overwritten in stmmac_ptp_register */
  235. .n_pins = 0,
  236. .pps = 0,
  237. .adjfine = stmmac_adjust_freq,
  238. .adjtime = stmmac_adjust_time,
  239. .gettime64 = stmmac_get_time,
  240. .settime64 = stmmac_set_time,
  241. .enable = stmmac_enable,
  242. .getcrosststamp = stmmac_getcrosststamp,
  243. };
  244. /**
  245. * stmmac_ptp_register
  246. * @priv: driver private structure
  247. * Description: this function will register the ptp clock driver
  248. * to kernel. It also does some house keeping work.
  249. */
  250. void stmmac_ptp_register(struct stmmac_priv *priv)
  251. {
  252. int i;
  253. for (i = 0; i < priv->dma_cap.pps_out_num; i++) {
  254. if (i >= STMMAC_PPS_MAX)
  255. break;
  256. priv->pps[i].available = true;
  257. }
  258. if (priv->plat->ptp_max_adj)
  259. stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
  260. /* Calculate the clock domain crossing (CDC) error if necessary */
  261. priv->plat->cdc_error_adj = 0;
  262. if (priv->plat->has_gmac4)
  263. priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
  264. stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
  265. stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
  266. rwlock_init(&priv->ptp_lock);
  267. mutex_init(&priv->aux_ts_lock);
  268. priv->ptp_clock_ops = stmmac_ptp_clock_ops;
  269. priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
  270. priv->device);
  271. if (IS_ERR(priv->ptp_clock)) {
  272. netdev_err(priv->dev, "ptp_clock_register failed\n");
  273. priv->ptp_clock = NULL;
  274. } else if (priv->ptp_clock)
  275. netdev_info(priv->dev, "registered PTP clock\n");
  276. }
  277. /**
  278. * stmmac_ptp_unregister
  279. * @priv: driver private structure
  280. * Description: this function will remove/unregister the ptp clock driver
  281. * from the kernel.
  282. */
  283. void stmmac_ptp_unregister(struct stmmac_priv *priv)
  284. {
  285. if (priv->ptp_clock) {
  286. ptp_clock_unregister(priv->ptp_clock);
  287. priv->ptp_clock = NULL;
  288. pr_debug("Removed PTP HW clock successfully on %s\n",
  289. priv->dev->name);
  290. }
  291. mutex_destroy(&priv->aux_ts_lock);
  292. }