timer_pit.c 4.8 KB

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