@@---------------------------------------------------------------
@@ Cortex A series Generic Timer APIs
@@
@@---------------------------------------------------------------


  @PRESERVE8

  .text

  .code 32

  .equ  MODE_MON, 0x16

@ ------------------------------------------------------------
@ Generic Timer Global Counter Frequency Register
@ ------------------------------------------------------------

  .global GTimer_getCounterFrequency
  @ Returns the value of generic timer global counter frequency
  @ unsigned int GTimer_getCounterFrequency(void)
GTimer_getCounterFrequency:
  MRC     p15, #0, r0, c14, c0, #0 @ Read CNTFRQ Register
  BX      lr
#if 0
  .global GTimer_setCounterFrequency
  @ Set and return the number of generic timer global counter frequency
  @ unsigned int GTimer_setCounterFrequency(unsigned int frequency)
  @ frequency (in r0) = The frequency to program 
  @ 0xFFFFFFFF (in r0) = The fail return with error 
GTimer_setCounterFrequency:
  MRS     r2, CPSR                 @ Get the CPSR value
  BIC     r2, r2, #0xFFFFFFE0      @ Only keep bit4:0
  TST     r2, #MODE_MON             @ Check whether the mode is Monitor or not
  BNE     fail                     @ This register can only be written in the secure status
  MCR     p15, #0, r0, c14, c0, #0 @ Write CNTFRQ Register
  MRC     p15, #0, r0, c14, c0, #0 @ Read CNTFRQ Register
  BX      lr
fail:                              @ Exit with returning the error value
  MOV     r0,  #0xFFFFFFFF
  BX      lr
#endif  
@ ------------------------------------------------------------
@ Generic Timer Global Physical Counter Register
@ ------------------------------------------------------------
 
  .global GTimer_getPhysicalCounter
  @ Returns the value of generic timer Physical Counter Register
  @ long long GTimer_getPhysicalCounter(void)
  @ Return word 0 (in r0) = The lower 32-bit physical counter 
  @ Return word 0 (in r1) = The higher 32-bit physical counter 

GTimer_getPhysicalCounter:
  MRRC    p15, #0, r0, r1, c14 @ Read 64-bit CNTPCT Register
  BX      lr
  
@ ------------------------------------------------------------
@ Generic Timer PL1 Physical Timer
@ ------------------------------------------------------------

  .global GTimer_getPL1PhyTmrCtrl
  @ Returns the value of generic timer PL1 physical timer control regitser
  @ unsigned int GTimer_getPL1PhyTmrCtrl(void)
  @ Return word (in r0) = The value of CNTP_CTL Register 
  
GTimer_getPL1PhyTmrCtrl:
  MRC     p15, #0, r0, c14, c2, #1 @ Read CNTP_CTL Register
  BX      lr

  .global GTimer_setPL1PhyTmrCtrl
  @ Set generic timer PL1 physical timer control regitser
  @ void GTimer_setPL1PhyTmrCtrl(unsigned int imask, unsigned int enable)
  @ imask (in r0) = The interrupt mask settings
  @ enable (in r1) = The enable settings
  
GTimer_setPL1PhyTmrCtrl:
  MRC     p15, #0, r2, c14, c2, #1 @ Read CNTP_CTL Register
  BIC     r2,  r2, #0x2            @ Clear the imask bit
  LSL     r0,  r0, #1
  ORR     r2,  r2, r0              @ OR the imask settings
  BIC     r2,  r2, #0x1            @ Clear the Enable bit
  ORR     r2,  r2, r1              @ OR the Enable settings
  MCR     p15, #0, r2, c14, c2, #1 @ Write CNTP_CTL Register
  BX      lr

  .global GTimer_getPL1PhyTmrTmrValue
  @ Returns the value of generic timer PL1 physical timer Timer Value regitser
  @ unsigned int GTimer_getPL1PhyTmrTmrValue(void)
  @ Return word (in r0) = The value of CNTP_TVAL Register 
  @ Reads TimerValue = (CompareValue ¨C (Counter - Offset))[31:0]
  
GTimer_getPL1PhyTmrTmrValue:
  MRC     p15, #0, r0, c14, c2, #0 @ Read CNTP_TVAL Register
  BX      lr

  .global GTimer_setPL1PhyTmrTmrValue
  @ Set the value of generic timer PL1 physical timer Timer Value regitser
  @ void GTimer_setPL1PhyTmrTmrValue(unsigned int tVal)
  @ tVal (in r0) = The set value for CNTP_TVAL Register
  @ Writes CompareValue = ((Counter - Offset)[63:0] + SignExtend(TimerValue))[63:0]
   
GTimer_setPL1PhyTmrTmrValue:
  MCR     p15, #0, r0, c14, c2, #0 @ write CNTP_TVAL Register
  BX      lr

  .global GTimer_getPL1PhyTmrCmpValue
  @ Returns the value of generic timer PL1 physical timer Compare Value regitser
  @ long long GTimer_getPL1PhyTmrCmpValue(void)
  @ Return word 0 (in r0) = The lower 32-bit PL1 physical timer Compare Value regitser 
  @ Return word 0 (in r1) = The higher 32-bit PL1 physical timer Compare Value regitser 
  
GTimer_getPL1PhyTmrCmpValue:
  MRRC    p15, #2, r0, r1, c14 @ Read 64-bit CNTP_CVAL Register
  BX      lr

  .global GTimer_SetPL1PhyTmrCmpValue
  @ Set the value of generic timer PL1 physical timer Compare Value regitser
  @ void GTimer_setPL1PhyTmrCmpValue(unsigned int lo, unsigned int hi)
  @ lo (in r0) = The expected lower 32-bit PL1 physical timer Compare Value regitser 
  @ hi (in r1) = The expected higher 32-bit PL1 physical timer Compare Value regitser 
    
GTimer_setPL1PhyTmrCmpValue:
  MCRR    p15, #2, r0, r1, c14 @ Write 64-bit CNTP_CVAL Register
  BX      lr

