cevt-rt3352.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 void systick_set_clock_mode(enum clock_event_mode mode,
  33. 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 + delta, 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_mode = systick_set_clock_mode,
  65. .event_handler = systick_event_handler,
  66. },
  67. };
  68. static struct irqaction systick_irqaction = {
  69. .handler = systick_interrupt,
  70. .flags = IRQF_PERCPU | IRQF_TIMER,
  71. .dev_id = &systick.dev,
  72. };
  73. static void systick_set_clock_mode(enum clock_event_mode mode,
  74. struct clock_event_device *evt)
  75. {
  76. struct systick_device *sdev;
  77. sdev = container_of(evt, struct systick_device, dev);
  78. switch (mode) {
  79. case CLOCK_EVT_MODE_ONESHOT:
  80. if (!sdev->irq_requested)
  81. setup_irq(systick.dev.irq, &systick_irqaction);
  82. sdev->irq_requested = 1;
  83. iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
  84. systick.membase + SYSTICK_CONFIG);
  85. break;
  86. case CLOCK_EVT_MODE_SHUTDOWN:
  87. if (sdev->irq_requested)
  88. free_irq(systick.dev.irq, &systick_irqaction);
  89. sdev->irq_requested = 0;
  90. iowrite32(0, systick.membase + SYSTICK_CONFIG);
  91. break;
  92. default:
  93. pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name);
  94. break;
  95. }
  96. }
  97. static void __init ralink_systick_init(struct device_node *np)
  98. {
  99. systick.membase = of_iomap(np, 0);
  100. if (!systick.membase)
  101. return;
  102. systick_irqaction.name = np->name;
  103. systick.dev.name = np->name;
  104. clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
  105. systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
  106. systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
  107. systick.dev.irq = irq_of_parse_and_map(np, 0);
  108. if (!systick.dev.irq) {
  109. pr_err("%s: request_irq failed", np->name);
  110. return;
  111. }
  112. clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
  113. SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up);
  114. clockevents_register_device(&systick.dev);
  115. pr_info("%s: runing - mult: %d, shift: %d\n",
  116. np->name, systick.dev.mult, systick.dev.shift);
  117. }
  118. CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);