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 }