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

     1  // NXP USBOH3USBO2 / USBPHY 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 usb implements a driver for the USB PHY designated as NXP
    11  // USBOH3USBO2, included in several i.MX SoCs, adopting the following
    12  // specifications:
    13  //   - IMX6ULLRM - i.MX 6ULL Applications Processor Reference Manual - Rev 1 2017/11
    14  //   - USB2.0    - USB Specification Revision 2.0
    15  //
    16  // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as
    17  // supported by the TamaGo framework for bare metal Go on ARM SoCs, see
    18  // https://github.com/usbarmory/tamago.
    19  package usb
    20  
    21  import (
    22  	"sync"
    23  
    24  	"github.com/usbarmory/tamago/internal/reg"
    25  )
    26  
    27  // USB registers
    28  const (
    29  	USB_ANALOG_USBx_CHRG_DETECT = 0x10
    30  	CHRG_DETECT_EN_B            = 20
    31  	CHRG_DETECT_CHK_CHRG_B      = 19
    32  
    33  	USBPHYx_PWD = 0x00
    34  
    35  	USBPHYx_CTRL            = 0x30
    36  	CTRL_SFTRST             = 31
    37  	CTRL_CLKGATE            = 30
    38  	CTRL_ENUTMILEVEL3       = 15
    39  	CTRL_ENUTMILEVEL2       = 14
    40  	CTRL_ENHOSTDISCONDETECT = 1
    41  
    42  	// p3823, 56.6 USB Core Memory Map/Register Definition, IMX6ULLRM
    43  
    44  	USB_UOGx_USBCMD = 0x140
    45  	USBCMD_RST      = 1
    46  	USBCMD_RS       = 0
    47  
    48  	USB_UOGx_USBSTS = 0x144
    49  	USBSTS_URI      = 6
    50  	USBSTS_UI       = 0
    51  
    52  	USB_UOGx_USBINTR = 0x148
    53  
    54  	USB_UOGx_DEVICEADDR = 0x154
    55  	DEVICEADDR_USBADR   = 25
    56  	DEVICEADDR_USBADRA  = 24
    57  
    58  	USB_UOGx_ENDPTLISTADDR = 0x158
    59  	ENDPTLISTADDR_EPBASE   = 11
    60  
    61  	USB_UOGx_PORTSC1 = 0x184
    62  	PORTSC_PTS_1     = 30
    63  	PORTSC_PSPD      = 26
    64  	PORTSC_PR        = 8
    65  
    66  	USB_UOGx_OTGSC = 0x1a4
    67  	OTGSC_OT       = 3
    68  
    69  	USB_UOGx_USBMODE  = 0x1a8
    70  	USBMODE_SDIS      = 4
    71  	USBMODE_SLOM      = 3
    72  	USBMODE_CM        = 0
    73  	USBMODE_CM_DEVICE = 0b10
    74  	USBMODE_CM_HOST   = 0b11
    75  
    76  	USB_UOGx_ENDPTSETUPSTAT = 0x1ac
    77  
    78  	USB_UOGx_ENDPTPRIME = 0x1b0
    79  	ENDPTPRIME_PETB     = 16
    80  	ENDPTPRIME_PERB     = 0
    81  
    82  	USB_UOGx_ENDPTFLUSH = 0x1b4
    83  	ENDPTFLUSH_FETB     = 16
    84  	ENDPTFLUSH_FERB     = 0
    85  
    86  	USB_UOGx_ENDPTSTAT = 0x1b8
    87  
    88  	USB_UOGx_ENDPTCOMPLETE = 0x1bc
    89  	ENDPTCOMPLETE_ETBR     = 16
    90  	ENDPTCOMPLETE_ERBR     = 0
    91  
    92  	USB_UOGx_ENDPTCTRL = 0x1c0
    93  	ENDPTCTRL_TXE      = 23
    94  	ENDPTCTRL_TXR      = 22
    95  	ENDPTCTRL_TXI      = 21
    96  	ENDPTCTRL_TXT      = 18
    97  	ENDPTCTRL_TXS      = 16
    98  	ENDPTCTRL_RXE      = 7
    99  	ENDPTCTRL_RXR      = 6
   100  	ENDPTCTRL_RXI      = 5
   101  	ENDPTCTRL_RXT      = 2
   102  	ENDPTCTRL_RXS      = 0
   103  )
   104  
   105  // USB interrupt events
   106  const (
   107  	// p3848, 56.6.19 Interrupt Status Register (USB_nUSBSTS),  IMX6ULLRM
   108  	// p3852, 56.6.20 Interrupt Enable Register (USB_nUSBINTR), IMX6ULLRM
   109  
   110  	IRQ_TI1   = 25
   111  	IRQ_TI0   = 24
   112  	IRQ_NAKI  = 16
   113  	IRQ_AS    = 15
   114  	IRQ_PS    = 14
   115  	IRQ_RCP   = 13
   116  	IRQ_HCH   = 12
   117  	IRQ_ULPII = 10
   118  	IRQ_SLI   = 8
   119  	IRQ_SRI   = 7
   120  	IRQ_URI   = 6
   121  	IRQ_AAI   = 5
   122  	IRQ_SEI   = 4
   123  	IRQ_FRI   = 3
   124  	IRQ_PCI   = 2
   125  	IRQ_UEI   = 1
   126  	IRQ_UI    = 0
   127  )
   128  
   129  // USB represents a USB controller instance.
   130  type USB struct {
   131  	sync.Mutex
   132  
   133  	// Controller index
   134  	Index int
   135  	// Base register
   136  	Base uint32
   137  	// Clock gate register
   138  	CCGR uint32
   139  	// Clock gate
   140  	CG int
   141  	// Analog base register
   142  	Analog uint32
   143  	// PHY base register
   144  	PHY uint32
   145  	// Interrupt ID
   146  	IRQ int
   147  	// PLL enable function
   148  	EnablePLL func(index int) error
   149  
   150  	// USB device configuration
   151  	Device *Device
   152  
   153  	// EP1-N transfer completion rendezvous point
   154  	event *sync.Cond
   155  	// EP1-N cancellation signal
   156  	exit chan struct{}
   157  	// EP-1-N completion synchronization
   158  	wg sync.WaitGroup
   159  
   160  	// control registers
   161  	ctrl     uint32
   162  	pwd      uint32
   163  	chrg     uint32
   164  	mode     uint32
   165  	otg      uint32
   166  	cmd      uint32
   167  	addr     uint32
   168  	sts      uint32
   169  	intr     uint32
   170  	sc       uint32
   171  	eplist   uint32
   172  	setup    uint32
   173  	flush    uint32
   174  	prime    uint32
   175  	stat     uint32
   176  	complete uint32
   177  	epctrl   uint32
   178  
   179  	// cache for endpoint list pointer
   180  	epListAddr uint32
   181  	// cache for endpoint queue heads pointers
   182  	dQH [MAX_ENDPOINTS][2]uint32
   183  }
   184  
   185  // Init initializes the USB controller.
   186  func (hw *USB) Init() {
   187  	hw.Lock()
   188  	defer hw.Unlock()
   189  
   190  	if hw.Base == 0 || hw.CCGR == 0 || hw.Analog == 0 || hw.PHY == 0 || hw.EnablePLL == nil {
   191  		panic("invalid USB controller instance")
   192  	}
   193  
   194  	hw.ctrl = hw.PHY + USBPHYx_CTRL
   195  	hw.pwd = hw.PHY + USBPHYx_PWD
   196  	hw.chrg = hw.Analog + USB_ANALOG_USBx_CHRG_DETECT
   197  	hw.mode = hw.Base + USB_UOGx_USBMODE
   198  	hw.otg = hw.Base + USB_UOGx_OTGSC
   199  	hw.cmd = hw.Base + USB_UOGx_USBCMD
   200  	hw.addr = hw.Base + USB_UOGx_DEVICEADDR
   201  	hw.sts = hw.Base + USB_UOGx_USBSTS
   202  	hw.intr = hw.Base + USB_UOGx_USBINTR
   203  	hw.sc = hw.Base + USB_UOGx_PORTSC1
   204  	hw.eplist = hw.Base + USB_UOGx_ENDPTLISTADDR
   205  	hw.setup = hw.Base + USB_UOGx_ENDPTSETUPSTAT
   206  	hw.flush = hw.Base + USB_UOGx_ENDPTFLUSH
   207  	hw.prime = hw.Base + USB_UOGx_ENDPTPRIME
   208  	hw.stat = hw.Base + USB_UOGx_ENDPTSTAT
   209  	hw.complete = hw.Base + USB_UOGx_ENDPTCOMPLETE
   210  	hw.epctrl = hw.Base + USB_UOGx_ENDPTCTRL
   211  
   212  	// enable clock
   213  	reg.SetN(hw.CCGR, hw.CG, 0b11, 0b11)
   214  	hw.EnablePLL(hw.Index)
   215  
   216  	// soft reset USB PHY
   217  	reg.Set(hw.ctrl, CTRL_SFTRST)
   218  	reg.Clear(hw.ctrl, CTRL_SFTRST)
   219  
   220  	// disable clock gate
   221  	reg.Clear(hw.ctrl, CTRL_CLKGATE)
   222  
   223  	// clear power down
   224  	reg.Write(hw.pwd, 0)
   225  
   226  	// enable UTMI+
   227  	reg.Set(hw.ctrl, CTRL_ENUTMILEVEL3)
   228  	reg.Set(hw.ctrl, CTRL_ENUTMILEVEL2)
   229  	// enable disconnection detect
   230  	reg.Set(hw.ctrl, CTRL_ENHOSTDISCONDETECT)
   231  
   232  	// disable charger detector
   233  	reg.Set(hw.chrg, CHRG_DETECT_EN_B)
   234  	reg.Set(hw.chrg, CHRG_DETECT_CHK_CHRG_B)
   235  }
   236  
   237  // Speed returns the port speed.
   238  func (hw *USB) Speed() (speed string) {
   239  	hw.Lock()
   240  	defer hw.Unlock()
   241  
   242  	switch reg.Get(hw.sc, PORTSC_PSPD, 0b11) {
   243  	case 0b00:
   244  		speed = "full"
   245  	case 0b01:
   246  		speed = "low"
   247  	case 0b10:
   248  		speed = "high"
   249  	case 0b11:
   250  		panic("invalid port speed")
   251  	}
   252  
   253  	return
   254  }
   255  
   256  // PowerDown shuts down the USB PHY.
   257  func (hw *USB) PowerDown() {
   258  	reg.Write(hw.pwd, 0xffffffff)
   259  }
   260  
   261  // Run sets the controller in run mode.
   262  func (hw *USB) Run() {
   263  	reg.Set(hw.cmd, USBCMD_RS)
   264  }
   265  
   266  // Stop sets the controller in stop mode.
   267  func (hw *USB) Stop() {
   268  	reg.Clear(hw.cmd, USBCMD_RS)
   269  }
   270  
   271  // Reset waits for and handles a bus reset.
   272  func (hw *USB) Reset() {
   273  	hw.Lock()
   274  	defer hw.Unlock()
   275  
   276  	reg.Wait(hw.sts, USBSTS_URI, 1, 1)
   277  
   278  	// p3792, 56.4.6.2.1 Bus Reset, IMX6ULLRM
   279  
   280  	// read and write back to clear setup token semaphores
   281  	reg.WriteBack(hw.setup)
   282  	// read and write back to clear setup status
   283  	reg.WriteBack(hw.complete)
   284  	// flush endpoint buffers
   285  	reg.Write(hw.flush, 0xffffffff)
   286  
   287  	reg.Wait(hw.sc, PORTSC_PR, 1, 0)
   288  
   289  	// clear reset
   290  	reg.Or(hw.sts, (1<<USBSTS_URI | 1<<USBSTS_UI))
   291  }
   292  
   293  // EnableInterrupt enables interrupt generation for a specific event.
   294  func (hw *USB) EnableInterrupt(event int) {
   295  	reg.Set(hw.intr, event)
   296  }
   297  
   298  // ClearInterrupt clears the interrupt corresponding to a specific event.
   299  func (hw *USB) ClearInterrupt(event int) {
   300  	reg.Set(hw.sts, event)
   301  }