time.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * linux/arch/arm/mach-imx/time.c
  3. *
  4. * Copyright (C) 2000-2001 Deep Blue Solutions
  5. * Copyright (C) 2002 Shane Nay (shane@minirl.com)
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/sched.h>
  13. #include <linux/init.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/time.h>
  17. #include <linux/clocksource.h>
  18. #include <asm/hardware.h>
  19. #include <asm/io.h>
  20. #include <asm/leds.h>
  21. #include <asm/irq.h>
  22. #include <asm/mach/time.h>
  23. /* Use timer 1 as system timer */
  24. #define TIMER_BASE IMX_TIM1_BASE
  25. static unsigned long evt_diff;
  26. /*
  27. * IRQ handler for the timer
  28. */
  29. static irqreturn_t
  30. imx_timer_interrupt(int irq, void *dev_id)
  31. {
  32. uint32_t tstat;
  33. /* clear the interrupt */
  34. tstat = IMX_TSTAT(TIMER_BASE);
  35. IMX_TSTAT(TIMER_BASE) = 0;
  36. if (tstat & TSTAT_COMP) {
  37. do {
  38. write_seqlock(&xtime_lock);
  39. timer_tick();
  40. write_sequnlock(&xtime_lock);
  41. IMX_TCMP(TIMER_BASE) += evt_diff;
  42. } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
  43. - IMX_TCN(TIMER_BASE)) < 0));
  44. }
  45. return IRQ_HANDLED;
  46. }
  47. static struct irqaction imx_timer_irq = {
  48. .name = "i.MX Timer Tick",
  49. .flags = IRQF_DISABLED | IRQF_TIMER,
  50. .handler = imx_timer_interrupt,
  51. };
  52. /*
  53. * Set up timer hardware into expected mode and state.
  54. */
  55. static void __init imx_timer_hardware_init(void)
  56. {
  57. /*
  58. * Initialise to a known state (all timers off, and timing reset)
  59. */
  60. IMX_TCTL(TIMER_BASE) = 0;
  61. IMX_TPRER(TIMER_BASE) = 0;
  62. IMX_TCMP(TIMER_BASE) = LATCH - 1;
  63. IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
  64. evt_diff = LATCH;
  65. }
  66. cycle_t imx_get_cycles(void)
  67. {
  68. return IMX_TCN(TIMER_BASE);
  69. }
  70. static struct clocksource clocksource_imx = {
  71. .name = "imx_timer1",
  72. .rating = 200,
  73. .read = imx_get_cycles,
  74. .mask = 0xFFFFFFFF,
  75. .shift = 20,
  76. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  77. };
  78. static int __init imx_clocksource_init(void)
  79. {
  80. clocksource_imx.mult =
  81. clocksource_hz2mult(imx_get_perclk1(), clocksource_imx.shift);
  82. clocksource_register(&clocksource_imx);
  83. return 0;
  84. }
  85. static void __init imx_timer_init(void)
  86. {
  87. imx_timer_hardware_init();
  88. imx_clocksource_init();
  89. /*
  90. * Make irqs happen for the system timer
  91. */
  92. setup_irq(TIM1_INT, &imx_timer_irq);
  93. }
  94. struct sys_timer imx_timer = {
  95. .init = imx_timer_init,
  96. };