clock.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * kirkwood clock
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "ureg.h"
  11. enum {
  12. Tcycles = CLOCKFREQ / HZ, /* cycles per clock tick */
  13. };
  14. static void
  15. clockintr(Ureg *ureg, void*)
  16. {
  17. m->fastclock++;
  18. timerintr(ureg, 0);
  19. intrclear(Irqbridge, IRQcputimer0);
  20. }
  21. void
  22. clockinit(void)
  23. {
  24. int s;
  25. long cyc;
  26. TimerReg *tmr = TIMERREG;
  27. tmr->ctl = 0;
  28. coherence();
  29. intrenable(Irqbridge, IRQcputimer0, clockintr, nil, "clock");
  30. s = spllo(); /* risky */
  31. /* take any deferred clock (& other) interrupts here */
  32. splx(s);
  33. /* adjust m->bootdelay, used by delay()? */
  34. m->ticks = 0;
  35. m->fastclock = 0;
  36. tmr->timer0 = Tcycles;
  37. tmr->ctl = Tmr0enable; /* just once */
  38. coherence();
  39. s = spllo(); /* risky */
  40. /* one iteration seems to take about 40 ns. */
  41. for (cyc = Tcycles; cyc > 0 && m->fastclock == 0; cyc--)
  42. ;
  43. splx(s);
  44. if (m->fastclock == 0) {
  45. serialputc('?');
  46. if (tmr->timer0 == 0)
  47. panic("clock not interrupting");
  48. else if (tmr->timer0 == tmr->reload0)
  49. panic("clock not ticking");
  50. else
  51. panic("clock running very slowly");
  52. }
  53. tmr->ctl = 0;
  54. coherence();
  55. tmr->timer0 = Tcycles;
  56. tmr->reload0 = Tcycles;
  57. tmr->ctl = Tmr0enable | Tmr0periodic;
  58. coherence();
  59. }
  60. void
  61. timerset(uvlong next)
  62. {
  63. #ifdef FANCYTIMERS
  64. Tn *tn;
  65. Tval offset;
  66. ilock(&timers.tn1lock);
  67. tn = (Tn*)Tn1;
  68. tn->cr = Tm;
  69. offset = next + tn->cv;
  70. if(offset < timers.tn1minperiod)
  71. offset = timers.tn1minperiod;
  72. else if(offset > timers.tn1maxperiod)
  73. offset = timers.tn1maxperiod;
  74. tn->lc = offset;
  75. tn->cr = Tm|Te;
  76. iunlock(&timers.tn1lock);
  77. #else
  78. USED(next);
  79. #endif
  80. }
  81. uvlong
  82. fastticks(uvlong *hz)
  83. {
  84. if(hz)
  85. *hz = HZ;
  86. return m->fastclock;
  87. }
  88. ulong
  89. µs(void)
  90. {
  91. return fastticks2us(fastticks(nil));
  92. }
  93. void
  94. microdelay(int l)
  95. {
  96. int i;
  97. l *= m->delayloop;
  98. l /= 1000;
  99. if(l <= 0)
  100. l = 1;
  101. for(i = 0; i < l; i++)
  102. ;
  103. }
  104. void
  105. delay(int l)
  106. {
  107. ulong i, j;
  108. j = m->delayloop;
  109. while(l-- > 0)
  110. for(i=0; i < j; i++)
  111. ;
  112. }
  113. ulong
  114. perfticks(void)
  115. {
  116. // return ((Tn*)Tn0)->cv; // TODO: FANCYTIMERS
  117. return (ulong)fastticks(nil);
  118. }