clock.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. * cortex-a clocks; excludes tegra 2 SoC clocks
  3. *
  4. * cortex-a processors include private `global' and local timers
  5. * at soc.scu + 0x200 (global) and + 0x600 (local).
  6. * the global timer is a single count-up timer shared by all cores
  7. * but with per-cpu comparator and auto-increment registers.
  8. * a local count-down timer can be used as a watchdog.
  9. *
  10. * v7 arch provides a 32-bit count-up cycle counter (at about 1GHz in our case)
  11. * but it's unsuitable as our source of fastticks, because it stops advancing
  12. * when the cpu is suspended by WFI.
  13. */
  14. #include "u.h"
  15. #include "../port/lib.h"
  16. #include "mem.h"
  17. #include "dat.h"
  18. #include "fns.h"
  19. #include "arm.h"
  20. enum {
  21. Debug = 0,
  22. Basetickfreq = Mhz, /* soc.µs rate in Hz */
  23. /* the local timers seem to run at half the expected rate */
  24. Clockfreqbase = 250*Mhz / 2, /* private timer rate (PERIPHCLK/2) */
  25. Tcycles = Clockfreqbase / HZ, /* cycles per clock tick */
  26. MinPeriod = Tcycles / 100,
  27. MaxPeriod = Tcycles,
  28. Dogtimeout = Dogsectimeout * Clockfreqbase,
  29. };
  30. typedef struct Ltimer Ltimer;
  31. typedef struct Pglbtmr Pglbtmr;
  32. typedef struct Ploctmr Ploctmr;
  33. /*
  34. * cortex-a private-intr local timer registers. all cpus see their
  35. * own local timers at the same base address.
  36. */
  37. struct Ltimer {
  38. ulong load; /* new value + 1 */
  39. ulong cnt; /* counts down */
  40. ulong ctl;
  41. ulong isr;
  42. /* watchdog only */
  43. ulong wdrst;
  44. ulong wddis; /* wo */
  45. ulong _pad0[2];
  46. };
  47. struct Ploctmr {
  48. Ltimer loc;
  49. Ltimer wd;
  50. };
  51. enum {
  52. /* ctl bits */
  53. Tmrena = 1<<0, /* timer enabled */
  54. Wdogena = Tmrena, /* watchdog enabled */
  55. Xreload = 1<<1, /* reload on intr; periodic interrupts */
  56. Tintena = 1<<2, /* enable irq 29 at cnt==0 (30 for watchdog) */
  57. Wdog = 1<<3, /* watchdog, not timer, mode */
  58. Xsclrshift = 8,
  59. Xsclrmask = MASK(8),
  60. /* isr bits */
  61. Xisrclk = 1<<0, /* write to clear */
  62. /* wdrst bits */
  63. Wdrst = 1<<0,
  64. /* wddis values */
  65. Wdon = 1,
  66. Wdoff1 = 0x12345678, /* send these two to switch to timer mode */
  67. Wdoff2 = 0x87654321,
  68. };
  69. /* cortex-a private-intr globl timer registers */
  70. struct Pglbtmr {
  71. ulong cnt[2]; /* counts up; little-endian uvlong */
  72. ulong ctl;
  73. ulong isr;
  74. ulong cmp[2]; /* little-endian uvlong */
  75. ulong inc;
  76. };
  77. enum {
  78. /* unique ctl bits (otherwise see X* above) */
  79. Gcmp = 1<<1,
  80. // Gtintena= 1<<2, /* enable irq 27 */
  81. Gincr = 1<<3,
  82. };
  83. /*
  84. * until 5[cl] inline vlong ops, avoid them where possible,
  85. * they are currently slow function calls.
  86. */
  87. typedef union Vlong Vlong;
  88. union Vlong {
  89. uvlong uvl;
  90. struct { /* little-endian */
  91. ulong low;
  92. ulong high;
  93. };
  94. };
  95. static int fired;
  96. static int ticking[MAXMACH];
  97. /* no lock is needed to update our local timer. splhi keeps it tight. */
  98. static void
  99. setltimer(Ltimer *tn, ulong ticks)
  100. {
  101. int s;
  102. assert(ticks <= Clockfreqbase);
  103. s = splhi();
  104. tn->load = ticks - 1;
  105. coherence();
  106. tn->ctl = Tmrena | Tintena | Xreload;
  107. coherence();
  108. splx(s);
  109. }
  110. static void
  111. ckstuck(int cpu, long myticks, long histicks)
  112. {
  113. if (labs(histicks - myticks) > HZ) {
  114. // iprint("cpu%d: clock ticks %ld (vs myticks %ld cpu0 %ld); "
  115. // "apparently stopped\n",
  116. // cpu, histicks, myticks, MACHP(0)->ticks);
  117. if (!ticking[cpu])
  118. panic("cpu%d: clock not interrupting", cpu);
  119. }
  120. }
  121. static void
  122. mpclocksanity(void)
  123. {
  124. int cpu, mycpu;
  125. long myticks, histicks;
  126. if (conf.nmach <= 1 || active.exiting || navailcpus == 0)
  127. return;
  128. mycpu = m->machno;
  129. myticks = m->ticks;
  130. if (myticks == HZ)
  131. ticking[mycpu] = 1;
  132. if (myticks < 5*HZ)
  133. return;
  134. for (cpu = 0; cpu < navailcpus; cpu++) {
  135. if (cpu == mycpu)
  136. continue;
  137. histicks = MACHP(cpu)->ticks;
  138. if (myticks == 5*HZ || histicks > 1)
  139. ckstuck(cpu, myticks, histicks);
  140. }
  141. }
  142. static void
  143. clockintr(Ureg* ureg, void *arg)
  144. {
  145. Ltimer *wd, *tn;
  146. Ploctmr *lt;
  147. lt = (Ploctmr *)arg;
  148. tn = &lt->loc;
  149. tn->isr = Xisrclk;
  150. coherence();
  151. timerintr(ureg, 0);
  152. #ifdef watchdog_not_bloody_useless
  153. /* appease the dogs */
  154. wd = &lt->wd;
  155. if (wd->cnt == 0 &&
  156. (wd->ctl & (Wdog | Wdogena | Tintena)) == (Wdog | Wdogena))
  157. panic("cpu%d: zero watchdog count but no system reset",
  158. m->machno);
  159. wd->load = Dogtimeout - 1;
  160. coherence();
  161. #endif
  162. SET(wd); USED(wd);
  163. tegclockintr();
  164. mpclocksanity();
  165. }
  166. void
  167. clockprod(Ureg *ureg)
  168. {
  169. Ltimer *tn;
  170. timerintr(ureg, 0);
  171. tegclockintr();
  172. if (m->machno != 0) { /* cpu1 gets stuck */
  173. tn = &((Ploctmr *)soc.loctmr)->loc;
  174. setltimer(tn, Tcycles);
  175. }
  176. }
  177. static void
  178. clockreset(Ltimer *tn)
  179. {
  180. if (probeaddr((uintptr)tn) < 0)
  181. panic("no clock at %#p", tn);
  182. tn->ctl = 0;
  183. coherence();
  184. }
  185. void
  186. watchdogoff(Ltimer *wd)
  187. {
  188. wd->ctl &= ~Wdogena;
  189. coherence();
  190. wd->wddis = Wdoff1;
  191. coherence();
  192. wd->wddis = Wdoff2;
  193. coherence();
  194. }
  195. /* clear any pending watchdog intrs or causes */
  196. void
  197. wdogclrintr(Ltimer *wd)
  198. {
  199. #ifdef watchdog_not_bloody_useless
  200. wd->isr = Xisrclk;
  201. coherence();
  202. wd->wdrst = Wdrst;
  203. coherence();
  204. #endif
  205. USED(wd);
  206. }
  207. /*
  208. * stop clock interrupts on this cpu and disable the local watchdog timer,
  209. * and, if on cpu0, shutdown the shared tegra2 watchdog timer.
  210. */
  211. void
  212. clockshutdown(void)
  213. {
  214. Ploctmr *lt;
  215. lt = (Ploctmr *)soc.loctmr;
  216. clockreset(&lt->loc);
  217. watchdogoff(&lt->wd);
  218. tegclockshutdown();
  219. }
  220. enum {
  221. Instrs = 10*Mhz,
  222. };
  223. /* we assume that perfticks are microseconds */
  224. static long
  225. issue1loop(void)
  226. {
  227. register int i;
  228. long st;
  229. i = Instrs;
  230. st = perfticks();
  231. do {
  232. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  233. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  234. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  235. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  236. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  237. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  238. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  239. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  240. --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
  241. --i; --i; --i; --i; --i; --i; --i; --i; --i;
  242. } while(--i >= 0);
  243. return perfticks() - st;
  244. }
  245. static long
  246. issue2loop(void)
  247. {
  248. register int i, j;
  249. long st;
  250. i = Instrs / 2; /* j gets half the decrements */
  251. j = 0;
  252. st = perfticks();
  253. do {
  254. --j; --i; --j; --i; --j; --i; --j; --i; --j;
  255. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  256. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  257. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  258. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  259. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  260. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  261. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  262. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  263. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  264. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  265. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  266. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  267. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  268. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  269. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  270. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  271. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  272. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  273. --i; --j; --i; --j; --i; --j; --i; --j; --i; --j;
  274. } while(--i >= 0);
  275. return perfticks() - st;
  276. }
  277. /* estimate instructions/s. */
  278. static void
  279. guessmips(long (*loop)(void), char *lab)
  280. {
  281. int s;
  282. long tcks;
  283. do {
  284. s = splhi();
  285. tcks = loop();
  286. splx(s);
  287. if (tcks < 0)
  288. iprint("again...");
  289. } while (tcks < 0);
  290. /*
  291. * Instrs instructions took tcks ticks @ Basetickfreq Hz.
  292. * round the result.
  293. */
  294. s = (((vlong)Basetickfreq * Instrs) / tcks + 500000) / 1000000;
  295. if (Debug)
  296. iprint("%ud mips (%s-issue)", s, lab);
  297. USED(s);
  298. }
  299. void
  300. wdogintr(Ureg *, void *ltmr)
  301. {
  302. #ifdef watchdog_not_bloody_useless
  303. Ltimer *wd;
  304. wd = ltmr;
  305. fired++;
  306. wdogclrintr(wd);
  307. #endif
  308. USED(ltmr);
  309. }
  310. static void
  311. ckcounting(Ltimer *lt)
  312. {
  313. ulong old;
  314. old = lt->cnt;
  315. if (old == lt->cnt)
  316. delay(1);
  317. if (old == lt->cnt)
  318. panic("cpu%d: watchdog timer not counting down", m->machno);
  319. }
  320. /* test fire with interrupt to see that it's working */
  321. static void
  322. ckwatchdog(Ltimer *wd)
  323. {
  324. #ifdef watchdog_not_bloody_useless
  325. int s;
  326. fired = 0;
  327. wd->load = Tcycles - 1;
  328. coherence();
  329. /* Tintena is supposed to be ignored in watchdog mode */
  330. wd->ctl |= Wdogena | Tintena;
  331. coherence();
  332. ckcounting(wd);
  333. s = spllo();
  334. delay(2 * 1000/HZ);
  335. splx(s);
  336. if (!fired)
  337. /* useless local watchdog */
  338. iprint("cpu%d: local watchdog failed to interrupt\n", m->machno);
  339. /* clean up */
  340. wd->ctl &= ~Wdogena;
  341. coherence();
  342. #endif
  343. USED(wd);
  344. }
  345. static void
  346. startwatchdog(void)
  347. {
  348. #ifdef watchdog_not_bloody_useless
  349. Ltimer *wd;
  350. Ploctmr *lt;
  351. lt = (Ploctmr *)soc.loctmr;
  352. wd = &lt->wd;
  353. watchdogoff(wd);
  354. wdogclrintr(wd);
  355. irqenable(Wdtmrirq, wdogintr, wd, "watchdog");
  356. ckwatchdog(wd);
  357. /* set up for normal use, causing reset */
  358. wd->ctl &= ~Tintena; /* reset, don't interrupt */
  359. coherence();
  360. wd->ctl |= Wdog;
  361. coherence();
  362. wd->load = Dogtimeout - 1;
  363. coherence();
  364. wd->ctl |= Wdogena;
  365. coherence();
  366. ckcounting(wd);
  367. #endif
  368. }
  369. static void
  370. clock0init(Ltimer *tn)
  371. {
  372. int s;
  373. ulong old, fticks;
  374. /*
  375. * calibrate fastclock
  376. */
  377. s = splhi();
  378. tn->load = ~0ul >> 1;
  379. coherence();
  380. tn->ctl = Tmrena;
  381. coherence();
  382. old = perfticks();
  383. fticks = tn->cnt;
  384. delay(1);
  385. fticks = abs(tn->cnt - fticks);
  386. old = perfticks() - old;
  387. splx(s);
  388. if (Debug)
  389. iprint("cpu%d: fastclock %ld/%ldµs = %ld fastticks/µs (MHz)\n",
  390. m->machno, fticks, old, (fticks + old/2 - 1) / old);
  391. USED(fticks, old);
  392. if (Debug)
  393. iprint("cpu%d: ", m->machno);
  394. guessmips(issue1loop, "single");
  395. if (Debug)
  396. iprint(", ");
  397. guessmips(issue2loop, "dual");
  398. if (Debug)
  399. iprint("\n");
  400. /*
  401. * m->delayloop should be the number of delay loop iterations
  402. * needed to consume 1 ms. 2 is instr'ns in the delay loop.
  403. */
  404. m->delayloop = m->cpuhz / (1000 * 2);
  405. // iprint("cpu%d: m->delayloop = %lud\n", m->machno, m->delayloop);
  406. tegclock0init();
  407. }
  408. /*
  409. * the local timer is the interrupting timer and does not
  410. * participate in measuring time. It is initially set to HZ.
  411. */
  412. void
  413. clockinit(void)
  414. {
  415. ulong old;
  416. Ltimer *tn;
  417. Ploctmr *lt;
  418. clockshutdown();
  419. /* turn my cycle counter on */
  420. cpwrsc(0, CpCLD, CpCLDena, CpCLDenacyc, 1<<31);
  421. /* turn all my counters on and clear my cycle counter */
  422. cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1<<2 | 1);
  423. /* let users read my cycle counter directly */
  424. cpwrsc(0, CpCLD, CpCLDuser, CpCLDenapmnc, 1);
  425. /* verify µs counter sanity */
  426. tegclockinit();
  427. lt = (Ploctmr *)soc.loctmr;
  428. tn = &lt->loc;
  429. if (m->machno == 0)
  430. irqenable(Loctmrirq, clockintr, lt, "clock");
  431. else
  432. intcunmask(Loctmrirq);
  433. /*
  434. * verify sanity of local timer
  435. */
  436. tn->load = Clockfreqbase / 1000;
  437. tn->isr = Xisrclk;
  438. coherence();
  439. tn->ctl = Tmrena;
  440. coherence();
  441. old = tn->cnt;
  442. delay(5);
  443. /* m->ticks won't be incremented here because timersinit hasn't run. */
  444. if (tn->cnt == old)
  445. panic("cpu%d: clock not ticking at all", m->machno);
  446. else if ((long)tn->cnt > 0)
  447. panic("cpu%d: clock ticking slowly", m->machno);
  448. if (m->machno == 0)
  449. clock0init(tn);
  450. /* if pci gets stuck, maybe one of the many watchdogs will nuke us. */
  451. startwatchdog();
  452. /*
  453. * desynchronize the processor clocks so that they all don't
  454. * try to resched at the same time.
  455. */
  456. delay(m->machno*2);
  457. setltimer(tn, Tcycles);
  458. }
  459. /* our fastticks are at 1MHz (Basetickfreq), so the conversion is trivial. */
  460. ulong
  461. µs(void)
  462. {
  463. return fastticks2us(fastticks(nil));
  464. }
  465. /* Tval is supposed to be in fastticks units. */
  466. void
  467. timerset(Tval next)
  468. {
  469. int s;
  470. long offset;
  471. Ltimer *tn;
  472. tn = &((Ploctmr *)soc.loctmr)->loc;
  473. s = splhi();
  474. offset = fastticks2us(next - fastticks(nil));
  475. /* offset is now in µs (MHz); convert to Clockfreqbase Hz. */
  476. offset *= Clockfreqbase / Mhz;
  477. if(offset < MinPeriod)
  478. offset = MinPeriod;
  479. else if(offset > MaxPeriod)
  480. offset = MaxPeriod;
  481. setltimer(tn, offset);
  482. splx(s);
  483. }
  484. static ulong
  485. cpucycles(void) /* cpu clock rate, except when waiting for intr (unused) */
  486. {
  487. ulong v;
  488. /* reads 32-bit cycle counter (counting up) */
  489. // v = cprdsc(0, CpCLD, CpCLDcyc, 0);
  490. v = getcyc(); /* fast asm */
  491. /* keep it non-negative; prevent m->fastclock ever going to 0 */
  492. return v == 0? 1: v;
  493. }
  494. long
  495. lcycles(void)
  496. {
  497. return perfticks();
  498. }
  499. uvlong
  500. fastticks(uvlong *hz)
  501. {
  502. int s;
  503. ulong newticks;
  504. Vlong *fcp;
  505. if(hz)
  506. *hz = Basetickfreq;
  507. fcp = (Vlong *)&m->fastclock;
  508. /* avoid reentry on interrupt or trap, to prevent recursion */
  509. s = splhi();
  510. newticks = perfticks();
  511. if(newticks < fcp->low) /* low word must have wrapped */
  512. fcp->high++;
  513. fcp->low = newticks;
  514. splx(s);
  515. if (fcp->low == 0 && fcp->high == 0 && m->ticks > HZ/10)
  516. panic("fastticks: zero m->fastclock; ticks %lud fastclock %#llux",
  517. m->ticks, m->fastclock);
  518. return m->fastclock;
  519. }
  520. void
  521. microdelay(int l)
  522. {
  523. for (l = l * (vlong)m->delayloop / 1000; --l >= 0; )
  524. ;
  525. }
  526. void
  527. delay(int l)
  528. {
  529. int i, d;
  530. d = m->delayloop;
  531. while(--l >= 0)
  532. for (i = d; --i >= 0; )
  533. ;
  534. }