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 }