timer.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. timer.c
  9. Abstract:
  10. This module implements platform timer services for the RK3288 SoC.
  11. Author:
  12. Evan Green 9-Jul-2015
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <uefifw.h>
  20. #include "veyronfw.h"
  21. //
  22. // --------------------------------------------------------------------- Macros
  23. //
  24. //
  25. // This macro reads from an RK32xx timer. _Base should be a pointer, and
  26. // _Register should be a RK32_TIMER_REGISTER value.
  27. //
  28. #define READ_TIMER_REGISTER(_Base, _Register) \
  29. EfiReadRegister32((_Base) + (_Register))
  30. //
  31. // This macro writes to an RK32xx timer. _Base should be a pointer,
  32. // _Register should be RK32_TIMER_REGISTER value, and _Value should be a 32-bit
  33. // integer.
  34. //
  35. #define WRITE_TIMER_REGISTER(_Base, _Register, _Value) \
  36. EfiWriteRegister32((_Base) + (_Register), (_Value))
  37. //
  38. // These macros read from and write to the watchdog timer.
  39. //
  40. #define RK32_READ_WATCHDOG(_Register) \
  41. EfiReadRegister32((VOID *)RK32_WATCHDOG_BASE + (_Register))
  42. #define RK32_WRITE_WATCHDOG(_Register, _Value) \
  43. EfiWriteRegister32((VOID *)RK32_WATCHDOG_BASE + (_Register), (_Value))
  44. //
  45. // ---------------------------------------------------------------- Definitions
  46. //
  47. //
  48. // Define the number of 24MHz clock ticks per interrupt. Shoot for 64
  49. // interrupts per second.
  50. //
  51. #define VEYRON_TIMER_TICK_COUNT (RK32_TIMER_FREQUENCY / 64)
  52. //
  53. // ------------------------------------------------------ Data Type Definitions
  54. //
  55. /*++
  56. Structure Description:
  57. This structure stores the internal state associated with an RK32xx timer.
  58. Members:
  59. Base - Stores the virtual address of the timer.
  60. CountDown - Stores a boolean indicating whether the timer counts down
  61. (TRUE) or up (FALSE).
  62. --*/
  63. typedef struct _RK32_TIMER_DATA {
  64. VOID *Base;
  65. BOOLEAN CountDown;
  66. } RK32_TIMER_DATA, *PRK32_TIMER_DATA;
  67. //
  68. // ----------------------------------------------- Internal Function Prototypes
  69. //
  70. VOID
  71. EfipPlatformServiceTimerInterrupt (
  72. UINT32 InterruptNumber
  73. );
  74. UINT64
  75. EfipPlatformReadTimer (
  76. VOID
  77. );
  78. VOID
  79. EfipRk32TimerInitialize (
  80. PRK32_TIMER_DATA Context
  81. );
  82. UINT64
  83. EfipRk32TimerRead (
  84. PRK32_TIMER_DATA Context
  85. );
  86. VOID
  87. EfipRk32TimerArm (
  88. PRK32_TIMER_DATA Context,
  89. BOOLEAN Periodic,
  90. UINT64 TickCount
  91. );
  92. VOID
  93. EfipRk32TimerDisarm (
  94. PRK32_TIMER_DATA Context
  95. );
  96. VOID
  97. EfipRk32TimerAcknowledgeInterrupt (
  98. PRK32_TIMER_DATA Context
  99. );
  100. EFI_STATUS
  101. EfipRk32QueryApbAlivePclkFrequency (
  102. UINT32 *Frequency
  103. );
  104. //
  105. // -------------------------------------------------------------------- Globals
  106. //
  107. RK32_TIMER_DATA EfiVeyronClockTimer;
  108. RK32_TIMER_DATA EfiVeyronTimeCounter;
  109. //
  110. // The watchdog timer runs on the APB Alive APB PCLK, whose frequency is
  111. // calculated from the general PLL.
  112. //
  113. UINT32 EfiRk32ApbAlivePclkFrequency = 0;
  114. //
  115. // ------------------------------------------------------------------ Functions
  116. //
  117. EFIAPI
  118. EFI_STATUS
  119. EfiPlatformSetWatchdogTimer (
  120. UINTN Timeout,
  121. UINT64 WatchdogCode,
  122. UINTN DataSize,
  123. CHAR16 *WatchdogData
  124. )
  125. /*++
  126. Routine Description:
  127. This routine sets the system's watchdog timer.
  128. Arguments:
  129. Timeout - Supplies the number of seconds to set the timer for.
  130. WatchdogCode - Supplies a numeric code to log on a watchdog timeout event.
  131. DataSize - Supplies the size of the watchdog data.
  132. WatchdogData - Supplies an optional buffer that includes a null-terminated
  133. string, optionally followed by additional binary data.
  134. Return Value:
  135. EFI_SUCCESS on success.
  136. EFI_INVALID_PARAMETER if the supplied watchdog code is invalid.
  137. EFI_UNSUPPORTED if there is no watchdog timer.
  138. EFI_DEVICE_ERROR if an error occurred accessing the device hardware.
  139. --*/
  140. {
  141. UINT32 Control;
  142. UINT32 CurrentCount;
  143. UINT64 DesiredCount;
  144. UINT32 Frequency;
  145. UINT32 RangeIndex;
  146. EFI_STATUS Status;
  147. //
  148. // Query the APB Alive PCLK frequency if necessary.
  149. //
  150. if (EfiRk32ApbAlivePclkFrequency == 0) {
  151. Status = EfipRk32QueryApbAlivePclkFrequency(&Frequency);
  152. if (EFI_ERROR(Status)) {
  153. return Status;
  154. }
  155. EfiRk32ApbAlivePclkFrequency = Frequency;
  156. }
  157. DesiredCount = (Timeout * EfiRk32ApbAlivePclkFrequency);
  158. if (DesiredCount > RK32_WATCHDOG_MAX) {
  159. DesiredCount = RK32_WATCHDOG_MAX;
  160. }
  161. //
  162. // First, disable the watchdog timer.
  163. //
  164. Control = RK32_READ_WATCHDOG(Rk32WatchdogControl);
  165. Control &= ~RK32_WATCHDOG_CONTROL_ENABLE;
  166. RK32_WRITE_WATCHDOG(Rk32WatchdogControl, Control);
  167. //
  168. // If the watchdog timer is being enabled, set the count value and fire it
  169. // back up.
  170. //
  171. if ((DesiredCount != 0) && (EfiDisableWatchdog == FALSE)) {
  172. //
  173. // Figure out the proper range index for the requested count. The
  174. // allowable ranges go 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
  175. // 0x000FFFFF, etc all the way up to 0x7FFFFFFF.
  176. //
  177. RangeIndex = 0;
  178. CurrentCount = RK32_WATCHDOG_MIN;
  179. while (CurrentCount < DesiredCount) {
  180. RangeIndex += 1;
  181. CurrentCount = (CurrentCount << 1) | 0x1;
  182. }
  183. RK32_WRITE_WATCHDOG(Rk32WatchdogTimeoutRange, RangeIndex);
  184. //
  185. // Restart the counter. The TRM cruelly refers to this as "kicking the
  186. // dog".
  187. //
  188. RK32_WRITE_WATCHDOG(Rk32WatchdogCounterRestart,
  189. RK32_WATCHDOG_RESTART_VALUE);
  190. //
  191. // Enable the watchdog.
  192. //
  193. Control |= RK32_WATCHDOG_CONTROL_ENABLE;
  194. Control &= ~RK32_WATCHDOG_CONTROL_BARK_FIRST;
  195. RK32_WRITE_WATCHDOG(Rk32WatchdogControl, Control);
  196. }
  197. return EFI_SUCCESS;
  198. }
  199. EFI_STATUS
  200. EfiPlatformInitializeTimers (
  201. UINT32 *ClockTimerInterruptNumber,
  202. EFI_PLATFORM_SERVICE_TIMER_INTERRUPT *ClockTimerServiceRoutine,
  203. EFI_PLATFORM_READ_TIMER *ReadTimerRoutine,
  204. UINT64 *ReadTimerFrequency,
  205. UINT32 *ReadTimerWidth
  206. )
  207. /*++
  208. Routine Description:
  209. This routine initializes platform timer services. There are actually two
  210. different timer services returned in this routine. The periodic timer tick
  211. provides a periodic interrupt. The read timer provides a free running
  212. counter value. These are likely serviced by different timers. For the
  213. periodic timer tick, this routine should start the periodic interrupts
  214. coming in. The periodic rate of the timer can be anything reasonable, as
  215. the time counter will be used to count actual duration. The rate should be
  216. greater than twice the rollover rate of the time counter to ensure proper
  217. time accounting. Interrupts are disabled at the processor core for the
  218. duration of this routine.
  219. Arguments:
  220. ClockTimerInterruptNumber - Supplies a pointer where the interrupt line
  221. number of the periodic timer tick will be returned.
  222. ClockTimerServiceRoutine - Supplies a pointer where a pointer to a routine
  223. called when the periodic timer tick interrupt occurs will be returned.
  224. ReadTimerRoutine - Supplies a pointer where a pointer to a routine
  225. called to read the current timer value will be returned.
  226. ReadTimerFrequency - Supplies the frequency of the counter.
  227. ReadTimerWidth - Supplies a pointer where the read timer bit width will be
  228. returned.
  229. Return Value:
  230. EFI Status code.
  231. --*/
  232. {
  233. EFI_STATUS Status;
  234. *ClockTimerInterruptNumber = RK32_INTERRUPT_TIMER0;
  235. *ClockTimerServiceRoutine = EfipPlatformServiceTimerInterrupt;
  236. *ReadTimerRoutine = EfipPlatformReadTimer;
  237. *ReadTimerFrequency = RK32_TIMER_FREQUENCY;
  238. *ReadTimerWidth = 64;
  239. //
  240. // Use timer 0 for the clock timer and timer 1 for the time counter. Both
  241. // run at 24MHz, and both count down.
  242. //
  243. EfiVeyronClockTimer.Base = (VOID *)(RK32_TIMER0_5_BASE +
  244. (0 * RK32_TIMER_REGISTER_STRIDE));
  245. EfiVeyronClockTimer.CountDown = TRUE;
  246. EfiVeyronTimeCounter.Base = (VOID *)(RK32_TIMER0_5_BASE +
  247. (1 * RK32_TIMER_REGISTER_STRIDE));
  248. EfiVeyronTimeCounter.CountDown = TRUE;
  249. EfipRk32TimerInitialize(&EfiVeyronClockTimer);
  250. EfipRk32TimerArm(&EfiVeyronClockTimer, TRUE, VEYRON_TIMER_TICK_COUNT);
  251. EfipRk32TimerInitialize(&EfiVeyronTimeCounter);
  252. Status = EfipPlatformSetInterruptLineState(*ClockTimerInterruptNumber,
  253. TRUE,
  254. FALSE);
  255. return Status;
  256. }
  257. VOID
  258. EfiPlatformTerminateTimers (
  259. VOID
  260. )
  261. /*++
  262. Routine Description:
  263. This routine terminates timer services in preparation for the termination
  264. of boot services.
  265. Arguments:
  266. None.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. EfipRk32TimerDisarm(&EfiVeyronClockTimer);
  272. return;
  273. }
  274. //
  275. // --------------------------------------------------------- Internal Functions
  276. //
  277. VOID
  278. EfipPlatformServiceTimerInterrupt (
  279. UINT32 InterruptNumber
  280. )
  281. /*++
  282. Routine Description:
  283. This routine is called to acknowledge a platform timer interrupt. This
  284. routine is responsible for quiescing the interrupt.
  285. Arguments:
  286. InterruptNumber - Supplies the interrupt number that occurred.
  287. Return Value:
  288. None.
  289. --*/
  290. {
  291. EfipRk32TimerAcknowledgeInterrupt(&EfiVeyronClockTimer);
  292. return;
  293. }
  294. UINT64
  295. EfipPlatformReadTimer (
  296. VOID
  297. )
  298. /*++
  299. Routine Description:
  300. This routine is called to read the current platform time value. The timer
  301. is assumed to be free running at a constant frequency, and should have a
  302. bit width as reported in the initialize function. The UEFI core will
  303. manage software bit extension out to 64 bits, this routine should just
  304. reporte the hardware timer value.
  305. Arguments:
  306. None.
  307. Return Value:
  308. Returns the hardware timer value.
  309. --*/
  310. {
  311. return EfipRk32TimerRead(&EfiVeyronTimeCounter);
  312. }
  313. VOID
  314. EfipRk32TimerInitialize (
  315. PRK32_TIMER_DATA Context
  316. )
  317. /*++
  318. Routine Description:
  319. This routine initializes an RK32xx timer.
  320. Arguments:
  321. Context - Supplies the pointer to the timer's context.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. if (Context->Base == NULL) {
  327. return;
  328. }
  329. //
  330. // Program the timer in free running mode with no interrupt.
  331. //
  332. WRITE_TIMER_REGISTER(Context->Base,
  333. Rk32TimerControl,
  334. RK32_TIMER_CONTROL_ENABLE);
  335. //
  336. // Set the load count register to the maximum period.
  337. //
  338. WRITE_TIMER_REGISTER(Context->Base,
  339. Rk32TimerLoadCountHigh,
  340. 0xFFFFFFFF);
  341. WRITE_TIMER_REGISTER(Context->Base,
  342. Rk32TimerLoadCountLow,
  343. 0xFFFFFFFF);
  344. //
  345. // Clear any previously pending interrupts.
  346. //
  347. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerInterruptStatus, 1);
  348. return;
  349. }
  350. UINT64
  351. EfipRk32TimerRead (
  352. PRK32_TIMER_DATA Context
  353. )
  354. /*++
  355. Routine Description:
  356. This routine returns the hardware counter's raw value.
  357. Arguments:
  358. Context - Supplies the pointer to the timer's context.
  359. Return Value:
  360. Returns the timer's current count.
  361. --*/
  362. {
  363. UINT32 High1;
  364. UINT32 High2;
  365. UINT32 Low;
  366. UINT64 Value;
  367. //
  368. // Do a high-low-high read to make sure sure the words didn't tear.
  369. //
  370. do {
  371. High1 = READ_TIMER_REGISTER(Context->Base, Rk32TimerCurrentValueHigh);
  372. Low = READ_TIMER_REGISTER(Context->Base, Rk32TimerCurrentValueLow);
  373. High2 = READ_TIMER_REGISTER(Context->Base, Rk32TimerCurrentValueHigh);
  374. } while (High1 != High2);
  375. Value = (((UINT64)High1) << 32) | Low;
  376. if (Context->CountDown != FALSE) {
  377. Value = ~Value;
  378. }
  379. return Value;
  380. }
  381. VOID
  382. EfipRk32TimerArm (
  383. PRK32_TIMER_DATA Context,
  384. BOOLEAN Periodic,
  385. UINT64 TickCount
  386. )
  387. /*++
  388. Routine Description:
  389. This routine arms the timer to fire an interrupt after the specified number
  390. of ticks.
  391. Arguments:
  392. Context - Supplies the pointer to the timer's context.
  393. Periodic - Supplies a boolean indicating if the timer should be armed
  394. periodically or one-shot.
  395. TickCount - Supplies the interval, in ticks, from now for the timer to fire
  396. in.
  397. Return Value:
  398. None.
  399. --*/
  400. {
  401. UINT32 Control;
  402. if (Context->CountDown == FALSE) {
  403. TickCount = 0 - TickCount;
  404. }
  405. //
  406. // Stop the timer before programming it, as demanded by the TRM.
  407. //
  408. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerControl, 0);
  409. //
  410. // Program the new tick count.
  411. //
  412. WRITE_TIMER_REGISTER(Context->Base,
  413. Rk32TimerLoadCountHigh,
  414. TickCount >> 32);
  415. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerLoadCountLow, TickCount);
  416. Control = RK32_TIMER_CONTROL_ENABLE | RK32_TIMER_CONTROL_INTERRUPT_ENABLE;
  417. if (Periodic == FALSE) {
  418. Control |= RK32_TIMER_CONTROL_ONE_SHOT;
  419. }
  420. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerControl, Control);
  421. return;
  422. }
  423. VOID
  424. EfipRk32TimerDisarm (
  425. PRK32_TIMER_DATA Context
  426. )
  427. /*++
  428. Routine Description:
  429. This routine disarms the timer, stopping interrupts from firing.
  430. Arguments:
  431. Context - Supplies the pointer to the timer's context.
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. //
  437. // Just stop the timer completely.
  438. //
  439. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerControl, 0);
  440. return;
  441. }
  442. VOID
  443. EfipRk32TimerAcknowledgeInterrupt (
  444. PRK32_TIMER_DATA Context
  445. )
  446. /*++
  447. Routine Description:
  448. This routine performs any actions necessary upon reciept of a timer's
  449. interrupt. This may involve writing to an acknowledge register to re-enable
  450. the timer to fire again, or other hardware specific actions.
  451. Arguments:
  452. Context - Supplies the pointer to the timer's context.
  453. Return Value:
  454. None.
  455. --*/
  456. {
  457. WRITE_TIMER_REGISTER(Context->Base, Rk32TimerInterruptStatus, 1);
  458. return;
  459. }
  460. EFI_STATUS
  461. EfipRk32QueryApbAlivePclkFrequency (
  462. UINT32 *Frequency
  463. )
  464. /*++
  465. Routine Description:
  466. This routine queries the APB Alive PCLK frequency.
  467. Arguments:
  468. Frequency - Supplies a pointer that receives the current frequency.
  469. Return Value:
  470. Status code.
  471. --*/
  472. {
  473. UINT32 Divisor;
  474. UINT32 GeneralPllFrequency;
  475. EFI_STATUS Status;
  476. UINT32 Value;
  477. //
  478. // The APB Alive PCLK timer is taken from the General PLL and divided by
  479. // the value stored in clock select register 33.
  480. //
  481. Status = EfipRk32GetPllClockFrequency(Rk32PllGeneral, &GeneralPllFrequency);
  482. if (EFI_ERROR(Status)) {
  483. return Status;
  484. }
  485. Value = EfiReadRegister32((VOID *)RK32_CRU_BASE + Rk32CruClockSelect33);
  486. Divisor = (Value & RK32_CRU_CLOCK_SELECT33_ALIVE_PCLK_DIVIDER_MASK) >>
  487. RK32_CRU_CLOCK_SELECT33_ALIVE_PCLK_DIVIDER_SHIFT;
  488. *Frequency = GeneralPllFrequency / (Divisor + 1);
  489. return EFI_SUCCESS;
  490. }