timer.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. timer.c
  5. Abstract:
  6. This module implements support for the BCM2709 timer services.
  7. Author:
  8. Chris Stevens 18-Mar-2015
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <uefifw.h>
  16. #include <dev/bcm2709.h>
  17. //
  18. // --------------------------------------------------------------------- Macros
  19. //
  20. //
  21. // This macro reads from a BCM2709 ARM timer.
  22. //
  23. #define READ_ARM_TIMER_REGISTER(_Register) \
  24. EfiReadRegister32(BCM2709_ARM_TIMER_BASE + (_Register))
  25. //
  26. // This macro writes to a BCM2709 ARM timer.
  27. //
  28. #define WRITE_ARM_TIMER_REGISTER(_Register, _Value) \
  29. EfiWriteRegister32(BCM2709_ARM_TIMER_BASE + (_Register), (_Value))
  30. //
  31. // This macro reads from a BCM2709 System timer.
  32. //
  33. #define READ_SYSTEM_TIMER_REGISTER(_Register) \
  34. EfiReadRegister32(BCM2709_SYSTEM_TIMER_BASE + (_Register))
  35. //
  36. // This macro writes to a BCM2709 System timer.
  37. //
  38. #define WRITE_SYSTEM_TIMER_REGISTER(_Register, _Value) \
  39. EfiWriteRegister32(BCM2709_SYSTEM_TIMER_BASE + (_Register), (_Value))
  40. //
  41. // ---------------------------------------------------------------- Definitions
  42. //
  43. //
  44. // ------------------------------------------------------ Data Type Definitions
  45. //
  46. //
  47. // ----------------------------------------------- Internal Function Prototypes
  48. //
  49. //
  50. // -------------------------------------------------------------------- Globals
  51. //
  52. //
  53. // ------------------------------------------------------------------ Functions
  54. //
  55. EFI_STATUS
  56. EfipBcm2709TimerInitialize (
  57. PBCM2709_TIMER Timer
  58. )
  59. /*++
  60. Routine Description:
  61. This routine initializes a BCM2709 timer.
  62. Arguments:
  63. Timer - Supplies the pointer to the timer data.
  64. Return Value:
  65. Status code.
  66. --*/
  67. {
  68. UINT32 ControlValue;
  69. //
  70. // The BCM2709 device library must be initialized first.
  71. //
  72. if (EfiBcm2709Initialized == FALSE) {
  73. return EFI_NOT_READY;
  74. }
  75. //
  76. // Program the default timer with no interrupt generation. There is nothing
  77. // to be done for the System Timer's free-running counter. It is already
  78. // enabled.
  79. //
  80. if (Timer->ClockTimer != FALSE) {
  81. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerPredivider, Timer->Predivider);
  82. ControlValue = READ_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl);
  83. ControlValue &= ~BCM2709_ARM_TIMER_CONTROL_INTERRUPT_ENABLE;
  84. ControlValue |= (BCM2709_ARM_TIMER_CONTROL_ENABLED |
  85. BCM2709_ARM_TIMER_CONTROL_DIVIDE_BY_1 |
  86. BCM2709_ARM_TIMER_CONTROL_32_BIT);
  87. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl, ControlValue);
  88. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerInterruptClear, 1);
  89. }
  90. return EFI_SUCCESS;
  91. }
  92. UINT64
  93. EfipBcm2709TimerRead (
  94. PBCM2709_TIMER Timer
  95. )
  96. /*++
  97. Routine Description:
  98. This routine returns the hardware counter's raw value.
  99. Arguments:
  100. Timer - Supplies the pointer to the timer data.
  101. Return Value:
  102. Returns the timer's current count.
  103. --*/
  104. {
  105. UINT32 Value;
  106. if (Timer->ClockTimer != FALSE) {
  107. Value = 0xFFFFFFFF;
  108. Value -= READ_ARM_TIMER_REGISTER(Bcm2709ArmTimerCurrentValue);
  109. } else {
  110. Value = READ_SYSTEM_TIMER_REGISTER(Bcm2709SystemTimerCounterLow);
  111. }
  112. return Value;
  113. }
  114. VOID
  115. EfipBcm2709TimerArm (
  116. PBCM2709_TIMER Timer,
  117. UINT64 TickCount
  118. )
  119. /*++
  120. Routine Description:
  121. This routine arms the timer to fire an interrupt after the specified number
  122. of ticks.
  123. Arguments:
  124. Timer - Supplies the pointer to the timer data.
  125. Periodic - Supplies a boolean indicating if the timer should be armed
  126. periodically or one-shot.
  127. TickCount - Supplies the interval, in ticks, from now for the timer to fire
  128. in.
  129. Return Value:
  130. None.
  131. --*/
  132. {
  133. UINT32 ControlValue;
  134. if (Timer->ClockTimer == FALSE) {
  135. return;
  136. }
  137. //
  138. // Set up the control value to program.
  139. //
  140. ControlValue = READ_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl);
  141. ControlValue |= (BCM2709_ARM_TIMER_CONTROL_ENABLED |
  142. BCM2709_ARM_TIMER_CONTROL_DIVIDE_BY_1 |
  143. BCM2709_ARM_TIMER_CONTROL_32_BIT |
  144. BCM2709_ARM_TIMER_CONTROL_INTERRUPT_ENABLE);
  145. //
  146. // Set the timer to its maximum value, set the configuration, clear the
  147. // interrupt, then set the value.
  148. //
  149. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerLoadValue, 0xFFFFFFFF);
  150. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl, ControlValue);
  151. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerInterruptClear, 1);
  152. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerLoadValue, TickCount);
  153. return;
  154. }
  155. VOID
  156. EfipBcm2709TimerDisarm (
  157. PBCM2709_TIMER Timer
  158. )
  159. /*++
  160. Routine Description:
  161. This routine disarms the timer, stopping interrupts from firing.
  162. Arguments:
  163. Timer - Supplies the pointer to the timer data.
  164. Return Value:
  165. None.
  166. --*/
  167. {
  168. UINT32 ControlValue;
  169. if (Timer->ClockTimer == FALSE) {
  170. return;
  171. }
  172. //
  173. // Disable the timer by programming it with no interrupt generation.
  174. //
  175. ControlValue = READ_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl);
  176. ControlValue &= ~BCM2709_ARM_TIMER_CONTROL_INTERRUPT_ENABLE;
  177. ControlValue |= (BCM2709_ARM_TIMER_CONTROL_ENABLED |
  178. BCM2709_ARM_TIMER_CONTROL_DIVIDE_BY_1 |
  179. BCM2709_ARM_TIMER_CONTROL_32_BIT);
  180. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerControl, ControlValue);
  181. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerInterruptClear, 1);
  182. return;
  183. }
  184. VOID
  185. EfipBcm2709TimerAcknowledgeInterrupt (
  186. PBCM2709_TIMER Timer
  187. )
  188. /*++
  189. Routine Description:
  190. This routine performs any actions necessary upon reciept of a timer's
  191. interrupt. This may involve writing to an acknowledge register to re-enable
  192. the timer to fire again, or other hardware specific actions.
  193. Arguments:
  194. Timer - Supplies the pointer to the timer data.
  195. Return Value:
  196. None.
  197. --*/
  198. {
  199. if (Timer->ClockTimer == FALSE) {
  200. return;
  201. }
  202. WRITE_ARM_TIMER_REGISTER(Bcm2709ArmTimerInterruptClear, 1);
  203. return;
  204. }
  205. //
  206. // --------------------------------------------------------- Internal Functions
  207. //