cevt-rtl9300.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/clockchips.h>
  3. #include <linux/init.h>
  4. #include <asm/time.h>
  5. #include <asm/idle.h>
  6. #include <linux/interrupt.h>
  7. #include <linux/of_address.h>
  8. #include <linux/of_irq.h>
  9. #include <linux/sched_clock.h>
  10. #include <mach-rtl83xx.h>
  11. /*
  12. * Timer registers
  13. * the RTL9300/9310 SoCs have 6 timers, each register block 0x10 apart
  14. */
  15. #define RTL9300_TC_DATA 0x0
  16. #define RTL9300_TC_CNT 0x4
  17. #define RTL9300_TC_CTRL 0x8
  18. #define RTL9300_TC_CTRL_MODE BIT(24)
  19. #define RTL9300_TC_CTRL_EN BIT(28)
  20. #define RTL9300_TC_INT 0xc
  21. #define RTL9300_TC_INT_IP BIT(16)
  22. #define RTL9300_TC_INT_IE BIT(20)
  23. // Timer modes
  24. #define TIMER_MODE_REPEAT 1
  25. #define TIMER_MODE_ONCE 0
  26. // Minimum divider is 2
  27. #define DIVISOR_RTL9300 2
  28. #define N_BITS 28
  29. #define RTL9300_CLOCK_RATE 87500000
  30. struct rtl9300_clk_dev {
  31. struct clock_event_device clkdev;
  32. void __iomem *base;
  33. };
  34. static void __iomem *rtl9300_tc_base(struct clock_event_device *clk)
  35. {
  36. struct rtl9300_clk_dev *rtl_clk = container_of(clk, struct rtl9300_clk_dev, clkdev);
  37. return rtl_clk->base;
  38. }
  39. static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
  40. {
  41. struct rtl9300_clk_dev *rtl_clk = dev_id;
  42. struct clock_event_device *clk = &rtl_clk->clkdev;
  43. u32 v = readl(rtl_clk->base + RTL9300_TC_INT);
  44. // Acknowledge the IRQ
  45. v |= RTL9300_TC_INT_IP;
  46. writel(v, rtl_clk->base + RTL9300_TC_INT);
  47. clk->event_handler(clk);
  48. return IRQ_HANDLED;
  49. }
  50. static void rtl9300_clock_stop(void __iomem *base)
  51. {
  52. u32 v;
  53. writel(0, base + RTL9300_TC_CTRL);
  54. // Acknowledge possibly pending IRQ
  55. v = readl(base + RTL9300_TC_INT);
  56. writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
  57. }
  58. static void rtl9300_timer_start(void __iomem *base, bool periodic)
  59. {
  60. u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300;
  61. writel(0, base + RTL9300_TC_CNT);
  62. pr_debug("------------- starting timer base %08x\n", (u32)base);
  63. writel(v, base + RTL9300_TC_CTRL);
  64. }
  65. static int rtl9300_next_event(unsigned long delta, struct clock_event_device *clk)
  66. {
  67. void __iomem *base = rtl9300_tc_base(clk);
  68. rtl9300_clock_stop(base);
  69. writel(delta, base + RTL9300_TC_DATA);
  70. rtl9300_timer_start(base, TIMER_MODE_ONCE);
  71. return 0;
  72. }
  73. static int rtl9300_state_periodic(struct clock_event_device *clk)
  74. {
  75. void __iomem *base = rtl9300_tc_base(clk);
  76. pr_debug("------------- rtl9300_state_periodic %08x\n", (u32)base);
  77. rtl9300_clock_stop(base);
  78. writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
  79. rtl9300_timer_start(base, TIMER_MODE_REPEAT);
  80. return 0;
  81. }
  82. static int rtl9300_state_oneshot(struct clock_event_device *clk)
  83. {
  84. void __iomem *base = rtl9300_tc_base(clk);
  85. pr_debug("------------- rtl9300_state_oneshot %08x\n", (u32)base);
  86. rtl9300_clock_stop(base);
  87. writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
  88. rtl9300_timer_start(base, TIMER_MODE_ONCE);
  89. return 0;
  90. }
  91. static int rtl9300_shutdown(struct clock_event_device *clk)
  92. {
  93. void __iomem *base = rtl9300_tc_base(clk);
  94. pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
  95. rtl9300_clock_stop(base);
  96. return 0;
  97. }
  98. static void rtl9300_clock_setup(void __iomem *base)
  99. {
  100. u32 v;
  101. // Disable timer
  102. writel(0, base + RTL9300_TC_CTRL);
  103. // Acknowledge possibly pending IRQ
  104. v = readl(base + RTL9300_TC_INT);
  105. writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
  106. // Setup maximum period (for use as clock-source)
  107. writel(0x0fffffff, base + RTL9300_TC_DATA);
  108. }
  109. static DEFINE_PER_CPU(struct rtl9300_clk_dev, rtl9300_clockevent);
  110. static DEFINE_PER_CPU(char [18], rtl9300_clock_name);
  111. void rtl9300_clockevent_init(void)
  112. {
  113. int cpu = smp_processor_id();
  114. int irq;
  115. struct rtl9300_clk_dev *rtl_clk = &per_cpu(rtl9300_clockevent, cpu);
  116. struct clock_event_device *cd = &rtl_clk->clkdev;
  117. unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
  118. unsigned long flags = IRQF_PERCPU | IRQF_TIMER;
  119. struct device_node *node;
  120. pr_info("%s called for cpu%d\n", __func__, cpu);
  121. BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
  122. node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300clock");
  123. if (!node) {
  124. pr_err("No DT entry found for realtek,rtl9300clock\n");
  125. return;
  126. }
  127. irq = irq_of_parse_and_map(node, cpu);
  128. pr_info("%s using IRQ %d\n", __func__, irq);
  129. rtl_clk->base = of_iomap(node, cpu);
  130. if (!rtl_clk->base) {
  131. pr_err("cannot map timer for cpu %d", cpu);
  132. return;
  133. }
  134. rtl9300_clock_setup(rtl_clk->base);
  135. sprintf(name, "rtl9300-counter-%d", cpu);
  136. cd->name = name;
  137. cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
  138. clockevent_set_clock(cd, RTL9300_CLOCK_RATE);
  139. cd->max_delta_ns = clockevent_delta2ns(0x0fffffff, cd);
  140. cd->max_delta_ticks = 0x0fffffff;
  141. cd->min_delta_ns = clockevent_delta2ns(0x20, cd);
  142. cd->min_delta_ticks = 0x20;
  143. cd->rating = 300;
  144. cd->irq = irq;
  145. cd->cpumask = cpumask_of(cpu);
  146. cd->set_next_event = rtl9300_next_event;
  147. cd->set_state_shutdown = rtl9300_shutdown;
  148. cd->set_state_periodic = rtl9300_state_periodic;
  149. cd->set_state_oneshot = rtl9300_state_oneshot;
  150. clockevents_register_device(cd);
  151. irq_set_affinity(irq, cd->cpumask);
  152. if (request_irq(irq, rtl9300_timer_interrupt, flags, name, rtl_clk))
  153. pr_err("Failed to request irq %d (%s)\n", irq, name);
  154. writel(RTL9300_TC_INT_IE, rtl_clk->base + RTL9300_TC_INT);
  155. }