github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/imx6ul/init.go (about)

     1  // NXP i.MX6UL initialization
     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 imx6ul
    11  
    12  import (
    13  	"runtime"
    14  	_ "unsafe"
    15  
    16  	"github.com/usbarmory/tamago/arm"
    17  	"github.com/usbarmory/tamago/bits"
    18  	"github.com/usbarmory/tamago/dma"
    19  	"github.com/usbarmory/tamago/internal/reg"
    20  	"github.com/usbarmory/tamago/soc/nxp/bee"
    21  	"github.com/usbarmory/tamago/soc/nxp/dcp"
    22  	"github.com/usbarmory/tamago/soc/nxp/enet"
    23  	"github.com/usbarmory/tamago/soc/nxp/usb"
    24  )
    25  
    26  // i.MX processor families
    27  const (
    28  	IMX6UL  = 0x64
    29  	IMX6ULL = 0x65
    30  )
    31  
    32  //go:linkname ramStackOffset runtime.ramStackOffset
    33  var ramStackOffset uint32 = 0x100
    34  
    35  var (
    36  	// Processor family
    37  	Family uint32
    38  
    39  	// Flag native or emulated processor
    40  	Native bool
    41  
    42  	// SDP flags whether Serial Download Protocol over USB has been used to
    43  	// boot this runtime. The value is always false on non-secure (e.g.
    44  	// TrustZone Normal World) processor modes.
    45  	SDP bool
    46  )
    47  
    48  // Init takes care of the lower level SoC initialization triggered early in
    49  // runtime setup (e.g. runtime.hwinit).
    50  func Init() {
    51  	if ARM.Mode() != arm.SYS_MODE {
    52  		// initialization required only when in PL1
    53  		return
    54  	}
    55  
    56  	ramStart, _ := runtime.MemRegion()
    57  
    58  	ARM.Init(ramStart)
    59  	ARM.EnableVFP()
    60  
    61  	// required when booting in SDP mode
    62  	ARM.EnableSMP()
    63  
    64  	// MMU initialization is required to take advantage of data cache
    65  	ARM.InitMMU()
    66  	ARM.EnableCache()
    67  
    68  	_, fam, revMajor, revMinor := SiliconVersion()
    69  	Family = fam
    70  
    71  	if revMajor != 0 || revMinor != 0 {
    72  		Native = true
    73  	}
    74  
    75  	initTimers()
    76  }
    77  
    78  func init() {
    79  	// Initialize watchdogs, this must be done within 16 seconds to clear
    80  	// their power-down counter event
    81  	// (p4085, 59.5.3 Power-down counter event, IMX6ULLRM).
    82  	WDOG1.Init()
    83  	WDOG2.Init()
    84  	WDOG3.Init()
    85  
    86  	// use internal OCRAM (iRAM) as default DMA region
    87  	dma.Init(OCRAM_START, OCRAM_SIZE)
    88  
    89  	OCOTP.Init()
    90  	model := Model()
    91  
    92  	switch model {
    93  	case "i.MX6UL":
    94  		if Native {
    95  			// Configuration and Manufacturing Info
    96  			// p2203, 35.5.15 OCOTP_CFG3, IMX6ULRM
    97  			cfg3, _ := OCOTP.Read(0, 4)
    98  
    99  			// BEE_UNAVAILABLE
   100  			if bits.Get(&cfg3, 25, 1) == 0 {
   101  				// Bus Encryption Engine
   102  				BEE = &bee.BEE{
   103  					Base: BEE_BASE,
   104  					SNVS: SNVS,
   105  				}
   106  
   107  				SNVS.DryIce = SNVS_LP_BASE
   108  			}
   109  		}
   110  
   111  		OCOTP.Banks = 16
   112  	case "i.MX6ULL", "i.MX6ULZ":
   113  		// Data Co-Processor
   114  		DCP = &dcp.DCP{
   115  			Base:            DCP_BASE,
   116  			CCGR:            CCM_CCGR0,
   117  			CG:              CCGRx_CG5,
   118  			DeriveKeyMemory: dma.Default(),
   119  		}
   120  
   121  		OCOTP.Banks = 8
   122  	}
   123  
   124  	switch model {
   125  	case "i.MX6UL", "i.MX6ULL":
   126  		// Ethernet MAC 1
   127  		ENET1 = &enet.ENET{
   128  			Index:     1,
   129  			Base:      ENET1_BASE,
   130  			CCGR:      CCM_CCGR0,
   131  			CG:        CCGRx_CG6,
   132  			Clock:     GetPeripheralClock,
   133  			IRQ:       ENET1_IRQ,
   134  			EnablePLL: EnableENETPLL,
   135  		}
   136  
   137  		// Ethernet MAC 2
   138  		ENET2 = &enet.ENET{
   139  			Index:     2,
   140  			Base:      ENET2_BASE,
   141  			CCGR:      CCM_CCGR0,
   142  			CG:        CCGRx_CG6,
   143  			Clock:     GetPeripheralClock,
   144  			IRQ:       ENET2_IRQ,
   145  			EnablePLL: EnableENETPLL,
   146  		}
   147  	}
   148  
   149  	if !Native || ARM.NonSecure() {
   150  		return
   151  	}
   152  
   153  	// OCOTP_ANA1 Temperature Sensor Calibration Data
   154  	// p3531, 52.2 Software Usage Guidelines, IMX6ULLRM
   155  	ana1, _ := OCOTP.Read(1, 6)
   156  	// initialize temperature monitor
   157  	TEMPMON.Init(ana1)
   158  
   159  	// DryIce Trim Values
   160  	// p1060, 8.5.2 DryIce Trim Value Register, IMX6ULSRM
   161  	mem1, _ := OCOTP.Read(1, 1)
   162  	// initialize security state machine (SSM)
   163  	SNVS.Init(mem1)
   164  
   165  	// On the i.MX6UL family the only way to detect if we are booting
   166  	// through Serial Download Mode over USB is to check whether the USB
   167  	// OTG1 controller was running in device mode prior to our own
   168  	// initialization.
   169  	if reg.Get(USB1_BASE+usb.USB_UOGx_USBMODE, usb.USBMODE_CM, 0b11) == usb.USBMODE_CM_DEVICE &&
   170  		reg.Get(USB1_BASE+usb.USB_UOGx_USBCMD, usb.USBCMD_RS, 1) != 0 {
   171  		SDP = true
   172  	}
   173  }