timer_pit.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * This code largely moved from arch/i386/kernel/time.c.
  3. * See comments there for proper credits.
  4. */
  5. #include <linux/spinlock.h>
  6. #include <linux/module.h>
  7. #include <linux/device.h>
  8. #include <linux/sysdev.h>
  9. #include <linux/timex.h>
  10. #include <asm/delay.h>
  11. #include <asm/mpspec.h>
  12. #include <asm/timer.h>
  13. #include <asm/smp.h>
  14. #include <asm/io.h>
  15. #include <asm/arch_hooks.h>
  16. #include <asm/i8253.h>
  17. #include "do_timer.h"
  18. #include "io_ports.h"
  19. static int count_p; /* counter in get_offset_pit() */
  20. static int __init init_pit(char* override)
  21. {
  22. /* check clock override */
  23. if (override[0] && strncmp(override,"pit",3))
  24. printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n");
  25. count_p = LATCH;
  26. return 0;
  27. }
  28. static void mark_offset_pit(void)
  29. {
  30. /* nothing needed */
  31. }
  32. static unsigned long long monotonic_clock_pit(void)
  33. {
  34. return 0;
  35. }
  36. static void delay_pit(unsigned long loops)
  37. {
  38. int d0;
  39. __asm__ __volatile__(
  40. "\tjmp 1f\n"
  41. ".align 16\n"
  42. "1:\tjmp 2f\n"
  43. ".align 16\n"
  44. "2:\tdecl %0\n\tjns 2b"
  45. :"=&a" (d0)
  46. :"0" (loops));
  47. }
  48. /* This function must be called with xtime_lock held.
  49. * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
  50. *
  51. * However, the pc-audio speaker driver changes the divisor so that
  52. * it gets interrupted rather more often - it loads 64 into the
  53. * counter rather than 11932! This has an adverse impact on
  54. * do_gettimeoffset() -- it stops working! What is also not
  55. * good is that the interval that our timer function gets called
  56. * is no longer 10.0002 ms, but 9.9767 ms. To get around this
  57. * would require using a different timing source. Maybe someone
  58. * could use the RTC - I know that this can interrupt at frequencies
  59. * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
  60. * it so that at startup, the timer code in sched.c would select
  61. * using either the RTC or the 8253 timer. The decision would be
  62. * based on whether there was any other device around that needed
  63. * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
  64. * and then do some jiggery to have a version of do_timer that
  65. * advanced the clock by 1/1024 s. Every time that reached over 1/100
  66. * of a second, then do all the old code. If the time was kept correct
  67. * then do_gettimeoffset could just return 0 - there is no low order
  68. * divider that can be accessed.
  69. *
  70. * Ideally, you would be able to use the RTC for the speaker driver,
  71. * but it appears that the speaker driver really needs interrupt more
  72. * often than every 120 us or so.
  73. *
  74. * Anyway, this needs more thought.... pjsg (1993-08-28)
  75. *
  76. * If you are really that interested, you should be reading
  77. * comp.protocols.time.ntp!
  78. */
  79. static unsigned long get_offset_pit(void)
  80. {
  81. int count;
  82. unsigned long flags;
  83. static unsigned long jiffies_p = 0;
  84. /*
  85. * cache volatile jiffies temporarily; we have xtime_lock.
  86. */
  87. unsigned long jiffies_t;
  88. spin_lock_irqsave(&i8253_lock, flags);
  89. /* timer count may underflow right here */
  90. outb_p(0x00, PIT_MODE); /* latch the count ASAP */
  91. count = inb_p(PIT_CH0); /* read the latched count */
  92. /*
  93. * We do this guaranteed double memory access instead of a _p
  94. * postfix in the previous port access. Wheee, hackady hack
  95. */
  96. jiffies_t = jiffies;
  97. count |= inb_p(PIT_CH0) << 8;
  98. /* VIA686a test code... reset the latch if count > max + 1 */
  99. if (count > LATCH) {
  100. outb_p(0x34, PIT_MODE);
  101. outb_p(LATCH & 0xff, PIT_CH0);
  102. outb(LATCH >> 8, PIT_CH0);
  103. count = LATCH - 1;
  104. }
  105. /*
  106. * avoiding timer inconsistencies (they are rare, but they happen)...
  107. * there are two kinds of problems that must be avoided here:
  108. * 1. the timer counter underflows
  109. * 2. hardware problem with the timer, not giving us continuous time,
  110. * the counter does small "jumps" upwards on some Pentium systems,
  111. * (see c't 95/10 page 335 for Neptun bug.)
  112. */
  113. if( jiffies_t == jiffies_p ) {
  114. if( count > count_p ) {
  115. /* the nutcase */
  116. count = do_timer_overflow(count);
  117. }
  118. } else
  119. jiffies_p = jiffies_t;
  120. count_p = count;
  121. spin_unlock_irqrestore(&i8253_lock, flags);
  122. count = ((LATCH-1) - count) * TICK_SIZE;
  123. count = (count + LATCH/2) / LATCH;
  124. return count;
  125. }
  126. /* tsc timer_opts struct */
  127. struct timer_opts timer_pit = {
  128. .name = "pit",
  129. .mark_offset = mark_offset_pit,
  130. .get_offset = get_offset_pit,
  131. .monotonic_clock = monotonic_clock_pit,
  132. .delay = delay_pit,
  133. };
  134. struct init_timer_opts __initdata timer_pit_init = {
  135. .init = init_pit,
  136. .opts = &timer_pit,
  137. };
  138. void setup_pit_timer(void)
  139. {
  140. unsigned long flags;
  141. spin_lock_irqsave(&i8253_lock, flags);
  142. outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
  143. udelay(10);
  144. outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
  145. udelay(10);
  146. outb(LATCH >> 8 , PIT_CH0); /* MSB */
  147. spin_unlock_irqrestore(&i8253_lock, flags);
  148. }