160-gemini-timers.patch 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. --- a/arch/arm/mach-gemini/time.c
  2. +++ b/arch/arm/mach-gemini/time.c
  3. @@ -15,15 +15,18 @@
  4. #include <asm/mach/time.h>
  5. #include <linux/clockchips.h>
  6. #include <linux/clocksource.h>
  7. +#include <linux/sched_clock.h>
  8. /*
  9. * Register definitions for the timers
  10. */
  11. -#define TIMER_COUNT(BASE_ADDR) (BASE_ADDR + 0x00)
  12. -#define TIMER_LOAD(BASE_ADDR) (BASE_ADDR + 0x04)
  13. -#define TIMER_MATCH1(BASE_ADDR) (BASE_ADDR + 0x08)
  14. -#define TIMER_MATCH2(BASE_ADDR) (BASE_ADDR + 0x0C)
  15. -#define TIMER_CR(BASE_ADDR) (BASE_ADDR + 0x30)
  16. +#define TIMER_COUNT(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x00)
  17. +#define TIMER_LOAD(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x04)
  18. +#define TIMER_MATCH1(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x08)
  19. +#define TIMER_MATCH2(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x0C)
  20. +#define TIMER_CR(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x30)
  21. +#define TIMER_INTR_STATE(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x34)
  22. +#define TIMER_INTR_MASK(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x38)
  23. #define TIMER_1_CR_ENABLE (1 << 0)
  24. #define TIMER_1_CR_CLOCK (1 << 1)
  25. @@ -34,27 +37,38 @@
  26. #define TIMER_3_CR_ENABLE (1 << 6)
  27. #define TIMER_3_CR_CLOCK (1 << 7)
  28. #define TIMER_3_CR_INT (1 << 8)
  29. +#define TIMER_1_CR_UPDOWN (1 << 9)
  30. +#define TIMER_2_CR_UPDOWN (1 << 10)
  31. +#define TIMER_3_CR_UPDOWN (1 << 11)
  32. +
  33. +#define TIMER_1_INT_MATCH1 (1 << 0)
  34. +#define TIMER_1_INT_MATCH2 (1 << 1)
  35. +#define TIMER_1_INT_OVERFLOW (1 << 2)
  36. +#define TIMER_2_INT_MATCH1 (1 << 3)
  37. +#define TIMER_2_INT_MATCH2 (1 << 4)
  38. +#define TIMER_2_INT_OVERFLOW (1 << 5)
  39. +#define TIMER_3_INT_MATCH1 (1 << 6)
  40. +#define TIMER_3_INT_MATCH2 (1 << 7)
  41. +#define TIMER_3_INT_OVERFLOW (1 << 8)
  42. +#define TIMER_INT_ALL_MASK 0x1ff
  43. static unsigned int tick_rate;
  44. +static u64 notrace gemini_read_sched_clock(void)
  45. +{
  46. + return readl(TIMER_COUNT(GEMINI_TIMER3_BASE));
  47. +}
  48. +
  49. static int gemini_timer_set_next_event(unsigned long cycles,
  50. struct clock_event_device *evt)
  51. {
  52. u32 cr;
  53. - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  54. -
  55. - /* This may be overdoing it, feel free to test without this */
  56. - cr &= ~TIMER_2_CR_ENABLE;
  57. - cr &= ~TIMER_2_CR_INT;
  58. - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  59. -
  60. - /* Set next event */
  61. - writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
  62. - writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
  63. - cr |= TIMER_2_CR_ENABLE;
  64. - cr |= TIMER_2_CR_INT;
  65. - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  66. + /* Setup the match register */
  67. + cr = readl(TIMER_COUNT(GEMINI_TIMER1_BASE));
  68. + writel(cr + cycles, TIMER_MATCH1(GEMINI_TIMER1_BASE));
  69. + if (readl(TIMER_COUNT(GEMINI_TIMER1_BASE)) - cr > cycles)
  70. + return -ETIME;
  71. return 0;
  72. }
  73. @@ -66,48 +80,68 @@ static void gemini_timer_set_mode(enum c
  74. u32 cr;
  75. switch (mode) {
  76. - case CLOCK_EVT_MODE_PERIODIC:
  77. - /* Start the timer */
  78. - writel(period,
  79. - TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
  80. - writel(period,
  81. - TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
  82. - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  83. - cr |= TIMER_2_CR_ENABLE;
  84. - cr |= TIMER_2_CR_INT;
  85. - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  86. + case CLOCK_EVT_MODE_PERIODIC:
  87. + /* Stop timer and interrupt. */
  88. + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
  89. + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
  90. + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
  91. +
  92. + /* Setup timer to fire at 1/HZ intervals. */
  93. + cr = 0xffffffff - (period - 1);
  94. + writel(cr, TIMER_COUNT(GEMINI_TIMER1_BASE));
  95. + writel(cr, TIMER_LOAD(GEMINI_TIMER1_BASE));
  96. +
  97. + /* enable interrupt on overflaw */
  98. + cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
  99. + cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
  100. + cr |= TIMER_1_INT_OVERFLOW;
  101. + writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
  102. +
  103. + /* start the timer */
  104. + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
  105. + cr |= TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
  106. + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
  107. break;
  108. +
  109. case CLOCK_EVT_MODE_ONESHOT:
  110. case CLOCK_EVT_MODE_UNUSED:
  111. - case CLOCK_EVT_MODE_SHUTDOWN:
  112. + case CLOCK_EVT_MODE_SHUTDOWN:
  113. + /* Stop timer and interrupt. */
  114. + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
  115. + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
  116. + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
  117. +
  118. + /* Setup counter start from 0 */
  119. + writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
  120. + writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
  121. +
  122. + /* enable interrupt */
  123. + cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
  124. + cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
  125. + cr |= TIMER_1_INT_MATCH1;
  126. + writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
  127. +
  128. + /* start the timer */
  129. + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
  130. + cr |= TIMER_1_CR_ENABLE;
  131. + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
  132. + break;
  133. +
  134. case CLOCK_EVT_MODE_RESUME:
  135. - /*
  136. - * Disable also for oneshot: the set_next() call will
  137. - * arm the timer instead.
  138. - */
  139. - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  140. - cr &= ~TIMER_2_CR_ENABLE;
  141. - cr &= ~TIMER_2_CR_INT;
  142. - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  143. break;
  144. - default:
  145. - break;
  146. }
  147. }
  148. -/* Use TIMER2 as clock event */
  149. static struct clock_event_device gemini_clockevent = {
  150. - .name = "TIMER2",
  151. - .rating = 300, /* Reasonably fast and accurate clock event */
  152. - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  153. - .set_next_event = gemini_timer_set_next_event,
  154. - .set_mode = gemini_timer_set_mode,
  155. + .name = "gemini_timer_1",
  156. + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  157. + .shift = 32,
  158. + .rating = 300,
  159. + .set_next_event = gemini_timer_set_next_event,
  160. + .set_mode = gemini_timer_set_mode,
  161. };
  162. -/*
  163. - * IRQ handler for the timer
  164. - */
  165. -static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
  166. +static irqreturn_t gemini_timer_intr(int irq, void *dev_id)
  167. {
  168. struct clock_event_device *evt = &gemini_clockevent;
  169. @@ -116,14 +150,11 @@ static irqreturn_t gemini_timer_interrup
  170. }
  171. static struct irqaction gemini_timer_irq = {
  172. - .name = "Gemini Timer Tick",
  173. - .flags = IRQF_TIMER,
  174. - .handler = gemini_timer_interrupt,
  175. + .name = "gemini timer 1",
  176. + .flags = IRQF_DISABLED | IRQF_TIMER,
  177. + .handler = gemini_timer_intr,
  178. };
  179. -/*
  180. - * Set up timer interrupt, and return the current time in seconds.
  181. - */
  182. void __init gemini_timer_init(void)
  183. {
  184. u32 reg_v;
  185. @@ -151,20 +182,35 @@ void __init gemini_timer_init(void)
  186. }
  187. /*
  188. - * Make irqs happen for the system timer
  189. + * Reset the interrupt mask and status
  190. */
  191. - setup_irq(IRQ_TIMER2, &gemini_timer_irq);
  192. + writel(TIMER_INT_ALL_MASK, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
  193. + writel(0, TIMER_INTR_STATE(GEMINI_TIMER_BASE));
  194. + writel(TIMER_1_CR_UPDOWN | TIMER_3_CR_ENABLE | TIMER_3_CR_UPDOWN,
  195. + TIMER_CR(GEMINI_TIMER_BASE));
  196. - /* Enable and use TIMER1 as clock source */
  197. - writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
  198. - writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
  199. - writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
  200. - if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
  201. - "TIMER1", tick_rate, 300, 32,
  202. - clocksource_mmio_readl_up))
  203. - pr_err("timer: failed to initialize gemini clock source\n");
  204. + /*
  205. + * Setup free-running clocksource timer (interrupts
  206. + * disabled.)
  207. + */
  208. + writel(0, TIMER_COUNT(GEMINI_TIMER3_BASE));
  209. + writel(0, TIMER_LOAD(GEMINI_TIMER3_BASE));
  210. + writel(0, TIMER_MATCH1(GEMINI_TIMER3_BASE));
  211. + writel(0, TIMER_MATCH2(GEMINI_TIMER3_BASE));
  212. + clocksource_mmio_init(TIMER_COUNT(GEMINI_TIMER3_BASE),
  213. + "gemini_clocksource", tick_rate,
  214. + 300, 32, clocksource_mmio_readl_up);
  215. + sched_clock_register(gemini_read_sched_clock, 32, tick_rate);
  216. - /* Configure and register the clockevent */
  217. + /*
  218. + * Setup clockevent timer (interrupt-driven.)
  219. + */
  220. + writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
  221. + writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
  222. + writel(0, TIMER_MATCH1(GEMINI_TIMER1_BASE));
  223. + writel(0, TIMER_MATCH2(GEMINI_TIMER1_BASE));
  224. + setup_irq(IRQ_TIMER1, &gemini_timer_irq);
  225. + gemini_clockevent.cpumask = cpumask_of(0);
  226. clockevents_config_and_register(&gemini_clockevent, tick_rate,
  227. 1, 0xffffffff);
  228. }