renesas-ostm.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Renesas Timer Support - OSTM
  4. *
  5. * Copyright (C) 2017 Renesas Electronics America, Inc.
  6. * Copyright (C) 2017 Chris Brandt
  7. */
  8. #include <linux/clk.h>
  9. #include <linux/clockchips.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/sched_clock.h>
  12. #include <linux/slab.h>
  13. #include "timer-of.h"
  14. /*
  15. * The OSTM contains independent channels.
  16. * The first OSTM channel probed will be set up as a free running
  17. * clocksource. Additionally we will use this clocksource for the system
  18. * schedule timer sched_clock().
  19. *
  20. * The second (or more) channel probed will be set up as an interrupt
  21. * driven clock event.
  22. */
  23. static void __iomem *system_clock; /* For sched_clock() */
  24. /* OSTM REGISTERS */
  25. #define OSTM_CMP 0x000 /* RW,32 */
  26. #define OSTM_CNT 0x004 /* R,32 */
  27. #define OSTM_TE 0x010 /* R,8 */
  28. #define OSTM_TS 0x014 /* W,8 */
  29. #define OSTM_TT 0x018 /* W,8 */
  30. #define OSTM_CTL 0x020 /* RW,8 */
  31. #define TE 0x01
  32. #define TS 0x01
  33. #define TT 0x01
  34. #define CTL_PERIODIC 0x00
  35. #define CTL_ONESHOT 0x02
  36. #define CTL_FREERUN 0x02
  37. static void ostm_timer_stop(struct timer_of *to)
  38. {
  39. if (readb(timer_of_base(to) + OSTM_TE) & TE) {
  40. writeb(TT, timer_of_base(to) + OSTM_TT);
  41. /*
  42. * Read back the register simply to confirm the write operation
  43. * has completed since I/O writes can sometimes get queued by
  44. * the bus architecture.
  45. */
  46. while (readb(timer_of_base(to) + OSTM_TE) & TE)
  47. ;
  48. }
  49. }
  50. static int __init ostm_init_clksrc(struct timer_of *to)
  51. {
  52. ostm_timer_stop(to);
  53. writel(0, timer_of_base(to) + OSTM_CMP);
  54. writeb(CTL_FREERUN, timer_of_base(to) + OSTM_CTL);
  55. writeb(TS, timer_of_base(to) + OSTM_TS);
  56. return clocksource_mmio_init(timer_of_base(to) + OSTM_CNT,
  57. to->np->full_name, timer_of_rate(to), 300,
  58. 32, clocksource_mmio_readl_up);
  59. }
  60. static u64 notrace ostm_read_sched_clock(void)
  61. {
  62. return readl(system_clock);
  63. }
  64. static void __init ostm_init_sched_clock(struct timer_of *to)
  65. {
  66. system_clock = timer_of_base(to) + OSTM_CNT;
  67. sched_clock_register(ostm_read_sched_clock, 32, timer_of_rate(to));
  68. }
  69. static int ostm_clock_event_next(unsigned long delta,
  70. struct clock_event_device *ced)
  71. {
  72. struct timer_of *to = to_timer_of(ced);
  73. ostm_timer_stop(to);
  74. writel(delta, timer_of_base(to) + OSTM_CMP);
  75. writeb(CTL_ONESHOT, timer_of_base(to) + OSTM_CTL);
  76. writeb(TS, timer_of_base(to) + OSTM_TS);
  77. return 0;
  78. }
  79. static int ostm_shutdown(struct clock_event_device *ced)
  80. {
  81. struct timer_of *to = to_timer_of(ced);
  82. ostm_timer_stop(to);
  83. return 0;
  84. }
  85. static int ostm_set_periodic(struct clock_event_device *ced)
  86. {
  87. struct timer_of *to = to_timer_of(ced);
  88. if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
  89. ostm_timer_stop(to);
  90. writel(timer_of_period(to) - 1, timer_of_base(to) + OSTM_CMP);
  91. writeb(CTL_PERIODIC, timer_of_base(to) + OSTM_CTL);
  92. writeb(TS, timer_of_base(to) + OSTM_TS);
  93. return 0;
  94. }
  95. static int ostm_set_oneshot(struct clock_event_device *ced)
  96. {
  97. struct timer_of *to = to_timer_of(ced);
  98. ostm_timer_stop(to);
  99. return 0;
  100. }
  101. static irqreturn_t ostm_timer_interrupt(int irq, void *dev_id)
  102. {
  103. struct clock_event_device *ced = dev_id;
  104. if (clockevent_state_oneshot(ced))
  105. ostm_timer_stop(to_timer_of(ced));
  106. /* notify clockevent layer */
  107. if (ced->event_handler)
  108. ced->event_handler(ced);
  109. return IRQ_HANDLED;
  110. }
  111. static int __init ostm_init_clkevt(struct timer_of *to)
  112. {
  113. struct clock_event_device *ced = &to->clkevt;
  114. ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC;
  115. ced->set_state_shutdown = ostm_shutdown;
  116. ced->set_state_periodic = ostm_set_periodic;
  117. ced->set_state_oneshot = ostm_set_oneshot;
  118. ced->set_next_event = ostm_clock_event_next;
  119. ced->shift = 32;
  120. ced->rating = 300;
  121. ced->cpumask = cpumask_of(0);
  122. clockevents_config_and_register(ced, timer_of_rate(to), 0xf,
  123. 0xffffffff);
  124. return 0;
  125. }
  126. static int __init ostm_init(struct device_node *np)
  127. {
  128. struct timer_of *to;
  129. int ret;
  130. to = kzalloc(sizeof(*to), GFP_KERNEL);
  131. if (!to)
  132. return -ENOMEM;
  133. to->flags = TIMER_OF_BASE | TIMER_OF_CLOCK;
  134. if (system_clock) {
  135. /*
  136. * clock sources don't use interrupts, clock events do
  137. */
  138. to->flags |= TIMER_OF_IRQ;
  139. to->of_irq.flags = IRQF_TIMER | IRQF_IRQPOLL;
  140. to->of_irq.handler = ostm_timer_interrupt;
  141. }
  142. ret = timer_of_init(np, to);
  143. if (ret)
  144. goto err_free;
  145. /*
  146. * First probed device will be used as system clocksource. Any
  147. * additional devices will be used as clock events.
  148. */
  149. if (!system_clock) {
  150. ret = ostm_init_clksrc(to);
  151. if (ret)
  152. goto err_cleanup;
  153. ostm_init_sched_clock(to);
  154. pr_info("%pOF: used for clocksource\n", np);
  155. } else {
  156. ret = ostm_init_clkevt(to);
  157. if (ret)
  158. goto err_cleanup;
  159. pr_info("%pOF: used for clock events\n", np);
  160. }
  161. return 0;
  162. err_cleanup:
  163. timer_of_cleanup(to);
  164. err_free:
  165. kfree(to);
  166. return ret;
  167. }
  168. TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init);