timer-loongson1-pwm.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Clocksource driver for Loongson-1 SoC
  4. *
  5. * Copyright (c) 2023 Keguang Zhang <keguang.zhang@gmail.com>
  6. */
  7. #include <linux/clockchips.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/sizes.h>
  10. #include "timer-of.h"
  11. /* Loongson-1 PWM Timer Register Definitions */
  12. #define PWM_CNTR 0x0
  13. #define PWM_HRC 0x4
  14. #define PWM_LRC 0x8
  15. #define PWM_CTRL 0xc
  16. /* PWM Control Register Bits */
  17. #define INT_LRC_EN BIT(11)
  18. #define INT_HRC_EN BIT(10)
  19. #define CNTR_RST BIT(7)
  20. #define INT_SR BIT(6)
  21. #define INT_EN BIT(5)
  22. #define PWM_SINGLE BIT(4)
  23. #define PWM_OE BIT(3)
  24. #define CNT_EN BIT(0)
  25. #define CNTR_WIDTH 24
  26. static DEFINE_RAW_SPINLOCK(ls1x_timer_lock);
  27. struct ls1x_clocksource {
  28. void __iomem *reg_base;
  29. unsigned long ticks_per_jiffy;
  30. struct clocksource clksrc;
  31. };
  32. static inline struct ls1x_clocksource *to_ls1x_clksrc(struct clocksource *c)
  33. {
  34. return container_of(c, struct ls1x_clocksource, clksrc);
  35. }
  36. static inline void ls1x_pwmtimer_set_period(unsigned int period,
  37. struct timer_of *to)
  38. {
  39. writel(period, timer_of_base(to) + PWM_LRC);
  40. writel(period, timer_of_base(to) + PWM_HRC);
  41. }
  42. static inline void ls1x_pwmtimer_clear(struct timer_of *to)
  43. {
  44. writel(0, timer_of_base(to) + PWM_CNTR);
  45. }
  46. static inline void ls1x_pwmtimer_start(struct timer_of *to)
  47. {
  48. writel((INT_EN | PWM_OE | CNT_EN), timer_of_base(to) + PWM_CTRL);
  49. }
  50. static inline void ls1x_pwmtimer_stop(struct timer_of *to)
  51. {
  52. writel(0, timer_of_base(to) + PWM_CTRL);
  53. }
  54. static inline void ls1x_pwmtimer_irq_ack(struct timer_of *to)
  55. {
  56. int val;
  57. val = readl(timer_of_base(to) + PWM_CTRL);
  58. val |= INT_SR;
  59. writel(val, timer_of_base(to) + PWM_CTRL);
  60. }
  61. static irqreturn_t ls1x_clockevent_isr(int irq, void *dev_id)
  62. {
  63. struct clock_event_device *clkevt = dev_id;
  64. struct timer_of *to = to_timer_of(clkevt);
  65. ls1x_pwmtimer_irq_ack(to);
  66. ls1x_pwmtimer_clear(to);
  67. ls1x_pwmtimer_start(to);
  68. clkevt->event_handler(clkevt);
  69. return IRQ_HANDLED;
  70. }
  71. static int ls1x_clockevent_set_state_periodic(struct clock_event_device *clkevt)
  72. {
  73. struct timer_of *to = to_timer_of(clkevt);
  74. raw_spin_lock(&ls1x_timer_lock);
  75. ls1x_pwmtimer_set_period(timer_of_period(to), to);
  76. ls1x_pwmtimer_clear(to);
  77. ls1x_pwmtimer_start(to);
  78. raw_spin_unlock(&ls1x_timer_lock);
  79. return 0;
  80. }
  81. static int ls1x_clockevent_tick_resume(struct clock_event_device *clkevt)
  82. {
  83. raw_spin_lock(&ls1x_timer_lock);
  84. ls1x_pwmtimer_start(to_timer_of(clkevt));
  85. raw_spin_unlock(&ls1x_timer_lock);
  86. return 0;
  87. }
  88. static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *clkevt)
  89. {
  90. raw_spin_lock(&ls1x_timer_lock);
  91. ls1x_pwmtimer_stop(to_timer_of(clkevt));
  92. raw_spin_unlock(&ls1x_timer_lock);
  93. return 0;
  94. }
  95. static int ls1x_clockevent_set_next(unsigned long evt,
  96. struct clock_event_device *clkevt)
  97. {
  98. struct timer_of *to = to_timer_of(clkevt);
  99. raw_spin_lock(&ls1x_timer_lock);
  100. ls1x_pwmtimer_set_period(evt, to);
  101. ls1x_pwmtimer_clear(to);
  102. ls1x_pwmtimer_start(to);
  103. raw_spin_unlock(&ls1x_timer_lock);
  104. return 0;
  105. }
  106. static struct timer_of ls1x_to = {
  107. .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
  108. .clkevt = {
  109. .name = "ls1x-pwmtimer",
  110. .features = CLOCK_EVT_FEAT_PERIODIC |
  111. CLOCK_EVT_FEAT_ONESHOT,
  112. .rating = 300,
  113. .set_next_event = ls1x_clockevent_set_next,
  114. .set_state_periodic = ls1x_clockevent_set_state_periodic,
  115. .set_state_oneshot = ls1x_clockevent_set_state_shutdown,
  116. .set_state_shutdown = ls1x_clockevent_set_state_shutdown,
  117. .tick_resume = ls1x_clockevent_tick_resume,
  118. },
  119. .of_irq = {
  120. .handler = ls1x_clockevent_isr,
  121. .flags = IRQF_TIMER,
  122. },
  123. };
  124. /*
  125. * Since the PWM timer overflows every two ticks, its not very useful
  126. * to just read by itself. So use jiffies to emulate a free
  127. * running counter:
  128. */
  129. static u64 ls1x_clocksource_read(struct clocksource *cs)
  130. {
  131. struct ls1x_clocksource *ls1x_cs = to_ls1x_clksrc(cs);
  132. unsigned long flags;
  133. int count;
  134. u32 jifs;
  135. static int old_count;
  136. static u32 old_jifs;
  137. raw_spin_lock_irqsave(&ls1x_timer_lock, flags);
  138. /*
  139. * Although our caller may have the read side of xtime_lock,
  140. * this is now a seqlock, and we are cheating in this routine
  141. * by having side effects on state that we cannot undo if
  142. * there is a collision on the seqlock and our caller has to
  143. * retry. (Namely, old_jifs and old_count.) So we must treat
  144. * jiffies as volatile despite the lock. We read jiffies
  145. * before latching the timer count to guarantee that although
  146. * the jiffies value might be older than the count (that is,
  147. * the counter may underflow between the last point where
  148. * jiffies was incremented and the point where we latch the
  149. * count), it cannot be newer.
  150. */
  151. jifs = jiffies;
  152. /* read the count */
  153. count = readl(ls1x_cs->reg_base + PWM_CNTR);
  154. /*
  155. * It's possible for count to appear to go the wrong way for this
  156. * reason:
  157. *
  158. * The timer counter underflows, but we haven't handled the resulting
  159. * interrupt and incremented jiffies yet.
  160. *
  161. * Previous attempts to handle these cases intelligently were buggy, so
  162. * we just do the simple thing now.
  163. */
  164. if (count < old_count && jifs == old_jifs)
  165. count = old_count;
  166. old_count = count;
  167. old_jifs = jifs;
  168. raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags);
  169. return (u64)(jifs * ls1x_cs->ticks_per_jiffy) + count;
  170. }
  171. static struct ls1x_clocksource ls1x_clocksource = {
  172. .clksrc = {
  173. .name = "ls1x-pwmtimer",
  174. .rating = 300,
  175. .read = ls1x_clocksource_read,
  176. .mask = CLOCKSOURCE_MASK(CNTR_WIDTH),
  177. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  178. },
  179. };
  180. static int __init ls1x_pwm_clocksource_init(struct device_node *np)
  181. {
  182. struct timer_of *to = &ls1x_to;
  183. int ret;
  184. ret = timer_of_init(np, to);
  185. if (ret)
  186. return ret;
  187. clockevents_config_and_register(&to->clkevt, timer_of_rate(to),
  188. 0x1, GENMASK(CNTR_WIDTH - 1, 0));
  189. ls1x_clocksource.reg_base = timer_of_base(to);
  190. ls1x_clocksource.ticks_per_jiffy = timer_of_period(to);
  191. return clocksource_register_hz(&ls1x_clocksource.clksrc,
  192. timer_of_rate(to));
  193. }
  194. TIMER_OF_DECLARE(ls1x_pwm_clocksource, "loongson,ls1b-pwmtimer",
  195. ls1x_pwm_clocksource_init);