timer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /*++
  2. Copyright (c) 2014 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 TI AM335x. These
  11. timers function identically to the OMAP4 timers, and could be merged.
  12. Author:
  13. Evan Green 19-Dec-2014
  14. Environment:
  15. Firmware
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <uefifw.h>
  21. #include "bbonefw.h"
  22. #include <minoca/soc/am335x.h>
  23. //
  24. // --------------------------------------------------------------------- Macros
  25. //
  26. //
  27. // This macro reads from an AM335 timer. _Base should be a pointer, and
  28. // _Register should be a AM335_TIMER_REGISTER value.
  29. //
  30. #define READ_TIMER_REGISTER(_Base, _Register) \
  31. EfiReadRegister32((VOID *)(_Base) + (_Register))
  32. //
  33. // This macro writes to an AM335 timer. _Base should be a pointer,
  34. // _Register should be GP_TIMER_REGISTER value, and _Value should be a ULONG.
  35. //
  36. #define WRITE_TIMER_REGISTER(_Base, _Register, _Value) \
  37. EfiWriteRegister32((VOID *)(_Base) + (_Register), (_Value))
  38. //
  39. // These macros read from and write to the watchdog timer.
  40. //
  41. #define AM335_READ_WATCHDOG(_Register) \
  42. EfiReadRegister32((VOID *)AM335_WATCHDOG_BASE + (_Register))
  43. #define AM335_WRITE_WATCHDOG(_Register, _Value) \
  44. EfiWriteRegister32((VOID *)AM335_WATCHDOG_BASE + (_Register), (_Value))
  45. //
  46. // These macros read from and write to the RTC.
  47. //
  48. #define AM3_READ_RTC(_Register) \
  49. *(volatile UINT32 *)(AM335_RTC_BASE + (_Register))
  50. #define AM3_WRITE_RTC(_Register, _Value) \
  51. *((volatile UINT32 *)(AM335_RTC_BASE + (_Register))) = (_Value)
  52. //
  53. // ---------------------------------------------------------------- Definitions
  54. //
  55. //
  56. // ------------------------------------------------------ Data Type Definitions
  57. //
  58. /*++
  59. Structure Description:
  60. This structure stores the internal state associated with an AM335 DM
  61. timer.
  62. Members:
  63. Base - Stores the virtual address of the timer.
  64. Index - Stores the zero-based index of this timer within the timer block.
  65. --*/
  66. typedef struct _AM335_TIMER_DATA {
  67. VOID *Base;
  68. UINT32 Index;
  69. UINT32 Offset;
  70. } AM335_TIMER_DATA, *PAM335_TIMER_DATA;
  71. //
  72. // ----------------------------------------------- Internal Function Prototypes
  73. //
  74. VOID
  75. EfipPlatformServiceTimerInterrupt (
  76. UINT32 InterruptNumber
  77. );
  78. UINT64
  79. EfipPlatformReadTimer (
  80. VOID
  81. );
  82. VOID
  83. EfipAm335TimerInitialize (
  84. PAM335_TIMER_DATA Context
  85. );
  86. UINT64
  87. EfipAm335TimerRead (
  88. PAM335_TIMER_DATA Context
  89. );
  90. VOID
  91. EfipAm335TimerArm (
  92. PAM335_TIMER_DATA Context,
  93. BOOLEAN Periodic,
  94. UINT64 TickCount
  95. );
  96. VOID
  97. EfipAm335TimerDisarm (
  98. PAM335_TIMER_DATA Context
  99. );
  100. VOID
  101. EfipAm335TimerAcknowledgeInterrupt (
  102. PAM335_TIMER_DATA Context
  103. );
  104. //
  105. // -------------------------------------------------------------------- Globals
  106. //
  107. AM335_TIMER_DATA EfiBeagleBoneClockTimer;
  108. AM335_TIMER_DATA EfiBeagleBoneTimeCounter;
  109. //
  110. // ------------------------------------------------------------------ Functions
  111. //
  112. EFIAPI
  113. EFI_STATUS
  114. EfiPlatformSetWatchdogTimer (
  115. UINTN Timeout,
  116. UINT64 WatchdogCode,
  117. UINTN DataSize,
  118. CHAR16 *WatchdogData
  119. )
  120. /*++
  121. Routine Description:
  122. This routine sets the system's watchdog timer.
  123. Arguments:
  124. Timeout - Supplies the number of seconds to set the timer for.
  125. WatchdogCode - Supplies a numeric code to log on a watchdog timeout event.
  126. DataSize - Supplies the size of the watchdog data.
  127. WatchdogData - Supplies an optional buffer that includes a null-terminated
  128. string, optionally followed by additional binary data.
  129. Return Value:
  130. EFI_SUCCESS on success.
  131. EFI_INVALID_PARAMETER if the supplied watchdog code is invalid.
  132. EFI_UNSUPPORTED if there is no watchdog timer.
  133. EFI_DEVICE_ERROR if an error occurred accessing the device hardware.
  134. --*/
  135. {
  136. UINT32 Count;
  137. Count = 0 - (Timeout * AM335_WATCHDOG_FREQUENCY);
  138. //
  139. // First, disable the watchdog timer.
  140. //
  141. AM335_WRITE_WATCHDOG(Am335WatchdogStartStop, AM335_WATCHDOG_DISABLE1);
  142. EfiStall(1000);
  143. AM335_WRITE_WATCHDOG(Am335WatchdogStartStop, AM335_WATCHDOG_DISABLE2);
  144. EfiStall(1000);
  145. //
  146. // If the watchdog timer is being enabled, set the count value and fire it
  147. // back up.
  148. //
  149. if ((Count != 0) && (EfiDisableWatchdog == FALSE)) {
  150. AM335_WRITE_WATCHDOG(Am335WatchdogLoadCount, Count);
  151. EfiStall(1000);
  152. AM335_WRITE_WATCHDOG(Am335WatchdogCurrentCount, Count);
  153. EfiStall(1000);
  154. AM335_WRITE_WATCHDOG(Am335WatchdogStartStop, AM335_WATCHDOG_ENABLE1);
  155. EfiStall(1000);
  156. AM335_WRITE_WATCHDOG(Am335WatchdogStartStop, AM335_WATCHDOG_ENABLE2);
  157. }
  158. return EFI_SUCCESS;
  159. }
  160. EFI_STATUS
  161. EfiPlatformInitializeTimers (
  162. UINT32 *ClockTimerInterruptNumber,
  163. EFI_PLATFORM_SERVICE_TIMER_INTERRUPT *ClockTimerServiceRoutine,
  164. EFI_PLATFORM_READ_TIMER *ReadTimerRoutine,
  165. UINT64 *ReadTimerFrequency,
  166. UINT32 *ReadTimerWidth
  167. )
  168. /*++
  169. Routine Description:
  170. This routine initializes platform timer services. There are actually two
  171. different timer services returned in this routine. The periodic timer tick
  172. provides a periodic interrupt. The read timer provides a free running
  173. counter value. These are likely serviced by different timers. For the
  174. periodic timer tick, this routine should start the periodic interrupts
  175. coming in. The periodic rate of the timer can be anything reasonable, as
  176. the time counter will be used to count actual duration. The rate should be
  177. greater than twice the rollover rate of the time counter to ensure proper
  178. time accounting. Interrupts are disabled at the processor core for the
  179. duration of this routine.
  180. Arguments:
  181. ClockTimerInterruptNumber - Supplies a pointer where the interrupt line
  182. number of the periodic timer tick will be returned.
  183. ClockTimerServiceRoutine - Supplies a pointer where a pointer to a routine
  184. called when the periodic timer tick interrupt occurs will be returned.
  185. ReadTimerRoutine - Supplies a pointer where a pointer to a routine
  186. called to read the current timer value will be returned.
  187. ReadTimerFrequency - Supplies the frequency of the counter.
  188. ReadTimerWidth - Supplies a pointer where the read timer bit width will be
  189. returned.
  190. Return Value:
  191. EFI Status code.
  192. --*/
  193. {
  194. EFI_STATUS Status;
  195. *ClockTimerInterruptNumber = AM335_IRQ_DMTIMER0;
  196. *ClockTimerServiceRoutine = EfipPlatformServiceTimerInterrupt;
  197. *ReadTimerRoutine = EfipPlatformReadTimer;
  198. *ReadTimerFrequency = AM335_32KHZ_FREQUENCY;
  199. *ReadTimerWidth = 32;
  200. //
  201. // Use GP timer 0 for the clock timer and GP timer 2 for the time counter.
  202. // Both run at 32kHz.
  203. //
  204. EfiBeagleBoneClockTimer.Base = (VOID *)AM335_DMTIMER0_BASE;
  205. EfiBeagleBoneClockTimer.Index = 0;
  206. EfiBeagleBoneTimeCounter.Base = (VOID *)AM335_DMTIMER2_BASE;
  207. EfiBeagleBoneTimeCounter.Index = 2;
  208. EfipAm335TimerInitialize(&EfiBeagleBoneClockTimer);
  209. EfipAm335TimerArm(&EfiBeagleBoneClockTimer,
  210. TRUE,
  211. BEAGLEBONE_TIMER_TICK_COUNT);
  212. EfipAm335TimerInitialize(&EfiBeagleBoneTimeCounter);
  213. Status = EfipPlatformSetInterruptLineState(*ClockTimerInterruptNumber,
  214. TRUE,
  215. FALSE);
  216. return Status;
  217. }
  218. VOID
  219. EfiPlatformTerminateTimers (
  220. VOID
  221. )
  222. /*++
  223. Routine Description:
  224. This routine terminates timer services in preparation for the termination
  225. of boot services.
  226. Arguments:
  227. None.
  228. Return Value:
  229. None.
  230. --*/
  231. {
  232. EfipAm335TimerDisarm(&EfiBeagleBoneClockTimer);
  233. return;
  234. }
  235. VOID
  236. EfipBeagleBoneBlackInitializeRtc (
  237. VOID
  238. )
  239. /*++
  240. Routine Description:
  241. This routine fires up the RTC in the AM335x for the BeagleBone Black, if it
  242. is not already running.
  243. Arguments:
  244. None.
  245. Return Value:
  246. None.
  247. --*/
  248. {
  249. UINT32 Control;
  250. UINT32 Status;
  251. UINT32 Value;
  252. //
  253. // Set the RTC to smart idle wakeup-capable.
  254. //
  255. Value = AM335_RTC_SYS_CONFIG_IDLE_MODE_SMART_WAKEUP;
  256. AM3_WRITE_RTC(Am335RtcSysConfig, Value);
  257. //
  258. // If the RTC is already running, then it's been set up from a previous
  259. // boot.
  260. //
  261. Status = AM3_READ_RTC(Am335RtcStatus);
  262. if ((Status & AM335_RTC_STATUS_RUN) != 0) {
  263. goto BeagleBoneBlackInitializeRtcEnd;
  264. }
  265. //
  266. // If the RTC has been disabled by a previous boot, leave it alone, as the
  267. // spec seems to indicate there's no turning it back on once it's off.
  268. //
  269. Control = AM3_READ_RTC(Am335RtcControl);
  270. if ((Control & AM335_RTC_CONTROL_RTC_DISABLE) != 0) {
  271. return;
  272. }
  273. //
  274. // Unlock the RTC to program it.
  275. //
  276. AM3_WRITE_RTC(Am335RtcKick0, AM335_RTC_KICK0_KEY);
  277. AM3_WRITE_RTC(Am335RtcKick1, AM335_RTC_KICK1_KEY);
  278. //
  279. // Select the internal clock source, and enable inputs.
  280. //
  281. Value = AM3_READ_RTC(Am335RtcOscillator);
  282. Value &= ~AM335_RTC_OSCILLATOR_SOURCE_EXTERNAL;
  283. AM3_WRITE_RTC(Am335RtcOscillator, Value);
  284. Value |= AM335_RTC_OSCILLATOR_ENABLE;
  285. AM3_WRITE_RTC(Am335RtcOscillator, Value);
  286. //
  287. // Start the RTC running in 24 hour mode.
  288. //
  289. Value = AM335_RTC_CONTROL_RUN;
  290. AM3_WRITE_RTC(Am335RtcControl, Value);
  291. do {
  292. Value = AM3_READ_RTC(Am335RtcStatus);
  293. } while ((Value & AM335_RTC_STATUS_RUN) == 0);
  294. //
  295. // Lock the RTC to prevent accidental writes.
  296. //
  297. AM3_WRITE_RTC(Am335RtcKick0, AM335_RTC_KICK0_KEY);
  298. AM3_WRITE_RTC(Am335RtcKick1, 0xFFFFFFFF);
  299. BeagleBoneBlackInitializeRtcEnd:
  300. return;
  301. }
  302. //
  303. // --------------------------------------------------------- Internal Functions
  304. //
  305. VOID
  306. EfipPlatformServiceTimerInterrupt (
  307. UINT32 InterruptNumber
  308. )
  309. /*++
  310. Routine Description:
  311. This routine is called to acknowledge a platform timer interrupt. This
  312. routine is responsible for quiescing the interrupt.
  313. Arguments:
  314. InterruptNumber - Supplies the interrupt number that occurred.
  315. Return Value:
  316. None.
  317. --*/
  318. {
  319. EfipAm335TimerAcknowledgeInterrupt(&EfiBeagleBoneClockTimer);
  320. return;
  321. }
  322. UINT64
  323. EfipPlatformReadTimer (
  324. VOID
  325. )
  326. /*++
  327. Routine Description:
  328. This routine is called to read the current platform time value. The timer
  329. is assumed to be free running at a constant frequency, and should have a
  330. bit width as reported in the initialize function. The UEFI core will
  331. manage software bit extension out to 64 bits, this routine should just
  332. reporte the hardware timer value.
  333. Arguments:
  334. None.
  335. Return Value:
  336. Returns the hardware timer value.
  337. --*/
  338. {
  339. return EfipAm335TimerRead(&EfiBeagleBoneTimeCounter);
  340. }
  341. VOID
  342. EfipAm335TimerInitialize (
  343. PAM335_TIMER_DATA Context
  344. )
  345. /*++
  346. Routine Description:
  347. This routine initializes an AM335 timer.
  348. Arguments:
  349. Context - Supplies the pointer to the timer's context.
  350. Return Value:
  351. None.
  352. --*/
  353. {
  354. UINT32 Value;
  355. if (Context->Base == NULL) {
  356. return;
  357. }
  358. //
  359. // Program the timer in free running mode with no interrupt.
  360. //
  361. WRITE_TIMER_REGISTER(Context->Base,
  362. Am335TimerOcpConfig,
  363. AM335_TIMER_IDLEMODE_SMART);
  364. //
  365. // Disable wakeup functionality.
  366. //
  367. WRITE_TIMER_REGISTER(Context->Base,
  368. Am335TimerInterruptWakeEnable,
  369. 0);
  370. //
  371. // Set the synchronous interface configuration register to non-posted mode,
  372. // which means that writes don't return until they complete. Posted mode
  373. // is faster for writes but requires polling a bit for reads.
  374. //
  375. WRITE_TIMER_REGISTER(Context->Base,
  376. Am335TimerSynchronousInterfaceControl,
  377. 0);
  378. //
  379. // Disable all interrupts for now. The alternate register interface uses a
  380. // set/clear style for the interrupt mask bits.
  381. //
  382. WRITE_TIMER_REGISTER(Context->Base,
  383. Am335TimerInterruptEnableClear,
  384. AM335_TIMER_INTERRUPT_MASK);
  385. //
  386. // Set the load value to zero to create a free-running timer, and reset the
  387. // current counter now too.
  388. //
  389. WRITE_TIMER_REGISTER(Context->Base, Am335TimerLoad, 0);
  390. WRITE_TIMER_REGISTER(Context->Base, Am335TimerCount, 0);
  391. //
  392. // Set the mode register to auto-reload, and start the timer.
  393. //
  394. Value = AM335_TIMER_OVERFLOW_TRIGGER | AM335_TIMER_STARTED |
  395. AM335_TIMER_AUTORELOAD;
  396. WRITE_TIMER_REGISTER(Context->Base, Am335TimerControl, Value);
  397. //
  398. // Reset all interrupt-pending bits.
  399. //
  400. //
  401. WRITE_TIMER_REGISTER(Context->Base,
  402. Am335TimerInterruptStatus,
  403. AM335_TIMER_INTERRUPT_MASK);
  404. return;
  405. }
  406. UINT64
  407. EfipAm335TimerRead (
  408. PAM335_TIMER_DATA Context
  409. )
  410. /*++
  411. Routine Description:
  412. This routine returns the hardware counter's raw value.
  413. Arguments:
  414. Context - Supplies the pointer to the timer's context.
  415. Return Value:
  416. Returns the timer's current count.
  417. --*/
  418. {
  419. UINT32 Value;
  420. Value = READ_TIMER_REGISTER(Context->Base, Am335TimerCount);
  421. return Value;
  422. }
  423. VOID
  424. EfipAm335TimerArm (
  425. PAM335_TIMER_DATA Context,
  426. BOOLEAN Periodic,
  427. UINT64 TickCount
  428. )
  429. /*++
  430. Routine Description:
  431. This routine arms the timer to fire an interrupt after the specified number
  432. of ticks.
  433. Arguments:
  434. Context - Supplies the pointer to the timer's context.
  435. Periodic - Supplies a boolean indicating if the timer should be armed
  436. periodically or one-shot.
  437. TickCount - Supplies the interval, in ticks, from now for the timer to fire
  438. in.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. UINT32 Value;
  444. if (TickCount >= 0xFFFFFFFF) {
  445. TickCount = 0xFFFFFFFF;
  446. }
  447. //
  448. // Start the timer ticking.
  449. //
  450. WRITE_TIMER_REGISTER(Context->Base, Am335TimerControl, 0);
  451. WRITE_TIMER_REGISTER(Context->Base,
  452. Am335TimerLoad,
  453. 0xFFFFFFFF - (UINT32)TickCount);
  454. WRITE_TIMER_REGISTER(Context->Base,
  455. Am335TimerCount,
  456. 0xFFFFFFFF - (UINT32)TickCount);
  457. Value = AM335_TIMER_STARTED;
  458. if (Periodic != FALSE) {
  459. Value |= AM335_TIMER_AUTORELOAD;
  460. }
  461. WRITE_TIMER_REGISTER(Context->Base, Am335TimerControl, Value);
  462. WRITE_TIMER_REGISTER(Context->Base,
  463. Am335TimerInterruptEnableSet,
  464. AM335_TIMER_OVERFLOW_INTERRUPT);
  465. return;
  466. }
  467. VOID
  468. EfipAm335TimerDisarm (
  469. PAM335_TIMER_DATA Context
  470. )
  471. /*++
  472. Routine Description:
  473. This routine disarms the timer, stopping interrupts from firing.
  474. Arguments:
  475. Context - Supplies the pointer to the timer's context.
  476. Return Value:
  477. None.
  478. --*/
  479. {
  480. //
  481. // Disable all interrupts.
  482. //
  483. WRITE_TIMER_REGISTER(Context->Base,
  484. Am335TimerInterruptEnableClear,
  485. AM335_TIMER_INTERRUPT_MASK);
  486. //
  487. // Reset all interrupt-pending bits.
  488. //
  489. WRITE_TIMER_REGISTER(Context->Base,
  490. Am335TimerInterruptStatus,
  491. AM335_TIMER_INTERRUPT_MASK);
  492. return;
  493. }
  494. VOID
  495. EfipAm335TimerAcknowledgeInterrupt (
  496. PAM335_TIMER_DATA Context
  497. )
  498. /*++
  499. Routine Description:
  500. This routine performs any actions necessary upon reciept of a timer's
  501. interrupt. This may involve writing to an acknowledge register to re-enable
  502. the timer to fire again, or other hardware specific actions.
  503. Arguments:
  504. Context - Supplies the pointer to the timer's context.
  505. Return Value:
  506. None.
  507. --*/
  508. {
  509. //
  510. // Clear the overflow interrupt by writing a 1 to the status bit.
  511. //
  512. WRITE_TIMER_REGISTER(Context->Base,
  513. Am335TimerInterruptStatus,
  514. AM335_TIMER_OVERFLOW_INTERRUPT);
  515. return;
  516. }