timer-meson6.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Amlogic Meson6 SoCs timer handling.
  4. *
  5. * Copyright (C) 2014 Carlo Caione <[email protected]>
  6. *
  7. * Based on code from Amlogic, Inc
  8. */
  9. #include <linux/bitfield.h>
  10. #include <linux/bitops.h>
  11. #include <linux/clk.h>
  12. #include <linux/clockchips.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/irq.h>
  15. #include <linux/irqreturn.h>
  16. #include <linux/sched_clock.h>
  17. #include <linux/of.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of_irq.h>
  20. #ifdef CONFIG_ARM
  21. #include <linux/delay.h>
  22. #endif
  23. #define MESON_ISA_TIMER_MUX 0x00
  24. #define MESON_ISA_TIMER_MUX_TIMERD_EN BIT(19)
  25. #define MESON_ISA_TIMER_MUX_TIMERC_EN BIT(18)
  26. #define MESON_ISA_TIMER_MUX_TIMERB_EN BIT(17)
  27. #define MESON_ISA_TIMER_MUX_TIMERA_EN BIT(16)
  28. #define MESON_ISA_TIMER_MUX_TIMERD_MODE BIT(15)
  29. #define MESON_ISA_TIMER_MUX_TIMERC_MODE BIT(14)
  30. #define MESON_ISA_TIMER_MUX_TIMERB_MODE BIT(13)
  31. #define MESON_ISA_TIMER_MUX_TIMERA_MODE BIT(12)
  32. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK GENMASK(10, 8)
  33. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_SYSTEM_CLOCK 0x0
  34. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US 0x1
  35. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_10US 0x2
  36. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_100US 0x3
  37. #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1MS 0x4
  38. #define MESON_ISA_TIMER_MUX_TIMERD_INPUT_CLOCK_MASK GENMASK(7, 6)
  39. #define MESON_ISA_TIMER_MUX_TIMERC_INPUT_CLOCK_MASK GENMASK(5, 4)
  40. #define MESON_ISA_TIMER_MUX_TIMERB_INPUT_CLOCK_MASK GENMASK(3, 2)
  41. #define MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK GENMASK(1, 0)
  42. #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US 0x0
  43. #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_10US 0x1
  44. #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_100US 0x0
  45. #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1MS 0x3
  46. #define MESON_ISA_TIMERA 0x04
  47. #define MESON_ISA_TIMERB 0x08
  48. #define MESON_ISA_TIMERC 0x0c
  49. #define MESON_ISA_TIMERD 0x10
  50. #define MESON_ISA_TIMERE 0x14
  51. static void __iomem *timer_base;
  52. #ifdef CONFIG_ARM
  53. static unsigned long meson6_read_current_timer(void)
  54. {
  55. return readl_relaxed(timer_base + MESON_ISA_TIMERE);
  56. }
  57. static struct delay_timer meson6_delay_timer = {
  58. .read_current_timer = meson6_read_current_timer,
  59. .freq = 1000 * 1000,
  60. };
  61. #endif
  62. static u64 notrace meson6_timer_sched_read(void)
  63. {
  64. return (u64)readl(timer_base + MESON_ISA_TIMERE);
  65. }
  66. static void meson6_clkevt_time_stop(void)
  67. {
  68. u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
  69. writel(val & ~MESON_ISA_TIMER_MUX_TIMERA_EN,
  70. timer_base + MESON_ISA_TIMER_MUX);
  71. }
  72. static void meson6_clkevt_time_setup(unsigned long delay)
  73. {
  74. writel(delay, timer_base + MESON_ISA_TIMERA);
  75. }
  76. static void meson6_clkevt_time_start(bool periodic)
  77. {
  78. u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
  79. if (periodic)
  80. val |= MESON_ISA_TIMER_MUX_TIMERA_MODE;
  81. else
  82. val &= ~MESON_ISA_TIMER_MUX_TIMERA_MODE;
  83. writel(val | MESON_ISA_TIMER_MUX_TIMERA_EN,
  84. timer_base + MESON_ISA_TIMER_MUX);
  85. }
  86. static int meson6_shutdown(struct clock_event_device *evt)
  87. {
  88. meson6_clkevt_time_stop();
  89. return 0;
  90. }
  91. static int meson6_set_oneshot(struct clock_event_device *evt)
  92. {
  93. meson6_clkevt_time_stop();
  94. meson6_clkevt_time_start(false);
  95. return 0;
  96. }
  97. static int meson6_set_periodic(struct clock_event_device *evt)
  98. {
  99. meson6_clkevt_time_stop();
  100. meson6_clkevt_time_setup(USEC_PER_SEC / HZ - 1);
  101. meson6_clkevt_time_start(true);
  102. return 0;
  103. }
  104. static int meson6_clkevt_next_event(unsigned long evt,
  105. struct clock_event_device *unused)
  106. {
  107. meson6_clkevt_time_stop();
  108. meson6_clkevt_time_setup(evt);
  109. meson6_clkevt_time_start(false);
  110. return 0;
  111. }
  112. static struct clock_event_device meson6_clockevent = {
  113. .name = "meson6_tick",
  114. .rating = 400,
  115. .features = CLOCK_EVT_FEAT_PERIODIC |
  116. CLOCK_EVT_FEAT_ONESHOT,
  117. .set_state_shutdown = meson6_shutdown,
  118. .set_state_periodic = meson6_set_periodic,
  119. .set_state_oneshot = meson6_set_oneshot,
  120. .tick_resume = meson6_shutdown,
  121. .set_next_event = meson6_clkevt_next_event,
  122. };
  123. static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id)
  124. {
  125. struct clock_event_device *evt = (struct clock_event_device *)dev_id;
  126. evt->event_handler(evt);
  127. return IRQ_HANDLED;
  128. }
  129. static int __init meson6_timer_init(struct device_node *node)
  130. {
  131. u32 val;
  132. int ret, irq;
  133. timer_base = of_io_request_and_map(node, 0, "meson6-timer");
  134. if (IS_ERR(timer_base)) {
  135. pr_err("Can't map registers\n");
  136. return -ENXIO;
  137. }
  138. irq = irq_of_parse_and_map(node, 0);
  139. if (irq <= 0) {
  140. pr_err("Can't parse IRQ\n");
  141. return -EINVAL;
  142. }
  143. /* Set 1us for timer E */
  144. val = readl(timer_base + MESON_ISA_TIMER_MUX);
  145. val &= ~MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK;
  146. val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK,
  147. MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US);
  148. writel(val, timer_base + MESON_ISA_TIMER_MUX);
  149. sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC);
  150. clocksource_mmio_init(timer_base + MESON_ISA_TIMERE, node->name,
  151. 1000 * 1000, 300, 32, clocksource_mmio_readl_up);
  152. /* Timer A base 1us */
  153. val &= ~MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK;
  154. val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK,
  155. MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US);
  156. writel(val, timer_base + MESON_ISA_TIMER_MUX);
  157. /* Stop the timer A */
  158. meson6_clkevt_time_stop();
  159. ret = request_irq(irq, meson6_timer_interrupt,
  160. IRQF_TIMER | IRQF_IRQPOLL, "meson6_timer",
  161. &meson6_clockevent);
  162. if (ret) {
  163. pr_warn("failed to setup irq %d\n", irq);
  164. return ret;
  165. }
  166. meson6_clockevent.cpumask = cpu_possible_mask;
  167. meson6_clockevent.irq = irq;
  168. clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC,
  169. 1, 0xfffe);
  170. #ifdef CONFIG_ARM
  171. /* Also use MESON_ISA_TIMERE for delays */
  172. register_current_timer_delay(&meson6_delay_timer);
  173. #endif
  174. return 0;
  175. }
  176. TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",
  177. meson6_timer_init);