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