time.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:2k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/mach-ebsa110/time.c
  3.  *
  4.  *  Copyright (C) 2001 Russell King
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  */
  10. #include <linux/sched.h>
  11. #include <linux/init.h>
  12. #include <asm/io.h>
  13. #define PIT_CTRL (PIT_BASE + 0x0d)
  14. #define PIT_T2 (PIT_BASE + 0x09)
  15. #define PIT_T1 (PIT_BASE + 0x05)
  16. #define PIT_T0 (PIT_BASE + 0x01)
  17. /*
  18.  * This is the rate at which your MCLK signal toggles (in Hz)
  19.  * This was measured on a 10 digit frequency counter sampling
  20.  * over 1 second.
  21.  */
  22. #define MCLK 47894000
  23. /*
  24.  * This is the rate at which the PIT timers get clocked
  25.  */
  26. #define CLKBY7 (MCLK / 7)
  27. /*
  28.  * If CLKBY7 is larger than this, then we must do software
  29.  * division of the timer interrupt.
  30.  */
  31. #if CLKBY7 > 6553500
  32. #define DIVISOR 2
  33. #else
  34. #define DIVISOR 1
  35. #endif
  36. /*
  37.  * This is the counter value
  38.  */
  39. #define COUNT ((CLKBY7 + (DIVISOR * HZ / 2)) / (DIVISOR * HZ))
  40. extern unsigned long (*gettimeoffset)(void);
  41. static unsigned long divisor;
  42. /*
  43.  * Get the time offset from the system PIT.  Note that if we have missed an
  44.  * interrupt, then the PIT counter will roll over (ie, be negative).
  45.  * This actually works out to be convenient.
  46.  */
  47. static unsigned long ebsa110_gettimeoffset(void)
  48. {
  49. unsigned long offset, count;
  50. __raw_writeb(0x40, PIT_CTRL);
  51. count = __raw_readb(PIT_T1);
  52. count |= __raw_readb(PIT_T1) << 8;
  53. /*
  54.  * If count > COUNT, make the number negative.
  55.  */
  56. if (count > COUNT)
  57. count |= 0xffff0000;
  58. offset = COUNT * (DIVISOR - divisor);
  59. offset -= count;
  60. /*
  61.  * `offset' is in units of timer counts.  Convert
  62.  * offset to units of microseconds.
  63.  */
  64. offset = offset * (1000000 / HZ) / (COUNT * DIVISOR);
  65. return offset;
  66. }
  67. int ebsa110_reset_timer(void)
  68. {
  69. u32 count;
  70. /* latch and read timer 1 */
  71. __raw_writeb(0x40, PIT_CTRL);
  72. count = __raw_readb(PIT_T1);
  73. count |= __raw_readb(PIT_T1) << 8;
  74. count += COUNT;
  75. __raw_writeb(count & 0xff, PIT_T1);
  76. __raw_writeb(count >> 8, PIT_T1);
  77. if (divisor == 0)
  78. divisor = DIVISOR;
  79. divisor -= 1;
  80. return divisor;
  81. }
  82. void __init ebsa110_setup_timer(void)
  83. {
  84. /*
  85.  * Timer 1, mode 2, LSB/MSB
  86.  */
  87. __raw_writeb(0x70, PIT_CTRL);
  88. __raw_writeb(COUNT & 0xff, PIT_T1);
  89. __raw_writeb(COUNT >> 8, PIT_T1);
  90. divisor = DIVISOR - 1;
  91. gettimeoffset = ebsa110_gettimeoffset;
  92. }