cevt-rt3352.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2013 by John Crispin <blogic@openwrt.org>
  7. */
  8. #include <linux/clockchips.h>
  9. #include <linux/clocksource.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/reset.h>
  12. #include <linux/init.h>
  13. #include <linux/time.h>
  14. #include <linux/of.h>
  15. #include <linux/of_irq.h>
  16. #include <linux/of_address.h>
  17. #include <asm/mach-ralink/ralink_regs.h>
  18. #define SYSTICK_FREQ (50 * 1000)
  19. #define SYSTICK_CONFIG 0x00
  20. #define SYSTICK_COMPARE 0x04
  21. #define SYSTICK_COUNT 0x08
  22. /* route systick irq to mips irq 7 instead of the r4k-timer */
  23. #define CFG_EXT_STK_EN 0x2
  24. /* enable the counter */
  25. #define CFG_CNT_EN 0x1
  26. struct systick_device {
  27. void __iomem *membase;
  28. struct clock_event_device dev;
  29. int irq_requested;
  30. int freq_scale;
  31. };
  32. static int systick_set_oneshot(struct clock_event_device *evt);
  33. static int systick_shutdown(struct clock_event_device *evt);
  34. static int systick_next_event(unsigned long delta,
  35. struct clock_event_device *evt)
  36. {
  37. struct systick_device *sdev;
  38. u32 count;
  39. sdev = container_of(evt, struct systick_device, dev);
  40. count = ioread32(sdev->membase + SYSTICK_COUNT);
  41. count = (count + delta) % SYSTICK_FREQ;
  42. iowrite32(count, sdev->membase + SYSTICK_COMPARE);
  43. return 0;
  44. }
  45. static void systick_event_handler(struct clock_event_device *dev)
  46. {
  47. /* noting to do here */
  48. }
  49. static irqreturn_t systick_interrupt(int irq, void *dev_id)
  50. {
  51. struct clock_event_device *dev = (struct clock_event_device *) dev_id;
  52. dev->event_handler(dev);
  53. return IRQ_HANDLED;
  54. }
  55. static struct systick_device systick = {
  56. .dev = {
  57. /*
  58. * cevt-r4k uses 300, make sure systick
  59. * gets used if available
  60. */
  61. .rating = 310,
  62. .features = CLOCK_EVT_FEAT_ONESHOT,
  63. .set_next_event = systick_next_event,
  64. .set_state_shutdown = systick_shutdown,
  65. .set_state_oneshot = systick_set_oneshot,
  66. .event_handler = systick_event_handler,
  67. },
  68. };
  69. static struct irqaction systick_irqaction = {
  70. .handler = systick_interrupt,
  71. .flags = IRQF_PERCPU | IRQF_TIMER,
  72. .dev_id = &systick.dev,
  73. };
  74. static int systick_shutdown(struct clock_event_device *evt)
  75. {
  76. struct systick_device *sdev;
  77. sdev = container_of(evt, struct systick_device, dev);
  78. if (sdev->irq_requested)
  79. free_irq(systick.dev.irq, &systick_irqaction);
  80. sdev->irq_requested = 0;
  81. iowrite32(0, systick.membase + SYSTICK_CONFIG);
  82. return 0;
  83. }
  84. static int systick_set_oneshot(struct clock_event_device *evt)
  85. {
  86. struct systick_device *sdev;
  87. sdev = container_of(evt, struct systick_device, dev);
  88. if (!sdev->irq_requested)
  89. setup_irq(systick.dev.irq, &systick_irqaction);
  90. sdev->irq_requested = 1;
  91. iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
  92. systick.membase + SYSTICK_CONFIG);
  93. return 0;
  94. }
  95. static void __init ralink_systick_init(struct device_node *np)
  96. {
  97. systick.membase = of_iomap(np, 0);
  98. if (!systick.membase)
  99. return;
  100. systick_irqaction.name = np->name;
  101. systick.dev.name = np->name;
  102. clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
  103. systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
  104. systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
  105. systick.dev.irq = irq_of_parse_and_map(np, 0);
  106. if (!systick.dev.irq) {
  107. pr_err("%s: request_irq failed", np->name);
  108. return;
  109. }
  110. clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
  111. SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up);
  112. clockevents_register_device(&systick.dev);
  113. pr_info("%s: running - mult: %d, shift: %d\n",
  114. np->name, systick.dev.mult, systick.dev.shift);
  115. }
  116. CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);