github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/imx6/usb/device.go (about) 1 // USB device mode support 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 11 12 import ( 13 "log" 14 "sync" 15 "time" 16 17 "github.com/f-secure-foundry/tamago/internal/reg" 18 "github.com/f-secure-foundry/tamago/soc/imx6" 19 ) 20 21 func init() { 22 if !imx6.Native { 23 return 24 } 25 26 // On i.MX6 the only way to detect if we are booting through Serial 27 // Download Mode over USB is to check whether the USB OTG1 controller 28 // was running in device mode prior to our own initialization. 29 if reg.Get(USB1_BASE+USB_UOGx_USBMODE, USBMODE_CM, 0b11) == USBMODE_CM_DEVICE && 30 reg.Get(USB1_BASE+USB_UOGx_USBCMD, USBCMD_RS, 1) != 0 { 31 sdp = true 32 } 33 } 34 35 // DeviceMode sets the USB controller in device mode. 36 func (hw *USB) DeviceMode() { 37 hw.Lock() 38 defer hw.Unlock() 39 40 reg.Set(hw.cmd, USBCMD_RST) 41 reg.Wait(hw.cmd, USBCMD_RST, 1, 0) 42 43 // p3872, 56.6.33 USB Device Mode (USB_nUSBMODE), IMX6ULLRM) 44 m := reg.Read(hw.mode) 45 46 // set device only controller 47 m = (m & ^uint32(0b11<<USBMODE_CM)) | (USBMODE_CM_DEVICE << USBMODE_CM) 48 // disable setup lockout 49 m |= (1 << USBMODE_SLOM) 50 // disable stream mode 51 m &^= (1 << USBMODE_SDIS) 52 53 reg.Write(hw.mode, m) 54 reg.Wait(hw.mode, USBMODE_CM, 0b11, USBMODE_CM_DEVICE) 55 56 // initialize endpoint queue head list 57 hw.initQH() 58 // set control endpoint 59 hw.set(0, IN, 64, true, 0) 60 hw.set(0, OUT, 64, true, 0) 61 62 // set OTG termination 63 reg.Set(hw.otg, OTGSC_OT) 64 65 // clear all pending interrupts 66 reg.Write(hw.sts, 0xffffffff) 67 68 // run 69 reg.Set(hw.cmd, USBCMD_RS) 70 } 71 72 // Start waits and handles configured USB endpoints in device mode, it should 73 // never return. Note that isochronous endpoints are not supported. 74 func (hw *USB) Start(dev *Device) { 75 var conf uint8 76 var wg sync.WaitGroup 77 78 for { 79 // check for bus reset 80 if reg.Get(hw.sts, USBSTS_URI, 1) == 1 { 81 // set inactive configuration 82 conf = 0 83 dev.ConfigurationValue = 0 84 85 // perform controller reset procedure 86 hw.Reset() 87 } 88 89 // wait for a setup packet 90 if !reg.WaitFor(10*time.Millisecond, hw.setup, 0, 1, 1) { 91 continue 92 } 93 94 // handle setup packet 95 if err := hw.handleSetup(dev, hw.getSetup()); err != nil { 96 log.Printf("imx6_usb: setup error, %v", err) 97 } 98 99 // check if configuration reload is required 100 if dev.ConfigurationValue == conf { 101 continue 102 } else { 103 conf = dev.ConfigurationValue 104 } 105 106 // stop configuration endpoints 107 if hw.done != nil { 108 close(hw.done) 109 wg.Wait() 110 } 111 112 // start configuration endpoints 113 hw.startEndpoints(&wg, dev, conf) 114 } 115 }