clock.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * omap3530 clocks
  3. *
  4. * timers count up to zero.
  5. *
  6. * the source clock signals for the timers are sometimes selectable. for
  7. * WDTIMER[23] and GPTIMER12, it's always the 32kHz clock. for the
  8. * others, it can be the 32kHz clock or the system clock. we use only
  9. * WDTIMER2 and GPTIMER[12], and configure GPTIMER[12] in archomap.c to
  10. * use the 32kHZ clock. WDTIMER1 is not accessible to us on GP
  11. * (general-purpose) omaps.
  12. */
  13. #include "u.h"
  14. #include "../port/lib.h"
  15. #include "mem.h"
  16. #include "dat.h"
  17. #include "fns.h"
  18. #include "arm.h"
  19. enum {
  20. Debug = 0,
  21. Tn0 = PHYSTIMER1,
  22. Tn1 = PHYSTIMER2,
  23. Tn0irq = 37, /* base IRQ for all timers */
  24. Freebase = 1, /* base of free-running timer */
  25. /*
  26. * clock is 32K (32,768) Hz, so one tick is 30.517µs,
  27. * so 327.68 ticks is 10ms, 32.768 tick is 1ms.
  28. */
  29. Clockfreqbase = 32 * 1024, /* base rate in Hz */
  30. Tcycles = Clockfreqbase / HZ, /* cycles per clock tick */
  31. MinPeriod = (Tcycles / 100 < 2? 2: Tcycles / 100),
  32. MaxPeriod = Tcycles,
  33. Dogtimeout = 20 * Clockfreqbase, /* was 4 s.; must be ≤ 21 s. */
  34. };
  35. enum {
  36. /* ticpcfg bits */
  37. Noidle = 1<<3,
  38. Softreset = 1<<1,
  39. /* tistat bits */
  40. Resetdone = 1<<0,
  41. /* tisr/tier bits */
  42. Ovf_it = 1<<1, /* gp: overflow intr */
  43. Mat_it = 1<<0, /* gp: match intr */
  44. Wdovf_it = 1<<0, /* wdog: overflow intr */
  45. /* tclr bits */
  46. Ar = 1<<1, /* gp only: autoreload mode overflow */
  47. St = 1<<0, /* gp only: start the timer */
  48. };
  49. /* omap35x timer registers */
  50. typedef struct Timerregs Timerregs;
  51. struct Timerregs {
  52. /* common to all timers, gp and watchdog */
  53. uchar pad0[0x10];
  54. ulong ticpcfg;
  55. ulong tistat; /* ro: low bit: reset done */
  56. ulong tisr;
  57. ulong tier;
  58. ulong twer;
  59. ulong tclr;
  60. ulong tcrr; /* counter: cycles to zero */
  61. ulong tldr;
  62. ulong ttgr; /* trigger */
  63. ulong twps; /* ro: write posted pending */
  64. /* gp timers only, unused by us */
  65. ulong tmar; /* value to compare with counter */
  66. ulong tcar1; /* ro */
  67. ulong tsicr;
  68. ulong tcar2; /* ro */
  69. union {
  70. ulong tpir; /* gp: 1 ms tick generation: +ve */
  71. ulong wspr; /* wdog: start/stop control */
  72. };
  73. ulong tnir; /* 1 ms tick generation: -ve */
  74. ulong tcvr; /* 1 ms tick generation: next counter value */
  75. ulong tocr; /* intr mask for n ticks */
  76. ulong towr;
  77. };
  78. static int ticks; /* for sanity checking; m->ticks doesn't always get called */
  79. static Lock clklck;
  80. static ulong rdcycles(void), rdbaseticks(void);
  81. /* write a watchdog timer's start/stop register */
  82. static void
  83. wdogwrss(Timerregs *tn, ulong val)
  84. {
  85. while (tn->twps & (1 << 4)) /* pending write to start/stop reg? */
  86. ;
  87. tn->wspr = val;
  88. coherence();
  89. while (tn->twps & (1 << 4)) /* pending write to start/stop reg? */
  90. ;
  91. }
  92. static void
  93. resetwait(Timerregs *tn)
  94. {
  95. long bound;
  96. for (bound = 400*1000*1000; !(tn->tistat & Resetdone) && bound > 0;
  97. bound--)
  98. ;
  99. if (bound <= 0)
  100. iprint("clock reset didn't complete\n");
  101. }
  102. static void
  103. wdogoff(Timerregs *tn)
  104. {
  105. resetwait(tn);
  106. wdogwrss(tn, 0xaaaa); /* magic off sequence */
  107. wdogwrss(tn, 0x5555);
  108. tn->tldr = 1;
  109. coherence();
  110. tn->tcrr = 1; /* paranoia */
  111. coherence();
  112. }
  113. static void wdogassure(void);
  114. static void
  115. wdogon(Timerregs *tn)
  116. {
  117. static int beenhere;
  118. resetwait(tn);
  119. tn->tldr = -Dogtimeout;
  120. tn->tcrr = -Dogtimeout;
  121. coherence();
  122. wdogwrss(tn, 0xbbbb); /* magic on sequence */
  123. wdogwrss(tn, 0x4444); /* magic on sequence */
  124. if (!beenhere) {
  125. beenhere = 1;
  126. /* touching the dog is not quick, so do it infrequently */
  127. addclock0link(wdogassure, HZ);
  128. }
  129. }
  130. static void
  131. wdogassure(void) /* reset the watch dog's counter */
  132. {
  133. Timerregs *tn;
  134. tn = (Timerregs *)PHYSWDOG;
  135. wdogoff(tn);
  136. tn->tcrr = -Dogtimeout;
  137. coherence();
  138. wdogon(tn);
  139. }
  140. static void
  141. clockintr(Ureg* ureg, void *arg)
  142. {
  143. Timerregs *tn;
  144. static int nesting;
  145. ticks++;
  146. coherence();
  147. if (nesting == 0) { /* if the clock interrupted itself, bail out */
  148. ++nesting;
  149. timerintr(ureg, 0);
  150. --nesting;
  151. }
  152. tn = arg;
  153. tn->tisr = Ovf_it; /* dismiss the interrupt */
  154. coherence();
  155. }
  156. static void
  157. clockreset(Timerregs *tn)
  158. {
  159. if (probeaddr((uintptr)&tn->ticpcfg) < 0)
  160. panic("no clock at %#p", tn);
  161. tn->ticpcfg = Softreset | Noidle;
  162. coherence();
  163. resetwait(tn);
  164. tn->tier = tn->tclr = 0;
  165. coherence();
  166. }
  167. /* stop clock interrupts and disable the watchdog timer */
  168. void
  169. clockshutdown(void)
  170. {
  171. clockreset((Timerregs *)PHYSWDT2);
  172. wdogoff((Timerregs *)PHYSWDT2);
  173. clockreset((Timerregs *)PHYSWDT3);
  174. wdogoff((Timerregs *)PHYSWDT3);
  175. clockreset((Timerregs *)Tn0);
  176. clockreset((Timerregs *)Tn1);
  177. }
  178. enum {
  179. Instrs = 10*1000*1000,
  180. };
  181. static long
  182. issue1loop(void)
  183. {
  184. register int i;
  185. long st;
  186. st = rdbaseticks();
  187. i = Instrs;
  188. do {
  189. --i; --i; --i; --i; --i;
  190. --i; --i; --i; --i;
  191. } while(--i >= 0);
  192. return rdbaseticks() - st;
  193. }
  194. static long
  195. issue2loop(void)
  196. {
  197. register int i, j;
  198. long st;
  199. st = rdbaseticks();
  200. i = Instrs / 2;
  201. j = 0;
  202. do {
  203. --i; --j; --i; --j;
  204. --i; --j; --i; --j;
  205. --j;
  206. } while(--i >= 0);
  207. return rdbaseticks() - st;
  208. }
  209. /* estimate instructions/s. using 32kHz clock */
  210. static void
  211. guessmips(long (*loop)(void), char *lab)
  212. {
  213. int s;
  214. long tcks;
  215. do {
  216. s = splhi();
  217. tcks = loop();
  218. splx(s);
  219. if (tcks < 0)
  220. iprint("again...");
  221. } while (tcks < 0);
  222. /*
  223. * Instrs instructions took tcks ticks @ Clockfreqbase Hz.
  224. */
  225. s = ((vlong)Clockfreqbase * Instrs) / tcks / 1000000;
  226. if (Debug)
  227. iprint("%ud mips (%s-issue)", s, lab);
  228. USED(s);
  229. }
  230. void
  231. clockinit(void)
  232. {
  233. int i, s;
  234. Timerregs *tn;
  235. clockshutdown();
  236. /* turn cycle counter on */
  237. cpwrsc(0, CpCLD, CpCLDena, CpCLDenacyc, 1<<31);
  238. /* turn all counters on and clear the cycle counter */
  239. cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1<<2 | 1);
  240. /* let users read the cycle counter directly */
  241. cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1);
  242. ilock(&clklck);
  243. m->fastclock = 1;
  244. m->ticks = ticks = 0;
  245. /*
  246. * T0 is a freerunning timer (cycle counter); it wraps,
  247. * automatically reloads, and does not dispatch interrupts.
  248. */
  249. tn = (Timerregs *)Tn0;
  250. tn->tcrr = Freebase; /* count up to 0 */
  251. tn->tldr = Freebase;
  252. coherence();
  253. tn->tclr = Ar | St;
  254. iunlock(&clklck);
  255. /*
  256. * T1 is the interrupting timer and does not participate
  257. * in measuring time. It is initially set to HZ.
  258. */
  259. tn = (Timerregs *)Tn1;
  260. irqenable(Tn0irq+1, clockintr, tn, "clock");
  261. ilock(&clklck);
  262. tn->tcrr = -Tcycles; /* approx.; count up to 0 */
  263. tn->tldr = -Tcycles;
  264. coherence();
  265. tn->tclr = Ar | St;
  266. coherence();
  267. tn->tier = Ovf_it;
  268. coherence();
  269. iunlock(&clklck);
  270. /*
  271. * verify sanity of timer1
  272. */
  273. s = spllo(); /* risky */
  274. for (i = 0; i < 5 && ticks == 0; i++) {
  275. delay(10);
  276. cachedwbinvse(&ticks, sizeof ticks);
  277. }
  278. splx(s);
  279. if (ticks == 0) {
  280. if (tn->tcrr == 0)
  281. panic("clock not interrupting");
  282. else if (tn->tcrr == tn->tldr)
  283. panic("clock not ticking at all");
  284. #ifdef PARANOID
  285. else
  286. panic("clock running very slowly");
  287. #endif
  288. }
  289. guessmips(issue1loop, "single");
  290. if (Debug)
  291. iprint(", ");
  292. guessmips(issue2loop, "dual");
  293. if (Debug)
  294. iprint("\n");
  295. /*
  296. * m->delayloop should be the number of delay loop iterations
  297. * needed to consume 1 ms. 2 is min. instructions in the delay loop.
  298. */
  299. m->delayloop = m->cpuhz / (1000 * 2);
  300. // iprint("m->delayloop = %lud\n", m->delayloop);
  301. /*
  302. * desynchronize the processor clocks so that they all don't
  303. * try to resched at the same time.
  304. */
  305. delay(m->machno*2);
  306. }
  307. void
  308. watchdoginit(void)
  309. {
  310. wdogassure();
  311. }
  312. ulong
  313. µs(void)
  314. {
  315. return fastticks2us(fastticks(nil));
  316. }
  317. void
  318. timerset(Tval next)
  319. {
  320. long offset;
  321. Timerregs *tn = (Timerregs *)Tn1;
  322. static Lock setlck;
  323. ilock(&setlck);
  324. offset = next - fastticks(nil);
  325. if(offset < MinPeriod)
  326. offset = MinPeriod;
  327. else if(offset > MaxPeriod)
  328. offset = MaxPeriod;
  329. tn->tcrr = -offset;
  330. coherence();
  331. iunlock(&setlck);
  332. }
  333. static ulong
  334. rdcycles(void)
  335. {
  336. ulong v;
  337. /* reads 32-bit cycle counter (counting up) */
  338. v = cprdsc(0, CpCLD, CpCLDcyc, 0);
  339. /* keep it positive; prevent m->fastclock ever going to 0 */
  340. return v == 0? 1: v;
  341. }
  342. static ulong
  343. rdbaseticks(void)
  344. {
  345. ulong v;
  346. v = ((Timerregs *)Tn0)->tcrr; /* tcrr should be counting up */
  347. /* keep it positive; prevent m->fastclock ever going to 0 */
  348. return v == 0? 1: v;
  349. }
  350. ulong
  351. perfticks(void)
  352. {
  353. return rdcycles();
  354. }
  355. long
  356. lcycles(void)
  357. {
  358. return perfticks();
  359. }
  360. /*
  361. * until 5[cal] inline vlong ops, avoid them where possible,
  362. * they are currently slow function calls.
  363. */
  364. typedef union Counter Counter;
  365. union Counter {
  366. uvlong uvl;
  367. struct { /* little-endian */
  368. ulong low;
  369. ulong high;
  370. };
  371. };
  372. enum {
  373. Fastvlongops = 0,
  374. };
  375. uvlong
  376. fastticks(uvlong *hz)
  377. {
  378. Counter now, sclnow;
  379. if(hz)
  380. *hz = m->cpuhz;
  381. ilock(&clklck);
  382. if (m->ticks > HZ/10 && m->fastclock == 0)
  383. panic("fastticks: zero m->fastclock; ticks %lud fastclock %#llux",
  384. m->ticks, m->fastclock);
  385. now.uvl = m->fastclock;
  386. now.low = rdcycles();
  387. if(now.uvl < m->fastclock) /* low bits must have wrapped */
  388. now.high++;
  389. m->fastclock = now.uvl;
  390. coherence();
  391. sclnow.uvl = now.uvl;
  392. iunlock(&clklck);
  393. return sclnow.uvl;
  394. }
  395. void
  396. microdelay(int l)
  397. {
  398. int i;
  399. l = l * (vlong)m->delayloop / 1000;
  400. if(l <= 0)
  401. l = 1;
  402. for(i = 0; i < l; i++)
  403. ;
  404. }
  405. void
  406. delay(int l)
  407. {
  408. ulong i, j;
  409. j = m->delayloop;
  410. while(l-- > 0)
  411. for(i=0; i < j; i++)
  412. ;
  413. }