time.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * System Timer Interrupt reconfigured to run in free-run mode.
  3. * Author: Vitaly Wool
  4. * Copyright 2004 MontaVista Software Inc.
  5. * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  6. */
  7. /*
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. /*!
  13. * @file time.c
  14. * @brief This file contains OS tick and wdog timer implementations.
  15. *
  16. * This file contains OS tick and wdog timer implementations.
  17. *
  18. * @ingroup Timers
  19. */
  20. #include <linux/module.h>
  21. #include <linux/init.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/irq.h>
  24. #include <asm/hardware.h>
  25. #include <asm/mach/time.h>
  26. #include <asm/io.h>
  27. #include <asm/arch/common.h>
  28. /*!
  29. * This is the timer interrupt service routine to do required tasks.
  30. * It also services the WDOG timer at the frequency of twice per WDOG
  31. * timeout value. For example, if the WDOG's timeout value is 4 (2
  32. * seconds since the WDOG runs at 0.5Hz), it will be serviced once
  33. * every 2/2=1 second.
  34. *
  35. * @param irq GPT interrupt source number (not used)
  36. * @param dev_id this parameter is not used
  37. * @return always returns \b IRQ_HANDLED as defined in
  38. * include/linux/interrupt.h.
  39. */
  40. static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
  41. {
  42. unsigned int next_match;
  43. write_seqlock(&xtime_lock);
  44. if (__raw_readl(MXC_GPT_GPTSR) & GPTSR_OF1) {
  45. do {
  46. timer_tick();
  47. next_match = __raw_readl(MXC_GPT_GPTOCR1) + LATCH;
  48. __raw_writel(GPTSR_OF1, MXC_GPT_GPTSR);
  49. __raw_writel(next_match, MXC_GPT_GPTOCR1);
  50. } while ((signed long)(next_match -
  51. __raw_readl(MXC_GPT_GPTCNT)) <= 0);
  52. }
  53. write_sequnlock(&xtime_lock);
  54. return IRQ_HANDLED;
  55. }
  56. /*!
  57. * This function is used to obtain the number of microseconds since the last
  58. * timer interrupt. Note that interrupts is disabled by do_gettimeofday().
  59. *
  60. * @return the number of microseconds since the last timer interrupt.
  61. */
  62. static unsigned long mxc_gettimeoffset(void)
  63. {
  64. unsigned long ticks_to_match, elapsed, usec, tick_usec, i;
  65. /* Get ticks before next timer match */
  66. ticks_to_match =
  67. __raw_readl(MXC_GPT_GPTOCR1) - __raw_readl(MXC_GPT_GPTCNT);
  68. /* We need elapsed ticks since last match */
  69. elapsed = LATCH - ticks_to_match;
  70. /* Now convert them to usec */
  71. /* Insure no overflow when calculating the usec below */
  72. for (i = 1, tick_usec = tick_nsec / 1000;; i *= 2) {
  73. tick_usec /= i;
  74. if ((0xFFFFFFFF / tick_usec) > elapsed)
  75. break;
  76. }
  77. usec = (unsigned long)(elapsed * tick_usec) / (LATCH / i);
  78. return usec;
  79. }
  80. /*!
  81. * The OS tick timer interrupt structure.
  82. */
  83. static struct irqaction timer_irq = {
  84. .name = "MXC Timer Tick",
  85. .flags = IRQF_DISABLED | IRQF_TIMER,
  86. .handler = mxc_timer_interrupt
  87. };
  88. /*!
  89. * This function is used to initialize the GPT to produce an interrupt
  90. * based on HZ. It is called by start_kernel() during system startup.
  91. */
  92. void __init mxc_init_time(void)
  93. {
  94. u32 reg, v;
  95. reg = __raw_readl(MXC_GPT_GPTCR);
  96. reg &= ~GPTCR_ENABLE;
  97. __raw_writel(reg, MXC_GPT_GPTCR);
  98. reg |= GPTCR_SWR;
  99. __raw_writel(reg, MXC_GPT_GPTCR);
  100. while ((__raw_readl(MXC_GPT_GPTCR) & GPTCR_SWR) != 0)
  101. cpu_relax();
  102. reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ;
  103. __raw_writel(reg, MXC_GPT_GPTCR);
  104. /* TODO: get timer rate from clk driver */
  105. v = 66500000;
  106. __raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_GPTPR);
  107. if ((v % CLOCK_TICK_RATE) != 0) {
  108. pr_info("\nWARNING: Can't generate CLOCK_TICK_RATE at %d Hz\n",
  109. CLOCK_TICK_RATE);
  110. }
  111. pr_info("Actual CLOCK_TICK_RATE is %d Hz\n",
  112. v / ((__raw_readl(MXC_GPT_GPTPR) & 0xFFF) + 1));
  113. reg = __raw_readl(MXC_GPT_GPTCNT);
  114. reg += LATCH;
  115. __raw_writel(reg, MXC_GPT_GPTOCR1);
  116. setup_irq(MXC_INT_GPT, &timer_irq);
  117. reg = __raw_readl(MXC_GPT_GPTCR);
  118. reg =
  119. GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_STOPEN | GPTCR_DOZEN |
  120. GPTCR_WAITEN | GPTCR_ENMOD | GPTCR_ENABLE;
  121. __raw_writel(reg, MXC_GPT_GPTCR);
  122. __raw_writel(GPTIR_OF1IE, MXC_GPT_GPTIR);
  123. }
  124. struct sys_timer mxc_timer = {
  125. .init = mxc_init_time,
  126. .offset = mxc_gettimeoffset,
  127. };