timer.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * System timer for Freescale STMP37XX/STMP378X
  3. *
  4. * Embedded Alley Solutions, Inc <source@embeddedalley.com>
  5. *
  6. * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  7. * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  8. */
  9. /*
  10. * The code contained herein is licensed under the GNU General Public
  11. * License. You may obtain a copy of the GNU General Public License
  12. * Version 2 or later at the following locations:
  13. *
  14. * http://www.opensource.org/licenses/gpl-license.html
  15. * http://www.gnu.org/copyleft/gpl.html
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/init.h>
  19. #include <linux/spinlock.h>
  20. #include <linux/clocksource.h>
  21. #include <linux/clockchips.h>
  22. #include <linux/io.h>
  23. #include <linux/irq.h>
  24. #include <linux/interrupt.h>
  25. #include <asm/mach/time.h>
  26. #include <mach/stmp3xxx.h>
  27. #include <mach/regs-timrot.h>
  28. static irqreturn_t
  29. stmp3xxx_timer_interrupt(int irq, void *dev_id)
  30. {
  31. struct clock_event_device *c = dev_id;
  32. if (HW_TIMROT_TIMCTRLn_RD(0) & (1<<15)) {
  33. HW_TIMROT_TIMCTRLn_CLR(0, (1<<15));
  34. c->event_handler(c);
  35. } else if (HW_TIMROT_TIMCTRLn_RD(1) & (1<<15)) {
  36. HW_TIMROT_TIMCTRLn_CLR(1, (1<<15));
  37. HW_TIMROT_TIMCTRLn_CLR(1, BM_TIMROT_TIMCTRLn_IRQ_EN);
  38. HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF);
  39. }
  40. return IRQ_HANDLED;
  41. }
  42. static cycle_t stmp3xxx_clock_read(struct clocksource *cs)
  43. {
  44. return ~((HW_TIMROT_TIMCOUNTn_RD(1) & 0xFFFF0000) >> 16);
  45. }
  46. static int
  47. stmp3xxx_timrot_set_next_event(unsigned long delta,
  48. struct clock_event_device *dev)
  49. {
  50. HW_TIMROT_TIMCOUNTn_WR(0, delta); /* reload */
  51. return 0;
  52. }
  53. static void
  54. stmp3xxx_timrot_set_mode(enum clock_event_mode mode,
  55. struct clock_event_device *dev)
  56. {
  57. }
  58. static struct clock_event_device ckevt_timrot = {
  59. .name = "timrot",
  60. .features = CLOCK_EVT_FEAT_ONESHOT,
  61. .shift = 32,
  62. .set_next_event = stmp3xxx_timrot_set_next_event,
  63. .set_mode = stmp3xxx_timrot_set_mode,
  64. };
  65. static struct clocksource cksrc_stmp3xxx = {
  66. .name = "cksrc_stmp3xxx",
  67. .rating = 250,
  68. .read = stmp3xxx_clock_read,
  69. .mask = CLOCKSOURCE_MASK(16),
  70. .shift = 10,
  71. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  72. };
  73. static struct irqaction stmp3xxx_timer_irq = {
  74. .name = "stmp3xxx_timer",
  75. .flags = IRQF_DISABLED | IRQF_TIMER,
  76. .handler = stmp3xxx_timer_interrupt,
  77. .dev_id = &ckevt_timrot,
  78. };
  79. /*
  80. * Set up timer interrupt, and return the current time in seconds.
  81. */
  82. static void __init stmp3xxx_init_timer(void)
  83. {
  84. cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
  85. cksrc_stmp3xxx.shift);
  86. ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
  87. ckevt_timrot.shift);
  88. ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
  89. ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
  90. ckevt_timrot.cpumask = cpumask_of(0);
  91. HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST |
  92. BM_TIMROT_ROTCTRL_CLKGATE);
  93. HW_TIMROT_TIMCOUNTn_WR(0, 0);
  94. HW_TIMROT_TIMCOUNTn_WR(1, 0);
  95. HW_TIMROT_TIMCTRLn_WR(0,
  96. (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
  97. BF_TIMROT_TIMCTRLn_PRESCALE(0) |
  98. BM_TIMROT_TIMCTRLn_RELOAD |
  99. BM_TIMROT_TIMCTRLn_UPDATE |
  100. BM_TIMROT_TIMCTRLn_IRQ_EN));
  101. HW_TIMROT_TIMCTRLn_WR(1,
  102. (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
  103. BF_TIMROT_TIMCTRLn_PRESCALE(0) |
  104. BM_TIMROT_TIMCTRLn_RELOAD |
  105. BM_TIMROT_TIMCTRLn_UPDATE));
  106. HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1);
  107. HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */
  108. setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
  109. clocksource_register(&cksrc_stmp3xxx);
  110. clockevents_register_device(&ckevt_timrot);
  111. }
  112. #ifdef CONFIG_PM
  113. void stmp3xxx_suspend_timer(void)
  114. {
  115. HW_TIMROT_TIMCTRLn_CLR(0, BM_TIMROT_TIMCTRLn_IRQ_EN);
  116. HW_TIMROT_TIMCTRLn_CLR(0, (1<<15));
  117. HW_TIMROT_ROTCTRL_SET(BM_TIMROT_ROTCTRL_CLKGATE);
  118. }
  119. void stmp3xxx_resume_timer(void)
  120. {
  121. HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST |
  122. BM_TIMROT_ROTCTRL_CLKGATE);
  123. HW_TIMROT_TIMCTRLn_WR(0,
  124. (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
  125. BF_TIMROT_TIMCTRLn_PRESCALE(0) |
  126. BM_TIMROT_TIMCTRLn_UPDATE |
  127. BM_TIMROT_TIMCTRLn_IRQ_EN));
  128. HW_TIMROT_TIMCTRLn_WR(1,
  129. (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
  130. BF_TIMROT_TIMCTRLn_PRESCALE(0) |
  131. BM_TIMROT_TIMCTRLn_RELOAD |
  132. BM_TIMROT_TIMCTRLn_UPDATE));
  133. HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1);
  134. HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */
  135. }
  136. #else
  137. #define stmp3xxx_suspend_timer NULL
  138. #define stmp3xxx_resume_timer NULL
  139. #endif /* CONFIG_PM */
  140. struct sys_timer stmp3xxx_timer = {
  141. .init = stmp3xxx_init_timer,
  142. .suspend = stmp3xxx_suspend_timer,
  143. .resume = stmp3xxx_resume_timer,
  144. };