time.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. if (__raw_readl(MXC_GPT_GPTSR) & GPTSR_OF1) {
  44. do {
  45. timer_tick();
  46. next_match = __raw_readl(MXC_GPT_GPTOCR1) + LATCH;
  47. __raw_writel(GPTSR_OF1, MXC_GPT_GPTSR);
  48. __raw_writel(next_match, MXC_GPT_GPTOCR1);
  49. } while ((signed long)(next_match -
  50. __raw_readl(MXC_GPT_GPTCNT)) <= 0);
  51. }
  52. return IRQ_HANDLED;
  53. }
  54. /*!
  55. * This function is used to obtain the number of microseconds since the last
  56. * timer interrupt. Note that interrupts is disabled by do_gettimeofday().
  57. *
  58. * @return the number of microseconds since the last timer interrupt.
  59. */
  60. static unsigned long mxc_gettimeoffset(void)
  61. {
  62. unsigned long ticks_to_match, elapsed, usec, tick_usec, i;
  63. /* Get ticks before next timer match */
  64. ticks_to_match =
  65. __raw_readl(MXC_GPT_GPTOCR1) - __raw_readl(MXC_GPT_GPTCNT);
  66. /* We need elapsed ticks since last match */
  67. elapsed = LATCH - ticks_to_match;
  68. /* Now convert them to usec */
  69. /* Insure no overflow when calculating the usec below */
  70. for (i = 1, tick_usec = tick_nsec / 1000;; i *= 2) {
  71. tick_usec /= i;
  72. if ((0xFFFFFFFF / tick_usec) > elapsed)
  73. break;
  74. }
  75. usec = (unsigned long)(elapsed * tick_usec) / (LATCH / i);
  76. return usec;
  77. }
  78. /*!
  79. * The OS tick timer interrupt structure.
  80. */
  81. static struct irqaction timer_irq = {
  82. .name = "MXC Timer Tick",
  83. .flags = IRQF_DISABLED | IRQF_TIMER,
  84. .handler = mxc_timer_interrupt
  85. };
  86. /*!
  87. * This function is used to initialize the GPT to produce an interrupt
  88. * based on HZ. It is called by start_kernel() during system startup.
  89. */
  90. void __init mxc_init_time(void)
  91. {
  92. u32 reg, v;
  93. reg = __raw_readl(MXC_GPT_GPTCR);
  94. reg &= ~GPTCR_ENABLE;
  95. __raw_writel(reg, MXC_GPT_GPTCR);
  96. reg |= GPTCR_SWR;
  97. __raw_writel(reg, MXC_GPT_GPTCR);
  98. while ((__raw_readl(MXC_GPT_GPTCR) & GPTCR_SWR) != 0)
  99. cpu_relax();
  100. reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ;
  101. __raw_writel(reg, MXC_GPT_GPTCR);
  102. /* TODO: get timer rate from clk driver */
  103. v = 66500000;
  104. __raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_GPTPR);
  105. if ((v % CLOCK_TICK_RATE) != 0) {
  106. pr_info("\nWARNING: Can't generate CLOCK_TICK_RATE at %d Hz\n",
  107. CLOCK_TICK_RATE);
  108. }
  109. pr_info("Actual CLOCK_TICK_RATE is %d Hz\n",
  110. v / ((__raw_readl(MXC_GPT_GPTPR) & 0xFFF) + 1));
  111. reg = __raw_readl(MXC_GPT_GPTCNT);
  112. reg += LATCH;
  113. __raw_writel(reg, MXC_GPT_GPTOCR1);
  114. setup_irq(MXC_INT_GPT, &timer_irq);
  115. reg = __raw_readl(MXC_GPT_GPTCR);
  116. reg =
  117. GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_STOPEN | GPTCR_DOZEN |
  118. GPTCR_WAITEN | GPTCR_ENMOD | GPTCR_ENABLE;
  119. __raw_writel(reg, MXC_GPT_GPTCR);
  120. __raw_writel(GPTIR_OF1IE, MXC_GPT_GPTIR);
  121. }
  122. struct sys_timer mxc_timer = {
  123. .init = mxc_init_time,
  124. .offset = mxc_gettimeoffset,
  125. };