dpaa2-ptp.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2013-2016 Freescale Semiconductor Inc.
  4. * Copyright 2016-2018 NXP
  5. * Copyright 2020 NXP
  6. */
  7. #include <linux/module.h>
  8. #include <linux/of.h>
  9. #include <linux/of_address.h>
  10. #include <linux/msi.h>
  11. #include <linux/fsl/mc.h>
  12. #include "dpaa2-ptp.h"
  13. static int dpaa2_ptp_enable(struct ptp_clock_info *ptp,
  14. struct ptp_clock_request *rq, int on)
  15. {
  16. struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
  17. struct fsl_mc_device *mc_dev;
  18. struct device *dev;
  19. u32 mask = 0;
  20. u32 bit;
  21. int err;
  22. dev = ptp_qoriq->dev;
  23. mc_dev = to_fsl_mc_device(dev);
  24. switch (rq->type) {
  25. case PTP_CLK_REQ_EXTTS:
  26. switch (rq->extts.index) {
  27. case 0:
  28. bit = DPRTC_EVENT_ETS1;
  29. break;
  30. case 1:
  31. bit = DPRTC_EVENT_ETS2;
  32. break;
  33. default:
  34. return -EINVAL;
  35. }
  36. if (on)
  37. extts_clean_up(ptp_qoriq, rq->extts.index, false);
  38. break;
  39. case PTP_CLK_REQ_PPS:
  40. bit = DPRTC_EVENT_PPS;
  41. break;
  42. default:
  43. return -EOPNOTSUPP;
  44. }
  45. err = dprtc_get_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
  46. DPRTC_IRQ_INDEX, &mask);
  47. if (err < 0) {
  48. dev_err(dev, "dprtc_get_irq_mask(): %d\n", err);
  49. return err;
  50. }
  51. if (on)
  52. mask |= bit;
  53. else
  54. mask &= ~bit;
  55. err = dprtc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
  56. DPRTC_IRQ_INDEX, mask);
  57. if (err < 0) {
  58. dev_err(dev, "dprtc_set_irq_mask(): %d\n", err);
  59. return err;
  60. }
  61. return 0;
  62. }
  63. static const struct ptp_clock_info dpaa2_ptp_caps = {
  64. .owner = THIS_MODULE,
  65. .name = "DPAA2 PTP Clock",
  66. .max_adj = 512000,
  67. .n_alarm = 2,
  68. .n_ext_ts = 2,
  69. .n_per_out = 3,
  70. .n_pins = 0,
  71. .pps = 1,
  72. .adjfine = ptp_qoriq_adjfine,
  73. .adjtime = ptp_qoriq_adjtime,
  74. .gettime64 = ptp_qoriq_gettime,
  75. .settime64 = ptp_qoriq_settime,
  76. .enable = dpaa2_ptp_enable,
  77. };
  78. static irqreturn_t dpaa2_ptp_irq_handler_thread(int irq, void *priv)
  79. {
  80. struct ptp_qoriq *ptp_qoriq = priv;
  81. struct ptp_clock_event event;
  82. struct fsl_mc_device *mc_dev;
  83. struct device *dev;
  84. u32 status = 0;
  85. int err;
  86. dev = ptp_qoriq->dev;
  87. mc_dev = to_fsl_mc_device(dev);
  88. err = dprtc_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
  89. DPRTC_IRQ_INDEX, &status);
  90. if (unlikely(err)) {
  91. dev_err(dev, "dprtc_get_irq_status err %d\n", err);
  92. return IRQ_NONE;
  93. }
  94. if (status & DPRTC_EVENT_PPS) {
  95. event.type = PTP_CLOCK_PPS;
  96. ptp_clock_event(ptp_qoriq->clock, &event);
  97. }
  98. if (status & DPRTC_EVENT_ETS1)
  99. extts_clean_up(ptp_qoriq, 0, true);
  100. if (status & DPRTC_EVENT_ETS2)
  101. extts_clean_up(ptp_qoriq, 1, true);
  102. err = dprtc_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
  103. DPRTC_IRQ_INDEX, status);
  104. if (unlikely(err)) {
  105. dev_err(dev, "dprtc_clear_irq_status err %d\n", err);
  106. return IRQ_NONE;
  107. }
  108. return IRQ_HANDLED;
  109. }
  110. static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
  111. {
  112. struct device *dev = &mc_dev->dev;
  113. struct ptp_qoriq *ptp_qoriq;
  114. struct device_node *node;
  115. void __iomem *base;
  116. int err;
  117. ptp_qoriq = devm_kzalloc(dev, sizeof(*ptp_qoriq), GFP_KERNEL);
  118. if (!ptp_qoriq)
  119. return -ENOMEM;
  120. err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
  121. if (err) {
  122. if (err == -ENXIO)
  123. err = -EPROBE_DEFER;
  124. else
  125. dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
  126. goto err_exit;
  127. }
  128. err = dprtc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
  129. &mc_dev->mc_handle);
  130. if (err) {
  131. dev_err(dev, "dprtc_open err %d\n", err);
  132. goto err_free_mcp;
  133. }
  134. ptp_qoriq->dev = dev;
  135. node = of_find_compatible_node(NULL, NULL, "fsl,dpaa2-ptp");
  136. if (!node) {
  137. err = -ENODEV;
  138. goto err_close;
  139. }
  140. dev->of_node = node;
  141. base = of_iomap(node, 0);
  142. if (!base) {
  143. err = -ENOMEM;
  144. goto err_put;
  145. }
  146. err = fsl_mc_allocate_irqs(mc_dev);
  147. if (err) {
  148. dev_err(dev, "MC irqs allocation failed\n");
  149. goto err_unmap;
  150. }
  151. ptp_qoriq->irq = mc_dev->irqs[0]->virq;
  152. err = request_threaded_irq(ptp_qoriq->irq, NULL,
  153. dpaa2_ptp_irq_handler_thread,
  154. IRQF_NO_SUSPEND | IRQF_ONESHOT,
  155. dev_name(dev), ptp_qoriq);
  156. if (err < 0) {
  157. dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
  158. goto err_free_mc_irq;
  159. }
  160. err = dprtc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
  161. DPRTC_IRQ_INDEX, 1);
  162. if (err < 0) {
  163. dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
  164. goto err_free_threaded_irq;
  165. }
  166. err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
  167. if (err)
  168. goto err_free_threaded_irq;
  169. dpaa2_phc_index = ptp_qoriq->phc_index;
  170. dpaa2_ptp = ptp_qoriq;
  171. dev_set_drvdata(dev, ptp_qoriq);
  172. return 0;
  173. err_free_threaded_irq:
  174. free_irq(ptp_qoriq->irq, ptp_qoriq);
  175. err_free_mc_irq:
  176. fsl_mc_free_irqs(mc_dev);
  177. err_unmap:
  178. iounmap(base);
  179. err_put:
  180. of_node_put(node);
  181. err_close:
  182. dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
  183. err_free_mcp:
  184. fsl_mc_portal_free(mc_dev->mc_io);
  185. err_exit:
  186. return err;
  187. }
  188. static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
  189. {
  190. struct device *dev = &mc_dev->dev;
  191. struct ptp_qoriq *ptp_qoriq;
  192. ptp_qoriq = dev_get_drvdata(dev);
  193. dpaa2_phc_index = -1;
  194. ptp_qoriq_free(ptp_qoriq);
  195. fsl_mc_free_irqs(mc_dev);
  196. dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
  197. fsl_mc_portal_free(mc_dev->mc_io);
  198. return 0;
  199. }
  200. static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
  201. {
  202. .vendor = FSL_MC_VENDOR_FREESCALE,
  203. .obj_type = "dprtc",
  204. },
  205. {}
  206. };
  207. MODULE_DEVICE_TABLE(fslmc, dpaa2_ptp_match_id_table);
  208. static struct fsl_mc_driver dpaa2_ptp_drv = {
  209. .driver = {
  210. .name = KBUILD_MODNAME,
  211. .owner = THIS_MODULE,
  212. },
  213. .probe = dpaa2_ptp_probe,
  214. .remove = dpaa2_ptp_remove,
  215. .match_id_table = dpaa2_ptp_match_id_table,
  216. };
  217. module_fsl_mc_driver(dpaa2_ptp_drv);
  218. MODULE_LICENSE("GPL v2");
  219. MODULE_DESCRIPTION("DPAA2 PTP Clock Driver");