// Copyright 2016 The Periph Authors. All rights reserved. // Use of this source code is governed under the Apache License, Version 2.0 // that can be found in the LICENSE file. package allwinner import ( "time" "periph.io/x/host/v3/cpu" ) // ReadTime returns the time on a monotonic timer. // // It only works if allwinner-dma successfully loaded. Otherwise it returns 0. func ReadTime() time.Duration { if drvDMA.timerMemory == nil { return 0 } v := uint64(drvDMA.timerMemory.counterHigh)<<32 | uint64(drvDMA.timerMemory.counterLow) if v == 0 { // BUG(maruel): Implement using AVS_CNT0_REG on A64. return 0 } // BUG(maruel): Assumes that counterCtrl & timerPLL6 is not set. const tick = time.Microsecond / 24 return time.Duration(v) * tick } // Nanospin spins the CPU without calling into the kernel code if possible. func Nanospin(t time.Duration) { start := ReadTime() if start == 0 { // Use the slow generic version. cpu.Nanospin(t) return } for ReadTime()-start < t { } } // const ( // 31:3 reserved timerPLL6 timerCtrl = 2 << 1 // CONT64_CLK_SRC_SEL; OSC24M if not set; timerReadLatchEnable timerCtrl = 1 << 1 // CONT64_RLATCH_EN; 1 to latch the counter to the registers timerClear = 1 << 0 // CONT64_CLR_EN; clears the counter ) // R8: Page 96 type timerCtrl uint32 // timerMap is the mapping of important registers across CPUs. type timerMap struct { reserved0 [0x80 / 4]uint32 // cntCtl timerCtrl // 0x80 AVS_CNT_CTL_REG AVS Control Register cnt0 uint32 // 0x84 AVS_CNT0_REG AVS Counter 0 Register cnt1 uint32 // 0x88 AVS_CNT1_REG AVS Counter 1 Register cndDrv uint32 // 0x8C AVS_CNT_DIV_REG AVS Divisor Register reserved1 [0x10 / 4]uint32 // On R8 only. counterCtrl timerCtrl // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control counterLow uint32 // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low counterHigh uint32 // 0x0A8 COUNTER64_HI_REG 64-bit Counter high } // A64: Page 161. type timerMapA64 struct { reserved0 uint32 // 0x0 TMR_IRQ_EN_REG Timer IRQ Enable Register reserved1 uint32 // 0x4 TMR_IRQ_STA_REG Timer Status Register reserved2 uint32 // 0x10 TMR0_CTRL_REG Timer 0 Control Register reserved3 uint32 // 0x14 TMR0_INTV_VALUE_REG Timer 0 Interval Value Register reserved4 uint32 // 0x18 TMR0_CUR_VALUE_REG Timer 0 Current Value Register reserved5 uint32 // 0x20 TMR1_CTRL_REG Timer 1 Control Register reserved6 uint32 // 0x24 TMR1_INTV_VALUE_REG Timer 1 Interval Value Register reserved7 uint32 // 0x28 TMR1_CUR_VALUE_REG Timer 1 Current Value Register cntCtl timerCtrl // 0x80 AVS_CNT_CTL_REG AVS Control Register cnt0 uint32 // 0x84 AVS_CNT0_REG AVS Counter 0 Register cnt1 uint32 // 0x88 AVS_CNT1_REG AVS Counter 1 Register cndDrv uint32 // 0x8C AVS_CNT_DIV_REG AVS Divisor Register reserved8 uint32 // 0xA0 WDOG0_IRQ_EN_REG Watchdog 0 IRQ Enable Register reserved9 uint32 // 0xA4 WDOG0_IRQ_STA_REG Watchdog 0 Status Register reserved10 uint32 // 0xB0 WDOG0_CTRL_REG Watchdog 0 Control Register reserved11 uint32 // 0xB4 WDOG0_CFG_REG Watchdog 0 Configuration Register reserved12 uint32 // 0xB8 WDOG0_MODE_REG Watchdog 0 Mode Register } // R8: Page 85 type timerMapR8 struct { reserved0 uint32 // 0x000 ASYNC_TMR_IRQ_EN_REG Timer IRQ Enable reserved1 uint32 // 0x004 ASYNC_TMR_IRQ_STAS_REG Timer Status reserved2 [2]uint32 // 0x008-0x00C reserved3 uint32 // 0x010 ASYNC_TMR0_CTRL_REG Timer 0 Control reserved4 uint32 // 0x014 ASYNC_TMR0_INTV_VALUE_REG Timer 0 Interval Value reserved5 uint32 // 0x018 ASYNC_TMR0_CURNT_VALUE_REG Timer 0 Current Value reserved6 uint32 // 0x01C reserved7 uint32 // 0x020 ASYNC_TMR1_CTRL_REG Timer 1 Control reserved8 uint32 // 0x024 ASYNC_TMR1_INTV_VALUE_REG Timer 1 Interval Value reserved9 uint32 // 0x028 ASYNC_TMR1_CURNT_VALUE_REG Timer 1 Current Value reserved10 uint32 // 0x02C reserved11 uint32 // 0x030 ASYNC_TMR2_CTRL_REG Timer 2 Control reserved12 uint32 // 0x034 ASYNC_TMR2_INTV_VALUE_REG Timer 2 Interval Value reserved13 uint32 // 0x038 ASYNC_TMR2_CURNT_VALUE_REG Timer 2 Current Value reserved14 uint32 // 0x03C reserved15 uint32 // 0x040 ASYNC_TMR3_CTRL_REG Timer 3 Control reserved16 uint32 // 0x044 ASYNC_TMR3_INTV_VALUE_REG Timer 3 Interval Value reserved17 [2]uint32 // 0x048-0x04C reserved18 uint32 // 0x050 ASYNC_TMR4_CTRL_REG Timer 4 Control reserved19 uint32 // 0x054 ASYNC_TMR4_INTV_VALUE_REG Timer 4 Interval Value reserved20 uint32 // 0x058 ASYNC_TMR4_CURNT_VALUE_REG Timer 4 Current Value reserved21 uint32 // 0x05C reserved22 uint32 // 0x060 ASYNC_TMR5_CTRL_REG Timer 5 Control reserved23 uint32 // 0x064 ASYNC_TMR5_INTV_VALUE_REG Timer 5 Interval Value reserved24 uint32 // 0x068 ASYNC_TMR5_CURNT_VALUE_REG Timer 5 Current Value reserved25 [5]uint32 // 0x06C-0x07C cntCtl timerCtrl // 0x080 AVS_CNT_CTL_REG AVS Control Register cnt0 uint32 // 0x084 AVS_CNT0_REG AVS Counter 0 Register cnt1 uint32 // 0x088 AVS_CNT1_REG AVS Counter 1 Register cndDiv uint32 // 0x08C AVS_CNT_DIVISOR_REG AVS Divisor reserved26 uint32 // 0x090 WDOG_CTRL_REG reserved27 uint32 // 0x094 WDOG_MODE_REG Watchdog Mode reserved28 [2]uint32 // 0x098-0x09C counterCtrl timerCtrl // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control counterLow uint32 // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low counterHigh uint32 // 0x0A8 COUNTER64_HI_REG 64-bit Counter high reserved29 [0x94]uint32 // 0x0AC-0x13C reserved30 uint32 // 0x140 CPU_CFG_REG CPU configuration register }