You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

i386_timer.c 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #include "latch.h"
  11. void __load_timer2(unsigned int ticks)
  12. {
  13. /*
  14. * Now let's take care of PPC channel 2
  15. *
  16. * Set the Gate high, program PPC channel 2 for mode 0,
  17. * (interrupt on terminal count mode), binary count,
  18. * load 5 * LATCH count, (LSB and MSB) to begin countdown.
  19. *
  20. * Note some implementations have a bug where the high bits byte
  21. * of channel 2 is ignored.
  22. */
  23. /* Set up the timer gate, turn off the speaker */
  24. /* Set the Gate high, disable speaker */
  25. outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
  26. /* binary, mode 0, LSB/MSB, Ch 2 */
  27. outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
  28. /* LSB of ticks */
  29. outb(ticks & 0xFF, TIMER2_PORT);
  30. /* MSB of ticks */
  31. outb(ticks >> 8, TIMER2_PORT);
  32. }
  33. static int __timer2_running(void)
  34. {
  35. return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
  36. }
  37. #if !defined(CONFIG_TSC_CURRTICKS)
  38. void setup_timers(void)
  39. {
  40. return;
  41. }
  42. void load_timer2(unsigned int ticks)
  43. {
  44. return __load_timer2(ticks);
  45. }
  46. int timer2_running(void)
  47. {
  48. return __timer2_running();
  49. }
  50. void ndelay(unsigned int nsecs)
  51. {
  52. waiton_timer2((nsecs * CLOCK_TICK_RATE)/1000000000);
  53. }
  54. void udelay(unsigned int usecs)
  55. {
  56. waiton_timer2((usecs * TICKS_PER_MS)/1000);
  57. }
  58. #endif /* !defined(CONFIG_TSC_CURRTICKS) */
  59. #if defined(CONFIG_TSC_CURRTICKS)
  60. #define rdtsc(low,high) \
  61. __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
  62. #define rdtscll(val) \
  63. __asm__ __volatile__ ("rdtsc" : "=A" (val))
  64. /* Number of clock ticks to time with the rtc */
  65. #define LATCH 0xFF
  66. #define LATCHES_PER_SEC ((CLOCK_TICK_RATE + (LATCH/2))/LATCH)
  67. #define TICKS_PER_LATCH ((LATCHES_PER_SEC + (TICKS_PER_SEC/2))/TICKS_PER_SEC)
  68. static void sleep_latch(void)
  69. {
  70. __load_timer2(LATCH);
  71. while(__timer2_running());
  72. }
  73. /* ------ Calibrate the TSC -------
  74. * Time how long it takes to excute a loop that runs in known time.
  75. * And find the convertion needed to get to CLOCK_TICK_RATE
  76. */
  77. static unsigned long long calibrate_tsc(void)
  78. {
  79. unsigned long startlow, starthigh;
  80. unsigned long endlow, endhigh;
  81. rdtsc(startlow,starthigh);
  82. sleep_latch();
  83. rdtsc(endlow,endhigh);
  84. /* 64-bit subtract - gcc just messes up with long longs */
  85. __asm__("subl %2,%0\n\t"
  86. "sbbl %3,%1"
  87. :"=a" (endlow), "=d" (endhigh)
  88. :"g" (startlow), "g" (starthigh),
  89. "0" (endlow), "1" (endhigh));
  90. /* Error: ECPUTOOFAST */
  91. if (endhigh)
  92. goto bad_ctc;
  93. endlow *= TICKS_PER_LATCH;
  94. return endlow;
  95. /*
  96. * The CTC wasn't reliable: we got a hit on the very first read,
  97. * or the CPU was so fast/slow that the quotient wouldn't fit in
  98. * 32 bits..
  99. */
  100. bad_ctc:
  101. printf("bad_ctc\n");
  102. return 0;
  103. }
  104. static unsigned long clocks_per_tick;
  105. void setup_timers(void)
  106. {
  107. if (!clocks_per_tick) {
  108. clocks_per_tick = calibrate_tsc();
  109. /* Display the CPU Mhz to easily test if the calibration was bad */
  110. printf("CPU %ld Mhz\n", (clocks_per_tick/1000 * TICKS_PER_SEC)/1000);
  111. }
  112. }
  113. unsigned long currticks(void)
  114. {
  115. unsigned long clocks_high, clocks_low;
  116. unsigned long currticks;
  117. /* Read the Time Stamp Counter */
  118. rdtsc(clocks_low, clocks_high);
  119. /* currticks = clocks / clocks_per_tick; */
  120. __asm__("divl %1"
  121. :"=a" (currticks)
  122. :"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
  123. return currticks;
  124. }
  125. static unsigned long long timer_timeout;
  126. static int __timer_running(void)
  127. {
  128. unsigned long long now;
  129. rdtscll(now);
  130. return now < timer_timeout;
  131. }
  132. void udelay(unsigned int usecs)
  133. {
  134. unsigned long long now;
  135. rdtscll(now);
  136. timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
  137. while(__timer_running());
  138. }
  139. void ndelay(unsigned int nsecs)
  140. {
  141. unsigned long long now;
  142. rdtscll(now);
  143. timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
  144. while(__timer_running());
  145. }
  146. void load_timer2(unsigned int timer2_ticks)
  147. {
  148. unsigned long long now;
  149. unsigned long clocks;
  150. rdtscll(now);
  151. clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
  152. timer_timeout = now + clocks;
  153. }
  154. int timer2_running(void)
  155. {
  156. return __timer_running();
  157. }
  158. #endif /* RTC_CURRTICKS */