github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/arm/timer.go (about)

     1  // ARM processor support
     2  // https://github.com/usbarmory/tamago
     3  //
     4  // Copyright (c) WithSecure Corporation
     5  // https://foundry.withsecure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package arm
    11  
    12  import (
    13  	"github.com/usbarmory/tamago/internal/reg"
    14  )
    15  
    16  // ARM timer register constants
    17  const (
    18  	// p2402, Table D5-1, ARMv7 Architecture Reference Manual
    19  	CNTCR = 0
    20  	// base frequency
    21  	CNTFID0 = 0x20
    22  
    23  	// p2410, D5.7.2 CNTCR, Counter Control Register, ARMv7 Architecture
    24  	// Reference Manual
    25  	//
    26  	// frequency = CNTFID0/CNTFID2
    27  	CNTCR_FCREQ2 = 10
    28  	// frequency = CNTFID0/CNTFID1
    29  	CNTCR_FCREQ1 = 9
    30  	// frequency = CNTFID0
    31  	CNTCR_FCREQ0 = 8
    32  	CNTCR_HDBG   = 1
    33  	CNTCR_EN     = 0
    34  
    35  	CNTKCTL_PL0PCTEN = 0
    36  
    37  	// nanoseconds
    38  	refFreq int64 = 1000000000
    39  )
    40  
    41  // defined in timer_arm.s
    42  func read_gtc() int64
    43  func read_cntfrq() int32
    44  func write_cntfrq(freq int32)
    45  func write_cntkctl(val uint32)
    46  func read_cntpct() int64
    47  func write_cntptval(val int32, enable bool)
    48  
    49  // Busyloop spins the processor for busy waiting purposes, taking a counter
    50  // value for the number of loops.
    51  func Busyloop(count int32)
    52  
    53  // InitGlobalTimers initializes ARM Cortex-A9 timers.
    54  func (cpu *CPU) InitGlobalTimers() {
    55  	cpu.TimerFn = read_gtc
    56  	cpu.TimerMultiplier = 10
    57  }
    58  
    59  // InitGenericTimers initializes ARM Cortex-A7 timers.
    60  func (cpu *CPU) InitGenericTimers(base uint32, freq int32) {
    61  	var timerFreq int64
    62  
    63  	if freq != 0 && cpu.Secure() {
    64  		// set base frequency
    65  		write_cntfrq(freq)
    66  
    67  		if base != 0 {
    68  			reg.Write(base+CNTFID0, uint32(freq))
    69  
    70  			// set system counter to base frequency
    71  			reg.Set(base+CNTCR, CNTCR_FCREQ0)
    72  			// stop system counter on debug
    73  			reg.Set(base+CNTCR, CNTCR_HDBG)
    74  			// start system counter
    75  			reg.Set(base+CNTCR, CNTCR_EN)
    76  		}
    77  
    78  		// grant PL0 access
    79  		write_cntkctl(1 << CNTKCTL_PL0PCTEN)
    80  	}
    81  
    82  	timerFreq = int64(read_cntfrq())
    83  
    84  	cpu.TimerMultiplier = int64(refFreq / timerFreq)
    85  	cpu.TimerFn = read_cntpct
    86  }
    87  
    88  // SetTimer sets the timer to the argument nanoseconds value.
    89  func (cpu *CPU) SetTimer(t int64) {
    90  	if cpu.TimerFn == nil || cpu.TimerMultiplier == 0 {
    91  		return
    92  	}
    93  
    94  	cpu.TimerOffset = t - int64(cpu.TimerFn()*cpu.TimerMultiplier)
    95  }
    96  
    97  // SetDownCounter sets a physical countdown timer.
    98  func (cpu *CPU) SetDownCounter(t int32, enable bool) {
    99  	write_cntptval(t, enable)
   100  }