timer.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* A couple of routines to implement a low-overhead timer for drivers */
  2. /*
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU General Public License as
  5. * published by the Free Software Foundation; either version 2, or (at
  6. * your option) any later version.
  7. */
  8. #include "etherboot.h"
  9. #include "timer.h"
  10. void load_timer2(unsigned int ticks)
  11. {
  12. /* Set up the timer gate, turn off the speaker */
  13. outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
  14. outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
  15. outb(ticks & 0xFF, TIMER2_PORT);
  16. outb(ticks >> 8, TIMER2_PORT);
  17. }
  18. #if defined(CONFIG_TSC_CURRTICKS)
  19. #define rdtsc(low,high) \
  20. __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
  21. #define rdtscll(val) \
  22. __asm__ __volatile__ ("rdtsc" : "=A" (val))
  23. #define HZ TICKS_PER_SEC
  24. #define CLOCK_TICK_RATE 1193180U /* Underlying HZ */
  25. /* LATCH is used in the interval timer and ftape setup. */
  26. #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
  27. /* ------ Calibrate the TSC -------
  28. * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
  29. * Too much 64-bit arithmetic here to do this cleanly in C, and for
  30. * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
  31. * output busy loop as low as possible. We avoid reading the CTC registers
  32. * directly because of the awkward 8-bit access mechanism of the 82C54
  33. * device.
  34. */
  35. #define CALIBRATE_LATCH (5 * LATCH)
  36. static unsigned long long calibrate_tsc(void)
  37. {
  38. /* Set the Gate high, disable speaker */
  39. outb((inb(0x61) & ~0x02) | 0x01, 0x61);
  40. /*
  41. * Now let's take care of CTC channel 2
  42. *
  43. * Set the Gate high, program CTC channel 2 for mode 0,
  44. * (interrupt on terminal count mode), binary count,
  45. * load 5 * LATCH count, (LSB and MSB) to begin countdown.
  46. */
  47. outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
  48. outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
  49. outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
  50. {
  51. unsigned long startlow, starthigh;
  52. unsigned long endlow, endhigh;
  53. unsigned long count;
  54. rdtsc(startlow,starthigh);
  55. count = 0;
  56. do {
  57. count++;
  58. } while ((inb(0x61) & 0x20) == 0);
  59. rdtsc(endlow,endhigh);
  60. /* Error: ECTCNEVERSET */
  61. if (count <= 1)
  62. goto bad_ctc;
  63. /* 64-bit subtract - gcc just messes up with long longs */
  64. __asm__("subl %2,%0\n\t"
  65. "sbbl %3,%1"
  66. :"=a" (endlow), "=d" (endhigh)
  67. :"g" (startlow), "g" (starthigh),
  68. "0" (endlow), "1" (endhigh));
  69. /* Error: ECPUTOOFAST */
  70. if (endhigh)
  71. goto bad_ctc;
  72. endlow /= 5;
  73. return endlow;
  74. }
  75. /*
  76. * The CTC wasn't reliable: we got a hit on the very first read,
  77. * or the CPU was so fast/slow that the quotient wouldn't fit in
  78. * 32 bits..
  79. */
  80. bad_ctc:
  81. printf("bad_ctc\n");
  82. return 0;
  83. }
  84. unsigned long currticks(void)
  85. {
  86. static unsigned long clocks_per_tick;
  87. unsigned long clocks_high, clocks_low;
  88. unsigned long currticks;
  89. if (!clocks_per_tick) {
  90. clocks_per_tick = calibrate_tsc();
  91. printf("clocks_per_tick = %d\n", clocks_per_tick);
  92. }
  93. /* Read the Time Stamp Counter */
  94. rdtsc(clocks_low, clocks_high);
  95. /* currticks = clocks / clocks_per_tick; */
  96. __asm__("divl %1"
  97. :"=a" (currticks)
  98. :"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
  99. return currticks;
  100. }
  101. #endif /* RTC_CURRTICKS */