1
0

timer.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. timer.c
  5. Abstract:
  6. This module implements platform timer services for the TI PandaBoard.
  7. Author:
  8. Evan Green 3-Mar-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <uefifw.h>
  16. #include "pandafw.h"
  17. //
  18. // --------------------------------------------------------------------- Macros
  19. //
  20. //
  21. // This macro reads from an OMAP4 timer. _Base should be a pointer, and
  22. // _Register should be a GP_TIMER_REGISTER value.
  23. //
  24. #define READ_TIMER_REGISTER(_Base, _Register) \
  25. EfiReadRegister32((UINT32 *)(_Base) + (_Register))
  26. //
  27. // This macro writes to an OMAP4 timer. _Base should be a pointer,
  28. // _Register should be GP_TIMER_REGISTER value, and _Value should be a ULONG.
  29. //
  30. #define WRITE_TIMER_REGISTER(_Base, _Register, _Value) \
  31. EfiWriteRegister32((UINT32 *)(_Base) + (_Register), (_Value))
  32. //
  33. // These macros read from and write to the watchdog timer.
  34. //
  35. #define OMAP4_READ_WATCHDOG(_Register) \
  36. EfiReadRegister32((VOID *)OMAP4430_WATCHDOG2_BASE + (_Register))
  37. #define OMAP4_WRITE_WATCHDOG(_Register, _Value) \
  38. EfiWriteRegister32((VOID *)OMAP4430_WATCHDOG2_BASE + (_Register), (_Value))
  39. //
  40. // ---------------------------------------------------------------- Definitions
  41. //
  42. #define OMAP4_WATCHDOG_FREQUENCY 32768
  43. //
  44. // Define the number of 32kHz clock ticks per interrupt. A value of 512 creates
  45. // a timer rate of 15.625ms, or about 64 interrupts per second.
  46. //
  47. #define PANDA_BOARD_TIMER_TICK_COUNT 512
  48. //
  49. // Define the offset between the standard register offsets and the alternates.
  50. //
  51. #define OMAP4_TIMER_ALTERATE_REGISTER_OFFSET 5
  52. //
  53. // Idle bits.
  54. //
  55. #define GPTIMER_IDLEMODE_NOIDLE 0x00000080
  56. //
  57. // Mode bits.
  58. //
  59. #define GPTIMER_STARTED 0x00000001
  60. #define GPTIMER_OVERFLOW_TRIGGER 0x00000400
  61. #define GPTIMER_OVERFLOW_AND_MATCH_TRIGGER 0x00000800
  62. #define GPTIMER_COMPARE_ENABLED 0x00000040
  63. #define GPTIMER_AUTORELOAD 0x00000002
  64. //
  65. // Interrupt enable bits.
  66. //
  67. #define GPTIMER_MATCH_INTERRUPT 0x00000001
  68. #define GPTIMER_OVERFLOW_INTERRUPT 0x00000002
  69. //
  70. // Define the two step sequence needed for disabling or enabling the watchdog
  71. // timer.
  72. //
  73. #define OMAP4_WATCHDOG_DISABLE1 0x0000AAAA
  74. #define OMAP4_WATCHDOG_DISABLE2 0x00005555
  75. #define OMAP4_WATCHDOG_ENABLE1 0x0000BBBB
  76. #define OMAP4_WATCHDOG_ENABLE2 0x00004444
  77. //
  78. // ------------------------------------------------------ Data Type Definitions
  79. //
  80. //
  81. // Define the GP timer register set, with offsets in UINT32s. This is a bit
  82. // confusing because on the OMAP4 there are two different (but very similar)
  83. // register sets depending on the timer. Starting with the Wakeup register
  84. // they're simply off by a fixed offset. Before then, they're slightly
  85. // different. The alternate registers (for GPTIMERs 3-9 and 11) are interleaved
  86. // here with the standard ones. The values here have also already taken into
  87. // account the fact that an offset is going to be added, so that alternate
  88. // ones are 5 ULONGs shy of their actual register offsets (the fixed offset
  89. // once things get back in sync).
  90. //
  91. typedef enum _GP_TIMER_REGISTER {
  92. GpTimerRevision = 0x00, // GPT_TIDR
  93. GpTimerInterfaceConfiguration1 = 0x04, // GPT1MS_TIOCP_CFG
  94. GpTimerRawInterruptStatus = 0x04, // GPT_IRQSTATUS_RAW
  95. GpTimerStatus = 0x05, // GPT_TISTAT
  96. GpTimerInterruptStatusAlternate = 0x05, // GPT_IRQSTATUS
  97. GpTimerInterruptStatus = 0x06, // GPT_TISR
  98. GpTimerInterruptEnableAlternate = 0x06, // GPT_IRQENABLE_SET
  99. GpTimerInterruptEnable = 0x07, // GPT_TIER
  100. GpTimerInterruptDisable = 0x07, // GPT_IRQENABLE_CLR
  101. GpTimerWakeup = 0x08, // GPT_TWER
  102. GpTimerMode = 0x09, // GPT_TCLR
  103. GpTimerCurrentCount = 0x0A, // GPT_TCRR
  104. GpTimerLoadCount = 0x0B, // GPT_TLDR
  105. GpTimerTriggerReload = 0x0C, // GPT_TTGR
  106. GpTimerWritePending = 0x0D, // GPT_TWPS
  107. GpTimerMatchCount = 0x0E, // GPT_TMAR
  108. GpTimerCapture1 = 0x0F, // GPT_TCAR1
  109. GpTimerInterfaceConfiguration2 = 0x10, // GPT_TSICR
  110. GpTimerCapture2 = 0x11, // GPT_TCAR2
  111. GpTimerPositive1msIncrement = 0x12, // GPT_TPIR
  112. GpTimerNegative1msIncrement = 0x13, // GPT_TNIR
  113. GpTimerCurrentRounding1ms = 0x14, // GPT_TCVR
  114. GpTimerOverflowValue = 0x16, // GPT_TOCR
  115. GpTimerMaskedOverflowCount = 0x17, // GPT_TOWR
  116. } GP_TIMER_REGISTER, *PGP_TIMER_REGISTER;
  117. //
  118. // Define the watchdog timer registers, offsets in bytes.
  119. //
  120. typedef enum _OMAP4_WATCHDOG_REGISTER {
  121. Omap4WatchdogRevision = 0x00,
  122. Omap4WatchdogInterfaceConfiguration = 0x10,
  123. Omap4WatchdogInterfaceStatus = 0x14,
  124. Omap4WatchdogInterruptStatus = 0x18,
  125. Omap4WatchdogInterruptEnable = 0x1C,
  126. Omap4WatchdogWakeEventEnable = 0x20,
  127. Omap4WatchdogPrescaler = 0x24,
  128. Omap4WatchdogCurrentCount = 0x28,
  129. Omap4WatchdogLoadCount = 0x2C,
  130. Omap4WatchdogWritePostControl = 0x34,
  131. Omap4WatchdogDelay = 0x44,
  132. Omap4WatchdogStartStop = 0x48,
  133. Omap4WatchdogRawInterruptStatus = 0x54,
  134. Omap4WatchdogInterruptEnableSet = 0x5C,
  135. Omap4WatchdogInterruptEnableClear = 0x60,
  136. Omap4WatchdogWakeEnable = 0x64
  137. } OMAP4_WATCHDOG_REGISTER, *POMAP4_WATCHDOG_REGISTER;
  138. /*++
  139. Structure Description:
  140. This structure stores the internal state associated with an OMAP4 GP
  141. timer.
  142. Members:
  143. Base - Stores the virtual address of the timer.
  144. Index - Stores the zero-based index of this timer within the timer block.
  145. Offset - Stores the offset, in ULONGs, that should be applied to every
  146. register access because the timer is using the alternate register
  147. definitions.
  148. --*/
  149. typedef struct _GP_TIMER_DATA {
  150. UINT32 *Base;
  151. UINT32 Index;
  152. UINT32 Offset;
  153. } GP_TIMER_DATA, *PGP_TIMER_DATA;
  154. //
  155. // ----------------------------------------------- Internal Function Prototypes
  156. //
  157. VOID
  158. EfipPlatformServiceTimerInterrupt (
  159. UINT32 InterruptNumber
  160. );
  161. UINT64
  162. EfipPlatformReadTimer (
  163. VOID
  164. );
  165. VOID
  166. EfipOmap4TimerInitialize (
  167. PGP_TIMER_DATA Context
  168. );
  169. UINT64
  170. EfipOmap4TimerRead (
  171. PGP_TIMER_DATA Context
  172. );
  173. VOID
  174. EfipOmap4TimerArm (
  175. PGP_TIMER_DATA Context,
  176. BOOLEAN Periodic,
  177. UINT64 TickCount
  178. );
  179. VOID
  180. EfipOmap4TimerDisarm (
  181. PGP_TIMER_DATA Context
  182. );
  183. VOID
  184. EfipOmap4TimerAcknowledgeInterrupt (
  185. PGP_TIMER_DATA Context
  186. );
  187. //
  188. // -------------------------------------------------------------------- Globals
  189. //
  190. GP_TIMER_DATA EfiPandaClockTimer;
  191. GP_TIMER_DATA EfiPandaTimeCounter;
  192. //
  193. // ------------------------------------------------------------------ Functions
  194. //
  195. EFIAPI
  196. EFI_STATUS
  197. EfiPlatformSetWatchdogTimer (
  198. UINTN Timeout,
  199. UINT64 WatchdogCode,
  200. UINTN DataSize,
  201. CHAR16 *WatchdogData
  202. )
  203. /*++
  204. Routine Description:
  205. This routine sets the system's watchdog timer.
  206. Arguments:
  207. Timeout - Supplies the number of seconds to set the timer for.
  208. WatchdogCode - Supplies a numeric code to log on a watchdog timeout event.
  209. DataSize - Supplies the size of the watchdog data.
  210. WatchdogData - Supplies an optional buffer that includes a null-terminated
  211. string, optionally followed by additional binary data.
  212. Return Value:
  213. EFI_SUCCESS on success.
  214. EFI_INVALID_PARAMETER if the supplied watchdog code is invalid.
  215. EFI_UNSUPPORTED if there is no watchdog timer.
  216. EFI_DEVICE_ERROR if an error occurred accessing the device hardware.
  217. --*/
  218. {
  219. UINT32 Count;
  220. Count = 0 - (Timeout * OMAP4_WATCHDOG_FREQUENCY);
  221. //
  222. // First, disable the watchdog timer.
  223. //
  224. OMAP4_WRITE_WATCHDOG(Omap4WatchdogStartStop, OMAP4_WATCHDOG_DISABLE1);
  225. EfiStall(1000);
  226. OMAP4_WRITE_WATCHDOG(Omap4WatchdogStartStop, OMAP4_WATCHDOG_DISABLE2);
  227. EfiStall(1000);
  228. //
  229. // If the watchdog timer is being enabled, set the count value and fire it
  230. // back up.
  231. //
  232. if ((Count != 0) && (EfiDisableWatchdog == FALSE)) {
  233. OMAP4_WRITE_WATCHDOG(Omap4WatchdogLoadCount, Count);
  234. EfiStall(1000);
  235. OMAP4_WRITE_WATCHDOG(Omap4WatchdogCurrentCount, Count);
  236. EfiStall(1000);
  237. OMAP4_WRITE_WATCHDOG(Omap4WatchdogStartStop, OMAP4_WATCHDOG_ENABLE1);
  238. EfiStall(1000);
  239. OMAP4_WRITE_WATCHDOG(Omap4WatchdogStartStop, OMAP4_WATCHDOG_ENABLE2);
  240. }
  241. return EFI_SUCCESS;
  242. }
  243. EFI_STATUS
  244. EfiPlatformInitializeTimers (
  245. UINT32 *ClockTimerInterruptNumber,
  246. EFI_PLATFORM_SERVICE_TIMER_INTERRUPT *ClockTimerServiceRoutine,
  247. EFI_PLATFORM_READ_TIMER *ReadTimerRoutine,
  248. UINT64 *ReadTimerFrequency,
  249. UINT32 *ReadTimerWidth
  250. )
  251. /*++
  252. Routine Description:
  253. This routine initializes platform timer services. There are actually two
  254. different timer services returned in this routine. The periodic timer tick
  255. provides a periodic interrupt. The read timer provides a free running
  256. counter value. These are likely serviced by different timers. For the
  257. periodic timer tick, this routine should start the periodic interrupts
  258. coming in. The periodic rate of the timer can be anything reasonable, as
  259. the time counter will be used to count actual duration. The rate should be
  260. greater than twice the rollover rate of the time counter to ensure proper
  261. time accounting. Interrupts are disabled at the processor core for the
  262. duration of this routine.
  263. Arguments:
  264. ClockTimerInterruptNumber - Supplies a pointer where the interrupt line
  265. number of the periodic timer tick will be returned.
  266. ClockTimerServiceRoutine - Supplies a pointer where a pointer to a routine
  267. called when the periodic timer tick interrupt occurs will be returned.
  268. ReadTimerRoutine - Supplies a pointer where a pointer to a routine
  269. called to read the current timer value will be returned.
  270. ReadTimerFrequency - Supplies the frequency of the counter.
  271. ReadTimerWidth - Supplies a pointer where the read timer bit width will be
  272. returned.
  273. Return Value:
  274. EFI Status code.
  275. --*/
  276. {
  277. EFI_STATUS Status;
  278. *ClockTimerInterruptNumber = OMAP4430_IRQ_GPTIMER2;
  279. *ClockTimerServiceRoutine = EfipPlatformServiceTimerInterrupt;
  280. *ReadTimerRoutine = EfipPlatformReadTimer;
  281. *ReadTimerFrequency = OMAP4430_32KHZ_FREQUENCY;
  282. *ReadTimerWidth = 32;
  283. //
  284. // Use GP timer 2 for the clock timer and GP timer 3 for the time counter.
  285. // Both run at 32kHz.
  286. //
  287. EfiPandaClockTimer.Base = (VOID *)OMAP4430_GPTIMER2_BASE;
  288. EfiPandaClockTimer.Index = 1;
  289. EfiPandaClockTimer.Offset = 0;
  290. EfiPandaTimeCounter.Base = (VOID *)OMAP4430_GPTIMER3_BASE;
  291. EfiPandaTimeCounter.Index = 2;
  292. EfiPandaTimeCounter.Offset = OMAP4_TIMER_ALTERATE_REGISTER_OFFSET;
  293. EfipOmap4TimerInitialize(&EfiPandaClockTimer);
  294. EfipOmap4TimerArm(&EfiPandaClockTimer, TRUE, PANDA_BOARD_TIMER_TICK_COUNT);
  295. EfipOmap4TimerInitialize(&EfiPandaTimeCounter);
  296. Status = EfipPlatformSetInterruptLineState(*ClockTimerInterruptNumber,
  297. TRUE,
  298. FALSE);
  299. return Status;
  300. }
  301. VOID
  302. EfiPlatformTerminateTimers (
  303. VOID
  304. )
  305. /*++
  306. Routine Description:
  307. This routine terminates timer services in preparation for the termination
  308. of boot services.
  309. Arguments:
  310. None.
  311. Return Value:
  312. None.
  313. --*/
  314. {
  315. EfipOmap4TimerDisarm(&EfiPandaClockTimer);
  316. return;
  317. }
  318. //
  319. // --------------------------------------------------------- Internal Functions
  320. //
  321. VOID
  322. EfipPlatformServiceTimerInterrupt (
  323. UINT32 InterruptNumber
  324. )
  325. /*++
  326. Routine Description:
  327. This routine is called to acknowledge a platform timer interrupt. This
  328. routine is responsible for quiescing the interrupt.
  329. Arguments:
  330. InterruptNumber - Supplies the interrupt number that occurred.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. EfipOmap4TimerAcknowledgeInterrupt(&EfiPandaClockTimer);
  336. return;
  337. }
  338. UINT64
  339. EfipPlatformReadTimer (
  340. VOID
  341. )
  342. /*++
  343. Routine Description:
  344. This routine is called to read the current platform time value. The timer
  345. is assumed to be free running at a constant frequency, and should have a
  346. bit width as reported in the initialize function. The UEFI core will
  347. manage software bit extension out to 64 bits, this routine should just
  348. reporte the hardware timer value.
  349. Arguments:
  350. None.
  351. Return Value:
  352. Returns the hardware timer value.
  353. --*/
  354. {
  355. return EfipOmap4TimerRead(&EfiPandaTimeCounter);
  356. }
  357. VOID
  358. EfipOmap4TimerInitialize (
  359. PGP_TIMER_DATA Context
  360. )
  361. /*++
  362. Routine Description:
  363. This routine initializes an OMAP4 timer.
  364. Arguments:
  365. Context - Supplies the pointer to the timer's context.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. UINT32 Value;
  371. if (Context->Base == NULL) {
  372. return;
  373. }
  374. //
  375. // Program the timer in free running mode with no interrupt. Set the
  376. // interface configuration to a state that disables going idle. This is
  377. // the only register that does not change at all between the standard
  378. // and alternate interface.
  379. //
  380. WRITE_TIMER_REGISTER(Context->Base,
  381. GpTimerInterfaceConfiguration1,
  382. GPTIMER_IDLEMODE_NOIDLE);
  383. //
  384. // Disable wakeup functionality.
  385. //
  386. WRITE_TIMER_REGISTER(Context->Base + Context->Offset, GpTimerWakeup, 0);
  387. //
  388. // Set the second interface configuration register to non-posted mode,
  389. // which means that writes don't return until they complete. Posted mode
  390. // is faster for writes but requires polling a bit for reads.
  391. //
  392. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  393. GpTimerInterfaceConfiguration2,
  394. 0);
  395. //
  396. // Disable all interrupts for now. The alternate register interface uses a
  397. // set/clear style for the interrupt mask bits.
  398. //
  399. if (Context->Offset == 0) {
  400. WRITE_TIMER_REGISTER(Context->Base, GpTimerInterruptEnable, 0);
  401. } else {
  402. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  403. GpTimerInterruptDisable,
  404. 0x7);
  405. }
  406. //
  407. // Set the load value to zero to create a free-running timer, and reset the
  408. // current counter now too.
  409. //
  410. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  411. GpTimerLoadCount,
  412. 0x00000000);
  413. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  414. GpTimerCurrentCount,
  415. 0x00000000);
  416. //
  417. // Set the mode register to auto-reload, and start the timer.
  418. //
  419. Value = GPTIMER_OVERFLOW_TRIGGER | GPTIMER_STARTED | GPTIMER_AUTORELOAD;
  420. WRITE_TIMER_REGISTER(Context->Base + Context->Offset, GpTimerMode, Value);
  421. //
  422. // Reset all interrupt-pending bits. This register has a unique offset
  423. // in the alternate interface.
  424. //
  425. if (Context->Offset == 0) {
  426. WRITE_TIMER_REGISTER(Context->Base, GpTimerInterruptStatus, 0x7);
  427. } else {
  428. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  429. GpTimerInterruptStatusAlternate,
  430. 0x7);
  431. }
  432. return;
  433. }
  434. UINT64
  435. EfipOmap4TimerRead (
  436. PGP_TIMER_DATA Context
  437. )
  438. /*++
  439. Routine Description:
  440. This routine returns the hardware counter's raw value.
  441. Arguments:
  442. Context - Supplies the pointer to the timer's context.
  443. Return Value:
  444. Returns the timer's current count.
  445. --*/
  446. {
  447. UINT32 Value;
  448. Value = READ_TIMER_REGISTER(Context->Base + Context->Offset,
  449. GpTimerCurrentCount);
  450. return Value;
  451. }
  452. VOID
  453. EfipOmap4TimerArm (
  454. PGP_TIMER_DATA Context,
  455. BOOLEAN Periodic,
  456. UINT64 TickCount
  457. )
  458. /*++
  459. Routine Description:
  460. This routine arms the timer to fire an interrupt after the specified number
  461. of ticks.
  462. Arguments:
  463. Context - Supplies the pointer to the timer's context.
  464. Periodic - Supplies a boolean indicating if the timer should be armed
  465. periodically or one-shot.
  466. TickCount - Supplies the interval, in ticks, from now for the timer to fire
  467. in.
  468. Return Value:
  469. None.
  470. --*/
  471. {
  472. UINT32 Value;
  473. if (TickCount >= 0xFFFFFFFF) {
  474. TickCount = 0xFFFFFFFF;
  475. }
  476. //
  477. // Start the timer ticking.
  478. //
  479. WRITE_TIMER_REGISTER(Context->Base + Context->Offset, GpTimerMode, 0);
  480. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  481. GpTimerLoadCount,
  482. 0xFFFFFFFF - (UINT32)TickCount);
  483. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  484. GpTimerCurrentCount,
  485. 0xFFFFFFFF - (UINT32)TickCount);
  486. Value = GPTIMER_STARTED;
  487. if (Periodic != FALSE) {
  488. Value |= GPTIMER_AUTORELOAD;
  489. }
  490. WRITE_TIMER_REGISTER(Context->Base + Context->Offset, GpTimerMode, Value);
  491. if (Context->Offset == 0) {
  492. WRITE_TIMER_REGISTER(Context->Base,
  493. GpTimerInterruptEnable,
  494. GPTIMER_OVERFLOW_INTERRUPT);
  495. } else {
  496. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  497. GpTimerInterruptEnableAlternate,
  498. GPTIMER_OVERFLOW_INTERRUPT);
  499. }
  500. return;
  501. }
  502. VOID
  503. EfipOmap4TimerDisarm (
  504. PGP_TIMER_DATA Context
  505. )
  506. /*++
  507. Routine Description:
  508. This routine disarms the timer, stopping interrupts from firing.
  509. Arguments:
  510. Context - Supplies the pointer to the timer's context.
  511. Return Value:
  512. None.
  513. --*/
  514. {
  515. //
  516. // Disable all interrupts. The alternate register interface uses a
  517. // set/clear style for the interrupt mask bits.
  518. //
  519. if (Context->Offset == 0) {
  520. WRITE_TIMER_REGISTER(Context->Base, GpTimerInterruptEnable, 0);
  521. } else {
  522. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  523. GpTimerInterruptDisable,
  524. 0x7);
  525. }
  526. //
  527. // Reset all interrupt-pending bits. This register has a unique offset
  528. // in the alternate interface.
  529. //
  530. if (Context->Offset == 0) {
  531. WRITE_TIMER_REGISTER(Context->Base, GpTimerInterruptStatus, 0x7);
  532. } else {
  533. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  534. GpTimerInterruptStatusAlternate,
  535. 0x7);
  536. }
  537. return;
  538. }
  539. VOID
  540. EfipOmap4TimerAcknowledgeInterrupt (
  541. PGP_TIMER_DATA Context
  542. )
  543. /*++
  544. Routine Description:
  545. This routine performs any actions necessary upon reciept of a timer's
  546. interrupt. This may involve writing to an acknowledge register to re-enable
  547. the timer to fire again, or other hardware specific actions.
  548. Arguments:
  549. Context - Supplies the pointer to the timer's context.
  550. Return Value:
  551. None.
  552. --*/
  553. {
  554. //
  555. // Clear the overflow interrupt by writing a 1 to the status bit.
  556. //
  557. if (Context->Offset == 0) {
  558. WRITE_TIMER_REGISTER(Context->Base,
  559. GpTimerInterruptStatus,
  560. GPTIMER_OVERFLOW_INTERRUPT);
  561. } else {
  562. WRITE_TIMER_REGISTER(Context->Base + Context->Offset,
  563. GpTimerInterruptStatusAlternate,
  564. GPTIMER_OVERFLOW_INTERRUPT);
  565. }
  566. return;
  567. }