ptp_ixp46x.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * PTP 1588 clock using the IXP46X
  4. *
  5. * Copyright (C) 2010 OMICRON electronics GmbH
  6. */
  7. #include <linux/device.h>
  8. #include <linux/err.h>
  9. #include <linux/gpio.h>
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/io.h>
  13. #include <linux/irq.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/ptp_clock_kernel.h>
  17. #include <mach/ixp46x_ts.h>
  18. #define DRIVER "ptp_ixp46x"
  19. #define N_EXT_TS 2
  20. #define MASTER_GPIO 8
  21. #define MASTER_IRQ 25
  22. #define SLAVE_GPIO 7
  23. #define SLAVE_IRQ 24
  24. struct ixp_clock {
  25. struct ixp46x_ts_regs *regs;
  26. struct ptp_clock *ptp_clock;
  27. struct ptp_clock_info caps;
  28. int exts0_enabled;
  29. int exts1_enabled;
  30. };
  31. DEFINE_SPINLOCK(register_lock);
  32. /*
  33. * Register access functions
  34. */
  35. static u64 ixp_systime_read(struct ixp46x_ts_regs *regs)
  36. {
  37. u64 ns;
  38. u32 lo, hi;
  39. lo = __raw_readl(&regs->systime_lo);
  40. hi = __raw_readl(&regs->systime_hi);
  41. ns = ((u64) hi) << 32;
  42. ns |= lo;
  43. ns <<= TICKS_NS_SHIFT;
  44. return ns;
  45. }
  46. static void ixp_systime_write(struct ixp46x_ts_regs *regs, u64 ns)
  47. {
  48. u32 hi, lo;
  49. ns >>= TICKS_NS_SHIFT;
  50. hi = ns >> 32;
  51. lo = ns & 0xffffffff;
  52. __raw_writel(lo, &regs->systime_lo);
  53. __raw_writel(hi, &regs->systime_hi);
  54. }
  55. /*
  56. * Interrupt service routine
  57. */
  58. static irqreturn_t isr(int irq, void *priv)
  59. {
  60. struct ixp_clock *ixp_clock = priv;
  61. struct ixp46x_ts_regs *regs = ixp_clock->regs;
  62. struct ptp_clock_event event;
  63. u32 ack = 0, lo, hi, val;
  64. val = __raw_readl(&regs->event);
  65. if (val & TSER_SNS) {
  66. ack |= TSER_SNS;
  67. if (ixp_clock->exts0_enabled) {
  68. hi = __raw_readl(&regs->asms_hi);
  69. lo = __raw_readl(&regs->asms_lo);
  70. event.type = PTP_CLOCK_EXTTS;
  71. event.index = 0;
  72. event.timestamp = ((u64) hi) << 32;
  73. event.timestamp |= lo;
  74. event.timestamp <<= TICKS_NS_SHIFT;
  75. ptp_clock_event(ixp_clock->ptp_clock, &event);
  76. }
  77. }
  78. if (val & TSER_SNM) {
  79. ack |= TSER_SNM;
  80. if (ixp_clock->exts1_enabled) {
  81. hi = __raw_readl(&regs->amms_hi);
  82. lo = __raw_readl(&regs->amms_lo);
  83. event.type = PTP_CLOCK_EXTTS;
  84. event.index = 1;
  85. event.timestamp = ((u64) hi) << 32;
  86. event.timestamp |= lo;
  87. event.timestamp <<= TICKS_NS_SHIFT;
  88. ptp_clock_event(ixp_clock->ptp_clock, &event);
  89. }
  90. }
  91. if (val & TTIPEND)
  92. ack |= TTIPEND; /* this bit seems to be always set */
  93. if (ack) {
  94. __raw_writel(ack, &regs->event);
  95. return IRQ_HANDLED;
  96. } else
  97. return IRQ_NONE;
  98. }
  99. /*
  100. * PTP clock operations
  101. */
  102. static int ptp_ixp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
  103. {
  104. u64 adj;
  105. u32 diff, addend;
  106. int neg_adj = 0;
  107. struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
  108. struct ixp46x_ts_regs *regs = ixp_clock->regs;
  109. if (ppb < 0) {
  110. neg_adj = 1;
  111. ppb = -ppb;
  112. }
  113. addend = DEFAULT_ADDEND;
  114. adj = addend;
  115. adj *= ppb;
  116. diff = div_u64(adj, 1000000000ULL);
  117. addend = neg_adj ? addend - diff : addend + diff;
  118. __raw_writel(addend, &regs->addend);
  119. return 0;
  120. }
  121. static int ptp_ixp_adjtime(struct ptp_clock_info *ptp, s64 delta)
  122. {
  123. s64 now;
  124. unsigned long flags;
  125. struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
  126. struct ixp46x_ts_regs *regs = ixp_clock->regs;
  127. spin_lock_irqsave(&register_lock, flags);
  128. now = ixp_systime_read(regs);
  129. now += delta;
  130. ixp_systime_write(regs, now);
  131. spin_unlock_irqrestore(&register_lock, flags);
  132. return 0;
  133. }
  134. static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
  135. {
  136. u64 ns;
  137. unsigned long flags;
  138. struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
  139. struct ixp46x_ts_regs *regs = ixp_clock->regs;
  140. spin_lock_irqsave(&register_lock, flags);
  141. ns = ixp_systime_read(regs);
  142. spin_unlock_irqrestore(&register_lock, flags);
  143. *ts = ns_to_timespec64(ns);
  144. return 0;
  145. }
  146. static int ptp_ixp_settime(struct ptp_clock_info *ptp,
  147. const struct timespec64 *ts)
  148. {
  149. u64 ns;
  150. unsigned long flags;
  151. struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
  152. struct ixp46x_ts_regs *regs = ixp_clock->regs;
  153. ns = timespec64_to_ns(ts);
  154. spin_lock_irqsave(&register_lock, flags);
  155. ixp_systime_write(regs, ns);
  156. spin_unlock_irqrestore(&register_lock, flags);
  157. return 0;
  158. }
  159. static int ptp_ixp_enable(struct ptp_clock_info *ptp,
  160. struct ptp_clock_request *rq, int on)
  161. {
  162. struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
  163. switch (rq->type) {
  164. case PTP_CLK_REQ_EXTTS:
  165. switch (rq->extts.index) {
  166. case 0:
  167. ixp_clock->exts0_enabled = on ? 1 : 0;
  168. break;
  169. case 1:
  170. ixp_clock->exts1_enabled = on ? 1 : 0;
  171. break;
  172. default:
  173. return -EINVAL;
  174. }
  175. return 0;
  176. default:
  177. break;
  178. }
  179. return -EOPNOTSUPP;
  180. }
  181. static const struct ptp_clock_info ptp_ixp_caps = {
  182. .owner = THIS_MODULE,
  183. .name = "IXP46X timer",
  184. .max_adj = 66666655,
  185. .n_ext_ts = N_EXT_TS,
  186. .n_pins = 0,
  187. .pps = 0,
  188. .adjfreq = ptp_ixp_adjfreq,
  189. .adjtime = ptp_ixp_adjtime,
  190. .gettime64 = ptp_ixp_gettime,
  191. .settime64 = ptp_ixp_settime,
  192. .enable = ptp_ixp_enable,
  193. };
  194. /* module operations */
  195. static struct ixp_clock ixp_clock;
  196. static int setup_interrupt(int gpio)
  197. {
  198. int irq;
  199. int err;
  200. err = gpio_request(gpio, "ixp4-ptp");
  201. if (err)
  202. return err;
  203. err = gpio_direction_input(gpio);
  204. if (err)
  205. return err;
  206. irq = gpio_to_irq(gpio);
  207. if (irq < 0)
  208. return irq;
  209. err = irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);
  210. if (err) {
  211. pr_err("cannot set trigger type for irq %d\n", irq);
  212. return err;
  213. }
  214. err = request_irq(irq, isr, 0, DRIVER, &ixp_clock);
  215. if (err) {
  216. pr_err("request_irq failed for irq %d\n", irq);
  217. return err;
  218. }
  219. return irq;
  220. }
  221. static void __exit ptp_ixp_exit(void)
  222. {
  223. free_irq(MASTER_IRQ, &ixp_clock);
  224. free_irq(SLAVE_IRQ, &ixp_clock);
  225. ixp46x_phc_index = -1;
  226. ptp_clock_unregister(ixp_clock.ptp_clock);
  227. }
  228. static int __init ptp_ixp_init(void)
  229. {
  230. if (!cpu_is_ixp46x())
  231. return -ENODEV;
  232. ixp_clock.regs =
  233. (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
  234. ixp_clock.caps = ptp_ixp_caps;
  235. ixp_clock.ptp_clock = ptp_clock_register(&ixp_clock.caps, NULL);
  236. if (IS_ERR(ixp_clock.ptp_clock))
  237. return PTR_ERR(ixp_clock.ptp_clock);
  238. ixp46x_phc_index = ptp_clock_index(ixp_clock.ptp_clock);
  239. __raw_writel(DEFAULT_ADDEND, &ixp_clock.regs->addend);
  240. __raw_writel(1, &ixp_clock.regs->trgt_lo);
  241. __raw_writel(0, &ixp_clock.regs->trgt_hi);
  242. __raw_writel(TTIPEND, &ixp_clock.regs->event);
  243. if (MASTER_IRQ != setup_interrupt(MASTER_GPIO)) {
  244. pr_err("failed to setup gpio %d as irq\n", MASTER_GPIO);
  245. goto no_master;
  246. }
  247. if (SLAVE_IRQ != setup_interrupt(SLAVE_GPIO)) {
  248. pr_err("failed to setup gpio %d as irq\n", SLAVE_GPIO);
  249. goto no_slave;
  250. }
  251. return 0;
  252. no_slave:
  253. free_irq(MASTER_IRQ, &ixp_clock);
  254. no_master:
  255. ptp_clock_unregister(ixp_clock.ptp_clock);
  256. return -ENODEV;
  257. }
  258. module_init(ptp_ixp_init);
  259. module_exit(ptp_ixp_exit);
  260. MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
  261. MODULE_DESCRIPTION("PTP clock using the IXP46X timer");
  262. MODULE_LICENSE("GPL");