timer-microchip-pit64b.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * 64-bit Periodic Interval Timer driver
  4. *
  5. * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries
  6. *
  7. * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/clockchips.h>
  11. #include <linux/delay.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/of_address.h>
  14. #include <linux/of_irq.h>
  15. #include <linux/sched_clock.h>
  16. #include <linux/slab.h>
  17. #define MCHP_PIT64B_CR 0x00 /* Control Register */
  18. #define MCHP_PIT64B_CR_START BIT(0)
  19. #define MCHP_PIT64B_CR_SWRST BIT(8)
  20. #define MCHP_PIT64B_MR 0x04 /* Mode Register */
  21. #define MCHP_PIT64B_MR_CONT BIT(0)
  22. #define MCHP_PIT64B_MR_ONE_SHOT (0)
  23. #define MCHP_PIT64B_MR_SGCLK BIT(3)
  24. #define MCHP_PIT64B_MR_PRES GENMASK(11, 8)
  25. #define MCHP_PIT64B_LSB_PR 0x08 /* LSB Period Register */
  26. #define MCHP_PIT64B_MSB_PR 0x0C /* MSB Period Register */
  27. #define MCHP_PIT64B_IER 0x10 /* Interrupt Enable Register */
  28. #define MCHP_PIT64B_IER_PERIOD BIT(0)
  29. #define MCHP_PIT64B_ISR 0x1C /* Interrupt Status Register */
  30. #define MCHP_PIT64B_TLSBR 0x20 /* Timer LSB Register */
  31. #define MCHP_PIT64B_TMSBR 0x24 /* Timer MSB Register */
  32. #define MCHP_PIT64B_PRES_MAX 0x10
  33. #define MCHP_PIT64B_LSBMASK GENMASK_ULL(31, 0)
  34. #define MCHP_PIT64B_PRES_TO_MODE(p) (MCHP_PIT64B_MR_PRES & ((p) << 8))
  35. #define MCHP_PIT64B_MODE_TO_PRES(m) ((MCHP_PIT64B_MR_PRES & (m)) >> 8)
  36. #define MCHP_PIT64B_DEF_FREQ 5000000UL /* 5 MHz */
  37. #define MCHP_PIT64B_NAME "pit64b"
  38. /**
  39. * struct mchp_pit64b_timer - PIT64B timer data structure
  40. * @base: base address of PIT64B hardware block
  41. * @pclk: PIT64B's peripheral clock
  42. * @gclk: PIT64B's generic clock
  43. * @mode: precomputed value for mode register
  44. */
  45. struct mchp_pit64b_timer {
  46. void __iomem *base;
  47. struct clk *pclk;
  48. struct clk *gclk;
  49. u32 mode;
  50. };
  51. /**
  52. * struct mchp_pit64b_clkevt - PIT64B clockevent data structure
  53. * @timer: PIT64B timer
  54. * @clkevt: clockevent
  55. */
  56. struct mchp_pit64b_clkevt {
  57. struct mchp_pit64b_timer timer;
  58. struct clock_event_device clkevt;
  59. };
  60. #define clkevt_to_mchp_pit64b_timer(x) \
  61. ((struct mchp_pit64b_timer *)container_of(x,\
  62. struct mchp_pit64b_clkevt, clkevt))
  63. /**
  64. * struct mchp_pit64b_clksrc - PIT64B clocksource data structure
  65. * @timer: PIT64B timer
  66. * @clksrc: clocksource
  67. */
  68. struct mchp_pit64b_clksrc {
  69. struct mchp_pit64b_timer timer;
  70. struct clocksource clksrc;
  71. };
  72. #define clksrc_to_mchp_pit64b_timer(x) \
  73. ((struct mchp_pit64b_timer *)container_of(x,\
  74. struct mchp_pit64b_clksrc, clksrc))
  75. /* Base address for clocksource timer. */
  76. static void __iomem *mchp_pit64b_cs_base;
  77. /* Default cycles for clockevent timer. */
  78. static u64 mchp_pit64b_ce_cycles;
  79. /* Delay timer. */
  80. static struct delay_timer mchp_pit64b_dt;
  81. static inline u64 mchp_pit64b_cnt_read(void __iomem *base)
  82. {
  83. unsigned long flags;
  84. u32 low, high;
  85. raw_local_irq_save(flags);
  86. /*
  87. * When using a 64 bit period TLSB must be read first, followed by the
  88. * read of TMSB. This sequence generates an atomic read of the 64 bit
  89. * timer value whatever the lapse of time between the accesses.
  90. */
  91. low = readl_relaxed(base + MCHP_PIT64B_TLSBR);
  92. high = readl_relaxed(base + MCHP_PIT64B_TMSBR);
  93. raw_local_irq_restore(flags);
  94. return (((u64)high << 32) | low);
  95. }
  96. static inline void mchp_pit64b_reset(struct mchp_pit64b_timer *timer,
  97. u64 cycles, u32 mode, u32 irqs)
  98. {
  99. u32 low, high;
  100. low = cycles & MCHP_PIT64B_LSBMASK;
  101. high = cycles >> 32;
  102. writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR);
  103. writel_relaxed(mode | timer->mode, timer->base + MCHP_PIT64B_MR);
  104. writel_relaxed(high, timer->base + MCHP_PIT64B_MSB_PR);
  105. writel_relaxed(low, timer->base + MCHP_PIT64B_LSB_PR);
  106. writel_relaxed(irqs, timer->base + MCHP_PIT64B_IER);
  107. writel_relaxed(MCHP_PIT64B_CR_START, timer->base + MCHP_PIT64B_CR);
  108. }
  109. static void mchp_pit64b_suspend(struct mchp_pit64b_timer *timer)
  110. {
  111. writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR);
  112. if (timer->mode & MCHP_PIT64B_MR_SGCLK)
  113. clk_disable_unprepare(timer->gclk);
  114. clk_disable_unprepare(timer->pclk);
  115. }
  116. static void mchp_pit64b_resume(struct mchp_pit64b_timer *timer)
  117. {
  118. clk_prepare_enable(timer->pclk);
  119. if (timer->mode & MCHP_PIT64B_MR_SGCLK)
  120. clk_prepare_enable(timer->gclk);
  121. }
  122. static void mchp_pit64b_clksrc_suspend(struct clocksource *cs)
  123. {
  124. struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs);
  125. mchp_pit64b_suspend(timer);
  126. }
  127. static void mchp_pit64b_clksrc_resume(struct clocksource *cs)
  128. {
  129. struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs);
  130. mchp_pit64b_resume(timer);
  131. mchp_pit64b_reset(timer, ULLONG_MAX, MCHP_PIT64B_MR_CONT, 0);
  132. }
  133. static u64 mchp_pit64b_clksrc_read(struct clocksource *cs)
  134. {
  135. return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
  136. }
  137. static u64 notrace mchp_pit64b_sched_read_clk(void)
  138. {
  139. return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
  140. }
  141. static unsigned long notrace mchp_pit64b_dt_read(void)
  142. {
  143. return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
  144. }
  145. static int mchp_pit64b_clkevt_shutdown(struct clock_event_device *cedev)
  146. {
  147. struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
  148. if (!clockevent_state_detached(cedev))
  149. mchp_pit64b_suspend(timer);
  150. return 0;
  151. }
  152. static int mchp_pit64b_clkevt_set_periodic(struct clock_event_device *cedev)
  153. {
  154. struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
  155. if (clockevent_state_shutdown(cedev))
  156. mchp_pit64b_resume(timer);
  157. mchp_pit64b_reset(timer, mchp_pit64b_ce_cycles, MCHP_PIT64B_MR_CONT,
  158. MCHP_PIT64B_IER_PERIOD);
  159. return 0;
  160. }
  161. static int mchp_pit64b_clkevt_set_oneshot(struct clock_event_device *cedev)
  162. {
  163. struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
  164. if (clockevent_state_shutdown(cedev))
  165. mchp_pit64b_resume(timer);
  166. mchp_pit64b_reset(timer, mchp_pit64b_ce_cycles, MCHP_PIT64B_MR_ONE_SHOT,
  167. MCHP_PIT64B_IER_PERIOD);
  168. return 0;
  169. }
  170. static int mchp_pit64b_clkevt_set_next_event(unsigned long evt,
  171. struct clock_event_device *cedev)
  172. {
  173. struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
  174. mchp_pit64b_reset(timer, evt, MCHP_PIT64B_MR_ONE_SHOT,
  175. MCHP_PIT64B_IER_PERIOD);
  176. return 0;
  177. }
  178. static irqreturn_t mchp_pit64b_interrupt(int irq, void *dev_id)
  179. {
  180. struct mchp_pit64b_clkevt *irq_data = dev_id;
  181. /* Need to clear the interrupt. */
  182. readl_relaxed(irq_data->timer.base + MCHP_PIT64B_ISR);
  183. irq_data->clkevt.event_handler(&irq_data->clkevt);
  184. return IRQ_HANDLED;
  185. }
  186. static void __init mchp_pit64b_pres_compute(u32 *pres, u32 clk_rate,
  187. u32 max_rate)
  188. {
  189. u32 tmp;
  190. for (*pres = 0; *pres < MCHP_PIT64B_PRES_MAX; (*pres)++) {
  191. tmp = clk_rate / (*pres + 1);
  192. if (tmp <= max_rate)
  193. break;
  194. }
  195. /* Use the biggest prescaler if we didn't match one. */
  196. if (*pres == MCHP_PIT64B_PRES_MAX)
  197. *pres = MCHP_PIT64B_PRES_MAX - 1;
  198. }
  199. /**
  200. * mchp_pit64b_init_mode() - prepare PIT64B mode register value to be used at
  201. * runtime; this includes prescaler and SGCLK bit
  202. * @timer: pointer to pit64b timer to init
  203. * @max_rate: maximum rate that timer's clock could use
  204. *
  205. * PIT64B timer may be fed by gclk or pclk. When gclk is used its rate has to
  206. * be at least 3 times lower that pclk's rate. pclk rate is fixed, gclk rate
  207. * could be changed via clock APIs. The chosen clock (pclk or gclk) could be
  208. * divided by the internal PIT64B's divider.
  209. *
  210. * This function, first tries to use GCLK by requesting the desired rate from
  211. * PMC and then using the internal PIT64B prescaler, if any, to reach the
  212. * requested rate. If PCLK/GCLK < 3 (condition requested by PIT64B hardware)
  213. * then the function falls back on using PCLK as clock source for PIT64B timer
  214. * choosing the highest prescaler in case it doesn't locate one to match the
  215. * requested frequency.
  216. *
  217. * Below is presented the PIT64B block in relation with PMC:
  218. *
  219. * PIT64B
  220. * PMC +------------------------------------+
  221. * +----+ | +-----+ |
  222. * | |-->gclk -->|-->| | +---------+ +-----+ |
  223. * | | | | MUX |--->| Divider |->|timer| |
  224. * | |-->pclk -->|-->| | +---------+ +-----+ |
  225. * +----+ | +-----+ |
  226. * | ^ |
  227. * | sel |
  228. * +------------------------------------+
  229. *
  230. * Where:
  231. * - gclk rate <= pclk rate/3
  232. * - gclk rate could be requested from PMC
  233. * - pclk rate is fixed (cannot be requested from PMC)
  234. */
  235. static int __init mchp_pit64b_init_mode(struct mchp_pit64b_timer *timer,
  236. unsigned long max_rate)
  237. {
  238. unsigned long pclk_rate, diff = 0, best_diff = ULONG_MAX;
  239. long gclk_round = 0;
  240. u32 pres, best_pres = 0;
  241. pclk_rate = clk_get_rate(timer->pclk);
  242. if (!pclk_rate)
  243. return -EINVAL;
  244. timer->mode = 0;
  245. /* Try using GCLK. */
  246. gclk_round = clk_round_rate(timer->gclk, max_rate);
  247. if (gclk_round < 0)
  248. goto pclk;
  249. if (pclk_rate / gclk_round < 3)
  250. goto pclk;
  251. mchp_pit64b_pres_compute(&pres, gclk_round, max_rate);
  252. best_diff = abs(gclk_round / (pres + 1) - max_rate);
  253. best_pres = pres;
  254. if (!best_diff) {
  255. timer->mode |= MCHP_PIT64B_MR_SGCLK;
  256. clk_set_rate(timer->gclk, gclk_round);
  257. goto done;
  258. }
  259. pclk:
  260. /* Check if requested rate could be obtained using PCLK. */
  261. mchp_pit64b_pres_compute(&pres, pclk_rate, max_rate);
  262. diff = abs(pclk_rate / (pres + 1) - max_rate);
  263. if (best_diff > diff) {
  264. /* Use PCLK. */
  265. best_pres = pres;
  266. } else {
  267. /* Use GCLK. */
  268. timer->mode |= MCHP_PIT64B_MR_SGCLK;
  269. clk_set_rate(timer->gclk, gclk_round);
  270. }
  271. done:
  272. timer->mode |= MCHP_PIT64B_PRES_TO_MODE(best_pres);
  273. pr_info("PIT64B: using clk=%s with prescaler %u, freq=%lu [Hz]\n",
  274. timer->mode & MCHP_PIT64B_MR_SGCLK ? "gclk" : "pclk", best_pres,
  275. timer->mode & MCHP_PIT64B_MR_SGCLK ?
  276. gclk_round / (best_pres + 1) : pclk_rate / (best_pres + 1));
  277. return 0;
  278. }
  279. static int __init mchp_pit64b_init_clksrc(struct mchp_pit64b_timer *timer,
  280. u32 clk_rate)
  281. {
  282. struct mchp_pit64b_clksrc *cs;
  283. int ret;
  284. cs = kzalloc_obj(*cs);
  285. if (!cs)
  286. return -ENOMEM;
  287. mchp_pit64b_resume(timer);
  288. mchp_pit64b_reset(timer, ULLONG_MAX, MCHP_PIT64B_MR_CONT, 0);
  289. mchp_pit64b_cs_base = timer->base;
  290. cs->timer.base = timer->base;
  291. cs->timer.pclk = timer->pclk;
  292. cs->timer.gclk = timer->gclk;
  293. cs->timer.mode = timer->mode;
  294. cs->clksrc.name = MCHP_PIT64B_NAME;
  295. cs->clksrc.mask = CLOCKSOURCE_MASK(64);
  296. cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
  297. cs->clksrc.rating = 210;
  298. cs->clksrc.read = mchp_pit64b_clksrc_read;
  299. cs->clksrc.suspend = mchp_pit64b_clksrc_suspend;
  300. cs->clksrc.resume = mchp_pit64b_clksrc_resume;
  301. ret = clocksource_register_hz(&cs->clksrc, clk_rate);
  302. if (ret) {
  303. pr_debug("clksrc: Failed to register PIT64B clocksource!\n");
  304. /* Stop timer. */
  305. mchp_pit64b_suspend(timer);
  306. kfree(cs);
  307. return ret;
  308. }
  309. sched_clock_register(mchp_pit64b_sched_read_clk, 64, clk_rate);
  310. mchp_pit64b_dt.read_current_timer = mchp_pit64b_dt_read;
  311. mchp_pit64b_dt.freq = clk_rate;
  312. register_current_timer_delay(&mchp_pit64b_dt);
  313. return 0;
  314. }
  315. static int __init mchp_pit64b_init_clkevt(struct mchp_pit64b_timer *timer,
  316. u32 clk_rate, u32 irq)
  317. {
  318. struct mchp_pit64b_clkevt *ce;
  319. int ret;
  320. ce = kzalloc_obj(*ce);
  321. if (!ce)
  322. return -ENOMEM;
  323. mchp_pit64b_ce_cycles = DIV_ROUND_CLOSEST(clk_rate, HZ);
  324. ce->timer.base = timer->base;
  325. ce->timer.pclk = timer->pclk;
  326. ce->timer.gclk = timer->gclk;
  327. ce->timer.mode = timer->mode;
  328. ce->clkevt.name = MCHP_PIT64B_NAME;
  329. ce->clkevt.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC;
  330. ce->clkevt.rating = 150;
  331. ce->clkevt.set_state_shutdown = mchp_pit64b_clkevt_shutdown;
  332. ce->clkevt.set_state_periodic = mchp_pit64b_clkevt_set_periodic;
  333. ce->clkevt.set_state_oneshot = mchp_pit64b_clkevt_set_oneshot;
  334. ce->clkevt.set_next_event = mchp_pit64b_clkevt_set_next_event;
  335. ce->clkevt.cpumask = cpumask_of(0);
  336. ce->clkevt.irq = irq;
  337. ret = request_irq(irq, mchp_pit64b_interrupt, IRQF_TIMER,
  338. "pit64b_tick", ce);
  339. if (ret) {
  340. pr_debug("clkevt: Failed to setup PIT64B IRQ\n");
  341. kfree(ce);
  342. return ret;
  343. }
  344. clockevents_config_and_register(&ce->clkevt, clk_rate, 1, ULONG_MAX);
  345. return 0;
  346. }
  347. static int __init mchp_pit64b_dt_init_timer(struct device_node *node,
  348. bool clkevt)
  349. {
  350. struct mchp_pit64b_timer timer;
  351. unsigned long clk_rate;
  352. u32 irq = 0;
  353. int ret;
  354. /* Parse DT node. */
  355. timer.pclk = of_clk_get_by_name(node, "pclk");
  356. if (IS_ERR(timer.pclk))
  357. return PTR_ERR(timer.pclk);
  358. timer.gclk = of_clk_get_by_name(node, "gclk");
  359. if (IS_ERR(timer.gclk))
  360. return PTR_ERR(timer.gclk);
  361. timer.base = of_iomap(node, 0);
  362. if (!timer.base)
  363. return -ENXIO;
  364. if (clkevt) {
  365. irq = irq_of_parse_and_map(node, 0);
  366. if (!irq) {
  367. ret = -ENODEV;
  368. goto io_unmap;
  369. }
  370. }
  371. /* Initialize mode (prescaler + SGCK bit). To be used at runtime. */
  372. ret = mchp_pit64b_init_mode(&timer, MCHP_PIT64B_DEF_FREQ);
  373. if (ret)
  374. goto irq_unmap;
  375. if (timer.mode & MCHP_PIT64B_MR_SGCLK)
  376. clk_rate = clk_get_rate(timer.gclk);
  377. else
  378. clk_rate = clk_get_rate(timer.pclk);
  379. clk_rate = clk_rate / (MCHP_PIT64B_MODE_TO_PRES(timer.mode) + 1);
  380. if (clkevt)
  381. ret = mchp_pit64b_init_clkevt(&timer, clk_rate, irq);
  382. else
  383. ret = mchp_pit64b_init_clksrc(&timer, clk_rate);
  384. if (ret)
  385. goto irq_unmap;
  386. return 0;
  387. irq_unmap:
  388. irq_dispose_mapping(irq);
  389. io_unmap:
  390. iounmap(timer.base);
  391. return ret;
  392. }
  393. static int __init mchp_pit64b_dt_init(struct device_node *node)
  394. {
  395. static int inits;
  396. switch (inits++) {
  397. case 0:
  398. /* 1st request, register clockevent. */
  399. return mchp_pit64b_dt_init_timer(node, true);
  400. case 1:
  401. /* 2nd request, register clocksource. */
  402. return mchp_pit64b_dt_init_timer(node, false);
  403. }
  404. /* The rest, don't care. */
  405. return -EINVAL;
  406. }
  407. TIMER_OF_DECLARE(mchp_pit64b, "microchip,sam9x60-pit64b", mchp_pit64b_dt_init);