github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/wdog/wdog.go (about) 1 // NXP Watchdog Timer (WDOG) driver 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 bee implements a driver for the NXP Watchdog Timer (WDOG) 11 // adopting the following reference specifications: 12 // - IMX6ULLRM - i.MX 6ULL Applications Processor Reference Manual - Rev 1 2017/11 13 // 14 // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as 15 // supported by the TamaGo framework for bare metal Go on ARM SoCs, see 16 // https://github.com/usbarmory/tamago. 17 package wdog 18 19 import ( 20 "sync" 21 22 "github.com/usbarmory/tamago/internal/reg" 23 ) 24 25 // WDOG registers 26 const ( 27 WDOGx_WCR = 0x00 28 WCR_WT = 8 29 WCR_SRE = 6 30 WCR_WDA = 5 31 WCR_SRS = 4 32 WCR_WDT = 3 33 WCR_WDE = 2 34 35 WDOGx_WSR = 0x02 36 37 WDOGx_WRSR = 0x04 38 WRSR_POR = 4 39 WRSR_TOUT = 1 40 WRSR_SFTW = 0 41 42 WDOGx_WICR = 0x06 43 WICR_WIE = 15 44 WICR_WTIS = 14 45 WICR_WICT = 0 46 47 WDOGx_WMCR = 0x08 48 WMCR_PDE = 0 49 ) 50 51 // WDOG service sequence 52 const ( 53 wsr_seq1 = 0x5555 54 wsr_seq2 = 0xaaaa 55 ) 56 57 // WDOG represents a Watchdog Timer instance. 58 type WDOG struct { 59 sync.Mutex 60 61 // Module index 62 Index int 63 // Base register 64 Base uint32 65 // Clock gate register 66 CCGR uint32 67 // Clock gate 68 CG int 69 // Interrupt ID 70 IRQ int 71 72 // control registers 73 wcr uint32 74 wsr uint32 75 wrsr uint32 76 wicr uint32 77 wmcr uint32 78 } 79 80 // Init initializes a Watchdog Timer instance. The initialization is required 81 // within 16 seconds of reset de-assertion to clear the power-down counter 82 // event. 83 func (hw *WDOG) Init() { 84 hw.Lock() 85 defer hw.Unlock() 86 87 if hw.Base == 0 || hw.CCGR == 0 { 88 panic("invalid WDOG module instance") 89 } 90 91 hw.wcr = hw.Base + WDOGx_WCR 92 hw.wsr = hw.Base + WDOGx_WSR 93 hw.wrsr = hw.Base + WDOGx_WRSR 94 hw.wicr = hw.Base + WDOGx_WICR 95 hw.wmcr = hw.Base + WDOGx_WMCR 96 97 // enable clock 98 reg.SetN(hw.CCGR, hw.CG, 0b11, 0b11) 99 100 // p4085, 59.5.3 Power-down counter event, IMX6ULLRM 101 reg.Clear16(hw.wmcr, WMCR_PDE) 102 } 103 104 // EnableInterrupt enables interrupt generation before the Watchdog timeout 105 // event per argument delay. The delay must be specified in milliseconds with 106 // 127500 as maximum value, the timeout resolution is 500ms. 107 func (hw *WDOG) EnableInterrupt(delay int) { 108 reg.SetN16(hw.wicr, WICR_WICT, 0xffff, 1 << WICR_WIE | uint16(delay/500)) 109 } 110 111 // ClearInterrupt clears the interrupt status register. 112 func (hw *WDOG) ClearInterrupt() { 113 reg.Set16(hw.wicr, WICR_WTIS) 114 } 115 116 // EnableTimeout activates the Watchdog Timer to trigger a reset after the 117 // argument timeout. The timeout must be specified in milliseconds with 128000 118 // as maximum value, the timeout resolution is 500ms. The timeout can be 119 // prevented, or reconfigured, with Service(). 120 func (hw *WDOG) EnableTimeout(timeout int) { 121 hw.Lock() 122 defer hw.Unlock() 123 124 reg.SetN16(hw.wcr, WCR_WT, 0xff, uint16(timeout/500-1)) 125 reg.Set16(hw.wcr, WCR_WDT) 126 reg.Set16(hw.wcr, WCR_WDE) 127 } 128 129 // Service prevents the timeout condition on a previously enabled Watchdog. 130 func (hw *WDOG) Service(timeout int) { 131 hw.Lock() 132 defer hw.Unlock() 133 134 // In case we are a TrustZone Watchdog the Normal World OS might 135 // disable our clock, which keeps the timeout but prevents servicing, 136 // therefore we re-enable the clock. 137 reg.SetN(hw.CCGR, hw.CG, 0b11, 0b11) 138 139 // update timeout 140 reg.SetN16(hw.wcr, WCR_WT, 0xff, uint16(timeout/500-1)) 141 142 if reg.Get16(hw.wicr, WICR_WIE, 1) == 1 { 143 // clear interrupt status 144 reg.Set16(hw.wicr, WICR_WTIS) 145 } 146 147 // perform service sequence 148 reg.Write16(hw.wsr, wsr_seq1) 149 reg.Write16(hw.wsr, wsr_seq2) 150 } 151 152 // Reset asserts the watchdog reset signal. 153 func (hw *WDOG) Reset() { 154 reg.Clear16(hw.wcr, WCR_WDA) 155 } 156 157 // SoftwareReset asserts the watchdog software reset signal. 158 func (hw *WDOG) SoftwareReset() { 159 reg.Set16(hw.wcr, WCR_SRE) 160 reg.Clear16(hw.wcr, WCR_SRS) 161 } 162 163 // ResetSource reads the watchdog reset status register which records the 164 // source of the output reset assertion. 165 func (hw *WDOG) ResetSource() uint16 { 166 return reg.Read16(hw.wrsr) 167 }