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  }