github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/imx6/usb/bus.go (about)

     1  // NXP USBOH3USBO2 / USBPHY driver
     2  // https://github.com/f-secure-foundry/tamago
     3  //
     4  // Copyright (c) F-Secure Corporation
     5  // https://foundry.f-secure.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 i.MX6 SoCs.
    12  //
    13  // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as
    14  // supported by the TamaGo framework for bare metal Go on ARM SoCs, see
    15  // https://github.com/f-secure-foundry/tamago.
    16  package usb
    17  
    18  import (
    19  	"sync"
    20  
    21  	"github.com/f-secure-foundry/tamago/internal/reg"
    22  	"github.com/f-secure-foundry/tamago/soc/imx6"
    23  )
    24  
    25  // USB registers
    26  const (
    27  	USB_ANALOG1_BASE = 0x020c81a0
    28  	USB_ANALOG2_BASE = 0x020c8200
    29  
    30  	USB_ANALOG_USBx_CHRG_DETECT = 0x10
    31  	CHRG_DETECT_EN_B            = 20
    32  	CHRG_DETECT_CHK_CHRG_B      = 19
    33  
    34  	USBPHY1_BASE = 0x020c9000
    35  	USBPHY2_BASE = 0x020ca000
    36  
    37  	USBPHYx_PWD = 0x00
    38  
    39  	USBPHYx_CTRL            = 0x30
    40  	CTRL_SFTRST             = 31
    41  	CTRL_CLKGATE            = 30
    42  	CTRL_ENUTMILEVEL3       = 15
    43  	CTRL_ENUTMILEVEL2       = 14
    44  	CTRL_ENHOSTDISCONDETECT = 1
    45  
    46  	USB1_BASE = 0x02184000
    47  	USB2_BASE = 0x02184200
    48  
    49  	// p3823, 56.6 USB Core Memory Map/Register Definition, IMX6ULLRM
    50  
    51  	USB_UOGx_USBCMD = 0x140
    52  	USBCMD_RST      = 1
    53  	USBCMD_RS       = 0
    54  
    55  	USB_UOGx_USBSTS = 0x144
    56  	USBSTS_URI      = 6
    57  	USBSTS_UI       = 0
    58  
    59  	USB_UOGx_DEVICEADDR = 0x154
    60  	DEVICEADDR_USBADR   = 25
    61  	DEVICEADDR_USBADRA  = 24
    62  
    63  	USB_UOGx_ENDPTLISTADDR = 0x158
    64  	ENDPTLISTADDR_EPBASE   = 11
    65  
    66  	USB_UOGx_PORTSC1 = 0x184
    67  	PORTSC_PTS_1     = 30
    68  	PORTSC_PSPD      = 26
    69  	PORTSC_PR        = 8
    70  
    71  	USB_UOGx_OTGSC = 0x1a4
    72  	OTGSC_OT       = 3
    73  
    74  	USB_UOGx_USBMODE  = 0x1a8
    75  	USBMODE_SDIS      = 4
    76  	USBMODE_SLOM      = 3
    77  	USBMODE_CM        = 0
    78  	USBMODE_CM_DEVICE = 0b10
    79  	USBMODE_CM_HOST   = 0b11
    80  
    81  	USB_UOGx_ENDPTSETUPSTAT = 0x1ac
    82  
    83  	USB_UOGx_ENDPTPRIME = 0x1b0
    84  	ENDPTPRIME_PETB     = 16
    85  	ENDPTPRIME_PERB     = 0
    86  
    87  	USB_UOGx_ENDPTFLUSH = 0x1b4
    88  	ENDPTFLUSH_FETB     = 16
    89  	ENDPTFLUSH_FERB     = 0
    90  
    91  	USB_UOGx_ENDPTSTAT = 0x1b8
    92  
    93  	USB_UOGx_ENDPTCOMPLETE = 0x1bc
    94  	ENDPTCOMPLETE_ETBR     = 16
    95  	ENDPTCOMPLETE_ERBR     = 0
    96  
    97  	USB_UOGx_ENDPTCTRL = 0x1c0
    98  	ENDPTCTRL_TXE      = 23
    99  	ENDPTCTRL_TXR      = 22
   100  	ENDPTCTRL_TXI      = 21
   101  	ENDPTCTRL_TXT      = 18
   102  	ENDPTCTRL_TXS      = 16
   103  	ENDPTCTRL_RXE      = 7
   104  	ENDPTCTRL_RXR      = 6
   105  	ENDPTCTRL_RXI      = 5
   106  	ENDPTCTRL_RXT      = 2
   107  	ENDPTCTRL_RXS      = 0
   108  )
   109  
   110  // USB represents a controller instance.
   111  type USB struct {
   112  	sync.Mutex
   113  
   114  	// signal for EP1-N cancellation
   115  	done chan bool
   116  	// controller index
   117  	n int
   118  
   119  	// control registers
   120  	pll      uint32
   121  	ctrl     uint32
   122  	pwd      uint32
   123  	chrg     uint32
   124  	mode     uint32
   125  	otg      uint32
   126  	cmd      uint32
   127  	addr     uint32
   128  	sts      uint32
   129  	sc       uint32
   130  	eplist   uint32
   131  	setup    uint32
   132  	flush    uint32
   133  	prime    uint32
   134  	stat     uint32
   135  	complete uint32
   136  	epctrl   uint32
   137  
   138  	// cache for endpoint list pointer
   139  	epListAddr uint32
   140  	// cache for endpoint queue heads pointers
   141  	dQH [MAX_ENDPOINTS][2]uint32
   142  }
   143  
   144  // USB1 instance
   145  var USB1 = &USB{n: 1}
   146  
   147  // USB2 instance
   148  var USB2 = &USB{n: 2}
   149  
   150  var sdp bool
   151  
   152  // SDP returns whether Serial Download Protocol over USB has been used to boot
   153  // this runtime.
   154  func SDP() bool {
   155  	return sdp
   156  }
   157  
   158  // Init initializes the USB controller.
   159  func (hw *USB) Init() {
   160  	var base uint32
   161  	var analogBase uint32
   162  	var phyBase uint32
   163  
   164  	hw.Lock()
   165  	defer hw.Unlock()
   166  
   167  	switch hw.n {
   168  	case 1:
   169  		base = USB1_BASE
   170  		analogBase = USB_ANALOG1_BASE
   171  		phyBase = USBPHY1_BASE
   172  		hw.pll = imx6.CCM_ANALOG_PLL_USB1
   173  	case 2:
   174  		base = USB2_BASE
   175  		analogBase = USB_ANALOG2_BASE
   176  		phyBase = USBPHY2_BASE
   177  		hw.pll = imx6.CCM_ANALOG_PLL_USB2
   178  	default:
   179  		panic("invalid USB controller instance")
   180  	}
   181  
   182  	hw.ctrl = phyBase + USBPHYx_CTRL
   183  	hw.pwd = phyBase + USBPHYx_PWD
   184  	hw.chrg = analogBase + USB_ANALOG_USBx_CHRG_DETECT
   185  	hw.mode = base + USB_UOGx_USBMODE
   186  	hw.otg = base + USB_UOGx_OTGSC
   187  	hw.cmd = base + USB_UOGx_USBCMD
   188  	hw.addr = base + USB_UOGx_DEVICEADDR
   189  	hw.sts = base + USB_UOGx_USBSTS
   190  	hw.sc = base + USB_UOGx_PORTSC1
   191  	hw.eplist = base + USB_UOGx_ENDPTLISTADDR
   192  	hw.setup = base + USB_UOGx_ENDPTSETUPSTAT
   193  	hw.flush = base + USB_UOGx_ENDPTFLUSH
   194  	hw.prime = base + USB_UOGx_ENDPTPRIME
   195  	hw.stat = base + USB_UOGx_ENDPTSTAT
   196  	hw.complete = base + USB_UOGx_ENDPTCOMPLETE
   197  	hw.epctrl = base + USB_UOGx_ENDPTCTRL
   198  
   199  	// enable clock
   200  	reg.SetN(imx6.CCM_CCGR6, imx6.CCGRx_CG0, 0b11, 0b11)
   201  
   202  	// power up PLL
   203  	reg.Set(hw.pll, imx6.PLL_POWER)
   204  	reg.Set(hw.pll, imx6.PLL_EN_USB_CLKS)
   205  
   206  	// wait for lock
   207  	reg.Wait(hw.pll, imx6.PLL_LOCK, 1, 1)
   208  
   209  	// remove bypass
   210  	reg.Clear(hw.pll, imx6.PLL_BYPASS)
   211  
   212  	// enable PLL
   213  	reg.Set(hw.pll, imx6.PLL_ENABLE)
   214  
   215  	// soft reset USB PHY
   216  	reg.Set(hw.ctrl, CTRL_SFTRST)
   217  	reg.Clear(hw.ctrl, CTRL_SFTRST)
   218  
   219  	// enable clocks
   220  	reg.Clear(hw.ctrl, CTRL_CLKGATE)
   221  
   222  	// clear power down
   223  	reg.Write(hw.pwd, 0)
   224  
   225  	// enable UTMI+
   226  	reg.Set(hw.ctrl, CTRL_ENUTMILEVEL3)
   227  	reg.Set(hw.ctrl, CTRL_ENUTMILEVEL2)
   228  	// enable disconnection detect
   229  	reg.Set(hw.ctrl, CTRL_ENHOSTDISCONDETECT)
   230  
   231  	// disable charger detector
   232  	reg.Set(hw.chrg, CHRG_DETECT_EN_B)
   233  	reg.Set(hw.chrg, CHRG_DETECT_CHK_CHRG_B)
   234  }
   235  
   236  // Speed returns the port speed.
   237  func (hw *USB) Speed() (speed string) {
   238  	hw.Lock()
   239  	defer hw.Unlock()
   240  
   241  	switch reg.Get(hw.sc, PORTSC_PSPD, 0b11) {
   242  	case 0b00:
   243  		speed = "full"
   244  	case 0b01:
   245  		speed = "low"
   246  	case 0b10:
   247  		speed = "high"
   248  	case 0b11:
   249  		panic("invalid port speed")
   250  	}
   251  
   252  	return
   253  }
   254  
   255  // PowerDown shuts down the USB PHY.
   256  func (hw *USB) PowerDown() {
   257  	reg.Write(hw.pwd, 0xffffffff)
   258  }
   259  
   260  // Run sets the controller in run mode.
   261  func (hw *USB) Run() {
   262  	reg.Set(hw.cmd, USBCMD_RS)
   263  }
   264  
   265  // Stop sets the controller in stop mode.
   266  func (hw *USB) Stop() {
   267  	reg.Clear(hw.cmd, USBCMD_RS)
   268  }
   269  
   270  // Reset waits for and handles a bus reset.
   271  func (hw *USB) Reset() {
   272  	hw.Lock()
   273  	defer hw.Unlock()
   274  
   275  	reg.Wait(hw.sts, USBSTS_URI, 1, 1)
   276  
   277  	// p3792, 56.4.6.2.1 Bus Reset, IMX6ULLRM
   278  
   279  	// read and write back to clear setup token semaphores
   280  	reg.WriteBack(hw.setup)
   281  	// read and write back to clear setup status
   282  	reg.WriteBack(hw.complete)
   283  	// flush endpoint buffers
   284  	reg.Write(hw.flush, 0xffffffff)
   285  
   286  	reg.Wait(hw.sc, PORTSC_PR, 1, 0)
   287  
   288  	// clear reset
   289  	reg.Or(hw.sts, (1<<USBSTS_URI | 1<<USBSTS_UI))
   290  }