timer-prima2.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * System timer for CSR SiRFprimaII
  4. *
  5. * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/clockchips.h>
  10. #include <linux/clocksource.h>
  11. #include <linux/bitops.h>
  12. #include <linux/irq.h>
  13. #include <linux/clk.h>
  14. #include <linux/err.h>
  15. #include <linux/slab.h>
  16. #include <linux/of.h>
  17. #include <linux/of_irq.h>
  18. #include <linux/of_address.h>
  19. #include <linux/sched_clock.h>
  20. #define PRIMA2_CLOCK_FREQ 1000000
  21. #define SIRFSOC_TIMER_COUNTER_LO 0x0000
  22. #define SIRFSOC_TIMER_COUNTER_HI 0x0004
  23. #define SIRFSOC_TIMER_MATCH_0 0x0008
  24. #define SIRFSOC_TIMER_MATCH_1 0x000C
  25. #define SIRFSOC_TIMER_MATCH_2 0x0010
  26. #define SIRFSOC_TIMER_MATCH_3 0x0014
  27. #define SIRFSOC_TIMER_MATCH_4 0x0018
  28. #define SIRFSOC_TIMER_MATCH_5 0x001C
  29. #define SIRFSOC_TIMER_STATUS 0x0020
  30. #define SIRFSOC_TIMER_INT_EN 0x0024
  31. #define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
  32. #define SIRFSOC_TIMER_DIV 0x002C
  33. #define SIRFSOC_TIMER_LATCH 0x0030
  34. #define SIRFSOC_TIMER_LATCHED_LO 0x0034
  35. #define SIRFSOC_TIMER_LATCHED_HI 0x0038
  36. #define SIRFSOC_TIMER_WDT_INDEX 5
  37. #define SIRFSOC_TIMER_LATCH_BIT BIT(0)
  38. #define SIRFSOC_TIMER_REG_CNT 11
  39. static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
  40. SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
  41. SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
  42. SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
  43. SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
  44. };
  45. static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
  46. static void __iomem *sirfsoc_timer_base;
  47. /* timer0 interrupt handler */
  48. static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
  49. {
  50. struct clock_event_device *ce = dev_id;
  51. WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) &
  52. BIT(0)));
  53. /* clear timer0 interrupt */
  54. writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
  55. ce->event_handler(ce);
  56. return IRQ_HANDLED;
  57. }
  58. /* read 64-bit timer counter */
  59. static u64 notrace sirfsoc_timer_read(struct clocksource *cs)
  60. {
  61. u64 cycles;
  62. /* latch the 64-bit timer counter */
  63. writel_relaxed(SIRFSOC_TIMER_LATCH_BIT,
  64. sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  65. cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
  66. cycles = (cycles << 32) |
  67. readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  68. return cycles;
  69. }
  70. static int sirfsoc_timer_set_next_event(unsigned long delta,
  71. struct clock_event_device *ce)
  72. {
  73. unsigned long now, next;
  74. writel_relaxed(SIRFSOC_TIMER_LATCH_BIT,
  75. sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  76. now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  77. next = now + delta;
  78. writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
  79. writel_relaxed(SIRFSOC_TIMER_LATCH_BIT,
  80. sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  81. now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  82. return next - now > delta ? -ETIME : 0;
  83. }
  84. static int sirfsoc_timer_shutdown(struct clock_event_device *evt)
  85. {
  86. u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  87. writel_relaxed(val & ~BIT(0),
  88. sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  89. return 0;
  90. }
  91. static int sirfsoc_timer_set_oneshot(struct clock_event_device *evt)
  92. {
  93. u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  94. writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  95. return 0;
  96. }
  97. static void sirfsoc_clocksource_suspend(struct clocksource *cs)
  98. {
  99. int i;
  100. writel_relaxed(SIRFSOC_TIMER_LATCH_BIT,
  101. sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  102. for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
  103. sirfsoc_timer_reg_val[i] =
  104. readl_relaxed(sirfsoc_timer_base +
  105. sirfsoc_timer_reg_list[i]);
  106. }
  107. static void sirfsoc_clocksource_resume(struct clocksource *cs)
  108. {
  109. int i;
  110. for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
  111. writel_relaxed(sirfsoc_timer_reg_val[i],
  112. sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
  113. writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
  114. sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
  115. writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
  116. sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
  117. }
  118. static struct clock_event_device sirfsoc_clockevent = {
  119. .name = "sirfsoc_clockevent",
  120. .rating = 200,
  121. .features = CLOCK_EVT_FEAT_ONESHOT,
  122. .set_state_shutdown = sirfsoc_timer_shutdown,
  123. .set_state_oneshot = sirfsoc_timer_set_oneshot,
  124. .set_next_event = sirfsoc_timer_set_next_event,
  125. };
  126. static struct clocksource sirfsoc_clocksource = {
  127. .name = "sirfsoc_clocksource",
  128. .rating = 200,
  129. .mask = CLOCKSOURCE_MASK(64),
  130. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  131. .read = sirfsoc_timer_read,
  132. .suspend = sirfsoc_clocksource_suspend,
  133. .resume = sirfsoc_clocksource_resume,
  134. };
  135. /* Overwrite weak default sched_clock with more precise one */
  136. static u64 notrace sirfsoc_read_sched_clock(void)
  137. {
  138. return sirfsoc_timer_read(NULL);
  139. }
  140. static void __init sirfsoc_clockevent_init(void)
  141. {
  142. sirfsoc_clockevent.cpumask = cpumask_of(0);
  143. clockevents_config_and_register(&sirfsoc_clockevent, PRIMA2_CLOCK_FREQ,
  144. 2, -2);
  145. }
  146. /* initialize the kernel jiffy timer source */
  147. static int __init sirfsoc_prima2_timer_init(struct device_node *np)
  148. {
  149. unsigned long rate;
  150. unsigned int irq;
  151. struct clk *clk;
  152. int ret;
  153. clk = of_clk_get(np, 0);
  154. if (IS_ERR(clk)) {
  155. pr_err("Failed to get clock\n");
  156. return PTR_ERR(clk);
  157. }
  158. ret = clk_prepare_enable(clk);
  159. if (ret) {
  160. pr_err("Failed to enable clock\n");
  161. return ret;
  162. }
  163. rate = clk_get_rate(clk);
  164. if (rate < PRIMA2_CLOCK_FREQ || rate % PRIMA2_CLOCK_FREQ) {
  165. pr_err("Invalid clock rate\n");
  166. return -EINVAL;
  167. }
  168. sirfsoc_timer_base = of_iomap(np, 0);
  169. if (!sirfsoc_timer_base) {
  170. pr_err("unable to map timer cpu registers\n");
  171. return -ENXIO;
  172. }
  173. irq = irq_of_parse_and_map(np, 0);
  174. writel_relaxed(rate / PRIMA2_CLOCK_FREQ / 2 - 1,
  175. sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
  176. writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
  177. writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
  178. writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
  179. ret = clocksource_register_hz(&sirfsoc_clocksource, PRIMA2_CLOCK_FREQ);
  180. if (ret) {
  181. pr_err("Failed to register clocksource\n");
  182. return ret;
  183. }
  184. sched_clock_register(sirfsoc_read_sched_clock, 64, PRIMA2_CLOCK_FREQ);
  185. ret = request_irq(irq, sirfsoc_timer_interrupt, IRQF_TIMER,
  186. "sirfsoc_timer0", &sirfsoc_clockevent);
  187. if (ret) {
  188. pr_err("Failed to setup irq\n");
  189. return ret;
  190. }
  191. sirfsoc_clockevent_init();
  192. return 0;
  193. }
  194. TIMER_OF_DECLARE(sirfsoc_prima2_timer,
  195. "sirf,prima2-tick", sirfsoc_prima2_timer_init);