cevt-gt641xx.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * GT641xx clockevent routines.
  4. *
  5. * Copyright (C) 2007 Yoichi Yuasa <[email protected]>
  6. */
  7. #include <linux/clockchips.h>
  8. #include <linux/init.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/irq.h>
  12. #include <asm/gt64120.h>
  13. #include <asm/time.h>
  14. static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock);
  15. static unsigned int gt641xx_base_clock;
  16. void gt641xx_set_base_clock(unsigned int clock)
  17. {
  18. gt641xx_base_clock = clock;
  19. }
  20. int gt641xx_timer0_state(void)
  21. {
  22. if (GT_READ(GT_TC0_OFS))
  23. return 0;
  24. GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
  25. GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK);
  26. return 1;
  27. }
  28. static int gt641xx_timer0_set_next_event(unsigned long delta,
  29. struct clock_event_device *evt)
  30. {
  31. u32 ctrl;
  32. raw_spin_lock(&gt641xx_timer_lock);
  33. ctrl = GT_READ(GT_TC_CONTROL_OFS);
  34. ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
  35. ctrl |= GT_TC_CONTROL_ENTC0_MSK;
  36. GT_WRITE(GT_TC0_OFS, delta);
  37. GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  38. raw_spin_unlock(&gt641xx_timer_lock);
  39. return 0;
  40. }
  41. static int gt641xx_timer0_shutdown(struct clock_event_device *evt)
  42. {
  43. u32 ctrl;
  44. raw_spin_lock(&gt641xx_timer_lock);
  45. ctrl = GT_READ(GT_TC_CONTROL_OFS);
  46. ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
  47. GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  48. raw_spin_unlock(&gt641xx_timer_lock);
  49. return 0;
  50. }
  51. static int gt641xx_timer0_set_oneshot(struct clock_event_device *evt)
  52. {
  53. u32 ctrl;
  54. raw_spin_lock(&gt641xx_timer_lock);
  55. ctrl = GT_READ(GT_TC_CONTROL_OFS);
  56. ctrl &= ~GT_TC_CONTROL_SELTC0_MSK;
  57. ctrl |= GT_TC_CONTROL_ENTC0_MSK;
  58. GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  59. raw_spin_unlock(&gt641xx_timer_lock);
  60. return 0;
  61. }
  62. static int gt641xx_timer0_set_periodic(struct clock_event_device *evt)
  63. {
  64. u32 ctrl;
  65. raw_spin_lock(&gt641xx_timer_lock);
  66. ctrl = GT_READ(GT_TC_CONTROL_OFS);
  67. ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
  68. GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  69. raw_spin_unlock(&gt641xx_timer_lock);
  70. return 0;
  71. }
  72. static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
  73. {
  74. }
  75. static struct clock_event_device gt641xx_timer0_clockevent = {
  76. .name = "gt641xx-timer0",
  77. .features = CLOCK_EVT_FEAT_PERIODIC |
  78. CLOCK_EVT_FEAT_ONESHOT,
  79. .irq = GT641XX_TIMER0_IRQ,
  80. .set_next_event = gt641xx_timer0_set_next_event,
  81. .set_state_shutdown = gt641xx_timer0_shutdown,
  82. .set_state_periodic = gt641xx_timer0_set_periodic,
  83. .set_state_oneshot = gt641xx_timer0_set_oneshot,
  84. .tick_resume = gt641xx_timer0_shutdown,
  85. .event_handler = gt641xx_timer0_event_handler,
  86. };
  87. static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
  88. {
  89. struct clock_event_device *cd = &gt641xx_timer0_clockevent;
  90. cd->event_handler(cd);
  91. return IRQ_HANDLED;
  92. }
  93. static int __init gt641xx_timer0_clockevent_init(void)
  94. {
  95. struct clock_event_device *cd;
  96. if (!gt641xx_base_clock)
  97. return 0;
  98. GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
  99. cd = &gt641xx_timer0_clockevent;
  100. cd->rating = 200 + gt641xx_base_clock / 10000000;
  101. clockevent_set_clock(cd, gt641xx_base_clock);
  102. cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
  103. cd->max_delta_ticks = 0x7fffffff;
  104. cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
  105. cd->min_delta_ticks = 0x300;
  106. cd->cpumask = cpumask_of(0);
  107. clockevents_register_device(&gt641xx_timer0_clockevent);
  108. return request_irq(GT641XX_TIMER0_IRQ, gt641xx_timer0_interrupt,
  109. IRQF_PERCPU | IRQF_TIMER, "gt641xx_timer0", NULL);
  110. }
  111. arch_initcall(gt641xx_timer0_clockevent_init);