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  }