github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/enet/enet.go (about) 1 // NXP 10/100-Mbps Ethernet MAC (ENET) 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 enet implements a driver for NXP Ethernet controllers adopting the 11 // 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 enet 18 19 import ( 20 "crypto/rand" 21 "encoding/binary" 22 "net" 23 "runtime" 24 "sync" 25 26 "github.com/usbarmory/tamago/internal/reg" 27 ) 28 29 // ENET registers 30 const ( 31 // p879, 22.5 Memory map/register definition, IMX6ULLRM 32 33 ENETx_EIR = 0x0004 34 ENETx_EIMR = 0x0008 35 36 ENETx_RDAR = 0x0010 37 RDAR_ACTIVE = 24 38 39 ENETx_TDAR = 0x0014 40 TDAR_ACTIVE = 24 41 42 ENETx_ECR = 0x0024 43 ECR_DBSWP = 8 44 ECR_EN1588 = 5 45 ECR_ETHEREN = 1 46 ECR_RESET = 0 47 48 ENETx_MMFR = 0x0040 49 MMFR_ST = 30 50 MMFR_OP = 28 51 MMFR_PA = 23 52 MMFR_RA = 18 53 MMFR_TA = 16 54 MMFR_DATA = 0 55 56 ENETx_MSCR = 0x0044 57 MSCR_HOLDTIME = 8 58 MSCR_MII_SPEED = 1 59 60 ENETx_MIB = 0x0064 61 MIB_DIS = 31 62 63 ENETx_RCR = 0x0084 64 RCR_MAX_FL = 16 65 RCR_RMII_MODE = 8 66 RCR_FCE = 5 67 RCR_MII_MODE = 2 68 RCR_LOOP = 0 69 70 ENETx_TCR = 0x00c4 71 TCR_FDEN = 2 72 73 ENETx_PALR = 0x00e4 74 ENETx_PAUR = 0x00e8 75 ENETx_RDSR = 0x0180 76 ENETx_TDSR = 0x0184 77 ENETx_MRBR = 0x0188 78 ENETx_FTRL = 0x01b0 79 80 ENETx_RACC = 0x01c4 81 RACC_LINEDIS = 6 82 ) 83 84 // ENET interrupt events 85 const ( 86 // p889, 22.5.1 Interrupt Event Register (ENETx_EIR), IMX6ULLRM 87 // p891, 22.5.2 Interrupt Mask Register (ENETx_EIMR), IMX6ULLRM 88 89 IRQ_BABR = 30 90 IRQ_BABT = 29 91 IRQ_GRA = 28 92 IRQ_TXF = 27 93 IRQ_TXB = 26 94 IRQ_RXF = 25 95 IRQ_RXB = 24 96 IRQ_MII = 23 97 IRQ_EBERR = 22 98 IRQ_LC = 21 99 IRQ_RL = 20 100 IRQ_UN = 19 101 IRQ_PLR = 18 102 IRQ_WAKEUP = 17 103 IRQ_TS_AVAIL = 16 104 IRQ_TS_TIMER = 15 105 ) 106 107 type Stats struct { 108 // The following MAC receive errors are tracked only if 109 // ENET.DiscardErrors is false at its initialization. 110 FrameLengthViolation uint32 111 NonOctetAlignedFrame uint32 112 CRCOrFrameError uint32 113 Overrun uint32 114 FrameTooSmall uint32 115 FrameTooLarge uint32 116 } 117 118 // ENET represents an Ethernet MAC instance. 119 type ENET struct { 120 sync.Mutex 121 122 // Controller index 123 Index int 124 // Base register 125 Base uint32 126 // Clock gate register 127 CCGR uint32 128 // Clock gate 129 CG int 130 // Clock retrieval function 131 Clock func() uint32 132 // Interrupt ID 133 IRQ int 134 // PLL enable function 135 EnablePLL func(index int) error 136 // PHY enable function 137 EnablePHY func(eth *ENET) error 138 // RMII mode 139 RMII bool 140 // MAC address (use SetMAC() for post Init() changes) 141 MAC net.HardwareAddr 142 // Incoming packet handler 143 RxHandler func([]byte) 144 // Descriptor ring size 145 RingSize int 146 147 // Discard MAC layer errors 148 DiscardErrors bool 149 // Statistics about the MAC 150 Stats Stats 151 152 // control registers 153 eir uint32 154 eimr uint32 155 rdar uint32 156 tdar uint32 157 ecr uint32 158 mmfr uint32 159 mscr uint32 160 mib uint32 161 rcr uint32 162 tcr uint32 163 palr uint32 164 paur uint32 165 rdsr uint32 166 tdsr uint32 167 mrbr uint32 168 ftrl uint32 169 racc uint32 170 171 // receive data buffers 172 rx bufferDescriptorRing 173 // transmit data buffers 174 tx bufferDescriptorRing 175 } 176 177 // Init initializes and enables the Ethernet MAC controller for 100 Mbps full 178 // duplex operation with Auto-Negotiation enabled. 179 func (hw *ENET) Init() { 180 hw.Lock() 181 182 if hw.Base == 0 || hw.Clock == nil || hw.EnablePLL == nil || hw.EnablePHY == nil { 183 panic("invalid ENET controller instance") 184 } 185 186 if hw.MAC == nil { 187 hw.MAC = make([]byte, 6) 188 rand.Read(hw.MAC) 189 // flag address as unicast and locally administered 190 hw.MAC[0] &= 0xfe 191 hw.MAC[0] |= 0x02 192 } else if len(hw.MAC) != 6 { 193 panic("invalid ENET hardware address") 194 } 195 196 if hw.RingSize == 0 { 197 hw.RingSize = defaultRingSize 198 } 199 200 hw.eir = hw.Base + ENETx_EIR 201 hw.eimr = hw.Base + ENETx_EIMR 202 hw.rdar = hw.Base + ENETx_RDAR 203 hw.tdar = hw.Base + ENETx_TDAR 204 hw.ecr = hw.Base + ENETx_ECR 205 hw.mmfr = hw.Base + ENETx_MMFR 206 hw.mscr = hw.Base + ENETx_MSCR 207 hw.mib = hw.Base + ENETx_MIB 208 hw.rcr = hw.Base + ENETx_RCR 209 hw.tcr = hw.Base + ENETx_TCR 210 hw.palr = hw.Base + ENETx_PALR 211 hw.paur = hw.Base + ENETx_PAUR 212 hw.rdsr = hw.Base + ENETx_RDSR 213 hw.tdsr = hw.Base + ENETx_TDSR 214 hw.mrbr = hw.Base + ENETx_MRBR 215 hw.ftrl = hw.Base + ENETx_FTRL 216 hw.racc = hw.Base + ENETx_RACC 217 218 hw.setup() 219 220 hw.Unlock() 221 } 222 223 func (hw *ENET) setup() { 224 // enable clock 225 reg.SetN(hw.CCGR, hw.CG, 0b11, 0b11) 226 hw.EnablePLL(hw.Index) 227 228 // soft reset 229 reg.Set(hw.ecr, ECR_RESET) 230 reg.Wait(hw.ecr, ECR_RESET, 1, 0) 231 reg.Set(hw.ecr, ECR_DBSWP) 232 233 // clear all interrupts 234 reg.Write(hw.eir, 0xffffffff) 235 // mask all interrupts 236 reg.Write(hw.eimr, 0) 237 238 // enable Full-Duplex 239 reg.Set(hw.tcr, TCR_FDEN) 240 // disable Management Information Database 241 reg.Set(hw.mib, MIB_DIS) 242 243 // use legacy descriptors 244 reg.Clear(hw.ecr, ECR_EN1588) 245 246 // set receive buffer size and maximum frame length 247 size := MTU + (bufferAlign - (MTU % bufferAlign)) 248 reg.Write(hw.mrbr, uint32(size)) 249 reg.Write(hw.ftrl, MTU) 250 reg.SetN(hw.rcr, RCR_MAX_FL, 0x3fff, MTU) 251 252 if hw.DiscardErrors { 253 reg.Set(hw.racc, RACC_LINEDIS) 254 } 255 256 // set physical address 257 hw.SetMAC(hw.MAC) 258 259 // set Media Independent Interface Mode 260 reg.Set(hw.rcr, RCR_MII_MODE) 261 reg.SetTo(hw.rcr, RCR_RMII_MODE, hw.RMII) 262 // enable Flow Control 263 reg.Set(hw.rcr, RCR_FCE) 264 // disable loopback 265 reg.Clear(hw.rcr, RCR_LOOP) 266 267 // set MII clock 268 reg.SetN(hw.mscr, MSCR_HOLDTIME, 0b111, 1) 269 reg.SetN(hw.mscr, MSCR_MII_SPEED, 0x3f, hw.Clock()/(2*2500000)) 270 271 // enable Ethernet MAC 272 reg.Set(hw.ecr, ECR_ETHEREN) 273 274 // enable Ethernet PHY 275 hw.EnablePHY(hw) 276 } 277 278 // SetMAC allows to change the controller physical address register after 279 // initialization. 280 func (hw *ENET) SetMAC(mac net.HardwareAddr) { 281 hw.MAC = mac 282 283 lower := binary.BigEndian.Uint32(hw.MAC[0:4]) 284 upper := binary.BigEndian.Uint16(hw.MAC[4:6]) 285 286 reg.Write(hw.palr, lower) 287 reg.Write(hw.paur, uint32(upper)<<16) 288 } 289 290 // Start begins processing of incoming packets. When the argument is true the 291 // function waits and handles received packets (see Rx()) through RxHandler() 292 // (when set), it should never return. 293 func (hw *ENET) Start(rx bool) { 294 // set receive and transmit descriptors 295 reg.Write(hw.rdsr, hw.rx.init(true, hw.RingSize, &hw.Stats)) 296 reg.Write(hw.tdsr, hw.tx.init(false, hw.RingSize, &hw.Stats)) 297 298 reg.Set(hw.rdar, RDAR_ACTIVE) 299 300 if !rx || hw.RxHandler == nil { 301 return 302 } 303 304 var buf []byte 305 306 for { 307 runtime.Gosched() 308 309 if buf = hw.Rx(); buf != nil { 310 hw.RxHandler(buf) 311 } 312 } 313 } 314 315 // EnableInterrupt enables interrupt generation for a specific event. 316 func (hw *ENET) EnableInterrupt(event int) { 317 reg.Set(hw.eimr, event) 318 } 319 320 // ClearInterrupt clears the interrupt corresponding to a specific event. 321 func (hw *ENET) ClearInterrupt(event int) { 322 reg.Set(hw.eir, event) 323 }