* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (260 commits) usb: renesas_usbhs: fixup inconsistent return from usbhs_pkt_push() usb/isp1760: Allow to optionally trigger low-level chip reset via GPIOLIB. USB: gadget: midi: memory leak in f_midi_bind_config() USB: gadget: midi: fix range check in f_midi_out_open() QE/FHCI: fixed the CONTROL bug usb: renesas_usbhs: tidyup for smatch warnings USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms EHCI: workaround for MosChip controller bug usb: gadget: file_storage: fix race on unloading USB: ftdi_sio.c: Use ftdi async_icount structure for TIOCMIWAIT, as in other drivers USB: ftdi_sio.c:Fill MSR fields of the ftdi async_icount structure USB: ftdi_sio.c: Fill LSR fields of the ftdi async_icount structure USB: ftdi_sio.c:Fill TX field of the ftdi async_icount structure USB: ftdi_sio.c: Fill the RX field of the ftdi async_icount structure USB: ftdi_sio.c: Basic icount infrastructure for ftdi_sio usb/isp1760: Let OF bindings depend on general CONFIG_OF instead of PPC_OF . USB: ftdi_sio: Support TI/Luminary Micro Stellaris BD-ICDI Board USB: Fix runtime wakeup on OHCI xHCI/USB: Make xHCI driver have a BOS descriptor. usb: gadget: add new usb gadget for ACM and mass storage ...
Unified · Split
| @@ -0,0 +1,46 @@ | ||
| 1 | +What: /sys/bus/pci/drivers/ehci_hcd/.../companion | |
| 2 | + /sys/bus/usb/devices/usbN/../companion | |
| 3 | +Date: January 2007 | |
| 4 | +KernelVersion: 2.6.21 | |
| 5 | +Contact: Alan Stern <stern@rowland.harvard.edu> | |
| 6 | +Description: | |
| 7 | + PCI-based EHCI USB controllers (i.e., high-speed USB-2.0 | |
| 8 | + controllers) are often implemented along with a set of | |
| 9 | + "companion" full/low-speed USB-1.1 controllers. When a | |
| 10 | + high-speed device is plugged in, the connection is routed | |
| 11 | + to the EHCI controller; when a full- or low-speed device | |
| 12 | + is plugged in, the connection is routed to the companion | |
| 13 | + controller. | |
| 14 | + | |
| 15 | + Sometimes you want to force a high-speed device to connect | |
| 16 | + at full speed, which can be accomplished by forcing the | |
| 17 | + connection to be routed to the companion controller. | |
| 18 | + That's what this file does. Writing a port number to the | |
| 19 | + file causes connections on that port to be routed to the | |
| 20 | + companion controller, and writing the negative of a port | |
| 21 | + number returns the port to normal operation. | |
| 22 | + | |
| 23 | + For example: To force the high-speed device attached to | |
| 24 | + port 4 on bus 2 to run at full speed: | |
| 25 | + | |
| 26 | + echo 4 >/sys/bus/usb/devices/usb2/../companion | |
| 27 | + | |
| 28 | + To return the port to high-speed operation: | |
| 29 | + | |
| 30 | + echo -4 >/sys/bus/usb/devices/usb2/../companion | |
| 31 | + | |
| 32 | + Reading the file gives the list of ports currently forced | |
| 33 | + to the companion controller. | |
| 34 | + | |
| 35 | + Note: Some EHCI controllers do not have companions; they | |
| 36 | + may contain an internal "transaction translator" or they | |
| 37 | + may be attached directly to a "rate-matching hub". This | |
| 38 | + mechanism will not work with such controllers. Also, it | |
| 39 | + cannot be used to force a port on a high-speed hub to | |
| 40 | + connect at full speed. | |
| 41 | + | |
| 42 | + Note: When this file was first added, it appeared in a | |
| 43 | + different sysfs directory. The location given above is | |
| 44 | + correct for 2.6.35 (and probably several earlier kernel | |
| 45 | + versions as well). | |
| 46 | + | |
| @@ -142,3 +142,18 @@ Description: · 141 unmodified lines | ||
| 142 | 142 | such devices. |
| 143 | 143 | Users: |
| 144 | 144 | usb_modeswitch |
| 145 | + | |
| 146 | +What: /sys/bus/usb/devices/.../power/usb2_hardware_lpm | |
| 147 | +Date: September 2011 | |
| 148 | +Contact: Andiry Xu <andiry.xu@amd.com> | |
| 149 | +Description: | |
| 150 | + If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device | |
| 151 | + is plugged in to a xHCI host which support link PM, it will | |
| 152 | + perform a LPM test; if the test is passed and host supports | |
| 153 | + USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will | |
| 154 | + be enabled for the device and the USB device directory will | |
| 155 | + contain a file named power/usb2_hardware_lpm. The file holds | |
| 156 | + a string value (enable or disable) indicating whether or not | |
| 157 | + USB2 hardware LPM is enabled for the device. Developer can | |
| 158 | + write y/Y/1 or n/N/0 to the file to enable/disable the | |
| 159 | + feature. | |
| @@ -0,0 +1,45 @@ | ||
| 1 | + | |
| 2 | + TODO | |
| 3 | +~~~~~~ | |
| 4 | +Please pick something while reading :) | |
| 5 | + | |
| 6 | +- Convert interrupt handler to per-ep-thread-irq | |
| 7 | + | |
| 8 | + As it turns out some DWC3-commands ~1ms to complete. Currently we spin | |
| 9 | + until the command completes which is bad. | |
| 10 | + | |
| 11 | + Implementation idea: | |
| 12 | + - dwc core implements a demultiplexing irq chip for interrupts per | |
| 13 | + endpoint. The interrupt numbers are allocated during probe and belong | |
| 14 | + to the device. If MSI provides per-endpoint interrupt this dummy | |
| 15 | + interrupt chip can be replaced with "real" interrupts. | |
| 16 | + - interrupts are requested / allocated on usb_ep_enable() and removed on | |
| 17 | + usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two | |
| 18 | + for ep0/1. | |
| 19 | + - dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout() | |
| 20 | + until the command completes. | |
| 21 | + - the interrupt handler is split into the following pieces: | |
| 22 | + - primary handler of the device | |
| 23 | + goes through every event and calls generic_handle_irq() for event | |
| 24 | + it. On return from generic_handle_irq() in acknowledges the event | |
| 25 | + counter so interrupt goes away (eventually). | |
| 26 | + | |
| 27 | + - threaded handler of the device | |
| 28 | + none | |
| 29 | + | |
| 30 | + - primary handler of the EP-interrupt | |
| 31 | + reads the event and tries to process it. Everything that requries | |
| 32 | + sleeping is handed over to the Thread. The event is saved in an | |
| 33 | + per-endpoint data-structure. | |
| 34 | + We probably have to pay attention not to process events once we | |
| 35 | + handed something to thread so we don't process event X prio Y | |
| 36 | + where X > Y. | |
| 37 | + | |
| 38 | + - threaded handler of the EP-interrupt | |
| 39 | + handles the remaining EP work which might sleep such as waiting | |
| 40 | + for command completion. | |
| 41 | + | |
| 42 | + Latency: | |
| 43 | + There should be no increase in latency since the interrupt-thread has a | |
| 44 | + high priority and will be run before an average task in user land | |
| 45 | + (except the user changed priorities). | |
| @@ -487,3 +487,29 @@ succeed, it may still remain active and thus cause the system to · 486 unmodified lines | ||
| 487 | 487 | resume as soon as the system suspend is complete. Or the remote |
| 488 | 488 | wakeup may fail and get lost. Which outcome occurs depends on timing |
| 489 | 489 | and on the hardware and firmware design. |
| 490 | + | |
| 491 | + | |
| 492 | + xHCI hardware link PM | |
| 493 | + --------------------- | |
| 494 | + | |
| 495 | +xHCI host controller provides hardware link power management to usb2.0 | |
| 496 | +(xHCI 1.0 feature) and usb3.0 devices which support link PM. By | |
| 497 | +enabling hardware LPM, the host can automatically put the device into | |
| 498 | +lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices), | |
| 499 | +which state device can enter and resume very quickly. | |
| 500 | + | |
| 501 | +The user interface for controlling USB2 hardware LPM is located in the | |
| 502 | +power/ subdirectory of each USB device's sysfs directory, that is, in | |
| 503 | +/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The | |
| 504 | +relevant attribute files is usb2_hardware_lpm. | |
| 505 | + | |
| 506 | + power/usb2_hardware_lpm | |
| 507 | + | |
| 508 | + When a USB2 device which support LPM is plugged to a | |
| 509 | + xHCI host root hub which support software LPM, the | |
| 510 | + host will run a software LPM test for it; if the device | |
| 511 | + enters L1 state and resume successfully and the host | |
| 512 | + supports USB2 hardware LPM, this file will show up and | |
| 513 | + driver will enable hardware LPM for the device. You | |
| 514 | + can write y/Y/1 or n/N/0 to the file to enable/disable | |
| 515 | + USB2 hardware LPM manually. This is for test purpose mainly. | |
| @@ -2136,6 +2136,14 @@ M: Matthew Garrett <mjg59@srcf.ucam.org> · 2135 unmodified lines | ||
| 2136 | 2136 | S: Maintained |
| 2137 | 2137 | F: drivers/platform/x86/dell-wmi.c |
| 2138 | 2138 | |
| 2139 | +DESIGNWARE USB3 DRD IP DRIVER | |
| 2140 | +M: Felipe Balbi <balbi@ti.com> | |
| 2141 | +L: linux-usb@vger.kernel.org | |
| 2142 | +L: linux-omap@vger.kernel.org | |
| 2143 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git | |
| 2144 | +S: Maintained | |
| 2145 | +F: drivers/usb/dwc3/ | |
| 2146 | + | |
| 2139 | 2147 | DEVICE NUMBER REGISTRY |
| 2140 | 2148 | M: Torben Mathiasen <device@lanana.org> |
| 2141 | 2149 | W: http://lanana.org/docs/device-list/index.html |
| @@ -35,6 +35,13 @@ extern struct pxa_device_desc pxa168_device_fb; · 34 unmodified lines | ||
| 35 | 35 | extern struct pxa_device_desc pxa168_device_keypad; |
| 36 | 36 | extern struct pxa_device_desc pxa168_device_eth; |
| 37 | 37 | |
| 38 | +struct pxa168_usb_pdata { | |
| 39 | + /* If NULL, default phy init routine for PXA168 would be called */ | |
| 40 | + int (*phy_init)(void __iomem *usb_phy_reg_base); | |
| 41 | +}; | |
| 42 | +/* pdata can be NULL */ | |
| 43 | +int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata); | |
| 44 | + | |
| 38 | 45 | static inline int pxa168_add_uart(int id) |
| 39 | 46 | { |
| 40 | 47 | struct pxa_device_desc *d = NULL; |
| @@ -25,6 +25,9 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <mach/dma.h> |
| 26 | 26 | #include <mach/devices.h> |
| 27 | 27 | #include <mach/mfp.h> |
| 28 | +#include <linux/platform_device.h> | |
| 29 | +#include <linux/dma-mapping.h> | |
| 30 | +#include <mach/pxa168.h> | |
| 28 | 31 | |
| 29 | 32 | #include "common.h" |
| 30 | 33 | #include "clock.h" |
| @@ -83,6 +86,7 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000); · 52 unmodified lines | ||
| 83 | 86 | static APMU_CLK(nand, NAND, 0x19b, 156000000); |
| 84 | 87 | static APMU_CLK(lcd, LCD, 0x7f, 312000000); |
| 85 | 88 | static APMU_CLK(eth, ETH, 0x09, 0); |
| 89 | +static APMU_CLK(usb, USB, 0x12, 0); | |
| 86 | 90 | |
| 87 | 91 | /* device and clock bindings */ |
| 88 | 92 | static struct clk_lookup pxa168_clkregs[] = { |
| @@ -104,6 +108,7 @@ static struct clk_lookup pxa168_clkregs[] = { · 15 unmodified lines | ||
| 104 | 108 | INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), |
| 105 | 109 | INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), |
| 106 | 110 | INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), |
| 111 | + INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"), | |
| 107 | 112 | }; |
| 108 | 113 | |
| 109 | 114 | static int __init pxa168_init(void) |
| @@ -169,3 +174,44 @@ PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61); · 59 unmodified lines | ||
| 169 | 174 | PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8); |
| 170 | 175 | PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c); |
| 171 | 176 | PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff); |
| 177 | + | |
| 178 | +struct resource pxa168_usb_host_resources[] = { | |
| 179 | + /* USB Host conroller register base */ | |
| 180 | + [0] = { | |
| 181 | + .start = 0xd4209000, | |
| 182 | + .end = 0xd4209000 + 0x200, | |
| 183 | + .flags = IORESOURCE_MEM, | |
| 184 | + .name = "pxa168-usb-host", | |
| 185 | + }, | |
| 186 | + /* USB PHY register base */ | |
| 187 | + [1] = { | |
| 188 | + .start = 0xd4206000, | |
| 189 | + .end = 0xd4206000 + 0xff, | |
| 190 | + .flags = IORESOURCE_MEM, | |
| 191 | + .name = "pxa168-usb-phy", | |
| 192 | + }, | |
| 193 | + [2] = { | |
| 194 | + .start = IRQ_PXA168_USB2, | |
| 195 | + .end = IRQ_PXA168_USB2, | |
| 196 | + .flags = IORESOURCE_IRQ, | |
| 197 | + }, | |
| 198 | +}; | |
| 199 | + | |
| 200 | +static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32); | |
| 201 | +struct platform_device pxa168_device_usb_host = { | |
| 202 | + .name = "pxa168-ehci", | |
| 203 | + .id = -1, | |
| 204 | + .dev = { | |
| 205 | + .dma_mask = &pxa168_usb_host_dmamask, | |
| 206 | + .coherent_dma_mask = DMA_BIT_MASK(32), | |
| 207 | + }, | |
| 208 | + | |
| 209 | + .num_resources = ARRAY_SIZE(pxa168_usb_host_resources), | |
| 210 | + .resource = pxa168_usb_host_resources, | |
| 211 | +}; | |
| 212 | + | |
| 213 | +int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata) | |
| 214 | +{ | |
| 215 | + pxa168_device_usb_host.dev.platform_data = pdata; | |
| 216 | + return platform_device_register(&pxa168_device_usb_host); | |
| 217 | +} | |
| @@ -242,14 +242,11 @@ obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \ · 241 unmodified lines | ||
| 242 | 242 | obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ |
| 243 | 243 | hsmmc.o |
| 244 | 244 | obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \ |
| 245 | − hsmmc.o \ | |
| 246 | − omap_phy_internal.o | |
| 245 | + hsmmc.o | |
| 247 | 246 | obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \ |
| 248 | − hsmmc.o \ | |
| 249 | − omap_phy_internal.o | |
| 247 | + hsmmc.o | |
| 250 | 248 | |
| 251 | −obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \ | |
| 252 | − omap_phy_internal.o \ | |
| 249 | +obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o | |
| 253 | 250 | |
| 254 | 251 | obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o |
| 255 | 252 | |
| @@ -260,6 +257,8 @@ obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o · 4 unmodified lines | ||
| 260 | 257 | usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o |
| 261 | 258 | obj-y += $(usbfs-m) $(usbfs-y) |
| 262 | 259 | obj-y += usb-musb.o |
| 260 | +obj-y += omap_phy_internal.o | |
| 261 | + | |
| 263 | 262 | obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o |
| 264 | 263 | obj-y += usb-host.o |
| 265 | 264 | |
| @@ -810,6 +810,7 @@ static struct usbhs_private usbhs1_private = { · 809 unmodified lines | ||
| 810 | 810 | }, |
| 811 | 811 | .driver_param = { |
| 812 | 812 | .buswait_bwait = 4, |
| 813 | + .has_otg = 1, | |
| 813 | 814 | .pipe_type = usbhs1_pipe_cfg, |
| 814 | 815 | .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), |
| 815 | 816 | .d0_tx_id = SHDMA_SLAVE_USB1_TX, |
| @@ -12,6 +12,11 @@ menuconfig USB_SUPPORT · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | if USB_SUPPORT |
| 14 | 14 | |
| 15 | +config USB_COMMON | |
| 16 | + tristate | |
| 17 | + default y | |
| 18 | + depends on USB || USB_GADGET | |
| 19 | + | |
| 15 | 20 | # Host-side USB depends on having a host controller |
| 16 | 21 | # NOTE: dummy_hcd is always an option, but it's ignored here ... |
| 17 | 22 | # NOTE: SL-811 option should be board-specific ... |
| @@ -19,6 +24,7 @@ config USB_ARCH_HAS_HCD · 1 unmodified line | ||
| 19 | 24 | boolean |
| 20 | 25 | default y if USB_ARCH_HAS_OHCI |
| 21 | 26 | default y if USB_ARCH_HAS_EHCI |
| 27 | + default y if USB_ARCH_HAS_XHCI | |
| 22 | 28 | default y if PCMCIA && !M32R # sl811_cs |
| 23 | 29 | default y if ARM # SL-811 |
| 24 | 30 | default y if BLACKFIN # SL-811 |
| @@ -54,7 +60,7 @@ config USB_ARCH_HAS_OHCI · 29 unmodified lines | ||
| 54 | 60 | # some non-PCI hcds implement EHCI |
| 55 | 61 | config USB_ARCH_HAS_EHCI |
| 56 | 62 | boolean |
| 57 | − default y if PPC_83xx | |
| 63 | + default y if FSL_SOC | |
| 58 | 64 | default y if PPC_MPC512x |
| 59 | 65 | default y if SOC_AU1200 |
| 60 | 66 | default y if ARCH_IXP4XX |
| @@ -69,6 +75,12 @@ config USB_ARCH_HAS_EHCI · 8 unmodified lines | ||
| 69 | 75 | default y if ARCH_MSM |
| 70 | 76 | default y if MICROBLAZE |
| 71 | 77 | default y if SPARC_LEON |
| 78 | + default y if ARCH_MMP | |
| 79 | + default PCI | |
| 80 | + | |
| 81 | +# some non-PCI HCDs implement xHCI | |
| 82 | +config USB_ARCH_HAS_XHCI | |
| 83 | + boolean | |
| 72 | 84 | default PCI |
| 73 | 85 | |
| 74 | 86 | # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. |
| @@ -110,6 +122,8 @@ config USB · 35 unmodified lines | ||
| 110 | 122 | |
| 111 | 123 | source "drivers/usb/core/Kconfig" |
| 112 | 124 | |
| 125 | +source "drivers/usb/dwc3/Kconfig" | |
| 126 | + | |
| 113 | 127 | source "drivers/usb/mon/Kconfig" |
| 114 | 128 | |
| 115 | 129 | source "drivers/usb/wusbcore/Kconfig" |
| @@ -6,6 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | obj-$(CONFIG_USB) += core/ |
| 8 | 8 | |
| 9 | +obj-$(CONFIG_USB_DWC3) += dwc3/ | |
| 10 | + | |
| 9 | 11 | obj-$(CONFIG_USB_MON) += mon/ |
| 10 | 12 | |
| 11 | 13 | obj-$(CONFIG_PCI) += host/ |
| @@ -51,3 +53,5 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb/ · 39 unmodified lines | ||
| 51 | 53 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/ |
| 52 | 54 | obj-$(CONFIG_USB_OTG_UTILS) += otg/ |
| 53 | 55 | obj-$(CONFIG_USB_GADGET) += gadget/ |
| 56 | + | |
| 57 | +obj-$(CONFIG_USB_COMMON) += usb-common.o | |
| @@ -1058,11 +1058,11 @@ made_compressed_probe: · 1057 unmodified lines | ||
| 1058 | 1058 | goto alloc_fail; |
| 1059 | 1059 | } |
| 1060 | 1060 | |
| 1061 | − ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); | |
| 1062 | − readsize = le16_to_cpu(epread->wMaxPacketSize) * | |
| 1061 | + ctrlsize = usb_endpoint_maxp(epctrl); | |
| 1062 | + readsize = usb_endpoint_maxp(epread) * | |
| 1063 | 1063 | (quirks == SINGLE_RX_URB ? 1 : 2); |
| 1064 | 1064 | acm->combined_interfaces = combined_interfaces; |
| 1065 | − acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; | |
| 1065 | + acm->writesize = usb_endpoint_maxp(epwrite) * 20; | |
| 1066 | 1066 | acm->control = control_interface; |
| 1067 | 1067 | acm->data = data_interface; |
| 1068 | 1068 | acm->minor = minor; |
| @@ -1534,6 +1534,9 @@ static const struct usb_device_id acm_ids[] = { · 465 unmodified lines | ||
| 1534 | 1534 | { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */ |
| 1535 | 1535 | { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ |
| 1536 | 1536 | |
| 1537 | + /* Support for Owen devices */ | |
| 1538 | + { USB_DEVICE(0x03eb, 0x0030), }, /* Owen SI30 */ | |
| 1539 | + | |
| 1537 | 1540 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
| 1538 | 1541 | |
| 1539 | 1542 | /* Support Lego NXT using pbLua firmware */ |
| @@ -682,7 +682,7 @@ next_desc: · 681 unmodified lines | ||
| 682 | 682 | if (!ep || !usb_endpoint_is_int_in(ep)) |
| 683 | 683 | goto err; |
| 684 | 684 | |
| 685 | − desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); | |
| 685 | + desc->wMaxPacketSize = usb_endpoint_maxp(ep); | |
| 686 | 686 | desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; |
| 687 | 687 | |
| 688 | 688 | desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); |
| @@ -186,8 +186,7 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) · 185 unmodified lines | ||
| 186 | 186 | for (n = 0; n < current_setting->desc.bNumEndpoints; n++) |
| 187 | 187 | if (current_setting->endpoint[n].desc.bEndpointAddress == |
| 188 | 188 | data->bulk_in) |
| 189 | − max_size = le16_to_cpu(current_setting->endpoint[n]. | |
| 190 | − desc.wMaxPacketSize); | |
| 189 | + max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc); | |
| 191 | 190 | |
| 192 | 191 | if (max_size == 0) { |
| 193 | 192 | dev_err(dev, "Couldn't get wMaxPacketSize\n"); |
| @@ -636,7 +635,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) · 442 unmodified lines | ||
| 636 | 635 | for (n = 0; n < current_setting->desc.bNumEndpoints; n++) { |
| 637 | 636 | desc = ¤t_setting->endpoint[n].desc; |
| 638 | 637 | if (desc->bEndpointAddress == data->bulk_in) |
| 639 | − max_size = le16_to_cpu(desc->wMaxPacketSize); | |
| 638 | + max_size = usb_endpoint_maxp(desc); | |
| 640 | 639 | } |
| 641 | 640 | |
| 642 | 641 | if (max_size == 0) { |
| @@ -124,9 +124,9 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, · 123 unmodified lines | ||
| 124 | 124 | |
| 125 | 125 | if (usb_endpoint_xfer_isoc(&ep->desc)) |
| 126 | 126 | max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * |
| 127 | − le16_to_cpu(ep->desc.wMaxPacketSize); | |
| 127 | + usb_endpoint_maxp(&ep->desc); | |
| 128 | 128 | else if (usb_endpoint_xfer_int(&ep->desc)) |
| 129 | − max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) * | |
| 129 | + max_tx = usb_endpoint_maxp(&ep->desc) * | |
| 130 | 130 | (desc->bMaxBurst + 1); |
| 131 | 131 | else |
| 132 | 132 | max_tx = 999999; |
| @@ -241,7 +241,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, · 108 unmodified lines | ||
| 241 | 241 | cfgno, inum, asnum, d->bEndpointAddress); |
| 242 | 242 | endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; |
| 243 | 243 | endpoint->desc.bInterval = 1; |
| 244 | − if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) | |
| 244 | + if (usb_endpoint_maxp(&endpoint->desc) > 8) | |
| 245 | 245 | endpoint->desc.wMaxPacketSize = cpu_to_le16(8); |
| 246 | 246 | } |
| 247 | 247 | |
| @@ -254,7 +254,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, · 6 unmodified lines | ||
| 254 | 254 | && usb_endpoint_xfer_bulk(d)) { |
| 255 | 255 | unsigned maxp; |
| 256 | 256 | |
| 257 | − maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff; | |
| 257 | + maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff; | |
| 258 | 258 | if (maxp != 512) |
| 259 | 259 | dev_warn(ddev, "config %d interface %d altsetting %d " |
| 260 | 260 | "bulk endpoint 0x%X has invalid maxpacket %d\n", |
| @@ -755,3 +755,106 @@ err2: · 494 unmodified lines | ||
| 755 | 755 | dev_err(ddev, "out of memory\n"); |
| 756 | 756 | return result; |
| 757 | 757 | } |
| 758 | + | |
| 759 | +void usb_release_bos_descriptor(struct usb_device *dev) | |
| 760 | +{ | |
| 761 | + if (dev->bos) { | |
| 762 | + kfree(dev->bos->desc); | |
| 763 | + kfree(dev->bos); | |
| 764 | + dev->bos = NULL; | |
| 765 | + } | |
| 766 | +} | |
| 767 | + | |
| 768 | +/* Get BOS descriptor set */ | |
| 769 | +int usb_get_bos_descriptor(struct usb_device *dev) | |
| 770 | +{ | |
| 771 | + struct device *ddev = &dev->dev; | |
| 772 | + struct usb_bos_descriptor *bos; | |
| 773 | + struct usb_dev_cap_header *cap; | |
| 774 | + unsigned char *buffer; | |
| 775 | + int length, total_len, num, i; | |
| 776 | + int ret; | |
| 777 | + | |
| 778 | + bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); | |
| 779 | + if (!bos) | |
| 780 | + return -ENOMEM; | |
| 781 | + | |
| 782 | + /* Get BOS descriptor */ | |
| 783 | + ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); | |
| 784 | + if (ret < USB_DT_BOS_SIZE) { | |
| 785 | + dev_err(ddev, "unable to get BOS descriptor\n"); | |
| 786 | + if (ret >= 0) | |
| 787 | + ret = -ENOMSG; | |
| 788 | + kfree(bos); | |
| 789 | + return ret; | |
| 790 | + } | |
| 791 | + | |
| 792 | + length = bos->bLength; | |
| 793 | + total_len = le16_to_cpu(bos->wTotalLength); | |
| 794 | + num = bos->bNumDeviceCaps; | |
| 795 | + kfree(bos); | |
| 796 | + if (total_len < length) | |
| 797 | + return -EINVAL; | |
| 798 | + | |
| 799 | + dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL); | |
| 800 | + if (!dev->bos) | |
| 801 | + return -ENOMEM; | |
| 802 | + | |
| 803 | + /* Now let's get the whole BOS descriptor set */ | |
| 804 | + buffer = kzalloc(total_len, GFP_KERNEL); | |
| 805 | + if (!buffer) { | |
| 806 | + ret = -ENOMEM; | |
| 807 | + goto err; | |
| 808 | + } | |
| 809 | + dev->bos->desc = (struct usb_bos_descriptor *)buffer; | |
| 810 | + | |
| 811 | + ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len); | |
| 812 | + if (ret < total_len) { | |
| 813 | + dev_err(ddev, "unable to get BOS descriptor set\n"); | |
| 814 | + if (ret >= 0) | |
| 815 | + ret = -ENOMSG; | |
| 816 | + goto err; | |
| 817 | + } | |
| 818 | + total_len -= length; | |
| 819 | + | |
| 820 | + for (i = 0; i < num; i++) { | |
| 821 | + buffer += length; | |
| 822 | + cap = (struct usb_dev_cap_header *)buffer; | |
| 823 | + length = cap->bLength; | |
| 824 | + | |
| 825 | + if (total_len < length) | |
| 826 | + break; | |
| 827 | + total_len -= length; | |
| 828 | + | |
| 829 | + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { | |
| 830 | + dev_warn(ddev, "descriptor type invalid, skip\n"); | |
| 831 | + continue; | |
| 832 | + } | |
| 833 | + | |
| 834 | + switch (cap->bDevCapabilityType) { | |
| 835 | + case USB_CAP_TYPE_WIRELESS_USB: | |
| 836 | + /* Wireless USB cap descriptor is handled by wusb */ | |
| 837 | + break; | |
| 838 | + case USB_CAP_TYPE_EXT: | |
| 839 | + dev->bos->ext_cap = | |
| 840 | + (struct usb_ext_cap_descriptor *)buffer; | |
| 841 | + break; | |
| 842 | + case USB_SS_CAP_TYPE: | |
| 843 | + dev->bos->ss_cap = | |
| 844 | + (struct usb_ss_cap_descriptor *)buffer; | |
| 845 | + break; | |
| 846 | + case CONTAINER_ID_TYPE: | |
| 847 | + dev->bos->ss_id = | |
| 848 | + (struct usb_ss_container_id_descriptor *)buffer; | |
| 849 | + break; | |
| 850 | + default: | |
| 851 | + break; | |
| 852 | + } | |
| 853 | + } | |
| 854 | + | |
| 855 | + return 0; | |
| 856 | + | |
| 857 | +err: | |
| 858 | + usb_release_bos_descriptor(dev); | |
| 859 | + return ret; | |
| 860 | +} | |
| @@ -190,7 +190,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, · 189 unmodified lines | ||
| 190 | 190 | dir = usb_endpoint_dir_in(desc) ? 'I' : 'O'; |
| 191 | 191 | |
| 192 | 192 | if (speed == USB_SPEED_HIGH) { |
| 193 | − switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { | |
| 193 | + switch (usb_endpoint_maxp(desc) & (0x03 << 11)) { | |
| 194 | 194 | case 1 << 11: |
| 195 | 195 | bandwidth = 2; break; |
| 196 | 196 | case 2 << 11: |
| @@ -240,7 +240,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, · 43 unmodified lines | ||
| 240 | 240 | |
| 241 | 241 | start += sprintf(start, format_endpt, desc->bEndpointAddress, dir, |
| 242 | 242 | desc->bmAttributes, type, |
| 243 | − (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * | |
| 243 | + (usb_endpoint_maxp(desc) & 0x07ff) * | |
| 244 | 244 | bandwidth, |
| 245 | 245 | interval, unit); |
| 246 | 246 | return start; |
| @@ -46,6 +46,7 @@ · 45 unmodified lines | ||
| 46 | 46 | #include <linux/cdev.h> |
| 47 | 47 | #include <linux/notifier.h> |
| 48 | 48 | #include <linux/security.h> |
| 49 | +#include <linux/user_namespace.h> | |
| 49 | 50 | #include <asm/uaccess.h> |
| 50 | 51 | #include <asm/byteorder.h> |
| 51 | 52 | #include <linux/moduleparam.h> |
| @@ -68,7 +69,7 @@ struct dev_state { · 16 unmodified lines | ||
| 68 | 69 | wait_queue_head_t wait; /* wake up if a request completed */ |
| 69 | 70 | unsigned int discsignr; |
| 70 | 71 | struct pid *disc_pid; |
| 71 | − uid_t disc_uid, disc_euid; | |
| 72 | + const struct cred *cred; | |
| 72 | 73 | void __user *disccontext; |
| 73 | 74 | unsigned long ifclaimed; |
| 74 | 75 | u32 secid; |
| @@ -79,7 +80,7 @@ struct async { · 4 unmodified lines | ||
| 79 | 80 | struct list_head asynclist; |
| 80 | 81 | struct dev_state *ps; |
| 81 | 82 | struct pid *pid; |
| 82 | − uid_t uid, euid; | |
| 83 | + const struct cred *cred; | |
| 83 | 84 | unsigned int signr; |
| 84 | 85 | unsigned int ifnum; |
| 85 | 86 | void __user *userbuffer; |
| @@ -248,6 +249,7 @@ static struct async *alloc_async(unsigned int numisoframes) · 162 unmodified lines | ||
| 248 | 249 | static void free_async(struct async *as) |
| 249 | 250 | { |
| 250 | 251 | put_pid(as->pid); |
| 252 | + put_cred(as->cred); | |
| 251 | 253 | kfree(as->urb->transfer_buffer); |
| 252 | 254 | kfree(as->urb->setup_packet); |
| 253 | 255 | usb_free_urb(as->urb); |
| @@ -393,9 +395,8 @@ static void async_completed(struct urb *urb) · 139 unmodified lines | ||
| 393 | 395 | struct dev_state *ps = as->ps; |
| 394 | 396 | struct siginfo sinfo; |
| 395 | 397 | struct pid *pid = NULL; |
| 396 | − uid_t uid = 0; | |
| 397 | − uid_t euid = 0; | |
| 398 | 398 | u32 secid = 0; |
| 399 | + const struct cred *cred = NULL; | |
| 399 | 400 | int signr; |
| 400 | 401 | |
| 401 | 402 | spin_lock(&ps->lock); |
| @@ -407,9 +408,8 @@ static void async_completed(struct urb *urb) · 5 unmodified lines | ||
| 407 | 408 | sinfo.si_errno = as->status; |
| 408 | 409 | sinfo.si_code = SI_ASYNCIO; |
| 409 | 410 | sinfo.si_addr = as->userurb; |
| 410 | − pid = as->pid; | |
| 411 | − uid = as->uid; | |
| 412 | − euid = as->euid; | |
| 411 | + pid = get_pid(as->pid); | |
| 412 | + cred = get_cred(as->cred); | |
| 413 | 413 | secid = as->secid; |
| 414 | 414 | } |
| 415 | 415 | snoop(&urb->dev->dev, "urb complete\n"); |
| @@ -422,9 +422,11 @@ static void async_completed(struct urb *urb) · 6 unmodified lines | ||
| 422 | 422 | cancel_bulk_urbs(ps, as->bulk_addr); |
| 423 | 423 | spin_unlock(&ps->lock); |
| 424 | 424 | |
| 425 | − if (signr) | |
| 426 | − kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, | |
| 427 | − euid, secid); | |
| 425 | + if (signr) { | |
| 426 | + kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid); | |
| 427 | + put_pid(pid); | |
| 428 | + put_cred(cred); | |
| 429 | + } | |
| 428 | 430 | |
| 429 | 431 | wake_up(&ps->wait); |
| 430 | 432 | } |
| @@ -607,9 +609,10 @@ static int findintfep(struct usb_device *dev, unsigned int ep) · 176 unmodified lines | ||
| 607 | 609 | } |
| 608 | 610 | |
| 609 | 611 | static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, |
| 610 | − unsigned int index) | |
| 612 | + unsigned int request, unsigned int index) | |
| 611 | 613 | { |
| 612 | 614 | int ret = 0; |
| 615 | + struct usb_host_interface *alt_setting; | |
| 613 | 616 | |
| 614 | 617 | if (ps->dev->state != USB_STATE_UNAUTHENTICATED |
| 615 | 618 | && ps->dev->state != USB_STATE_ADDRESS |
| @@ -618,6 +621,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, · 2 unmodified lines | ||
| 618 | 621 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) |
| 619 | 622 | return 0; |
| 620 | 623 | |
| 624 | + /* | |
| 625 | + * check for the special corner case 'get_device_id' in the printer | |
| 626 | + * class specification, where wIndex is (interface << 8 | altsetting) | |
| 627 | + * instead of just interface | |
| 628 | + */ | |
| 629 | + if (requesttype == 0xa1 && request == 0) { | |
| 630 | + alt_setting = usb_find_alt_setting(ps->dev->actconfig, | |
| 631 | + index >> 8, index & 0xff); | |
| 632 | + if (alt_setting | |
| 633 | + && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER) | |
| 634 | + index >>= 8; | |
| 635 | + } | |
| 636 | + | |
| 621 | 637 | index &= 0xff; |
| 622 | 638 | switch (requesttype & USB_RECIP_MASK) { |
| 623 | 639 | case USB_RECIP_ENDPOINT: |
| @@ -656,7 +672,6 @@ static int usbdev_open(struct inode *inode, struct file *file) · 32 unmodified lines | ||
| 656 | 672 | { |
| 657 | 673 | struct usb_device *dev = NULL; |
| 658 | 674 | struct dev_state *ps; |
| 659 | − const struct cred *cred = current_cred(); | |
| 660 | 675 | int ret; |
| 661 | 676 | |
| 662 | 677 | ret = -ENOMEM; |
| @@ -706,8 +721,7 @@ static int usbdev_open(struct inode *inode, struct file *file) · 43 unmodified lines | ||
| 706 | 721 | init_waitqueue_head(&ps->wait); |
| 707 | 722 | ps->discsignr = 0; |
| 708 | 723 | ps->disc_pid = get_pid(task_pid(current)); |
| 709 | − ps->disc_uid = cred->uid; | |
| 710 | − ps->disc_euid = cred->euid; | |
| 724 | + ps->cred = get_current_cred(); | |
| 711 | 725 | ps->disccontext = NULL; |
| 712 | 726 | ps->ifclaimed = 0; |
| 713 | 727 | security_task_getsecid(current, &ps->secid); |
| @@ -749,6 +763,7 @@ static int usbdev_release(struct inode *inode, struct file *file) · 35 unmodified lines | ||
| 749 | 763 | usb_unlock_device(dev); |
| 750 | 764 | usb_put_dev(dev); |
| 751 | 765 | put_pid(ps->disc_pid); |
| 766 | + put_cred(ps->cred); | |
| 752 | 767 | |
| 753 | 768 | as = async_getcompleted(ps); |
| 754 | 769 | while (as) { |
| @@ -770,7 +785,8 @@ static int proc_control(struct dev_state *ps, void __user *arg) · 15 unmodified lines | ||
| 770 | 785 | |
| 771 | 786 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
| 772 | 787 | return -EFAULT; |
| 773 | − ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex); | |
| 788 | + ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest, | |
| 789 | + ctrl.wIndex); | |
| 774 | 790 | if (ret) |
| 775 | 791 | return ret; |
| 776 | 792 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ |
| @@ -1048,7 +1064,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 271 unmodified lines | ||
| 1048 | 1064 | struct usb_host_endpoint *ep; |
| 1049 | 1065 | struct async *as; |
| 1050 | 1066 | struct usb_ctrlrequest *dr = NULL; |
| 1051 | − const struct cred *cred = current_cred(); | |
| 1052 | 1067 | unsigned int u, totlen, isofrmlen; |
| 1053 | 1068 | int ret, ifnum = -1; |
| 1054 | 1069 | int is_in; |
| @@ -1100,7 +1115,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 45 unmodified lines | ||
| 1100 | 1115 | kfree(dr); |
| 1101 | 1116 | return -EINVAL; |
| 1102 | 1117 | } |
| 1103 | − ret = check_ctrlrecip(ps, dr->bRequestType, | |
| 1118 | + ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, | |
| 1104 | 1119 | le16_to_cpup(&dr->wIndex)); |
| 1105 | 1120 | if (ret) { |
| 1106 | 1121 | kfree(dr); |
| @@ -1262,8 +1277,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 155 unmodified lines | ||
| 1262 | 1277 | as->signr = uurb->signr; |
| 1263 | 1278 | as->ifnum = ifnum; |
| 1264 | 1279 | as->pid = get_pid(task_pid(current)); |
| 1265 | − as->uid = cred->uid; | |
| 1266 | − as->euid = cred->euid; | |
| 1280 | + as->cred = get_current_cred(); | |
| 1267 | 1281 | security_task_getsecid(current, &as->secid); |
| 1268 | 1282 | if (!is_in && uurb->buffer_length > 0) { |
| 1269 | 1283 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
| @@ -1981,9 +1995,8 @@ static void usbdev_remove(struct usb_device *udev) · 711 unmodified lines | ||
| 1981 | 1995 | sinfo.si_errno = EPIPE; |
| 1982 | 1996 | sinfo.si_code = SI_ASYNCIO; |
| 1983 | 1997 | sinfo.si_addr = ps->disccontext; |
| 1984 | − kill_pid_info_as_uid(ps->discsignr, &sinfo, | |
| 1985 | − ps->disc_pid, ps->disc_uid, | |
| 1986 | − ps->disc_euid, ps->secid); | |
| 1998 | + kill_pid_info_as_cred(ps->discsignr, &sinfo, | |
| 1999 | + ps->disc_pid, ps->cred, ps->secid); | |
| 1987 | 2000 | } |
| 1988 | 2001 | } |
| 1989 | 2002 | } |
| @@ -1583,7 +1583,7 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) · 1582 unmodified lines | ||
| 1583 | 1583 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
| 1584 | 1584 | __func__, atomic_read(&intf->dev.power.usage_count), |
| 1585 | 1585 | status); |
| 1586 | − if (status > 0) | |
| 1586 | + if (status > 0 || status == -EINPROGRESS) | |
| 1587 | 1587 | status = 0; |
| 1588 | 1588 | return status; |
| 1589 | 1589 | } |
| @@ -1700,6 +1700,20 @@ int usb_runtime_idle(struct device *dev) · 110 unmodified lines | ||
| 1700 | 1700 | return 0; |
| 1701 | 1701 | } |
| 1702 | 1702 | |
| 1703 | +int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) | |
| 1704 | +{ | |
| 1705 | + struct usb_hcd *hcd = bus_to_hcd(udev->bus); | |
| 1706 | + int ret = -EPERM; | |
| 1707 | + | |
| 1708 | + if (hcd->driver->set_usb2_hw_lpm) { | |
| 1709 | + ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable); | |
| 1710 | + if (!ret) | |
| 1711 | + udev->usb2_hw_lpm_enabled = enable; | |
| 1712 | + } | |
| 1713 | + | |
| 1714 | + return ret; | |
| 1715 | +} | |
| 1716 | + | |
| 1703 | 1717 | #endif /* CONFIG_USB_SUSPEND */ |
| 1704 | 1718 | |
| 1705 | 1719 | struct bus_type usb_bus_type = { |
| @@ -56,7 +56,7 @@ static ssize_t show_ep_wMaxPacketSize(struct device *dev, · 55 unmodified lines | ||
| 56 | 56 | { |
| 57 | 57 | struct ep_device *ep = to_ep_device(dev); |
| 58 | 58 | return sprintf(buf, "%04x\n", |
| 59 | − le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); | |
| 59 | + usb_endpoint_maxp(ep->desc) & 0x07ff); | |
| 60 | 60 | } |
| 61 | 61 | static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); |
| 62 | 62 | |
| @@ -242,7 +242,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 241 unmodified lines | ||
| 242 | 242 | |
| 243 | 243 | pci_set_master(dev); |
| 244 | 244 | |
| 245 | − retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | |
| 245 | + retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); | |
| 246 | 246 | if (retval != 0) |
| 247 | 247 | goto unmap_registers; |
| 248 | 248 | set_hs_companion(dev, hcd); |
| @@ -442,7 +442,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) · 441 unmodified lines | ||
| 442 | 442 | struct usb_ctrlrequest *cmd; |
| 443 | 443 | u16 typeReq, wValue, wIndex, wLength; |
| 444 | 444 | u8 *ubuf = urb->transfer_buffer; |
| 445 | − u8 tbuf [sizeof (struct usb_hub_descriptor)] | |
| 445 | + /* | |
| 446 | + * tbuf should be as big as the BOS descriptor and | |
| 447 | + * the USB hub descriptor. | |
| 448 | + */ | |
| 449 | + u8 tbuf[USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE] | |
| 446 | 450 | __attribute__((aligned(4))); |
| 447 | 451 | const u8 *bufp = tbuf; |
| 448 | 452 | unsigned len = 0; |
| @@ -562,6 +566,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) · 113 unmodified lines | ||
| 562 | 566 | else /* unsupported IDs --> "protocol stall" */ |
| 563 | 567 | goto error; |
| 564 | 568 | break; |
| 569 | + case USB_DT_BOS << 8: | |
| 570 | + goto nongeneric; | |
| 565 | 571 | default: |
| 566 | 572 | goto error; |
| 567 | 573 | } |
| @@ -596,6 +602,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) · 28 unmodified lines | ||
| 596 | 602 | /* CLASS REQUESTS (and errors) */ |
| 597 | 603 | |
| 598 | 604 | default: |
| 605 | +nongeneric: | |
| 599 | 606 | /* non-generic request */ |
| 600 | 607 | switch (typeReq) { |
| 601 | 608 | case GetHubStatus: |
| @@ -605,6 +612,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) · 3 unmodified lines | ||
| 605 | 612 | case GetHubDescriptor: |
| 606 | 613 | len = sizeof (struct usb_hub_descriptor); |
| 607 | 614 | break; |
| 615 | + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: | |
| 616 | + /* len is returned by hub_control */ | |
| 617 | + break; | |
| 608 | 618 | } |
| 609 | 619 | status = hcd->driver->hub_control (hcd, |
| 610 | 620 | typeReq, wValue, wIndex, |
| @@ -615,7 +625,7 @@ error: · 4 unmodified lines | ||
| 615 | 625 | status = -EPIPE; |
| 616 | 626 | } |
| 617 | 627 | |
| 618 | − if (status) { | |
| 628 | + if (status < 0) { | |
| 619 | 629 | len = 0; |
| 620 | 630 | if (status != -EPIPE) { |
| 621 | 631 | dev_dbg (hcd->self.controller, |
| @@ -624,6 +634,10 @@ error: · 2 unmodified lines | ||
| 624 | 634 | typeReq, wValue, wIndex, |
| 625 | 635 | wLength, status); |
| 626 | 636 | } |
| 637 | + } else if (status > 0) { | |
| 638 | + /* hub_control may return the length of data copied. */ | |
| 639 | + len = status; | |
| 640 | + status = 0; | |
| 627 | 641 | } |
| 628 | 642 | if (len) { |
| 629 | 643 | if (urb->transfer_buffer_length < len) |
| @@ -2429,7 +2443,7 @@ int usb_add_hcd(struct usb_hcd *hcd, · 1799 unmodified lines | ||
| 2429 | 2443 | * but drivers can override it in reset() if needed, along with |
| 2430 | 2444 | * recording the overall controller's system wakeup capability. |
| 2431 | 2445 | */ |
| 2432 | − device_init_wakeup(&rhdev->dev, 1); | |
| 2446 | + device_set_wakeup_capable(&rhdev->dev, 1); | |
| 2433 | 2447 | |
| 2434 | 2448 | /* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is |
| 2435 | 2449 | * registered. But since the controller can die at any time, |
| @@ -2478,6 +2492,13 @@ int usb_add_hcd(struct usb_hcd *hcd, · 42 unmodified lines | ||
| 2478 | 2492 | } |
| 2479 | 2493 | if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) |
| 2480 | 2494 | usb_hcd_poll_rh_status(hcd); |
| 2495 | + | |
| 2496 | + /* | |
| 2497 | + * Host controllers don't generate their own wakeup requests; | |
| 2498 | + * they only forward requests from the root hub. Therefore | |
| 2499 | + * controllers should always be enabled for remote wakeup. | |
| 2500 | + */ | |
| 2501 | + device_wakeup_enable(hcd->self.controller); | |
| 2481 | 2502 | return retval; |
| 2482 | 2503 | |
| 2483 | 2504 | error_create_attr_group: |
| @@ -1636,11 +1636,6 @@ void usb_disconnect(struct usb_device **pdev) · 1635 unmodified lines | ||
| 1636 | 1636 | int i; |
| 1637 | 1637 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
| 1638 | 1638 | |
| 1639 | − if (!udev) { | |
| 1640 | − pr_debug ("%s nodev\n", __func__); | |
| 1641 | − return; | |
| 1642 | − } | |
| 1643 | − | |
| 1644 | 1639 | /* mark the device as inactive, so any further urb submissions for |
| 1645 | 1640 | * this device (and any of its children) will fail immediately. |
| 1646 | 1641 | * this quiesces everything except pending urbs. |
| @@ -2030,11 +2025,23 @@ static unsigned hub_is_wusb(struct usb_hub *hub) · 383 unmodified lines | ||
| 2030 | 2025 | |
| 2031 | 2026 | #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ |
| 2032 | 2027 | #define HUB_SHORT_RESET_TIME 10 |
| 2028 | +#define HUB_BH_RESET_TIME 50 | |
| 2033 | 2029 | #define HUB_LONG_RESET_TIME 200 |
| 2034 | 2030 | #define HUB_RESET_TIMEOUT 500 |
| 2035 | 2031 | |
| 2032 | +static int hub_port_reset(struct usb_hub *hub, int port1, | |
| 2033 | + struct usb_device *udev, unsigned int delay, bool warm); | |
| 2034 | + | |
| 2035 | +/* Is a USB 3.0 port in the Inactive state? */ | |
| 2036 | +static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus) | |
| 2037 | +{ | |
| 2038 | + return hub_is_superspeed(hub->hdev) && | |
| 2039 | + (portstatus & USB_PORT_STAT_LINK_STATE) == | |
| 2040 | + USB_SS_PORT_LS_SS_INACTIVE; | |
| 2041 | +} | |
| 2042 | + | |
| 2036 | 2043 | static int hub_port_wait_reset(struct usb_hub *hub, int port1, |
| 2037 | − struct usb_device *udev, unsigned int delay) | |
| 2044 | + struct usb_device *udev, unsigned int delay, bool warm) | |
| 2038 | 2045 | { |
| 2039 | 2046 | int delay_time, ret; |
| 2040 | 2047 | u16 portstatus; |
| @@ -2051,28 +2058,71 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, · 10 unmodified lines | ||
| 2051 | 2058 | if (ret < 0) |
| 2052 | 2059 | return ret; |
| 2053 | 2060 | |
| 2054 | − /* Device went away? */ | |
| 2055 | − if (!(portstatus & USB_PORT_STAT_CONNECTION)) | |
| 2056 | − return -ENOTCONN; | |
| 2057 | − | |
| 2058 | − /* bomb out completely if the connection bounced */ | |
| 2059 | − if ((portchange & USB_PORT_STAT_C_CONNECTION)) | |
| 2060 | − return -ENOTCONN; | |
| 2061 | − | |
| 2062 | − /* if we`ve finished resetting, then break out of the loop */ | |
| 2063 | − if (!(portstatus & USB_PORT_STAT_RESET) && | |
| 2064 | − (portstatus & USB_PORT_STAT_ENABLE)) { | |
| 2065 | − if (hub_is_wusb(hub)) | |
| 2066 | − udev->speed = USB_SPEED_WIRELESS; | |
| 2067 | − else if (hub_is_superspeed(hub->hdev)) | |
| 2068 | − udev->speed = USB_SPEED_SUPER; | |
| 2069 | − else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | |
| 2070 | − udev->speed = USB_SPEED_HIGH; | |
| 2071 | − else if (portstatus & USB_PORT_STAT_LOW_SPEED) | |
| 2072 | − udev->speed = USB_SPEED_LOW; | |
| 2073 | − else | |
| 2074 | − udev->speed = USB_SPEED_FULL; | |
| 2075 | − return 0; | |
| 2061 | + /* | |
| 2062 | + * Some buggy devices require a warm reset to be issued even | |
| 2063 | + * when the port appears not to be connected. | |
| 2064 | + */ | |
| 2065 | + if (!warm) { | |
| 2066 | + /* | |
| 2067 | + * Some buggy devices can cause an NEC host controller | |
| 2068 | + * to transition to the "Error" state after a hot port | |
| 2069 | + * reset. This will show up as the port state in | |
| 2070 | + * "Inactive", and the port may also report a | |
| 2071 | + * disconnect. Forcing a warm port reset seems to make | |
| 2072 | + * the device work. | |
| 2073 | + * | |
| 2074 | + * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 | |
| 2075 | + */ | |
| 2076 | + if (hub_port_inactive(hub, portstatus)) { | |
| 2077 | + int ret; | |
| 2078 | + | |
| 2079 | + if ((portchange & USB_PORT_STAT_C_CONNECTION)) | |
| 2080 | + clear_port_feature(hub->hdev, port1, | |
| 2081 | + USB_PORT_FEAT_C_CONNECTION); | |
| 2082 | + if (portchange & USB_PORT_STAT_C_LINK_STATE) | |
| 2083 | + clear_port_feature(hub->hdev, port1, | |
| 2084 | + USB_PORT_FEAT_C_PORT_LINK_STATE); | |
| 2085 | + if (portchange & USB_PORT_STAT_C_RESET) | |
| 2086 | + clear_port_feature(hub->hdev, port1, | |
| 2087 | + USB_PORT_FEAT_C_RESET); | |
| 2088 | + dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", | |
| 2089 | + port1); | |
| 2090 | + ret = hub_port_reset(hub, port1, | |
| 2091 | + udev, HUB_BH_RESET_TIME, | |
| 2092 | + true); | |
| 2093 | + if ((portchange & USB_PORT_STAT_C_CONNECTION)) | |
| 2094 | + clear_port_feature(hub->hdev, port1, | |
| 2095 | + USB_PORT_FEAT_C_CONNECTION); | |
| 2096 | + return ret; | |
| 2097 | + } | |
| 2098 | + /* Device went away? */ | |
| 2099 | + if (!(portstatus & USB_PORT_STAT_CONNECTION)) | |
| 2100 | + return -ENOTCONN; | |
| 2101 | + | |
| 2102 | + /* bomb out completely if the connection bounced */ | |
| 2103 | + if ((portchange & USB_PORT_STAT_C_CONNECTION)) | |
| 2104 | + return -ENOTCONN; | |
| 2105 | + | |
| 2106 | + /* if we`ve finished resetting, then break out of | |
| 2107 | + * the loop | |
| 2108 | + */ | |
| 2109 | + if (!(portstatus & USB_PORT_STAT_RESET) && | |
| 2110 | + (portstatus & USB_PORT_STAT_ENABLE)) { | |
| 2111 | + if (hub_is_wusb(hub)) | |
| 2112 | + udev->speed = USB_SPEED_WIRELESS; | |
| 2113 | + else if (hub_is_superspeed(hub->hdev)) | |
| 2114 | + udev->speed = USB_SPEED_SUPER; | |
| 2115 | + else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | |
| 2116 | + udev->speed = USB_SPEED_HIGH; | |
| 2117 | + else if (portstatus & USB_PORT_STAT_LOW_SPEED) | |
| 2118 | + udev->speed = USB_SPEED_LOW; | |
| 2119 | + else | |
| 2120 | + udev->speed = USB_SPEED_FULL; | |
| 2121 | + return 0; | |
| 2122 | + } | |
| 2123 | + } else { | |
| 2124 | + if (portchange & USB_PORT_STAT_C_BH_RESET) | |
| 2125 | + return 0; | |
| 2076 | 2126 | } |
| 2077 | 2127 | |
| 2078 | 2128 | /* switch to the long delay after two short delay failures */ |
| @@ -2080,35 +2130,84 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, · 1 unmodified line | ||
| 2080 | 2130 | delay = HUB_LONG_RESET_TIME; |
| 2081 | 2131 | |
| 2082 | 2132 | dev_dbg (hub->intfdev, |
| 2083 | − "port %d not reset yet, waiting %dms\n", | |
| 2084 | − port1, delay); | |
| 2133 | + "port %d not %sreset yet, waiting %dms\n", | |
| 2134 | + port1, warm ? "warm " : "", delay); | |
| 2085 | 2135 | } |
| 2086 | 2136 | |
| 2087 | 2137 | return -EBUSY; |
| 2088 | 2138 | } |
| 2089 | 2139 | |
| 2140 | +static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |
| 2141 | + struct usb_device *udev, int *status, bool warm) | |
| 2142 | +{ | |
| 2143 | + switch (*status) { | |
| 2144 | + case 0: | |
| 2145 | + if (!warm) { | |
| 2146 | + struct usb_hcd *hcd; | |
| 2147 | + /* TRSTRCY = 10 ms; plus some extra */ | |
| 2148 | + msleep(10 + 40); | |
| 2149 | + update_devnum(udev, 0); | |
| 2150 | + hcd = bus_to_hcd(udev->bus); | |
| 2151 | + if (hcd->driver->reset_device) { | |
| 2152 | + *status = hcd->driver->reset_device(hcd, udev); | |
| 2153 | + if (*status < 0) { | |
| 2154 | + dev_err(&udev->dev, "Cannot reset " | |
| 2155 | + "HCD device state\n"); | |
| 2156 | + break; | |
| 2157 | + } | |
| 2158 | + } | |
| 2159 | + } | |
| 2160 | + /* FALL THROUGH */ | |
| 2161 | + case -ENOTCONN: | |
| 2162 | + case -ENODEV: | |
| 2163 | + clear_port_feature(hub->hdev, | |
| 2164 | + port1, USB_PORT_FEAT_C_RESET); | |
| 2165 | + /* FIXME need disconnect() for NOTATTACHED device */ | |
| 2166 | + if (warm) { | |
| 2167 | + clear_port_feature(hub->hdev, port1, | |
| 2168 | + USB_PORT_FEAT_C_BH_PORT_RESET); | |
| 2169 | + clear_port_feature(hub->hdev, port1, | |
| 2170 | + USB_PORT_FEAT_C_PORT_LINK_STATE); | |
| 2171 | + } else { | |
| 2172 | + usb_set_device_state(udev, *status | |
| 2173 | + ? USB_STATE_NOTATTACHED | |
| 2174 | + : USB_STATE_DEFAULT); | |
| 2175 | + } | |
| 2176 | + break; | |
| 2177 | + } | |
| 2178 | +} | |
| 2179 | + | |
| 2180 | +/* Handle port reset and port warm(BH) reset (for USB3 protocol ports) */ | |
| 2090 | 2181 | static int hub_port_reset(struct usb_hub *hub, int port1, |
| 2091 | − struct usb_device *udev, unsigned int delay) | |
| 2182 | + struct usb_device *udev, unsigned int delay, bool warm) | |
| 2092 | 2183 | { |
| 2093 | 2184 | int i, status; |
| 2094 | − struct usb_hcd *hcd; | |
| 2095 | 2185 | |
| 2096 | − hcd = bus_to_hcd(udev->bus); | |
| 2097 | − /* Block EHCI CF initialization during the port reset. | |
| 2098 | − * Some companion controllers don't like it when they mix. | |
| 2099 | − */ | |
| 2100 | − down_read(&ehci_cf_port_reset_rwsem); | |
| 2186 | + if (!warm) { | |
| 2187 | + /* Block EHCI CF initialization during the port reset. | |
| 2188 | + * Some companion controllers don't like it when they mix. | |
| 2189 | + */ | |
| 2190 | + down_read(&ehci_cf_port_reset_rwsem); | |
| 2191 | + } else { | |
| 2192 | + if (!hub_is_superspeed(hub->hdev)) { | |
| 2193 | + dev_err(hub->intfdev, "only USB3 hub support " | |
| 2194 | + "warm reset\n"); | |
| 2195 | + return -EINVAL; | |
| 2196 | + } | |
| 2197 | + } | |
| 2101 | 2198 | |
| 2102 | 2199 | /* Reset the port */ |
| 2103 | 2200 | for (i = 0; i < PORT_RESET_TRIES; i++) { |
| 2104 | − status = set_port_feature(hub->hdev, | |
| 2105 | − port1, USB_PORT_FEAT_RESET); | |
| 2106 | − if (status) | |
| 2201 | + status = set_port_feature(hub->hdev, port1, (warm ? | |
| 2202 | + USB_PORT_FEAT_BH_PORT_RESET : | |
| 2203 | + USB_PORT_FEAT_RESET)); | |
| 2204 | + if (status) { | |
| 2107 | 2205 | dev_err(hub->intfdev, |
| 2108 | − "cannot reset port %d (err = %d)\n", | |
| 2109 | − port1, status); | |
| 2110 | − else { | |
| 2111 | − status = hub_port_wait_reset(hub, port1, udev, delay); | |
| 2206 | + "cannot %sreset port %d (err = %d)\n", | |
| 2207 | + warm ? "warm " : "", port1, status); | |
| 2208 | + } else { | |
| 2209 | + status = hub_port_wait_reset(hub, port1, udev, delay, | |
| 2210 | + warm); | |
| 2112 | 2211 | if (status && status != -ENOTCONN) |
| 2113 | 2212 | dev_dbg(hub->intfdev, |
| 2114 | 2213 | "port_wait_reset: err = %d\n", |
| @@ -2116,34 +2215,14 @@ static int hub_port_reset(struct usb_hub *hub, int port1, · 1 unmodified line | ||
| 2116 | 2215 | } |
| 2117 | 2216 | |
| 2118 | 2217 | /* return on disconnect or reset */ |
| 2119 | − switch (status) { | |
| 2120 | − case 0: | |
| 2121 | − /* TRSTRCY = 10 ms; plus some extra */ | |
| 2122 | − msleep(10 + 40); | |
| 2123 | − update_devnum(udev, 0); | |
| 2124 | − if (hcd->driver->reset_device) { | |
| 2125 | − status = hcd->driver->reset_device(hcd, udev); | |
| 2126 | − if (status < 0) { | |
| 2127 | − dev_err(&udev->dev, "Cannot reset " | |
| 2128 | − "HCD device state\n"); | |
| 2129 | − break; | |
| 2130 | − } | |
| 2131 | − } | |
| 2132 | − /* FALL THROUGH */ | |
| 2133 | − case -ENOTCONN: | |
| 2134 | − case -ENODEV: | |
| 2135 | − clear_port_feature(hub->hdev, | |
| 2136 | − port1, USB_PORT_FEAT_C_RESET); | |
| 2137 | − /* FIXME need disconnect() for NOTATTACHED device */ | |
| 2138 | − usb_set_device_state(udev, status | |
| 2139 | − ? USB_STATE_NOTATTACHED | |
| 2140 | − : USB_STATE_DEFAULT); | |
| 2218 | + if (status == 0 || status == -ENOTCONN || status == -ENODEV) { | |
| 2219 | + hub_port_finish_reset(hub, port1, udev, &status, warm); | |
| 2141 | 2220 | goto done; |
| 2142 | 2221 | } |
| 2143 | 2222 | |
| 2144 | 2223 | dev_dbg (hub->intfdev, |
| 2145 | − "port %d not enabled, trying reset again...\n", | |
| 2146 | − port1); | |
| 2224 | + "port %d not enabled, trying %sreset again...\n", | |
| 2225 | + port1, warm ? "warm " : ""); | |
| 2147 | 2226 | delay = HUB_LONG_RESET_TIME; |
| 2148 | 2227 | } |
| 2149 | 2228 | |
| @@ -2151,45 +2230,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1, · 1 unmodified line | ||
| 2151 | 2230 | "Cannot enable port %i. Maybe the USB cable is bad?\n", |
| 2152 | 2231 | port1); |
| 2153 | 2232 | |
| 2154 | − done: | |
| 2155 | − up_read(&ehci_cf_port_reset_rwsem); | |
| 2156 | − return status; | |
| 2157 | −} | |
| 2158 | − | |
| 2159 | −/* Warm reset a USB3 protocol port */ | |
| 2160 | −static int hub_port_warm_reset(struct usb_hub *hub, int port) | |
| 2161 | −{ | |
| 2162 | − int ret; | |
| 2163 | − u16 portstatus, portchange; | |
| 2164 | − | |
| 2165 | − if (!hub_is_superspeed(hub->hdev)) { | |
| 2166 | − dev_err(hub->intfdev, "only USB3 hub support warm reset\n"); | |
| 2167 | − return -EINVAL; | |
| 2168 | − } | |
| 2169 | − | |
| 2170 | − /* Warm reset the port */ | |
| 2171 | − ret = set_port_feature(hub->hdev, | |
| 2172 | − port, USB_PORT_FEAT_BH_PORT_RESET); | |
| 2173 | − if (ret) { | |
| 2174 | − dev_err(hub->intfdev, "cannot warm reset port %d\n", port); | |
| 2175 | − return ret; | |
| 2176 | − } | |
| 2177 | − | |
| 2178 | − msleep(20); | |
| 2179 | − ret = hub_port_status(hub, port, &portstatus, &portchange); | |
| 2180 | − | |
| 2181 | − if (portchange & USB_PORT_STAT_C_RESET) | |
| 2182 | − clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET); | |
| 2183 | − | |
| 2184 | − if (portchange & USB_PORT_STAT_C_BH_RESET) | |
| 2185 | − clear_port_feature(hub->hdev, port, | |
| 2186 | − USB_PORT_FEAT_C_BH_PORT_RESET); | |
| 2187 | − | |
| 2188 | − if (portchange & USB_PORT_STAT_C_LINK_STATE) | |
| 2189 | − clear_port_feature(hub->hdev, port, | |
| 2190 | − USB_PORT_FEAT_C_PORT_LINK_STATE); | |
| 2233 | +done: | |
| 2234 | + if (!warm) | |
| 2235 | + up_read(&ehci_cf_port_reset_rwsem); | |
| 2191 | 2236 | |
| 2192 | − return ret; | |
| 2237 | + return status; | |
| 2193 | 2238 | } |
| 2194 | 2239 | |
| 2195 | 2240 | /* Check if a port is power on */ |
| @@ -2347,6 +2392,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) · 151 unmodified lines | ||
| 2347 | 2392 | } |
| 2348 | 2393 | } |
| 2349 | 2394 | |
| 2395 | + /* disable USB2 hardware LPM */ | |
| 2396 | + if (udev->usb2_hw_lpm_enabled == 1) | |
| 2397 | + usb_set_usb2_hardware_lpm(udev, 0); | |
| 2398 | + | |
| 2350 | 2399 | /* see 7.1.7.6 */ |
| 2351 | 2400 | if (hub_is_superspeed(hub->hdev)) |
| 2352 | 2401 | status = set_port_feature(hub->hdev, |
| @@ -2558,7 +2607,12 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) · 205 unmodified lines | ||
| 2558 | 2607 | if (status < 0) { |
| 2559 | 2608 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); |
| 2560 | 2609 | hub_port_logical_disconnect(hub, port1); |
| 2610 | + } else { | |
| 2611 | + /* Try to enable USB2 hardware LPM */ | |
| 2612 | + if (udev->usb2_hw_lpm_capable == 1) | |
| 2613 | + usb_set_usb2_hardware_lpm(udev, 1); | |
| 2561 | 2614 | } |
| 2615 | + | |
| 2562 | 2616 | return status; |
| 2563 | 2617 | } |
| 2564 | 2618 | |
| @@ -2798,7 +2852,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 233 unmodified lines | ||
| 2798 | 2852 | int i, j, retval; |
| 2799 | 2853 | unsigned delay = HUB_SHORT_RESET_TIME; |
| 2800 | 2854 | enum usb_device_speed oldspeed = udev->speed; |
| 2801 | − char *speed, *type; | |
| 2855 | + const char *speed; | |
| 2802 | 2856 | int devnum = udev->devnum; |
| 2803 | 2857 | |
| 2804 | 2858 | /* root hub ports have a slightly longer reset period |
| @@ -2819,7 +2873,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 14 unmodified lines | ||
| 2819 | 2873 | |
| 2820 | 2874 | /* Reset the device; full speed may morph to high speed */ |
| 2821 | 2875 | /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ |
| 2822 | − retval = hub_port_reset(hub, port1, udev, delay); | |
| 2876 | + retval = hub_port_reset(hub, port1, udev, delay, false); | |
| 2823 | 2877 | if (retval < 0) /* error or disconnect */ |
| 2824 | 2878 | goto fail; |
| 2825 | 2879 | /* success, speed is known */ |
| @@ -2858,25 +2912,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 32 unmodified lines | ||
| 2858 | 2912 | default: |
| 2859 | 2913 | goto fail; |
| 2860 | 2914 | } |
| 2861 | − | |
| 2862 | − type = ""; | |
| 2863 | − switch (udev->speed) { | |
| 2864 | − case USB_SPEED_LOW: speed = "low"; break; | |
| 2865 | − case USB_SPEED_FULL: speed = "full"; break; | |
| 2866 | − case USB_SPEED_HIGH: speed = "high"; break; | |
| 2867 | − case USB_SPEED_SUPER: | |
| 2868 | − speed = "super"; | |
| 2869 | − break; | |
| 2870 | − case USB_SPEED_WIRELESS: | |
| 2871 | − speed = "variable"; | |
| 2872 | − type = "Wireless "; | |
| 2873 | − break; | |
| 2874 | − default: speed = "?"; break; | |
| 2875 | − } | |
| 2915 | + | |
| 2916 | + if (udev->speed == USB_SPEED_WIRELESS) | |
| 2917 | + speed = "variable speed Wireless"; | |
| 2918 | + else | |
| 2919 | + speed = usb_speed_string(udev->speed); | |
| 2920 | + | |
| 2876 | 2921 | if (udev->speed != USB_SPEED_SUPER) |
| 2877 | 2922 | dev_info(&udev->dev, |
| 2878 | − "%s %s speed %sUSB device number %d using %s\n", | |
| 2879 | − (udev->config) ? "reset" : "new", speed, type, | |
| 2923 | + "%s %s USB device number %d using %s\n", | |
| 2924 | + (udev->config) ? "reset" : "new", speed, | |
| 2880 | 2925 | devnum, udev->bus->controller->driver->name); |
| 2881 | 2926 | |
| 2882 | 2927 | /* Set up TT records, if needed */ |
| @@ -2949,7 +2994,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 66 unmodified lines | ||
| 2949 | 2994 | buf->bMaxPacketSize0; |
| 2950 | 2995 | kfree(buf); |
| 2951 | 2996 | |
| 2952 | − retval = hub_port_reset(hub, port1, udev, delay); | |
| 2997 | + retval = hub_port_reset(hub, port1, udev, delay, false); | |
| 2953 | 2998 | if (retval < 0) /* error or disconnect */ |
| 2954 | 2999 | goto fail; |
| 2955 | 3000 | if (oldspeed != udev->speed) { |
| @@ -3023,7 +3068,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 67 unmodified lines | ||
| 3023 | 3068 | i = 512; |
| 3024 | 3069 | else |
| 3025 | 3070 | i = udev->descriptor.bMaxPacketSize0; |
| 3026 | − if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { | |
| 3071 | + if (usb_endpoint_maxp(&udev->ep0.desc) != i) { | |
| 3027 | 3072 | if (udev->speed == USB_SPEED_LOW || |
| 3028 | 3073 | !(i == 8 || i == 16 || i == 32 || i == 64)) { |
| 3029 | 3074 | dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); |
| @@ -3047,6 +3092,15 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, · 17 unmodified lines | ||
| 3047 | 3092 | goto fail; |
| 3048 | 3093 | } |
| 3049 | 3094 | |
| 3095 | + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { | |
| 3096 | + retval = usb_get_bos_descriptor(udev); | |
| 3097 | + if (!retval) { | |
| 3098 | + if (udev->bos->ext_cap && (USB_LPM_SUPPORT & | |
| 3099 | + le32_to_cpu(udev->bos->ext_cap->bmAttributes))) | |
| 3100 | + udev->lpm_capable = 1; | |
| 3101 | + } | |
| 3102 | + } | |
| 3103 | + | |
| 3050 | 3104 | retval = 0; |
| 3051 | 3105 | /* notify HCD that we have a device connected and addressed */ |
| 3052 | 3106 | if (hcd->driver->update_device) |
| @@ -3570,7 +3624,8 @@ static void hub_events(void) · 517 unmodified lines | ||
| 3570 | 3624 | (portstatus & USB_PORT_STAT_LINK_STATE) |
| 3571 | 3625 | == USB_SS_PORT_LS_SS_INACTIVE) { |
| 3572 | 3626 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
| 3573 | − hub_port_warm_reset(hub, i); | |
| 3627 | + hub_port_reset(hub, i, NULL, | |
| 3628 | + HUB_BH_RESET_TIME, true); | |
| 3574 | 3629 | } |
| 3575 | 3630 | |
| 3576 | 3631 | if (connect_change) |
| @@ -435,7 +435,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, · 434 unmodified lines | ||
| 435 | 435 | |
| 436 | 436 | len = sg->length; |
| 437 | 437 | if (length) { |
| 438 | − len = min_t(unsigned, len, length); | |
| 438 | + len = min_t(size_t, len, length); | |
| 439 | 439 | length -= len; |
| 440 | 440 | if (length == 0) |
| 441 | 441 | io->entries = i + 1; |
| @@ -38,6 +38,27 @@ static const struct usb_device_id usb_quirk_list[] = { · 37 unmodified lines | ||
| 38 | 38 | /* Creative SB Audigy 2 NX */ |
| 39 | 39 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 40 | 40 | |
| 41 | + /* Logitech Webcam C200 */ | |
| 42 | + { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 43 | + | |
| 44 | + /* Logitech Webcam C250 */ | |
| 45 | + { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 46 | + | |
| 47 | + /* Logitech Webcam C300 */ | |
| 48 | + { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 49 | + | |
| 50 | + /* Logitech Webcam B/C500 */ | |
| 51 | + { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 52 | + | |
| 53 | + /* Logitech Webcam Pro 9000 */ | |
| 54 | + { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 55 | + | |
| 56 | + /* Logitech Webcam C310 */ | |
| 57 | + { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 58 | + | |
| 59 | + /* Logitech Webcam C270 */ | |
| 60 | + { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 61 | + | |
| 41 | 62 | /* Logitech Harmony 700-series */ |
| 42 | 63 | { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, |
| 43 | 64 | |
| @@ -69,6 +90,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 25 unmodified lines | ||
| 69 | 90 | { USB_DEVICE(0x06a3, 0x0006), .driver_info = |
| 70 | 91 | USB_QUIRK_CONFIG_INTF_STRINGS }, |
| 71 | 92 | |
| 93 | + /* Guillemot Webcam Hercules Dualpix Exchange*/ | |
| 94 | + { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 95 | + | |
| 72 | 96 | /* M-Systems Flash Disk Pioneers */ |
| 73 | 97 | { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 74 | 98 | |
| @@ -412,6 +412,56 @@ set_level(struct device *dev, struct device_attribute *attr, · 411 unmodified lines | ||
| 412 | 412 | |
| 413 | 413 | static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level); |
| 414 | 414 | |
| 415 | +static ssize_t | |
| 416 | +show_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr, | |
| 417 | + char *buf) | |
| 418 | +{ | |
| 419 | + struct usb_device *udev = to_usb_device(dev); | |
| 420 | + const char *p; | |
| 421 | + | |
| 422 | + if (udev->usb2_hw_lpm_enabled == 1) | |
| 423 | + p = "enabled"; | |
| 424 | + else | |
| 425 | + p = "disabled"; | |
| 426 | + | |
| 427 | + return sprintf(buf, "%s\n", p); | |
| 428 | +} | |
| 429 | + | |
| 430 | +static ssize_t | |
| 431 | +set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr, | |
| 432 | + const char *buf, size_t count) | |
| 433 | +{ | |
| 434 | + struct usb_device *udev = to_usb_device(dev); | |
| 435 | + bool value; | |
| 436 | + int ret; | |
| 437 | + | |
| 438 | + usb_lock_device(udev); | |
| 439 | + | |
| 440 | + ret = strtobool(buf, &value); | |
| 441 | + | |
| 442 | + if (!ret) | |
| 443 | + ret = usb_set_usb2_hardware_lpm(udev, value); | |
| 444 | + | |
| 445 | + usb_unlock_device(udev); | |
| 446 | + | |
| 447 | + if (!ret) | |
| 448 | + return count; | |
| 449 | + | |
| 450 | + return ret; | |
| 451 | +} | |
| 452 | + | |
| 453 | +static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, | |
| 454 | + set_usb2_hardware_lpm); | |
| 455 | + | |
| 456 | +static struct attribute *usb2_hardware_lpm_attr[] = { | |
| 457 | + &dev_attr_usb2_hardware_lpm.attr, | |
| 458 | + NULL, | |
| 459 | +}; | |
| 460 | +static struct attribute_group usb2_hardware_lpm_attr_group = { | |
| 461 | + .name = power_group_name, | |
| 462 | + .attrs = usb2_hardware_lpm_attr, | |
| 463 | +}; | |
| 464 | + | |
| 415 | 465 | static struct attribute *power_attrs[] = { |
| 416 | 466 | &dev_attr_autosuspend.attr, |
| 417 | 467 | &dev_attr_level.attr, |
| @@ -428,13 +478,20 @@ static int add_power_attributes(struct device *dev) · 10 unmodified lines | ||
| 428 | 478 | { |
| 429 | 479 | int rc = 0; |
| 430 | 480 | |
| 431 | − if (is_usb_device(dev)) | |
| 481 | + if (is_usb_device(dev)) { | |
| 482 | + struct usb_device *udev = to_usb_device(dev); | |
| 432 | 483 | rc = sysfs_merge_group(&dev->kobj, &power_attr_group); |
| 484 | + if (udev->usb2_hw_lpm_capable == 1) | |
| 485 | + rc = sysfs_merge_group(&dev->kobj, | |
| 486 | + &usb2_hardware_lpm_attr_group); | |
| 487 | + } | |
| 488 | + | |
| 433 | 489 | return rc; |
| 434 | 490 | } |
| 435 | 491 | |
| 436 | 492 | static void remove_power_attributes(struct device *dev) |
| 437 | 493 | { |
| 494 | + sysfs_unmerge_group(&dev->kobj, &usb2_hardware_lpm_attr_group); | |
| 438 | 495 | sysfs_unmerge_group(&dev->kobj, &power_attr_group); |
| 439 | 496 | } |
| 440 | 497 | |
| @@ -350,7 +350,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) · 349 unmodified lines | ||
| 350 | 350 | dev->state < USB_STATE_CONFIGURED) |
| 351 | 351 | return -ENODEV; |
| 352 | 352 | |
| 353 | − max = le16_to_cpu(ep->desc.wMaxPacketSize); | |
| 353 | + max = usb_endpoint_maxp(&ep->desc); | |
| 354 | 354 | if (max <= 0) { |
| 355 | 355 | dev_dbg(&dev->dev, |
| 356 | 356 | "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", |
| @@ -225,6 +225,7 @@ static void usb_release_dev(struct device *dev) · 224 unmodified lines | ||
| 225 | 225 | hcd = bus_to_hcd(udev->bus); |
| 226 | 226 | |
| 227 | 227 | usb_destroy_configuration(udev); |
| 228 | + usb_release_bos_descriptor(udev); | |
| 228 | 229 | usb_put_hcd(hcd); |
| 229 | 230 | kfree(udev->product); |
| 230 | 231 | kfree(udev->manufacturer); |
| @@ -28,6 +28,8 @@ extern int usb_remove_device(struct usb_device *udev); · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | extern int usb_get_device_descriptor(struct usb_device *dev, |
| 30 | 30 | unsigned int size); |
| 31 | +extern int usb_get_bos_descriptor(struct usb_device *dev); | |
| 32 | +extern void usb_release_bos_descriptor(struct usb_device *dev); | |
| 31 | 33 | extern char *usb_cache_string(struct usb_device *udev, int index); |
| 32 | 34 | extern int usb_set_configuration(struct usb_device *dev, int configuration); |
| 33 | 35 | extern int usb_choose_configuration(struct usb_device *udev); |
| @@ -80,6 +82,7 @@ extern int usb_remote_wakeup(struct usb_device *dev); · 46 unmodified lines | ||
| 80 | 82 | extern int usb_runtime_suspend(struct device *dev); |
| 81 | 83 | extern int usb_runtime_resume(struct device *dev); |
| 82 | 84 | extern int usb_runtime_idle(struct device *dev); |
| 85 | +extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); | |
| 83 | 86 | |
| 84 | 87 | #else |
| 85 | 88 | |
| @@ -94,6 +97,10 @@ static inline int usb_remote_wakeup(struct usb_device *udev) · 8 unmodified lines | ||
| 94 | 97 | return 0; |
| 95 | 98 | } |
| 96 | 99 | |
| 100 | +static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) | |
| 101 | +{ | |
| 102 | + return 0; | |
| 103 | +} | |
| 97 | 104 | #endif |
| 98 | 105 | |
| 99 | 106 | extern struct bus_type usb_bus_type; |
| @@ -0,0 +1,25 @@ | ||
| 1 | +config USB_DWC3 | |
| 2 | + tristate "DesignWare USB3 DRD Core Support" | |
| 3 | + depends on (USB || USB_GADGET) | |
| 4 | + select USB_OTG_UTILS | |
| 5 | + help | |
| 6 | + Say Y or M here if your system has a Dual Role SuperSpeed | |
| 7 | + USB controller based on the DesignWare USB3 IP Core. | |
| 8 | + | |
| 9 | + If you choose to build this driver is a dynamically linked | |
| 10 | + module, the module will be called dwc3.ko. | |
| 11 | + | |
| 12 | +if USB_DWC3 | |
| 13 | + | |
| 14 | +config USB_DWC3_DEBUG | |
| 15 | + bool "Enable Debugging Messages" | |
| 16 | + help | |
| 17 | + Say Y here to enable debugging messages on DWC3 Driver. | |
| 18 | + | |
| 19 | +config USB_DWC3_VERBOSE | |
| 20 | + bool "Enable Verbose Debugging Messages" | |
| 21 | + depends on USB_DWC3_DEBUG | |
| 22 | + help | |
| 23 | + Say Y here to enable verbose debugging messages on DWC3 Driver. | |
| 24 | + | |
| 25 | +endif | |
| @@ -0,0 +1,36 @@ | ||
| 1 | +ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG | |
| 2 | +ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG | |
| 3 | + | |
| 4 | +obj-$(CONFIG_USB_DWC3) += dwc3.o | |
| 5 | + | |
| 6 | +dwc3-y := core.o | |
| 7 | + | |
| 8 | +ifneq ($(CONFIG_USB_GADGET_DWC3),) | |
| 9 | + dwc3-y += gadget.o ep0.o | |
| 10 | +endif | |
| 11 | + | |
| 12 | +ifneq ($(CONFIG_DEBUG_FS),) | |
| 13 | + dwc3-y += debugfs.o | |
| 14 | +endif | |
| 15 | + | |
| 16 | +## | |
| 17 | +# Platform-specific glue layers go here | |
| 18 | +# | |
| 19 | +# NOTICE: Make sure your glue layer doesn't depend on anything | |
| 20 | +# which is arch-specific and that it compiles on all situations. | |
| 21 | +# | |
| 22 | +# We want to keep this requirement in order to be able to compile | |
| 23 | +# the entire driver (with all its glue layers) on several architectures | |
| 24 | +# and make sure it compiles fine. This will also help with allmodconfig | |
| 25 | +# and allyesconfig builds. | |
| 26 | +# | |
| 27 | +# The only exception is the PCI glue layer, but that's only because | |
| 28 | +# PCI doesn't provide nops if CONFIG_PCI isn't enabled. | |
| 29 | +## | |
| 30 | + | |
| 31 | +obj-$(CONFIG_USB_DWC3) += dwc3-omap.o | |
| 32 | + | |
| 33 | +ifneq ($(CONFIG_PCI),) | |
| 34 | + obj-$(CONFIG_USB_DWC3) += dwc3-pci.o | |
| 35 | +endif | |
| 36 | + | |
| @@ -0,0 +1,484 @@ | ||
| 1 | +/** | |
| 2 | + * core.c - DesignWare USB3 DRD Controller Core file | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/module.h> | |
| 40 | +#include <linux/kernel.h> | |
| 41 | +#include <linux/slab.h> | |
| 42 | +#include <linux/spinlock.h> | |
| 43 | +#include <linux/platform_device.h> | |
| 44 | +#include <linux/pm_runtime.h> | |
| 45 | +#include <linux/interrupt.h> | |
| 46 | +#include <linux/ioport.h> | |
| 47 | +#include <linux/io.h> | |
| 48 | +#include <linux/list.h> | |
| 49 | +#include <linux/delay.h> | |
| 50 | +#include <linux/dma-mapping.h> | |
| 51 | + | |
| 52 | +#include <linux/usb/ch9.h> | |
| 53 | +#include <linux/usb/gadget.h> | |
| 54 | +#include <linux/module.h> | |
| 55 | + | |
| 56 | +#include "core.h" | |
| 57 | +#include "gadget.h" | |
| 58 | +#include "io.h" | |
| 59 | + | |
| 60 | +#include "debug.h" | |
| 61 | + | |
| 62 | +/** | |
| 63 | + * dwc3_core_soft_reset - Issues core soft reset and PHY reset | |
| 64 | + * @dwc: pointer to our context structure | |
| 65 | + */ | |
| 66 | +static void dwc3_core_soft_reset(struct dwc3 *dwc) | |
| 67 | +{ | |
| 68 | + u32 reg; | |
| 69 | + | |
| 70 | + /* Before Resetting PHY, put Core in Reset */ | |
| 71 | + reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
| 72 | + reg |= DWC3_GCTL_CORESOFTRESET; | |
| 73 | + dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
| 74 | + | |
| 75 | + /* Assert USB3 PHY reset */ | |
| 76 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
| 77 | + reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; | |
| 78 | + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
| 79 | + | |
| 80 | + /* Assert USB2 PHY reset */ | |
| 81 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
| 82 | + reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; | |
| 83 | + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
| 84 | + | |
| 85 | + mdelay(100); | |
| 86 | + | |
| 87 | + /* Clear USB3 PHY reset */ | |
| 88 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
| 89 | + reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; | |
| 90 | + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
| 91 | + | |
| 92 | + /* Clear USB2 PHY reset */ | |
| 93 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
| 94 | + reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; | |
| 95 | + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
| 96 | + | |
| 97 | + /* After PHYs are stable we can take Core out of reset state */ | |
| 98 | + reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
| 99 | + reg &= ~DWC3_GCTL_CORESOFTRESET; | |
| 100 | + dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
| 101 | +} | |
| 102 | + | |
| 103 | +/** | |
| 104 | + * dwc3_free_one_event_buffer - Frees one event buffer | |
| 105 | + * @dwc: Pointer to our controller context structure | |
| 106 | + * @evt: Pointer to event buffer to be freed | |
| 107 | + */ | |
| 108 | +static void dwc3_free_one_event_buffer(struct dwc3 *dwc, | |
| 109 | + struct dwc3_event_buffer *evt) | |
| 110 | +{ | |
| 111 | + dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); | |
| 112 | + kfree(evt); | |
| 113 | +} | |
| 114 | + | |
| 115 | +/** | |
| 116 | + * dwc3_alloc_one_event_buffer - Allocated one event buffer structure | |
| 117 | + * @dwc: Pointer to our controller context structure | |
| 118 | + * @length: size of the event buffer | |
| 119 | + * | |
| 120 | + * Returns a pointer to the allocated event buffer structure on succes | |
| 121 | + * otherwise ERR_PTR(errno). | |
| 122 | + */ | |
| 123 | +static struct dwc3_event_buffer *__devinit | |
| 124 | +dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) | |
| 125 | +{ | |
| 126 | + struct dwc3_event_buffer *evt; | |
| 127 | + | |
| 128 | + evt = kzalloc(sizeof(*evt), GFP_KERNEL); | |
| 129 | + if (!evt) | |
| 130 | + return ERR_PTR(-ENOMEM); | |
| 131 | + | |
| 132 | + evt->dwc = dwc; | |
| 133 | + evt->length = length; | |
| 134 | + evt->buf = dma_alloc_coherent(dwc->dev, length, | |
| 135 | + &evt->dma, GFP_KERNEL); | |
| 136 | + if (!evt->buf) { | |
| 137 | + kfree(evt); | |
| 138 | + return ERR_PTR(-ENOMEM); | |
| 139 | + } | |
| 140 | + | |
| 141 | + return evt; | |
| 142 | +} | |
| 143 | + | |
| 144 | +/** | |
| 145 | + * dwc3_free_event_buffers - frees all allocated event buffers | |
| 146 | + * @dwc: Pointer to our controller context structure | |
| 147 | + */ | |
| 148 | +static void dwc3_free_event_buffers(struct dwc3 *dwc) | |
| 149 | +{ | |
| 150 | + struct dwc3_event_buffer *evt; | |
| 151 | + int i; | |
| 152 | + | |
| 153 | + for (i = 0; i < DWC3_EVENT_BUFFERS_NUM; i++) { | |
| 154 | + evt = dwc->ev_buffs[i]; | |
| 155 | + if (evt) { | |
| 156 | + dwc3_free_one_event_buffer(dwc, evt); | |
| 157 | + dwc->ev_buffs[i] = NULL; | |
| 158 | + } | |
| 159 | + } | |
| 160 | +} | |
| 161 | + | |
| 162 | +/** | |
| 163 | + * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length | |
| 164 | + * @dwc: Pointer to out controller context structure | |
| 165 | + * @num: number of event buffers to allocate | |
| 166 | + * @length: size of event buffer | |
| 167 | + * | |
| 168 | + * Returns 0 on success otherwise negative errno. In error the case, dwc | |
| 169 | + * may contain some buffers allocated but not all which were requested. | |
| 170 | + */ | |
| 171 | +static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned num, | |
| 172 | + unsigned length) | |
| 173 | +{ | |
| 174 | + int i; | |
| 175 | + | |
| 176 | + for (i = 0; i < num; i++) { | |
| 177 | + struct dwc3_event_buffer *evt; | |
| 178 | + | |
| 179 | + evt = dwc3_alloc_one_event_buffer(dwc, length); | |
| 180 | + if (IS_ERR(evt)) { | |
| 181 | + dev_err(dwc->dev, "can't allocate event buffer\n"); | |
| 182 | + return PTR_ERR(evt); | |
| 183 | + } | |
| 184 | + dwc->ev_buffs[i] = evt; | |
| 185 | + } | |
| 186 | + | |
| 187 | + return 0; | |
| 188 | +} | |
| 189 | + | |
| 190 | +/** | |
| 191 | + * dwc3_event_buffers_setup - setup our allocated event buffers | |
| 192 | + * @dwc: Pointer to out controller context structure | |
| 193 | + * | |
| 194 | + * Returns 0 on success otherwise negative errno. | |
| 195 | + */ | |
| 196 | +static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) | |
| 197 | +{ | |
| 198 | + struct dwc3_event_buffer *evt; | |
| 199 | + int n; | |
| 200 | + | |
| 201 | + for (n = 0; n < DWC3_EVENT_BUFFERS_NUM; n++) { | |
| 202 | + evt = dwc->ev_buffs[n]; | |
| 203 | + dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", | |
| 204 | + evt->buf, (unsigned long long) evt->dma, | |
| 205 | + evt->length); | |
| 206 | + | |
| 207 | + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), | |
| 208 | + lower_32_bits(evt->dma)); | |
| 209 | + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), | |
| 210 | + upper_32_bits(evt->dma)); | |
| 211 | + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), | |
| 212 | + evt->length & 0xffff); | |
| 213 | + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); | |
| 214 | + } | |
| 215 | + | |
| 216 | + return 0; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) | |
| 220 | +{ | |
| 221 | + struct dwc3_event_buffer *evt; | |
| 222 | + int n; | |
| 223 | + | |
| 224 | + for (n = 0; n < DWC3_EVENT_BUFFERS_NUM; n++) { | |
| 225 | + evt = dwc->ev_buffs[n]; | |
| 226 | + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); | |
| 227 | + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); | |
| 228 | + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); | |
| 229 | + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); | |
| 230 | + } | |
| 231 | +} | |
| 232 | + | |
| 233 | +static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) | |
| 234 | +{ | |
| 235 | + struct dwc3_hwparams *parms = &dwc->hwparams; | |
| 236 | + | |
| 237 | + parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); | |
| 238 | + parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); | |
| 239 | + parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); | |
| 240 | + parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); | |
| 241 | + parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); | |
| 242 | + parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); | |
| 243 | + parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); | |
| 244 | + parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); | |
| 245 | + parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); | |
| 246 | +} | |
| 247 | + | |
| 248 | +/** | |
| 249 | + * dwc3_core_init - Low-level initialization of DWC3 Core | |
| 250 | + * @dwc: Pointer to our controller context structure | |
| 251 | + * | |
| 252 | + * Returns 0 on success otherwise negative errno. | |
| 253 | + */ | |
| 254 | +static int __devinit dwc3_core_init(struct dwc3 *dwc) | |
| 255 | +{ | |
| 256 | + unsigned long timeout; | |
| 257 | + u32 reg; | |
| 258 | + int ret; | |
| 259 | + | |
| 260 | + reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); | |
| 261 | + /* This should read as U3 followed by revision number */ | |
| 262 | + if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { | |
| 263 | + dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); | |
| 264 | + ret = -ENODEV; | |
| 265 | + goto err0; | |
| 266 | + } | |
| 267 | + dwc->revision = reg & DWC3_GSNPSREV_MASK; | |
| 268 | + | |
| 269 | + dwc3_core_soft_reset(dwc); | |
| 270 | + | |
| 271 | + /* issue device SoftReset too */ | |
| 272 | + timeout = jiffies + msecs_to_jiffies(500); | |
| 273 | + dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); | |
| 274 | + do { | |
| 275 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 276 | + if (!(reg & DWC3_DCTL_CSFTRST)) | |
| 277 | + break; | |
| 278 | + | |
| 279 | + if (time_after(jiffies, timeout)) { | |
| 280 | + dev_err(dwc->dev, "Reset Timed Out\n"); | |
| 281 | + ret = -ETIMEDOUT; | |
| 282 | + goto err0; | |
| 283 | + } | |
| 284 | + | |
| 285 | + cpu_relax(); | |
| 286 | + } while (true); | |
| 287 | + | |
| 288 | + ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_NUM, | |
| 289 | + DWC3_EVENT_BUFFERS_SIZE); | |
| 290 | + if (ret) { | |
| 291 | + dev_err(dwc->dev, "failed to allocate event buffers\n"); | |
| 292 | + ret = -ENOMEM; | |
| 293 | + goto err1; | |
| 294 | + } | |
| 295 | + | |
| 296 | + ret = dwc3_event_buffers_setup(dwc); | |
| 297 | + if (ret) { | |
| 298 | + dev_err(dwc->dev, "failed to setup event buffers\n"); | |
| 299 | + goto err1; | |
| 300 | + } | |
| 301 | + | |
| 302 | + dwc3_cache_hwparams(dwc); | |
| 303 | + | |
| 304 | + return 0; | |
| 305 | + | |
| 306 | +err1: | |
| 307 | + dwc3_free_event_buffers(dwc); | |
| 308 | + | |
| 309 | +err0: | |
| 310 | + return ret; | |
| 311 | +} | |
| 312 | + | |
| 313 | +static void dwc3_core_exit(struct dwc3 *dwc) | |
| 314 | +{ | |
| 315 | + dwc3_event_buffers_cleanup(dwc); | |
| 316 | + dwc3_free_event_buffers(dwc); | |
| 317 | +} | |
| 318 | + | |
| 319 | +#define DWC3_ALIGN_MASK (16 - 1) | |
| 320 | + | |
| 321 | +static int __devinit dwc3_probe(struct platform_device *pdev) | |
| 322 | +{ | |
| 323 | + const struct platform_device_id *id = platform_get_device_id(pdev); | |
| 324 | + struct resource *res; | |
| 325 | + struct dwc3 *dwc; | |
| 326 | + void __iomem *regs; | |
| 327 | + unsigned int features = id->driver_data; | |
| 328 | + int ret = -ENOMEM; | |
| 329 | + int irq; | |
| 330 | + void *mem; | |
| 331 | + | |
| 332 | + mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); | |
| 333 | + if (!mem) { | |
| 334 | + dev_err(&pdev->dev, "not enough memory\n"); | |
| 335 | + goto err0; | |
| 336 | + } | |
| 337 | + dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); | |
| 338 | + dwc->mem = mem; | |
| 339 | + | |
| 340 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 341 | + if (!res) { | |
| 342 | + dev_err(&pdev->dev, "missing resource\n"); | |
| 343 | + goto err1; | |
| 344 | + } | |
| 345 | + | |
| 346 | + res = request_mem_region(res->start, resource_size(res), | |
| 347 | + dev_name(&pdev->dev)); | |
| 348 | + if (!res) { | |
| 349 | + dev_err(&pdev->dev, "can't request mem region\n"); | |
| 350 | + goto err1; | |
| 351 | + } | |
| 352 | + | |
| 353 | + regs = ioremap(res->start, resource_size(res)); | |
| 354 | + if (!regs) { | |
| 355 | + dev_err(&pdev->dev, "ioremap failed\n"); | |
| 356 | + goto err2; | |
| 357 | + } | |
| 358 | + | |
| 359 | + irq = platform_get_irq(pdev, 0); | |
| 360 | + if (irq < 0) { | |
| 361 | + dev_err(&pdev->dev, "missing IRQ\n"); | |
| 362 | + goto err3; | |
| 363 | + } | |
| 364 | + | |
| 365 | + spin_lock_init(&dwc->lock); | |
| 366 | + platform_set_drvdata(pdev, dwc); | |
| 367 | + | |
| 368 | + dwc->regs = regs; | |
| 369 | + dwc->regs_size = resource_size(res); | |
| 370 | + dwc->dev = &pdev->dev; | |
| 371 | + dwc->irq = irq; | |
| 372 | + | |
| 373 | + pm_runtime_enable(&pdev->dev); | |
| 374 | + pm_runtime_get_sync(&pdev->dev); | |
| 375 | + pm_runtime_forbid(&pdev->dev); | |
| 376 | + | |
| 377 | + ret = dwc3_core_init(dwc); | |
| 378 | + if (ret) { | |
| 379 | + dev_err(&pdev->dev, "failed to initialize core\n"); | |
| 380 | + goto err3; | |
| 381 | + } | |
| 382 | + | |
| 383 | + if (features & DWC3_HAS_PERIPHERAL) { | |
| 384 | + ret = dwc3_gadget_init(dwc); | |
| 385 | + if (ret) { | |
| 386 | + dev_err(&pdev->dev, "failed to initialized gadget\n"); | |
| 387 | + goto err4; | |
| 388 | + } | |
| 389 | + } | |
| 390 | + | |
| 391 | + ret = dwc3_debugfs_init(dwc); | |
| 392 | + if (ret) { | |
| 393 | + dev_err(&pdev->dev, "failed to initialize debugfs\n"); | |
| 394 | + goto err5; | |
| 395 | + } | |
| 396 | + | |
| 397 | + pm_runtime_allow(&pdev->dev); | |
| 398 | + | |
| 399 | + return 0; | |
| 400 | + | |
| 401 | +err5: | |
| 402 | + if (features & DWC3_HAS_PERIPHERAL) | |
| 403 | + dwc3_gadget_exit(dwc); | |
| 404 | + | |
| 405 | +err4: | |
| 406 | + dwc3_core_exit(dwc); | |
| 407 | + | |
| 408 | +err3: | |
| 409 | + iounmap(regs); | |
| 410 | + | |
| 411 | +err2: | |
| 412 | + release_mem_region(res->start, resource_size(res)); | |
| 413 | + | |
| 414 | +err1: | |
| 415 | + kfree(dwc->mem); | |
| 416 | + | |
| 417 | +err0: | |
| 418 | + return ret; | |
| 419 | +} | |
| 420 | + | |
| 421 | +static int __devexit dwc3_remove(struct platform_device *pdev) | |
| 422 | +{ | |
| 423 | + const struct platform_device_id *id = platform_get_device_id(pdev); | |
| 424 | + struct dwc3 *dwc = platform_get_drvdata(pdev); | |
| 425 | + struct resource *res; | |
| 426 | + unsigned int features = id->driver_data; | |
| 427 | + | |
| 428 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 429 | + | |
| 430 | + pm_runtime_put(&pdev->dev); | |
| 431 | + pm_runtime_disable(&pdev->dev); | |
| 432 | + | |
| 433 | + dwc3_debugfs_exit(dwc); | |
| 434 | + | |
| 435 | + if (features & DWC3_HAS_PERIPHERAL) | |
| 436 | + dwc3_gadget_exit(dwc); | |
| 437 | + | |
| 438 | + dwc3_core_exit(dwc); | |
| 439 | + release_mem_region(res->start, resource_size(res)); | |
| 440 | + iounmap(dwc->regs); | |
| 441 | + kfree(dwc->mem); | |
| 442 | + | |
| 443 | + return 0; | |
| 444 | +} | |
| 445 | + | |
| 446 | +static const struct platform_device_id dwc3_id_table[] __devinitconst = { | |
| 447 | + { | |
| 448 | + .name = "dwc3-omap", | |
| 449 | + .driver_data = (DWC3_HAS_PERIPHERAL | |
| 450 | + | DWC3_HAS_XHCI | |
| 451 | + | DWC3_HAS_OTG), | |
| 452 | + }, | |
| 453 | + { | |
| 454 | + .name = "dwc3-pci", | |
| 455 | + .driver_data = DWC3_HAS_PERIPHERAL, | |
| 456 | + }, | |
| 457 | + { }, /* Terminating Entry */ | |
| 458 | +}; | |
| 459 | +MODULE_DEVICE_TABLE(platform, dwc3_id_table); | |
| 460 | + | |
| 461 | +static struct platform_driver dwc3_driver = { | |
| 462 | + .probe = dwc3_probe, | |
| 463 | + .remove = __devexit_p(dwc3_remove), | |
| 464 | + .driver = { | |
| 465 | + .name = "dwc3", | |
| 466 | + }, | |
| 467 | + .id_table = dwc3_id_table, | |
| 468 | +}; | |
| 469 | + | |
| 470 | +MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |
| 471 | +MODULE_LICENSE("Dual BSD/GPL"); | |
| 472 | +MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); | |
| 473 | + | |
| 474 | +static int __devinit dwc3_init(void) | |
| 475 | +{ | |
| 476 | + return platform_driver_register(&dwc3_driver); | |
| 477 | +} | |
| 478 | +module_init(dwc3_init); | |
| 479 | + | |
| 480 | +static void __exit dwc3_exit(void) | |
| 481 | +{ | |
| 482 | + platform_driver_unregister(&dwc3_driver); | |
| 483 | +} | |
| 484 | +module_exit(dwc3_exit); | |
| @@ -0,0 +1,768 @@ | ||
| 1 | +/** | |
| 2 | + * core.h - DesignWare USB3 DRD Core Header | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#ifndef __DRIVERS_USB_DWC3_CORE_H | |
| 40 | +#define __DRIVERS_USB_DWC3_CORE_H | |
| 41 | + | |
| 42 | +#include <linux/device.h> | |
| 43 | +#include <linux/spinlock.h> | |
| 44 | +#include <linux/list.h> | |
| 45 | +#include <linux/dma-mapping.h> | |
| 46 | +#include <linux/mm.h> | |
| 47 | +#include <linux/debugfs.h> | |
| 48 | + | |
| 49 | +#include <linux/usb/ch9.h> | |
| 50 | +#include <linux/usb/gadget.h> | |
| 51 | + | |
| 52 | +/* Global constants */ | |
| 53 | +#define DWC3_ENDPOINTS_NUM 32 | |
| 54 | + | |
| 55 | +#define DWC3_EVENT_BUFFERS_NUM 2 | |
| 56 | +#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE | |
| 57 | +#define DWC3_EVENT_TYPE_MASK 0xfe | |
| 58 | + | |
| 59 | +#define DWC3_EVENT_TYPE_DEV 0 | |
| 60 | +#define DWC3_EVENT_TYPE_CARKIT 3 | |
| 61 | +#define DWC3_EVENT_TYPE_I2C 4 | |
| 62 | + | |
| 63 | +#define DWC3_DEVICE_EVENT_DISCONNECT 0 | |
| 64 | +#define DWC3_DEVICE_EVENT_RESET 1 | |
| 65 | +#define DWC3_DEVICE_EVENT_CONNECT_DONE 2 | |
| 66 | +#define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE 3 | |
| 67 | +#define DWC3_DEVICE_EVENT_WAKEUP 4 | |
| 68 | +#define DWC3_DEVICE_EVENT_EOPF 6 | |
| 69 | +#define DWC3_DEVICE_EVENT_SOF 7 | |
| 70 | +#define DWC3_DEVICE_EVENT_ERRATIC_ERROR 9 | |
| 71 | +#define DWC3_DEVICE_EVENT_CMD_CMPL 10 | |
| 72 | +#define DWC3_DEVICE_EVENT_OVERFLOW 11 | |
| 73 | + | |
| 74 | +#define DWC3_GEVNTCOUNT_MASK 0xfffc | |
| 75 | +#define DWC3_GSNPSID_MASK 0xffff0000 | |
| 76 | +#define DWC3_GSNPSREV_MASK 0xffff | |
| 77 | + | |
| 78 | +/* Global Registers */ | |
| 79 | +#define DWC3_GSBUSCFG0 0xc100 | |
| 80 | +#define DWC3_GSBUSCFG1 0xc104 | |
| 81 | +#define DWC3_GTXTHRCFG 0xc108 | |
| 82 | +#define DWC3_GRXTHRCFG 0xc10c | |
| 83 | +#define DWC3_GCTL 0xc110 | |
| 84 | +#define DWC3_GEVTEN 0xc114 | |
| 85 | +#define DWC3_GSTS 0xc118 | |
| 86 | +#define DWC3_GSNPSID 0xc120 | |
| 87 | +#define DWC3_GGPIO 0xc124 | |
| 88 | +#define DWC3_GUID 0xc128 | |
| 89 | +#define DWC3_GUCTL 0xc12c | |
| 90 | +#define DWC3_GBUSERRADDR0 0xc130 | |
| 91 | +#define DWC3_GBUSERRADDR1 0xc134 | |
| 92 | +#define DWC3_GPRTBIMAP0 0xc138 | |
| 93 | +#define DWC3_GPRTBIMAP1 0xc13c | |
| 94 | +#define DWC3_GHWPARAMS0 0xc140 | |
| 95 | +#define DWC3_GHWPARAMS1 0xc144 | |
| 96 | +#define DWC3_GHWPARAMS2 0xc148 | |
| 97 | +#define DWC3_GHWPARAMS3 0xc14c | |
| 98 | +#define DWC3_GHWPARAMS4 0xc150 | |
| 99 | +#define DWC3_GHWPARAMS5 0xc154 | |
| 100 | +#define DWC3_GHWPARAMS6 0xc158 | |
| 101 | +#define DWC3_GHWPARAMS7 0xc15c | |
| 102 | +#define DWC3_GDBGFIFOSPACE 0xc160 | |
| 103 | +#define DWC3_GDBGLTSSM 0xc164 | |
| 104 | +#define DWC3_GPRTBIMAP_HS0 0xc180 | |
| 105 | +#define DWC3_GPRTBIMAP_HS1 0xc184 | |
| 106 | +#define DWC3_GPRTBIMAP_FS0 0xc188 | |
| 107 | +#define DWC3_GPRTBIMAP_FS1 0xc18c | |
| 108 | + | |
| 109 | +#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) | |
| 110 | +#define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) | |
| 111 | + | |
| 112 | +#define DWC3_GUSB2PHYACC(n) (0xc280 + (n * 0x04)) | |
| 113 | + | |
| 114 | +#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04)) | |
| 115 | + | |
| 116 | +#define DWC3_GTXFIFOSIZ(n) (0xc300 + (n * 0x04)) | |
| 117 | +#define DWC3_GRXFIFOSIZ(n) (0xc380 + (n * 0x04)) | |
| 118 | + | |
| 119 | +#define DWC3_GEVNTADRLO(n) (0xc400 + (n * 0x10)) | |
| 120 | +#define DWC3_GEVNTADRHI(n) (0xc404 + (n * 0x10)) | |
| 121 | +#define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10)) | |
| 122 | +#define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) | |
| 123 | + | |
| 124 | +#define DWC3_GHWPARAMS8 0xc600 | |
| 125 | + | |
| 126 | +/* Device Registers */ | |
| 127 | +#define DWC3_DCFG 0xc700 | |
| 128 | +#define DWC3_DCTL 0xc704 | |
| 129 | +#define DWC3_DEVTEN 0xc708 | |
| 130 | +#define DWC3_DSTS 0xc70c | |
| 131 | +#define DWC3_DGCMDPAR 0xc710 | |
| 132 | +#define DWC3_DGCMD 0xc714 | |
| 133 | +#define DWC3_DALEPENA 0xc720 | |
| 134 | +#define DWC3_DEPCMDPAR2(n) (0xc800 + (n * 0x10)) | |
| 135 | +#define DWC3_DEPCMDPAR1(n) (0xc804 + (n * 0x10)) | |
| 136 | +#define DWC3_DEPCMDPAR0(n) (0xc808 + (n * 0x10)) | |
| 137 | +#define DWC3_DEPCMD(n) (0xc80c + (n * 0x10)) | |
| 138 | + | |
| 139 | +/* OTG Registers */ | |
| 140 | +#define DWC3_OCFG 0xcc00 | |
| 141 | +#define DWC3_OCTL 0xcc04 | |
| 142 | +#define DWC3_OEVTEN 0xcc08 | |
| 143 | +#define DWC3_OSTS 0xcc0C | |
| 144 | + | |
| 145 | +/* Bit fields */ | |
| 146 | + | |
| 147 | +/* Global Configuration Register */ | |
| 148 | +#define DWC3_GCTL_PWRDNSCALE(n) (n << 19) | |
| 149 | +#define DWC3_GCTL_U2RSTECN (1 << 16) | |
| 150 | +#define DWC3_GCTL_RAMCLKSEL(x) ((x & DWC3_GCTL_CLK_MASK) << 6) | |
| 151 | +#define DWC3_GCTL_CLK_BUS (0) | |
| 152 | +#define DWC3_GCTL_CLK_PIPE (1) | |
| 153 | +#define DWC3_GCTL_CLK_PIPEHALF (2) | |
| 154 | +#define DWC3_GCTL_CLK_MASK (3) | |
| 155 | + | |
| 156 | +#define DWC3_GCTL_PRTCAPDIR(n) (n << 12) | |
| 157 | +#define DWC3_GCTL_PRTCAP_HOST 1 | |
| 158 | +#define DWC3_GCTL_PRTCAP_DEVICE 2 | |
| 159 | +#define DWC3_GCTL_PRTCAP_OTG 3 | |
| 160 | + | |
| 161 | +#define DWC3_GCTL_CORESOFTRESET (1 << 11) | |
| 162 | +#define DWC3_GCTL_SCALEDOWN(n) (n << 4) | |
| 163 | +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) | |
| 164 | +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) | |
| 165 | + | |
| 166 | +/* Global USB2 PHY Configuration Register */ | |
| 167 | +#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) | |
| 168 | +#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) | |
| 169 | + | |
| 170 | +/* Global USB3 PIPE Control Register */ | |
| 171 | +#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) | |
| 172 | +#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) | |
| 173 | + | |
| 174 | +/* Global HWPARAMS1 Register */ | |
| 175 | +#define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24) | |
| 176 | +#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 | |
| 177 | +#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 | |
| 178 | + | |
| 179 | +/* Device Configuration Register */ | |
| 180 | +#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) | |
| 181 | +#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) | |
| 182 | + | |
| 183 | +#define DWC3_DCFG_SPEED_MASK (7 << 0) | |
| 184 | +#define DWC3_DCFG_SUPERSPEED (4 << 0) | |
| 185 | +#define DWC3_DCFG_HIGHSPEED (0 << 0) | |
| 186 | +#define DWC3_DCFG_FULLSPEED2 (1 << 0) | |
| 187 | +#define DWC3_DCFG_LOWSPEED (2 << 0) | |
| 188 | +#define DWC3_DCFG_FULLSPEED1 (3 << 0) | |
| 189 | + | |
| 190 | +/* Device Control Register */ | |
| 191 | +#define DWC3_DCTL_RUN_STOP (1 << 31) | |
| 192 | +#define DWC3_DCTL_CSFTRST (1 << 30) | |
| 193 | +#define DWC3_DCTL_LSFTRST (1 << 29) | |
| 194 | + | |
| 195 | +#define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) | |
| 196 | +#define DWC3_DCTL_HIRD_THRES(n) (((n) & DWC3_DCTL_HIRD_THRES_MASK) >> 24) | |
| 197 | + | |
| 198 | +#define DWC3_DCTL_APPL1RES (1 << 23) | |
| 199 | + | |
| 200 | +#define DWC3_DCTL_INITU2ENA (1 << 12) | |
| 201 | +#define DWC3_DCTL_ACCEPTU2ENA (1 << 11) | |
| 202 | +#define DWC3_DCTL_INITU1ENA (1 << 10) | |
| 203 | +#define DWC3_DCTL_ACCEPTU1ENA (1 << 9) | |
| 204 | +#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1) | |
| 205 | + | |
| 206 | +#define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5) | |
| 207 | +#define DWC3_DCTL_ULSTCHNGREQ(n) (((n) << 5) & DWC3_DCTL_ULSTCHNGREQ_MASK) | |
| 208 | + | |
| 209 | +#define DWC3_DCTL_ULSTCHNG_NO_ACTION (DWC3_DCTL_ULSTCHNGREQ(0)) | |
| 210 | +#define DWC3_DCTL_ULSTCHNG_SS_DISABLED (DWC3_DCTL_ULSTCHNGREQ(4)) | |
| 211 | +#define DWC3_DCTL_ULSTCHNG_RX_DETECT (DWC3_DCTL_ULSTCHNGREQ(5)) | |
| 212 | +#define DWC3_DCTL_ULSTCHNG_SS_INACTIVE (DWC3_DCTL_ULSTCHNGREQ(6)) | |
| 213 | +#define DWC3_DCTL_ULSTCHNG_RECOVERY (DWC3_DCTL_ULSTCHNGREQ(8)) | |
| 214 | +#define DWC3_DCTL_ULSTCHNG_COMPLIANCE (DWC3_DCTL_ULSTCHNGREQ(10)) | |
| 215 | +#define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11)) | |
| 216 | + | |
| 217 | +/* Device Event Enable Register */ | |
| 218 | +#define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12) | |
| 219 | +#define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11) | |
| 220 | +#define DWC3_DEVTEN_CMDCMPLTEN (1 << 10) | |
| 221 | +#define DWC3_DEVTEN_ERRTICERREN (1 << 9) | |
| 222 | +#define DWC3_DEVTEN_SOFEN (1 << 7) | |
| 223 | +#define DWC3_DEVTEN_EOPFEN (1 << 6) | |
| 224 | +#define DWC3_DEVTEN_WKUPEVTEN (1 << 4) | |
| 225 | +#define DWC3_DEVTEN_ULSTCNGEN (1 << 3) | |
| 226 | +#define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) | |
| 227 | +#define DWC3_DEVTEN_USBRSTEN (1 << 1) | |
| 228 | +#define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) | |
| 229 | + | |
| 230 | +/* Device Status Register */ | |
| 231 | +#define DWC3_DSTS_PWRUPREQ (1 << 24) | |
| 232 | +#define DWC3_DSTS_COREIDLE (1 << 23) | |
| 233 | +#define DWC3_DSTS_DEVCTRLHLT (1 << 22) | |
| 234 | + | |
| 235 | +#define DWC3_DSTS_USBLNKST_MASK (0x0f << 18) | |
| 236 | +#define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18) | |
| 237 | + | |
| 238 | +#define DWC3_DSTS_RXFIFOEMPTY (1 << 17) | |
| 239 | + | |
| 240 | +#define DWC3_DSTS_SOFFN_MASK (0x3ff << 3) | |
| 241 | +#define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) | |
| 242 | + | |
| 243 | +#define DWC3_DSTS_CONNECTSPD (7 << 0) | |
| 244 | + | |
| 245 | +#define DWC3_DSTS_SUPERSPEED (4 << 0) | |
| 246 | +#define DWC3_DSTS_HIGHSPEED (0 << 0) | |
| 247 | +#define DWC3_DSTS_FULLSPEED2 (1 << 0) | |
| 248 | +#define DWC3_DSTS_LOWSPEED (2 << 0) | |
| 249 | +#define DWC3_DSTS_FULLSPEED1 (3 << 0) | |
| 250 | + | |
| 251 | +/* Device Generic Command Register */ | |
| 252 | +#define DWC3_DGCMD_SET_LMP 0x01 | |
| 253 | +#define DWC3_DGCMD_SET_PERIODIC_PAR 0x02 | |
| 254 | +#define DWC3_DGCMD_XMIT_FUNCTION 0x03 | |
| 255 | +#define DWC3_DGCMD_SELECTED_FIFO_FLUSH 0x09 | |
| 256 | +#define DWC3_DGCMD_ALL_FIFO_FLUSH 0x0a | |
| 257 | +#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c | |
| 258 | +#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 | |
| 259 | + | |
| 260 | +/* Device Endpoint Command Register */ | |
| 261 | +#define DWC3_DEPCMD_PARAM_SHIFT 16 | |
| 262 | +#define DWC3_DEPCMD_PARAM(x) (x << DWC3_DEPCMD_PARAM_SHIFT) | |
| 263 | +#define DWC3_DEPCMD_GET_RSC_IDX(x) ((x >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) | |
| 264 | +#define DWC3_DEPCMD_STATUS_MASK (0x0f << 12) | |
| 265 | +#define DWC3_DEPCMD_STATUS(x) ((x & DWC3_DEPCMD_STATUS_MASK) >> 12) | |
| 266 | +#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) | |
| 267 | +#define DWC3_DEPCMD_CMDACT (1 << 10) | |
| 268 | +#define DWC3_DEPCMD_CMDIOC (1 << 8) | |
| 269 | + | |
| 270 | +#define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0) | |
| 271 | +#define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0) | |
| 272 | +#define DWC3_DEPCMD_UPDATETRANSFER (0x07 << 0) | |
| 273 | +#define DWC3_DEPCMD_STARTTRANSFER (0x06 << 0) | |
| 274 | +#define DWC3_DEPCMD_CLEARSTALL (0x05 << 0) | |
| 275 | +#define DWC3_DEPCMD_SETSTALL (0x04 << 0) | |
| 276 | +#define DWC3_DEPCMD_GETSEQNUMBER (0x03 << 0) | |
| 277 | +#define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) | |
| 278 | +#define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) | |
| 279 | + | |
| 280 | +/* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ | |
| 281 | +#define DWC3_DALEPENA_EP(n) (1 << n) | |
| 282 | + | |
| 283 | +#define DWC3_DEPCMD_TYPE_CONTROL 0 | |
| 284 | +#define DWC3_DEPCMD_TYPE_ISOC 1 | |
| 285 | +#define DWC3_DEPCMD_TYPE_BULK 2 | |
| 286 | +#define DWC3_DEPCMD_TYPE_INTR 3 | |
| 287 | + | |
| 288 | +/* Structures */ | |
| 289 | + | |
| 290 | +struct dwc3_trb_hw; | |
| 291 | + | |
| 292 | +/** | |
| 293 | + * struct dwc3_event_buffer - Software event buffer representation | |
| 294 | + * @list: a list of event buffers | |
| 295 | + * @buf: _THE_ buffer | |
| 296 | + * @length: size of this buffer | |
| 297 | + * @dma: dma_addr_t | |
| 298 | + * @dwc: pointer to DWC controller | |
| 299 | + */ | |
| 300 | +struct dwc3_event_buffer { | |
| 301 | + void *buf; | |
| 302 | + unsigned length; | |
| 303 | + unsigned int lpos; | |
| 304 | + | |
| 305 | + dma_addr_t dma; | |
| 306 | + | |
| 307 | + struct dwc3 *dwc; | |
| 308 | +}; | |
| 309 | + | |
| 310 | +#define DWC3_EP_FLAG_STALLED (1 << 0) | |
| 311 | +#define DWC3_EP_FLAG_WEDGED (1 << 1) | |
| 312 | + | |
| 313 | +#define DWC3_EP_DIRECTION_TX true | |
| 314 | +#define DWC3_EP_DIRECTION_RX false | |
| 315 | + | |
| 316 | +#define DWC3_TRB_NUM 32 | |
| 317 | +#define DWC3_TRB_MASK (DWC3_TRB_NUM - 1) | |
| 318 | + | |
| 319 | +/** | |
| 320 | + * struct dwc3_ep - device side endpoint representation | |
| 321 | + * @endpoint: usb endpoint | |
| 322 | + * @request_list: list of requests for this endpoint | |
| 323 | + * @req_queued: list of requests on this ep which have TRBs setup | |
| 324 | + * @trb_pool: array of transaction buffers | |
| 325 | + * @trb_pool_dma: dma address of @trb_pool | |
| 326 | + * @free_slot: next slot which is going to be used | |
| 327 | + * @busy_slot: first slot which is owned by HW | |
| 328 | + * @desc: usb_endpoint_descriptor pointer | |
| 329 | + * @dwc: pointer to DWC controller | |
| 330 | + * @flags: endpoint flags (wedged, stalled, ...) | |
| 331 | + * @current_trb: index of current used trb | |
| 332 | + * @number: endpoint number (1 - 15) | |
| 333 | + * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK | |
| 334 | + * @res_trans_idx: Resource transfer index | |
| 335 | + * @interval: the intervall on which the ISOC transfer is started | |
| 336 | + * @name: a human readable name e.g. ep1out-bulk | |
| 337 | + * @direction: true for TX, false for RX | |
| 338 | + * @stream_capable: true when streams are enabled | |
| 339 | + */ | |
| 340 | +struct dwc3_ep { | |
| 341 | + struct usb_ep endpoint; | |
| 342 | + struct list_head request_list; | |
| 343 | + struct list_head req_queued; | |
| 344 | + | |
| 345 | + struct dwc3_trb_hw *trb_pool; | |
| 346 | + dma_addr_t trb_pool_dma; | |
| 347 | + u32 free_slot; | |
| 348 | + u32 busy_slot; | |
| 349 | + const struct usb_endpoint_descriptor *desc; | |
| 350 | + struct dwc3 *dwc; | |
| 351 | + | |
| 352 | + unsigned flags; | |
| 353 | +#define DWC3_EP_ENABLED (1 << 0) | |
| 354 | +#define DWC3_EP_STALL (1 << 1) | |
| 355 | +#define DWC3_EP_WEDGE (1 << 2) | |
| 356 | +#define DWC3_EP_BUSY (1 << 4) | |
| 357 | +#define DWC3_EP_PENDING_REQUEST (1 << 5) | |
| 358 | + | |
| 359 | + /* This last one is specific to EP0 */ | |
| 360 | +#define DWC3_EP0_DIR_IN (1 << 31) | |
| 361 | + | |
| 362 | + unsigned current_trb; | |
| 363 | + | |
| 364 | + u8 number; | |
| 365 | + u8 type; | |
| 366 | + u8 res_trans_idx; | |
| 367 | + u32 interval; | |
| 368 | + | |
| 369 | + char name[20]; | |
| 370 | + | |
| 371 | + unsigned direction:1; | |
| 372 | + unsigned stream_capable:1; | |
| 373 | +}; | |
| 374 | + | |
| 375 | +enum dwc3_phy { | |
| 376 | + DWC3_PHY_UNKNOWN = 0, | |
| 377 | + DWC3_PHY_USB3, | |
| 378 | + DWC3_PHY_USB2, | |
| 379 | +}; | |
| 380 | + | |
| 381 | +enum dwc3_ep0_next { | |
| 382 | + DWC3_EP0_UNKNOWN = 0, | |
| 383 | + DWC3_EP0_COMPLETE, | |
| 384 | + DWC3_EP0_NRDY_SETUP, | |
| 385 | + DWC3_EP0_NRDY_DATA, | |
| 386 | + DWC3_EP0_NRDY_STATUS, | |
| 387 | +}; | |
| 388 | + | |
| 389 | +enum dwc3_ep0_state { | |
| 390 | + EP0_UNCONNECTED = 0, | |
| 391 | + EP0_SETUP_PHASE, | |
| 392 | + EP0_DATA_PHASE, | |
| 393 | + EP0_STATUS_PHASE, | |
| 394 | +}; | |
| 395 | + | |
| 396 | +enum dwc3_link_state { | |
| 397 | + /* In SuperSpeed */ | |
| 398 | + DWC3_LINK_STATE_U0 = 0x00, /* in HS, means ON */ | |
| 399 | + DWC3_LINK_STATE_U1 = 0x01, | |
| 400 | + DWC3_LINK_STATE_U2 = 0x02, /* in HS, means SLEEP */ | |
| 401 | + DWC3_LINK_STATE_U3 = 0x03, /* in HS, means SUSPEND */ | |
| 402 | + DWC3_LINK_STATE_SS_DIS = 0x04, | |
| 403 | + DWC3_LINK_STATE_RX_DET = 0x05, /* in HS, means Early Suspend */ | |
| 404 | + DWC3_LINK_STATE_SS_INACT = 0x06, | |
| 405 | + DWC3_LINK_STATE_POLL = 0x07, | |
| 406 | + DWC3_LINK_STATE_RECOV = 0x08, | |
| 407 | + DWC3_LINK_STATE_HRESET = 0x09, | |
| 408 | + DWC3_LINK_STATE_CMPLY = 0x0a, | |
| 409 | + DWC3_LINK_STATE_LPBK = 0x0b, | |
| 410 | + DWC3_LINK_STATE_MASK = 0x0f, | |
| 411 | +}; | |
| 412 | + | |
| 413 | +enum dwc3_device_state { | |
| 414 | + DWC3_DEFAULT_STATE, | |
| 415 | + DWC3_ADDRESS_STATE, | |
| 416 | + DWC3_CONFIGURED_STATE, | |
| 417 | +}; | |
| 418 | + | |
| 419 | +/** | |
| 420 | + * struct dwc3_trb - transfer request block | |
| 421 | + * @bpl: lower 32bit of the buffer | |
| 422 | + * @bph: higher 32bit of the buffer | |
| 423 | + * @length: buffer size (up to 16mb - 1) | |
| 424 | + * @pcm1: packet count m1 | |
| 425 | + * @trbsts: trb status | |
| 426 | + * 0 = ok | |
| 427 | + * 1 = missed isoc | |
| 428 | + * 2 = setup pending | |
| 429 | + * @hwo: hardware owner of descriptor | |
| 430 | + * @lst: last trb | |
| 431 | + * @chn: chain buffers | |
| 432 | + * @csp: continue on short packets (only supported on isoc eps) | |
| 433 | + * @trbctl: trb control | |
| 434 | + * 1 = normal | |
| 435 | + * 2 = control-setup | |
| 436 | + * 3 = control-status-2 | |
| 437 | + * 4 = control-status-3 | |
| 438 | + * 5 = control-data (first trb of data stage) | |
| 439 | + * 6 = isochronous-first (first trb of service interval) | |
| 440 | + * 7 = isochronous | |
| 441 | + * 8 = link trb | |
| 442 | + * others = reserved | |
| 443 | + * @isp_imi: interrupt on short packet / interrupt on missed isoc | |
| 444 | + * @ioc: interrupt on complete | |
| 445 | + * @sid_sofn: Stream ID / SOF Number | |
| 446 | + */ | |
| 447 | +struct dwc3_trb { | |
| 448 | + u64 bplh; | |
| 449 | + | |
| 450 | + union { | |
| 451 | + struct { | |
| 452 | + u32 length:24; | |
| 453 | + u32 pcm1:2; | |
| 454 | + u32 reserved27_26:2; | |
| 455 | + u32 trbsts:4; | |
| 456 | +#define DWC3_TRB_STS_OKAY 0 | |
| 457 | +#define DWC3_TRB_STS_MISSED_ISOC 1 | |
| 458 | +#define DWC3_TRB_STS_SETUP_PENDING 2 | |
| 459 | + }; | |
| 460 | + u32 len_pcm; | |
| 461 | + }; | |
| 462 | + | |
| 463 | + union { | |
| 464 | + struct { | |
| 465 | + u32 hwo:1; | |
| 466 | + u32 lst:1; | |
| 467 | + u32 chn:1; | |
| 468 | + u32 csp:1; | |
| 469 | + u32 trbctl:6; | |
| 470 | + u32 isp_imi:1; | |
| 471 | + u32 ioc:1; | |
| 472 | + u32 reserved13_12:2; | |
| 473 | + u32 sid_sofn:16; | |
| 474 | + u32 reserved31_30:2; | |
| 475 | + }; | |
| 476 | + u32 control; | |
| 477 | + }; | |
| 478 | +} __packed; | |
| 479 | + | |
| 480 | +/** | |
| 481 | + * struct dwc3_trb_hw - transfer request block (hw format) | |
| 482 | + * @bpl: DW0-3 | |
| 483 | + * @bph: DW4-7 | |
| 484 | + * @size: DW8-B | |
| 485 | + * @trl: DWC-F | |
| 486 | + */ | |
| 487 | +struct dwc3_trb_hw { | |
| 488 | + __le32 bpl; | |
| 489 | + __le32 bph; | |
| 490 | + __le32 size; | |
| 491 | + __le32 ctrl; | |
| 492 | +} __packed; | |
| 493 | + | |
| 494 | +static inline void dwc3_trb_to_hw(struct dwc3_trb *nat, struct dwc3_trb_hw *hw) | |
| 495 | +{ | |
| 496 | + hw->bpl = cpu_to_le32(lower_32_bits(nat->bplh)); | |
| 497 | + hw->bph = cpu_to_le32(upper_32_bits(nat->bplh)); | |
| 498 | + hw->size = cpu_to_le32p(&nat->len_pcm); | |
| 499 | + /* HWO is written last */ | |
| 500 | + hw->ctrl = cpu_to_le32p(&nat->control); | |
| 501 | +} | |
| 502 | + | |
| 503 | +static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat) | |
| 504 | +{ | |
| 505 | + u64 bplh; | |
| 506 | + | |
| 507 | + bplh = le32_to_cpup(&hw->bpl); | |
| 508 | + bplh |= (u64) le32_to_cpup(&hw->bph) << 32; | |
| 509 | + nat->bplh = bplh; | |
| 510 | + | |
| 511 | + nat->len_pcm = le32_to_cpup(&hw->size); | |
| 512 | + nat->control = le32_to_cpup(&hw->ctrl); | |
| 513 | +} | |
| 514 | + | |
| 515 | +/** | |
| 516 | + * dwc3_hwparams - copy of HWPARAMS registers | |
| 517 | + * @hwparams0 - GHWPARAMS0 | |
| 518 | + * @hwparams1 - GHWPARAMS1 | |
| 519 | + * @hwparams2 - GHWPARAMS2 | |
| 520 | + * @hwparams3 - GHWPARAMS3 | |
| 521 | + * @hwparams4 - GHWPARAMS4 | |
| 522 | + * @hwparams5 - GHWPARAMS5 | |
| 523 | + * @hwparams6 - GHWPARAMS6 | |
| 524 | + * @hwparams7 - GHWPARAMS7 | |
| 525 | + * @hwparams8 - GHWPARAMS8 | |
| 526 | + */ | |
| 527 | +struct dwc3_hwparams { | |
| 528 | + u32 hwparams0; | |
| 529 | + u32 hwparams1; | |
| 530 | + u32 hwparams2; | |
| 531 | + u32 hwparams3; | |
| 532 | + u32 hwparams4; | |
| 533 | + u32 hwparams5; | |
| 534 | + u32 hwparams6; | |
| 535 | + u32 hwparams7; | |
| 536 | + u32 hwparams8; | |
| 537 | +}; | |
| 538 | + | |
| 539 | +/** | |
| 540 | + * struct dwc3 - representation of our controller | |
| 541 | + * @ctrl_req: usb control request which is used for ep0 | |
| 542 | + * @ep0_trb: trb which is used for the ctrl_req | |
| 543 | + * @ep0_bounce: bounce buffer for ep0 | |
| 544 | + * @setup_buf: used while precessing STD USB requests | |
| 545 | + * @ctrl_req_addr: dma address of ctrl_req | |
| 546 | + * @ep0_trb: dma address of ep0_trb | |
| 547 | + * @ep0_usb_req: dummy req used while handling STD USB requests | |
| 548 | + * @setup_buf_addr: dma address of setup_buf | |
| 549 | + * @ep0_bounce_addr: dma address of ep0_bounce | |
| 550 | + * @lock: for synchronizing | |
| 551 | + * @dev: pointer to our struct device | |
| 552 | + * @event_buffer_list: a list of event buffers | |
| 553 | + * @gadget: device side representation of the peripheral controller | |
| 554 | + * @gadget_driver: pointer to the gadget driver | |
| 555 | + * @regs: base address for our registers | |
| 556 | + * @regs_size: address space size | |
| 557 | + * @irq: IRQ number | |
| 558 | + * @revision: revision register contents | |
| 559 | + * @is_selfpowered: true when we are selfpowered | |
| 560 | + * @three_stage_setup: set if we perform a three phase setup | |
| 561 | + * @ep0_status_pending: ep0 status response without a req is pending | |
| 562 | + * @ep0_bounced: true when we used bounce buffer | |
| 563 | + * @ep0_expect_in: true when we expect a DATA IN transfer | |
| 564 | + * @start_config_issued: true when StartConfig command has been issued | |
| 565 | + * @ep0_next_event: hold the next expected event | |
| 566 | + * @ep0state: state of endpoint zero | |
| 567 | + * @link_state: link state | |
| 568 | + * @speed: device speed (super, high, full, low) | |
| 569 | + * @mem: points to start of memory which is used for this struct. | |
| 570 | + * @hwparams: copy of hwparams registers | |
| 571 | + * @root: debugfs root folder pointer | |
| 572 | + */ | |
| 573 | +struct dwc3 { | |
| 574 | + struct usb_ctrlrequest *ctrl_req; | |
| 575 | + struct dwc3_trb_hw *ep0_trb; | |
| 576 | + void *ep0_bounce; | |
| 577 | + u8 *setup_buf; | |
| 578 | + dma_addr_t ctrl_req_addr; | |
| 579 | + dma_addr_t ep0_trb_addr; | |
| 580 | + dma_addr_t setup_buf_addr; | |
| 581 | + dma_addr_t ep0_bounce_addr; | |
| 582 | + struct usb_request ep0_usb_req; | |
| 583 | + /* device lock */ | |
| 584 | + spinlock_t lock; | |
| 585 | + struct device *dev; | |
| 586 | + | |
| 587 | + struct dwc3_event_buffer *ev_buffs[DWC3_EVENT_BUFFERS_NUM]; | |
| 588 | + struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; | |
| 589 | + | |
| 590 | + struct usb_gadget gadget; | |
| 591 | + struct usb_gadget_driver *gadget_driver; | |
| 592 | + | |
| 593 | + void __iomem *regs; | |
| 594 | + size_t regs_size; | |
| 595 | + | |
| 596 | + int irq; | |
| 597 | + | |
| 598 | + u32 revision; | |
| 599 | + | |
| 600 | +#define DWC3_REVISION_173A 0x5533173a | |
| 601 | +#define DWC3_REVISION_175A 0x5533175a | |
| 602 | +#define DWC3_REVISION_180A 0x5533180a | |
| 603 | +#define DWC3_REVISION_183A 0x5533183a | |
| 604 | +#define DWC3_REVISION_185A 0x5533185a | |
| 605 | +#define DWC3_REVISION_188A 0x5533188a | |
| 606 | +#define DWC3_REVISION_190A 0x5533190a | |
| 607 | + | |
| 608 | + unsigned is_selfpowered:1; | |
| 609 | + unsigned three_stage_setup:1; | |
| 610 | + unsigned ep0_status_pending:1; | |
| 611 | + unsigned ep0_bounced:1; | |
| 612 | + unsigned ep0_expect_in:1; | |
| 613 | + unsigned start_config_issued:1; | |
| 614 | + | |
| 615 | + enum dwc3_ep0_next ep0_next_event; | |
| 616 | + enum dwc3_ep0_state ep0state; | |
| 617 | + enum dwc3_link_state link_state; | |
| 618 | + enum dwc3_device_state dev_state; | |
| 619 | + | |
| 620 | + u8 speed; | |
| 621 | + void *mem; | |
| 622 | + | |
| 623 | + struct dwc3_hwparams hwparams; | |
| 624 | + struct dentry *root; | |
| 625 | +}; | |
| 626 | + | |
| 627 | +/* -------------------------------------------------------------------------- */ | |
| 628 | + | |
| 629 | +#define DWC3_TRBSTS_OK 0 | |
| 630 | +#define DWC3_TRBSTS_MISSED_ISOC 1 | |
| 631 | +#define DWC3_TRBSTS_SETUP_PENDING 2 | |
| 632 | + | |
| 633 | +#define DWC3_TRBCTL_NORMAL 1 | |
| 634 | +#define DWC3_TRBCTL_CONTROL_SETUP 2 | |
| 635 | +#define DWC3_TRBCTL_CONTROL_STATUS2 3 | |
| 636 | +#define DWC3_TRBCTL_CONTROL_STATUS3 4 | |
| 637 | +#define DWC3_TRBCTL_CONTROL_DATA 5 | |
| 638 | +#define DWC3_TRBCTL_ISOCHRONOUS_FIRST 6 | |
| 639 | +#define DWC3_TRBCTL_ISOCHRONOUS 7 | |
| 640 | +#define DWC3_TRBCTL_LINK_TRB 8 | |
| 641 | + | |
| 642 | +/* -------------------------------------------------------------------------- */ | |
| 643 | + | |
| 644 | +struct dwc3_event_type { | |
| 645 | + u32 is_devspec:1; | |
| 646 | + u32 type:6; | |
| 647 | + u32 reserved8_31:25; | |
| 648 | +} __packed; | |
| 649 | + | |
| 650 | +#define DWC3_DEPEVT_XFERCOMPLETE 0x01 | |
| 651 | +#define DWC3_DEPEVT_XFERINPROGRESS 0x02 | |
| 652 | +#define DWC3_DEPEVT_XFERNOTREADY 0x03 | |
| 653 | +#define DWC3_DEPEVT_RXTXFIFOEVT 0x04 | |
| 654 | +#define DWC3_DEPEVT_STREAMEVT 0x06 | |
| 655 | +#define DWC3_DEPEVT_EPCMDCMPLT 0x07 | |
| 656 | + | |
| 657 | +/** | |
| 658 | + * struct dwc3_event_depvt - Device Endpoint Events | |
| 659 | + * @one_bit: indicates this is an endpoint event (not used) | |
| 660 | + * @endpoint_number: number of the endpoint | |
| 661 | + * @endpoint_event: The event we have: | |
| 662 | + * 0x00 - Reserved | |
| 663 | + * 0x01 - XferComplete | |
| 664 | + * 0x02 - XferInProgress | |
| 665 | + * 0x03 - XferNotReady | |
| 666 | + * 0x04 - RxTxFifoEvt (IN->Underrun, OUT->Overrun) | |
| 667 | + * 0x05 - Reserved | |
| 668 | + * 0x06 - StreamEvt | |
| 669 | + * 0x07 - EPCmdCmplt | |
| 670 | + * @reserved11_10: Reserved, don't use. | |
| 671 | + * @status: Indicates the status of the event. Refer to databook for | |
| 672 | + * more information. | |
| 673 | + * @parameters: Parameters of the current event. Refer to databook for | |
| 674 | + * more information. | |
| 675 | + */ | |
| 676 | +struct dwc3_event_depevt { | |
| 677 | + u32 one_bit:1; | |
| 678 | + u32 endpoint_number:5; | |
| 679 | + u32 endpoint_event:4; | |
| 680 | + u32 reserved11_10:2; | |
| 681 | + u32 status:4; | |
| 682 | +#define DEPEVT_STATUS_BUSERR (1 << 0) | |
| 683 | +#define DEPEVT_STATUS_SHORT (1 << 1) | |
| 684 | +#define DEPEVT_STATUS_IOC (1 << 2) | |
| 685 | +#define DEPEVT_STATUS_LST (1 << 3) | |
| 686 | + | |
| 687 | +/* Stream event only */ | |
| 688 | +#define DEPEVT_STREAMEVT_FOUND 1 | |
| 689 | +#define DEPEVT_STREAMEVT_NOTFOUND 2 | |
| 690 | + | |
| 691 | +/* Control-only Status */ | |
| 692 | +#define DEPEVT_STATUS_CONTROL_SETUP 0 | |
| 693 | +#define DEPEVT_STATUS_CONTROL_DATA 1 | |
| 694 | +#define DEPEVT_STATUS_CONTROL_STATUS 2 | |
| 695 | + | |
| 696 | + u32 parameters:16; | |
| 697 | +} __packed; | |
| 698 | + | |
| 699 | +/** | |
| 700 | + * struct dwc3_event_devt - Device Events | |
| 701 | + * @one_bit: indicates this is a non-endpoint event (not used) | |
| 702 | + * @device_event: indicates it's a device event. Should read as 0x00 | |
| 703 | + * @type: indicates the type of device event. | |
| 704 | + * 0 - DisconnEvt | |
| 705 | + * 1 - USBRst | |
| 706 | + * 2 - ConnectDone | |
| 707 | + * 3 - ULStChng | |
| 708 | + * 4 - WkUpEvt | |
| 709 | + * 5 - Reserved | |
| 710 | + * 6 - EOPF | |
| 711 | + * 7 - SOF | |
| 712 | + * 8 - Reserved | |
| 713 | + * 9 - ErrticErr | |
| 714 | + * 10 - CmdCmplt | |
| 715 | + * 11 - EvntOverflow | |
| 716 | + * 12 - VndrDevTstRcved | |
| 717 | + * @reserved15_12: Reserved, not used | |
| 718 | + * @event_info: Information about this event | |
| 719 | + * @reserved31_24: Reserved, not used | |
| 720 | + */ | |
| 721 | +struct dwc3_event_devt { | |
| 722 | + u32 one_bit:1; | |
| 723 | + u32 device_event:7; | |
| 724 | + u32 type:4; | |
| 725 | + u32 reserved15_12:4; | |
| 726 | + u32 event_info:8; | |
| 727 | + u32 reserved31_24:8; | |
| 728 | +} __packed; | |
| 729 | + | |
| 730 | +/** | |
| 731 | + * struct dwc3_event_gevt - Other Core Events | |
| 732 | + * @one_bit: indicates this is a non-endpoint event (not used) | |
| 733 | + * @device_event: indicates it's (0x03) Carkit or (0x04) I2C event. | |
| 734 | + * @phy_port_number: self-explanatory | |
| 735 | + * @reserved31_12: Reserved, not used. | |
| 736 | + */ | |
| 737 | +struct dwc3_event_gevt { | |
| 738 | + u32 one_bit:1; | |
| 739 | + u32 device_event:7; | |
| 740 | + u32 phy_port_number:4; | |
| 741 | + u32 reserved31_12:20; | |
| 742 | +} __packed; | |
| 743 | + | |
| 744 | +/** | |
| 745 | + * union dwc3_event - representation of Event Buffer contents | |
| 746 | + * @raw: raw 32-bit event | |
| 747 | + * @type: the type of the event | |
| 748 | + * @depevt: Device Endpoint Event | |
| 749 | + * @devt: Device Event | |
| 750 | + * @gevt: Global Event | |
| 751 | + */ | |
| 752 | +union dwc3_event { | |
| 753 | + u32 raw; | |
| 754 | + struct dwc3_event_type type; | |
| 755 | + struct dwc3_event_depevt depevt; | |
| 756 | + struct dwc3_event_devt devt; | |
| 757 | + struct dwc3_event_gevt gevt; | |
| 758 | +}; | |
| 759 | + | |
| 760 | +/* | |
| 761 | + * DWC3 Features to be used as Driver Data | |
| 762 | + */ | |
| 763 | + | |
| 764 | +#define DWC3_HAS_PERIPHERAL BIT(0) | |
| 765 | +#define DWC3_HAS_XHCI BIT(1) | |
| 766 | +#define DWC3_HAS_OTG BIT(3) | |
| 767 | + | |
| 768 | +#endif /* __DRIVERS_USB_DWC3_CORE_H */ | |
| @@ -0,0 +1,50 @@ | ||
| 1 | +/** | |
| 2 | + * debug.h - DesignWare USB3 DRD Controller Debug Header | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include "core.h" | |
| 40 | + | |
| 41 | +#ifdef CONFIG_DEBUG_FS | |
| 42 | +extern int dwc3_debugfs_init(struct dwc3 *); | |
| 43 | +extern void dwc3_debugfs_exit(struct dwc3 *); | |
| 44 | +#else | |
| 45 | +static inline int dwc3_debugfs_init(struct dwc3 *d) | |
| 46 | +{ return 0; } | |
| 47 | +static inline void dwc3_debugfs_exit(struct dwc3 *d) | |
| 48 | +{ } | |
| 49 | +#endif | |
| 50 | + | |
| @@ -0,0 +1,441 @@ | ||
| 1 | +/** | |
| 2 | + * debugfs.c - DesignWare USB3 DRD Controller DebugFS file | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/kernel.h> | |
| 40 | +#include <linux/slab.h> | |
| 41 | +#include <linux/ptrace.h> | |
| 42 | +#include <linux/types.h> | |
| 43 | +#include <linux/spinlock.h> | |
| 44 | +#include <linux/debugfs.h> | |
| 45 | +#include <linux/seq_file.h> | |
| 46 | +#include <linux/delay.h> | |
| 47 | + | |
| 48 | +#include <asm/uaccess.h> | |
| 49 | + | |
| 50 | +#include "core.h" | |
| 51 | +#include "gadget.h" | |
| 52 | +#include "io.h" | |
| 53 | + | |
| 54 | +struct dwc3_register { | |
| 55 | + const char *name; | |
| 56 | + u32 offset; | |
| 57 | +}; | |
| 58 | + | |
| 59 | +#define dump_register(nm) \ | |
| 60 | +{ \ | |
| 61 | + .name = __stringify(nm), \ | |
| 62 | + .offset = DWC3_ ##nm, \ | |
| 63 | +} | |
| 64 | + | |
| 65 | +static const struct dwc3_register dwc3_regs[] = { | |
| 66 | + dump_register(GSBUSCFG0), | |
| 67 | + dump_register(GSBUSCFG1), | |
| 68 | + dump_register(GTXTHRCFG), | |
| 69 | + dump_register(GRXTHRCFG), | |
| 70 | + dump_register(GCTL), | |
| 71 | + dump_register(GEVTEN), | |
| 72 | + dump_register(GSTS), | |
| 73 | + dump_register(GSNPSID), | |
| 74 | + dump_register(GGPIO), | |
| 75 | + dump_register(GUID), | |
| 76 | + dump_register(GUCTL), | |
| 77 | + dump_register(GBUSERRADDR0), | |
| 78 | + dump_register(GBUSERRADDR1), | |
| 79 | + dump_register(GPRTBIMAP0), | |
| 80 | + dump_register(GPRTBIMAP1), | |
| 81 | + dump_register(GHWPARAMS0), | |
| 82 | + dump_register(GHWPARAMS1), | |
| 83 | + dump_register(GHWPARAMS2), | |
| 84 | + dump_register(GHWPARAMS3), | |
| 85 | + dump_register(GHWPARAMS4), | |
| 86 | + dump_register(GHWPARAMS5), | |
| 87 | + dump_register(GHWPARAMS6), | |
| 88 | + dump_register(GHWPARAMS7), | |
| 89 | + dump_register(GDBGFIFOSPACE), | |
| 90 | + dump_register(GDBGLTSSM), | |
| 91 | + dump_register(GPRTBIMAP_HS0), | |
| 92 | + dump_register(GPRTBIMAP_HS1), | |
| 93 | + dump_register(GPRTBIMAP_FS0), | |
| 94 | + dump_register(GPRTBIMAP_FS1), | |
| 95 | + | |
| 96 | + dump_register(GUSB2PHYCFG(0)), | |
| 97 | + dump_register(GUSB2PHYCFG(1)), | |
| 98 | + dump_register(GUSB2PHYCFG(2)), | |
| 99 | + dump_register(GUSB2PHYCFG(3)), | |
| 100 | + dump_register(GUSB2PHYCFG(4)), | |
| 101 | + dump_register(GUSB2PHYCFG(5)), | |
| 102 | + dump_register(GUSB2PHYCFG(6)), | |
| 103 | + dump_register(GUSB2PHYCFG(7)), | |
| 104 | + dump_register(GUSB2PHYCFG(8)), | |
| 105 | + dump_register(GUSB2PHYCFG(9)), | |
| 106 | + dump_register(GUSB2PHYCFG(10)), | |
| 107 | + dump_register(GUSB2PHYCFG(11)), | |
| 108 | + dump_register(GUSB2PHYCFG(12)), | |
| 109 | + dump_register(GUSB2PHYCFG(13)), | |
| 110 | + dump_register(GUSB2PHYCFG(14)), | |
| 111 | + dump_register(GUSB2PHYCFG(15)), | |
| 112 | + | |
| 113 | + dump_register(GUSB2I2CCTL(0)), | |
| 114 | + dump_register(GUSB2I2CCTL(1)), | |
| 115 | + dump_register(GUSB2I2CCTL(2)), | |
| 116 | + dump_register(GUSB2I2CCTL(3)), | |
| 117 | + dump_register(GUSB2I2CCTL(4)), | |
| 118 | + dump_register(GUSB2I2CCTL(5)), | |
| 119 | + dump_register(GUSB2I2CCTL(6)), | |
| 120 | + dump_register(GUSB2I2CCTL(7)), | |
| 121 | + dump_register(GUSB2I2CCTL(8)), | |
| 122 | + dump_register(GUSB2I2CCTL(9)), | |
| 123 | + dump_register(GUSB2I2CCTL(10)), | |
| 124 | + dump_register(GUSB2I2CCTL(11)), | |
| 125 | + dump_register(GUSB2I2CCTL(12)), | |
| 126 | + dump_register(GUSB2I2CCTL(13)), | |
| 127 | + dump_register(GUSB2I2CCTL(14)), | |
| 128 | + dump_register(GUSB2I2CCTL(15)), | |
| 129 | + | |
| 130 | + dump_register(GUSB2PHYACC(0)), | |
| 131 | + dump_register(GUSB2PHYACC(1)), | |
| 132 | + dump_register(GUSB2PHYACC(2)), | |
| 133 | + dump_register(GUSB2PHYACC(3)), | |
| 134 | + dump_register(GUSB2PHYACC(4)), | |
| 135 | + dump_register(GUSB2PHYACC(5)), | |
| 136 | + dump_register(GUSB2PHYACC(6)), | |
| 137 | + dump_register(GUSB2PHYACC(7)), | |
| 138 | + dump_register(GUSB2PHYACC(8)), | |
| 139 | + dump_register(GUSB2PHYACC(9)), | |
| 140 | + dump_register(GUSB2PHYACC(10)), | |
| 141 | + dump_register(GUSB2PHYACC(11)), | |
| 142 | + dump_register(GUSB2PHYACC(12)), | |
| 143 | + dump_register(GUSB2PHYACC(13)), | |
| 144 | + dump_register(GUSB2PHYACC(14)), | |
| 145 | + dump_register(GUSB2PHYACC(15)), | |
| 146 | + | |
| 147 | + dump_register(GUSB3PIPECTL(0)), | |
| 148 | + dump_register(GUSB3PIPECTL(1)), | |
| 149 | + dump_register(GUSB3PIPECTL(2)), | |
| 150 | + dump_register(GUSB3PIPECTL(3)), | |
| 151 | + dump_register(GUSB3PIPECTL(4)), | |
| 152 | + dump_register(GUSB3PIPECTL(5)), | |
| 153 | + dump_register(GUSB3PIPECTL(6)), | |
| 154 | + dump_register(GUSB3PIPECTL(7)), | |
| 155 | + dump_register(GUSB3PIPECTL(8)), | |
| 156 | + dump_register(GUSB3PIPECTL(9)), | |
| 157 | + dump_register(GUSB3PIPECTL(10)), | |
| 158 | + dump_register(GUSB3PIPECTL(11)), | |
| 159 | + dump_register(GUSB3PIPECTL(12)), | |
| 160 | + dump_register(GUSB3PIPECTL(13)), | |
| 161 | + dump_register(GUSB3PIPECTL(14)), | |
| 162 | + dump_register(GUSB3PIPECTL(15)), | |
| 163 | + | |
| 164 | + dump_register(GTXFIFOSIZ(0)), | |
| 165 | + dump_register(GTXFIFOSIZ(1)), | |
| 166 | + dump_register(GTXFIFOSIZ(2)), | |
| 167 | + dump_register(GTXFIFOSIZ(3)), | |
| 168 | + dump_register(GTXFIFOSIZ(4)), | |
| 169 | + dump_register(GTXFIFOSIZ(5)), | |
| 170 | + dump_register(GTXFIFOSIZ(6)), | |
| 171 | + dump_register(GTXFIFOSIZ(7)), | |
| 172 | + dump_register(GTXFIFOSIZ(8)), | |
| 173 | + dump_register(GTXFIFOSIZ(9)), | |
| 174 | + dump_register(GTXFIFOSIZ(10)), | |
| 175 | + dump_register(GTXFIFOSIZ(11)), | |
| 176 | + dump_register(GTXFIFOSIZ(12)), | |
| 177 | + dump_register(GTXFIFOSIZ(13)), | |
| 178 | + dump_register(GTXFIFOSIZ(14)), | |
| 179 | + dump_register(GTXFIFOSIZ(15)), | |
| 180 | + dump_register(GTXFIFOSIZ(16)), | |
| 181 | + dump_register(GTXFIFOSIZ(17)), | |
| 182 | + dump_register(GTXFIFOSIZ(18)), | |
| 183 | + dump_register(GTXFIFOSIZ(19)), | |
| 184 | + dump_register(GTXFIFOSIZ(20)), | |
| 185 | + dump_register(GTXFIFOSIZ(21)), | |
| 186 | + dump_register(GTXFIFOSIZ(22)), | |
| 187 | + dump_register(GTXFIFOSIZ(23)), | |
| 188 | + dump_register(GTXFIFOSIZ(24)), | |
| 189 | + dump_register(GTXFIFOSIZ(25)), | |
| 190 | + dump_register(GTXFIFOSIZ(26)), | |
| 191 | + dump_register(GTXFIFOSIZ(27)), | |
| 192 | + dump_register(GTXFIFOSIZ(28)), | |
| 193 | + dump_register(GTXFIFOSIZ(29)), | |
| 194 | + dump_register(GTXFIFOSIZ(30)), | |
| 195 | + dump_register(GTXFIFOSIZ(31)), | |
| 196 | + | |
| 197 | + dump_register(GRXFIFOSIZ(0)), | |
| 198 | + dump_register(GRXFIFOSIZ(1)), | |
| 199 | + dump_register(GRXFIFOSIZ(2)), | |
| 200 | + dump_register(GRXFIFOSIZ(3)), | |
| 201 | + dump_register(GRXFIFOSIZ(4)), | |
| 202 | + dump_register(GRXFIFOSIZ(5)), | |
| 203 | + dump_register(GRXFIFOSIZ(6)), | |
| 204 | + dump_register(GRXFIFOSIZ(7)), | |
| 205 | + dump_register(GRXFIFOSIZ(8)), | |
| 206 | + dump_register(GRXFIFOSIZ(9)), | |
| 207 | + dump_register(GRXFIFOSIZ(10)), | |
| 208 | + dump_register(GRXFIFOSIZ(11)), | |
| 209 | + dump_register(GRXFIFOSIZ(12)), | |
| 210 | + dump_register(GRXFIFOSIZ(13)), | |
| 211 | + dump_register(GRXFIFOSIZ(14)), | |
| 212 | + dump_register(GRXFIFOSIZ(15)), | |
| 213 | + dump_register(GRXFIFOSIZ(16)), | |
| 214 | + dump_register(GRXFIFOSIZ(17)), | |
| 215 | + dump_register(GRXFIFOSIZ(18)), | |
| 216 | + dump_register(GRXFIFOSIZ(19)), | |
| 217 | + dump_register(GRXFIFOSIZ(20)), | |
| 218 | + dump_register(GRXFIFOSIZ(21)), | |
| 219 | + dump_register(GRXFIFOSIZ(22)), | |
| 220 | + dump_register(GRXFIFOSIZ(23)), | |
| 221 | + dump_register(GRXFIFOSIZ(24)), | |
| 222 | + dump_register(GRXFIFOSIZ(25)), | |
| 223 | + dump_register(GRXFIFOSIZ(26)), | |
| 224 | + dump_register(GRXFIFOSIZ(27)), | |
| 225 | + dump_register(GRXFIFOSIZ(28)), | |
| 226 | + dump_register(GRXFIFOSIZ(29)), | |
| 227 | + dump_register(GRXFIFOSIZ(30)), | |
| 228 | + dump_register(GRXFIFOSIZ(31)), | |
| 229 | + | |
| 230 | + dump_register(GEVNTADRLO(0)), | |
| 231 | + dump_register(GEVNTADRHI(0)), | |
| 232 | + dump_register(GEVNTSIZ(0)), | |
| 233 | + dump_register(GEVNTCOUNT(0)), | |
| 234 | + | |
| 235 | + dump_register(GHWPARAMS8), | |
| 236 | + dump_register(DCFG), | |
| 237 | + dump_register(DCTL), | |
| 238 | + dump_register(DEVTEN), | |
| 239 | + dump_register(DSTS), | |
| 240 | + dump_register(DGCMDPAR), | |
| 241 | + dump_register(DGCMD), | |
| 242 | + dump_register(DALEPENA), | |
| 243 | + | |
| 244 | + dump_register(DEPCMDPAR2(0)), | |
| 245 | + dump_register(DEPCMDPAR2(1)), | |
| 246 | + dump_register(DEPCMDPAR2(2)), | |
| 247 | + dump_register(DEPCMDPAR2(3)), | |
| 248 | + dump_register(DEPCMDPAR2(4)), | |
| 249 | + dump_register(DEPCMDPAR2(5)), | |
| 250 | + dump_register(DEPCMDPAR2(6)), | |
| 251 | + dump_register(DEPCMDPAR2(7)), | |
| 252 | + dump_register(DEPCMDPAR2(8)), | |
| 253 | + dump_register(DEPCMDPAR2(9)), | |
| 254 | + dump_register(DEPCMDPAR2(10)), | |
| 255 | + dump_register(DEPCMDPAR2(11)), | |
| 256 | + dump_register(DEPCMDPAR2(12)), | |
| 257 | + dump_register(DEPCMDPAR2(13)), | |
| 258 | + dump_register(DEPCMDPAR2(14)), | |
| 259 | + dump_register(DEPCMDPAR2(15)), | |
| 260 | + dump_register(DEPCMDPAR2(16)), | |
| 261 | + dump_register(DEPCMDPAR2(17)), | |
| 262 | + dump_register(DEPCMDPAR2(18)), | |
| 263 | + dump_register(DEPCMDPAR2(19)), | |
| 264 | + dump_register(DEPCMDPAR2(20)), | |
| 265 | + dump_register(DEPCMDPAR2(21)), | |
| 266 | + dump_register(DEPCMDPAR2(22)), | |
| 267 | + dump_register(DEPCMDPAR2(23)), | |
| 268 | + dump_register(DEPCMDPAR2(24)), | |
| 269 | + dump_register(DEPCMDPAR2(25)), | |
| 270 | + dump_register(DEPCMDPAR2(26)), | |
| 271 | + dump_register(DEPCMDPAR2(27)), | |
| 272 | + dump_register(DEPCMDPAR2(28)), | |
| 273 | + dump_register(DEPCMDPAR2(29)), | |
| 274 | + dump_register(DEPCMDPAR2(30)), | |
| 275 | + dump_register(DEPCMDPAR2(31)), | |
| 276 | + | |
| 277 | + dump_register(DEPCMDPAR1(0)), | |
| 278 | + dump_register(DEPCMDPAR1(1)), | |
| 279 | + dump_register(DEPCMDPAR1(2)), | |
| 280 | + dump_register(DEPCMDPAR1(3)), | |
| 281 | + dump_register(DEPCMDPAR1(4)), | |
| 282 | + dump_register(DEPCMDPAR1(5)), | |
| 283 | + dump_register(DEPCMDPAR1(6)), | |
| 284 | + dump_register(DEPCMDPAR1(7)), | |
| 285 | + dump_register(DEPCMDPAR1(8)), | |
| 286 | + dump_register(DEPCMDPAR1(9)), | |
| 287 | + dump_register(DEPCMDPAR1(10)), | |
| 288 | + dump_register(DEPCMDPAR1(11)), | |
| 289 | + dump_register(DEPCMDPAR1(12)), | |
| 290 | + dump_register(DEPCMDPAR1(13)), | |
| 291 | + dump_register(DEPCMDPAR1(14)), | |
| 292 | + dump_register(DEPCMDPAR1(15)), | |
| 293 | + dump_register(DEPCMDPAR1(16)), | |
| 294 | + dump_register(DEPCMDPAR1(17)), | |
| 295 | + dump_register(DEPCMDPAR1(18)), | |
| 296 | + dump_register(DEPCMDPAR1(19)), | |
| 297 | + dump_register(DEPCMDPAR1(20)), | |
| 298 | + dump_register(DEPCMDPAR1(21)), | |
| 299 | + dump_register(DEPCMDPAR1(22)), | |
| 300 | + dump_register(DEPCMDPAR1(23)), | |
| 301 | + dump_register(DEPCMDPAR1(24)), | |
| 302 | + dump_register(DEPCMDPAR1(25)), | |
| 303 | + dump_register(DEPCMDPAR1(26)), | |
| 304 | + dump_register(DEPCMDPAR1(27)), | |
| 305 | + dump_register(DEPCMDPAR1(28)), | |
| 306 | + dump_register(DEPCMDPAR1(29)), | |
| 307 | + dump_register(DEPCMDPAR1(30)), | |
| 308 | + dump_register(DEPCMDPAR1(31)), | |
| 309 | + | |
| 310 | + dump_register(DEPCMDPAR0(0)), | |
| 311 | + dump_register(DEPCMDPAR0(1)), | |
| 312 | + dump_register(DEPCMDPAR0(2)), | |
| 313 | + dump_register(DEPCMDPAR0(3)), | |
| 314 | + dump_register(DEPCMDPAR0(4)), | |
| 315 | + dump_register(DEPCMDPAR0(5)), | |
| 316 | + dump_register(DEPCMDPAR0(6)), | |
| 317 | + dump_register(DEPCMDPAR0(7)), | |
| 318 | + dump_register(DEPCMDPAR0(8)), | |
| 319 | + dump_register(DEPCMDPAR0(9)), | |
| 320 | + dump_register(DEPCMDPAR0(10)), | |
| 321 | + dump_register(DEPCMDPAR0(11)), | |
| 322 | + dump_register(DEPCMDPAR0(12)), | |
| 323 | + dump_register(DEPCMDPAR0(13)), | |
| 324 | + dump_register(DEPCMDPAR0(14)), | |
| 325 | + dump_register(DEPCMDPAR0(15)), | |
| 326 | + dump_register(DEPCMDPAR0(16)), | |
| 327 | + dump_register(DEPCMDPAR0(17)), | |
| 328 | + dump_register(DEPCMDPAR0(18)), | |
| 329 | + dump_register(DEPCMDPAR0(19)), | |
| 330 | + dump_register(DEPCMDPAR0(20)), | |
| 331 | + dump_register(DEPCMDPAR0(21)), | |
| 332 | + dump_register(DEPCMDPAR0(22)), | |
| 333 | + dump_register(DEPCMDPAR0(23)), | |
| 334 | + dump_register(DEPCMDPAR0(24)), | |
| 335 | + dump_register(DEPCMDPAR0(25)), | |
| 336 | + dump_register(DEPCMDPAR0(26)), | |
| 337 | + dump_register(DEPCMDPAR0(27)), | |
| 338 | + dump_register(DEPCMDPAR0(28)), | |
| 339 | + dump_register(DEPCMDPAR0(29)), | |
| 340 | + dump_register(DEPCMDPAR0(30)), | |
| 341 | + dump_register(DEPCMDPAR0(31)), | |
| 342 | + | |
| 343 | + dump_register(DEPCMD(0)), | |
| 344 | + dump_register(DEPCMD(1)), | |
| 345 | + dump_register(DEPCMD(2)), | |
| 346 | + dump_register(DEPCMD(3)), | |
| 347 | + dump_register(DEPCMD(4)), | |
| 348 | + dump_register(DEPCMD(5)), | |
| 349 | + dump_register(DEPCMD(6)), | |
| 350 | + dump_register(DEPCMD(7)), | |
| 351 | + dump_register(DEPCMD(8)), | |
| 352 | + dump_register(DEPCMD(9)), | |
| 353 | + dump_register(DEPCMD(10)), | |
| 354 | + dump_register(DEPCMD(11)), | |
| 355 | + dump_register(DEPCMD(12)), | |
| 356 | + dump_register(DEPCMD(13)), | |
| 357 | + dump_register(DEPCMD(14)), | |
| 358 | + dump_register(DEPCMD(15)), | |
| 359 | + dump_register(DEPCMD(16)), | |
| 360 | + dump_register(DEPCMD(17)), | |
| 361 | + dump_register(DEPCMD(18)), | |
| 362 | + dump_register(DEPCMD(19)), | |
| 363 | + dump_register(DEPCMD(20)), | |
| 364 | + dump_register(DEPCMD(21)), | |
| 365 | + dump_register(DEPCMD(22)), | |
| 366 | + dump_register(DEPCMD(23)), | |
| 367 | + dump_register(DEPCMD(24)), | |
| 368 | + dump_register(DEPCMD(25)), | |
| 369 | + dump_register(DEPCMD(26)), | |
| 370 | + dump_register(DEPCMD(27)), | |
| 371 | + dump_register(DEPCMD(28)), | |
| 372 | + dump_register(DEPCMD(29)), | |
| 373 | + dump_register(DEPCMD(30)), | |
| 374 | + dump_register(DEPCMD(31)), | |
| 375 | + | |
| 376 | + dump_register(OCFG), | |
| 377 | + dump_register(OCTL), | |
| 378 | + dump_register(OEVTEN), | |
| 379 | + dump_register(OSTS), | |
| 380 | +}; | |
| 381 | + | |
| 382 | +static int dwc3_regdump_show(struct seq_file *s, void *unused) | |
| 383 | +{ | |
| 384 | + struct dwc3 *dwc = s->private; | |
| 385 | + int i; | |
| 386 | + | |
| 387 | + seq_printf(s, "DesignWare USB3 Core Register Dump\n"); | |
| 388 | + | |
| 389 | + for (i = 0; i < ARRAY_SIZE(dwc3_regs); i++) { | |
| 390 | + seq_printf(s, "%-20s : %08x\n", dwc3_regs[i].name, | |
| 391 | + dwc3_readl(dwc->regs, dwc3_regs[i].offset)); | |
| 392 | + } | |
| 393 | + | |
| 394 | + return 0; | |
| 395 | +} | |
| 396 | + | |
| 397 | +static int dwc3_regdump_open(struct inode *inode, struct file *file) | |
| 398 | +{ | |
| 399 | + return single_open(file, dwc3_regdump_show, inode->i_private); | |
| 400 | +} | |
| 401 | + | |
| 402 | +static const struct file_operations dwc3_regdump_fops = { | |
| 403 | + .open = dwc3_regdump_open, | |
| 404 | + .read = seq_read, | |
| 405 | + .release = single_release, | |
| 406 | +}; | |
| 407 | + | |
| 408 | +int __devinit dwc3_debugfs_init(struct dwc3 *dwc) | |
| 409 | +{ | |
| 410 | + struct dentry *root; | |
| 411 | + struct dentry *file; | |
| 412 | + int ret; | |
| 413 | + | |
| 414 | + root = debugfs_create_dir(dev_name(dwc->dev), NULL); | |
| 415 | + if (IS_ERR(root)){ | |
| 416 | + ret = PTR_ERR(root); | |
| 417 | + goto err0; | |
| 418 | + } | |
| 419 | + | |
| 420 | + dwc->root = root; | |
| 421 | + | |
| 422 | + file = debugfs_create_file("regdump", S_IRUGO, root, dwc, | |
| 423 | + &dwc3_regdump_fops); | |
| 424 | + if (IS_ERR(file)) { | |
| 425 | + ret = PTR_ERR(file); | |
| 426 | + goto err1; | |
| 427 | + } | |
| 428 | + return 0; | |
| 429 | + | |
| 430 | +err1: | |
| 431 | + debugfs_remove_recursive(root); | |
| 432 | + | |
| 433 | +err0: | |
| 434 | + return ret; | |
| 435 | +} | |
| 436 | + | |
| 437 | +void __devexit dwc3_debugfs_exit(struct dwc3 *dwc) | |
| 438 | +{ | |
| 439 | + debugfs_remove_recursive(dwc->root); | |
| 440 | + dwc->root = NULL; | |
| 441 | +} | |
| @@ -0,0 +1,401 @@ | ||
| 1 | +/** | |
| 2 | + * dwc3-omap.c - OMAP Specific Glue layer | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/module.h> | |
| 40 | +#include <linux/kernel.h> | |
| 41 | +#include <linux/slab.h> | |
| 42 | +#include <linux/interrupt.h> | |
| 43 | +#include <linux/spinlock.h> | |
| 44 | +#include <linux/platform_device.h> | |
| 45 | +#include <linux/platform_data/dwc3-omap.h> | |
| 46 | +#include <linux/dma-mapping.h> | |
| 47 | +#include <linux/ioport.h> | |
| 48 | +#include <linux/io.h> | |
| 49 | +#include <linux/module.h> | |
| 50 | + | |
| 51 | +#include "io.h" | |
| 52 | + | |
| 53 | +/* | |
| 54 | + * All these registers belong to OMAP's Wrapper around the | |
| 55 | + * DesignWare USB3 Core. | |
| 56 | + */ | |
| 57 | + | |
| 58 | +#define USBOTGSS_REVISION 0x0000 | |
| 59 | +#define USBOTGSS_SYSCONFIG 0x0010 | |
| 60 | +#define USBOTGSS_IRQ_EOI 0x0020 | |
| 61 | +#define USBOTGSS_IRQSTATUS_RAW_0 0x0024 | |
| 62 | +#define USBOTGSS_IRQSTATUS_0 0x0028 | |
| 63 | +#define USBOTGSS_IRQENABLE_SET_0 0x002c | |
| 64 | +#define USBOTGSS_IRQENABLE_CLR_0 0x0030 | |
| 65 | +#define USBOTGSS_IRQSTATUS_RAW_1 0x0034 | |
| 66 | +#define USBOTGSS_IRQSTATUS_1 0x0038 | |
| 67 | +#define USBOTGSS_IRQENABLE_SET_1 0x003c | |
| 68 | +#define USBOTGSS_IRQENABLE_CLR_1 0x0040 | |
| 69 | +#define USBOTGSS_UTMI_OTG_CTRL 0x0080 | |
| 70 | +#define USBOTGSS_UTMI_OTG_STATUS 0x0084 | |
| 71 | +#define USBOTGSS_MMRAM_OFFSET 0x0100 | |
| 72 | +#define USBOTGSS_FLADJ 0x0104 | |
| 73 | +#define USBOTGSS_DEBUG_CFG 0x0108 | |
| 74 | +#define USBOTGSS_DEBUG_DATA 0x010c | |
| 75 | + | |
| 76 | +/* SYSCONFIG REGISTER */ | |
| 77 | +#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) | |
| 78 | +#define USBOTGSS_SYSCONFIG_STANDBYMODE(x) ((x) << 4) | |
| 79 | + | |
| 80 | +#define USBOTGSS_STANDBYMODE_FORCE_STANDBY 0 | |
| 81 | +#define USBOTGSS_STANDBYMODE_NO_STANDBY 1 | |
| 82 | +#define USBOTGSS_STANDBYMODE_SMART_STANDBY 2 | |
| 83 | +#define USBOTGSS_STANDBYMODE_SMART_WAKEUP 3 | |
| 84 | + | |
| 85 | +#define USBOTGSS_STANDBYMODE_MASK (0x03 << 4) | |
| 86 | + | |
| 87 | +#define USBOTGSS_SYSCONFIG_IDLEMODE(x) ((x) << 2) | |
| 88 | + | |
| 89 | +#define USBOTGSS_IDLEMODE_FORCE_IDLE 0 | |
| 90 | +#define USBOTGSS_IDLEMODE_NO_IDLE 1 | |
| 91 | +#define USBOTGSS_IDLEMODE_SMART_IDLE 2 | |
| 92 | +#define USBOTGSS_IDLEMODE_SMART_WAKEUP 3 | |
| 93 | + | |
| 94 | +#define USBOTGSS_IDLEMODE_MASK (0x03 << 2) | |
| 95 | + | |
| 96 | +/* IRQ_EOI REGISTER */ | |
| 97 | +#define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0) | |
| 98 | + | |
| 99 | +/* IRQS0 BITS */ | |
| 100 | +#define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) | |
| 101 | + | |
| 102 | +/* IRQ1 BITS */ | |
| 103 | +#define USBOTGSS_IRQ1_DMADISABLECLR (1 << 17) | |
| 104 | +#define USBOTGSS_IRQ1_OEVT (1 << 16) | |
| 105 | +#define USBOTGSS_IRQ1_DRVVBUS_RISE (1 << 13) | |
| 106 | +#define USBOTGSS_IRQ1_CHRGVBUS_RISE (1 << 12) | |
| 107 | +#define USBOTGSS_IRQ1_DISCHRGVBUS_RISE (1 << 11) | |
| 108 | +#define USBOTGSS_IRQ1_IDPULLUP_RISE (1 << 8) | |
| 109 | +#define USBOTGSS_IRQ1_DRVVBUS_FALL (1 << 5) | |
| 110 | +#define USBOTGSS_IRQ1_CHRGVBUS_FALL (1 << 4) | |
| 111 | +#define USBOTGSS_IRQ1_DISCHRGVBUS_FALL (1 << 3) | |
| 112 | +#define USBOTGSS_IRQ1_IDPULLUP_FALL (1 << 0) | |
| 113 | + | |
| 114 | +/* UTMI_OTG_CTRL REGISTER */ | |
| 115 | +#define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS (1 << 5) | |
| 116 | +#define USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS (1 << 4) | |
| 117 | +#define USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS (1 << 3) | |
| 118 | +#define USBOTGSS_UTMI_OTG_CTRL_IDPULLUP (1 << 0) | |
| 119 | + | |
| 120 | +/* UTMI_OTG_STATUS REGISTER */ | |
| 121 | +#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE (1 << 31) | |
| 122 | +#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT (1 << 9) | |
| 123 | +#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE (1 << 8) | |
| 124 | +#define USBOTGSS_UTMI_OTG_STATUS_IDDIG (1 << 4) | |
| 125 | +#define USBOTGSS_UTMI_OTG_STATUS_SESSEND (1 << 3) | |
| 126 | +#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID (1 << 2) | |
| 127 | +#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1) | |
| 128 | + | |
| 129 | +struct dwc3_omap { | |
| 130 | + /* device lock */ | |
| 131 | + spinlock_t lock; | |
| 132 | + | |
| 133 | + struct platform_device *dwc3; | |
| 134 | + struct device *dev; | |
| 135 | + | |
| 136 | + int irq; | |
| 137 | + void __iomem *base; | |
| 138 | + | |
| 139 | + void *context; | |
| 140 | + u32 resource_size; | |
| 141 | + | |
| 142 | + u32 dma_status:1; | |
| 143 | +}; | |
| 144 | + | |
| 145 | +static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) | |
| 146 | +{ | |
| 147 | + struct dwc3_omap *omap = _omap; | |
| 148 | + u32 reg; | |
| 149 | + | |
| 150 | + spin_lock(&omap->lock); | |
| 151 | + | |
| 152 | + reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_1); | |
| 153 | + | |
| 154 | + if (reg & USBOTGSS_IRQ1_DMADISABLECLR) { | |
| 155 | + dev_dbg(omap->dev, "DMA Disable was Cleared\n"); | |
| 156 | + omap->dma_status = false; | |
| 157 | + } | |
| 158 | + | |
| 159 | + if (reg & USBOTGSS_IRQ1_OEVT) | |
| 160 | + dev_dbg(omap->dev, "OTG Event\n"); | |
| 161 | + | |
| 162 | + if (reg & USBOTGSS_IRQ1_DRVVBUS_RISE) | |
| 163 | + dev_dbg(omap->dev, "DRVVBUS Rise\n"); | |
| 164 | + | |
| 165 | + if (reg & USBOTGSS_IRQ1_CHRGVBUS_RISE) | |
| 166 | + dev_dbg(omap->dev, "CHRGVBUS Rise\n"); | |
| 167 | + | |
| 168 | + if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_RISE) | |
| 169 | + dev_dbg(omap->dev, "DISCHRGVBUS Rise\n"); | |
| 170 | + | |
| 171 | + if (reg & USBOTGSS_IRQ1_IDPULLUP_RISE) | |
| 172 | + dev_dbg(omap->dev, "IDPULLUP Rise\n"); | |
| 173 | + | |
| 174 | + if (reg & USBOTGSS_IRQ1_DRVVBUS_FALL) | |
| 175 | + dev_dbg(omap->dev, "DRVVBUS Fall\n"); | |
| 176 | + | |
| 177 | + if (reg & USBOTGSS_IRQ1_CHRGVBUS_FALL) | |
| 178 | + dev_dbg(omap->dev, "CHRGVBUS Fall\n"); | |
| 179 | + | |
| 180 | + if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_FALL) | |
| 181 | + dev_dbg(omap->dev, "DISCHRGVBUS Fall\n"); | |
| 182 | + | |
| 183 | + if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL) | |
| 184 | + dev_dbg(omap->dev, "IDPULLUP Fall\n"); | |
| 185 | + | |
| 186 | + dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg); | |
| 187 | + | |
| 188 | + reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_0); | |
| 189 | + dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg); | |
| 190 | + | |
| 191 | + spin_unlock(&omap->lock); | |
| 192 | + | |
| 193 | + return IRQ_HANDLED; | |
| 194 | +} | |
| 195 | + | |
| 196 | +static int __devinit dwc3_omap_probe(struct platform_device *pdev) | |
| 197 | +{ | |
| 198 | + struct dwc3_omap_data *pdata = pdev->dev.platform_data; | |
| 199 | + struct platform_device *dwc3; | |
| 200 | + struct dwc3_omap *omap; | |
| 201 | + struct resource *res; | |
| 202 | + | |
| 203 | + int ret = -ENOMEM; | |
| 204 | + int irq; | |
| 205 | + | |
| 206 | + u32 reg; | |
| 207 | + | |
| 208 | + void __iomem *base; | |
| 209 | + void *context; | |
| 210 | + | |
| 211 | + omap = kzalloc(sizeof(*omap), GFP_KERNEL); | |
| 212 | + if (!omap) { | |
| 213 | + dev_err(&pdev->dev, "not enough memory\n"); | |
| 214 | + goto err0; | |
| 215 | + } | |
| 216 | + | |
| 217 | + platform_set_drvdata(pdev, omap); | |
| 218 | + | |
| 219 | + irq = platform_get_irq(pdev, 1); | |
| 220 | + if (irq < 0) { | |
| 221 | + dev_err(&pdev->dev, "missing IRQ resource\n"); | |
| 222 | + ret = -EINVAL; | |
| 223 | + goto err1; | |
| 224 | + } | |
| 225 | + | |
| 226 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
| 227 | + if (!res) { | |
| 228 | + dev_err(&pdev->dev, "missing memory base resource\n"); | |
| 229 | + ret = -EINVAL; | |
| 230 | + goto err1; | |
| 231 | + } | |
| 232 | + | |
| 233 | + base = ioremap_nocache(res->start, resource_size(res)); | |
| 234 | + if (!base) { | |
| 235 | + dev_err(&pdev->dev, "ioremap failed\n"); | |
| 236 | + goto err1; | |
| 237 | + } | |
| 238 | + | |
| 239 | + dwc3 = platform_device_alloc("dwc3-omap", -1); | |
| 240 | + if (!dwc3) { | |
| 241 | + dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); | |
| 242 | + goto err2; | |
| 243 | + } | |
| 244 | + | |
| 245 | + context = kzalloc(resource_size(res), GFP_KERNEL); | |
| 246 | + if (!context) { | |
| 247 | + dev_err(&pdev->dev, "couldn't allocate dwc3 context memory\n"); | |
| 248 | + goto err3; | |
| 249 | + } | |
| 250 | + | |
| 251 | + spin_lock_init(&omap->lock); | |
| 252 | + dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask); | |
| 253 | + | |
| 254 | + dwc3->dev.parent = &pdev->dev; | |
| 255 | + dwc3->dev.dma_mask = pdev->dev.dma_mask; | |
| 256 | + dwc3->dev.dma_parms = pdev->dev.dma_parms; | |
| 257 | + omap->resource_size = resource_size(res); | |
| 258 | + omap->context = context; | |
| 259 | + omap->dev = &pdev->dev; | |
| 260 | + omap->irq = irq; | |
| 261 | + omap->base = base; | |
| 262 | + omap->dwc3 = dwc3; | |
| 263 | + | |
| 264 | + reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); | |
| 265 | + | |
| 266 | + if (!pdata) { | |
| 267 | + dev_dbg(&pdev->dev, "missing platform data\n"); | |
| 268 | + } else { | |
| 269 | + switch (pdata->utmi_mode) { | |
| 270 | + case DWC3_OMAP_UTMI_MODE_SW: | |
| 271 | + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; | |
| 272 | + break; | |
| 273 | + case DWC3_OMAP_UTMI_MODE_HW: | |
| 274 | + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; | |
| 275 | + break; | |
| 276 | + default: | |
| 277 | + dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n", | |
| 278 | + pdata->utmi_mode); | |
| 279 | + } | |
| 280 | + } | |
| 281 | + | |
| 282 | + dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); | |
| 283 | + | |
| 284 | + /* check the DMA Status */ | |
| 285 | + reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG); | |
| 286 | + omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); | |
| 287 | + | |
| 288 | + /* Set No-Idle and No-Standby */ | |
| 289 | + reg &= ~(USBOTGSS_STANDBYMODE_MASK | |
| 290 | + | USBOTGSS_IDLEMODE_MASK); | |
| 291 | + | |
| 292 | + reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY) | |
| 293 | + | USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE)); | |
| 294 | + | |
| 295 | + dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg); | |
| 296 | + | |
| 297 | + ret = request_irq(omap->irq, dwc3_omap_interrupt, 0, | |
| 298 | + "dwc3-omap", omap); | |
| 299 | + if (ret) { | |
| 300 | + dev_err(&pdev->dev, "failed to request IRQ #%d --> %d\n", | |
| 301 | + omap->irq, ret); | |
| 302 | + goto err4; | |
| 303 | + } | |
| 304 | + | |
| 305 | + /* enable all IRQs */ | |
| 306 | + reg = USBOTGSS_IRQO_COREIRQ_ST; | |
| 307 | + dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg); | |
| 308 | + | |
| 309 | + reg = (USBOTGSS_IRQ1_OEVT | | |
| 310 | + USBOTGSS_IRQ1_DRVVBUS_RISE | | |
| 311 | + USBOTGSS_IRQ1_CHRGVBUS_RISE | | |
| 312 | + USBOTGSS_IRQ1_DISCHRGVBUS_RISE | | |
| 313 | + USBOTGSS_IRQ1_IDPULLUP_RISE | | |
| 314 | + USBOTGSS_IRQ1_DRVVBUS_FALL | | |
| 315 | + USBOTGSS_IRQ1_CHRGVBUS_FALL | | |
| 316 | + USBOTGSS_IRQ1_DISCHRGVBUS_FALL | | |
| 317 | + USBOTGSS_IRQ1_IDPULLUP_FALL); | |
| 318 | + | |
| 319 | + dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); | |
| 320 | + | |
| 321 | + ret = platform_device_add_resources(dwc3, pdev->resource, | |
| 322 | + pdev->num_resources); | |
| 323 | + if (ret) { | |
| 324 | + dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n"); | |
| 325 | + goto err5; | |
| 326 | + } | |
| 327 | + | |
| 328 | + ret = platform_device_add(dwc3); | |
| 329 | + if (ret) { | |
| 330 | + dev_err(&pdev->dev, "failed to register dwc3 device\n"); | |
| 331 | + goto err5; | |
| 332 | + } | |
| 333 | + | |
| 334 | + return 0; | |
| 335 | + | |
| 336 | +err5: | |
| 337 | + free_irq(omap->irq, omap); | |
| 338 | + | |
| 339 | +err4: | |
| 340 | + kfree(omap->context); | |
| 341 | + | |
| 342 | +err3: | |
| 343 | + platform_device_put(dwc3); | |
| 344 | + | |
| 345 | +err2: | |
| 346 | + iounmap(base); | |
| 347 | + | |
| 348 | +err1: | |
| 349 | + kfree(omap); | |
| 350 | + | |
| 351 | +err0: | |
| 352 | + return ret; | |
| 353 | +} | |
| 354 | + | |
| 355 | +static int __devexit dwc3_omap_remove(struct platform_device *pdev) | |
| 356 | +{ | |
| 357 | + struct dwc3_omap *omap = platform_get_drvdata(pdev); | |
| 358 | + | |
| 359 | + platform_device_unregister(omap->dwc3); | |
| 360 | + | |
| 361 | + free_irq(omap->irq, omap); | |
| 362 | + iounmap(omap->base); | |
| 363 | + | |
| 364 | + kfree(omap->context); | |
| 365 | + kfree(omap); | |
| 366 | + | |
| 367 | + return 0; | |
| 368 | +} | |
| 369 | + | |
| 370 | +static const struct of_device_id of_dwc3_matach[] = { | |
| 371 | + { | |
| 372 | + "ti,dwc3", | |
| 373 | + }, | |
| 374 | + { }, | |
| 375 | +}; | |
| 376 | +MODULE_DEVICE_TABLE(of, of_dwc3_matach); | |
| 377 | + | |
| 378 | +static struct platform_driver dwc3_omap_driver = { | |
| 379 | + .probe = dwc3_omap_probe, | |
| 380 | + .remove = __devexit_p(dwc3_omap_remove), | |
| 381 | + .driver = { | |
| 382 | + .name = "omap-dwc3", | |
| 383 | + .of_match_table = of_dwc3_matach, | |
| 384 | + }, | |
| 385 | +}; | |
| 386 | + | |
| 387 | +MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |
| 388 | +MODULE_LICENSE("Dual BSD/GPL"); | |
| 389 | +MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer"); | |
| 390 | + | |
| 391 | +static int __devinit dwc3_omap_init(void) | |
| 392 | +{ | |
| 393 | + return platform_driver_register(&dwc3_omap_driver); | |
| 394 | +} | |
| 395 | +module_init(dwc3_omap_init); | |
| 396 | + | |
| 397 | +static void __exit dwc3_omap_exit(void) | |
| 398 | +{ | |
| 399 | + platform_driver_unregister(&dwc3_omap_driver); | |
| 400 | +} | |
| 401 | +module_exit(dwc3_omap_exit); | |
| @@ -0,0 +1,219 @@ | ||
| 1 | +/** | |
| 2 | + * dwc3-pci.c - PCI Specific glue layer | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/kernel.h> | |
| 40 | +#include <linux/module.h> | |
| 41 | +#include <linux/slab.h> | |
| 42 | +#include <linux/pci.h> | |
| 43 | +#include <linux/platform_device.h> | |
| 44 | + | |
| 45 | +/* FIXME define these in <linux/pci_ids.h> */ | |
| 46 | +#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 | |
| 47 | +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd | |
| 48 | + | |
| 49 | +#define DWC3_PCI_DEVS_POSSIBLE 32 | |
| 50 | + | |
| 51 | +struct dwc3_pci { | |
| 52 | + struct device *dev; | |
| 53 | + struct platform_device *dwc3; | |
| 54 | +}; | |
| 55 | + | |
| 56 | +static DECLARE_BITMAP(dwc3_pci_devs, DWC3_PCI_DEVS_POSSIBLE); | |
| 57 | + | |
| 58 | +static int dwc3_pci_get_device_id(struct dwc3_pci *glue) | |
| 59 | +{ | |
| 60 | + int id; | |
| 61 | + | |
| 62 | +again: | |
| 63 | + id = find_first_zero_bit(dwc3_pci_devs, DWC3_PCI_DEVS_POSSIBLE); | |
| 64 | + if (id < DWC3_PCI_DEVS_POSSIBLE) { | |
| 65 | + int old; | |
| 66 | + | |
| 67 | + old = test_and_set_bit(id, dwc3_pci_devs); | |
| 68 | + if (old) | |
| 69 | + goto again; | |
| 70 | + } else { | |
| 71 | + dev_err(glue->dev, "no space for new device\n"); | |
| 72 | + id = -ENOMEM; | |
| 73 | + } | |
| 74 | + | |
| 75 | + return 0; | |
| 76 | +} | |
| 77 | + | |
| 78 | +static void dwc3_pci_put_device_id(struct dwc3_pci *glue, int id) | |
| 79 | +{ | |
| 80 | + int ret; | |
| 81 | + | |
| 82 | + if (id < 0) | |
| 83 | + return; | |
| 84 | + | |
| 85 | + ret = test_bit(id, dwc3_pci_devs); | |
| 86 | + WARN(!ret, "Device: %s\nID %d not in use\n", | |
| 87 | + dev_driver_string(glue->dev), id); | |
| 88 | + clear_bit(id, dwc3_pci_devs); | |
| 89 | +} | |
| 90 | + | |
| 91 | +static int __devinit dwc3_pci_probe(struct pci_dev *pci, | |
| 92 | + const struct pci_device_id *id) | |
| 93 | +{ | |
| 94 | + struct resource res[2]; | |
| 95 | + struct platform_device *dwc3; | |
| 96 | + struct dwc3_pci *glue; | |
| 97 | + int ret = -ENOMEM; | |
| 98 | + int devid; | |
| 99 | + | |
| 100 | + glue = kzalloc(sizeof(*glue), GFP_KERNEL); | |
| 101 | + if (!glue) { | |
| 102 | + dev_err(&pci->dev, "not enough memory\n"); | |
| 103 | + goto err0; | |
| 104 | + } | |
| 105 | + | |
| 106 | + glue->dev = &pci->dev; | |
| 107 | + | |
| 108 | + ret = pci_enable_device(pci); | |
| 109 | + if (ret) { | |
| 110 | + dev_err(&pci->dev, "failed to enable pci device\n"); | |
| 111 | + goto err1; | |
| 112 | + } | |
| 113 | + | |
| 114 | + pci_set_power_state(pci, PCI_D0); | |
| 115 | + pci_set_master(pci); | |
| 116 | + | |
| 117 | + devid = dwc3_pci_get_device_id(glue); | |
| 118 | + if (devid < 0) | |
| 119 | + goto err2; | |
| 120 | + | |
| 121 | + dwc3 = platform_device_alloc("dwc3-pci", devid); | |
| 122 | + if (!dwc3) { | |
| 123 | + dev_err(&pci->dev, "couldn't allocate dwc3 device\n"); | |
| 124 | + goto err3; | |
| 125 | + } | |
| 126 | + | |
| 127 | + memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); | |
| 128 | + | |
| 129 | + res[0].start = pci_resource_start(pci, 0); | |
| 130 | + res[0].end = pci_resource_end(pci, 0); | |
| 131 | + res[0].name = "dwc_usb3"; | |
| 132 | + res[0].flags = IORESOURCE_MEM; | |
| 133 | + | |
| 134 | + res[1].start = pci->irq; | |
| 135 | + res[1].name = "dwc_usb3"; | |
| 136 | + res[1].flags = IORESOURCE_IRQ; | |
| 137 | + | |
| 138 | + ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); | |
| 139 | + if (ret) { | |
| 140 | + dev_err(&pci->dev, "couldn't add resources to dwc3 device\n"); | |
| 141 | + goto err4; | |
| 142 | + } | |
| 143 | + | |
| 144 | + pci_set_drvdata(pci, glue); | |
| 145 | + | |
| 146 | + dma_set_coherent_mask(&dwc3->dev, pci->dev.coherent_dma_mask); | |
| 147 | + | |
| 148 | + dwc3->dev.dma_mask = pci->dev.dma_mask; | |
| 149 | + dwc3->dev.dma_parms = pci->dev.dma_parms; | |
| 150 | + dwc3->dev.parent = &pci->dev; | |
| 151 | + glue->dwc3 = dwc3; | |
| 152 | + | |
| 153 | + ret = platform_device_add(dwc3); | |
| 154 | + if (ret) { | |
| 155 | + dev_err(&pci->dev, "failed to register dwc3 device\n"); | |
| 156 | + goto err4; | |
| 157 | + } | |
| 158 | + | |
| 159 | + return 0; | |
| 160 | + | |
| 161 | +err4: | |
| 162 | + pci_set_drvdata(pci, NULL); | |
| 163 | + platform_device_put(dwc3); | |
| 164 | + | |
| 165 | +err3: | |
| 166 | + dwc3_pci_put_device_id(glue, devid); | |
| 167 | + | |
| 168 | +err2: | |
| 169 | + pci_disable_device(pci); | |
| 170 | + | |
| 171 | +err1: | |
| 172 | + kfree(pci); | |
| 173 | + | |
| 174 | +err0: | |
| 175 | + return ret; | |
| 176 | +} | |
| 177 | + | |
| 178 | +static void __devexit dwc3_pci_remove(struct pci_dev *pci) | |
| 179 | +{ | |
| 180 | + struct dwc3_pci *glue = pci_get_drvdata(pci); | |
| 181 | + | |
| 182 | + dwc3_pci_put_device_id(glue, glue->dwc3->id); | |
| 183 | + platform_device_unregister(glue->dwc3); | |
| 184 | + pci_set_drvdata(pci, NULL); | |
| 185 | + pci_disable_device(pci); | |
| 186 | + kfree(glue); | |
| 187 | +} | |
| 188 | + | |
| 189 | +static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { | |
| 190 | + { | |
| 191 | + PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, | |
| 192 | + PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), | |
| 193 | + }, | |
| 194 | + { } /* Terminating Entry */ | |
| 195 | +}; | |
| 196 | +MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); | |
| 197 | + | |
| 198 | +static struct pci_driver dwc3_pci_driver = { | |
| 199 | + .name = "pci-dwc3", | |
| 200 | + .id_table = dwc3_pci_id_table, | |
| 201 | + .probe = dwc3_pci_probe, | |
| 202 | + .remove = __devexit_p(dwc3_pci_remove), | |
| 203 | +}; | |
| 204 | + | |
| 205 | +MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |
| 206 | +MODULE_LICENSE("Dual BSD/GPL"); | |
| 207 | +MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); | |
| 208 | + | |
| 209 | +static int __devinit dwc3_pci_init(void) | |
| 210 | +{ | |
| 211 | + return pci_register_driver(&dwc3_pci_driver); | |
| 212 | +} | |
| 213 | +module_init(dwc3_pci_init); | |
| 214 | + | |
| 215 | +static void __exit dwc3_pci_exit(void) | |
| 216 | +{ | |
| 217 | + pci_unregister_driver(&dwc3_pci_driver); | |
| 218 | +} | |
| 219 | +module_exit(dwc3_pci_exit); | |
| @@ -0,0 +1,804 @@ | ||
| 1 | +/** | |
| 2 | + * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/kernel.h> | |
| 40 | +#include <linux/slab.h> | |
| 41 | +#include <linux/spinlock.h> | |
| 42 | +#include <linux/platform_device.h> | |
| 43 | +#include <linux/pm_runtime.h> | |
| 44 | +#include <linux/interrupt.h> | |
| 45 | +#include <linux/io.h> | |
| 46 | +#include <linux/list.h> | |
| 47 | +#include <linux/dma-mapping.h> | |
| 48 | + | |
| 49 | +#include <linux/usb/ch9.h> | |
| 50 | +#include <linux/usb/gadget.h> | |
| 51 | + | |
| 52 | +#include "core.h" | |
| 53 | +#include "gadget.h" | |
| 54 | +#include "io.h" | |
| 55 | + | |
| 56 | +static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | |
| 57 | + const struct dwc3_event_depevt *event); | |
| 58 | + | |
| 59 | +static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) | |
| 60 | +{ | |
| 61 | + switch (state) { | |
| 62 | + case EP0_UNCONNECTED: | |
| 63 | + return "Unconnected"; | |
| 64 | + case EP0_SETUP_PHASE: | |
| 65 | + return "Setup Phase"; | |
| 66 | + case EP0_DATA_PHASE: | |
| 67 | + return "Data Phase"; | |
| 68 | + case EP0_STATUS_PHASE: | |
| 69 | + return "Status Phase"; | |
| 70 | + default: | |
| 71 | + return "UNKNOWN"; | |
| 72 | + } | |
| 73 | +} | |
| 74 | + | |
| 75 | +static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, | |
| 76 | + u32 len, u32 type) | |
| 77 | +{ | |
| 78 | + struct dwc3_gadget_ep_cmd_params params; | |
| 79 | + struct dwc3_trb_hw *trb_hw; | |
| 80 | + struct dwc3_trb trb; | |
| 81 | + struct dwc3_ep *dep; | |
| 82 | + | |
| 83 | + int ret; | |
| 84 | + | |
| 85 | + dep = dwc->eps[epnum]; | |
| 86 | + if (dep->flags & DWC3_EP_BUSY) { | |
| 87 | + dev_vdbg(dwc->dev, "%s: still busy\n", dep->name); | |
| 88 | + return 0; | |
| 89 | + } | |
| 90 | + | |
| 91 | + trb_hw = dwc->ep0_trb; | |
| 92 | + memset(&trb, 0, sizeof(trb)); | |
| 93 | + | |
| 94 | + trb.trbctl = type; | |
| 95 | + trb.bplh = buf_dma; | |
| 96 | + trb.length = len; | |
| 97 | + | |
| 98 | + trb.hwo = 1; | |
| 99 | + trb.lst = 1; | |
| 100 | + trb.ioc = 1; | |
| 101 | + trb.isp_imi = 1; | |
| 102 | + | |
| 103 | + dwc3_trb_to_hw(&trb, trb_hw); | |
| 104 | + | |
| 105 | + memset(¶ms, 0, sizeof(params)); | |
| 106 | + params.param0 = upper_32_bits(dwc->ep0_trb_addr); | |
| 107 | + params.param1 = lower_32_bits(dwc->ep0_trb_addr); | |
| 108 | + | |
| 109 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 110 | + DWC3_DEPCMD_STARTTRANSFER, ¶ms); | |
| 111 | + if (ret < 0) { | |
| 112 | + dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n"); | |
| 113 | + return ret; | |
| 114 | + } | |
| 115 | + | |
| 116 | + dep->flags |= DWC3_EP_BUSY; | |
| 117 | + dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 118 | + dep->number); | |
| 119 | + | |
| 120 | + dwc->ep0_next_event = DWC3_EP0_COMPLETE; | |
| 121 | + | |
| 122 | + return 0; | |
| 123 | +} | |
| 124 | + | |
| 125 | +static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, | |
| 126 | + struct dwc3_request *req) | |
| 127 | +{ | |
| 128 | + int ret = 0; | |
| 129 | + | |
| 130 | + req->request.actual = 0; | |
| 131 | + req->request.status = -EINPROGRESS; | |
| 132 | + req->epnum = dep->number; | |
| 133 | + | |
| 134 | + list_add_tail(&req->list, &dep->request_list); | |
| 135 | + | |
| 136 | + /* | |
| 137 | + * Gadget driver might not be quick enough to queue a request | |
| 138 | + * before we get a Transfer Not Ready event on this endpoint. | |
| 139 | + * | |
| 140 | + * In that case, we will set DWC3_EP_PENDING_REQUEST. When that | |
| 141 | + * flag is set, it's telling us that as soon as Gadget queues the | |
| 142 | + * required request, we should kick the transfer here because the | |
| 143 | + * IRQ we were waiting for is long gone. | |
| 144 | + */ | |
| 145 | + if (dep->flags & DWC3_EP_PENDING_REQUEST) { | |
| 146 | + struct dwc3 *dwc = dep->dwc; | |
| 147 | + unsigned direction; | |
| 148 | + u32 type; | |
| 149 | + | |
| 150 | + direction = !!(dep->flags & DWC3_EP0_DIR_IN); | |
| 151 | + | |
| 152 | + if (dwc->ep0state == EP0_STATUS_PHASE) { | |
| 153 | + type = dwc->three_stage_setup | |
| 154 | + ? DWC3_TRBCTL_CONTROL_STATUS3 | |
| 155 | + : DWC3_TRBCTL_CONTROL_STATUS2; | |
| 156 | + } else if (dwc->ep0state == EP0_DATA_PHASE) { | |
| 157 | + type = DWC3_TRBCTL_CONTROL_DATA; | |
| 158 | + } else { | |
| 159 | + /* should never happen */ | |
| 160 | + WARN_ON(1); | |
| 161 | + return 0; | |
| 162 | + } | |
| 163 | + | |
| 164 | + ret = dwc3_ep0_start_trans(dwc, direction, | |
| 165 | + req->request.dma, req->request.length, type); | |
| 166 | + dep->flags &= ~(DWC3_EP_PENDING_REQUEST | | |
| 167 | + DWC3_EP0_DIR_IN); | |
| 168 | + } | |
| 169 | + | |
| 170 | + return ret; | |
| 171 | +} | |
| 172 | + | |
| 173 | +int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, | |
| 174 | + gfp_t gfp_flags) | |
| 175 | +{ | |
| 176 | + struct dwc3_request *req = to_dwc3_request(request); | |
| 177 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 178 | + struct dwc3 *dwc = dep->dwc; | |
| 179 | + | |
| 180 | + unsigned long flags; | |
| 181 | + | |
| 182 | + int ret; | |
| 183 | + | |
| 184 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 185 | + if (!dep->desc) { | |
| 186 | + dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", | |
| 187 | + request, dep->name); | |
| 188 | + ret = -ESHUTDOWN; | |
| 189 | + goto out; | |
| 190 | + } | |
| 191 | + | |
| 192 | + /* we share one TRB for ep0/1 */ | |
| 193 | + if (!list_empty(&dwc->eps[0]->request_list) || | |
| 194 | + !list_empty(&dwc->eps[1]->request_list) || | |
| 195 | + dwc->ep0_status_pending) { | |
| 196 | + ret = -EBUSY; | |
| 197 | + goto out; | |
| 198 | + } | |
| 199 | + | |
| 200 | + dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", | |
| 201 | + request, dep->name, request->length, | |
| 202 | + dwc3_ep0_state_string(dwc->ep0state)); | |
| 203 | + | |
| 204 | + ret = __dwc3_gadget_ep0_queue(dep, req); | |
| 205 | + | |
| 206 | +out: | |
| 207 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 208 | + | |
| 209 | + return ret; | |
| 210 | +} | |
| 211 | + | |
| 212 | +static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) | |
| 213 | +{ | |
| 214 | + struct dwc3_ep *dep = dwc->eps[0]; | |
| 215 | + | |
| 216 | + /* stall is always issued on EP0 */ | |
| 217 | + __dwc3_gadget_ep_set_halt(dwc->eps[0], 1); | |
| 218 | + dwc->eps[0]->flags = DWC3_EP_ENABLED; | |
| 219 | + | |
| 220 | + if (!list_empty(&dep->request_list)) { | |
| 221 | + struct dwc3_request *req; | |
| 222 | + | |
| 223 | + req = next_request(&dep->request_list); | |
| 224 | + dwc3_gadget_giveback(dep, req, -ECONNRESET); | |
| 225 | + } | |
| 226 | + | |
| 227 | + dwc->ep0state = EP0_SETUP_PHASE; | |
| 228 | + dwc3_ep0_out_start(dwc); | |
| 229 | +} | |
| 230 | + | |
| 231 | +void dwc3_ep0_out_start(struct dwc3 *dwc) | |
| 232 | +{ | |
| 233 | + int ret; | |
| 234 | + | |
| 235 | + ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, | |
| 236 | + DWC3_TRBCTL_CONTROL_SETUP); | |
| 237 | + WARN_ON(ret < 0); | |
| 238 | +} | |
| 239 | + | |
| 240 | +static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le) | |
| 241 | +{ | |
| 242 | + struct dwc3_ep *dep; | |
| 243 | + u32 windex = le16_to_cpu(wIndex_le); | |
| 244 | + u32 epnum; | |
| 245 | + | |
| 246 | + epnum = (windex & USB_ENDPOINT_NUMBER_MASK) << 1; | |
| 247 | + if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | |
| 248 | + epnum |= 1; | |
| 249 | + | |
| 250 | + dep = dwc->eps[epnum]; | |
| 251 | + if (dep->flags & DWC3_EP_ENABLED) | |
| 252 | + return dep; | |
| 253 | + | |
| 254 | + return NULL; | |
| 255 | +} | |
| 256 | + | |
| 257 | +static void dwc3_ep0_send_status_response(struct dwc3 *dwc) | |
| 258 | +{ | |
| 259 | + dwc3_ep0_start_trans(dwc, 1, dwc->setup_buf_addr, | |
| 260 | + dwc->ep0_usb_req.length, | |
| 261 | + DWC3_TRBCTL_CONTROL_DATA); | |
| 262 | +} | |
| 263 | + | |
| 264 | +/* | |
| 265 | + * ch 9.4.5 | |
| 266 | + */ | |
| 267 | +static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |
| 268 | +{ | |
| 269 | + struct dwc3_ep *dep; | |
| 270 | + u32 recip; | |
| 271 | + u16 usb_status = 0; | |
| 272 | + __le16 *response_pkt; | |
| 273 | + | |
| 274 | + recip = ctrl->bRequestType & USB_RECIP_MASK; | |
| 275 | + switch (recip) { | |
| 276 | + case USB_RECIP_DEVICE: | |
| 277 | + /* | |
| 278 | + * We are self-powered. U1/U2/LTM will be set later | |
| 279 | + * once we handle this states. RemoteWakeup is 0 on SS | |
| 280 | + */ | |
| 281 | + usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; | |
| 282 | + break; | |
| 283 | + | |
| 284 | + case USB_RECIP_INTERFACE: | |
| 285 | + /* | |
| 286 | + * Function Remote Wake Capable D0 | |
| 287 | + * Function Remote Wakeup D1 | |
| 288 | + */ | |
| 289 | + break; | |
| 290 | + | |
| 291 | + case USB_RECIP_ENDPOINT: | |
| 292 | + dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); | |
| 293 | + if (!dep) | |
| 294 | + return -EINVAL; | |
| 295 | + | |
| 296 | + if (dep->flags & DWC3_EP_STALL) | |
| 297 | + usb_status = 1 << USB_ENDPOINT_HALT; | |
| 298 | + break; | |
| 299 | + default: | |
| 300 | + return -EINVAL; | |
| 301 | + }; | |
| 302 | + | |
| 303 | + response_pkt = (__le16 *) dwc->setup_buf; | |
| 304 | + *response_pkt = cpu_to_le16(usb_status); | |
| 305 | + dwc->ep0_usb_req.length = sizeof(*response_pkt); | |
| 306 | + dwc->ep0_status_pending = 1; | |
| 307 | + | |
| 308 | + return 0; | |
| 309 | +} | |
| 310 | + | |
| 311 | +static int dwc3_ep0_handle_feature(struct dwc3 *dwc, | |
| 312 | + struct usb_ctrlrequest *ctrl, int set) | |
| 313 | +{ | |
| 314 | + struct dwc3_ep *dep; | |
| 315 | + u32 recip; | |
| 316 | + u32 wValue; | |
| 317 | + u32 wIndex; | |
| 318 | + u32 reg; | |
| 319 | + int ret; | |
| 320 | + u32 mode; | |
| 321 | + | |
| 322 | + wValue = le16_to_cpu(ctrl->wValue); | |
| 323 | + wIndex = le16_to_cpu(ctrl->wIndex); | |
| 324 | + recip = ctrl->bRequestType & USB_RECIP_MASK; | |
| 325 | + switch (recip) { | |
| 326 | + case USB_RECIP_DEVICE: | |
| 327 | + | |
| 328 | + /* | |
| 329 | + * 9.4.1 says only only for SS, in AddressState only for | |
| 330 | + * default control pipe | |
| 331 | + */ | |
| 332 | + switch (wValue) { | |
| 333 | + case USB_DEVICE_U1_ENABLE: | |
| 334 | + case USB_DEVICE_U2_ENABLE: | |
| 335 | + case USB_DEVICE_LTM_ENABLE: | |
| 336 | + if (dwc->dev_state != DWC3_CONFIGURED_STATE) | |
| 337 | + return -EINVAL; | |
| 338 | + if (dwc->speed != DWC3_DSTS_SUPERSPEED) | |
| 339 | + return -EINVAL; | |
| 340 | + } | |
| 341 | + | |
| 342 | + /* XXX add U[12] & LTM */ | |
| 343 | + switch (wValue) { | |
| 344 | + case USB_DEVICE_REMOTE_WAKEUP: | |
| 345 | + break; | |
| 346 | + case USB_DEVICE_U1_ENABLE: | |
| 347 | + break; | |
| 348 | + case USB_DEVICE_U2_ENABLE: | |
| 349 | + break; | |
| 350 | + case USB_DEVICE_LTM_ENABLE: | |
| 351 | + break; | |
| 352 | + | |
| 353 | + case USB_DEVICE_TEST_MODE: | |
| 354 | + if ((wIndex & 0xff) != 0) | |
| 355 | + return -EINVAL; | |
| 356 | + if (!set) | |
| 357 | + return -EINVAL; | |
| 358 | + | |
| 359 | + mode = wIndex >> 8; | |
| 360 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 361 | + reg &= ~DWC3_DCTL_TSTCTRL_MASK; | |
| 362 | + | |
| 363 | + switch (mode) { | |
| 364 | + case TEST_J: | |
| 365 | + case TEST_K: | |
| 366 | + case TEST_SE0_NAK: | |
| 367 | + case TEST_PACKET: | |
| 368 | + case TEST_FORCE_EN: | |
| 369 | + reg |= mode << 1; | |
| 370 | + break; | |
| 371 | + default: | |
| 372 | + return -EINVAL; | |
| 373 | + } | |
| 374 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 375 | + break; | |
| 376 | + default: | |
| 377 | + return -EINVAL; | |
| 378 | + } | |
| 379 | + break; | |
| 380 | + | |
| 381 | + case USB_RECIP_INTERFACE: | |
| 382 | + switch (wValue) { | |
| 383 | + case USB_INTRF_FUNC_SUSPEND: | |
| 384 | + if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) | |
| 385 | + /* XXX enable Low power suspend */ | |
| 386 | + ; | |
| 387 | + if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) | |
| 388 | + /* XXX enable remote wakeup */ | |
| 389 | + ; | |
| 390 | + break; | |
| 391 | + default: | |
| 392 | + return -EINVAL; | |
| 393 | + } | |
| 394 | + break; | |
| 395 | + | |
| 396 | + case USB_RECIP_ENDPOINT: | |
| 397 | + switch (wValue) { | |
| 398 | + case USB_ENDPOINT_HALT: | |
| 399 | + | |
| 400 | + dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); | |
| 401 | + if (!dep) | |
| 402 | + return -EINVAL; | |
| 403 | + ret = __dwc3_gadget_ep_set_halt(dep, set); | |
| 404 | + if (ret) | |
| 405 | + return -EINVAL; | |
| 406 | + break; | |
| 407 | + default: | |
| 408 | + return -EINVAL; | |
| 409 | + } | |
| 410 | + break; | |
| 411 | + | |
| 412 | + default: | |
| 413 | + return -EINVAL; | |
| 414 | + }; | |
| 415 | + | |
| 416 | + return 0; | |
| 417 | +} | |
| 418 | + | |
| 419 | +static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |
| 420 | +{ | |
| 421 | + u32 addr; | |
| 422 | + u32 reg; | |
| 423 | + | |
| 424 | + addr = le16_to_cpu(ctrl->wValue); | |
| 425 | + if (addr > 127) | |
| 426 | + return -EINVAL; | |
| 427 | + | |
| 428 | + reg = dwc3_readl(dwc->regs, DWC3_DCFG); | |
| 429 | + reg &= ~(DWC3_DCFG_DEVADDR_MASK); | |
| 430 | + reg |= DWC3_DCFG_DEVADDR(addr); | |
| 431 | + dwc3_writel(dwc->regs, DWC3_DCFG, reg); | |
| 432 | + | |
| 433 | + if (addr) | |
| 434 | + dwc->dev_state = DWC3_ADDRESS_STATE; | |
| 435 | + else | |
| 436 | + dwc->dev_state = DWC3_DEFAULT_STATE; | |
| 437 | + | |
| 438 | + return 0; | |
| 439 | +} | |
| 440 | + | |
| 441 | +static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |
| 442 | +{ | |
| 443 | + int ret; | |
| 444 | + | |
| 445 | + spin_unlock(&dwc->lock); | |
| 446 | + ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); | |
| 447 | + spin_lock(&dwc->lock); | |
| 448 | + return ret; | |
| 449 | +} | |
| 450 | + | |
| 451 | +static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |
| 452 | +{ | |
| 453 | + u32 cfg; | |
| 454 | + int ret; | |
| 455 | + | |
| 456 | + dwc->start_config_issued = false; | |
| 457 | + cfg = le16_to_cpu(ctrl->wValue); | |
| 458 | + | |
| 459 | + switch (dwc->dev_state) { | |
| 460 | + case DWC3_DEFAULT_STATE: | |
| 461 | + return -EINVAL; | |
| 462 | + break; | |
| 463 | + | |
| 464 | + case DWC3_ADDRESS_STATE: | |
| 465 | + ret = dwc3_ep0_delegate_req(dwc, ctrl); | |
| 466 | + /* if the cfg matches and the cfg is non zero */ | |
| 467 | + if (!ret && cfg) | |
| 468 | + dwc->dev_state = DWC3_CONFIGURED_STATE; | |
| 469 | + break; | |
| 470 | + | |
| 471 | + case DWC3_CONFIGURED_STATE: | |
| 472 | + ret = dwc3_ep0_delegate_req(dwc, ctrl); | |
| 473 | + if (!cfg) | |
| 474 | + dwc->dev_state = DWC3_ADDRESS_STATE; | |
| 475 | + break; | |
| 476 | + } | |
| 477 | + return 0; | |
| 478 | +} | |
| 479 | + | |
| 480 | +static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |
| 481 | +{ | |
| 482 | + int ret; | |
| 483 | + | |
| 484 | + switch (ctrl->bRequest) { | |
| 485 | + case USB_REQ_GET_STATUS: | |
| 486 | + dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n"); | |
| 487 | + ret = dwc3_ep0_handle_status(dwc, ctrl); | |
| 488 | + break; | |
| 489 | + case USB_REQ_CLEAR_FEATURE: | |
| 490 | + dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n"); | |
| 491 | + ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); | |
| 492 | + break; | |
| 493 | + case USB_REQ_SET_FEATURE: | |
| 494 | + dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n"); | |
| 495 | + ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); | |
| 496 | + break; | |
| 497 | + case USB_REQ_SET_ADDRESS: | |
| 498 | + dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n"); | |
| 499 | + ret = dwc3_ep0_set_address(dwc, ctrl); | |
| 500 | + break; | |
| 501 | + case USB_REQ_SET_CONFIGURATION: | |
| 502 | + dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n"); | |
| 503 | + ret = dwc3_ep0_set_config(dwc, ctrl); | |
| 504 | + break; | |
| 505 | + default: | |
| 506 | + dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); | |
| 507 | + ret = dwc3_ep0_delegate_req(dwc, ctrl); | |
| 508 | + break; | |
| 509 | + }; | |
| 510 | + | |
| 511 | + return ret; | |
| 512 | +} | |
| 513 | + | |
| 514 | +static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | |
| 515 | + const struct dwc3_event_depevt *event) | |
| 516 | +{ | |
| 517 | + struct usb_ctrlrequest *ctrl = dwc->ctrl_req; | |
| 518 | + int ret; | |
| 519 | + u32 len; | |
| 520 | + | |
| 521 | + if (!dwc->gadget_driver) | |
| 522 | + goto err; | |
| 523 | + | |
| 524 | + len = le16_to_cpu(ctrl->wLength); | |
| 525 | + if (!len) { | |
| 526 | + dwc->three_stage_setup = false; | |
| 527 | + dwc->ep0_expect_in = false; | |
| 528 | + dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; | |
| 529 | + } else { | |
| 530 | + dwc->three_stage_setup = true; | |
| 531 | + dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN); | |
| 532 | + dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; | |
| 533 | + } | |
| 534 | + | |
| 535 | + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | |
| 536 | + ret = dwc3_ep0_std_request(dwc, ctrl); | |
| 537 | + else | |
| 538 | + ret = dwc3_ep0_delegate_req(dwc, ctrl); | |
| 539 | + | |
| 540 | + if (ret >= 0) | |
| 541 | + return; | |
| 542 | + | |
| 543 | +err: | |
| 544 | + dwc3_ep0_stall_and_restart(dwc); | |
| 545 | +} | |
| 546 | + | |
| 547 | +static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |
| 548 | + const struct dwc3_event_depevt *event) | |
| 549 | +{ | |
| 550 | + struct dwc3_request *r = NULL; | |
| 551 | + struct usb_request *ur; | |
| 552 | + struct dwc3_trb trb; | |
| 553 | + struct dwc3_ep *dep; | |
| 554 | + u32 transferred; | |
| 555 | + u8 epnum; | |
| 556 | + | |
| 557 | + epnum = event->endpoint_number; | |
| 558 | + dep = dwc->eps[epnum]; | |
| 559 | + | |
| 560 | + dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; | |
| 561 | + | |
| 562 | + if (!dwc->ep0_status_pending) { | |
| 563 | + r = next_request(&dwc->eps[0]->request_list); | |
| 564 | + ur = &r->request; | |
| 565 | + } else { | |
| 566 | + ur = &dwc->ep0_usb_req; | |
| 567 | + dwc->ep0_status_pending = 0; | |
| 568 | + } | |
| 569 | + | |
| 570 | + dwc3_trb_to_nat(dwc->ep0_trb, &trb); | |
| 571 | + | |
| 572 | + if (dwc->ep0_bounced) { | |
| 573 | + struct dwc3_ep *ep0 = dwc->eps[0]; | |
| 574 | + | |
| 575 | + transferred = min_t(u32, ur->length, | |
| 576 | + ep0->endpoint.maxpacket - trb.length); | |
| 577 | + memcpy(ur->buf, dwc->ep0_bounce, transferred); | |
| 578 | + dwc->ep0_bounced = false; | |
| 579 | + } else { | |
| 580 | + transferred = ur->length - trb.length; | |
| 581 | + ur->actual += transferred; | |
| 582 | + } | |
| 583 | + | |
| 584 | + if ((epnum & 1) && ur->actual < ur->length) { | |
| 585 | + /* for some reason we did not get everything out */ | |
| 586 | + | |
| 587 | + dwc3_ep0_stall_and_restart(dwc); | |
| 588 | + } else { | |
| 589 | + /* | |
| 590 | + * handle the case where we have to send a zero packet. This | |
| 591 | + * seems to be case when req.length > maxpacket. Could it be? | |
| 592 | + */ | |
| 593 | + if (r) | |
| 594 | + dwc3_gadget_giveback(dep, r, 0); | |
| 595 | + } | |
| 596 | +} | |
| 597 | + | |
| 598 | +static void dwc3_ep0_complete_req(struct dwc3 *dwc, | |
| 599 | + const struct dwc3_event_depevt *event) | |
| 600 | +{ | |
| 601 | + struct dwc3_request *r; | |
| 602 | + struct dwc3_ep *dep; | |
| 603 | + | |
| 604 | + dep = dwc->eps[0]; | |
| 605 | + | |
| 606 | + if (!list_empty(&dep->request_list)) { | |
| 607 | + r = next_request(&dep->request_list); | |
| 608 | + | |
| 609 | + dwc3_gadget_giveback(dep, r, 0); | |
| 610 | + } | |
| 611 | + | |
| 612 | + dwc->ep0state = EP0_SETUP_PHASE; | |
| 613 | + dwc3_ep0_out_start(dwc); | |
| 614 | +} | |
| 615 | + | |
| 616 | +static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, | |
| 617 | + const struct dwc3_event_depevt *event) | |
| 618 | +{ | |
| 619 | + struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; | |
| 620 | + | |
| 621 | + dep->flags &= ~DWC3_EP_BUSY; | |
| 622 | + | |
| 623 | + switch (dwc->ep0state) { | |
| 624 | + case EP0_SETUP_PHASE: | |
| 625 | + dev_vdbg(dwc->dev, "Inspecting Setup Bytes\n"); | |
| 626 | + dwc3_ep0_inspect_setup(dwc, event); | |
| 627 | + break; | |
| 628 | + | |
| 629 | + case EP0_DATA_PHASE: | |
| 630 | + dev_vdbg(dwc->dev, "Data Phase\n"); | |
| 631 | + dwc3_ep0_complete_data(dwc, event); | |
| 632 | + break; | |
| 633 | + | |
| 634 | + case EP0_STATUS_PHASE: | |
| 635 | + dev_vdbg(dwc->dev, "Status Phase\n"); | |
| 636 | + dwc3_ep0_complete_req(dwc, event); | |
| 637 | + break; | |
| 638 | + default: | |
| 639 | + WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state); | |
| 640 | + } | |
| 641 | +} | |
| 642 | + | |
| 643 | +static void dwc3_ep0_do_control_setup(struct dwc3 *dwc, | |
| 644 | + const struct dwc3_event_depevt *event) | |
| 645 | +{ | |
| 646 | + dwc->ep0state = EP0_SETUP_PHASE; | |
| 647 | + dwc3_ep0_out_start(dwc); | |
| 648 | +} | |
| 649 | + | |
| 650 | +static void dwc3_ep0_do_control_data(struct dwc3 *dwc, | |
| 651 | + const struct dwc3_event_depevt *event) | |
| 652 | +{ | |
| 653 | + struct dwc3_ep *dep; | |
| 654 | + struct dwc3_request *req; | |
| 655 | + int ret; | |
| 656 | + | |
| 657 | + dep = dwc->eps[0]; | |
| 658 | + dwc->ep0state = EP0_DATA_PHASE; | |
| 659 | + | |
| 660 | + if (dwc->ep0_status_pending) { | |
| 661 | + dwc3_ep0_send_status_response(dwc); | |
| 662 | + return; | |
| 663 | + } | |
| 664 | + | |
| 665 | + if (list_empty(&dep->request_list)) { | |
| 666 | + dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); | |
| 667 | + dep->flags |= DWC3_EP_PENDING_REQUEST; | |
| 668 | + | |
| 669 | + if (event->endpoint_number) | |
| 670 | + dep->flags |= DWC3_EP0_DIR_IN; | |
| 671 | + return; | |
| 672 | + } | |
| 673 | + | |
| 674 | + req = next_request(&dep->request_list); | |
| 675 | + req->direction = !!event->endpoint_number; | |
| 676 | + | |
| 677 | + dwc->ep0state = EP0_DATA_PHASE; | |
| 678 | + if (req->request.length == 0) { | |
| 679 | + ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 680 | + dwc->ctrl_req_addr, 0, | |
| 681 | + DWC3_TRBCTL_CONTROL_DATA); | |
| 682 | + } else if ((req->request.length % dep->endpoint.maxpacket) | |
| 683 | + && (event->endpoint_number == 0)) { | |
| 684 | + dwc3_map_buffer_to_dma(req); | |
| 685 | + | |
| 686 | + WARN_ON(req->request.length > dep->endpoint.maxpacket); | |
| 687 | + | |
| 688 | + dwc->ep0_bounced = true; | |
| 689 | + | |
| 690 | + /* | |
| 691 | + * REVISIT in case request length is bigger than EP0 | |
| 692 | + * wMaxPacketSize, we will need two chained TRBs to handle | |
| 693 | + * the transfer. | |
| 694 | + */ | |
| 695 | + ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 696 | + dwc->ep0_bounce_addr, dep->endpoint.maxpacket, | |
| 697 | + DWC3_TRBCTL_CONTROL_DATA); | |
| 698 | + } else { | |
| 699 | + dwc3_map_buffer_to_dma(req); | |
| 700 | + | |
| 701 | + ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 702 | + req->request.dma, req->request.length, | |
| 703 | + DWC3_TRBCTL_CONTROL_DATA); | |
| 704 | + } | |
| 705 | + | |
| 706 | + WARN_ON(ret < 0); | |
| 707 | +} | |
| 708 | + | |
| 709 | +static void dwc3_ep0_do_control_status(struct dwc3 *dwc, | |
| 710 | + const struct dwc3_event_depevt *event) | |
| 711 | +{ | |
| 712 | + u32 type; | |
| 713 | + int ret; | |
| 714 | + | |
| 715 | + dwc->ep0state = EP0_STATUS_PHASE; | |
| 716 | + | |
| 717 | + type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 | |
| 718 | + : DWC3_TRBCTL_CONTROL_STATUS2; | |
| 719 | + | |
| 720 | + ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 721 | + dwc->ctrl_req_addr, 0, type); | |
| 722 | + | |
| 723 | + WARN_ON(ret < 0); | |
| 724 | +} | |
| 725 | + | |
| 726 | +static void dwc3_ep0_xfernotready(struct dwc3 *dwc, | |
| 727 | + const struct dwc3_event_depevt *event) | |
| 728 | +{ | |
| 729 | + switch (event->status) { | |
| 730 | + case DEPEVT_STATUS_CONTROL_SETUP: | |
| 731 | + dev_vdbg(dwc->dev, "Control Setup\n"); | |
| 732 | + dwc3_ep0_do_control_setup(dwc, event); | |
| 733 | + break; | |
| 734 | + | |
| 735 | + case DEPEVT_STATUS_CONTROL_DATA: | |
| 736 | + dev_vdbg(dwc->dev, "Control Data\n"); | |
| 737 | + | |
| 738 | + if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { | |
| 739 | + dev_vdbg(dwc->dev, "Expected %d got %d\n", | |
| 740 | + dwc->ep0_next_event, | |
| 741 | + DWC3_EP0_NRDY_DATA); | |
| 742 | + | |
| 743 | + dwc3_ep0_stall_and_restart(dwc); | |
| 744 | + return; | |
| 745 | + } | |
| 746 | + | |
| 747 | + /* | |
| 748 | + * One of the possible error cases is when Host _does_ | |
| 749 | + * request for Data Phase, but it does so on the wrong | |
| 750 | + * direction. | |
| 751 | + * | |
| 752 | + * Here, we already know ep0_next_event is DATA (see above), | |
| 753 | + * so we only need to check for direction. | |
| 754 | + */ | |
| 755 | + if (dwc->ep0_expect_in != event->endpoint_number) { | |
| 756 | + dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); | |
| 757 | + dwc3_ep0_stall_and_restart(dwc); | |
| 758 | + return; | |
| 759 | + } | |
| 760 | + | |
| 761 | + dwc3_ep0_do_control_data(dwc, event); | |
| 762 | + break; | |
| 763 | + | |
| 764 | + case DEPEVT_STATUS_CONTROL_STATUS: | |
| 765 | + dev_vdbg(dwc->dev, "Control Status\n"); | |
| 766 | + | |
| 767 | + if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { | |
| 768 | + dev_vdbg(dwc->dev, "Expected %d got %d\n", | |
| 769 | + dwc->ep0_next_event, | |
| 770 | + DWC3_EP0_NRDY_STATUS); | |
| 771 | + | |
| 772 | + dwc3_ep0_stall_and_restart(dwc); | |
| 773 | + return; | |
| 774 | + } | |
| 775 | + dwc3_ep0_do_control_status(dwc, event); | |
| 776 | + } | |
| 777 | +} | |
| 778 | + | |
| 779 | +void dwc3_ep0_interrupt(struct dwc3 *dwc, | |
| 780 | + const const struct dwc3_event_depevt *event) | |
| 781 | +{ | |
| 782 | + u8 epnum = event->endpoint_number; | |
| 783 | + | |
| 784 | + dev_dbg(dwc->dev, "%s while ep%d%s in state '%s'\n", | |
| 785 | + dwc3_ep_event_string(event->endpoint_event), | |
| 786 | + epnum >> 1, (epnum & 1) ? "in" : "out", | |
| 787 | + dwc3_ep0_state_string(dwc->ep0state)); | |
| 788 | + | |
| 789 | + switch (event->endpoint_event) { | |
| 790 | + case DWC3_DEPEVT_XFERCOMPLETE: | |
| 791 | + dwc3_ep0_xfer_complete(dwc, event); | |
| 792 | + break; | |
| 793 | + | |
| 794 | + case DWC3_DEPEVT_XFERNOTREADY: | |
| 795 | + dwc3_ep0_xfernotready(dwc, event); | |
| 796 | + break; | |
| 797 | + | |
| 798 | + case DWC3_DEPEVT_XFERINPROGRESS: | |
| 799 | + case DWC3_DEPEVT_RXTXFIFOEVT: | |
| 800 | + case DWC3_DEPEVT_STREAMEVT: | |
| 801 | + case DWC3_DEPEVT_EPCMDCMPLT: | |
| 802 | + break; | |
| 803 | + } | |
| 804 | +} | |
| @@ -0,0 +1,2104 @@ | ||
| 1 | +/** | |
| 2 | + * gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#include <linux/kernel.h> | |
| 40 | +#include <linux/delay.h> | |
| 41 | +#include <linux/slab.h> | |
| 42 | +#include <linux/spinlock.h> | |
| 43 | +#include <linux/platform_device.h> | |
| 44 | +#include <linux/pm_runtime.h> | |
| 45 | +#include <linux/interrupt.h> | |
| 46 | +#include <linux/io.h> | |
| 47 | +#include <linux/list.h> | |
| 48 | +#include <linux/dma-mapping.h> | |
| 49 | + | |
| 50 | +#include <linux/usb/ch9.h> | |
| 51 | +#include <linux/usb/gadget.h> | |
| 52 | + | |
| 53 | +#include "core.h" | |
| 54 | +#include "gadget.h" | |
| 55 | +#include "io.h" | |
| 56 | + | |
| 57 | +#define DMA_ADDR_INVALID (~(dma_addr_t)0) | |
| 58 | + | |
| 59 | +void dwc3_map_buffer_to_dma(struct dwc3_request *req) | |
| 60 | +{ | |
| 61 | + struct dwc3 *dwc = req->dep->dwc; | |
| 62 | + | |
| 63 | + if (req->request.length == 0) { | |
| 64 | + /* req->request.dma = dwc->setup_buf_addr; */ | |
| 65 | + return; | |
| 66 | + } | |
| 67 | + | |
| 68 | + if (req->request.dma == DMA_ADDR_INVALID) { | |
| 69 | + req->request.dma = dma_map_single(dwc->dev, req->request.buf, | |
| 70 | + req->request.length, req->direction | |
| 71 | + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 72 | + req->mapped = true; | |
| 73 | + } | |
| 74 | +} | |
| 75 | + | |
| 76 | +void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) | |
| 77 | +{ | |
| 78 | + struct dwc3 *dwc = req->dep->dwc; | |
| 79 | + | |
| 80 | + if (req->request.length == 0) { | |
| 81 | + req->request.dma = DMA_ADDR_INVALID; | |
| 82 | + return; | |
| 83 | + } | |
| 84 | + | |
| 85 | + if (req->mapped) { | |
| 86 | + dma_unmap_single(dwc->dev, req->request.dma, | |
| 87 | + req->request.length, req->direction | |
| 88 | + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 89 | + req->mapped = 0; | |
| 90 | + req->request.dma = DMA_ADDR_INVALID; | |
| 91 | + } | |
| 92 | +} | |
| 93 | + | |
| 94 | +void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |
| 95 | + int status) | |
| 96 | +{ | |
| 97 | + struct dwc3 *dwc = dep->dwc; | |
| 98 | + | |
| 99 | + if (req->queued) { | |
| 100 | + dep->busy_slot++; | |
| 101 | + /* | |
| 102 | + * Skip LINK TRB. We can't use req->trb and check for | |
| 103 | + * DWC3_TRBCTL_LINK_TRB because it points the TRB we just | |
| 104 | + * completed (not the LINK TRB). | |
| 105 | + */ | |
| 106 | + if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | |
| 107 | + usb_endpoint_xfer_isoc(dep->desc)) | |
| 108 | + dep->busy_slot++; | |
| 109 | + } | |
| 110 | + list_del(&req->list); | |
| 111 | + | |
| 112 | + if (req->request.status == -EINPROGRESS) | |
| 113 | + req->request.status = status; | |
| 114 | + | |
| 115 | + dwc3_unmap_buffer_from_dma(req); | |
| 116 | + | |
| 117 | + dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", | |
| 118 | + req, dep->name, req->request.actual, | |
| 119 | + req->request.length, status); | |
| 120 | + | |
| 121 | + spin_unlock(&dwc->lock); | |
| 122 | + req->request.complete(&req->dep->endpoint, &req->request); | |
| 123 | + spin_lock(&dwc->lock); | |
| 124 | +} | |
| 125 | + | |
| 126 | +static const char *dwc3_gadget_ep_cmd_string(u8 cmd) | |
| 127 | +{ | |
| 128 | + switch (cmd) { | |
| 129 | + case DWC3_DEPCMD_DEPSTARTCFG: | |
| 130 | + return "Start New Configuration"; | |
| 131 | + case DWC3_DEPCMD_ENDTRANSFER: | |
| 132 | + return "End Transfer"; | |
| 133 | + case DWC3_DEPCMD_UPDATETRANSFER: | |
| 134 | + return "Update Transfer"; | |
| 135 | + case DWC3_DEPCMD_STARTTRANSFER: | |
| 136 | + return "Start Transfer"; | |
| 137 | + case DWC3_DEPCMD_CLEARSTALL: | |
| 138 | + return "Clear Stall"; | |
| 139 | + case DWC3_DEPCMD_SETSTALL: | |
| 140 | + return "Set Stall"; | |
| 141 | + case DWC3_DEPCMD_GETSEQNUMBER: | |
| 142 | + return "Get Data Sequence Number"; | |
| 143 | + case DWC3_DEPCMD_SETTRANSFRESOURCE: | |
| 144 | + return "Set Endpoint Transfer Resource"; | |
| 145 | + case DWC3_DEPCMD_SETEPCONFIG: | |
| 146 | + return "Set Endpoint Configuration"; | |
| 147 | + default: | |
| 148 | + return "UNKNOWN command"; | |
| 149 | + } | |
| 150 | +} | |
| 151 | + | |
| 152 | +int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, | |
| 153 | + unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) | |
| 154 | +{ | |
| 155 | + struct dwc3_ep *dep = dwc->eps[ep]; | |
| 156 | + u32 timeout = 500; | |
| 157 | + u32 reg; | |
| 158 | + | |
| 159 | + dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n", | |
| 160 | + dep->name, | |
| 161 | + dwc3_gadget_ep_cmd_string(cmd), params->param0, | |
| 162 | + params->param1, params->param2); | |
| 163 | + | |
| 164 | + dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); | |
| 165 | + dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1); | |
| 166 | + dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2); | |
| 167 | + | |
| 168 | + dwc3_writel(dwc->regs, DWC3_DEPCMD(ep), cmd | DWC3_DEPCMD_CMDACT); | |
| 169 | + do { | |
| 170 | + reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(ep)); | |
| 171 | + if (!(reg & DWC3_DEPCMD_CMDACT)) { | |
| 172 | + dev_vdbg(dwc->dev, "Command Complete --> %d\n", | |
| 173 | + DWC3_DEPCMD_STATUS(reg)); | |
| 174 | + return 0; | |
| 175 | + } | |
| 176 | + | |
| 177 | + /* | |
| 178 | + * We can't sleep here, because it is also called from | |
| 179 | + * interrupt context. | |
| 180 | + */ | |
| 181 | + timeout--; | |
| 182 | + if (!timeout) | |
| 183 | + return -ETIMEDOUT; | |
| 184 | + | |
| 185 | + udelay(1); | |
| 186 | + } while (1); | |
| 187 | +} | |
| 188 | + | |
| 189 | +static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, | |
| 190 | + struct dwc3_trb_hw *trb) | |
| 191 | +{ | |
| 192 | + u32 offset = (char *) trb - (char *) dep->trb_pool; | |
| 193 | + | |
| 194 | + return dep->trb_pool_dma + offset; | |
| 195 | +} | |
| 196 | + | |
| 197 | +static int dwc3_alloc_trb_pool(struct dwc3_ep *dep) | |
| 198 | +{ | |
| 199 | + struct dwc3 *dwc = dep->dwc; | |
| 200 | + | |
| 201 | + if (dep->trb_pool) | |
| 202 | + return 0; | |
| 203 | + | |
| 204 | + if (dep->number == 0 || dep->number == 1) | |
| 205 | + return 0; | |
| 206 | + | |
| 207 | + dep->trb_pool = dma_alloc_coherent(dwc->dev, | |
| 208 | + sizeof(struct dwc3_trb) * DWC3_TRB_NUM, | |
| 209 | + &dep->trb_pool_dma, GFP_KERNEL); | |
| 210 | + if (!dep->trb_pool) { | |
| 211 | + dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n", | |
| 212 | + dep->name); | |
| 213 | + return -ENOMEM; | |
| 214 | + } | |
| 215 | + | |
| 216 | + return 0; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static void dwc3_free_trb_pool(struct dwc3_ep *dep) | |
| 220 | +{ | |
| 221 | + struct dwc3 *dwc = dep->dwc; | |
| 222 | + | |
| 223 | + dma_free_coherent(dwc->dev, sizeof(struct dwc3_trb) * DWC3_TRB_NUM, | |
| 224 | + dep->trb_pool, dep->trb_pool_dma); | |
| 225 | + | |
| 226 | + dep->trb_pool = NULL; | |
| 227 | + dep->trb_pool_dma = 0; | |
| 228 | +} | |
| 229 | + | |
| 230 | +static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | |
| 231 | +{ | |
| 232 | + struct dwc3_gadget_ep_cmd_params params; | |
| 233 | + u32 cmd; | |
| 234 | + | |
| 235 | + memset(¶ms, 0x00, sizeof(params)); | |
| 236 | + | |
| 237 | + if (dep->number != 1) { | |
| 238 | + cmd = DWC3_DEPCMD_DEPSTARTCFG; | |
| 239 | + /* XferRscIdx == 0 for ep0 and 2 for the remaining */ | |
| 240 | + if (dep->number > 1) { | |
| 241 | + if (dwc->start_config_issued) | |
| 242 | + return 0; | |
| 243 | + dwc->start_config_issued = true; | |
| 244 | + cmd |= DWC3_DEPCMD_PARAM(2); | |
| 245 | + } | |
| 246 | + | |
| 247 | + return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); | |
| 248 | + } | |
| 249 | + | |
| 250 | + return 0; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | |
| 254 | + const struct usb_endpoint_descriptor *desc) | |
| 255 | +{ | |
| 256 | + struct dwc3_gadget_ep_cmd_params params; | |
| 257 | + | |
| 258 | + memset(¶ms, 0x00, sizeof(params)); | |
| 259 | + | |
| 260 | + params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) | |
| 261 | + | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) | |
| 262 | + | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst); | |
| 263 | + | |
| 264 | + params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN | |
| 265 | + | DWC3_DEPCFG_XFER_NOT_READY_EN; | |
| 266 | + | |
| 267 | + if (usb_endpoint_xfer_bulk(desc) && dep->endpoint.max_streams) { | |
| 268 | + params.param1 |= DWC3_DEPCFG_STREAM_CAPABLE | |
| 269 | + | DWC3_DEPCFG_STREAM_EVENT_EN; | |
| 270 | + dep->stream_capable = true; | |
| 271 | + } | |
| 272 | + | |
| 273 | + if (usb_endpoint_xfer_isoc(desc)) | |
| 274 | + params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; | |
| 275 | + | |
| 276 | + /* | |
| 277 | + * We are doing 1:1 mapping for endpoints, meaning | |
| 278 | + * Physical Endpoints 2 maps to Logical Endpoint 2 and | |
| 279 | + * so on. We consider the direction bit as part of the physical | |
| 280 | + * endpoint number. So USB endpoint 0x81 is 0x03. | |
| 281 | + */ | |
| 282 | + params.param1 |= DWC3_DEPCFG_EP_NUMBER(dep->number); | |
| 283 | + | |
| 284 | + /* | |
| 285 | + * We must use the lower 16 TX FIFOs even though | |
| 286 | + * HW might have more | |
| 287 | + */ | |
| 288 | + if (dep->direction) | |
| 289 | + params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1); | |
| 290 | + | |
| 291 | + if (desc->bInterval) { | |
| 292 | + params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1); | |
| 293 | + dep->interval = 1 << (desc->bInterval - 1); | |
| 294 | + } | |
| 295 | + | |
| 296 | + return dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 297 | + DWC3_DEPCMD_SETEPCONFIG, ¶ms); | |
| 298 | +} | |
| 299 | + | |
| 300 | +static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) | |
| 301 | +{ | |
| 302 | + struct dwc3_gadget_ep_cmd_params params; | |
| 303 | + | |
| 304 | + memset(¶ms, 0x00, sizeof(params)); | |
| 305 | + | |
| 306 | + params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1); | |
| 307 | + | |
| 308 | + return dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 309 | + DWC3_DEPCMD_SETTRANSFRESOURCE, ¶ms); | |
| 310 | +} | |
| 311 | + | |
| 312 | +/** | |
| 313 | + * __dwc3_gadget_ep_enable - Initializes a HW endpoint | |
| 314 | + * @dep: endpoint to be initialized | |
| 315 | + * @desc: USB Endpoint Descriptor | |
| 316 | + * | |
| 317 | + * Caller should take care of locking | |
| 318 | + */ | |
| 319 | +static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |
| 320 | + const struct usb_endpoint_descriptor *desc) | |
| 321 | +{ | |
| 322 | + struct dwc3 *dwc = dep->dwc; | |
| 323 | + u32 reg; | |
| 324 | + int ret = -ENOMEM; | |
| 325 | + | |
| 326 | + if (!(dep->flags & DWC3_EP_ENABLED)) { | |
| 327 | + ret = dwc3_gadget_start_config(dwc, dep); | |
| 328 | + if (ret) | |
| 329 | + return ret; | |
| 330 | + } | |
| 331 | + | |
| 332 | + ret = dwc3_gadget_set_ep_config(dwc, dep, desc); | |
| 333 | + if (ret) | |
| 334 | + return ret; | |
| 335 | + | |
| 336 | + if (!(dep->flags & DWC3_EP_ENABLED)) { | |
| 337 | + struct dwc3_trb_hw *trb_st_hw; | |
| 338 | + struct dwc3_trb_hw *trb_link_hw; | |
| 339 | + struct dwc3_trb trb_link; | |
| 340 | + | |
| 341 | + ret = dwc3_gadget_set_xfer_resource(dwc, dep); | |
| 342 | + if (ret) | |
| 343 | + return ret; | |
| 344 | + | |
| 345 | + dep->desc = desc; | |
| 346 | + dep->type = usb_endpoint_type(desc); | |
| 347 | + dep->flags |= DWC3_EP_ENABLED; | |
| 348 | + | |
| 349 | + reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); | |
| 350 | + reg |= DWC3_DALEPENA_EP(dep->number); | |
| 351 | + dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); | |
| 352 | + | |
| 353 | + if (!usb_endpoint_xfer_isoc(desc)) | |
| 354 | + return 0; | |
| 355 | + | |
| 356 | + memset(&trb_link, 0, sizeof(trb_link)); | |
| 357 | + | |
| 358 | + /* Link TRB for ISOC. The HWO but is never reset */ | |
| 359 | + trb_st_hw = &dep->trb_pool[0]; | |
| 360 | + | |
| 361 | + trb_link.bplh = dwc3_trb_dma_offset(dep, trb_st_hw); | |
| 362 | + trb_link.trbctl = DWC3_TRBCTL_LINK_TRB; | |
| 363 | + trb_link.hwo = true; | |
| 364 | + | |
| 365 | + trb_link_hw = &dep->trb_pool[DWC3_TRB_NUM - 1]; | |
| 366 | + dwc3_trb_to_hw(&trb_link, trb_link_hw); | |
| 367 | + } | |
| 368 | + | |
| 369 | + return 0; | |
| 370 | +} | |
| 371 | + | |
| 372 | +static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum); | |
| 373 | +static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) | |
| 374 | +{ | |
| 375 | + struct dwc3_request *req; | |
| 376 | + | |
| 377 | + if (!list_empty(&dep->req_queued)) | |
| 378 | + dwc3_stop_active_transfer(dwc, dep->number); | |
| 379 | + | |
| 380 | + while (!list_empty(&dep->request_list)) { | |
| 381 | + req = next_request(&dep->request_list); | |
| 382 | + | |
| 383 | + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); | |
| 384 | + } | |
| 385 | +} | |
| 386 | + | |
| 387 | +/** | |
| 388 | + * __dwc3_gadget_ep_disable - Disables a HW endpoint | |
| 389 | + * @dep: the endpoint to disable | |
| 390 | + * | |
| 391 | + * This function also removes requests which are currently processed ny the | |
| 392 | + * hardware and those which are not yet scheduled. | |
| 393 | + * Caller should take care of locking. | |
| 394 | + */ | |
| 395 | +static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) | |
| 396 | +{ | |
| 397 | + struct dwc3 *dwc = dep->dwc; | |
| 398 | + u32 reg; | |
| 399 | + | |
| 400 | + dwc3_remove_requests(dwc, dep); | |
| 401 | + | |
| 402 | + reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); | |
| 403 | + reg &= ~DWC3_DALEPENA_EP(dep->number); | |
| 404 | + dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); | |
| 405 | + | |
| 406 | + dep->stream_capable = false; | |
| 407 | + dep->desc = NULL; | |
| 408 | + dep->type = 0; | |
| 409 | + dep->flags = 0; | |
| 410 | + | |
| 411 | + return 0; | |
| 412 | +} | |
| 413 | + | |
| 414 | +/* -------------------------------------------------------------------------- */ | |
| 415 | + | |
| 416 | +static int dwc3_gadget_ep0_enable(struct usb_ep *ep, | |
| 417 | + const struct usb_endpoint_descriptor *desc) | |
| 418 | +{ | |
| 419 | + return -EINVAL; | |
| 420 | +} | |
| 421 | + | |
| 422 | +static int dwc3_gadget_ep0_disable(struct usb_ep *ep) | |
| 423 | +{ | |
| 424 | + return -EINVAL; | |
| 425 | +} | |
| 426 | + | |
| 427 | +/* -------------------------------------------------------------------------- */ | |
| 428 | + | |
| 429 | +static int dwc3_gadget_ep_enable(struct usb_ep *ep, | |
| 430 | + const struct usb_endpoint_descriptor *desc) | |
| 431 | +{ | |
| 432 | + struct dwc3_ep *dep; | |
| 433 | + struct dwc3 *dwc; | |
| 434 | + unsigned long flags; | |
| 435 | + int ret; | |
| 436 | + | |
| 437 | + if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { | |
| 438 | + pr_debug("dwc3: invalid parameters\n"); | |
| 439 | + return -EINVAL; | |
| 440 | + } | |
| 441 | + | |
| 442 | + if (!desc->wMaxPacketSize) { | |
| 443 | + pr_debug("dwc3: missing wMaxPacketSize\n"); | |
| 444 | + return -EINVAL; | |
| 445 | + } | |
| 446 | + | |
| 447 | + dep = to_dwc3_ep(ep); | |
| 448 | + dwc = dep->dwc; | |
| 449 | + | |
| 450 | + switch (usb_endpoint_type(desc)) { | |
| 451 | + case USB_ENDPOINT_XFER_CONTROL: | |
| 452 | + strncat(dep->name, "-control", sizeof(dep->name)); | |
| 453 | + break; | |
| 454 | + case USB_ENDPOINT_XFER_ISOC: | |
| 455 | + strncat(dep->name, "-isoc", sizeof(dep->name)); | |
| 456 | + break; | |
| 457 | + case USB_ENDPOINT_XFER_BULK: | |
| 458 | + strncat(dep->name, "-bulk", sizeof(dep->name)); | |
| 459 | + break; | |
| 460 | + case USB_ENDPOINT_XFER_INT: | |
| 461 | + strncat(dep->name, "-int", sizeof(dep->name)); | |
| 462 | + break; | |
| 463 | + default: | |
| 464 | + dev_err(dwc->dev, "invalid endpoint transfer type\n"); | |
| 465 | + } | |
| 466 | + | |
| 467 | + if (dep->flags & DWC3_EP_ENABLED) { | |
| 468 | + dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", | |
| 469 | + dep->name); | |
| 470 | + return 0; | |
| 471 | + } | |
| 472 | + | |
| 473 | + dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); | |
| 474 | + | |
| 475 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 476 | + ret = __dwc3_gadget_ep_enable(dep, desc); | |
| 477 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 478 | + | |
| 479 | + return ret; | |
| 480 | +} | |
| 481 | + | |
| 482 | +static int dwc3_gadget_ep_disable(struct usb_ep *ep) | |
| 483 | +{ | |
| 484 | + struct dwc3_ep *dep; | |
| 485 | + struct dwc3 *dwc; | |
| 486 | + unsigned long flags; | |
| 487 | + int ret; | |
| 488 | + | |
| 489 | + if (!ep) { | |
| 490 | + pr_debug("dwc3: invalid parameters\n"); | |
| 491 | + return -EINVAL; | |
| 492 | + } | |
| 493 | + | |
| 494 | + dep = to_dwc3_ep(ep); | |
| 495 | + dwc = dep->dwc; | |
| 496 | + | |
| 497 | + if (!(dep->flags & DWC3_EP_ENABLED)) { | |
| 498 | + dev_WARN_ONCE(dwc->dev, true, "%s is already disabled\n", | |
| 499 | + dep->name); | |
| 500 | + return 0; | |
| 501 | + } | |
| 502 | + | |
| 503 | + snprintf(dep->name, sizeof(dep->name), "ep%d%s", | |
| 504 | + dep->number >> 1, | |
| 505 | + (dep->number & 1) ? "in" : "out"); | |
| 506 | + | |
| 507 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 508 | + ret = __dwc3_gadget_ep_disable(dep); | |
| 509 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 510 | + | |
| 511 | + return ret; | |
| 512 | +} | |
| 513 | + | |
| 514 | +static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, | |
| 515 | + gfp_t gfp_flags) | |
| 516 | +{ | |
| 517 | + struct dwc3_request *req; | |
| 518 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 519 | + struct dwc3 *dwc = dep->dwc; | |
| 520 | + | |
| 521 | + req = kzalloc(sizeof(*req), gfp_flags); | |
| 522 | + if (!req) { | |
| 523 | + dev_err(dwc->dev, "not enough memory\n"); | |
| 524 | + return NULL; | |
| 525 | + } | |
| 526 | + | |
| 527 | + req->epnum = dep->number; | |
| 528 | + req->dep = dep; | |
| 529 | + req->request.dma = DMA_ADDR_INVALID; | |
| 530 | + | |
| 531 | + return &req->request; | |
| 532 | +} | |
| 533 | + | |
| 534 | +static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |
| 535 | + struct usb_request *request) | |
| 536 | +{ | |
| 537 | + struct dwc3_request *req = to_dwc3_request(request); | |
| 538 | + | |
| 539 | + kfree(req); | |
| 540 | +} | |
| 541 | + | |
| 542 | +/* | |
| 543 | + * dwc3_prepare_trbs - setup TRBs from requests | |
| 544 | + * @dep: endpoint for which requests are being prepared | |
| 545 | + * @starting: true if the endpoint is idle and no requests are queued. | |
| 546 | + * | |
| 547 | + * The functions goes through the requests list and setups TRBs for the | |
| 548 | + * transfers. The functions returns once there are not more TRBs available or | |
| 549 | + * it run out of requests. | |
| 550 | + */ | |
| 551 | +static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |
| 552 | + bool starting) | |
| 553 | +{ | |
| 554 | + struct dwc3_request *req, *n, *ret = NULL; | |
| 555 | + struct dwc3_trb_hw *trb_hw; | |
| 556 | + struct dwc3_trb trb; | |
| 557 | + u32 trbs_left; | |
| 558 | + | |
| 559 | + BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | |
| 560 | + | |
| 561 | + /* the first request must not be queued */ | |
| 562 | + trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; | |
| 563 | + /* | |
| 564 | + * if busy & slot are equal than it is either full or empty. If we are | |
| 565 | + * starting to proceed requests then we are empty. Otherwise we ar | |
| 566 | + * full and don't do anything | |
| 567 | + */ | |
| 568 | + if (!trbs_left) { | |
| 569 | + if (!starting) | |
| 570 | + return NULL; | |
| 571 | + trbs_left = DWC3_TRB_NUM; | |
| 572 | + /* | |
| 573 | + * In case we start from scratch, we queue the ISOC requests | |
| 574 | + * starting from slot 1. This is done because we use ring | |
| 575 | + * buffer and have no LST bit to stop us. Instead, we place | |
| 576 | + * IOC bit TRB_NUM/4. We try to avoid to having an interrupt | |
| 577 | + * after the first request so we start at slot 1 and have | |
| 578 | + * 7 requests proceed before we hit the first IOC. | |
| 579 | + * Other transfer types don't use the ring buffer and are | |
| 580 | + * processed from the first TRB until the last one. Since we | |
| 581 | + * don't wrap around we have to start at the beginning. | |
| 582 | + */ | |
| 583 | + if (usb_endpoint_xfer_isoc(dep->desc)) { | |
| 584 | + dep->busy_slot = 1; | |
| 585 | + dep->free_slot = 1; | |
| 586 | + } else { | |
| 587 | + dep->busy_slot = 0; | |
| 588 | + dep->free_slot = 0; | |
| 589 | + } | |
| 590 | + } | |
| 591 | + | |
| 592 | + /* The last TRB is a link TRB, not used for xfer */ | |
| 593 | + if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) | |
| 594 | + return NULL; | |
| 595 | + | |
| 596 | + list_for_each_entry_safe(req, n, &dep->request_list, list) { | |
| 597 | + unsigned int last_one = 0; | |
| 598 | + unsigned int cur_slot; | |
| 599 | + | |
| 600 | + trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | |
| 601 | + cur_slot = dep->free_slot; | |
| 602 | + dep->free_slot++; | |
| 603 | + | |
| 604 | + /* Skip the LINK-TRB on ISOC */ | |
| 605 | + if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | |
| 606 | + usb_endpoint_xfer_isoc(dep->desc)) | |
| 607 | + continue; | |
| 608 | + | |
| 609 | + dwc3_gadget_move_request_queued(req); | |
| 610 | + memset(&trb, 0, sizeof(trb)); | |
| 611 | + trbs_left--; | |
| 612 | + | |
| 613 | + /* Is our TRB pool empty? */ | |
| 614 | + if (!trbs_left) | |
| 615 | + last_one = 1; | |
| 616 | + /* Is this the last request? */ | |
| 617 | + if (list_empty(&dep->request_list)) | |
| 618 | + last_one = 1; | |
| 619 | + | |
| 620 | + /* | |
| 621 | + * FIXME we shouldn't need to set LST bit always but we are | |
| 622 | + * facing some weird problem with the Hardware where it doesn't | |
| 623 | + * complete even though it has been previously started. | |
| 624 | + * | |
| 625 | + * While we're debugging the problem, as a workaround to | |
| 626 | + * multiple TRBs handling, use only one TRB at a time. | |
| 627 | + */ | |
| 628 | + last_one = 1; | |
| 629 | + | |
| 630 | + req->trb = trb_hw; | |
| 631 | + if (!ret) | |
| 632 | + ret = req; | |
| 633 | + | |
| 634 | + trb.bplh = req->request.dma; | |
| 635 | + | |
| 636 | + if (usb_endpoint_xfer_isoc(dep->desc)) { | |
| 637 | + trb.isp_imi = true; | |
| 638 | + trb.csp = true; | |
| 639 | + } else { | |
| 640 | + trb.lst = last_one; | |
| 641 | + } | |
| 642 | + | |
| 643 | + if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | |
| 644 | + trb.sid_sofn = req->request.stream_id; | |
| 645 | + | |
| 646 | + switch (usb_endpoint_type(dep->desc)) { | |
| 647 | + case USB_ENDPOINT_XFER_CONTROL: | |
| 648 | + trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | |
| 649 | + break; | |
| 650 | + | |
| 651 | + case USB_ENDPOINT_XFER_ISOC: | |
| 652 | + trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | |
| 653 | + | |
| 654 | + /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | |
| 655 | + if (!(cur_slot % (DWC3_TRB_NUM / 4))) | |
| 656 | + trb.ioc = last_one; | |
| 657 | + break; | |
| 658 | + | |
| 659 | + case USB_ENDPOINT_XFER_BULK: | |
| 660 | + case USB_ENDPOINT_XFER_INT: | |
| 661 | + trb.trbctl = DWC3_TRBCTL_NORMAL; | |
| 662 | + break; | |
| 663 | + default: | |
| 664 | + /* | |
| 665 | + * This is only possible with faulty memory because we | |
| 666 | + * checked it already :) | |
| 667 | + */ | |
| 668 | + BUG(); | |
| 669 | + } | |
| 670 | + | |
| 671 | + trb.length = req->request.length; | |
| 672 | + trb.hwo = true; | |
| 673 | + | |
| 674 | + dwc3_trb_to_hw(&trb, trb_hw); | |
| 675 | + req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | |
| 676 | + | |
| 677 | + if (last_one) | |
| 678 | + break; | |
| 679 | + } | |
| 680 | + | |
| 681 | + return ret; | |
| 682 | +} | |
| 683 | + | |
| 684 | +static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, | |
| 685 | + int start_new) | |
| 686 | +{ | |
| 687 | + struct dwc3_gadget_ep_cmd_params params; | |
| 688 | + struct dwc3_request *req; | |
| 689 | + struct dwc3 *dwc = dep->dwc; | |
| 690 | + int ret; | |
| 691 | + u32 cmd; | |
| 692 | + | |
| 693 | + if (start_new && (dep->flags & DWC3_EP_BUSY)) { | |
| 694 | + dev_vdbg(dwc->dev, "%s: endpoint busy\n", dep->name); | |
| 695 | + return -EBUSY; | |
| 696 | + } | |
| 697 | + dep->flags &= ~DWC3_EP_PENDING_REQUEST; | |
| 698 | + | |
| 699 | + /* | |
| 700 | + * If we are getting here after a short-out-packet we don't enqueue any | |
| 701 | + * new requests as we try to set the IOC bit only on the last request. | |
| 702 | + */ | |
| 703 | + if (start_new) { | |
| 704 | + if (list_empty(&dep->req_queued)) | |
| 705 | + dwc3_prepare_trbs(dep, start_new); | |
| 706 | + | |
| 707 | + /* req points to the first request which will be sent */ | |
| 708 | + req = next_request(&dep->req_queued); | |
| 709 | + } else { | |
| 710 | + /* | |
| 711 | + * req points to the first request where HWO changed | |
| 712 | + * from 0 to 1 | |
| 713 | + */ | |
| 714 | + req = dwc3_prepare_trbs(dep, start_new); | |
| 715 | + } | |
| 716 | + if (!req) { | |
| 717 | + dep->flags |= DWC3_EP_PENDING_REQUEST; | |
| 718 | + return 0; | |
| 719 | + } | |
| 720 | + | |
| 721 | + memset(¶ms, 0, sizeof(params)); | |
| 722 | + params.param0 = upper_32_bits(req->trb_dma); | |
| 723 | + params.param1 = lower_32_bits(req->trb_dma); | |
| 724 | + | |
| 725 | + if (start_new) | |
| 726 | + cmd = DWC3_DEPCMD_STARTTRANSFER; | |
| 727 | + else | |
| 728 | + cmd = DWC3_DEPCMD_UPDATETRANSFER; | |
| 729 | + | |
| 730 | + cmd |= DWC3_DEPCMD_PARAM(cmd_param); | |
| 731 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | |
| 732 | + if (ret < 0) { | |
| 733 | + dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n"); | |
| 734 | + | |
| 735 | + /* | |
| 736 | + * FIXME we need to iterate over the list of requests | |
| 737 | + * here and stop, unmap, free and del each of the linked | |
| 738 | + * requests instead of we do now. | |
| 739 | + */ | |
| 740 | + dwc3_unmap_buffer_from_dma(req); | |
| 741 | + list_del(&req->list); | |
| 742 | + return ret; | |
| 743 | + } | |
| 744 | + | |
| 745 | + dep->flags |= DWC3_EP_BUSY; | |
| 746 | + dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 747 | + dep->number); | |
| 748 | + if (!dep->res_trans_idx) | |
| 749 | + printk_once(KERN_ERR "%s() res_trans_idx is invalid\n", __func__); | |
| 750 | + return 0; | |
| 751 | +} | |
| 752 | + | |
| 753 | +static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |
| 754 | +{ | |
| 755 | + req->request.actual = 0; | |
| 756 | + req->request.status = -EINPROGRESS; | |
| 757 | + req->direction = dep->direction; | |
| 758 | + req->epnum = dep->number; | |
| 759 | + | |
| 760 | + /* | |
| 761 | + * We only add to our list of requests now and | |
| 762 | + * start consuming the list once we get XferNotReady | |
| 763 | + * IRQ. | |
| 764 | + * | |
| 765 | + * That way, we avoid doing anything that we don't need | |
| 766 | + * to do now and defer it until the point we receive a | |
| 767 | + * particular token from the Host side. | |
| 768 | + * | |
| 769 | + * This will also avoid Host cancelling URBs due to too | |
| 770 | + * many NACKs. | |
| 771 | + */ | |
| 772 | + dwc3_map_buffer_to_dma(req); | |
| 773 | + list_add_tail(&req->list, &dep->request_list); | |
| 774 | + | |
| 775 | + /* | |
| 776 | + * There is one special case: XferNotReady with | |
| 777 | + * empty list of requests. We need to kick the | |
| 778 | + * transfer here in that situation, otherwise | |
| 779 | + * we will be NAKing forever. | |
| 780 | + * | |
| 781 | + * If we get XferNotReady before gadget driver | |
| 782 | + * has a chance to queue a request, we will ACK | |
| 783 | + * the IRQ but won't be able to receive the data | |
| 784 | + * until the next request is queued. The following | |
| 785 | + * code is handling exactly that. | |
| 786 | + */ | |
| 787 | + if (dep->flags & DWC3_EP_PENDING_REQUEST) { | |
| 788 | + int ret; | |
| 789 | + int start_trans; | |
| 790 | + | |
| 791 | + start_trans = 1; | |
| 792 | + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | |
| 793 | + dep->flags & DWC3_EP_BUSY) | |
| 794 | + start_trans = 0; | |
| 795 | + | |
| 796 | + ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans); | |
| 797 | + if (ret && ret != -EBUSY) { | |
| 798 | + struct dwc3 *dwc = dep->dwc; | |
| 799 | + | |
| 800 | + dev_dbg(dwc->dev, "%s: failed to kick transfers\n", | |
| 801 | + dep->name); | |
| 802 | + } | |
| 803 | + }; | |
| 804 | + | |
| 805 | + return 0; | |
| 806 | +} | |
| 807 | + | |
| 808 | +static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, | |
| 809 | + gfp_t gfp_flags) | |
| 810 | +{ | |
| 811 | + struct dwc3_request *req = to_dwc3_request(request); | |
| 812 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 813 | + struct dwc3 *dwc = dep->dwc; | |
| 814 | + | |
| 815 | + unsigned long flags; | |
| 816 | + | |
| 817 | + int ret; | |
| 818 | + | |
| 819 | + if (!dep->desc) { | |
| 820 | + dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", | |
| 821 | + request, ep->name); | |
| 822 | + return -ESHUTDOWN; | |
| 823 | + } | |
| 824 | + | |
| 825 | + dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", | |
| 826 | + request, ep->name, request->length); | |
| 827 | + | |
| 828 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 829 | + ret = __dwc3_gadget_ep_queue(dep, req); | |
| 830 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 831 | + | |
| 832 | + return ret; | |
| 833 | +} | |
| 834 | + | |
| 835 | +static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |
| 836 | + struct usb_request *request) | |
| 837 | +{ | |
| 838 | + struct dwc3_request *req = to_dwc3_request(request); | |
| 839 | + struct dwc3_request *r = NULL; | |
| 840 | + | |
| 841 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 842 | + struct dwc3 *dwc = dep->dwc; | |
| 843 | + | |
| 844 | + unsigned long flags; | |
| 845 | + int ret = 0; | |
| 846 | + | |
| 847 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 848 | + | |
| 849 | + list_for_each_entry(r, &dep->request_list, list) { | |
| 850 | + if (r == req) | |
| 851 | + break; | |
| 852 | + } | |
| 853 | + | |
| 854 | + if (r != req) { | |
| 855 | + list_for_each_entry(r, &dep->req_queued, list) { | |
| 856 | + if (r == req) | |
| 857 | + break; | |
| 858 | + } | |
| 859 | + if (r == req) { | |
| 860 | + /* wait until it is processed */ | |
| 861 | + dwc3_stop_active_transfer(dwc, dep->number); | |
| 862 | + goto out0; | |
| 863 | + } | |
| 864 | + dev_err(dwc->dev, "request %p was not queued to %s\n", | |
| 865 | + request, ep->name); | |
| 866 | + ret = -EINVAL; | |
| 867 | + goto out0; | |
| 868 | + } | |
| 869 | + | |
| 870 | + /* giveback the request */ | |
| 871 | + dwc3_gadget_giveback(dep, req, -ECONNRESET); | |
| 872 | + | |
| 873 | +out0: | |
| 874 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 875 | + | |
| 876 | + return ret; | |
| 877 | +} | |
| 878 | + | |
| 879 | +int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) | |
| 880 | +{ | |
| 881 | + struct dwc3_gadget_ep_cmd_params params; | |
| 882 | + struct dwc3 *dwc = dep->dwc; | |
| 883 | + int ret; | |
| 884 | + | |
| 885 | + memset(¶ms, 0x00, sizeof(params)); | |
| 886 | + | |
| 887 | + if (value) { | |
| 888 | + if (dep->number == 0 || dep->number == 1) { | |
| 889 | + /* | |
| 890 | + * Whenever EP0 is stalled, we will restart | |
| 891 | + * the state machine, thus moving back to | |
| 892 | + * Setup Phase | |
| 893 | + */ | |
| 894 | + dwc->ep0state = EP0_SETUP_PHASE; | |
| 895 | + } | |
| 896 | + | |
| 897 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 898 | + DWC3_DEPCMD_SETSTALL, ¶ms); | |
| 899 | + if (ret) | |
| 900 | + dev_err(dwc->dev, "failed to %s STALL on %s\n", | |
| 901 | + value ? "set" : "clear", | |
| 902 | + dep->name); | |
| 903 | + else | |
| 904 | + dep->flags |= DWC3_EP_STALL; | |
| 905 | + } else { | |
| 906 | + if (dep->flags & DWC3_EP_WEDGE) | |
| 907 | + return 0; | |
| 908 | + | |
| 909 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 910 | + DWC3_DEPCMD_CLEARSTALL, ¶ms); | |
| 911 | + if (ret) | |
| 912 | + dev_err(dwc->dev, "failed to %s STALL on %s\n", | |
| 913 | + value ? "set" : "clear", | |
| 914 | + dep->name); | |
| 915 | + else | |
| 916 | + dep->flags &= ~DWC3_EP_STALL; | |
| 917 | + } | |
| 918 | + | |
| 919 | + return ret; | |
| 920 | +} | |
| 921 | + | |
| 922 | +static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) | |
| 923 | +{ | |
| 924 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 925 | + struct dwc3 *dwc = dep->dwc; | |
| 926 | + | |
| 927 | + unsigned long flags; | |
| 928 | + | |
| 929 | + int ret; | |
| 930 | + | |
| 931 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 932 | + | |
| 933 | + if (usb_endpoint_xfer_isoc(dep->desc)) { | |
| 934 | + dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); | |
| 935 | + ret = -EINVAL; | |
| 936 | + goto out; | |
| 937 | + } | |
| 938 | + | |
| 939 | + ret = __dwc3_gadget_ep_set_halt(dep, value); | |
| 940 | +out: | |
| 941 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 942 | + | |
| 943 | + return ret; | |
| 944 | +} | |
| 945 | + | |
| 946 | +static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) | |
| 947 | +{ | |
| 948 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 949 | + | |
| 950 | + dep->flags |= DWC3_EP_WEDGE; | |
| 951 | + | |
| 952 | + return dwc3_gadget_ep_set_halt(ep, 1); | |
| 953 | +} | |
| 954 | + | |
| 955 | +/* -------------------------------------------------------------------------- */ | |
| 956 | + | |
| 957 | +static struct usb_endpoint_descriptor dwc3_gadget_ep0_desc = { | |
| 958 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 959 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 960 | + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | |
| 961 | +}; | |
| 962 | + | |
| 963 | +static const struct usb_ep_ops dwc3_gadget_ep0_ops = { | |
| 964 | + .enable = dwc3_gadget_ep0_enable, | |
| 965 | + .disable = dwc3_gadget_ep0_disable, | |
| 966 | + .alloc_request = dwc3_gadget_ep_alloc_request, | |
| 967 | + .free_request = dwc3_gadget_ep_free_request, | |
| 968 | + .queue = dwc3_gadget_ep0_queue, | |
| 969 | + .dequeue = dwc3_gadget_ep_dequeue, | |
| 970 | + .set_halt = dwc3_gadget_ep_set_halt, | |
| 971 | + .set_wedge = dwc3_gadget_ep_set_wedge, | |
| 972 | +}; | |
| 973 | + | |
| 974 | +static const struct usb_ep_ops dwc3_gadget_ep_ops = { | |
| 975 | + .enable = dwc3_gadget_ep_enable, | |
| 976 | + .disable = dwc3_gadget_ep_disable, | |
| 977 | + .alloc_request = dwc3_gadget_ep_alloc_request, | |
| 978 | + .free_request = dwc3_gadget_ep_free_request, | |
| 979 | + .queue = dwc3_gadget_ep_queue, | |
| 980 | + .dequeue = dwc3_gadget_ep_dequeue, | |
| 981 | + .set_halt = dwc3_gadget_ep_set_halt, | |
| 982 | + .set_wedge = dwc3_gadget_ep_set_wedge, | |
| 983 | +}; | |
| 984 | + | |
| 985 | +/* -------------------------------------------------------------------------- */ | |
| 986 | + | |
| 987 | +static int dwc3_gadget_get_frame(struct usb_gadget *g) | |
| 988 | +{ | |
| 989 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 990 | + u32 reg; | |
| 991 | + | |
| 992 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 993 | + return DWC3_DSTS_SOFFN(reg); | |
| 994 | +} | |
| 995 | + | |
| 996 | +static int dwc3_gadget_wakeup(struct usb_gadget *g) | |
| 997 | +{ | |
| 998 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 999 | + | |
| 1000 | + unsigned long timeout; | |
| 1001 | + unsigned long flags; | |
| 1002 | + | |
| 1003 | + u32 reg; | |
| 1004 | + | |
| 1005 | + int ret = 0; | |
| 1006 | + | |
| 1007 | + u8 link_state; | |
| 1008 | + u8 speed; | |
| 1009 | + | |
| 1010 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 1011 | + | |
| 1012 | + /* | |
| 1013 | + * According to the Databook Remote wakeup request should | |
| 1014 | + * be issued only when the device is in early suspend state. | |
| 1015 | + * | |
| 1016 | + * We can check that via USB Link State bits in DSTS register. | |
| 1017 | + */ | |
| 1018 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 1019 | + | |
| 1020 | + speed = reg & DWC3_DSTS_CONNECTSPD; | |
| 1021 | + if (speed == DWC3_DSTS_SUPERSPEED) { | |
| 1022 | + dev_dbg(dwc->dev, "no wakeup on SuperSpeed\n"); | |
| 1023 | + ret = -EINVAL; | |
| 1024 | + goto out; | |
| 1025 | + } | |
| 1026 | + | |
| 1027 | + link_state = DWC3_DSTS_USBLNKST(reg); | |
| 1028 | + | |
| 1029 | + switch (link_state) { | |
| 1030 | + case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */ | |
| 1031 | + case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */ | |
| 1032 | + break; | |
| 1033 | + default: | |
| 1034 | + dev_dbg(dwc->dev, "can't wakeup from link state %d\n", | |
| 1035 | + link_state); | |
| 1036 | + ret = -EINVAL; | |
| 1037 | + goto out; | |
| 1038 | + } | |
| 1039 | + | |
| 1040 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 1041 | + | |
| 1042 | + /* | |
| 1043 | + * Switch link state to Recovery. In HS/FS/LS this means | |
| 1044 | + * RemoteWakeup Request | |
| 1045 | + */ | |
| 1046 | + reg |= DWC3_DCTL_ULSTCHNG_RECOVERY; | |
| 1047 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1048 | + | |
| 1049 | + /* wait for at least 2000us */ | |
| 1050 | + usleep_range(2000, 2500); | |
| 1051 | + | |
| 1052 | + /* write zeroes to Link Change Request */ | |
| 1053 | + reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; | |
| 1054 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1055 | + | |
| 1056 | + /* pool until Link State change to ON */ | |
| 1057 | + timeout = jiffies + msecs_to_jiffies(100); | |
| 1058 | + | |
| 1059 | + while (!(time_after(jiffies, timeout))) { | |
| 1060 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 1061 | + | |
| 1062 | + /* in HS, means ON */ | |
| 1063 | + if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) | |
| 1064 | + break; | |
| 1065 | + } | |
| 1066 | + | |
| 1067 | + if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { | |
| 1068 | + dev_err(dwc->dev, "failed to send remote wakeup\n"); | |
| 1069 | + ret = -EINVAL; | |
| 1070 | + } | |
| 1071 | + | |
| 1072 | +out: | |
| 1073 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1074 | + | |
| 1075 | + return ret; | |
| 1076 | +} | |
| 1077 | + | |
| 1078 | +static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, | |
| 1079 | + int is_selfpowered) | |
| 1080 | +{ | |
| 1081 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 1082 | + | |
| 1083 | + dwc->is_selfpowered = !!is_selfpowered; | |
| 1084 | + | |
| 1085 | + return 0; | |
| 1086 | +} | |
| 1087 | + | |
| 1088 | +static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) | |
| 1089 | +{ | |
| 1090 | + u32 reg; | |
| 1091 | + u32 timeout = 500; | |
| 1092 | + | |
| 1093 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 1094 | + if (is_on) | |
| 1095 | + reg |= DWC3_DCTL_RUN_STOP; | |
| 1096 | + else | |
| 1097 | + reg &= ~DWC3_DCTL_RUN_STOP; | |
| 1098 | + | |
| 1099 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1100 | + | |
| 1101 | + do { | |
| 1102 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 1103 | + if (is_on) { | |
| 1104 | + if (!(reg & DWC3_DSTS_DEVCTRLHLT)) | |
| 1105 | + break; | |
| 1106 | + } else { | |
| 1107 | + if (reg & DWC3_DSTS_DEVCTRLHLT) | |
| 1108 | + break; | |
| 1109 | + } | |
| 1110 | + timeout--; | |
| 1111 | + if (!timeout) | |
| 1112 | + break; | |
| 1113 | + udelay(1); | |
| 1114 | + } while (1); | |
| 1115 | + | |
| 1116 | + dev_vdbg(dwc->dev, "gadget %s data soft-%s\n", | |
| 1117 | + dwc->gadget_driver | |
| 1118 | + ? dwc->gadget_driver->function : "no-function", | |
| 1119 | + is_on ? "connect" : "disconnect"); | |
| 1120 | +} | |
| 1121 | + | |
| 1122 | +static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) | |
| 1123 | +{ | |
| 1124 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 1125 | + unsigned long flags; | |
| 1126 | + | |
| 1127 | + is_on = !!is_on; | |
| 1128 | + | |
| 1129 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 1130 | + dwc3_gadget_run_stop(dwc, is_on); | |
| 1131 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1132 | + | |
| 1133 | + return 0; | |
| 1134 | +} | |
| 1135 | + | |
| 1136 | +static int dwc3_gadget_start(struct usb_gadget *g, | |
| 1137 | + struct usb_gadget_driver *driver) | |
| 1138 | +{ | |
| 1139 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 1140 | + struct dwc3_ep *dep; | |
| 1141 | + unsigned long flags; | |
| 1142 | + int ret = 0; | |
| 1143 | + u32 reg; | |
| 1144 | + | |
| 1145 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 1146 | + | |
| 1147 | + if (dwc->gadget_driver) { | |
| 1148 | + dev_err(dwc->dev, "%s is already bound to %s\n", | |
| 1149 | + dwc->gadget.name, | |
| 1150 | + dwc->gadget_driver->driver.name); | |
| 1151 | + ret = -EBUSY; | |
| 1152 | + goto err0; | |
| 1153 | + } | |
| 1154 | + | |
| 1155 | + dwc->gadget_driver = driver; | |
| 1156 | + dwc->gadget.dev.driver = &driver->driver; | |
| 1157 | + | |
| 1158 | + reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
| 1159 | + | |
| 1160 | + reg &= ~DWC3_GCTL_SCALEDOWN(3); | |
| 1161 | + reg &= ~DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG); | |
| 1162 | + reg &= ~DWC3_GCTL_DISSCRAMBLE; | |
| 1163 | + reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE); | |
| 1164 | + | |
| 1165 | + switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams0)) { | |
| 1166 | + case DWC3_GHWPARAMS1_EN_PWROPT_CLK: | |
| 1167 | + reg &= ~DWC3_GCTL_DSBLCLKGTNG; | |
| 1168 | + break; | |
| 1169 | + default: | |
| 1170 | + dev_dbg(dwc->dev, "No power optimization available\n"); | |
| 1171 | + } | |
| 1172 | + | |
| 1173 | + /* | |
| 1174 | + * WORKAROUND: DWC3 revisions <1.90a have a bug | |
| 1175 | + * when The device fails to connect at SuperSpeed | |
| 1176 | + * and falls back to high-speed mode which causes | |
| 1177 | + * the device to enter in a Connect/Disconnect loop | |
| 1178 | + */ | |
| 1179 | + if (dwc->revision < DWC3_REVISION_190A) | |
| 1180 | + reg |= DWC3_GCTL_U2RSTECN; | |
| 1181 | + | |
| 1182 | + dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
| 1183 | + | |
| 1184 | + reg = dwc3_readl(dwc->regs, DWC3_DCFG); | |
| 1185 | + reg &= ~(DWC3_DCFG_SPEED_MASK); | |
| 1186 | + reg |= DWC3_DCFG_SUPERSPEED; | |
| 1187 | + dwc3_writel(dwc->regs, DWC3_DCFG, reg); | |
| 1188 | + | |
| 1189 | + dwc->start_config_issued = false; | |
| 1190 | + | |
| 1191 | + /* Start with SuperSpeed Default */ | |
| 1192 | + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | |
| 1193 | + | |
| 1194 | + dep = dwc->eps[0]; | |
| 1195 | + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc); | |
| 1196 | + if (ret) { | |
| 1197 | + dev_err(dwc->dev, "failed to enable %s\n", dep->name); | |
| 1198 | + goto err0; | |
| 1199 | + } | |
| 1200 | + | |
| 1201 | + dep = dwc->eps[1]; | |
| 1202 | + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc); | |
| 1203 | + if (ret) { | |
| 1204 | + dev_err(dwc->dev, "failed to enable %s\n", dep->name); | |
| 1205 | + goto err1; | |
| 1206 | + } | |
| 1207 | + | |
| 1208 | + /* begin to receive SETUP packets */ | |
| 1209 | + dwc->ep0state = EP0_SETUP_PHASE; | |
| 1210 | + dwc3_ep0_out_start(dwc); | |
| 1211 | + | |
| 1212 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1213 | + | |
| 1214 | + return 0; | |
| 1215 | + | |
| 1216 | +err1: | |
| 1217 | + __dwc3_gadget_ep_disable(dwc->eps[0]); | |
| 1218 | + | |
| 1219 | +err0: | |
| 1220 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1221 | + | |
| 1222 | + return ret; | |
| 1223 | +} | |
| 1224 | + | |
| 1225 | +static int dwc3_gadget_stop(struct usb_gadget *g, | |
| 1226 | + struct usb_gadget_driver *driver) | |
| 1227 | +{ | |
| 1228 | + struct dwc3 *dwc = gadget_to_dwc(g); | |
| 1229 | + unsigned long flags; | |
| 1230 | + | |
| 1231 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 1232 | + | |
| 1233 | + __dwc3_gadget_ep_disable(dwc->eps[0]); | |
| 1234 | + __dwc3_gadget_ep_disable(dwc->eps[1]); | |
| 1235 | + | |
| 1236 | + dwc->gadget_driver = NULL; | |
| 1237 | + dwc->gadget.dev.driver = NULL; | |
| 1238 | + | |
| 1239 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1240 | + | |
| 1241 | + return 0; | |
| 1242 | +} | |
| 1243 | +static const struct usb_gadget_ops dwc3_gadget_ops = { | |
| 1244 | + .get_frame = dwc3_gadget_get_frame, | |
| 1245 | + .wakeup = dwc3_gadget_wakeup, | |
| 1246 | + .set_selfpowered = dwc3_gadget_set_selfpowered, | |
| 1247 | + .pullup = dwc3_gadget_pullup, | |
| 1248 | + .udc_start = dwc3_gadget_start, | |
| 1249 | + .udc_stop = dwc3_gadget_stop, | |
| 1250 | +}; | |
| 1251 | + | |
| 1252 | +/* -------------------------------------------------------------------------- */ | |
| 1253 | + | |
| 1254 | +static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc) | |
| 1255 | +{ | |
| 1256 | + struct dwc3_ep *dep; | |
| 1257 | + u8 epnum; | |
| 1258 | + | |
| 1259 | + INIT_LIST_HEAD(&dwc->gadget.ep_list); | |
| 1260 | + | |
| 1261 | + for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | |
| 1262 | + dep = kzalloc(sizeof(*dep), GFP_KERNEL); | |
| 1263 | + if (!dep) { | |
| 1264 | + dev_err(dwc->dev, "can't allocate endpoint %d\n", | |
| 1265 | + epnum); | |
| 1266 | + return -ENOMEM; | |
| 1267 | + } | |
| 1268 | + | |
| 1269 | + dep->dwc = dwc; | |
| 1270 | + dep->number = epnum; | |
| 1271 | + dwc->eps[epnum] = dep; | |
| 1272 | + | |
| 1273 | + snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, | |
| 1274 | + (epnum & 1) ? "in" : "out"); | |
| 1275 | + dep->endpoint.name = dep->name; | |
| 1276 | + dep->direction = (epnum & 1); | |
| 1277 | + | |
| 1278 | + if (epnum == 0 || epnum == 1) { | |
| 1279 | + dep->endpoint.maxpacket = 512; | |
| 1280 | + dep->endpoint.ops = &dwc3_gadget_ep0_ops; | |
| 1281 | + if (!epnum) | |
| 1282 | + dwc->gadget.ep0 = &dep->endpoint; | |
| 1283 | + } else { | |
| 1284 | + int ret; | |
| 1285 | + | |
| 1286 | + dep->endpoint.maxpacket = 1024; | |
| 1287 | + dep->endpoint.ops = &dwc3_gadget_ep_ops; | |
| 1288 | + list_add_tail(&dep->endpoint.ep_list, | |
| 1289 | + &dwc->gadget.ep_list); | |
| 1290 | + | |
| 1291 | + ret = dwc3_alloc_trb_pool(dep); | |
| 1292 | + if (ret) { | |
| 1293 | + dev_err(dwc->dev, "%s: failed to allocate TRB pool\n", dep->name); | |
| 1294 | + return ret; | |
| 1295 | + } | |
| 1296 | + } | |
| 1297 | + INIT_LIST_HEAD(&dep->request_list); | |
| 1298 | + INIT_LIST_HEAD(&dep->req_queued); | |
| 1299 | + } | |
| 1300 | + | |
| 1301 | + return 0; | |
| 1302 | +} | |
| 1303 | + | |
| 1304 | +static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) | |
| 1305 | +{ | |
| 1306 | + struct dwc3_ep *dep; | |
| 1307 | + u8 epnum; | |
| 1308 | + | |
| 1309 | + for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | |
| 1310 | + dep = dwc->eps[epnum]; | |
| 1311 | + dwc3_free_trb_pool(dep); | |
| 1312 | + | |
| 1313 | + if (epnum != 0 && epnum != 1) | |
| 1314 | + list_del(&dep->endpoint.ep_list); | |
| 1315 | + | |
| 1316 | + kfree(dep); | |
| 1317 | + } | |
| 1318 | +} | |
| 1319 | + | |
| 1320 | +static void dwc3_gadget_release(struct device *dev) | |
| 1321 | +{ | |
| 1322 | + dev_dbg(dev, "%s\n", __func__); | |
| 1323 | +} | |
| 1324 | + | |
| 1325 | +/* -------------------------------------------------------------------------- */ | |
| 1326 | +static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, | |
| 1327 | + const struct dwc3_event_depevt *event, int status) | |
| 1328 | +{ | |
| 1329 | + struct dwc3_request *req; | |
| 1330 | + struct dwc3_trb trb; | |
| 1331 | + unsigned int count; | |
| 1332 | + unsigned int s_pkt = 0; | |
| 1333 | + | |
| 1334 | + do { | |
| 1335 | + req = next_request(&dep->req_queued); | |
| 1336 | + if (!req) | |
| 1337 | + break; | |
| 1338 | + | |
| 1339 | + dwc3_trb_to_nat(req->trb, &trb); | |
| 1340 | + | |
| 1341 | + if (trb.hwo && status != -ESHUTDOWN) | |
| 1342 | + /* | |
| 1343 | + * We continue despite the error. There is not much we | |
| 1344 | + * can do. If we don't clean in up we loop for ever. If | |
| 1345 | + * we skip the TRB than it gets overwritten reused after | |
| 1346 | + * a while since we use them in a ring buffer. a BUG() | |
| 1347 | + * would help. Lets hope that if this occures, someone | |
| 1348 | + * fixes the root cause instead of looking away :) | |
| 1349 | + */ | |
| 1350 | + dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", | |
| 1351 | + dep->name, req->trb); | |
| 1352 | + count = trb.length; | |
| 1353 | + | |
| 1354 | + if (dep->direction) { | |
| 1355 | + if (count) { | |
| 1356 | + dev_err(dwc->dev, "incomplete IN transfer %s\n", | |
| 1357 | + dep->name); | |
| 1358 | + status = -ECONNRESET; | |
| 1359 | + } | |
| 1360 | + } else { | |
| 1361 | + if (count && (event->status & DEPEVT_STATUS_SHORT)) | |
| 1362 | + s_pkt = 1; | |
| 1363 | + } | |
| 1364 | + | |
| 1365 | + /* | |
| 1366 | + * We assume here we will always receive the entire data block | |
| 1367 | + * which we should receive. Meaning, if we program RX to | |
| 1368 | + * receive 4K but we receive only 2K, we assume that's all we | |
| 1369 | + * should receive and we simply bounce the request back to the | |
| 1370 | + * gadget driver for further processing. | |
| 1371 | + */ | |
| 1372 | + req->request.actual += req->request.length - count; | |
| 1373 | + dwc3_gadget_giveback(dep, req, status); | |
| 1374 | + if (s_pkt) | |
| 1375 | + break; | |
| 1376 | + if ((event->status & DEPEVT_STATUS_LST) && trb.lst) | |
| 1377 | + break; | |
| 1378 | + if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc) | |
| 1379 | + break; | |
| 1380 | + } while (1); | |
| 1381 | + | |
| 1382 | + if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc) | |
| 1383 | + return 0; | |
| 1384 | + return 1; | |
| 1385 | +} | |
| 1386 | + | |
| 1387 | +static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, | |
| 1388 | + struct dwc3_ep *dep, const struct dwc3_event_depevt *event, | |
| 1389 | + int start_new) | |
| 1390 | +{ | |
| 1391 | + unsigned status = 0; | |
| 1392 | + int clean_busy; | |
| 1393 | + | |
| 1394 | + if (event->status & DEPEVT_STATUS_BUSERR) | |
| 1395 | + status = -ECONNRESET; | |
| 1396 | + | |
| 1397 | + clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); | |
| 1398 | + if (clean_busy) { | |
| 1399 | + dep->flags &= ~DWC3_EP_BUSY; | |
| 1400 | + dep->res_trans_idx = 0; | |
| 1401 | + } | |
| 1402 | +} | |
| 1403 | + | |
| 1404 | +static void dwc3_gadget_start_isoc(struct dwc3 *dwc, | |
| 1405 | + struct dwc3_ep *dep, const struct dwc3_event_depevt *event) | |
| 1406 | +{ | |
| 1407 | + u32 uf; | |
| 1408 | + | |
| 1409 | + if (list_empty(&dep->request_list)) { | |
| 1410 | + dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", | |
| 1411 | + dep->name); | |
| 1412 | + return; | |
| 1413 | + } | |
| 1414 | + | |
| 1415 | + if (event->parameters) { | |
| 1416 | + u32 mask; | |
| 1417 | + | |
| 1418 | + mask = ~(dep->interval - 1); | |
| 1419 | + uf = event->parameters & mask; | |
| 1420 | + /* 4 micro frames in the future */ | |
| 1421 | + uf += dep->interval * 4; | |
| 1422 | + } else { | |
| 1423 | + uf = 0; | |
| 1424 | + } | |
| 1425 | + | |
| 1426 | + __dwc3_gadget_kick_transfer(dep, uf, 1); | |
| 1427 | +} | |
| 1428 | + | |
| 1429 | +static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, | |
| 1430 | + const struct dwc3_event_depevt *event) | |
| 1431 | +{ | |
| 1432 | + struct dwc3 *dwc = dep->dwc; | |
| 1433 | + struct dwc3_event_depevt mod_ev = *event; | |
| 1434 | + | |
| 1435 | + /* | |
| 1436 | + * We were asked to remove one requests. It is possible that this | |
| 1437 | + * request and a few other were started together and have the same | |
| 1438 | + * transfer index. Since we stopped the complete endpoint we don't | |
| 1439 | + * know how many requests were already completed (and not yet) | |
| 1440 | + * reported and how could be done (later). We purge them all until | |
| 1441 | + * the end of the list. | |
| 1442 | + */ | |
| 1443 | + mod_ev.status = DEPEVT_STATUS_LST; | |
| 1444 | + dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); | |
| 1445 | + dep->flags &= ~DWC3_EP_BUSY; | |
| 1446 | + /* pending requets are ignored and are queued on XferNotReady */ | |
| 1447 | +} | |
| 1448 | + | |
| 1449 | +static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, | |
| 1450 | + const struct dwc3_event_depevt *event) | |
| 1451 | +{ | |
| 1452 | + u32 param = event->parameters; | |
| 1453 | + u32 cmd_type = (param >> 8) & ((1 << 5) - 1); | |
| 1454 | + | |
| 1455 | + switch (cmd_type) { | |
| 1456 | + case DWC3_DEPCMD_ENDTRANSFER: | |
| 1457 | + dwc3_process_ep_cmd_complete(dep, event); | |
| 1458 | + break; | |
| 1459 | + case DWC3_DEPCMD_STARTTRANSFER: | |
| 1460 | + dep->res_trans_idx = param & 0x7f; | |
| 1461 | + break; | |
| 1462 | + default: | |
| 1463 | + printk(KERN_ERR "%s() unknown /unexpected type: %d\n", | |
| 1464 | + __func__, cmd_type); | |
| 1465 | + break; | |
| 1466 | + }; | |
| 1467 | +} | |
| 1468 | + | |
| 1469 | +static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |
| 1470 | + const struct dwc3_event_depevt *event) | |
| 1471 | +{ | |
| 1472 | + struct dwc3_ep *dep; | |
| 1473 | + u8 epnum = event->endpoint_number; | |
| 1474 | + | |
| 1475 | + dep = dwc->eps[epnum]; | |
| 1476 | + | |
| 1477 | + dev_vdbg(dwc->dev, "%s: %s\n", dep->name, | |
| 1478 | + dwc3_ep_event_string(event->endpoint_event)); | |
| 1479 | + | |
| 1480 | + if (epnum == 0 || epnum == 1) { | |
| 1481 | + dwc3_ep0_interrupt(dwc, event); | |
| 1482 | + return; | |
| 1483 | + } | |
| 1484 | + | |
| 1485 | + switch (event->endpoint_event) { | |
| 1486 | + case DWC3_DEPEVT_XFERCOMPLETE: | |
| 1487 | + if (usb_endpoint_xfer_isoc(dep->desc)) { | |
| 1488 | + dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", | |
| 1489 | + dep->name); | |
| 1490 | + return; | |
| 1491 | + } | |
| 1492 | + | |
| 1493 | + dwc3_endpoint_transfer_complete(dwc, dep, event, 1); | |
| 1494 | + break; | |
| 1495 | + case DWC3_DEPEVT_XFERINPROGRESS: | |
| 1496 | + if (!usb_endpoint_xfer_isoc(dep->desc)) { | |
| 1497 | + dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", | |
| 1498 | + dep->name); | |
| 1499 | + return; | |
| 1500 | + } | |
| 1501 | + | |
| 1502 | + dwc3_endpoint_transfer_complete(dwc, dep, event, 0); | |
| 1503 | + break; | |
| 1504 | + case DWC3_DEPEVT_XFERNOTREADY: | |
| 1505 | + if (usb_endpoint_xfer_isoc(dep->desc)) { | |
| 1506 | + dwc3_gadget_start_isoc(dwc, dep, event); | |
| 1507 | + } else { | |
| 1508 | + int ret; | |
| 1509 | + | |
| 1510 | + dev_vdbg(dwc->dev, "%s: reason %s\n", | |
| 1511 | + dep->name, event->status | |
| 1512 | + ? "Transfer Active" | |
| 1513 | + : "Transfer Not Active"); | |
| 1514 | + | |
| 1515 | + ret = __dwc3_gadget_kick_transfer(dep, 0, 1); | |
| 1516 | + if (!ret || ret == -EBUSY) | |
| 1517 | + return; | |
| 1518 | + | |
| 1519 | + dev_dbg(dwc->dev, "%s: failed to kick transfers\n", | |
| 1520 | + dep->name); | |
| 1521 | + } | |
| 1522 | + | |
| 1523 | + break; | |
| 1524 | + case DWC3_DEPEVT_STREAMEVT: | |
| 1525 | + if (!usb_endpoint_xfer_bulk(dep->desc)) { | |
| 1526 | + dev_err(dwc->dev, "Stream event for non-Bulk %s\n", | |
| 1527 | + dep->name); | |
| 1528 | + return; | |
| 1529 | + } | |
| 1530 | + | |
| 1531 | + switch (event->status) { | |
| 1532 | + case DEPEVT_STREAMEVT_FOUND: | |
| 1533 | + dev_vdbg(dwc->dev, "Stream %d found and started\n", | |
| 1534 | + event->parameters); | |
| 1535 | + | |
| 1536 | + break; | |
| 1537 | + case DEPEVT_STREAMEVT_NOTFOUND: | |
| 1538 | + /* FALLTHROUGH */ | |
| 1539 | + default: | |
| 1540 | + dev_dbg(dwc->dev, "Couldn't find suitable stream\n"); | |
| 1541 | + } | |
| 1542 | + break; | |
| 1543 | + case DWC3_DEPEVT_RXTXFIFOEVT: | |
| 1544 | + dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); | |
| 1545 | + break; | |
| 1546 | + case DWC3_DEPEVT_EPCMDCMPLT: | |
| 1547 | + dwc3_ep_cmd_compl(dep, event); | |
| 1548 | + break; | |
| 1549 | + } | |
| 1550 | +} | |
| 1551 | + | |
| 1552 | +static void dwc3_disconnect_gadget(struct dwc3 *dwc) | |
| 1553 | +{ | |
| 1554 | + if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { | |
| 1555 | + spin_unlock(&dwc->lock); | |
| 1556 | + dwc->gadget_driver->disconnect(&dwc->gadget); | |
| 1557 | + spin_lock(&dwc->lock); | |
| 1558 | + } | |
| 1559 | +} | |
| 1560 | + | |
| 1561 | +static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) | |
| 1562 | +{ | |
| 1563 | + struct dwc3_ep *dep; | |
| 1564 | + struct dwc3_gadget_ep_cmd_params params; | |
| 1565 | + u32 cmd; | |
| 1566 | + int ret; | |
| 1567 | + | |
| 1568 | + dep = dwc->eps[epnum]; | |
| 1569 | + | |
| 1570 | + WARN_ON(!dep->res_trans_idx); | |
| 1571 | + if (dep->res_trans_idx) { | |
| 1572 | + cmd = DWC3_DEPCMD_ENDTRANSFER; | |
| 1573 | + cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; | |
| 1574 | + cmd |= DWC3_DEPCMD_PARAM(dep->res_trans_idx); | |
| 1575 | + memset(¶ms, 0, sizeof(params)); | |
| 1576 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | |
| 1577 | + WARN_ON_ONCE(ret); | |
| 1578 | + dep->res_trans_idx = 0; | |
| 1579 | + } | |
| 1580 | +} | |
| 1581 | + | |
| 1582 | +static void dwc3_stop_active_transfers(struct dwc3 *dwc) | |
| 1583 | +{ | |
| 1584 | + u32 epnum; | |
| 1585 | + | |
| 1586 | + for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | |
| 1587 | + struct dwc3_ep *dep; | |
| 1588 | + | |
| 1589 | + dep = dwc->eps[epnum]; | |
| 1590 | + if (!(dep->flags & DWC3_EP_ENABLED)) | |
| 1591 | + continue; | |
| 1592 | + | |
| 1593 | + dwc3_remove_requests(dwc, dep); | |
| 1594 | + } | |
| 1595 | +} | |
| 1596 | + | |
| 1597 | +static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) | |
| 1598 | +{ | |
| 1599 | + u32 epnum; | |
| 1600 | + | |
| 1601 | + for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | |
| 1602 | + struct dwc3_ep *dep; | |
| 1603 | + struct dwc3_gadget_ep_cmd_params params; | |
| 1604 | + int ret; | |
| 1605 | + | |
| 1606 | + dep = dwc->eps[epnum]; | |
| 1607 | + | |
| 1608 | + if (!(dep->flags & DWC3_EP_STALL)) | |
| 1609 | + continue; | |
| 1610 | + | |
| 1611 | + dep->flags &= ~DWC3_EP_STALL; | |
| 1612 | + | |
| 1613 | + memset(¶ms, 0, sizeof(params)); | |
| 1614 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | |
| 1615 | + DWC3_DEPCMD_CLEARSTALL, ¶ms); | |
| 1616 | + WARN_ON_ONCE(ret); | |
| 1617 | + } | |
| 1618 | +} | |
| 1619 | + | |
| 1620 | +static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) | |
| 1621 | +{ | |
| 1622 | + dev_vdbg(dwc->dev, "%s\n", __func__); | |
| 1623 | +#if 0 | |
| 1624 | + XXX | |
| 1625 | + U1/U2 is powersave optimization. Skip it for now. Anyway we need to | |
| 1626 | + enable it before we can disable it. | |
| 1627 | + | |
| 1628 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 1629 | + reg &= ~DWC3_DCTL_INITU1ENA; | |
| 1630 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1631 | + | |
| 1632 | + reg &= ~DWC3_DCTL_INITU2ENA; | |
| 1633 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1634 | +#endif | |
| 1635 | + | |
| 1636 | + dwc3_stop_active_transfers(dwc); | |
| 1637 | + dwc3_disconnect_gadget(dwc); | |
| 1638 | + dwc->start_config_issued = false; | |
| 1639 | + | |
| 1640 | + dwc->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1641 | +} | |
| 1642 | + | |
| 1643 | +static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on) | |
| 1644 | +{ | |
| 1645 | + u32 reg; | |
| 1646 | + | |
| 1647 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
| 1648 | + | |
| 1649 | + if (on) | |
| 1650 | + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; | |
| 1651 | + else | |
| 1652 | + reg |= DWC3_GUSB3PIPECTL_SUSPHY; | |
| 1653 | + | |
| 1654 | + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
| 1655 | +} | |
| 1656 | + | |
| 1657 | +static void dwc3_gadget_usb2_phy_power(struct dwc3 *dwc, int on) | |
| 1658 | +{ | |
| 1659 | + u32 reg; | |
| 1660 | + | |
| 1661 | + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
| 1662 | + | |
| 1663 | + if (on) | |
| 1664 | + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | |
| 1665 | + else | |
| 1666 | + reg |= DWC3_GUSB2PHYCFG_SUSPHY; | |
| 1667 | + | |
| 1668 | + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
| 1669 | +} | |
| 1670 | + | |
| 1671 | +static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) | |
| 1672 | +{ | |
| 1673 | + u32 reg; | |
| 1674 | + | |
| 1675 | + dev_vdbg(dwc->dev, "%s\n", __func__); | |
| 1676 | + | |
| 1677 | + /* Enable PHYs */ | |
| 1678 | + dwc3_gadget_usb2_phy_power(dwc, true); | |
| 1679 | + dwc3_gadget_usb3_phy_power(dwc, true); | |
| 1680 | + | |
| 1681 | + if (dwc->gadget.speed != USB_SPEED_UNKNOWN) | |
| 1682 | + dwc3_disconnect_gadget(dwc); | |
| 1683 | + | |
| 1684 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 1685 | + reg &= ~DWC3_DCTL_TSTCTRL_MASK; | |
| 1686 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1687 | + | |
| 1688 | + dwc3_stop_active_transfers(dwc); | |
| 1689 | + dwc3_clear_stall_all_ep(dwc); | |
| 1690 | + dwc->start_config_issued = false; | |
| 1691 | + | |
| 1692 | + /* Reset device address to zero */ | |
| 1693 | + reg = dwc3_readl(dwc->regs, DWC3_DCFG); | |
| 1694 | + reg &= ~(DWC3_DCFG_DEVADDR_MASK); | |
| 1695 | + dwc3_writel(dwc->regs, DWC3_DCFG, reg); | |
| 1696 | +} | |
| 1697 | + | |
| 1698 | +static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) | |
| 1699 | +{ | |
| 1700 | + u32 reg; | |
| 1701 | + u32 usb30_clock = DWC3_GCTL_CLK_BUS; | |
| 1702 | + | |
| 1703 | + /* | |
| 1704 | + * We change the clock only at SS but I dunno why I would want to do | |
| 1705 | + * this. Maybe it becomes part of the power saving plan. | |
| 1706 | + */ | |
| 1707 | + | |
| 1708 | + if (speed != DWC3_DSTS_SUPERSPEED) | |
| 1709 | + return; | |
| 1710 | + | |
| 1711 | + /* | |
| 1712 | + * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed | |
| 1713 | + * each time on Connect Done. | |
| 1714 | + */ | |
| 1715 | + if (!usb30_clock) | |
| 1716 | + return; | |
| 1717 | + | |
| 1718 | + reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
| 1719 | + reg |= DWC3_GCTL_RAMCLKSEL(usb30_clock); | |
| 1720 | + dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
| 1721 | +} | |
| 1722 | + | |
| 1723 | +static void dwc3_gadget_disable_phy(struct dwc3 *dwc, u8 speed) | |
| 1724 | +{ | |
| 1725 | + switch (speed) { | |
| 1726 | + case USB_SPEED_SUPER: | |
| 1727 | + dwc3_gadget_usb2_phy_power(dwc, false); | |
| 1728 | + break; | |
| 1729 | + case USB_SPEED_HIGH: | |
| 1730 | + case USB_SPEED_FULL: | |
| 1731 | + case USB_SPEED_LOW: | |
| 1732 | + dwc3_gadget_usb3_phy_power(dwc, false); | |
| 1733 | + break; | |
| 1734 | + } | |
| 1735 | +} | |
| 1736 | + | |
| 1737 | +static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) | |
| 1738 | +{ | |
| 1739 | + struct dwc3_gadget_ep_cmd_params params; | |
| 1740 | + struct dwc3_ep *dep; | |
| 1741 | + int ret; | |
| 1742 | + u32 reg; | |
| 1743 | + u8 speed; | |
| 1744 | + | |
| 1745 | + dev_vdbg(dwc->dev, "%s\n", __func__); | |
| 1746 | + | |
| 1747 | + memset(¶ms, 0x00, sizeof(params)); | |
| 1748 | + | |
| 1749 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 1750 | + speed = reg & DWC3_DSTS_CONNECTSPD; | |
| 1751 | + dwc->speed = speed; | |
| 1752 | + | |
| 1753 | + dwc3_update_ram_clk_sel(dwc, speed); | |
| 1754 | + | |
| 1755 | + switch (speed) { | |
| 1756 | + case DWC3_DCFG_SUPERSPEED: | |
| 1757 | + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | |
| 1758 | + dwc->gadget.ep0->maxpacket = 512; | |
| 1759 | + dwc->gadget.speed = USB_SPEED_SUPER; | |
| 1760 | + break; | |
| 1761 | + case DWC3_DCFG_HIGHSPEED: | |
| 1762 | + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | |
| 1763 | + dwc->gadget.ep0->maxpacket = 64; | |
| 1764 | + dwc->gadget.speed = USB_SPEED_HIGH; | |
| 1765 | + break; | |
| 1766 | + case DWC3_DCFG_FULLSPEED2: | |
| 1767 | + case DWC3_DCFG_FULLSPEED1: | |
| 1768 | + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | |
| 1769 | + dwc->gadget.ep0->maxpacket = 64; | |
| 1770 | + dwc->gadget.speed = USB_SPEED_FULL; | |
| 1771 | + break; | |
| 1772 | + case DWC3_DCFG_LOWSPEED: | |
| 1773 | + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); | |
| 1774 | + dwc->gadget.ep0->maxpacket = 8; | |
| 1775 | + dwc->gadget.speed = USB_SPEED_LOW; | |
| 1776 | + break; | |
| 1777 | + } | |
| 1778 | + | |
| 1779 | + /* Disable unneded PHY */ | |
| 1780 | + dwc3_gadget_disable_phy(dwc, dwc->gadget.speed); | |
| 1781 | + | |
| 1782 | + dep = dwc->eps[0]; | |
| 1783 | + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc); | |
| 1784 | + if (ret) { | |
| 1785 | + dev_err(dwc->dev, "failed to enable %s\n", dep->name); | |
| 1786 | + return; | |
| 1787 | + } | |
| 1788 | + | |
| 1789 | + dep = dwc->eps[1]; | |
| 1790 | + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc); | |
| 1791 | + if (ret) { | |
| 1792 | + dev_err(dwc->dev, "failed to enable %s\n", dep->name); | |
| 1793 | + return; | |
| 1794 | + } | |
| 1795 | + | |
| 1796 | + /* | |
| 1797 | + * Configure PHY via GUSB3PIPECTLn if required. | |
| 1798 | + * | |
| 1799 | + * Update GTXFIFOSIZn | |
| 1800 | + * | |
| 1801 | + * In both cases reset values should be sufficient. | |
| 1802 | + */ | |
| 1803 | +} | |
| 1804 | + | |
| 1805 | +static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) | |
| 1806 | +{ | |
| 1807 | + dev_vdbg(dwc->dev, "%s\n", __func__); | |
| 1808 | + | |
| 1809 | + /* | |
| 1810 | + * TODO take core out of low power mode when that's | |
| 1811 | + * implemented. | |
| 1812 | + */ | |
| 1813 | + | |
| 1814 | + dwc->gadget_driver->resume(&dwc->gadget); | |
| 1815 | +} | |
| 1816 | + | |
| 1817 | +static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, | |
| 1818 | + unsigned int evtinfo) | |
| 1819 | +{ | |
| 1820 | + /* The fith bit says SuperSpeed yes or no. */ | |
| 1821 | + dwc->link_state = evtinfo & DWC3_LINK_STATE_MASK; | |
| 1822 | + | |
| 1823 | + dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); | |
| 1824 | +} | |
| 1825 | + | |
| 1826 | +static void dwc3_gadget_interrupt(struct dwc3 *dwc, | |
| 1827 | + const struct dwc3_event_devt *event) | |
| 1828 | +{ | |
| 1829 | + switch (event->type) { | |
| 1830 | + case DWC3_DEVICE_EVENT_DISCONNECT: | |
| 1831 | + dwc3_gadget_disconnect_interrupt(dwc); | |
| 1832 | + break; | |
| 1833 | + case DWC3_DEVICE_EVENT_RESET: | |
| 1834 | + dwc3_gadget_reset_interrupt(dwc); | |
| 1835 | + break; | |
| 1836 | + case DWC3_DEVICE_EVENT_CONNECT_DONE: | |
| 1837 | + dwc3_gadget_conndone_interrupt(dwc); | |
| 1838 | + break; | |
| 1839 | + case DWC3_DEVICE_EVENT_WAKEUP: | |
| 1840 | + dwc3_gadget_wakeup_interrupt(dwc); | |
| 1841 | + break; | |
| 1842 | + case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: | |
| 1843 | + dwc3_gadget_linksts_change_interrupt(dwc, event->event_info); | |
| 1844 | + break; | |
| 1845 | + case DWC3_DEVICE_EVENT_EOPF: | |
| 1846 | + dev_vdbg(dwc->dev, "End of Periodic Frame\n"); | |
| 1847 | + break; | |
| 1848 | + case DWC3_DEVICE_EVENT_SOF: | |
| 1849 | + dev_vdbg(dwc->dev, "Start of Periodic Frame\n"); | |
| 1850 | + break; | |
| 1851 | + case DWC3_DEVICE_EVENT_ERRATIC_ERROR: | |
| 1852 | + dev_vdbg(dwc->dev, "Erratic Error\n"); | |
| 1853 | + break; | |
| 1854 | + case DWC3_DEVICE_EVENT_CMD_CMPL: | |
| 1855 | + dev_vdbg(dwc->dev, "Command Complete\n"); | |
| 1856 | + break; | |
| 1857 | + case DWC3_DEVICE_EVENT_OVERFLOW: | |
| 1858 | + dev_vdbg(dwc->dev, "Overflow\n"); | |
| 1859 | + break; | |
| 1860 | + default: | |
| 1861 | + dev_dbg(dwc->dev, "UNKNOWN IRQ %d\n", event->type); | |
| 1862 | + } | |
| 1863 | +} | |
| 1864 | + | |
| 1865 | +static void dwc3_process_event_entry(struct dwc3 *dwc, | |
| 1866 | + const union dwc3_event *event) | |
| 1867 | +{ | |
| 1868 | + /* Endpoint IRQ, handle it and return early */ | |
| 1869 | + if (event->type.is_devspec == 0) { | |
| 1870 | + /* depevt */ | |
| 1871 | + return dwc3_endpoint_interrupt(dwc, &event->depevt); | |
| 1872 | + } | |
| 1873 | + | |
| 1874 | + switch (event->type.type) { | |
| 1875 | + case DWC3_EVENT_TYPE_DEV: | |
| 1876 | + dwc3_gadget_interrupt(dwc, &event->devt); | |
| 1877 | + break; | |
| 1878 | + /* REVISIT what to do with Carkit and I2C events ? */ | |
| 1879 | + default: | |
| 1880 | + dev_err(dwc->dev, "UNKNOWN IRQ type %d\n", event->raw); | |
| 1881 | + } | |
| 1882 | +} | |
| 1883 | + | |
| 1884 | +static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) | |
| 1885 | +{ | |
| 1886 | + struct dwc3_event_buffer *evt; | |
| 1887 | + int left; | |
| 1888 | + u32 count; | |
| 1889 | + | |
| 1890 | + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); | |
| 1891 | + count &= DWC3_GEVNTCOUNT_MASK; | |
| 1892 | + if (!count) | |
| 1893 | + return IRQ_NONE; | |
| 1894 | + | |
| 1895 | + evt = dwc->ev_buffs[buf]; | |
| 1896 | + left = count; | |
| 1897 | + | |
| 1898 | + while (left > 0) { | |
| 1899 | + union dwc3_event event; | |
| 1900 | + | |
| 1901 | + memcpy(&event.raw, (evt->buf + evt->lpos), sizeof(event.raw)); | |
| 1902 | + dwc3_process_event_entry(dwc, &event); | |
| 1903 | + /* | |
| 1904 | + * XXX we wrap around correctly to the next entry as almost all | |
| 1905 | + * entries are 4 bytes in size. There is one entry which has 12 | |
| 1906 | + * bytes which is a regular entry followed by 8 bytes data. ATM | |
| 1907 | + * I don't know how things are organized if were get next to the | |
| 1908 | + * a boundary so I worry about that once we try to handle that. | |
| 1909 | + */ | |
| 1910 | + evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; | |
| 1911 | + left -= 4; | |
| 1912 | + | |
| 1913 | + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); | |
| 1914 | + } | |
| 1915 | + | |
| 1916 | + return IRQ_HANDLED; | |
| 1917 | +} | |
| 1918 | + | |
| 1919 | +static irqreturn_t dwc3_interrupt(int irq, void *_dwc) | |
| 1920 | +{ | |
| 1921 | + struct dwc3 *dwc = _dwc; | |
| 1922 | + int i; | |
| 1923 | + irqreturn_t ret = IRQ_NONE; | |
| 1924 | + | |
| 1925 | + spin_lock(&dwc->lock); | |
| 1926 | + | |
| 1927 | + for (i = 0; i < DWC3_EVENT_BUFFERS_NUM; i++) { | |
| 1928 | + irqreturn_t status; | |
| 1929 | + | |
| 1930 | + status = dwc3_process_event_buf(dwc, i); | |
| 1931 | + if (status == IRQ_HANDLED) | |
| 1932 | + ret = status; | |
| 1933 | + } | |
| 1934 | + | |
| 1935 | + spin_unlock(&dwc->lock); | |
| 1936 | + | |
| 1937 | + return ret; | |
| 1938 | +} | |
| 1939 | + | |
| 1940 | +/** | |
| 1941 | + * dwc3_gadget_init - Initializes gadget related registers | |
| 1942 | + * @dwc: Pointer to out controller context structure | |
| 1943 | + * | |
| 1944 | + * Returns 0 on success otherwise negative errno. | |
| 1945 | + */ | |
| 1946 | +int __devinit dwc3_gadget_init(struct dwc3 *dwc) | |
| 1947 | +{ | |
| 1948 | + u32 reg; | |
| 1949 | + int ret; | |
| 1950 | + int irq; | |
| 1951 | + | |
| 1952 | + dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
| 1953 | + &dwc->ctrl_req_addr, GFP_KERNEL); | |
| 1954 | + if (!dwc->ctrl_req) { | |
| 1955 | + dev_err(dwc->dev, "failed to allocate ctrl request\n"); | |
| 1956 | + ret = -ENOMEM; | |
| 1957 | + goto err0; | |
| 1958 | + } | |
| 1959 | + | |
| 1960 | + dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
| 1961 | + &dwc->ep0_trb_addr, GFP_KERNEL); | |
| 1962 | + if (!dwc->ep0_trb) { | |
| 1963 | + dev_err(dwc->dev, "failed to allocate ep0 trb\n"); | |
| 1964 | + ret = -ENOMEM; | |
| 1965 | + goto err1; | |
| 1966 | + } | |
| 1967 | + | |
| 1968 | + dwc->setup_buf = dma_alloc_coherent(dwc->dev, | |
| 1969 | + sizeof(*dwc->setup_buf) * 2, | |
| 1970 | + &dwc->setup_buf_addr, GFP_KERNEL); | |
| 1971 | + if (!dwc->setup_buf) { | |
| 1972 | + dev_err(dwc->dev, "failed to allocate setup buffer\n"); | |
| 1973 | + ret = -ENOMEM; | |
| 1974 | + goto err2; | |
| 1975 | + } | |
| 1976 | + | |
| 1977 | + dwc->ep0_bounce = dma_alloc_coherent(dwc->dev, | |
| 1978 | + 512, &dwc->ep0_bounce_addr, GFP_KERNEL); | |
| 1979 | + if (!dwc->ep0_bounce) { | |
| 1980 | + dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); | |
| 1981 | + ret = -ENOMEM; | |
| 1982 | + goto err3; | |
| 1983 | + } | |
| 1984 | + | |
| 1985 | + dev_set_name(&dwc->gadget.dev, "gadget"); | |
| 1986 | + | |
| 1987 | + dwc->gadget.ops = &dwc3_gadget_ops; | |
| 1988 | + dwc->gadget.is_dualspeed = true; | |
| 1989 | + dwc->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1990 | + dwc->gadget.dev.parent = dwc->dev; | |
| 1991 | + | |
| 1992 | + dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); | |
| 1993 | + | |
| 1994 | + dwc->gadget.dev.dma_parms = dwc->dev->dma_parms; | |
| 1995 | + dwc->gadget.dev.dma_mask = dwc->dev->dma_mask; | |
| 1996 | + dwc->gadget.dev.release = dwc3_gadget_release; | |
| 1997 | + dwc->gadget.name = "dwc3-gadget"; | |
| 1998 | + | |
| 1999 | + /* | |
| 2000 | + * REVISIT: Here we should clear all pending IRQs to be | |
| 2001 | + * sure we're starting from a well known location. | |
| 2002 | + */ | |
| 2003 | + | |
| 2004 | + ret = dwc3_gadget_init_endpoints(dwc); | |
| 2005 | + if (ret) | |
| 2006 | + goto err4; | |
| 2007 | + | |
| 2008 | + irq = platform_get_irq(to_platform_device(dwc->dev), 0); | |
| 2009 | + | |
| 2010 | + ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, | |
| 2011 | + "dwc3", dwc); | |
| 2012 | + if (ret) { | |
| 2013 | + dev_err(dwc->dev, "failed to request irq #%d --> %d\n", | |
| 2014 | + irq, ret); | |
| 2015 | + goto err5; | |
| 2016 | + } | |
| 2017 | + | |
| 2018 | + /* Enable all but Start and End of Frame IRQs */ | |
| 2019 | + reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | | |
| 2020 | + DWC3_DEVTEN_EVNTOVERFLOWEN | | |
| 2021 | + DWC3_DEVTEN_CMDCMPLTEN | | |
| 2022 | + DWC3_DEVTEN_ERRTICERREN | | |
| 2023 | + DWC3_DEVTEN_WKUPEVTEN | | |
| 2024 | + DWC3_DEVTEN_ULSTCNGEN | | |
| 2025 | + DWC3_DEVTEN_CONNECTDONEEN | | |
| 2026 | + DWC3_DEVTEN_USBRSTEN | | |
| 2027 | + DWC3_DEVTEN_DISCONNEVTEN); | |
| 2028 | + dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); | |
| 2029 | + | |
| 2030 | + ret = device_register(&dwc->gadget.dev); | |
| 2031 | + if (ret) { | |
| 2032 | + dev_err(dwc->dev, "failed to register gadget device\n"); | |
| 2033 | + put_device(&dwc->gadget.dev); | |
| 2034 | + goto err6; | |
| 2035 | + } | |
| 2036 | + | |
| 2037 | + ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); | |
| 2038 | + if (ret) { | |
| 2039 | + dev_err(dwc->dev, "failed to register udc\n"); | |
| 2040 | + goto err7; | |
| 2041 | + } | |
| 2042 | + | |
| 2043 | + return 0; | |
| 2044 | + | |
| 2045 | +err7: | |
| 2046 | + device_unregister(&dwc->gadget.dev); | |
| 2047 | + | |
| 2048 | +err6: | |
| 2049 | + dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); | |
| 2050 | + free_irq(irq, dwc); | |
| 2051 | + | |
| 2052 | +err5: | |
| 2053 | + dwc3_gadget_free_endpoints(dwc); | |
| 2054 | + | |
| 2055 | +err4: | |
| 2056 | + dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, | |
| 2057 | + dwc->ep0_bounce_addr); | |
| 2058 | + | |
| 2059 | +err3: | |
| 2060 | + dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2, | |
| 2061 | + dwc->setup_buf, dwc->setup_buf_addr); | |
| 2062 | + | |
| 2063 | +err2: | |
| 2064 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
| 2065 | + dwc->ep0_trb, dwc->ep0_trb_addr); | |
| 2066 | + | |
| 2067 | +err1: | |
| 2068 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
| 2069 | + dwc->ctrl_req, dwc->ctrl_req_addr); | |
| 2070 | + | |
| 2071 | +err0: | |
| 2072 | + return ret; | |
| 2073 | +} | |
| 2074 | + | |
| 2075 | +void dwc3_gadget_exit(struct dwc3 *dwc) | |
| 2076 | +{ | |
| 2077 | + int irq; | |
| 2078 | + int i; | |
| 2079 | + | |
| 2080 | + usb_del_gadget_udc(&dwc->gadget); | |
| 2081 | + irq = platform_get_irq(to_platform_device(dwc->dev), 0); | |
| 2082 | + | |
| 2083 | + dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); | |
| 2084 | + free_irq(irq, dwc); | |
| 2085 | + | |
| 2086 | + for (i = 0; i < ARRAY_SIZE(dwc->eps); i++) | |
| 2087 | + __dwc3_gadget_ep_disable(dwc->eps[i]); | |
| 2088 | + | |
| 2089 | + dwc3_gadget_free_endpoints(dwc); | |
| 2090 | + | |
| 2091 | + dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, | |
| 2092 | + dwc->ep0_bounce_addr); | |
| 2093 | + | |
| 2094 | + dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2, | |
| 2095 | + dwc->setup_buf, dwc->setup_buf_addr); | |
| 2096 | + | |
| 2097 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
| 2098 | + dwc->ep0_trb, dwc->ep0_trb_addr); | |
| 2099 | + | |
| 2100 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
| 2101 | + dwc->ctrl_req, dwc->ctrl_req_addr); | |
| 2102 | + | |
| 2103 | + device_unregister(&dwc->gadget.dev); | |
| 2104 | +} | |
| @@ -0,0 +1,211 @@ | ||
| 1 | +/** | |
| 2 | + * gadget.h - DesignWare USB3 DRD Gadget Header | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#ifndef __DRIVERS_USB_DWC3_GADGET_H | |
| 40 | +#define __DRIVERS_USB_DWC3_GADGET_H | |
| 41 | + | |
| 42 | +#include <linux/list.h> | |
| 43 | +#include <linux/usb/gadget.h> | |
| 44 | +#include "io.h" | |
| 45 | + | |
| 46 | +struct dwc3; | |
| 47 | +#define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint)) | |
| 48 | +#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) | |
| 49 | + | |
| 50 | +/* DEPCFG parameter 1 */ | |
| 51 | +#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0) | |
| 52 | +#define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) | |
| 53 | +#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) | |
| 54 | +#define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) | |
| 55 | +#define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) | |
| 56 | +#define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) | |
| 57 | +#define DWC3_DEPCFG_BINTERVAL_M1(n) ((n) << 16) | |
| 58 | +#define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) | |
| 59 | +#define DWC3_DEPCFG_EP_NUMBER(n) ((n) << 25) | |
| 60 | +#define DWC3_DEPCFG_BULK_BASED (1 << 30) | |
| 61 | +#define DWC3_DEPCFG_FIFO_BASED (1 << 31) | |
| 62 | + | |
| 63 | +/* DEPCFG parameter 0 */ | |
| 64 | +#define DWC3_DEPCFG_EP_TYPE(n) ((n) << 1) | |
| 65 | +#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) ((n) << 3) | |
| 66 | +#define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) | |
| 67 | +#define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) | |
| 68 | +#define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) | |
| 69 | +#define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) | |
| 70 | + | |
| 71 | +/* DEPXFERCFG parameter 0 */ | |
| 72 | +#define DWC3_DEPXFERCFG_NUM_XFER_RES(n) ((n) & 0xffff) | |
| 73 | + | |
| 74 | +struct dwc3_gadget_ep_cmd_params { | |
| 75 | + u32 param2; | |
| 76 | + u32 param1; | |
| 77 | + u32 param0; | |
| 78 | +}; | |
| 79 | + | |
| 80 | +/* -------------------------------------------------------------------------- */ | |
| 81 | + | |
| 82 | +struct dwc3_request { | |
| 83 | + struct usb_request request; | |
| 84 | + struct list_head list; | |
| 85 | + struct dwc3_ep *dep; | |
| 86 | + | |
| 87 | + u8 epnum; | |
| 88 | + struct dwc3_trb_hw *trb; | |
| 89 | + dma_addr_t trb_dma; | |
| 90 | + | |
| 91 | + unsigned direction:1; | |
| 92 | + unsigned mapped:1; | |
| 93 | + unsigned queued:1; | |
| 94 | +}; | |
| 95 | +#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request)) | |
| 96 | + | |
| 97 | +static inline struct dwc3_request *next_request(struct list_head *list) | |
| 98 | +{ | |
| 99 | + if (list_empty(list)) | |
| 100 | + return NULL; | |
| 101 | + | |
| 102 | + return list_first_entry(list, struct dwc3_request, list); | |
| 103 | +} | |
| 104 | + | |
| 105 | +static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) | |
| 106 | +{ | |
| 107 | + struct dwc3_ep *dep = req->dep; | |
| 108 | + | |
| 109 | + req->queued = true; | |
| 110 | + list_move_tail(&req->list, &dep->req_queued); | |
| 111 | +} | |
| 112 | + | |
| 113 | +#if defined(CONFIG_USB_GADGET_DWC3) || defined(CONFIG_USB_GADGET_DWC3_MODULE) | |
| 114 | +int dwc3_gadget_init(struct dwc3 *dwc); | |
| 115 | +void dwc3_gadget_exit(struct dwc3 *dwc); | |
| 116 | +#else | |
| 117 | +static inline int dwc3_gadget_init(struct dwc3 *dwc) { return 0; } | |
| 118 | +static inline void dwc3_gadget_exit(struct dwc3 *dwc) { } | |
| 119 | +static inline int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, | |
| 120 | + unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) | |
| 121 | +{ | |
| 122 | + return 0; | |
| 123 | +} | |
| 124 | +#endif | |
| 125 | + | |
| 126 | +void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |
| 127 | + int status); | |
| 128 | + | |
| 129 | +void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event); | |
| 130 | +void dwc3_ep0_out_start(struct dwc3 *dwc); | |
| 131 | +int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, | |
| 132 | + gfp_t gfp_flags); | |
| 133 | +int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); | |
| 134 | +int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, | |
| 135 | + unsigned cmd, struct dwc3_gadget_ep_cmd_params *params); | |
| 136 | +void dwc3_map_buffer_to_dma(struct dwc3_request *req); | |
| 137 | +void dwc3_unmap_buffer_from_dma(struct dwc3_request *req); | |
| 138 | + | |
| 139 | +/** | |
| 140 | + * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW | |
| 141 | + * @dwc: DesignWare USB3 Pointer | |
| 142 | + * @number: DWC endpoint number | |
| 143 | + * | |
| 144 | + * Caller should take care of locking | |
| 145 | + */ | |
| 146 | +static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3 *dwc, u8 number) | |
| 147 | +{ | |
| 148 | + u32 res_id; | |
| 149 | + | |
| 150 | + res_id = dwc3_readl(dwc->regs, DWC3_DEPCMD(number)); | |
| 151 | + | |
| 152 | + return DWC3_DEPCMD_GET_RSC_IDX(res_id); | |
| 153 | +} | |
| 154 | + | |
| 155 | +/** | |
| 156 | + * dwc3_gadget_event_string - returns event name | |
| 157 | + * @event: the event code | |
| 158 | + */ | |
| 159 | +static inline const char *dwc3_gadget_event_string(u8 event) | |
| 160 | +{ | |
| 161 | + switch (event) { | |
| 162 | + case DWC3_DEVICE_EVENT_DISCONNECT: | |
| 163 | + return "Disconnect"; | |
| 164 | + case DWC3_DEVICE_EVENT_RESET: | |
| 165 | + return "Reset"; | |
| 166 | + case DWC3_DEVICE_EVENT_CONNECT_DONE: | |
| 167 | + return "Connection Done"; | |
| 168 | + case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: | |
| 169 | + return "Link Status Change"; | |
| 170 | + case DWC3_DEVICE_EVENT_WAKEUP: | |
| 171 | + return "WakeUp"; | |
| 172 | + case DWC3_DEVICE_EVENT_EOPF: | |
| 173 | + return "End-Of-Frame"; | |
| 174 | + case DWC3_DEVICE_EVENT_SOF: | |
| 175 | + return "Start-Of-Frame"; | |
| 176 | + case DWC3_DEVICE_EVENT_ERRATIC_ERROR: | |
| 177 | + return "Erratic Error"; | |
| 178 | + case DWC3_DEVICE_EVENT_CMD_CMPL: | |
| 179 | + return "Command Complete"; | |
| 180 | + case DWC3_DEVICE_EVENT_OVERFLOW: | |
| 181 | + return "Overflow"; | |
| 182 | + } | |
| 183 | + | |
| 184 | + return "UNKNOWN"; | |
| 185 | +} | |
| 186 | + | |
| 187 | +/** | |
| 188 | + * dwc3_ep_event_string - returns event name | |
| 189 | + * @event: then event code | |
| 190 | + */ | |
| 191 | +static inline const char *dwc3_ep_event_string(u8 event) | |
| 192 | +{ | |
| 193 | + switch (event) { | |
| 194 | + case DWC3_DEPEVT_XFERCOMPLETE: | |
| 195 | + return "Transfer Complete"; | |
| 196 | + case DWC3_DEPEVT_XFERINPROGRESS: | |
| 197 | + return "Transfer In-Progress"; | |
| 198 | + case DWC3_DEPEVT_XFERNOTREADY: | |
| 199 | + return "Transfer Not Ready"; | |
| 200 | + case DWC3_DEPEVT_RXTXFIFOEVT: | |
| 201 | + return "FIFO"; | |
| 202 | + case DWC3_DEPEVT_STREAMEVT: | |
| 203 | + return "Stream"; | |
| 204 | + case DWC3_DEPEVT_EPCMDCMPLT: | |
| 205 | + return "Endpoint Command Complete"; | |
| 206 | + } | |
| 207 | + | |
| 208 | + return "UNKNOWN"; | |
| 209 | +} | |
| 210 | + | |
| 211 | +#endif /* __DRIVERS_USB_DWC3_GADGET_H */ | |
| @@ -0,0 +1,54 @@ | ||
| 1 | +/** | |
| 2 | + * io.h - DesignWare USB3 DRD IO Header | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | |
| 5 | + * | |
| 6 | + * Authors: Felipe Balbi <balbi@ti.com>, | |
| 7 | + * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
| 8 | + * | |
| 9 | + * Redistribution and use in source and binary forms, with or without | |
| 10 | + * modification, are permitted provided that the following conditions | |
| 11 | + * are met: | |
| 12 | + * 1. Redistributions of source code must retain the above copyright | |
| 13 | + * notice, this list of conditions, and the following disclaimer, | |
| 14 | + * without modification. | |
| 15 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | + * notice, this list of conditions and the following disclaimer in the | |
| 17 | + * documentation and/or other materials provided with the distribution. | |
| 18 | + * 3. The names of the above-listed copyright holders may not be used | |
| 19 | + * to endorse or promote products derived from this software without | |
| 20 | + * specific prior written permission. | |
| 21 | + * | |
| 22 | + * ALTERNATIVELY, this software may be distributed under the terms of the | |
| 23 | + * GNU General Public License ("GPL") version 2, as published by the Free | |
| 24 | + * Software Foundation. | |
| 25 | + * | |
| 26 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| 27 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 28 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 29 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 30 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 31 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 32 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 33 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 34 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 35 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 36 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#ifndef __DRIVERS_USB_DWC3_IO_H | |
| 40 | +#define __DRIVERS_USB_DWC3_IO_H | |
| 41 | + | |
| 42 | +#include <asm/io.h> | |
| 43 | + | |
| 44 | +static inline u32 dwc3_readl(void __iomem *base, u32 offset) | |
| 45 | +{ | |
| 46 | + return readl(base + offset); | |
| 47 | +} | |
| 48 | + | |
| 49 | +static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) | |
| 50 | +{ | |
| 51 | + writel(value, base + offset); | |
| 52 | +} | |
| 53 | + | |
| 54 | +#endif /* __DRIVERS_USB_DWC3_IO_H */ | |
| @@ -96,6 +96,22 @@ config USB_GADGET_VBUS_DRAW · 95 unmodified lines | ||
| 96 | 96 | This value will be used except for system-specific gadget |
| 97 | 97 | drivers that have more specific information. |
| 98 | 98 | |
| 99 | +config USB_GADGET_STORAGE_NUM_BUFFERS | |
| 100 | + int "Number of storage pipeline buffers" | |
| 101 | + range 2 4 | |
| 102 | + default 2 | |
| 103 | + help | |
| 104 | + Usually 2 buffers are enough to establish a good buffering | |
| 105 | + pipeline. The number may be increased in order to compensate | |
| 106 | + for a bursty VFS behaviour. For instance there may be CPU wake up | |
| 107 | + latencies that makes the VFS to appear bursty in a system with | |
| 108 | + an CPU on-demand governor. Especially if DMA is doing IO to | |
| 109 | + offload the CPU. In this case the CPU will go into power | |
| 110 | + save often and spin up occasionally to move data within VFS. | |
| 111 | + If selecting USB_GADGET_DEBUG_FILES this value may be set by | |
| 112 | + a module parameter as well. | |
| 113 | + If unsure, say 2. | |
| 114 | + | |
| 99 | 115 | # |
| 100 | 116 | # USB Peripheral Controller Support |
| 101 | 117 | # |
| @@ -255,12 +271,11 @@ config USB_S3C_HSOTG · 153 unmodified lines | ||
| 255 | 271 | integrated into the S3C64XX series SoC. |
| 256 | 272 | |
| 257 | 273 | config USB_IMX |
| 258 | − tristate "Freescale IMX USB Peripheral Controller" | |
| 259 | − depends on ARCH_MX1 | |
| 274 | + tristate "Freescale i.MX1 USB Peripheral Controller" | |
| 275 | + depends on ARCH_MXC | |
| 260 | 276 | help |
| 261 | − Freescale's IMX series include an integrated full speed | |
| 262 | − USB 1.1 device controller. The controller in the IMX series | |
| 263 | − is register-compatible. | |
| 277 | + Freescale's i.MX1 includes an integrated full speed | |
| 278 | + USB 1.1 device controller. | |
| 264 | 279 | |
| 265 | 280 | It has Six fixed-function endpoints, as well as endpoint |
| 266 | 281 | zero (for control transfers). |
| @@ -303,6 +318,18 @@ config USB_PXA_U2O · 36 unmodified lines | ||
| 303 | 318 | PXA9xx Processor series include a high speed USB2.0 device |
| 304 | 319 | controller, which support high speed and full speed USB peripheral. |
| 305 | 320 | |
| 321 | +config USB_GADGET_DWC3 | |
| 322 | + tristate "DesignWare USB3.0 (DRD) Controller" | |
| 323 | + depends on USB_DWC3 | |
| 324 | + select USB_GADGET_DUALSPEED | |
| 325 | + select USB_GADGET_SUPERSPEED | |
| 326 | + help | |
| 327 | + DesignWare USB3.0 controller is a SuperSpeed USB3.0 Controller | |
| 328 | + which can be configured for peripheral-only, host-only, hub-only | |
| 329 | + and Dual-Role operation. This Controller was first integrated into | |
| 330 | + the OMAP5 series of processors. More information about the OMAP5 | |
| 331 | + version of this controller, refer to http://www.ti.com/omap5. | |
| 332 | + | |
| 306 | 333 | # |
| 307 | 334 | # Controllers available in both integrated and discrete versions |
| 308 | 335 | # |
| @@ -846,6 +873,16 @@ config USB_G_NOKIA · 537 unmodified lines | ||
| 846 | 873 | It's only really useful for N900 hardware. If you're building |
| 847 | 874 | a kernel for N900, say Y or M here. If unsure, say N. |
| 848 | 875 | |
| 876 | +config USB_G_ACM_MS | |
| 877 | + tristate "CDC Composite Device (ACM and mass storage)" | |
| 878 | + depends on BLOCK | |
| 879 | + help | |
| 880 | + This driver provides two functions in one configuration: | |
| 881 | + a mass storage, and a CDC ACM (serial port) link. | |
| 882 | + | |
| 883 | + Say "y" to link the driver statically, or "m" to build a | |
| 884 | + dynamically linked module called "g_acm_ms". | |
| 885 | + | |
| 849 | 886 | config USB_G_MULTI |
| 850 | 887 | tristate "Multifunction Composite Gadget (EXPERIMENTAL)" |
| 851 | 888 | depends on BLOCK && NET |
| @@ -28,7 +28,7 @@ obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o · 27 unmodified lines | ||
| 28 | 28 | obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o |
| 29 | 29 | obj-$(CONFIG_USB_EG20T) += pch_udc.o |
| 30 | 30 | obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o |
| 31 | −mv_udc-y := mv_udc_core.o mv_udc_phy.o | |
| 31 | +mv_udc-y := mv_udc_core.o | |
| 32 | 32 | obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o |
| 33 | 33 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o |
| 34 | 34 | |
| @@ -51,6 +51,7 @@ g_dbgp-y := dbgp.o · 16 unmodified lines | ||
| 51 | 51 | g_nokia-y := nokia.o |
| 52 | 52 | g_webcam-y := webcam.o |
| 53 | 53 | g_ncm-y := ncm.o |
| 54 | +g_acm_ms-y := acm_ms.o | |
| 54 | 55 | |
| 55 | 56 | obj-$(CONFIG_USB_ZERO) += g_zero.o |
| 56 | 57 | obj-$(CONFIG_USB_AUDIO) += g_audio.o |
| @@ -69,3 +70,4 @@ obj-$(CONFIG_USB_G_MULTI) += g_multi.o · 12 unmodified lines | ||
| 69 | 70 | obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o |
| 70 | 71 | obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o |
| 71 | 72 | obj-$(CONFIG_USB_G_NCM) += g_ncm.o |
| 73 | +obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o | |
| @@ -0,0 +1,256 @@ | ||
| 1 | +/* | |
| 2 | + * acm_ms.c -- Composite driver, with ACM and mass storage support | |
| 3 | + * | |
| 4 | + * Copyright (C) 2008 David Brownell | |
| 5 | + * Copyright (C) 2008 Nokia Corporation | |
| 6 | + * Author: David Brownell | |
| 7 | + * Modified: Klaus Schwarzkopf <schwarzkopf@sensortherm.de> | |
| 8 | + * | |
| 9 | + * Heavily based on multi.c and cdc2.c | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; either version 2 of the License, or | |
| 14 | + * (at your option) any later version. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#include <linux/kernel.h> | |
| 18 | +#include <linux/utsname.h> | |
| 19 | + | |
| 20 | +#include "u_serial.h" | |
| 21 | + | |
| 22 | +#define DRIVER_DESC "Composite Gadget (ACM + MS)" | |
| 23 | +#define DRIVER_VERSION "2011/10/10" | |
| 24 | + | |
| 25 | +/*-------------------------------------------------------------------------*/ | |
| 26 | + | |
| 27 | +/* | |
| 28 | + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | |
| 29 | + * Instead: allocate your own, using normal USB-IF procedures. | |
| 30 | + */ | |
| 31 | +#define ACM_MS_VENDOR_NUM 0x1d6b /* Linux Foundation */ | |
| 32 | +#define ACM_MS_PRODUCT_NUM 0x0106 /* Composite Gadget: ACM + MS*/ | |
| 33 | + | |
| 34 | +/*-------------------------------------------------------------------------*/ | |
| 35 | + | |
| 36 | +/* | |
| 37 | + * Kbuild is not very cooperative with respect to linking separately | |
| 38 | + * compiled library objects into one module. So for now we won't use | |
| 39 | + * separate compilation ... ensuring init/exit sections work to shrink | |
| 40 | + * the runtime footprint, and giving us at least some parts of what | |
| 41 | + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | |
| 42 | + */ | |
| 43 | + | |
| 44 | +#include "composite.c" | |
| 45 | +#include "usbstring.c" | |
| 46 | +#include "config.c" | |
| 47 | +#include "epautoconf.c" | |
| 48 | +#include "u_serial.c" | |
| 49 | +#include "f_acm.c" | |
| 50 | +#include "f_mass_storage.c" | |
| 51 | + | |
| 52 | +/*-------------------------------------------------------------------------*/ | |
| 53 | + | |
| 54 | +static struct usb_device_descriptor device_desc = { | |
| 55 | + .bLength = sizeof device_desc, | |
| 56 | + .bDescriptorType = USB_DT_DEVICE, | |
| 57 | + | |
| 58 | + .bcdUSB = cpu_to_le16(0x0200), | |
| 59 | + | |
| 60 | + .bDeviceClass = USB_CLASS_MISC /* 0xEF */, | |
| 61 | + .bDeviceSubClass = 2, | |
| 62 | + .bDeviceProtocol = 1, | |
| 63 | + | |
| 64 | + /* .bMaxPacketSize0 = f(hardware) */ | |
| 65 | + | |
| 66 | + /* Vendor and product id can be overridden by module parameters. */ | |
| 67 | + .idVendor = cpu_to_le16(ACM_MS_VENDOR_NUM), | |
| 68 | + .idProduct = cpu_to_le16(ACM_MS_PRODUCT_NUM), | |
| 69 | + /* .bcdDevice = f(hardware) */ | |
| 70 | + /* .iManufacturer = DYNAMIC */ | |
| 71 | + /* .iProduct = DYNAMIC */ | |
| 72 | + /* NO SERIAL NUMBER */ | |
| 73 | + /*.bNumConfigurations = DYNAMIC*/ | |
| 74 | +}; | |
| 75 | + | |
| 76 | +static struct usb_otg_descriptor otg_descriptor = { | |
| 77 | + .bLength = sizeof otg_descriptor, | |
| 78 | + .bDescriptorType = USB_DT_OTG, | |
| 79 | + | |
| 80 | + /* | |
| 81 | + * REVISIT SRP-only hardware is possible, although | |
| 82 | + * it would not be called "OTG" ... | |
| 83 | + */ | |
| 84 | + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, | |
| 85 | +}; | |
| 86 | + | |
| 87 | +static const struct usb_descriptor_header *otg_desc[] = { | |
| 88 | + (struct usb_descriptor_header *) &otg_descriptor, | |
| 89 | + NULL, | |
| 90 | +}; | |
| 91 | + | |
| 92 | + | |
| 93 | +/* string IDs are assigned dynamically */ | |
| 94 | + | |
| 95 | +#define STRING_MANUFACTURER_IDX 0 | |
| 96 | +#define STRING_PRODUCT_IDX 1 | |
| 97 | + | |
| 98 | +static char manufacturer[50]; | |
| 99 | + | |
| 100 | +static struct usb_string strings_dev[] = { | |
| 101 | + [STRING_MANUFACTURER_IDX].s = manufacturer, | |
| 102 | + [STRING_PRODUCT_IDX].s = DRIVER_DESC, | |
| 103 | + { } /* end of list */ | |
| 104 | +}; | |
| 105 | + | |
| 106 | +static struct usb_gadget_strings stringtab_dev = { | |
| 107 | + .language = 0x0409, /* en-us */ | |
| 108 | + .strings = strings_dev, | |
| 109 | +}; | |
| 110 | + | |
| 111 | +static struct usb_gadget_strings *dev_strings[] = { | |
| 112 | + &stringtab_dev, | |
| 113 | + NULL, | |
| 114 | +}; | |
| 115 | + | |
| 116 | +/****************************** Configurations ******************************/ | |
| 117 | + | |
| 118 | +static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; | |
| 119 | +FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); | |
| 120 | + | |
| 121 | +static struct fsg_common fsg_common; | |
| 122 | + | |
| 123 | +/*-------------------------------------------------------------------------*/ | |
| 124 | + | |
| 125 | +/* | |
| 126 | + * We _always_ have both ACM and mass storage functions. | |
| 127 | + */ | |
| 128 | +static int __init acm_ms_do_config(struct usb_configuration *c) | |
| 129 | +{ | |
| 130 | + int status; | |
| 131 | + | |
| 132 | + if (gadget_is_otg(c->cdev->gadget)) { | |
| 133 | + c->descriptors = otg_desc; | |
| 134 | + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | |
| 135 | + } | |
| 136 | + | |
| 137 | + | |
| 138 | + status = acm_bind_config(c, 0); | |
| 139 | + if (status < 0) | |
| 140 | + return status; | |
| 141 | + | |
| 142 | + status = fsg_bind_config(c->cdev, c, &fsg_common); | |
| 143 | + if (status < 0) | |
| 144 | + return status; | |
| 145 | + | |
| 146 | + return 0; | |
| 147 | +} | |
| 148 | + | |
| 149 | +static struct usb_configuration acm_ms_config_driver = { | |
| 150 | + .label = DRIVER_DESC, | |
| 151 | + .bConfigurationValue = 1, | |
| 152 | + /* .iConfiguration = DYNAMIC */ | |
| 153 | + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | |
| 154 | +}; | |
| 155 | + | |
| 156 | +/*-------------------------------------------------------------------------*/ | |
| 157 | + | |
| 158 | +static int __init acm_ms_bind(struct usb_composite_dev *cdev) | |
| 159 | +{ | |
| 160 | + int gcnum; | |
| 161 | + struct usb_gadget *gadget = cdev->gadget; | |
| 162 | + int status; | |
| 163 | + void *retp; | |
| 164 | + | |
| 165 | + /* set up serial link layer */ | |
| 166 | + status = gserial_setup(cdev->gadget, 1); | |
| 167 | + if (status < 0) | |
| 168 | + return status; | |
| 169 | + | |
| 170 | + /* set up mass storage function */ | |
| 171 | + retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); | |
| 172 | + if (IS_ERR(retp)) { | |
| 173 | + status = PTR_ERR(retp); | |
| 174 | + goto fail0; | |
| 175 | + } | |
| 176 | + | |
| 177 | + /* set bcdDevice */ | |
| 178 | + gcnum = usb_gadget_controller_number(gadget); | |
| 179 | + if (gcnum >= 0) { | |
| 180 | + device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); | |
| 181 | + } else { | |
| 182 | + WARNING(cdev, "controller '%s' not recognized; trying %s\n", | |
| 183 | + gadget->name, | |
| 184 | + acm_ms_config_driver.label); | |
| 185 | + device_desc.bcdDevice = | |
| 186 | + cpu_to_le16(0x0300 | 0x0099); | |
| 187 | + } | |
| 188 | + | |
| 189 | + /* | |
| 190 | + * Allocate string descriptor numbers ... note that string | |
| 191 | + * contents can be overridden by the composite_dev glue. | |
| 192 | + */ | |
| 193 | + | |
| 194 | + /* device descriptor strings: manufacturer, product */ | |
| 195 | + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", | |
| 196 | + init_utsname()->sysname, init_utsname()->release, | |
| 197 | + gadget->name); | |
| 198 | + status = usb_string_id(cdev); | |
| 199 | + if (status < 0) | |
| 200 | + goto fail1; | |
| 201 | + strings_dev[STRING_MANUFACTURER_IDX].id = status; | |
| 202 | + device_desc.iManufacturer = status; | |
| 203 | + | |
| 204 | + status = usb_string_id(cdev); | |
| 205 | + if (status < 0) | |
| 206 | + goto fail1; | |
| 207 | + strings_dev[STRING_PRODUCT_IDX].id = status; | |
| 208 | + device_desc.iProduct = status; | |
| 209 | + | |
| 210 | + /* register our configuration */ | |
| 211 | + status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); | |
| 212 | + if (status < 0) | |
| 213 | + goto fail1; | |
| 214 | + | |
| 215 | + dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", | |
| 216 | + DRIVER_DESC); | |
| 217 | + fsg_common_put(&fsg_common); | |
| 218 | + return 0; | |
| 219 | + | |
| 220 | + /* error recovery */ | |
| 221 | +fail1: | |
| 222 | + fsg_common_put(&fsg_common); | |
| 223 | +fail0: | |
| 224 | + gserial_cleanup(); | |
| 225 | + return status; | |
| 226 | +} | |
| 227 | + | |
| 228 | +static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) | |
| 229 | +{ | |
| 230 | + gserial_cleanup(); | |
| 231 | + | |
| 232 | + return 0; | |
| 233 | +} | |
| 234 | + | |
| 235 | +static struct usb_composite_driver acm_ms_driver = { | |
| 236 | + .name = "g_acm_ms", | |
| 237 | + .dev = &device_desc, | |
| 238 | + .strings = dev_strings, | |
| 239 | + .unbind = __exit_p(acm_ms_unbind), | |
| 240 | +}; | |
| 241 | + | |
| 242 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
| 243 | +MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>"); | |
| 244 | +MODULE_LICENSE("GPL v2"); | |
| 245 | + | |
| 246 | +static int __init init(void) | |
| 247 | +{ | |
| 248 | + return usb_composite_probe(&acm_ms_driver, acm_ms_bind); | |
| 249 | +} | |
| 250 | +module_init(init); | |
| 251 | + | |
| 252 | +static void __exit cleanup(void) | |
| 253 | +{ | |
| 254 | + usb_composite_unregister(&acm_ms_driver); | |
| 255 | +} | |
| 256 | +module_exit(cleanup); | |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | /* |
| @@ -354,7 +345,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) · 331 unmodified lines | ||
| 354 | 345 | writel(tmp, &dev->ep[ep->num].regs->ctl); |
| 355 | 346 | |
| 356 | 347 | /* set max packet size */ |
| 357 | − maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 348 | + maxpacket = usb_endpoint_maxp(desc); | |
| 358 | 349 | tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt); |
| 359 | 350 | tmp = AMD_ADDBITS(tmp, maxpacket, UDC_EP_MAX_PKT_SIZE); |
| 360 | 351 | ep->ep.maxpacket = maxpacket; |
| @@ -3014,13 +3005,8 @@ __acquires(dev->lock) · 2653 unmodified lines | ||
| 3014 | 3005 | |
| 3015 | 3006 | /* link up all endpoints */ |
| 3016 | 3007 | udc_setup_endpoints(dev); |
| 3017 | − if (dev->gadget.speed == USB_SPEED_HIGH) { | |
| 3018 | − dev_info(&dev->pdev->dev, "Connect: speed = %s\n", | |
| 3019 | − "high"); | |
| 3020 | − } else if (dev->gadget.speed == USB_SPEED_FULL) { | |
| 3021 | − dev_info(&dev->pdev->dev, "Connect: speed = %s\n", | |
| 3022 | − "full"); | |
| 3023 | − } | |
| 3008 | + dev_info(&dev->pdev->dev, "Connect: %s\n", | |
| 3009 | + usb_speed_string(dev->gadget.speed)); | |
| 3024 | 3010 | |
| 3025 | 3011 | /* init ep 0 */ |
| 3026 | 3012 | activate_control_endpoints(dev); |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | #ifndef AMD5536UDC_H |
| @@ -9,16 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the | |
| 20 | − * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 21 | − * Boston, MA 02111-1307, USA. | |
| 22 | 12 | */ |
| 23 | 13 | |
| 24 | 14 | #undef VERBOSE_DEBUG |
| @@ -460,7 +450,7 @@ static void nuke(struct at91_ep *ep, int status) · 435 unmodified lines | ||
| 460 | 450 | { |
| 461 | 451 | struct at91_request *req; |
| 462 | 452 | |
| 463 | − // terminer chaque requete dans la queue | |
| 453 | + /* terminate any request in the queue */ | |
| 464 | 454 | ep->stopped = 1; |
| 465 | 455 | if (list_empty(&ep->queue)) |
| 466 | 456 | return; |
| @@ -487,7 +477,7 @@ static int at91_ep_enable(struct usb_ep *_ep, · 20 unmodified lines | ||
| 487 | 477 | || !desc || ep->desc |
| 488 | 478 | || _ep->name == ep0name |
| 489 | 479 | || desc->bDescriptorType != USB_DT_ENDPOINT |
| 490 | − || (maxpacket = le16_to_cpu(desc->wMaxPacketSize)) == 0 | |
| 480 | + || (maxpacket = usb_endpoint_maxp(desc)) == 0 | |
| 491 | 481 | || maxpacket > ep->maxpacket) { |
| 492 | 482 | DBG("bad ep or descriptor\n"); |
| 493 | 483 | return -EINVAL; |
| @@ -788,7 +778,7 @@ static const struct usb_ep_ops at91_ep_ops = { · 294 unmodified lines | ||
| 788 | 778 | .queue = at91_ep_queue, |
| 789 | 779 | .dequeue = at91_ep_dequeue, |
| 790 | 780 | .set_halt = at91_ep_set_halt, |
| 791 | − // there's only imprecise fifo status reporting | |
| 781 | + /* there's only imprecise fifo status reporting */ | |
| 792 | 782 | }; |
| 793 | 783 | |
| 794 | 784 | /*-------------------------------------------------------------------------*/ |
| @@ -846,7 +836,7 @@ static void udc_reinit(struct at91_udc *udc) · 51 unmodified lines | ||
| 846 | 836 | ep->fifo_bank = 0; |
| 847 | 837 | ep->ep.maxpacket = ep->maxpacket; |
| 848 | 838 | ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i); |
| 849 | − // initialiser une queue par endpoint | |
| 839 | + /* initialize one queue per endpoint */ | |
| 850 | 840 | INIT_LIST_HEAD(&ep->queue); |
| 851 | 841 | } |
| 852 | 842 | } |
| @@ -952,7 +942,7 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active) · 99 unmodified lines | ||
| 952 | 942 | struct at91_udc *udc = to_udc(gadget); |
| 953 | 943 | unsigned long flags; |
| 954 | 944 | |
| 955 | − // VDBG("vbus %s\n", is_active ? "on" : "off"); | |
| 945 | + /* VDBG("vbus %s\n", is_active ? "on" : "off"); */ | |
| 956 | 946 | spin_lock_irqsave(&udc->lock, flags); |
| 957 | 947 | udc->vbus = (is_active != 0); |
| 958 | 948 | if (udc->driver) |
| @@ -1003,7 +993,7 @@ static const struct usb_gadget_ops at91_udc_ops = { · 44 unmodified lines | ||
| 1003 | 993 | * VBUS-powered devices may also also want to support bigger |
| 1004 | 994 | * power budgets after an appropriate SET_CONFIGURATION. |
| 1005 | 995 | */ |
| 1006 | − // .vbus_power = at91_vbus_power, | |
| 996 | + /* .vbus_power = at91_vbus_power, */ | |
| 1007 | 997 | }; |
| 1008 | 998 | |
| 1009 | 999 | /*-------------------------------------------------------------------------*/ |
| @@ -1072,7 +1062,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) · 62 unmodified lines | ||
| 1072 | 1062 | ep->is_in = 0; |
| 1073 | 1063 | } |
| 1074 | 1064 | } else { |
| 1075 | − // REVISIT this happens sometimes under load; why?? | |
| 1065 | + /* REVISIT this happens sometimes under load; why?? */ | |
| 1076 | 1066 | ERR("SETUP len %d, csr %08x\n", rxcount, csr); |
| 1077 | 1067 | status = -EINVAL; |
| 1078 | 1068 | } |
| @@ -1451,7 +1441,7 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc) · 372 unmodified lines | ||
| 1451 | 1441 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP); |
| 1452 | 1442 | at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM); |
| 1453 | 1443 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP); |
| 1454 | − // VDBG("bus suspend\n"); | |
| 1444 | + /* VDBG("bus suspend\n"); */ | |
| 1455 | 1445 | if (udc->suspended) |
| 1456 | 1446 | continue; |
| 1457 | 1447 | udc->suspended = 1; |
| @@ -1473,7 +1463,7 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc) · 15 unmodified lines | ||
| 1473 | 1463 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); |
| 1474 | 1464 | at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP); |
| 1475 | 1465 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); |
| 1476 | − // VDBG("bus resume\n"); | |
| 1466 | + /* VDBG("bus resume\n"); */ | |
| 1477 | 1467 | if (!udc->suspended) |
| 1478 | 1468 | continue; |
| 1479 | 1469 | udc->suspended = 0; |
| @@ -1820,7 +1810,7 @@ static int __init at91udc_probe(struct platform_device *pdev) · 340 unmodified lines | ||
| 1820 | 1810 | /* request UDC and maybe VBUS irqs */ |
| 1821 | 1811 | udc->udp_irq = platform_get_irq(pdev, 0); |
| 1822 | 1812 | retval = request_irq(udc->udp_irq, at91_udc_irq, |
| 1823 | − IRQF_DISABLED, driver_name, udc); | |
| 1813 | + 0, driver_name, udc); | |
| 1824 | 1814 | if (retval < 0) { |
| 1825 | 1815 | DBG("request irq %d failed\n", udc->udp_irq); |
| 1826 | 1816 | goto fail1; |
| @@ -1848,7 +1838,7 @@ static int __init at91udc_probe(struct platform_device *pdev) · 21 unmodified lines | ||
| 1848 | 1838 | jiffies + VBUS_POLL_TIMEOUT); |
| 1849 | 1839 | } else { |
| 1850 | 1840 | if (request_irq(udc->board.vbus_pin, at91_vbus_irq, |
| 1851 | − IRQF_DISABLED, driver_name, udc)) { | |
| 1841 | + 0, driver_name, udc)) { | |
| 1852 | 1842 | DBG("request vbus irq %d failed\n", |
| 1853 | 1843 | udc->board.vbus_pin); |
| 1854 | 1844 | retval = -EBUSY; |
| @@ -7,16 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | 9 | * (at your option) any later version. |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; if not, write to the | |
| 18 | − * Free Software Foundation, Inc., | |
| 19 | − * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 20 | 10 | */ |
| 21 | 11 | |
| 22 | 12 | #ifndef AT91_UDC_H |
| @@ -527,7 +527,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) · 526 unmodified lines | ||
| 527 | 527 | |
| 528 | 528 | DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); |
| 529 | 529 | |
| 530 | − maxpacket = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; | |
| 530 | + maxpacket = usb_endpoint_maxp(desc) & 0x7ff; | |
| 531 | 531 | |
| 532 | 532 | if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index) |
| 533 | 533 | || ep->index == 0 |
| @@ -571,7 +571,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) · 37 unmodified lines | ||
| 571 | 571 | * Bits 11:12 specify number of _additional_ |
| 572 | 572 | * transactions per microframe. |
| 573 | 573 | */ |
| 574 | − nr_trans = ((le16_to_cpu(desc->wMaxPacketSize) >> 11) & 3) + 1; | |
| 574 | + nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1; | |
| 575 | 575 | if (nr_trans > 3) |
| 576 | 576 | return -EINVAL; |
| 577 | 577 | |
| @@ -1718,13 +1718,12 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) · 1140 unmodified lines | ||
| 1718 | 1718 | spin_lock(&udc->lock); |
| 1719 | 1719 | } |
| 1720 | 1720 | |
| 1721 | − if (status & USBA_HIGH_SPEED) { | |
| 1722 | − DBG(DBG_BUS, "High-speed bus reset detected\n"); | |
| 1721 | + if (status & USBA_HIGH_SPEED) | |
| 1723 | 1722 | udc->gadget.speed = USB_SPEED_HIGH; |
| 1724 | − } else { | |
| 1725 | − DBG(DBG_BUS, "Full-speed bus reset detected\n"); | |
| 1723 | + else | |
| 1726 | 1724 | udc->gadget.speed = USB_SPEED_FULL; |
| 1727 | − } | |
| 1725 | + DBG(DBG_BUS, "%s bus reset detected\n", | |
| 1726 | + usb_speed_string(udc->gadget.speed)); | |
| 1728 | 1727 | |
| 1729 | 1728 | ep0 = &usba_ep[0]; |
| 1730 | 1729 | ep0->desc = &usba_ep0_desc; |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | #include <linux/kernel.h> |
| @@ -3,17 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | − * | |
| 7 | − * This program is distributed in the hope that it will be useful, | |
| 8 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 9 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 10 | − * GNU General Public License for more details. | |
| 11 | − * | |
| 12 | − * You should have received a copy of the GNU General Public License | |
| 13 | − * along with this program; if not, write to the Free Software | |
| 14 | − * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 15 | − * 02110-1301, USA. | |
| 16 | − * | |
| 17 | 6 | */ |
| 18 | 7 | |
| 19 | 8 | #include <linux/module.h> |
| @@ -2101,7 +2101,7 @@ static int ep_enable(struct usb_ep *ep, · 2100 unmodified lines | ||
| 2101 | 2101 | mEp->num = usb_endpoint_num(desc); |
| 2102 | 2102 | mEp->type = usb_endpoint_type(desc); |
| 2103 | 2103 | |
| 2104 | − mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); | |
| 2104 | + mEp->ep.maxpacket = usb_endpoint_maxp(desc); | |
| 2105 | 2105 | |
| 2106 | 2106 | dbg_event(_usb_addr(mEp), "ENABLE", 0); |
| 2107 | 2107 | |
| @@ -7,15 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | 9 | * (at your option) any later version. |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; if not, write to the Free Software | |
| 18 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | 10 | */ |
| 20 | 11 | |
| 21 | 12 | /* #define VERBOSE_DEBUG */ |
| @@ -164,7 +155,7 @@ int config_ep_by_speed(struct usb_gadget *g, · 142 unmodified lines | ||
| 164 | 155 | |
| 165 | 156 | ep_found: |
| 166 | 157 | /* commit results */ |
| 167 | − _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize); | |
| 158 | + _ep->maxpacket = usb_endpoint_maxp(chosen_desc); | |
| 168 | 159 | _ep->desc = chosen_desc; |
| 169 | 160 | _ep->comp_desc = NULL; |
| 170 | 161 | _ep->maxburst = 0; |
| @@ -551,9 +542,9 @@ static int bos_desc(struct usb_composite_dev *cdev) · 380 unmodified lines | ||
| 551 | 542 | if (cdev->gadget->ops->get_config_params) |
| 552 | 543 | cdev->gadget->ops->get_config_params(&dcd_config_params); |
| 553 | 544 | else { |
| 554 | − dcd_config_params.bU1devExitLat = USB_DEFULT_U1_DEV_EXIT_LAT; | |
| 545 | + dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT; | |
| 555 | 546 | dcd_config_params.bU2DevExitLat = |
| 556 | − cpu_to_le16(USB_DEFULT_U2_DEV_EXIT_LAT); | |
| 547 | + cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); | |
| 557 | 548 | } |
| 558 | 549 | ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; |
| 559 | 550 | ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; |
| @@ -626,25 +617,9 @@ static int set_config(struct usb_composite_dev *cdev, · 66 unmodified lines | ||
| 626 | 617 | result = 0; |
| 627 | 618 | } |
| 628 | 619 | |
| 629 | − INFO(cdev, "%s speed config #%d: %s\n", | |
| 630 | − ({ char *speed; | |
| 631 | − switch (gadget->speed) { | |
| 632 | − case USB_SPEED_LOW: | |
| 633 | − speed = "low"; | |
| 634 | − break; | |
| 635 | − case USB_SPEED_FULL: | |
| 636 | − speed = "full"; | |
| 637 | − break; | |
| 638 | − case USB_SPEED_HIGH: | |
| 639 | − speed = "high"; | |
| 640 | − break; | |
| 641 | − case USB_SPEED_SUPER: | |
| 642 | − speed = "super"; | |
| 643 | − break; | |
| 644 | − default: | |
| 645 | − speed = "?"; | |
| 646 | − break; | |
| 647 | − } ; speed; }), number, c ? c->label : "unconfigured"); | |
| 620 | + INFO(cdev, "%s config #%d: %s\n", | |
| 621 | + usb_speed_string(gadget->speed), | |
| 622 | + number, c ? c->label : "unconfigured"); | |
| 648 | 623 | |
| 649 | 624 | if (!c) |
| 650 | 625 | goto done; |
| @@ -7,15 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | 9 | * (at your option) any later version. |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; if not, write to the Free Software | |
| 18 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | 10 | */ |
| 20 | 11 | |
| 21 | 12 | #include <linux/errno.h> |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | * Copyright (C) 2010 Stephane Duverger |
| 5 | 5 | * |
| 6 | 6 | * Released under the GPLv2. |
| 7 | − * | |
| 8 | 7 | */ |
| 9 | 8 | |
| 10 | 9 | /* verbose messages */ |
| @@ -10,15 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | 13 | */ |
| 23 | 14 | |
| 24 | 15 | |
| @@ -439,7 +430,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) · 414 unmodified lines | ||
| 439 | 430 | * maximum packet size. |
| 440 | 431 | * For SS devices the wMaxPacketSize is limited by 1024. |
| 441 | 432 | */ |
| 442 | − max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; | |
| 433 | + max = usb_endpoint_maxp(desc) & 0x7ff; | |
| 443 | 434 | |
| 444 | 435 | /* drivers must not request bad settings, since lower levels |
| 445 | 436 | * (hardware or its drivers) may not check. some endpoints |
| @@ -1277,7 +1268,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) · 831 unmodified lines | ||
| 1277 | 1268 | int tmp; |
| 1278 | 1269 | |
| 1279 | 1270 | /* high bandwidth mode */ |
| 1280 | − tmp = le16_to_cpu(ep->desc->wMaxPacketSize); | |
| 1271 | + tmp = usb_endpoint_maxp(ep->desc); | |
| 1281 | 1272 | tmp = (tmp >> 11) & 0x03; |
| 1282 | 1273 | tmp *= 8 /* applies to entire frame */; |
| 1283 | 1274 | limit += limit * tmp; |
| @@ -7,16 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | 9 | * (at your option) any later version. |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; if not, write to the Free Software | |
| 18 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | − * | |
| 20 | 10 | */ |
| 21 | 11 | |
| 22 | 12 | #include <linux/kernel.h> |
| @@ -158,7 +148,7 @@ ep_matches ( · 135 unmodified lines | ||
| 158 | 148 | * where it's an output parameter representing the full speed limit. |
| 159 | 149 | * the usb spec fixes high speed bulk maxpacket at 512 bytes. |
| 160 | 150 | */ |
| 161 | − max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); | |
| 151 | + max = 0x7ff & usb_endpoint_maxp(desc); | |
| 162 | 152 | switch (type) { |
| 163 | 153 | case USB_ENDPOINT_XFER_INT: |
| 164 | 154 | /* INT: limit 64 bytes full speed, 1024 high/super speed */ |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | /* #define VERBOSE_DEBUG */ |
| @@ -460,7 +460,7 @@ static int audio_set_endpoint_req(struct usb_function *f, · 459 unmodified lines | ||
| 460 | 460 | |
| 461 | 461 | switch (ctrl->bRequest) { |
| 462 | 462 | case UAC_SET_CUR: |
| 463 | − value = 0; | |
| 463 | + value = len; | |
| 464 | 464 | break; |
| 465 | 465 | |
| 466 | 466 | case UAC_SET_MIN: |
| @@ -499,7 +499,7 @@ static int audio_get_endpoint_req(struct usb_function *f, · 32 unmodified lines | ||
| 499 | 499 | case UAC_GET_MIN: |
| 500 | 500 | case UAC_GET_MAX: |
| 501 | 501 | case UAC_GET_RES: |
| 502 | − value = 3; | |
| 502 | + value = len; | |
| 503 | 503 | break; |
| 504 | 504 | case UAC_GET_MEM: |
| 505 | 505 | break; |
| @@ -681,17 +681,18 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) · 175 unmodified lines | ||
| 681 | 681 | |
| 682 | 682 | status = -ENOMEM; |
| 683 | 683 | |
| 684 | − /* supcard all relevant hardware speeds... we expect that when | |
| 684 | + /* copy descriptors, and track endpoint copies */ | |
| 685 | + f->descriptors = usb_copy_descriptors(f_audio_desc); | |
| 686 | + | |
| 687 | + /* | |
| 688 | + * support all relevant hardware speeds... we expect that when | |
| 685 | 689 | * hardware is dual speed, all bulk-capable endpoints work at |
| 686 | 690 | * both speeds |
| 687 | 691 | */ |
| 688 | − | |
| 689 | − /* copy descriptors, and track endpoint copies */ | |
| 690 | 692 | if (gadget_is_dualspeed(c->cdev->gadget)) { |
| 691 | 693 | c->highspeed = true; |
| 692 | 694 | f->hs_descriptors = usb_copy_descriptors(f_audio_desc); |
| 693 | − } else | |
| 694 | − f->descriptors = usb_copy_descriptors(f_audio_desc); | |
| 695 | + } | |
| 695 | 696 | |
| 696 | 697 | return 0; |
| 697 | 698 | |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | /* #define VERBOSE_DEBUG */ |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | #include <linux/kernel.h> |
| @@ -12,15 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| 13 | 13 | * the Free Software Foundation; either version 2 of the License, or |
| 14 | 14 | * (at your option) any later version. |
| 15 | − * | |
| 16 | − * This program is distributed in the hope that it will be useful, | |
| 17 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | − * GNU General Public License for more details. | |
| 20 | − * | |
| 21 | − * You should have received a copy of the GNU General Public License | |
| 22 | − * along with this program; if not, write to the Free Software | |
| 23 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 24 | 15 | */ |
| 25 | 16 | |
| 26 | 17 | |
| @@ -7,15 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | 9 | * (at your option) any later version. |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; if not, write to the Free Software | |
| 18 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | 10 | */ |
| 20 | 11 | |
| 21 | 12 | #include <linux/kernel.h> |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | /* #define VERBOSE_DEBUG */ |
| @@ -112,8 +112,7 @@ · 111 unmodified lines | ||
| 112 | 112 | * is not loaded (an empty string as "filename" in the fsg_config |
| 113 | 113 | * structure causes error). The CD-ROM emulation includes a single |
| 114 | 114 | * data track and no audio tracks; hence there need be only one |
| 115 | − * backing file per LUN. Note also that the CD-ROM block length is | |
| 116 | − * set to 512 rather than the more common value 2048. | |
| 115 | + * backing file per LUN. | |
| 117 | 116 | * |
| 118 | 117 | * |
| 119 | 118 | * MSF includes support for module parameters. If gadget using it |
| @@ -363,7 +362,7 @@ struct fsg_common { · 243 unmodified lines | ||
| 363 | 362 | |
| 364 | 363 | struct fsg_buffhd *next_buffhd_to_fill; |
| 365 | 364 | struct fsg_buffhd *next_buffhd_to_drain; |
| 366 | − struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; | |
| 365 | + struct fsg_buffhd *buffhds; | |
| 367 | 366 | |
| 368 | 367 | int cmnd_size; |
| 369 | 368 | u8 cmnd[MAX_COMMAND_SIZE]; |
| @@ -745,7 +744,6 @@ static int do_read(struct fsg_common *common) · 375 unmodified lines | ||
| 745 | 744 | u32 amount_left; |
| 746 | 745 | loff_t file_offset, file_offset_tmp; |
| 747 | 746 | unsigned int amount; |
| 748 | − unsigned int partial_page; | |
| 749 | 747 | ssize_t nread; |
| 750 | 748 | |
| 751 | 749 | /* |
| @@ -771,7 +769,7 @@ static int do_read(struct fsg_common *common) · 19 unmodified lines | ||
| 771 | 769 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 772 | 770 | return -EINVAL; |
| 773 | 771 | } |
| 774 | − file_offset = ((loff_t) lba) << 9; | |
| 772 | + file_offset = ((loff_t) lba) << curlun->blkbits; | |
| 775 | 773 | |
| 776 | 774 | /* Carry out the file reads */ |
| 777 | 775 | amount_left = common->data_size_from_cmnd; |
| @@ -784,18 +782,10 @@ static int do_read(struct fsg_common *common) · 6 unmodified lines | ||
| 784 | 782 | * Try to read the remaining amount. |
| 785 | 783 | * But don't read more than the buffer size. |
| 786 | 784 | * And don't try to read past the end of the file. |
| 787 | − * Finally, if we're not at a page boundary, don't read past | |
| 788 | − * the next page. | |
| 789 | − * If this means reading 0 then we were asked to read past | |
| 790 | − * the end of file. | |
| 791 | 785 | */ |
| 792 | 786 | amount = min(amount_left, FSG_BUFLEN); |
| 793 | 787 | amount = min((loff_t)amount, |
| 794 | 788 | curlun->file_length - file_offset); |
| 795 | − partial_page = file_offset & (PAGE_CACHE_SIZE - 1); | |
| 796 | − if (partial_page > 0) | |
| 797 | − amount = min(amount, (unsigned int)PAGE_CACHE_SIZE - | |
| 798 | − partial_page); | |
| 799 | 789 | |
| 800 | 790 | /* Wait for the next buffer to become available */ |
| 801 | 791 | bh = common->next_buffhd_to_fill; |
| @@ -812,7 +802,8 @@ static int do_read(struct fsg_common *common) · 10 unmodified lines | ||
| 812 | 802 | if (amount == 0) { |
| 813 | 803 | curlun->sense_data = |
| 814 | 804 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 815 | − curlun->sense_data_info = file_offset >> 9; | |
| 805 | + curlun->sense_data_info = | |
| 806 | + file_offset >> curlun->blkbits; | |
| 816 | 807 | curlun->info_valid = 1; |
| 817 | 808 | bh->inreq->length = 0; |
| 818 | 809 | bh->state = BUF_STATE_FULL; |
| @@ -835,18 +826,25 @@ static int do_read(struct fsg_common *common) · 16 unmodified lines | ||
| 835 | 826 | } else if (nread < amount) { |
| 836 | 827 | LDBG(curlun, "partial file read: %d/%u\n", |
| 837 | 828 | (int)nread, amount); |
| 838 | − nread -= (nread & 511); /* Round down to a block */ | |
| 829 | + nread = round_down(nread, curlun->blksize); | |
| 839 | 830 | } |
| 840 | 831 | file_offset += nread; |
| 841 | 832 | amount_left -= nread; |
| 842 | 833 | common->residue -= nread; |
| 834 | + | |
| 835 | + /* | |
| 836 | + * Except at the end of the transfer, nread will be | |
| 837 | + * equal to the buffer size, which is divisible by the | |
| 838 | + * bulk-in maxpacket size. | |
| 839 | + */ | |
| 843 | 840 | bh->inreq->length = nread; |
| 844 | 841 | bh->state = BUF_STATE_FULL; |
| 845 | 842 | |
| 846 | 843 | /* If an error occurred, report it and its position */ |
| 847 | 844 | if (nread < amount) { |
| 848 | 845 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
| 849 | − curlun->sense_data_info = file_offset >> 9; | |
| 846 | + curlun->sense_data_info = | |
| 847 | + file_offset >> curlun->blkbits; | |
| 850 | 848 | curlun->info_valid = 1; |
| 851 | 849 | break; |
| 852 | 850 | } |
| @@ -877,7 +875,6 @@ static int do_write(struct fsg_common *common) · 24 unmodified lines | ||
| 877 | 875 | u32 amount_left_to_req, amount_left_to_write; |
| 878 | 876 | loff_t usb_offset, file_offset, file_offset_tmp; |
| 879 | 877 | unsigned int amount; |
| 880 | − unsigned int partial_page; | |
| 881 | 878 | ssize_t nwritten; |
| 882 | 879 | int rc; |
| 883 | 880 | |
| @@ -921,7 +918,7 @@ static int do_write(struct fsg_common *common) · 37 unmodified lines | ||
| 921 | 918 | |
| 922 | 919 | /* Carry out the file writes */ |
| 923 | 920 | get_some_more = 1; |
| 924 | − file_offset = usb_offset = ((loff_t) lba) << 9; | |
| 921 | + file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; | |
| 925 | 922 | amount_left_to_req = common->data_size_from_cmnd; |
| 926 | 923 | amount_left_to_write = common->data_size_from_cmnd; |
| 927 | 924 | |
| @@ -933,41 +930,21 @@ static int do_write(struct fsg_common *common) · 5 unmodified lines | ||
| 933 | 930 | |
| 934 | 931 | /* |
| 935 | 932 | * Figure out how much we want to get: |
| 936 | − * Try to get the remaining amount. | |
| 937 | − * But don't get more than the buffer size. | |
| 938 | − * And don't try to go past the end of the file. | |
| 939 | − * If we're not at a page boundary, | |
| 940 | − * don't go past the next page. | |
| 941 | − * If this means getting 0, then we were asked | |
| 942 | − * to write past the end of file. | |
| 943 | − * Finally, round down to a block boundary. | |
| 933 | + * Try to get the remaining amount, | |
| 934 | + * but not more than the buffer size. | |
| 944 | 935 | */ |
| 945 | 936 | amount = min(amount_left_to_req, FSG_BUFLEN); |
| 946 | − amount = min((loff_t)amount, | |
| 947 | − curlun->file_length - usb_offset); | |
| 948 | − partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); | |
| 949 | − if (partial_page > 0) | |
| 950 | − amount = min(amount, | |
| 951 | − (unsigned int)PAGE_CACHE_SIZE - partial_page); | |
| 952 | − | |
| 953 | − if (amount == 0) { | |
| 937 | + | |
| 938 | + /* Beyond the end of the backing file? */ | |
| 939 | + if (usb_offset >= curlun->file_length) { | |
| 954 | 940 | get_some_more = 0; |
| 955 | 941 | curlun->sense_data = |
| 956 | 942 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 957 | − curlun->sense_data_info = usb_offset >> 9; | |
| 943 | + curlun->sense_data_info = | |
| 944 | + usb_offset >> curlun->blkbits; | |
| 958 | 945 | curlun->info_valid = 1; |
| 959 | 946 | continue; |
| 960 | 947 | } |
| 961 | − amount -= amount & 511; | |
| 962 | − if (amount == 0) { | |
| 963 | − | |
| 964 | − /* | |
| 965 | − * Why were we were asked to transfer a | |
| 966 | − * partial block? | |
| 967 | − */ | |
| 968 | − get_some_more = 0; | |
| 969 | − continue; | |
| 970 | − } | |
| 971 | 948 | |
| 972 | 949 | /* Get the next buffer */ |
| 973 | 950 | usb_offset += amount; |
| @@ -977,12 +954,11 @@ static int do_write(struct fsg_common *common) · 3 unmodified lines | ||
| 977 | 954 | get_some_more = 0; |
| 978 | 955 | |
| 979 | 956 | /* |
| 980 | − * amount is always divisible by 512, hence by | |
| 981 | − * the bulk-out maxpacket size | |
| 957 | + * Except at the end of the transfer, amount will be | |
| 958 | + * equal to the buffer size, which is divisible by | |
| 959 | + * the bulk-out maxpacket size. | |
| 982 | 960 | */ |
| 983 | − bh->outreq->length = amount; | |
| 984 | − bh->bulk_out_intended_length = amount; | |
| 985 | − bh->outreq->short_not_ok = 1; | |
| 961 | + set_bulk_out_req_length(common, bh, amount); | |
| 986 | 962 | if (!start_out_transfer(common, bh)) |
| 987 | 963 | /* Dunno what to do if common->fsg is NULL */ |
| 988 | 964 | return -EIO; |
| @@ -1002,7 +978,8 @@ static int do_write(struct fsg_common *common) · 13 unmodified lines | ||
| 1002 | 978 | /* Did something go wrong with the transfer? */ |
| 1003 | 979 | if (bh->outreq->status != 0) { |
| 1004 | 980 | curlun->sense_data = SS_COMMUNICATION_FAILURE; |
| 1005 | − curlun->sense_data_info = file_offset >> 9; | |
| 981 | + curlun->sense_data_info = | |
| 982 | + file_offset >> curlun->blkbits; | |
| 1006 | 983 | curlun->info_valid = 1; |
| 1007 | 984 | break; |
| 1008 | 985 | } |
| @@ -1016,6 +993,16 @@ static int do_write(struct fsg_common *common) · 7 unmodified lines | ||
| 1016 | 993 | amount = curlun->file_length - file_offset; |
| 1017 | 994 | } |
| 1018 | 995 | |
| 996 | + /* Don't accept excess data. The spec doesn't say | |
| 997 | + * what to do in this case. We'll ignore the error. | |
| 998 | + */ | |
| 999 | + amount = min(amount, bh->bulk_out_intended_length); | |
| 1000 | + | |
| 1001 | + /* Don't write a partial block */ | |
| 1002 | + amount = round_down(amount, curlun->blksize); | |
| 1003 | + if (amount == 0) | |
| 1004 | + goto empty_write; | |
| 1005 | + | |
| 1019 | 1006 | /* Perform the write */ |
| 1020 | 1007 | file_offset_tmp = file_offset; |
| 1021 | 1008 | nwritten = vfs_write(curlun->filp, |
| @@ -1033,8 +1020,7 @@ static int do_write(struct fsg_common *common) · 11 unmodified lines | ||
| 1033 | 1020 | } else if (nwritten < amount) { |
| 1034 | 1021 | LDBG(curlun, "partial file write: %d/%u\n", |
| 1035 | 1022 | (int)nwritten, amount); |
| 1036 | − nwritten -= (nwritten & 511); | |
| 1037 | − /* Round down to a block */ | |
| 1023 | + nwritten = round_down(nwritten, curlun->blksize); | |
| 1038 | 1024 | } |
| 1039 | 1025 | file_offset += nwritten; |
| 1040 | 1026 | amount_left_to_write -= nwritten; |
| @@ -1043,13 +1029,15 @@ static int do_write(struct fsg_common *common) · 2 unmodified lines | ||
| 1043 | 1029 | /* If an error occurred, report it and its position */ |
| 1044 | 1030 | if (nwritten < amount) { |
| 1045 | 1031 | curlun->sense_data = SS_WRITE_ERROR; |
| 1046 | − curlun->sense_data_info = file_offset >> 9; | |
| 1032 | + curlun->sense_data_info = | |
| 1033 | + file_offset >> curlun->blkbits; | |
| 1047 | 1034 | curlun->info_valid = 1; |
| 1048 | 1035 | break; |
| 1049 | 1036 | } |
| 1050 | 1037 | |
| 1038 | + empty_write: | |
| 1051 | 1039 | /* Did the host decide to stop early? */ |
| 1052 | − if (bh->outreq->actual != bh->outreq->length) { | |
| 1040 | + if (bh->outreq->actual < bh->bulk_out_intended_length) { | |
| 1053 | 1041 | common->short_packet_received = 1; |
| 1054 | 1042 | break; |
| 1055 | 1043 | } |
| @@ -1129,8 +1117,8 @@ static int do_verify(struct fsg_common *common) · 73 unmodified lines | ||
| 1129 | 1117 | return -EIO; /* No default reply */ |
| 1130 | 1118 | |
| 1131 | 1119 | /* Prepare to carry out the file verify */ |
| 1132 | − amount_left = verification_length << 9; | |
| 1133 | − file_offset = ((loff_t) lba) << 9; | |
| 1120 | + amount_left = verification_length << curlun->blkbits; | |
| 1121 | + file_offset = ((loff_t) lba) << curlun->blkbits; | |
| 1134 | 1122 | |
| 1135 | 1123 | /* Write out all the dirty buffers before invalidating them */ |
| 1136 | 1124 | fsg_lun_fsync_sub(curlun); |
| @@ -1148,8 +1136,6 @@ static int do_verify(struct fsg_common *common) · 11 unmodified lines | ||
| 1148 | 1136 | * Try to read the remaining amount, but not more than |
| 1149 | 1137 | * the buffer size. |
| 1150 | 1138 | * And don't try to read past the end of the file. |
| 1151 | − * If this means reading 0 then we were asked to read | |
| 1152 | − * past the end of file. | |
| 1153 | 1139 | */ |
| 1154 | 1140 | amount = min(amount_left, FSG_BUFLEN); |
| 1155 | 1141 | amount = min((loff_t)amount, |
| @@ -1157,7 +1143,8 @@ static int do_verify(struct fsg_common *common) · 1 unmodified line | ||
| 1157 | 1143 | if (amount == 0) { |
| 1158 | 1144 | curlun->sense_data = |
| 1159 | 1145 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 1160 | − curlun->sense_data_info = file_offset >> 9; | |
| 1146 | + curlun->sense_data_info = | |
| 1147 | + file_offset >> curlun->blkbits; | |
| 1161 | 1148 | curlun->info_valid = 1; |
| 1162 | 1149 | break; |
| 1163 | 1150 | } |
| @@ -1179,11 +1166,12 @@ static int do_verify(struct fsg_common *common) · 15 unmodified lines | ||
| 1179 | 1166 | } else if (nread < amount) { |
| 1180 | 1167 | LDBG(curlun, "partial file verify: %d/%u\n", |
| 1181 | 1168 | (int)nread, amount); |
| 1182 | − nread -= nread & 511; /* Round down to a sector */ | |
| 1169 | + nread = round_down(nread, curlun->blksize); | |
| 1183 | 1170 | } |
| 1184 | 1171 | if (nread == 0) { |
| 1185 | 1172 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
| 1186 | − curlun->sense_data_info = file_offset >> 9; | |
| 1173 | + curlun->sense_data_info = | |
| 1174 | + file_offset >> curlun->blkbits; | |
| 1187 | 1175 | curlun->info_valid = 1; |
| 1188 | 1176 | break; |
| 1189 | 1177 | } |
| @@ -1289,7 +1277,7 @@ static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) · 99 unmodified lines | ||
| 1289 | 1277 | |
| 1290 | 1278 | put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); |
| 1291 | 1279 | /* Max logical block */ |
| 1292 | − put_unaligned_be32(512, &buf[4]); /* Block length */ | |
| 1280 | + put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */ | |
| 1293 | 1281 | return 8; |
| 1294 | 1282 | } |
| 1295 | 1283 | |
| @@ -1527,7 +1515,7 @@ static int do_read_format_capacities(struct fsg_common *common, · 231 unmodified lines | ||
| 1527 | 1515 | |
| 1528 | 1516 | put_unaligned_be32(curlun->num_sectors, &buf[0]); |
| 1529 | 1517 | /* Number of blocks */ |
| 1530 | − put_unaligned_be32(512, &buf[4]); /* Block length */ | |
| 1518 | + put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */ | |
| 1531 | 1519 | buf[4] = 0x02; /* Current capacity */ |
| 1532 | 1520 | return 12; |
| 1533 | 1521 | } |
| @@ -1607,7 +1595,7 @@ static int throw_away_data(struct fsg_common *common) · 73 unmodified lines | ||
| 1607 | 1595 | common->next_buffhd_to_drain = bh->next; |
| 1608 | 1596 | |
| 1609 | 1597 | /* A short packet or an error ends everything */ |
| 1610 | − if (bh->outreq->actual != bh->outreq->length || | |
| 1598 | + if (bh->outreq->actual < bh->bulk_out_intended_length || | |
| 1611 | 1599 | bh->outreq->status != 0) { |
| 1612 | 1600 | raise_exception(common, |
| 1613 | 1601 | FSG_STATE_ABORT_BULK_OUT); |
| @@ -1623,12 +1611,11 @@ static int throw_away_data(struct fsg_common *common) · 9 unmodified lines | ||
| 1623 | 1611 | amount = min(common->usb_amount_left, FSG_BUFLEN); |
| 1624 | 1612 | |
| 1625 | 1613 | /* |
| 1626 | − * amount is always divisible by 512, hence by | |
| 1614 | + * Except at the end of the transfer, amount will be | |
| 1615 | + * equal to the buffer size, which is divisible by | |
| 1627 | 1616 | * the bulk-out maxpacket size. |
| 1628 | 1617 | */ |
| 1629 | − bh->outreq->length = amount; | |
| 1630 | − bh->bulk_out_intended_length = amount; | |
| 1631 | − bh->outreq->short_not_ok = 1; | |
| 1618 | + set_bulk_out_req_length(common, bh, amount); | |
| 1632 | 1619 | if (!start_out_transfer(common, bh)) |
| 1633 | 1620 | /* Dunno what to do if common->fsg is NULL */ |
| 1634 | 1621 | return -EIO; |
| @@ -2022,7 +2009,8 @@ static int do_scsi_command(struct fsg_common *common) · 387 unmodified lines | ||
| 2022 | 2009 | |
| 2023 | 2010 | case READ_6: |
| 2024 | 2011 | i = common->cmnd[4]; |
| 2025 | − common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | |
| 2012 | + common->data_size_from_cmnd = (i == 0 ? 256 : i) << | |
| 2013 | + common->curlun->blkbits; | |
| 2026 | 2014 | reply = check_command(common, 6, DATA_DIR_TO_HOST, |
| 2027 | 2015 | (7<<1) | (1<<4), 1, |
| 2028 | 2016 | "READ(6)"); |
| @@ -2032,7 +2020,8 @@ static int do_scsi_command(struct fsg_common *common) · 3 unmodified lines | ||
| 2032 | 2020 | |
| 2033 | 2021 | case READ_10: |
| 2034 | 2022 | common->data_size_from_cmnd = |
| 2035 | − get_unaligned_be16(&common->cmnd[7]) << 9; | |
| 2023 | + get_unaligned_be16(&common->cmnd[7]) << | |
| 2024 | + common->curlun->blkbits; | |
| 2036 | 2025 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
| 2037 | 2026 | (1<<1) | (0xf<<2) | (3<<7), 1, |
| 2038 | 2027 | "READ(10)"); |
| @@ -2042,7 +2031,8 @@ static int do_scsi_command(struct fsg_common *common) · 3 unmodified lines | ||
| 2042 | 2031 | |
| 2043 | 2032 | case READ_12: |
| 2044 | 2033 | common->data_size_from_cmnd = |
| 2045 | − get_unaligned_be32(&common->cmnd[6]) << 9; | |
| 2034 | + get_unaligned_be32(&common->cmnd[6]) << | |
| 2035 | + common->curlun->blkbits; | |
| 2046 | 2036 | reply = check_command(common, 12, DATA_DIR_TO_HOST, |
| 2047 | 2037 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
| 2048 | 2038 | "READ(12)"); |
| @@ -2142,7 +2132,8 @@ static int do_scsi_command(struct fsg_common *common) · 93 unmodified lines | ||
| 2142 | 2132 | |
| 2143 | 2133 | case WRITE_6: |
| 2144 | 2134 | i = common->cmnd[4]; |
| 2145 | − common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | |
| 2135 | + common->data_size_from_cmnd = (i == 0 ? 256 : i) << | |
| 2136 | + common->curlun->blkbits; | |
| 2146 | 2137 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, |
| 2147 | 2138 | (7<<1) | (1<<4), 1, |
| 2148 | 2139 | "WRITE(6)"); |
| @@ -2152,7 +2143,8 @@ static int do_scsi_command(struct fsg_common *common) · 3 unmodified lines | ||
| 2152 | 2143 | |
| 2153 | 2144 | case WRITE_10: |
| 2154 | 2145 | common->data_size_from_cmnd = |
| 2155 | − get_unaligned_be16(&common->cmnd[7]) << 9; | |
| 2146 | + get_unaligned_be16(&common->cmnd[7]) << | |
| 2147 | + common->curlun->blkbits; | |
| 2156 | 2148 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, |
| 2157 | 2149 | (1<<1) | (0xf<<2) | (3<<7), 1, |
| 2158 | 2150 | "WRITE(10)"); |
| @@ -2162,7 +2154,8 @@ static int do_scsi_command(struct fsg_common *common) · 3 unmodified lines | ||
| 2162 | 2154 | |
| 2163 | 2155 | case WRITE_12: |
| 2164 | 2156 | common->data_size_from_cmnd = |
| 2165 | − get_unaligned_be32(&common->cmnd[6]) << 9; | |
| 2157 | + get_unaligned_be32(&common->cmnd[6]) << | |
| 2158 | + common->curlun->blkbits; | |
| 2166 | 2159 | reply = check_command(common, 12, DATA_DIR_FROM_HOST, |
| 2167 | 2160 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
| 2168 | 2161 | "WRITE(12)"); |
| @@ -2297,7 +2290,6 @@ static int get_next_command(struct fsg_common *common) · 128 unmodified lines | ||
| 2297 | 2290 | |
| 2298 | 2291 | /* Queue a request to read a Bulk-only CBW */ |
| 2299 | 2292 | set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); |
| 2300 | − bh->outreq->short_not_ok = 1; | |
| 2301 | 2293 | if (!start_out_transfer(common, bh)) |
| 2302 | 2294 | /* Don't know what to do if common->fsg is NULL */ |
| 2303 | 2295 | return -EIO; |
| @@ -2348,7 +2340,7 @@ reset: · 44 unmodified lines | ||
| 2348 | 2340 | if (common->fsg) { |
| 2349 | 2341 | fsg = common->fsg; |
| 2350 | 2342 | |
| 2351 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2343 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2352 | 2344 | struct fsg_buffhd *bh = &common->buffhds[i]; |
| 2353 | 2345 | |
| 2354 | 2346 | if (bh->inreq) { |
| @@ -2401,12 +2393,11 @@ reset: · 46 unmodified lines | ||
| 2401 | 2393 | goto reset; |
| 2402 | 2394 | fsg->bulk_out->driver_data = common; |
| 2403 | 2395 | fsg->bulk_out_enabled = 1; |
| 2404 | − common->bulk_out_maxpacket = | |
| 2405 | − le16_to_cpu(fsg->bulk_out->desc->wMaxPacketSize); | |
| 2396 | + common->bulk_out_maxpacket = usb_endpoint_maxp(fsg->bulk_out->desc); | |
| 2406 | 2397 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); |
| 2407 | 2398 | |
| 2408 | 2399 | /* Allocate the requests */ |
| 2409 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2400 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2410 | 2401 | struct fsg_buffhd *bh = &common->buffhds[i]; |
| 2411 | 2402 | |
| 2412 | 2403 | rc = alloc_request(common, fsg->bulk_in, &bh->inreq); |
| @@ -2475,7 +2466,7 @@ static void handle_exception(struct fsg_common *common) · 62 unmodified lines | ||
| 2475 | 2466 | |
| 2476 | 2467 | /* Cancel all the pending transfers */ |
| 2477 | 2468 | if (likely(common->fsg)) { |
| 2478 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2469 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2479 | 2470 | bh = &common->buffhds[i]; |
| 2480 | 2471 | if (bh->inreq_busy) |
| 2481 | 2472 | usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); |
| @@ -2487,7 +2478,7 @@ static void handle_exception(struct fsg_common *common) · 5 unmodified lines | ||
| 2487 | 2478 | /* Wait until everything is idle */ |
| 2488 | 2479 | for (;;) { |
| 2489 | 2480 | int num_active = 0; |
| 2490 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2481 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2491 | 2482 | bh = &common->buffhds[i]; |
| 2492 | 2483 | num_active += bh->inreq_busy + bh->outreq_busy; |
| 2493 | 2484 | } |
| @@ -2510,7 +2501,7 @@ static void handle_exception(struct fsg_common *common) · 16 unmodified lines | ||
| 2510 | 2501 | */ |
| 2511 | 2502 | spin_lock_irq(&common->lock); |
| 2512 | 2503 | |
| 2513 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2504 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2514 | 2505 | bh = &common->buffhds[i]; |
| 2515 | 2506 | bh->state = BUF_STATE_EMPTY; |
| 2516 | 2507 | } |
| @@ -2719,6 +2710,10 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, · 202 unmodified lines | ||
| 2719 | 2710 | int nluns, i, rc; |
| 2720 | 2711 | char *pathbuf; |
| 2721 | 2712 | |
| 2713 | + rc = fsg_num_buffers_validate(); | |
| 2714 | + if (rc != 0) | |
| 2715 | + return ERR_PTR(rc); | |
| 2716 | + | |
| 2722 | 2717 | /* Find out how many LUNs there should be */ |
| 2723 | 2718 | nluns = cfg->nluns; |
| 2724 | 2719 | if (nluns < 1 || nluns > FSG_MAX_LUNS) { |
| @@ -2737,6 +2732,14 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, · 12 unmodified lines | ||
| 2737 | 2732 | common->free_storage_on_release = 0; |
| 2738 | 2733 | } |
| 2739 | 2734 | |
| 2735 | + common->buffhds = kcalloc(fsg_num_buffers, | |
| 2736 | + sizeof *(common->buffhds), GFP_KERNEL); | |
| 2737 | + if (!common->buffhds) { | |
| 2738 | + if (common->free_storage_on_release) | |
| 2739 | + kfree(common); | |
| 2740 | + return ERR_PTR(-ENOMEM); | |
| 2741 | + } | |
| 2742 | + | |
| 2740 | 2743 | common->ops = cfg->ops; |
| 2741 | 2744 | common->private_data = cfg->private_data; |
| 2742 | 2745 | |
| @@ -2814,7 +2817,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, · 71 unmodified lines | ||
| 2814 | 2817 | |
| 2815 | 2818 | /* Data buffers cyclic list */ |
| 2816 | 2819 | bh = common->buffhds; |
| 2817 | − i = FSG_NUM_BUFFERS; | |
| 2820 | + i = fsg_num_buffers; | |
| 2818 | 2821 | goto buffhds_first_it; |
| 2819 | 2822 | do { |
| 2820 | 2823 | bh->next = bh + 1; |
| @@ -2940,12 +2943,13 @@ static void fsg_common_release(struct kref *ref) · 119 unmodified lines | ||
| 2940 | 2943 | |
| 2941 | 2944 | { |
| 2942 | 2945 | struct fsg_buffhd *bh = common->buffhds; |
| 2943 | − unsigned i = FSG_NUM_BUFFERS; | |
| 2946 | + unsigned i = fsg_num_buffers; | |
| 2944 | 2947 | do { |
| 2945 | 2948 | kfree(bh->buf); |
| 2946 | 2949 | } while (++bh, --i); |
| 2947 | 2950 | } |
| 2948 | 2951 | |
| 2952 | + kfree(common->buffhds); | |
| 2949 | 2953 | if (common->free_storage_on_release) |
| 2950 | 2954 | kfree(common); |
| 2951 | 2955 | } |
| @@ -3019,6 +3023,28 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) · 67 unmodified lines | ||
| 3019 | 3023 | } |
| 3020 | 3024 | } |
| 3021 | 3025 | |
| 3026 | + if (gadget_is_superspeed(gadget)) { | |
| 3027 | + unsigned max_burst; | |
| 3028 | + | |
| 3029 | + /* Calculate bMaxBurst, we know packet size is 1024 */ | |
| 3030 | + max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); | |
| 3031 | + | |
| 3032 | + fsg_ss_bulk_in_desc.bEndpointAddress = | |
| 3033 | + fsg_fs_bulk_in_desc.bEndpointAddress; | |
| 3034 | + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; | |
| 3035 | + | |
| 3036 | + fsg_ss_bulk_out_desc.bEndpointAddress = | |
| 3037 | + fsg_fs_bulk_out_desc.bEndpointAddress; | |
| 3038 | + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; | |
| 3039 | + | |
| 3040 | + f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); | |
| 3041 | + if (unlikely(!f->ss_descriptors)) { | |
| 3042 | + usb_free_descriptors(f->hs_descriptors); | |
| 3043 | + usb_free_descriptors(f->descriptors); | |
| 3044 | + return -ENOMEM; | |
| 3045 | + } | |
| 3046 | + } | |
| 3047 | + | |
| 3022 | 3048 | return 0; |
| 3023 | 3049 | |
| 3024 | 3050 | autoconf_fail: |
| @@ -0,0 +1,998 @@ | ||
| 1 | +/* | |
| 2 | + * f_midi.c -- USB MIDI class function driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2006 Thumtronics Pty Ltd. | |
| 5 | + * Developed for Thumtronics by Grey Innovation | |
| 6 | + * Ben Williamson <ben.williamson@greyinnovation.com> | |
| 7 | + * | |
| 8 | + * Rewritten for the composite framework | |
| 9 | + * Copyright (C) 2011 Daniel Mack <zonque@gmail.com> | |
| 10 | + * | |
| 11 | + * Based on drivers/usb/gadget/f_audio.c, | |
| 12 | + * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | |
| 13 | + * Copyright (C) 2008 Analog Devices, Inc | |
| 14 | + * | |
| 15 | + * and drivers/usb/gadget/midi.c, | |
| 16 | + * Copyright (C) 2006 Thumtronics Pty Ltd. | |
| 17 | + * Ben Williamson <ben.williamson@greyinnovation.com> | |
| 18 | + * | |
| 19 | + * Licensed under the GPL-2 or later. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include <linux/kernel.h> | |
| 23 | +#include <linux/slab.h> | |
| 24 | +#include <linux/utsname.h> | |
| 25 | +#include <linux/device.h> | |
| 26 | + | |
| 27 | +#include <sound/core.h> | |
| 28 | +#include <sound/initval.h> | |
| 29 | +#include <sound/rawmidi.h> | |
| 30 | + | |
| 31 | +#include <linux/usb/ch9.h> | |
| 32 | +#include <linux/usb/gadget.h> | |
| 33 | +#include <linux/usb/audio.h> | |
| 34 | +#include <linux/usb/midi.h> | |
| 35 | + | |
| 36 | +MODULE_AUTHOR("Ben Williamson"); | |
| 37 | +MODULE_LICENSE("GPL v2"); | |
| 38 | + | |
| 39 | +static const char f_midi_shortname[] = "f_midi"; | |
| 40 | +static const char f_midi_longname[] = "MIDI Gadget"; | |
| 41 | + | |
| 42 | +/* | |
| 43 | + * We can only handle 16 cables on one single endpoint, as cable numbers are | |
| 44 | + * stored in 4-bit fields. And as the interface currently only holds one | |
| 45 | + * single endpoint, this is the maximum number of ports we can allow. | |
| 46 | + */ | |
| 47 | +#define MAX_PORTS 16 | |
| 48 | + | |
| 49 | +/* | |
| 50 | + * This is a gadget, and the IN/OUT naming is from the host's perspective. | |
| 51 | + * USB -> OUT endpoint -> rawmidi | |
| 52 | + * USB <- IN endpoint <- rawmidi | |
| 53 | + */ | |
| 54 | +struct gmidi_in_port { | |
| 55 | + struct f_midi *midi; | |
| 56 | + int active; | |
| 57 | + uint8_t cable; | |
| 58 | + uint8_t state; | |
| 59 | +#define STATE_UNKNOWN 0 | |
| 60 | +#define STATE_1PARAM 1 | |
| 61 | +#define STATE_2PARAM_1 2 | |
| 62 | +#define STATE_2PARAM_2 3 | |
| 63 | +#define STATE_SYSEX_0 4 | |
| 64 | +#define STATE_SYSEX_1 5 | |
| 65 | +#define STATE_SYSEX_2 6 | |
| 66 | + uint8_t data[2]; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +struct f_midi { | |
| 70 | + struct usb_function func; | |
| 71 | + struct usb_gadget *gadget; | |
| 72 | + struct usb_ep *in_ep, *out_ep; | |
| 73 | + struct snd_card *card; | |
| 74 | + struct snd_rawmidi *rmidi; | |
| 75 | + | |
| 76 | + struct snd_rawmidi_substream *in_substream[MAX_PORTS]; | |
| 77 | + struct snd_rawmidi_substream *out_substream[MAX_PORTS]; | |
| 78 | + struct gmidi_in_port *in_port[MAX_PORTS]; | |
| 79 | + | |
| 80 | + unsigned long out_triggered; | |
| 81 | + struct tasklet_struct tasklet; | |
| 82 | + unsigned int in_ports; | |
| 83 | + unsigned int out_ports; | |
| 84 | + int index; | |
| 85 | + char *id; | |
| 86 | + unsigned int buflen, qlen; | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static inline struct f_midi *func_to_midi(struct usb_function *f) | |
| 90 | +{ | |
| 91 | + return container_of(f, struct f_midi, func); | |
| 92 | +} | |
| 93 | + | |
| 94 | +static void f_midi_transmit(struct f_midi *midi, struct usb_request *req); | |
| 95 | + | |
| 96 | +DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); | |
| 97 | +DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | |
| 98 | +DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16); | |
| 99 | +DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); | |
| 100 | + | |
| 101 | +/* B.3.1 Standard AC Interface Descriptor */ | |
| 102 | +static struct usb_interface_descriptor ac_interface_desc __initdata = { | |
| 103 | + .bLength = USB_DT_INTERFACE_SIZE, | |
| 104 | + .bDescriptorType = USB_DT_INTERFACE, | |
| 105 | + /* .bInterfaceNumber = DYNAMIC */ | |
| 106 | + /* .bNumEndpoints = DYNAMIC */ | |
| 107 | + .bInterfaceClass = USB_CLASS_AUDIO, | |
| 108 | + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | |
| 109 | + /* .iInterface = DYNAMIC */ | |
| 110 | +}; | |
| 111 | + | |
| 112 | +/* B.3.2 Class-Specific AC Interface Descriptor */ | |
| 113 | +static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { | |
| 114 | + .bLength = UAC_DT_AC_HEADER_SIZE(1), | |
| 115 | + .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 116 | + .bDescriptorSubtype = USB_MS_HEADER, | |
| 117 | + .bcdADC = cpu_to_le16(0x0100), | |
| 118 | + .wTotalLength = cpu_to_le16(UAC_DT_AC_HEADER_SIZE(1)), | |
| 119 | + .bInCollection = 1, | |
| 120 | + /* .baInterfaceNr = DYNAMIC */ | |
| 121 | +}; | |
| 122 | + | |
| 123 | +/* B.4.1 Standard MS Interface Descriptor */ | |
| 124 | +static struct usb_interface_descriptor ms_interface_desc __initdata = { | |
| 125 | + .bLength = USB_DT_INTERFACE_SIZE, | |
| 126 | + .bDescriptorType = USB_DT_INTERFACE, | |
| 127 | + /* .bInterfaceNumber = DYNAMIC */ | |
| 128 | + .bNumEndpoints = 2, | |
| 129 | + .bInterfaceClass = USB_CLASS_AUDIO, | |
| 130 | + .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, | |
| 131 | + /* .iInterface = DYNAMIC */ | |
| 132 | +}; | |
| 133 | + | |
| 134 | +/* B.4.2 Class-Specific MS Interface Descriptor */ | |
| 135 | +static struct usb_ms_header_descriptor ms_header_desc __initdata = { | |
| 136 | + .bLength = USB_DT_MS_HEADER_SIZE, | |
| 137 | + .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 138 | + .bDescriptorSubtype = USB_MS_HEADER, | |
| 139 | + .bcdMSC = cpu_to_le16(0x0100), | |
| 140 | + /* .wTotalLength = DYNAMIC */ | |
| 141 | +}; | |
| 142 | + | |
| 143 | +/* B.4.3 Embedded MIDI IN Jack Descriptor */ | |
| 144 | +static struct usb_midi_in_jack_descriptor jack_in_emb_desc = { | |
| 145 | + .bLength = USB_DT_MIDI_IN_SIZE, | |
| 146 | + .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 147 | + .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, | |
| 148 | + .bJackType = USB_MS_EMBEDDED, | |
| 149 | + /* .bJackID = DYNAMIC */ | |
| 150 | +}; | |
| 151 | + | |
| 152 | +/* B.4.4 Embedded MIDI OUT Jack Descriptor */ | |
| 153 | +static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = { | |
| 154 | + /* .bLength = DYNAMIC */ | |
| 155 | + .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 156 | + .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, | |
| 157 | + .bJackType = USB_MS_EMBEDDED, | |
| 158 | + /* .bJackID = DYNAMIC */ | |
| 159 | + /* .bNrInputPins = DYNAMIC */ | |
| 160 | + /* .pins = DYNAMIC */ | |
| 161 | +}; | |
| 162 | + | |
| 163 | +/* B.5.1 Standard Bulk OUT Endpoint Descriptor */ | |
| 164 | +static struct usb_endpoint_descriptor bulk_out_desc = { | |
| 165 | + .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
| 166 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 167 | + .bEndpointAddress = USB_DIR_OUT, | |
| 168 | + .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 169 | +}; | |
| 170 | + | |
| 171 | +/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */ | |
| 172 | +static struct usb_ms_endpoint_descriptor_16 ms_out_desc = { | |
| 173 | + /* .bLength = DYNAMIC */ | |
| 174 | + .bDescriptorType = USB_DT_CS_ENDPOINT, | |
| 175 | + .bDescriptorSubtype = USB_MS_GENERAL, | |
| 176 | + /* .bNumEmbMIDIJack = DYNAMIC */ | |
| 177 | + /* .baAssocJackID = DYNAMIC */ | |
| 178 | +}; | |
| 179 | + | |
| 180 | +/* B.6.1 Standard Bulk IN Endpoint Descriptor */ | |
| 181 | +static struct usb_endpoint_descriptor bulk_in_desc = { | |
| 182 | + .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
| 183 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 184 | + .bEndpointAddress = USB_DIR_IN, | |
| 185 | + .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 186 | +}; | |
| 187 | + | |
| 188 | +/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */ | |
| 189 | +static struct usb_ms_endpoint_descriptor_16 ms_in_desc = { | |
| 190 | + /* .bLength = DYNAMIC */ | |
| 191 | + .bDescriptorType = USB_DT_CS_ENDPOINT, | |
| 192 | + .bDescriptorSubtype = USB_MS_GENERAL, | |
| 193 | + /* .bNumEmbMIDIJack = DYNAMIC */ | |
| 194 | + /* .baAssocJackID = DYNAMIC */ | |
| 195 | +}; | |
| 196 | + | |
| 197 | +/* string IDs are assigned dynamically */ | |
| 198 | + | |
| 199 | +#define STRING_FUNC_IDX 0 | |
| 200 | + | |
| 201 | +static struct usb_string midi_string_defs[] = { | |
| 202 | + [STRING_FUNC_IDX].s = "MIDI function", | |
| 203 | + { } /* end of list */ | |
| 204 | +}; | |
| 205 | + | |
| 206 | +static struct usb_gadget_strings midi_stringtab = { | |
| 207 | + .language = 0x0409, /* en-us */ | |
| 208 | + .strings = midi_string_defs, | |
| 209 | +}; | |
| 210 | + | |
| 211 | +static struct usb_gadget_strings *midi_strings[] = { | |
| 212 | + &midi_stringtab, | |
| 213 | + NULL, | |
| 214 | +}; | |
| 215 | + | |
| 216 | +static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) | |
| 217 | +{ | |
| 218 | + struct usb_request *req; | |
| 219 | + | |
| 220 | + req = usb_ep_alloc_request(ep, GFP_ATOMIC); | |
| 221 | + if (req) { | |
| 222 | + req->length = length; | |
| 223 | + req->buf = kmalloc(length, GFP_ATOMIC); | |
| 224 | + if (!req->buf) { | |
| 225 | + usb_ep_free_request(ep, req); | |
| 226 | + req = NULL; | |
| 227 | + } | |
| 228 | + } | |
| 229 | + return req; | |
| 230 | +} | |
| 231 | + | |
| 232 | +static void free_ep_req(struct usb_ep *ep, struct usb_request *req) | |
| 233 | +{ | |
| 234 | + kfree(req->buf); | |
| 235 | + usb_ep_free_request(ep, req); | |
| 236 | +} | |
| 237 | + | |
| 238 | +static const uint8_t f_midi_cin_length[] = { | |
| 239 | + 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | |
| 240 | +}; | |
| 241 | + | |
| 242 | +/* | |
| 243 | + * Receives a chunk of MIDI data. | |
| 244 | + */ | |
| 245 | +static void f_midi_read_data(struct usb_ep *ep, int cable, | |
| 246 | + uint8_t *data, int length) | |
| 247 | +{ | |
| 248 | + struct f_midi *midi = ep->driver_data; | |
| 249 | + struct snd_rawmidi_substream *substream = midi->out_substream[cable]; | |
| 250 | + | |
| 251 | + if (!substream) | |
| 252 | + /* Nobody is listening - throw it on the floor. */ | |
| 253 | + return; | |
| 254 | + | |
| 255 | + if (!test_bit(cable, &midi->out_triggered)) | |
| 256 | + return; | |
| 257 | + | |
| 258 | + snd_rawmidi_receive(substream, data, length); | |
| 259 | +} | |
| 260 | + | |
| 261 | +static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req) | |
| 262 | +{ | |
| 263 | + unsigned int i; | |
| 264 | + u8 *buf = req->buf; | |
| 265 | + | |
| 266 | + for (i = 0; i + 3 < req->actual; i += 4) | |
| 267 | + if (buf[i] != 0) { | |
| 268 | + int cable = buf[i] >> 4; | |
| 269 | + int length = f_midi_cin_length[buf[i] & 0x0f]; | |
| 270 | + f_midi_read_data(ep, cable, &buf[i + 1], length); | |
| 271 | + } | |
| 272 | +} | |
| 273 | + | |
| 274 | +static void | |
| 275 | +f_midi_complete(struct usb_ep *ep, struct usb_request *req) | |
| 276 | +{ | |
| 277 | + struct f_midi *midi = ep->driver_data; | |
| 278 | + struct usb_composite_dev *cdev = midi->func.config->cdev; | |
| 279 | + int status = req->status; | |
| 280 | + | |
| 281 | + switch (status) { | |
| 282 | + case 0: /* normal completion */ | |
| 283 | + if (ep == midi->out_ep) { | |
| 284 | + /* We received stuff. req is queued again, below */ | |
| 285 | + f_midi_handle_out_data(ep, req); | |
| 286 | + } else if (ep == midi->in_ep) { | |
| 287 | + /* Our transmit completed. See if there's more to go. | |
| 288 | + * f_midi_transmit eats req, don't queue it again. */ | |
| 289 | + f_midi_transmit(midi, req); | |
| 290 | + return; | |
| 291 | + } | |
| 292 | + break; | |
| 293 | + | |
| 294 | + /* this endpoint is normally active while we're configured */ | |
| 295 | + case -ECONNABORTED: /* hardware forced ep reset */ | |
| 296 | + case -ECONNRESET: /* request dequeued */ | |
| 297 | + case -ESHUTDOWN: /* disconnect from host */ | |
| 298 | + VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status, | |
| 299 | + req->actual, req->length); | |
| 300 | + if (ep == midi->out_ep) | |
| 301 | + f_midi_handle_out_data(ep, req); | |
| 302 | + | |
| 303 | + free_ep_req(ep, req); | |
| 304 | + return; | |
| 305 | + | |
| 306 | + case -EOVERFLOW: /* buffer overrun on read means that | |
| 307 | + * we didn't provide a big enough buffer. | |
| 308 | + */ | |
| 309 | + default: | |
| 310 | + DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name, | |
| 311 | + status, req->actual, req->length); | |
| 312 | + break; | |
| 313 | + case -EREMOTEIO: /* short read */ | |
| 314 | + break; | |
| 315 | + } | |
| 316 | + | |
| 317 | + status = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 318 | + if (status) { | |
| 319 | + ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n", | |
| 320 | + ep->name, req->length, status); | |
| 321 | + usb_ep_set_halt(ep); | |
| 322 | + /* FIXME recover later ... somehow */ | |
| 323 | + } | |
| 324 | +} | |
| 325 | + | |
| 326 | +static int f_midi_start_ep(struct f_midi *midi, | |
| 327 | + struct usb_function *f, | |
| 328 | + struct usb_ep *ep) | |
| 329 | +{ | |
| 330 | + int err; | |
| 331 | + struct usb_composite_dev *cdev = f->config->cdev; | |
| 332 | + | |
| 333 | + if (ep->driver_data) | |
| 334 | + usb_ep_disable(ep); | |
| 335 | + | |
| 336 | + err = config_ep_by_speed(midi->gadget, f, ep); | |
| 337 | + if (err) { | |
| 338 | + ERROR(cdev, "can't configure %s: %d\n", ep->name, err); | |
| 339 | + return err; | |
| 340 | + } | |
| 341 | + | |
| 342 | + err = usb_ep_enable(ep); | |
| 343 | + if (err) { | |
| 344 | + ERROR(cdev, "can't start %s: %d\n", ep->name, err); | |
| 345 | + return err; | |
| 346 | + } | |
| 347 | + | |
| 348 | + ep->driver_data = midi; | |
| 349 | + | |
| 350 | + return 0; | |
| 351 | +} | |
| 352 | + | |
| 353 | +static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |
| 354 | +{ | |
| 355 | + struct f_midi *midi = func_to_midi(f); | |
| 356 | + struct usb_composite_dev *cdev = f->config->cdev; | |
| 357 | + unsigned i; | |
| 358 | + int err; | |
| 359 | + | |
| 360 | + err = f_midi_start_ep(midi, f, midi->in_ep); | |
| 361 | + if (err) | |
| 362 | + return err; | |
| 363 | + | |
| 364 | + err = f_midi_start_ep(midi, f, midi->out_ep); | |
| 365 | + if (err) | |
| 366 | + return err; | |
| 367 | + | |
| 368 | + if (midi->out_ep->driver_data) | |
| 369 | + usb_ep_disable(midi->out_ep); | |
| 370 | + | |
| 371 | + err = config_ep_by_speed(midi->gadget, f, midi->out_ep); | |
| 372 | + if (err) { | |
| 373 | + ERROR(cdev, "can't configure %s: %d\n", | |
| 374 | + midi->out_ep->name, err); | |
| 375 | + return err; | |
| 376 | + } | |
| 377 | + | |
| 378 | + err = usb_ep_enable(midi->out_ep); | |
| 379 | + if (err) { | |
| 380 | + ERROR(cdev, "can't start %s: %d\n", | |
| 381 | + midi->out_ep->name, err); | |
| 382 | + return err; | |
| 383 | + } | |
| 384 | + | |
| 385 | + midi->out_ep->driver_data = midi; | |
| 386 | + | |
| 387 | + /* allocate a bunch of read buffers and queue them all at once. */ | |
| 388 | + for (i = 0; i < midi->qlen && err == 0; i++) { | |
| 389 | + struct usb_request *req = | |
| 390 | + alloc_ep_req(midi->out_ep, midi->buflen); | |
| 391 | + if (req == NULL) | |
| 392 | + return -ENOMEM; | |
| 393 | + | |
| 394 | + req->complete = f_midi_complete; | |
| 395 | + err = usb_ep_queue(midi->out_ep, req, GFP_ATOMIC); | |
| 396 | + if (err) { | |
| 397 | + ERROR(midi, "%s queue req: %d\n", | |
| 398 | + midi->out_ep->name, err); | |
| 399 | + } | |
| 400 | + } | |
| 401 | + | |
| 402 | + return 0; | |
| 403 | +} | |
| 404 | + | |
| 405 | +static void f_midi_disable(struct usb_function *f) | |
| 406 | +{ | |
| 407 | + struct f_midi *midi = func_to_midi(f); | |
| 408 | + struct usb_composite_dev *cdev = f->config->cdev; | |
| 409 | + | |
| 410 | + DBG(cdev, "disable\n"); | |
| 411 | + | |
| 412 | + /* | |
| 413 | + * just disable endpoints, forcing completion of pending i/o. | |
| 414 | + * all our completion handlers free their requests in this case. | |
| 415 | + */ | |
| 416 | + usb_ep_disable(midi->in_ep); | |
| 417 | + usb_ep_disable(midi->out_ep); | |
| 418 | +} | |
| 419 | + | |
| 420 | +static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) | |
| 421 | +{ | |
| 422 | + struct usb_composite_dev *cdev = f->config->cdev; | |
| 423 | + struct f_midi *midi = func_to_midi(f); | |
| 424 | + struct snd_card *card; | |
| 425 | + | |
| 426 | + DBG(cdev, "unbind\n"); | |
| 427 | + | |
| 428 | + /* just to be sure */ | |
| 429 | + f_midi_disable(f); | |
| 430 | + | |
| 431 | + card = midi->card; | |
| 432 | + midi->card = NULL; | |
| 433 | + if (card) | |
| 434 | + snd_card_free(card); | |
| 435 | + | |
| 436 | + kfree(midi->id); | |
| 437 | + midi->id = NULL; | |
| 438 | + | |
| 439 | + usb_free_descriptors(f->descriptors); | |
| 440 | + kfree(midi); | |
| 441 | +} | |
| 442 | + | |
| 443 | +static int f_midi_snd_free(struct snd_device *device) | |
| 444 | +{ | |
| 445 | + return 0; | |
| 446 | +} | |
| 447 | + | |
| 448 | +static void f_midi_transmit_packet(struct usb_request *req, uint8_t p0, | |
| 449 | + uint8_t p1, uint8_t p2, uint8_t p3) | |
| 450 | +{ | |
| 451 | + unsigned length = req->length; | |
| 452 | + u8 *buf = (u8 *)req->buf + length; | |
| 453 | + | |
| 454 | + buf[0] = p0; | |
| 455 | + buf[1] = p1; | |
| 456 | + buf[2] = p2; | |
| 457 | + buf[3] = p3; | |
| 458 | + req->length = length + 4; | |
| 459 | +} | |
| 460 | + | |
| 461 | +/* | |
| 462 | + * Converts MIDI commands to USB MIDI packets. | |
| 463 | + */ | |
| 464 | +static void f_midi_transmit_byte(struct usb_request *req, | |
| 465 | + struct gmidi_in_port *port, uint8_t b) | |
| 466 | +{ | |
| 467 | + uint8_t p0 = port->cable << 4; | |
| 468 | + | |
| 469 | + if (b >= 0xf8) { | |
| 470 | + f_midi_transmit_packet(req, p0 | 0x0f, b, 0, 0); | |
| 471 | + } else if (b >= 0xf0) { | |
| 472 | + switch (b) { | |
| 473 | + case 0xf0: | |
| 474 | + port->data[0] = b; | |
| 475 | + port->state = STATE_SYSEX_1; | |
| 476 | + break; | |
| 477 | + case 0xf1: | |
| 478 | + case 0xf3: | |
| 479 | + port->data[0] = b; | |
| 480 | + port->state = STATE_1PARAM; | |
| 481 | + break; | |
| 482 | + case 0xf2: | |
| 483 | + port->data[0] = b; | |
| 484 | + port->state = STATE_2PARAM_1; | |
| 485 | + break; | |
| 486 | + case 0xf4: | |
| 487 | + case 0xf5: | |
| 488 | + port->state = STATE_UNKNOWN; | |
| 489 | + break; | |
| 490 | + case 0xf6: | |
| 491 | + f_midi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0); | |
| 492 | + port->state = STATE_UNKNOWN; | |
| 493 | + break; | |
| 494 | + case 0xf7: | |
| 495 | + switch (port->state) { | |
| 496 | + case STATE_SYSEX_0: | |
| 497 | + f_midi_transmit_packet(req, | |
| 498 | + p0 | 0x05, 0xf7, 0, 0); | |
| 499 | + break; | |
| 500 | + case STATE_SYSEX_1: | |
| 501 | + f_midi_transmit_packet(req, | |
| 502 | + p0 | 0x06, port->data[0], 0xf7, 0); | |
| 503 | + break; | |
| 504 | + case STATE_SYSEX_2: | |
| 505 | + f_midi_transmit_packet(req, | |
| 506 | + p0 | 0x07, port->data[0], | |
| 507 | + port->data[1], 0xf7); | |
| 508 | + break; | |
| 509 | + } | |
| 510 | + port->state = STATE_UNKNOWN; | |
| 511 | + break; | |
| 512 | + } | |
| 513 | + } else if (b >= 0x80) { | |
| 514 | + port->data[0] = b; | |
| 515 | + if (b >= 0xc0 && b <= 0xdf) | |
| 516 | + port->state = STATE_1PARAM; | |
| 517 | + else | |
| 518 | + port->state = STATE_2PARAM_1; | |
| 519 | + } else { /* b < 0x80 */ | |
| 520 | + switch (port->state) { | |
| 521 | + case STATE_1PARAM: | |
| 522 | + if (port->data[0] < 0xf0) { | |
| 523 | + p0 |= port->data[0] >> 4; | |
| 524 | + } else { | |
| 525 | + p0 |= 0x02; | |
| 526 | + port->state = STATE_UNKNOWN; | |
| 527 | + } | |
| 528 | + f_midi_transmit_packet(req, p0, port->data[0], b, 0); | |
| 529 | + break; | |
| 530 | + case STATE_2PARAM_1: | |
| 531 | + port->data[1] = b; | |
| 532 | + port->state = STATE_2PARAM_2; | |
| 533 | + break; | |
| 534 | + case STATE_2PARAM_2: | |
| 535 | + if (port->data[0] < 0xf0) { | |
| 536 | + p0 |= port->data[0] >> 4; | |
| 537 | + port->state = STATE_2PARAM_1; | |
| 538 | + } else { | |
| 539 | + p0 |= 0x03; | |
| 540 | + port->state = STATE_UNKNOWN; | |
| 541 | + } | |
| 542 | + f_midi_transmit_packet(req, | |
| 543 | + p0, port->data[0], port->data[1], b); | |
| 544 | + break; | |
| 545 | + case STATE_SYSEX_0: | |
| 546 | + port->data[0] = b; | |
| 547 | + port->state = STATE_SYSEX_1; | |
| 548 | + break; | |
| 549 | + case STATE_SYSEX_1: | |
| 550 | + port->data[1] = b; | |
| 551 | + port->state = STATE_SYSEX_2; | |
| 552 | + break; | |
| 553 | + case STATE_SYSEX_2: | |
| 554 | + f_midi_transmit_packet(req, | |
| 555 | + p0 | 0x04, port->data[0], port->data[1], b); | |
| 556 | + port->state = STATE_SYSEX_0; | |
| 557 | + break; | |
| 558 | + } | |
| 559 | + } | |
| 560 | +} | |
| 561 | + | |
| 562 | +static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) | |
| 563 | +{ | |
| 564 | + struct usb_ep *ep = midi->in_ep; | |
| 565 | + int i; | |
| 566 | + | |
| 567 | + if (!ep) | |
| 568 | + return; | |
| 569 | + | |
| 570 | + if (!req) | |
| 571 | + req = alloc_ep_req(ep, midi->buflen); | |
| 572 | + | |
| 573 | + if (!req) { | |
| 574 | + ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n"); | |
| 575 | + return; | |
| 576 | + } | |
| 577 | + req->length = 0; | |
| 578 | + req->complete = f_midi_complete; | |
| 579 | + | |
| 580 | + for (i = 0; i < MAX_PORTS; i++) { | |
| 581 | + struct gmidi_in_port *port = midi->in_port[i]; | |
| 582 | + struct snd_rawmidi_substream *substream = midi->in_substream[i]; | |
| 583 | + | |
| 584 | + if (!port || !port->active || !substream) | |
| 585 | + continue; | |
| 586 | + | |
| 587 | + while (req->length + 3 < midi->buflen) { | |
| 588 | + uint8_t b; | |
| 589 | + if (snd_rawmidi_transmit(substream, &b, 1) != 1) { | |
| 590 | + port->active = 0; | |
| 591 | + break; | |
| 592 | + } | |
| 593 | + f_midi_transmit_byte(req, port, b); | |
| 594 | + } | |
| 595 | + } | |
| 596 | + | |
| 597 | + if (req->length > 0) | |
| 598 | + usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 599 | + else | |
| 600 | + free_ep_req(ep, req); | |
| 601 | +} | |
| 602 | + | |
| 603 | +static void f_midi_in_tasklet(unsigned long data) | |
| 604 | +{ | |
| 605 | + struct f_midi *midi = (struct f_midi *) data; | |
| 606 | + f_midi_transmit(midi, NULL); | |
| 607 | +} | |
| 608 | + | |
| 609 | +static int f_midi_in_open(struct snd_rawmidi_substream *substream) | |
| 610 | +{ | |
| 611 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 612 | + | |
| 613 | + if (!midi->in_port[substream->number]) | |
| 614 | + return -EINVAL; | |
| 615 | + | |
| 616 | + VDBG(midi, "%s()\n", __func__); | |
| 617 | + midi->in_substream[substream->number] = substream; | |
| 618 | + midi->in_port[substream->number]->state = STATE_UNKNOWN; | |
| 619 | + return 0; | |
| 620 | +} | |
| 621 | + | |
| 622 | +static int f_midi_in_close(struct snd_rawmidi_substream *substream) | |
| 623 | +{ | |
| 624 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 625 | + | |
| 626 | + VDBG(midi, "%s()\n", __func__); | |
| 627 | + return 0; | |
| 628 | +} | |
| 629 | + | |
| 630 | +static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) | |
| 631 | +{ | |
| 632 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 633 | + | |
| 634 | + if (!midi->in_port[substream->number]) | |
| 635 | + return; | |
| 636 | + | |
| 637 | + VDBG(midi, "%s() %d\n", __func__, up); | |
| 638 | + midi->in_port[substream->number]->active = up; | |
| 639 | + if (up) | |
| 640 | + tasklet_hi_schedule(&midi->tasklet); | |
| 641 | +} | |
| 642 | + | |
| 643 | +static int f_midi_out_open(struct snd_rawmidi_substream *substream) | |
| 644 | +{ | |
| 645 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 646 | + | |
| 647 | + if (substream->number >= MAX_PORTS) | |
| 648 | + return -EINVAL; | |
| 649 | + | |
| 650 | + VDBG(midi, "%s()\n", __func__); | |
| 651 | + midi->out_substream[substream->number] = substream; | |
| 652 | + return 0; | |
| 653 | +} | |
| 654 | + | |
| 655 | +static int f_midi_out_close(struct snd_rawmidi_substream *substream) | |
| 656 | +{ | |
| 657 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 658 | + | |
| 659 | + VDBG(midi, "%s()\n", __func__); | |
| 660 | + return 0; | |
| 661 | +} | |
| 662 | + | |
| 663 | +static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up) | |
| 664 | +{ | |
| 665 | + struct f_midi *midi = substream->rmidi->private_data; | |
| 666 | + | |
| 667 | + VDBG(midi, "%s()\n", __func__); | |
| 668 | + | |
| 669 | + if (up) | |
| 670 | + set_bit(substream->number, &midi->out_triggered); | |
| 671 | + else | |
| 672 | + clear_bit(substream->number, &midi->out_triggered); | |
| 673 | +} | |
| 674 | + | |
| 675 | +static struct snd_rawmidi_ops gmidi_in_ops = { | |
| 676 | + .open = f_midi_in_open, | |
| 677 | + .close = f_midi_in_close, | |
| 678 | + .trigger = f_midi_in_trigger, | |
| 679 | +}; | |
| 680 | + | |
| 681 | +static struct snd_rawmidi_ops gmidi_out_ops = { | |
| 682 | + .open = f_midi_out_open, | |
| 683 | + .close = f_midi_out_close, | |
| 684 | + .trigger = f_midi_out_trigger | |
| 685 | +}; | |
| 686 | + | |
| 687 | +/* register as a sound "card" */ | |
| 688 | +static int f_midi_register_card(struct f_midi *midi) | |
| 689 | +{ | |
| 690 | + struct snd_card *card; | |
| 691 | + struct snd_rawmidi *rmidi; | |
| 692 | + int err; | |
| 693 | + static struct snd_device_ops ops = { | |
| 694 | + .dev_free = f_midi_snd_free, | |
| 695 | + }; | |
| 696 | + | |
| 697 | + err = snd_card_create(midi->index, midi->id, THIS_MODULE, 0, &card); | |
| 698 | + if (err < 0) { | |
| 699 | + ERROR(midi, "snd_card_create() failed\n"); | |
| 700 | + goto fail; | |
| 701 | + } | |
| 702 | + midi->card = card; | |
| 703 | + | |
| 704 | + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, midi, &ops); | |
| 705 | + if (err < 0) { | |
| 706 | + ERROR(midi, "snd_device_new() failed: error %d\n", err); | |
| 707 | + goto fail; | |
| 708 | + } | |
| 709 | + | |
| 710 | + strcpy(card->driver, f_midi_longname); | |
| 711 | + strcpy(card->longname, f_midi_longname); | |
| 712 | + strcpy(card->shortname, f_midi_shortname); | |
| 713 | + | |
| 714 | + /* Set up rawmidi */ | |
| 715 | + snd_component_add(card, "MIDI"); | |
| 716 | + err = snd_rawmidi_new(card, card->longname, 0, | |
| 717 | + midi->out_ports, midi->in_ports, &rmidi); | |
| 718 | + if (err < 0) { | |
| 719 | + ERROR(midi, "snd_rawmidi_new() failed: error %d\n", err); | |
| 720 | + goto fail; | |
| 721 | + } | |
| 722 | + midi->rmidi = rmidi; | |
| 723 | + strcpy(rmidi->name, card->shortname); | |
| 724 | + rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | |
| 725 | + SNDRV_RAWMIDI_INFO_INPUT | | |
| 726 | + SNDRV_RAWMIDI_INFO_DUPLEX; | |
| 727 | + rmidi->private_data = midi; | |
| 728 | + | |
| 729 | + /* | |
| 730 | + * Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT. | |
| 731 | + * It's an upside-down world being a gadget. | |
| 732 | + */ | |
| 733 | + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); | |
| 734 | + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); | |
| 735 | + | |
| 736 | + snd_card_set_dev(card, &midi->gadget->dev); | |
| 737 | + | |
| 738 | + /* register it - we're ready to go */ | |
| 739 | + err = snd_card_register(card); | |
| 740 | + if (err < 0) { | |
| 741 | + ERROR(midi, "snd_card_register() failed\n"); | |
| 742 | + goto fail; | |
| 743 | + } | |
| 744 | + | |
| 745 | + VDBG(midi, "%s() finished ok\n", __func__); | |
| 746 | + return 0; | |
| 747 | + | |
| 748 | +fail: | |
| 749 | + if (midi->card) { | |
| 750 | + snd_card_free(midi->card); | |
| 751 | + midi->card = NULL; | |
| 752 | + } | |
| 753 | + return err; | |
| 754 | +} | |
| 755 | + | |
| 756 | +/* MIDI function driver setup/binding */ | |
| 757 | + | |
| 758 | +static int __init | |
| 759 | +f_midi_bind(struct usb_configuration *c, struct usb_function *f) | |
| 760 | +{ | |
| 761 | + struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12]; | |
| 762 | + struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; | |
| 763 | + struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS]; | |
| 764 | + struct usb_composite_dev *cdev = c->cdev; | |
| 765 | + struct f_midi *midi = func_to_midi(f); | |
| 766 | + int status, n, jack = 1, i = 0; | |
| 767 | + | |
| 768 | + /* maybe allocate device-global string ID */ | |
| 769 | + if (midi_string_defs[0].id == 0) { | |
| 770 | + status = usb_string_id(c->cdev); | |
| 771 | + if (status < 0) | |
| 772 | + goto fail; | |
| 773 | + midi_string_defs[0].id = status; | |
| 774 | + } | |
| 775 | + | |
| 776 | + /* We have two interfaces, AudioControl and MIDIStreaming */ | |
| 777 | + status = usb_interface_id(c, f); | |
| 778 | + if (status < 0) | |
| 779 | + goto fail; | |
| 780 | + ac_interface_desc.bInterfaceNumber = status; | |
| 781 | + | |
| 782 | + status = usb_interface_id(c, f); | |
| 783 | + if (status < 0) | |
| 784 | + goto fail; | |
| 785 | + ms_interface_desc.bInterfaceNumber = status; | |
| 786 | + ac_header_desc.baInterfaceNr[0] = status; | |
| 787 | + | |
| 788 | + status = -ENODEV; | |
| 789 | + | |
| 790 | + /* allocate instance-specific endpoints */ | |
| 791 | + midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc); | |
| 792 | + if (!midi->in_ep) | |
| 793 | + goto fail; | |
| 794 | + midi->in_ep->driver_data = cdev; /* claim */ | |
| 795 | + | |
| 796 | + midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc); | |
| 797 | + if (!midi->out_ep) | |
| 798 | + goto fail; | |
| 799 | + midi->out_ep->driver_data = cdev; /* claim */ | |
| 800 | + | |
| 801 | + /* | |
| 802 | + * construct the function's descriptor set. As the number of | |
| 803 | + * input and output MIDI ports is configurable, we have to do | |
| 804 | + * it that way. | |
| 805 | + */ | |
| 806 | + | |
| 807 | + /* add the headers - these are always the same */ | |
| 808 | + midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc; | |
| 809 | + midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc; | |
| 810 | + midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc; | |
| 811 | + | |
| 812 | + /* calculate the header's wTotalLength */ | |
| 813 | + n = USB_DT_MS_HEADER_SIZE | |
| 814 | + + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE | |
| 815 | + + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1); | |
| 816 | + ms_header_desc.wTotalLength = cpu_to_le16(n); | |
| 817 | + | |
| 818 | + midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc; | |
| 819 | + | |
| 820 | + /* we have one embedded IN jack */ | |
| 821 | + jack_in_emb_desc.bJackID = jack++; | |
| 822 | + midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc; | |
| 823 | + | |
| 824 | + /* and a dynamic amount of external IN jacks */ | |
| 825 | + for (n = 0; n < midi->in_ports; n++) { | |
| 826 | + struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n]; | |
| 827 | + | |
| 828 | + ext->bLength = USB_DT_MIDI_IN_SIZE; | |
| 829 | + ext->bDescriptorType = USB_DT_CS_INTERFACE; | |
| 830 | + ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; | |
| 831 | + ext->bJackType = USB_MS_EXTERNAL; | |
| 832 | + ext->bJackID = jack++; | |
| 833 | + ext->iJack = 0; | |
| 834 | + | |
| 835 | + midi_function[i++] = (struct usb_descriptor_header *) ext; | |
| 836 | + } | |
| 837 | + | |
| 838 | + /* one embedded OUT jack ... */ | |
| 839 | + jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports); | |
| 840 | + jack_out_emb_desc.bJackID = jack++; | |
| 841 | + jack_out_emb_desc.bNrInputPins = midi->in_ports; | |
| 842 | + /* ... which referencess all external IN jacks */ | |
| 843 | + for (n = 0; n < midi->in_ports; n++) { | |
| 844 | + jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID; | |
| 845 | + jack_out_emb_desc.pins[n].baSourcePin = 1; | |
| 846 | + } | |
| 847 | + | |
| 848 | + midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc; | |
| 849 | + | |
| 850 | + /* and multiple external OUT jacks ... */ | |
| 851 | + for (n = 0; n < midi->out_ports; n++) { | |
| 852 | + struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n]; | |
| 853 | + int m; | |
| 854 | + | |
| 855 | + ext->bLength = USB_DT_MIDI_OUT_SIZE(1); | |
| 856 | + ext->bDescriptorType = USB_DT_CS_INTERFACE; | |
| 857 | + ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; | |
| 858 | + ext->bJackType = USB_MS_EXTERNAL; | |
| 859 | + ext->bJackID = jack++; | |
| 860 | + ext->bNrInputPins = 1; | |
| 861 | + ext->iJack = 0; | |
| 862 | + /* ... which all reference the same embedded IN jack */ | |
| 863 | + for (m = 0; m < midi->out_ports; m++) { | |
| 864 | + ext->pins[m].baSourceID = jack_in_emb_desc.bJackID; | |
| 865 | + ext->pins[m].baSourcePin = 1; | |
| 866 | + } | |
| 867 | + | |
| 868 | + midi_function[i++] = (struct usb_descriptor_header *) ext; | |
| 869 | + } | |
| 870 | + | |
| 871 | + /* configure the endpoint descriptors ... */ | |
| 872 | + ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); | |
| 873 | + ms_out_desc.bNumEmbMIDIJack = midi->in_ports; | |
| 874 | + for (n = 0; n < midi->in_ports; n++) | |
| 875 | + ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID; | |
| 876 | + | |
| 877 | + ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); | |
| 878 | + ms_in_desc.bNumEmbMIDIJack = midi->out_ports; | |
| 879 | + for (n = 0; n < midi->out_ports; n++) | |
| 880 | + ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID; | |
| 881 | + | |
| 882 | + /* ... and add them to the list */ | |
| 883 | + midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc; | |
| 884 | + midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc; | |
| 885 | + midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc; | |
| 886 | + midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc; | |
| 887 | + midi_function[i++] = NULL; | |
| 888 | + | |
| 889 | + /* | |
| 890 | + * support all relevant hardware speeds... we expect that when | |
| 891 | + * hardware is dual speed, all bulk-capable endpoints work at | |
| 892 | + * both speeds | |
| 893 | + */ | |
| 894 | + /* copy descriptors, and track endpoint copies */ | |
| 895 | + if (gadget_is_dualspeed(c->cdev->gadget)) { | |
| 896 | + c->highspeed = true; | |
| 897 | + bulk_in_desc.wMaxPacketSize = cpu_to_le16(512); | |
| 898 | + bulk_out_desc.wMaxPacketSize = cpu_to_le16(512); | |
| 899 | + f->hs_descriptors = usb_copy_descriptors(midi_function); | |
| 900 | + } else { | |
| 901 | + f->descriptors = usb_copy_descriptors(midi_function); | |
| 902 | + } | |
| 903 | + | |
| 904 | + return 0; | |
| 905 | + | |
| 906 | +fail: | |
| 907 | + /* we might as well release our claims on endpoints */ | |
| 908 | + if (midi->out_ep) | |
| 909 | + midi->out_ep->driver_data = NULL; | |
| 910 | + if (midi->in_ep) | |
| 911 | + midi->in_ep->driver_data = NULL; | |
| 912 | + | |
| 913 | + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); | |
| 914 | + | |
| 915 | + return status; | |
| 916 | +} | |
| 917 | + | |
| 918 | +/** | |
| 919 | + * f_midi_bind_config - add USB MIDI function to a configuration | |
| 920 | + * @c: the configuration to supcard the USB audio function | |
| 921 | + * @index: the soundcard index to use for the ALSA device creation | |
| 922 | + * @id: the soundcard id to use for the ALSA device creation | |
| 923 | + * @buflen: the buffer length to use | |
| 924 | + * @qlen the number of read requests to pre-allocate | |
| 925 | + * Context: single threaded during gadget setup | |
| 926 | + * | |
| 927 | + * Returns zero on success, else negative errno. | |
| 928 | + */ | |
| 929 | +int __init f_midi_bind_config(struct usb_configuration *c, | |
| 930 | + int index, char *id, | |
| 931 | + unsigned int in_ports, | |
| 932 | + unsigned int out_ports, | |
| 933 | + unsigned int buflen, | |
| 934 | + unsigned int qlen) | |
| 935 | +{ | |
| 936 | + struct f_midi *midi; | |
| 937 | + int status, i; | |
| 938 | + | |
| 939 | + /* sanity check */ | |
| 940 | + if (in_ports > MAX_PORTS || out_ports > MAX_PORTS) | |
| 941 | + return -EINVAL; | |
| 942 | + | |
| 943 | + /* allocate and initialize one new instance */ | |
| 944 | + midi = kzalloc(sizeof *midi, GFP_KERNEL); | |
| 945 | + if (!midi) { | |
| 946 | + status = -ENOMEM; | |
| 947 | + goto fail; | |
| 948 | + } | |
| 949 | + | |
| 950 | + for (i = 0; i < in_ports; i++) { | |
| 951 | + struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL); | |
| 952 | + if (!port) { | |
| 953 | + status = -ENOMEM; | |
| 954 | + goto setup_fail; | |
| 955 | + } | |
| 956 | + | |
| 957 | + port->midi = midi; | |
| 958 | + port->active = 0; | |
| 959 | + port->cable = i; | |
| 960 | + midi->in_port[i] = port; | |
| 961 | + } | |
| 962 | + | |
| 963 | + midi->gadget = c->cdev->gadget; | |
| 964 | + tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); | |
| 965 | + | |
| 966 | + /* set up ALSA midi devices */ | |
| 967 | + midi->in_ports = in_ports; | |
| 968 | + midi->out_ports = out_ports; | |
| 969 | + status = f_midi_register_card(midi); | |
| 970 | + if (status < 0) | |
| 971 | + goto setup_fail; | |
| 972 | + | |
| 973 | + midi->func.name = "gmidi function"; | |
| 974 | + midi->func.strings = midi_strings; | |
| 975 | + midi->func.bind = f_midi_bind; | |
| 976 | + midi->func.unbind = f_midi_unbind; | |
| 977 | + midi->func.set_alt = f_midi_set_alt; | |
| 978 | + midi->func.disable = f_midi_disable; | |
| 979 | + | |
| 980 | + midi->id = kstrdup(id, GFP_KERNEL); | |
| 981 | + midi->index = index; | |
| 982 | + midi->buflen = buflen; | |
| 983 | + midi->qlen = qlen; | |
| 984 | + | |
| 985 | + status = usb_add_function(c, &midi->func); | |
| 986 | + if (status) | |
| 987 | + goto setup_fail; | |
| 988 | + | |
| 989 | + return 0; | |
| 990 | + | |
| 991 | +setup_fail: | |
| 992 | + for (--i; i >= 0; i--) | |
| 993 | + kfree(midi->in_port[i]); | |
| 994 | + kfree(midi); | |
| 995 | +fail: | |
| 996 | + return status; | |
| 997 | +} | |
| 998 | + | |
| @@ -13,15 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | * it under the terms of the GNU General Public License as published by |
| 14 | 14 | * the Free Software Foundation; either version 2 of the License, or |
| 15 | 15 | * (at your option) any later version. |
| 16 | − * | |
| 17 | − * This program is distributed in the hope that it will be useful, | |
| 18 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | − * GNU General Public License for more details. | |
| 21 | − * | |
| 22 | − * You should have received a copy of the GNU General Public License | |
| 23 | − * along with this program; if not, write to the Free Software | |
| 24 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 25 | 16 | */ |
| 26 | 17 | |
| 27 | 18 | #include <linux/kernel.h> |
| @@ -10,15 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | 13 | */ |
| 23 | 14 | |
| 24 | 15 | /* #define VERBOSE_DEBUG */ |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or |
| 9 | 9 | * modify it under the terms of the GNU General Public License |
| 10 | 10 | * version 2 as published by the Free Software Foundation. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, but | |
| 13 | − * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | − * General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
| 20 | − * 02110-1301 USA | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | #include <linux/mm.h> |
| @@ -11,15 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | * it under the terms of the GNU General Public License as published by |
| 12 | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | 13 | * (at your option) any later version. |
| 14 | − * | |
| 15 | − * This program is distributed in the hope that it will be useful, | |
| 16 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − * GNU General Public License for more details. | |
| 19 | − * | |
| 20 | − * You should have received a copy of the GNU General Public License | |
| 21 | − * along with this program; if not, write to the Free Software | |
| 22 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 23 | 14 | */ |
| 24 | 15 | |
| 25 | 16 | /* #define VERBOSE_DEBUG */ |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | /* #define VERBOSE_DEBUG */ |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | #include <linux/slab.h> |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #include <linux/kernel.h> |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #ifndef _F_UVC_H_ |
| @@ -69,8 +69,7 @@ · 68 unmodified lines | ||
| 69 | 69 | * each LUN would be settable independently as a disk drive or a CD-ROM |
| 70 | 70 | * drive, but currently all LUNs have to be the same type. The CD-ROM |
| 71 | 71 | * emulation includes a single data track and no audio tracks; hence there |
| 72 | − * need be only one backing file per LUN. Note also that the CD-ROM block | |
| 73 | − * length is set to 512 rather than the more common value 2048. | |
| 72 | + * need be only one backing file per LUN. | |
| 74 | 73 | * |
| 75 | 74 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are |
| 76 | 75 | * needed (an interrupt-out endpoint is also needed for CBI). The memory |
| @@ -461,7 +460,6 @@ struct fsg_dev { · 384 unmodified lines | ||
| 461 | 460 | |
| 462 | 461 | struct fsg_buffhd *next_buffhd_to_fill; |
| 463 | 462 | struct fsg_buffhd *next_buffhd_to_drain; |
| 464 | − struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; | |
| 465 | 463 | |
| 466 | 464 | int thread_wakeup_needed; |
| 467 | 465 | struct completion thread_notifier; |
| @@ -488,6 +486,8 @@ struct fsg_dev { · 20 unmodified lines | ||
| 488 | 486 | unsigned int nluns; |
| 489 | 487 | struct fsg_lun *luns; |
| 490 | 488 | struct fsg_lun *curlun; |
| 489 | + /* Must be the last entry */ | |
| 490 | + struct fsg_buffhd buffhds[]; | |
| 491 | 491 | }; |
| 492 | 492 | |
| 493 | 493 | typedef void (*fsg_routine_t)(struct fsg_dev *); |
| @@ -586,7 +586,19 @@ dev_qualifier = { · 92 unmodified lines | ||
| 586 | 586 | .bNumConfigurations = 1, |
| 587 | 587 | }; |
| 588 | 588 | |
| 589 | +static int populate_bos(struct fsg_dev *fsg, u8 *buf) | |
| 590 | +{ | |
| 591 | + memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE); | |
| 592 | + buf += USB_DT_BOS_SIZE; | |
| 593 | + | |
| 594 | + memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE); | |
| 595 | + buf += USB_DT_USB_EXT_CAP_SIZE; | |
| 589 | 596 | |
| 597 | + memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE); | |
| 598 | + | |
| 599 | + return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE | |
| 600 | + + USB_DT_USB_EXT_CAP_SIZE; | |
| 601 | +} | |
| 590 | 602 | |
| 591 | 603 | /* |
| 592 | 604 | * Config descriptors must agree with the code that sets configurations |
| @@ -935,7 +947,8 @@ static int standard_setup_req(struct fsg_dev *fsg, · 342 unmodified lines | ||
| 935 | 947 | break; |
| 936 | 948 | case USB_DT_DEVICE_QUALIFIER: |
| 937 | 949 | VDBG(fsg, "get device qualifier\n"); |
| 938 | − if (!gadget_is_dualspeed(fsg->gadget)) | |
| 950 | + if (!gadget_is_dualspeed(fsg->gadget) || | |
| 951 | + fsg->gadget->speed == USB_SPEED_SUPER) | |
| 939 | 952 | break; |
| 940 | 953 | /* |
| 941 | 954 | * Assume ep0 uses the same maxpacket value for both |
| @@ -948,7 +961,8 @@ static int standard_setup_req(struct fsg_dev *fsg, · 6 unmodified lines | ||
| 948 | 961 | |
| 949 | 962 | case USB_DT_OTHER_SPEED_CONFIG: |
| 950 | 963 | VDBG(fsg, "get other-speed config descriptor\n"); |
| 951 | − if (!gadget_is_dualspeed(fsg->gadget)) | |
| 964 | + if (!gadget_is_dualspeed(fsg->gadget) || | |
| 965 | + fsg->gadget->speed == USB_SPEED_SUPER) | |
| 952 | 966 | break; |
| 953 | 967 | goto get_config; |
| 954 | 968 | case USB_DT_CONFIG: |
| @@ -967,7 +981,15 @@ get_config: · 12 unmodified lines | ||
| 967 | 981 | value = usb_gadget_get_string(&fsg_stringtab, |
| 968 | 982 | w_value & 0xff, req->buf); |
| 969 | 983 | break; |
| 984 | + | |
| 985 | + case USB_DT_BOS: | |
| 986 | + VDBG(fsg, "get bos descriptor\n"); | |
| 987 | + | |
| 988 | + if (gadget_is_superspeed(fsg->gadget)) | |
| 989 | + value = populate_bos(fsg, req->buf); | |
| 990 | + break; | |
| 970 | 991 | } |
| 992 | + | |
| 971 | 993 | break; |
| 972 | 994 | |
| 973 | 995 | /* One config, two speeds */ |
| @@ -1136,7 +1158,6 @@ static int do_read(struct fsg_dev *fsg) · 162 unmodified lines | ||
| 1136 | 1158 | u32 amount_left; |
| 1137 | 1159 | loff_t file_offset, file_offset_tmp; |
| 1138 | 1160 | unsigned int amount; |
| 1139 | − unsigned int partial_page; | |
| 1140 | 1161 | ssize_t nread; |
| 1141 | 1162 | |
| 1142 | 1163 | /* Get the starting Logical Block Address and check that it's |
| @@ -1158,7 +1179,7 @@ static int do_read(struct fsg_dev *fsg) · 15 unmodified lines | ||
| 1158 | 1179 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 1159 | 1180 | return -EINVAL; |
| 1160 | 1181 | } |
| 1161 | − file_offset = ((loff_t) lba) << 9; | |
| 1182 | + file_offset = ((loff_t) lba) << curlun->blkbits; | |
| 1162 | 1183 | |
| 1163 | 1184 | /* Carry out the file reads */ |
| 1164 | 1185 | amount_left = fsg->data_size_from_cmnd; |
| @@ -1171,17 +1192,10 @@ static int do_read(struct fsg_dev *fsg) · 6 unmodified lines | ||
| 1171 | 1192 | * Try to read the remaining amount. |
| 1172 | 1193 | * But don't read more than the buffer size. |
| 1173 | 1194 | * And don't try to read past the end of the file. |
| 1174 | − * Finally, if we're not at a page boundary, don't read past | |
| 1175 | − * the next page. | |
| 1176 | − * If this means reading 0 then we were asked to read past | |
| 1177 | − * the end of file. */ | |
| 1195 | + */ | |
| 1178 | 1196 | amount = min((unsigned int) amount_left, mod_data.buflen); |
| 1179 | 1197 | amount = min((loff_t) amount, |
| 1180 | 1198 | curlun->file_length - file_offset); |
| 1181 | − partial_page = file_offset & (PAGE_CACHE_SIZE - 1); | |
| 1182 | − if (partial_page > 0) | |
| 1183 | − amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - | |
| 1184 | − partial_page); | |
| 1185 | 1199 | |
| 1186 | 1200 | /* Wait for the next buffer to become available */ |
| 1187 | 1201 | bh = fsg->next_buffhd_to_fill; |
| @@ -1196,7 +1210,7 @@ static int do_read(struct fsg_dev *fsg) · 8 unmodified lines | ||
| 1196 | 1210 | if (amount == 0) { |
| 1197 | 1211 | curlun->sense_data = |
| 1198 | 1212 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 1199 | − curlun->sense_data_info = file_offset >> 9; | |
| 1213 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1200 | 1214 | curlun->info_valid = 1; |
| 1201 | 1215 | bh->inreq->length = 0; |
| 1202 | 1216 | bh->state = BUF_STATE_FULL; |
| @@ -1221,18 +1235,23 @@ static int do_read(struct fsg_dev *fsg) · 18 unmodified lines | ||
| 1221 | 1235 | } else if (nread < amount) { |
| 1222 | 1236 | LDBG(curlun, "partial file read: %d/%u\n", |
| 1223 | 1237 | (int) nread, amount); |
| 1224 | − nread -= (nread & 511); // Round down to a block | |
| 1238 | + nread = round_down(nread, curlun->blksize); | |
| 1225 | 1239 | } |
| 1226 | 1240 | file_offset += nread; |
| 1227 | 1241 | amount_left -= nread; |
| 1228 | 1242 | fsg->residue -= nread; |
| 1243 | + | |
| 1244 | + /* Except at the end of the transfer, nread will be | |
| 1245 | + * equal to the buffer size, which is divisible by the | |
| 1246 | + * bulk-in maxpacket size. | |
| 1247 | + */ | |
| 1229 | 1248 | bh->inreq->length = nread; |
| 1230 | 1249 | bh->state = BUF_STATE_FULL; |
| 1231 | 1250 | |
| 1232 | 1251 | /* If an error occurred, report it and its position */ |
| 1233 | 1252 | if (nread < amount) { |
| 1234 | 1253 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
| 1235 | − curlun->sense_data_info = file_offset >> 9; | |
| 1254 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1236 | 1255 | curlun->info_valid = 1; |
| 1237 | 1256 | break; |
| 1238 | 1257 | } |
| @@ -1262,7 +1281,6 @@ static int do_write(struct fsg_dev *fsg) · 23 unmodified lines | ||
| 1262 | 1281 | u32 amount_left_to_req, amount_left_to_write; |
| 1263 | 1282 | loff_t usb_offset, file_offset, file_offset_tmp; |
| 1264 | 1283 | unsigned int amount; |
| 1265 | − unsigned int partial_page; | |
| 1266 | 1284 | ssize_t nwritten; |
| 1267 | 1285 | int rc; |
| 1268 | 1286 | |
| @@ -1303,7 +1321,7 @@ static int do_write(struct fsg_dev *fsg) · 34 unmodified lines | ||
| 1303 | 1321 | |
| 1304 | 1322 | /* Carry out the file writes */ |
| 1305 | 1323 | get_some_more = 1; |
| 1306 | − file_offset = usb_offset = ((loff_t) lba) << 9; | |
| 1324 | + file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; | |
| 1307 | 1325 | amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; |
| 1308 | 1326 | |
| 1309 | 1327 | while (amount_left_to_write > 0) { |
| @@ -1313,38 +1331,20 @@ static int do_write(struct fsg_dev *fsg) · 3 unmodified lines | ||
| 1313 | 1331 | if (bh->state == BUF_STATE_EMPTY && get_some_more) { |
| 1314 | 1332 | |
| 1315 | 1333 | /* Figure out how much we want to get: |
| 1316 | − * Try to get the remaining amount. | |
| 1317 | − * But don't get more than the buffer size. | |
| 1318 | − * And don't try to go past the end of the file. | |
| 1319 | − * If we're not at a page boundary, | |
| 1320 | − * don't go past the next page. | |
| 1321 | − * If this means getting 0, then we were asked | |
| 1322 | − * to write past the end of file. | |
| 1323 | − * Finally, round down to a block boundary. */ | |
| 1334 | + * Try to get the remaining amount, | |
| 1335 | + * but not more than the buffer size. | |
| 1336 | + */ | |
| 1324 | 1337 | amount = min(amount_left_to_req, mod_data.buflen); |
| 1325 | − amount = min((loff_t) amount, curlun->file_length - | |
| 1326 | − usb_offset); | |
| 1327 | − partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); | |
| 1328 | − if (partial_page > 0) | |
| 1329 | − amount = min(amount, | |
| 1330 | − (unsigned int) PAGE_CACHE_SIZE - partial_page); | |
| 1331 | − | |
| 1332 | − if (amount == 0) { | |
| 1338 | + | |
| 1339 | + /* Beyond the end of the backing file? */ | |
| 1340 | + if (usb_offset >= curlun->file_length) { | |
| 1333 | 1341 | get_some_more = 0; |
| 1334 | 1342 | curlun->sense_data = |
| 1335 | 1343 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 1336 | − curlun->sense_data_info = usb_offset >> 9; | |
| 1344 | + curlun->sense_data_info = usb_offset >> curlun->blkbits; | |
| 1337 | 1345 | curlun->info_valid = 1; |
| 1338 | 1346 | continue; |
| 1339 | 1347 | } |
| 1340 | − amount -= (amount & 511); | |
| 1341 | − if (amount == 0) { | |
| 1342 | − | |
| 1343 | − /* Why were we were asked to transfer a | |
| 1344 | − * partial block? */ | |
| 1345 | − get_some_more = 0; | |
| 1346 | − continue; | |
| 1347 | − } | |
| 1348 | 1348 | |
| 1349 | 1349 | /* Get the next buffer */ |
| 1350 | 1350 | usb_offset += amount; |
| @@ -1353,11 +1353,11 @@ static int do_write(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 1353 | 1353 | if (amount_left_to_req == 0) |
| 1354 | 1354 | get_some_more = 0; |
| 1355 | 1355 | |
| 1356 | − /* amount is always divisible by 512, hence by | |
| 1357 | − * the bulk-out maxpacket size */ | |
| 1358 | − bh->outreq->length = bh->bulk_out_intended_length = | |
| 1359 | − amount; | |
| 1360 | − bh->outreq->short_not_ok = 1; | |
| 1356 | + /* Except at the end of the transfer, amount will be | |
| 1357 | + * equal to the buffer size, which is divisible by | |
| 1358 | + * the bulk-out maxpacket size. | |
| 1359 | + */ | |
| 1360 | + set_bulk_out_req_length(fsg, bh, amount); | |
| 1361 | 1361 | start_transfer(fsg, fsg->bulk_out, bh->outreq, |
| 1362 | 1362 | &bh->outreq_busy, &bh->state); |
| 1363 | 1363 | fsg->next_buffhd_to_fill = bh->next; |
| @@ -1376,7 +1376,7 @@ static int do_write(struct fsg_dev *fsg) · 12 unmodified lines | ||
| 1376 | 1376 | /* Did something go wrong with the transfer? */ |
| 1377 | 1377 | if (bh->outreq->status != 0) { |
| 1378 | 1378 | curlun->sense_data = SS_COMMUNICATION_FAILURE; |
| 1379 | − curlun->sense_data_info = file_offset >> 9; | |
| 1379 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1380 | 1380 | curlun->info_valid = 1; |
| 1381 | 1381 | break; |
| 1382 | 1382 | } |
| @@ -1390,6 +1390,16 @@ static int do_write(struct fsg_dev *fsg) · 7 unmodified lines | ||
| 1390 | 1390 | amount = curlun->file_length - file_offset; |
| 1391 | 1391 | } |
| 1392 | 1392 | |
| 1393 | + /* Don't accept excess data. The spec doesn't say | |
| 1394 | + * what to do in this case. We'll ignore the error. | |
| 1395 | + */ | |
| 1396 | + amount = min(amount, bh->bulk_out_intended_length); | |
| 1397 | + | |
| 1398 | + /* Don't write a partial block */ | |
| 1399 | + amount = round_down(amount, curlun->blksize); | |
| 1400 | + if (amount == 0) | |
| 1401 | + goto empty_write; | |
| 1402 | + | |
| 1393 | 1403 | /* Perform the write */ |
| 1394 | 1404 | file_offset_tmp = file_offset; |
| 1395 | 1405 | nwritten = vfs_write(curlun->filp, |
| @@ -1408,8 +1418,7 @@ static int do_write(struct fsg_dev *fsg) · 12 unmodified lines | ||
| 1408 | 1418 | } else if (nwritten < amount) { |
| 1409 | 1419 | LDBG(curlun, "partial file write: %d/%u\n", |
| 1410 | 1420 | (int) nwritten, amount); |
| 1411 | − nwritten -= (nwritten & 511); | |
| 1412 | − // Round down to a block | |
| 1421 | + nwritten = round_down(nwritten, curlun->blksize); | |
| 1413 | 1422 | } |
| 1414 | 1423 | file_offset += nwritten; |
| 1415 | 1424 | amount_left_to_write -= nwritten; |
| @@ -1418,13 +1427,14 @@ static int do_write(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 1418 | 1427 | /* If an error occurred, report it and its position */ |
| 1419 | 1428 | if (nwritten < amount) { |
| 1420 | 1429 | curlun->sense_data = SS_WRITE_ERROR; |
| 1421 | − curlun->sense_data_info = file_offset >> 9; | |
| 1430 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1422 | 1431 | curlun->info_valid = 1; |
| 1423 | 1432 | break; |
| 1424 | 1433 | } |
| 1425 | 1434 | |
| 1435 | + empty_write: | |
| 1426 | 1436 | /* Did the host decide to stop early? */ |
| 1427 | − if (bh->outreq->actual != bh->outreq->length) { | |
| 1437 | + if (bh->outreq->actual < bh->bulk_out_intended_length) { | |
| 1428 | 1438 | fsg->short_packet_received = 1; |
| 1429 | 1439 | break; |
| 1430 | 1440 | } |
| @@ -1500,8 +1510,8 @@ static int do_verify(struct fsg_dev *fsg) · 69 unmodified lines | ||
| 1500 | 1510 | return -EIO; // No default reply |
| 1501 | 1511 | |
| 1502 | 1512 | /* Prepare to carry out the file verify */ |
| 1503 | − amount_left = verification_length << 9; | |
| 1504 | − file_offset = ((loff_t) lba) << 9; | |
| 1513 | + amount_left = verification_length << curlun->blkbits; | |
| 1514 | + file_offset = ((loff_t) lba) << curlun->blkbits; | |
| 1505 | 1515 | |
| 1506 | 1516 | /* Write out all the dirty buffers before invalidating them */ |
| 1507 | 1517 | fsg_lun_fsync_sub(curlun); |
| @@ -1519,15 +1529,14 @@ static int do_verify(struct fsg_dev *fsg) · 11 unmodified lines | ||
| 1519 | 1529 | * Try to read the remaining amount, but not more than |
| 1520 | 1530 | * the buffer size. |
| 1521 | 1531 | * And don't try to read past the end of the file. |
| 1522 | − * If this means reading 0 then we were asked to read | |
| 1523 | − * past the end of file. */ | |
| 1532 | + */ | |
| 1524 | 1533 | amount = min((unsigned int) amount_left, mod_data.buflen); |
| 1525 | 1534 | amount = min((loff_t) amount, |
| 1526 | 1535 | curlun->file_length - file_offset); |
| 1527 | 1536 | if (amount == 0) { |
| 1528 | 1537 | curlun->sense_data = |
| 1529 | 1538 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
| 1530 | − curlun->sense_data_info = file_offset >> 9; | |
| 1539 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1531 | 1540 | curlun->info_valid = 1; |
| 1532 | 1541 | break; |
| 1533 | 1542 | } |
| @@ -1550,11 +1559,11 @@ static int do_verify(struct fsg_dev *fsg) · 16 unmodified lines | ||
| 1550 | 1559 | } else if (nread < amount) { |
| 1551 | 1560 | LDBG(curlun, "partial file verify: %d/%u\n", |
| 1552 | 1561 | (int) nread, amount); |
| 1553 | − nread -= (nread & 511); // Round down to a sector | |
| 1562 | + nread = round_down(nread, curlun->blksize); | |
| 1554 | 1563 | } |
| 1555 | 1564 | if (nread == 0) { |
| 1556 | 1565 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
| 1557 | − curlun->sense_data_info = file_offset >> 9; | |
| 1566 | + curlun->sense_data_info = file_offset >> curlun->blkbits; | |
| 1558 | 1567 | curlun->info_valid = 1; |
| 1559 | 1568 | break; |
| 1560 | 1569 | } |
| @@ -1668,7 +1677,7 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) · 107 unmodified lines | ||
| 1668 | 1677 | |
| 1669 | 1678 | put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); |
| 1670 | 1679 | /* Max logical block */ |
| 1671 | − put_unaligned_be32(512, &buf[4]); /* Block length */ | |
| 1680 | + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ | |
| 1672 | 1681 | return 8; |
| 1673 | 1682 | } |
| 1674 | 1683 | |
| @@ -1890,7 +1899,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg, · 215 unmodified lines | ||
| 1890 | 1899 | |
| 1891 | 1900 | put_unaligned_be32(curlun->num_sectors, &buf[0]); |
| 1892 | 1901 | /* Number of blocks */ |
| 1893 | − put_unaligned_be32(512, &buf[4]); /* Block length */ | |
| 1902 | + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ | |
| 1894 | 1903 | buf[4] = 0x02; /* Current capacity */ |
| 1895 | 1904 | return 12; |
| 1896 | 1905 | } |
| @@ -1969,7 +1978,7 @@ static int throw_away_data(struct fsg_dev *fsg) · 72 unmodified lines | ||
| 1969 | 1978 | fsg->next_buffhd_to_drain = bh->next; |
| 1970 | 1979 | |
| 1971 | 1980 | /* A short packet or an error ends everything */ |
| 1972 | − if (bh->outreq->actual != bh->outreq->length || | |
| 1981 | + if (bh->outreq->actual < bh->bulk_out_intended_length || | |
| 1973 | 1982 | bh->outreq->status != 0) { |
| 1974 | 1983 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); |
| 1975 | 1984 | return -EINTR; |
| @@ -1983,11 +1992,11 @@ static int throw_away_data(struct fsg_dev *fsg) · 7 unmodified lines | ||
| 1983 | 1992 | amount = min(fsg->usb_amount_left, |
| 1984 | 1993 | (u32) mod_data.buflen); |
| 1985 | 1994 | |
| 1986 | − /* amount is always divisible by 512, hence by | |
| 1987 | − * the bulk-out maxpacket size */ | |
| 1988 | − bh->outreq->length = bh->bulk_out_intended_length = | |
| 1989 | − amount; | |
| 1990 | − bh->outreq->short_not_ok = 1; | |
| 1995 | + /* Except at the end of the transfer, amount will be | |
| 1996 | + * equal to the buffer size, which is divisible by | |
| 1997 | + * the bulk-out maxpacket size. | |
| 1998 | + */ | |
| 1999 | + set_bulk_out_req_length(fsg, bh, amount); | |
| 1991 | 2000 | start_transfer(fsg, fsg->bulk_out, bh->outreq, |
| 1992 | 2001 | &bh->outreq_busy, &bh->state); |
| 1993 | 2002 | fsg->next_buffhd_to_fill = bh->next; |
| @@ -2415,7 +2424,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 421 unmodified lines | ||
| 2415 | 2424 | |
| 2416 | 2425 | case READ_6: |
| 2417 | 2426 | i = fsg->cmnd[4]; |
| 2418 | − fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | |
| 2427 | + fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits; | |
| 2419 | 2428 | if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, |
| 2420 | 2429 | (7<<1) | (1<<4), 1, |
| 2421 | 2430 | "READ(6)")) == 0) |
| @@ -2424,7 +2433,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 2424 | 2433 | |
| 2425 | 2434 | case READ_10: |
| 2426 | 2435 | fsg->data_size_from_cmnd = |
| 2427 | − get_unaligned_be16(&fsg->cmnd[7]) << 9; | |
| 2436 | + get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits; | |
| 2428 | 2437 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, |
| 2429 | 2438 | (1<<1) | (0xf<<2) | (3<<7), 1, |
| 2430 | 2439 | "READ(10)")) == 0) |
| @@ -2433,7 +2442,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 2433 | 2442 | |
| 2434 | 2443 | case READ_12: |
| 2435 | 2444 | fsg->data_size_from_cmnd = |
| 2436 | − get_unaligned_be32(&fsg->cmnd[6]) << 9; | |
| 2445 | + get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits; | |
| 2437 | 2446 | if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, |
| 2438 | 2447 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
| 2439 | 2448 | "READ(12)")) == 0) |
| @@ -2519,7 +2528,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 79 unmodified lines | ||
| 2519 | 2528 | |
| 2520 | 2529 | case WRITE_6: |
| 2521 | 2530 | i = fsg->cmnd[4]; |
| 2522 | − fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | |
| 2531 | + fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits; | |
| 2523 | 2532 | if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, |
| 2524 | 2533 | (7<<1) | (1<<4), 1, |
| 2525 | 2534 | "WRITE(6)")) == 0) |
| @@ -2528,7 +2537,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 2528 | 2537 | |
| 2529 | 2538 | case WRITE_10: |
| 2530 | 2539 | fsg->data_size_from_cmnd = |
| 2531 | − get_unaligned_be16(&fsg->cmnd[7]) << 9; | |
| 2540 | + get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits; | |
| 2532 | 2541 | if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, |
| 2533 | 2542 | (1<<1) | (0xf<<2) | (3<<7), 1, |
| 2534 | 2543 | "WRITE(10)")) == 0) |
| @@ -2537,7 +2546,7 @@ static int do_scsi_command(struct fsg_dev *fsg) · 2 unmodified lines | ||
| 2537 | 2546 | |
| 2538 | 2547 | case WRITE_12: |
| 2539 | 2548 | fsg->data_size_from_cmnd = |
| 2540 | − get_unaligned_be32(&fsg->cmnd[6]) << 9; | |
| 2549 | + get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits; | |
| 2541 | 2550 | if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, |
| 2542 | 2551 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
| 2543 | 2552 | "WRITE(12)")) == 0) |
| @@ -2666,7 +2675,6 @@ static int get_next_command(struct fsg_dev *fsg) · 122 unmodified lines | ||
| 2666 | 2675 | |
| 2667 | 2676 | /* Queue a request to read a Bulk-only CBW */ |
| 2668 | 2677 | set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); |
| 2669 | − bh->outreq->short_not_ok = 1; | |
| 2670 | 2678 | start_transfer(fsg, fsg->bulk_out, bh->outreq, |
| 2671 | 2679 | &bh->outreq_busy, &bh->state); |
| 2672 | 2680 | |
| @@ -2752,7 +2760,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting) · 79 unmodified lines | ||
| 2752 | 2760 | |
| 2753 | 2761 | reset: |
| 2754 | 2762 | /* Deallocate the requests */ |
| 2755 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2763 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2756 | 2764 | struct fsg_buffhd *bh = &fsg->buffhds[i]; |
| 2757 | 2765 | |
| 2758 | 2766 | if (bh->inreq) { |
| @@ -2791,29 +2799,32 @@ reset: · 32 unmodified lines | ||
| 2791 | 2799 | |
| 2792 | 2800 | /* Enable the endpoints */ |
| 2793 | 2801 | d = fsg_ep_desc(fsg->gadget, |
| 2794 | − &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); | |
| 2802 | + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, | |
| 2803 | + &fsg_ss_bulk_in_desc); | |
| 2795 | 2804 | if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) |
| 2796 | 2805 | goto reset; |
| 2797 | 2806 | fsg->bulk_in_enabled = 1; |
| 2798 | 2807 | |
| 2799 | 2808 | d = fsg_ep_desc(fsg->gadget, |
| 2800 | − &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); | |
| 2809 | + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, | |
| 2810 | + &fsg_ss_bulk_out_desc); | |
| 2801 | 2811 | if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) |
| 2802 | 2812 | goto reset; |
| 2803 | 2813 | fsg->bulk_out_enabled = 1; |
| 2804 | − fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); | |
| 2814 | + fsg->bulk_out_maxpacket = usb_endpoint_maxp(d); | |
| 2805 | 2815 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); |
| 2806 | 2816 | |
| 2807 | 2817 | if (transport_is_cbi()) { |
| 2808 | 2818 | d = fsg_ep_desc(fsg->gadget, |
| 2809 | − &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc); | |
| 2819 | + &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, | |
| 2820 | + &fsg_ss_intr_in_desc); | |
| 2810 | 2821 | if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) |
| 2811 | 2822 | goto reset; |
| 2812 | 2823 | fsg->intr_in_enabled = 1; |
| 2813 | 2824 | } |
| 2814 | 2825 | |
| 2815 | 2826 | /* Allocate the requests */ |
| 2816 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2827 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2817 | 2828 | struct fsg_buffhd *bh = &fsg->buffhds[i]; |
| 2818 | 2829 | |
| 2819 | 2830 | if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) |
| @@ -2862,17 +2873,10 @@ static int do_set_config(struct fsg_dev *fsg, u8 new_config) · 42 unmodified lines | ||
| 2862 | 2873 | fsg->config = new_config; |
| 2863 | 2874 | if ((rc = do_set_interface(fsg, 0)) != 0) |
| 2864 | 2875 | fsg->config = 0; // Reset on errors |
| 2865 | − else { | |
| 2866 | − char *speed; | |
| 2867 | − | |
| 2868 | − switch (fsg->gadget->speed) { | |
| 2869 | − case USB_SPEED_LOW: speed = "low"; break; | |
| 2870 | − case USB_SPEED_FULL: speed = "full"; break; | |
| 2871 | − case USB_SPEED_HIGH: speed = "high"; break; | |
| 2872 | − default: speed = "?"; break; | |
| 2873 | − } | |
| 2874 | − INFO(fsg, "%s speed config #%d\n", speed, fsg->config); | |
| 2875 | − } | |
| 2876 | + else | |
| 2877 | + INFO(fsg, "%s config #%d\n", | |
| 2878 | + usb_speed_string(fsg->gadget->speed), | |
| 2879 | + fsg->config); | |
| 2876 | 2880 | } |
| 2877 | 2881 | return rc; |
| 2878 | 2882 | } |
| @@ -2909,7 +2913,7 @@ static void handle_exception(struct fsg_dev *fsg) · 30 unmodified lines | ||
| 2909 | 2913 | /* Cancel all the pending transfers */ |
| 2910 | 2914 | if (fsg->intreq_busy) |
| 2911 | 2915 | usb_ep_dequeue(fsg->intr_in, fsg->intreq); |
| 2912 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2916 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2913 | 2917 | bh = &fsg->buffhds[i]; |
| 2914 | 2918 | if (bh->inreq_busy) |
| 2915 | 2919 | usb_ep_dequeue(fsg->bulk_in, bh->inreq); |
| @@ -2920,7 +2924,7 @@ static void handle_exception(struct fsg_dev *fsg) · 4 unmodified lines | ||
| 2920 | 2924 | /* Wait until everything is idle */ |
| 2921 | 2925 | for (;;) { |
| 2922 | 2926 | num_active = fsg->intreq_busy; |
| 2923 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2927 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2924 | 2928 | bh = &fsg->buffhds[i]; |
| 2925 | 2929 | num_active += bh->inreq_busy + bh->outreq_busy; |
| 2926 | 2930 | } |
| @@ -2942,7 +2946,7 @@ static void handle_exception(struct fsg_dev *fsg) · 15 unmodified lines | ||
| 2942 | 2946 | * state, and the exception. Then invoke the handler. */ |
| 2943 | 2947 | spin_lock_irq(&fsg->lock); |
| 2944 | 2948 | |
| 2945 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 2949 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 2946 | 2950 | bh = &fsg->buffhds[i]; |
| 2947 | 2951 | bh->state = BUF_STATE_EMPTY; |
| 2948 | 2952 | } |
| @@ -3149,6 +3153,15 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) · 200 unmodified lines | ||
| 3149 | 3153 | DBG(fsg, "unbind\n"); |
| 3150 | 3154 | clear_bit(REGISTERED, &fsg->atomic_bitflags); |
| 3151 | 3155 | |
| 3156 | + /* If the thread isn't already dead, tell it to exit now */ | |
| 3157 | + if (fsg->state != FSG_STATE_TERMINATED) { | |
| 3158 | + raise_exception(fsg, FSG_STATE_EXIT); | |
| 3159 | + wait_for_completion(&fsg->thread_notifier); | |
| 3160 | + | |
| 3161 | + /* The cleanup routine waits for this completion also */ | |
| 3162 | + complete(&fsg->thread_notifier); | |
| 3163 | + } | |
| 3164 | + | |
| 3152 | 3165 | /* Unregister the sysfs attribute files and the LUNs */ |
| 3153 | 3166 | for (i = 0; i < fsg->nluns; ++i) { |
| 3154 | 3167 | curlun = &fsg->luns[i]; |
| @@ -3162,17 +3175,8 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) · 7 unmodified lines | ||
| 3162 | 3175 | } |
| 3163 | 3176 | } |
| 3164 | 3177 | |
| 3165 | − /* If the thread isn't already dead, tell it to exit now */ | |
| 3166 | − if (fsg->state != FSG_STATE_TERMINATED) { | |
| 3167 | − raise_exception(fsg, FSG_STATE_EXIT); | |
| 3168 | − wait_for_completion(&fsg->thread_notifier); | |
| 3169 | − | |
| 3170 | − /* The cleanup routine waits for this completion also */ | |
| 3171 | − complete(&fsg->thread_notifier); | |
| 3172 | − } | |
| 3173 | − | |
| 3174 | 3178 | /* Free the data buffers */ |
| 3175 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) | |
| 3179 | + for (i = 0; i < fsg_num_buffers; ++i) | |
| 3176 | 3180 | kfree(fsg->buffhds[i].buf); |
| 3177 | 3181 | |
| 3178 | 3182 | /* Free the request and buffer for endpoint 0 */ |
| @@ -3445,6 +3449,24 @@ static int __init fsg_bind(struct usb_gadget *gadget) · 266 unmodified lines | ||
| 3445 | 3449 | fsg_fs_intr_in_desc.bEndpointAddress; |
| 3446 | 3450 | } |
| 3447 | 3451 | |
| 3452 | + if (gadget_is_superspeed(gadget)) { | |
| 3453 | + unsigned max_burst; | |
| 3454 | + | |
| 3455 | + fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; | |
| 3456 | + | |
| 3457 | + /* Calculate bMaxBurst, we know packet size is 1024 */ | |
| 3458 | + max_burst = min_t(unsigned, mod_data.buflen / 1024, 15); | |
| 3459 | + | |
| 3460 | + /* Assume endpoint addresses are the same for both speeds */ | |
| 3461 | + fsg_ss_bulk_in_desc.bEndpointAddress = | |
| 3462 | + fsg_fs_bulk_in_desc.bEndpointAddress; | |
| 3463 | + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; | |
| 3464 | + | |
| 3465 | + fsg_ss_bulk_out_desc.bEndpointAddress = | |
| 3466 | + fsg_fs_bulk_out_desc.bEndpointAddress; | |
| 3467 | + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; | |
| 3468 | + } | |
| 3469 | + | |
| 3448 | 3470 | if (gadget_is_otg(gadget)) |
| 3449 | 3471 | fsg_otg_desc.bmAttributes |= USB_OTG_HNP; |
| 3450 | 3472 | |
| @@ -3460,7 +3482,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) · 9 unmodified lines | ||
| 3460 | 3482 | req->complete = ep0_complete; |
| 3461 | 3483 | |
| 3462 | 3484 | /* Allocate the data buffers */ |
| 3463 | − for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | |
| 3485 | + for (i = 0; i < fsg_num_buffers; ++i) { | |
| 3464 | 3486 | struct fsg_buffhd *bh = &fsg->buffhds[i]; |
| 3465 | 3487 | |
| 3466 | 3488 | /* Allocate for the bulk-in endpoint. We assume that |
| @@ -3471,7 +3493,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) · 4 unmodified lines | ||
| 3471 | 3493 | goto out; |
| 3472 | 3494 | bh->next = bh + 1; |
| 3473 | 3495 | } |
| 3474 | − fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0]; | |
| 3496 | + fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0]; | |
| 3475 | 3497 | |
| 3476 | 3498 | /* This should reflect the actual gadget power source */ |
| 3477 | 3499 | usb_gadget_set_selfpowered(gadget); |
| @@ -3561,11 +3583,7 @@ static void fsg_resume(struct usb_gadget *gadget) · 83 unmodified lines | ||
| 3561 | 3583 | /*-------------------------------------------------------------------------*/ |
| 3562 | 3584 | |
| 3563 | 3585 | static struct usb_gadget_driver fsg_driver = { |
| 3564 | −#ifdef CONFIG_USB_GADGET_DUALSPEED | |
| 3565 | − .speed = USB_SPEED_HIGH, | |
| 3566 | −#else | |
| 3567 | − .speed = USB_SPEED_FULL, | |
| 3568 | −#endif | |
| 3586 | + .speed = USB_SPEED_SUPER, | |
| 3569 | 3587 | .function = (char *) fsg_string_product, |
| 3570 | 3588 | .unbind = fsg_unbind, |
| 3571 | 3589 | .disconnect = fsg_disconnect, |
| @@ -3587,7 +3605,9 @@ static int __init fsg_alloc(void) · 15 unmodified lines | ||
| 3587 | 3605 | { |
| 3588 | 3606 | struct fsg_dev *fsg; |
| 3589 | 3607 | |
| 3590 | − fsg = kzalloc(sizeof *fsg, GFP_KERNEL); | |
| 3608 | + fsg = kzalloc(sizeof *fsg + | |
| 3609 | + fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL); | |
| 3610 | + | |
| 3591 | 3611 | if (!fsg) |
| 3592 | 3612 | return -ENOMEM; |
| 3593 | 3613 | spin_lock_init(&fsg->lock); |
| @@ -3605,6 +3625,10 @@ static int __init fsg_init(void) · 11 unmodified lines | ||
| 3605 | 3625 | int rc; |
| 3606 | 3626 | struct fsg_dev *fsg; |
| 3607 | 3627 | |
| 3628 | + rc = fsg_num_buffers_validate(); | |
| 3629 | + if (rc != 0) | |
| 3630 | + return rc; | |
| 3631 | + | |
| 3608 | 3632 | if ((rc = fsg_alloc()) != 0) |
| 3609 | 3633 | return rc; |
| 3610 | 3634 | fsg = the_fsg; |
| @@ -540,7 +540,7 @@ static int qe_ep_init(struct qe_udc *udc, · 539 unmodified lines | ||
| 540 | 540 | int reval = 0; |
| 541 | 541 | u16 max = 0; |
| 542 | 542 | |
| 543 | − max = le16_to_cpu(desc->wMaxPacketSize); | |
| 543 | + max = usb_endpoint_maxp(desc); | |
| 544 | 544 | |
| 545 | 545 | /* check the max package size validate for this endpoint */ |
| 546 | 546 | /* Refer to USB2.0 spec table 9-13, |
| @@ -559,7 +559,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, · 558 unmodified lines | ||
| 559 | 559 | if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) |
| 560 | 560 | return -ESHUTDOWN; |
| 561 | 561 | |
| 562 | − max = le16_to_cpu(desc->wMaxPacketSize); | |
| 562 | + max = usb_endpoint_maxp(desc); | |
| 563 | 563 | |
| 564 | 564 | /* Disable automatic zlp generation. Driver is responsible to indicate |
| 565 | 565 | * explicitly through req->req.zero. This is needed to enable multi-td |
| @@ -1715,34 +1715,31 @@ static void dtd_complete_irq(struct fsl_udc *udc) · 1149 unmodified lines | ||
| 1715 | 1715 | } |
| 1716 | 1716 | } |
| 1717 | 1717 | |
| 1718 | +static inline enum usb_device_speed portscx_device_speed(u32 reg) | |
| 1719 | +{ | |
| 1720 | + switch (speed & PORTSCX_PORT_SPEED_MASK) { | |
| 1721 | + case PORTSCX_PORT_SPEED_HIGH: | |
| 1722 | + return USB_SPEED_HIGH; | |
| 1723 | + case PORTSCX_PORT_SPEED_FULL: | |
| 1724 | + return USB_SPEED_FULL; | |
| 1725 | + case PORTSCX_PORT_SPEED_LOW: | |
| 1726 | + return USB_SPEED_LOW; | |
| 1727 | + default: | |
| 1728 | + return USB_SPEED_UNKNOWN; | |
| 1729 | + } | |
| 1730 | +} | |
| 1731 | + | |
| 1718 | 1732 | /* Process a port change interrupt */ |
| 1719 | 1733 | static void port_change_irq(struct fsl_udc *udc) |
| 1720 | 1734 | { |
| 1721 | − u32 speed; | |
| 1722 | − | |
| 1723 | 1735 | if (udc->bus_reset) |
| 1724 | 1736 | udc->bus_reset = 0; |
| 1725 | 1737 | |
| 1726 | 1738 | /* Bus resetting is finished */ |
| 1727 | − if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { | |
| 1739 | + if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) | |
| 1728 | 1740 | /* Get the speed */ |
| 1729 | − speed = (fsl_readl(&dr_regs->portsc1) | |
| 1730 | − & PORTSCX_PORT_SPEED_MASK); | |
| 1731 | − switch (speed) { | |
| 1732 | − case PORTSCX_PORT_SPEED_HIGH: | |
| 1733 | − udc->gadget.speed = USB_SPEED_HIGH; | |
| 1734 | − break; | |
| 1735 | − case PORTSCX_PORT_SPEED_FULL: | |
| 1736 | − udc->gadget.speed = USB_SPEED_FULL; | |
| 1737 | − break; | |
| 1738 | − case PORTSCX_PORT_SPEED_LOW: | |
| 1739 | − udc->gadget.speed = USB_SPEED_LOW; | |
| 1740 | − break; | |
| 1741 | − default: | |
| 1742 | − udc->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1743 | − break; | |
| 1744 | − } | |
| 1745 | − } | |
| 1741 | + udc->gadget.speed = | |
| 1742 | + portscx_device_speed(fsl_readl(&dr_regs->portsc1)); | |
| 1746 | 1743 | |
| 1747 | 1744 | /* Update USB state */ |
| 1748 | 1745 | if (!udc->resume_state) |
| @@ -2167,20 +2164,8 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, · 418 unmodified lines | ||
| 2167 | 2164 | default: |
| 2168 | 2165 | s = "None"; break; |
| 2169 | 2166 | } |
| 2170 | − s;} ), ( { | |
| 2171 | − char *s; | |
| 2172 | − switch (tmp_reg & PORTSCX_PORT_SPEED_UNDEF) { | |
| 2173 | − case PORTSCX_PORT_SPEED_FULL: | |
| 2174 | − s = "Full Speed"; break; | |
| 2175 | − case PORTSCX_PORT_SPEED_LOW: | |
| 2176 | − s = "Low Speed"; break; | |
| 2177 | − case PORTSCX_PORT_SPEED_HIGH: | |
| 2178 | − s = "High Speed"; break; | |
| 2179 | − default: | |
| 2180 | − s = "Undefined"; break; | |
| 2181 | − } | |
| 2182 | − s; | |
| 2183 | − } ), | |
| 2167 | + s;} ), | |
| 2168 | + usb_speed_string(portscx_device_speed(tmp_reg)), | |
| 2184 | 2169 | (tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ? |
| 2185 | 2170 | "Normal PHY mode" : "Low power mode", |
| 2186 | 2171 | (tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" : |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | #include <linux/dma-mapping.h> |
| 23 | 13 | #include <linux/err.h> |
| @@ -220,7 +210,7 @@ static int config_ep(struct fusb300_ep *ep, · 196 unmodified lines | ||
| 220 | 210 | |
| 221 | 211 | info.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; |
| 222 | 212 | info.dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0; |
| 223 | − info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 213 | + info.maxpacket = usb_endpoint_maxp(desc); | |
| 224 | 214 | info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
| 225 | 215 | |
| 226 | 216 | if ((info.type == USB_ENDPOINT_XFER_INT) || |
| @@ -1479,7 +1469,7 @@ static int __init fusb300_probe(struct platform_device *pdev) · 1252 unmodified lines | ||
| 1479 | 1469 | fusb300->gadget.name = udc_name; |
| 1480 | 1470 | fusb300->reg = reg; |
| 1481 | 1471 | |
| 1482 | − ret = request_irq(ires->start, fusb300_irq, IRQF_DISABLED | IRQF_SHARED, | |
| 1472 | + ret = request_irq(ires->start, fusb300_irq, IRQF_SHARED, | |
| 1483 | 1473 | udc_name, fusb300); |
| 1484 | 1474 | if (ret < 0) { |
| 1485 | 1475 | pr_err("request_irq error (%d)\n", ret); |
| @@ -1487,7 +1477,7 @@ static int __init fusb300_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 1487 | 1477 | } |
| 1488 | 1478 | |
| 1489 | 1479 | ret = request_irq(ires1->start, fusb300_irq, |
| 1490 | − IRQF_DISABLED | IRQF_SHARED, udc_name, fusb300); | |
| 1480 | + IRQF_SHARED, udc_name, fusb300); | |
| 1491 | 1481 | if (ret < 0) { |
| 1492 | 1482 | pr_err("request_irq1 error (%d)\n", ret); |
| 1493 | 1483 | goto clean_up; |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | #define pr_fmt(fmt) "g_ffs: " fmt |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) |
| 32 | 32 | #define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name)) |
| 33 | 33 | #define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name)) |
| 34 | +#define gadget_is_dwc3(g) (!strcmp("dwc3-gadget", (g)->name)) | |
| 34 | 35 | #define gadget_is_fsl_qe(g) (!strcmp("fsl_qe_udc", (g)->name)) |
| 35 | 36 | #define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name)) |
| 36 | 37 | #define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) |
| @@ -115,6 +116,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) · 78 unmodified lines | ||
| 115 | 116 | return 0x30; |
| 116 | 117 | else if (gadget_is_net2272(gadget)) |
| 117 | 118 | return 0x31; |
| 119 | + else if (gadget_is_dwc3(gadget)) | |
| 120 | + return 0x32; | |
| 118 | 121 | |
| 119 | 122 | return -ENOENT; |
| 120 | 123 | } |
| @@ -36,134 +36,43 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #include "gadget_chips.h" |
| 38 | 38 | |
| 39 | − | |
| 40 | −/* | |
| 41 | − * Kbuild is not very cooperative with respect to linking separately | |
| 42 | − * compiled library objects into one module. So for now we won't use | |
| 43 | − * separate compilation ... ensuring init/exit sections work to shrink | |
| 44 | − * the runtime footprint, and giving us at least some parts of what | |
| 45 | − * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | |
| 46 | − */ | |
| 39 | +#include "composite.c" | |
| 47 | 40 | #include "usbstring.c" |
| 48 | 41 | #include "config.c" |
| 49 | 42 | #include "epautoconf.c" |
| 43 | +#include "f_midi.c" | |
| 50 | 44 | |
| 51 | 45 | /*-------------------------------------------------------------------------*/ |
| 52 | 46 | |
| 53 | − | |
| 54 | 47 | MODULE_AUTHOR("Ben Williamson"); |
| 55 | 48 | MODULE_LICENSE("GPL v2"); |
| 56 | 49 | |
| 57 | −#define DRIVER_VERSION "25 Jul 2006" | |
| 58 | − | |
| 59 | 50 | static const char shortname[] = "g_midi"; |
| 60 | 51 | static const char longname[] = "MIDI Gadget"; |
| 61 | 52 | |
| 62 | 53 | static int index = SNDRV_DEFAULT_IDX1; |
| 63 | −static char *id = SNDRV_DEFAULT_STR1; | |
| 64 | − | |
| 65 | −module_param(index, int, 0444); | |
| 54 | +module_param(index, int, S_IRUGO); | |
| 66 | 55 | MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter."); |
| 67 | −module_param(id, charp, 0444); | |
| 68 | −MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter."); | |
| 69 | − | |
| 70 | −/* Some systems will want different product identifiers published in the | |
| 71 | − * device descriptor, either numbers or strings or both. These string | |
| 72 | − * parameters are in UTF-8 (superset of ASCII's 7 bit characters). | |
| 73 | − */ | |
| 74 | − | |
| 75 | −static ushort idVendor; | |
| 76 | −module_param(idVendor, ushort, S_IRUGO); | |
| 77 | −MODULE_PARM_DESC(idVendor, "USB Vendor ID"); | |
| 78 | − | |
| 79 | −static ushort idProduct; | |
| 80 | −module_param(idProduct, ushort, S_IRUGO); | |
| 81 | −MODULE_PARM_DESC(idProduct, "USB Product ID"); | |
| 82 | − | |
| 83 | −static ushort bcdDevice; | |
| 84 | −module_param(bcdDevice, ushort, S_IRUGO); | |
| 85 | −MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); | |
| 86 | − | |
| 87 | −static char *iManufacturer; | |
| 88 | −module_param(iManufacturer, charp, S_IRUGO); | |
| 89 | −MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); | |
| 90 | − | |
| 91 | −static char *iProduct; | |
| 92 | −module_param(iProduct, charp, S_IRUGO); | |
| 93 | −MODULE_PARM_DESC(iProduct, "USB Product string"); | |
| 94 | − | |
| 95 | −static char *iSerialNumber; | |
| 96 | −module_param(iSerialNumber, charp, S_IRUGO); | |
| 97 | −MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); | |
| 98 | − | |
| 99 | −/* | |
| 100 | − * this version autoconfigures as much as possible, | |
| 101 | − * which is reasonable for most "bulk-only" drivers. | |
| 102 | − */ | |
| 103 | −static const char *EP_IN_NAME; | |
| 104 | −static const char *EP_OUT_NAME; | |
| 105 | 56 | |
| 57 | +static char *id = SNDRV_DEFAULT_STR1; | |
| 58 | +module_param(id, charp, S_IRUGO); | |
| 59 | +MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter."); | |
| 106 | 60 | |
| 107 | −/* big enough to hold our biggest descriptor */ | |
| 108 | −#define USB_BUFSIZ 256 | |
| 109 | − | |
| 110 | − | |
| 111 | −/* This is a gadget, and the IN/OUT naming is from the host's perspective. | |
| 112 | − USB -> OUT endpoint -> rawmidi | |
| 113 | − USB <- IN endpoint <- rawmidi */ | |
| 114 | −struct gmidi_in_port { | |
| 115 | − struct gmidi_device* dev; | |
| 116 | − int active; | |
| 117 | − uint8_t cable; /* cable number << 4 */ | |
| 118 | − uint8_t state; | |
| 119 | −#define STATE_UNKNOWN 0 | |
| 120 | −#define STATE_1PARAM 1 | |
| 121 | −#define STATE_2PARAM_1 2 | |
| 122 | −#define STATE_2PARAM_2 3 | |
| 123 | −#define STATE_SYSEX_0 4 | |
| 124 | −#define STATE_SYSEX_1 5 | |
| 125 | −#define STATE_SYSEX_2 6 | |
| 126 | − uint8_t data[2]; | |
| 127 | −}; | |
| 128 | − | |
| 129 | −struct gmidi_device { | |
| 130 | − spinlock_t lock; | |
| 131 | − struct usb_gadget *gadget; | |
| 132 | − struct usb_request *req; /* for control responses */ | |
| 133 | − u8 config; | |
| 134 | − struct usb_ep *in_ep, *out_ep; | |
| 135 | − struct snd_card *card; | |
| 136 | − struct snd_rawmidi *rmidi; | |
| 137 | − struct snd_rawmidi_substream *in_substream; | |
| 138 | − struct snd_rawmidi_substream *out_substream; | |
| 139 | − | |
| 140 | − /* For the moment we only support one port in | |
| 141 | − each direction, but in_port is kept as a | |
| 142 | − separate struct so we can have more later. */ | |
| 143 | − struct gmidi_in_port in_port; | |
| 144 | − unsigned long out_triggered; | |
| 145 | − struct tasklet_struct tasklet; | |
| 146 | −}; | |
| 147 | − | |
| 148 | −static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); | |
| 149 | − | |
| 150 | − | |
| 151 | −#define DBG(d, fmt, args...) \ | |
| 152 | − dev_dbg(&(d)->gadget->dev , fmt , ## args) | |
| 153 | −#define VDBG(d, fmt, args...) \ | |
| 154 | − dev_vdbg(&(d)->gadget->dev , fmt , ## args) | |
| 155 | −#define ERROR(d, fmt, args...) \ | |
| 156 | − dev_err(&(d)->gadget->dev , fmt , ## args) | |
| 157 | −#define INFO(d, fmt, args...) \ | |
| 158 | − dev_info(&(d)->gadget->dev , fmt , ## args) | |
| 159 | − | |
| 160 | − | |
| 161 | −static unsigned buflen = 256; | |
| 162 | −static unsigned qlen = 32; | |
| 163 | − | |
| 61 | +static unsigned int buflen = 256; | |
| 164 | 62 | module_param(buflen, uint, S_IRUGO); |
| 63 | +MODULE_PARM_DESC(buflen, "MIDI buffer length"); | |
| 64 | + | |
| 65 | +static unsigned int qlen = 32; | |
| 165 | 66 | module_param(qlen, uint, S_IRUGO); |
| 67 | +MODULE_PARM_DESC(qlen, "USB read request queue length"); | |
| 166 | 68 | |
| 69 | +static unsigned int in_ports = 1; | |
| 70 | +module_param(in_ports, uint, S_IRUGO); | |
| 71 | +MODULE_PARM_DESC(in_ports, "Number of MIDI input ports"); | |
| 72 | + | |
| 73 | +static unsigned int out_ports = 1; | |
| 74 | +module_param(out_ports, uint, S_IRUGO); | |
| 75 | +MODULE_PARM_DESC(out_ports, "Number of MIDI output ports"); | |
| 167 | 76 | |
| 168 | 77 | /* Thanks to Grey Innovation for donating this product ID. |
| 169 | 78 | * |
| @@ -173,1149 +82,124 @@ module_param(qlen, uint, S_IRUGO); · 3 unmodified lines | ||
| 173 | 82 | #define DRIVER_VENDOR_NUM 0x17b3 /* Grey Innovation */ |
| 174 | 83 | #define DRIVER_PRODUCT_NUM 0x0004 /* Linux-USB "MIDI Gadget" */ |
| 175 | 84 | |
| 85 | +/* string IDs are assigned dynamically */ | |
| 176 | 86 | |
| 177 | −/* | |
| 178 | − * DESCRIPTORS ... most are static, but strings and (full) | |
| 179 | − * configuration descriptors are built on demand. | |
| 180 | − */ | |
| 181 | − | |
| 182 | −#define STRING_MANUFACTURER 25 | |
| 183 | −#define STRING_PRODUCT 42 | |
| 184 | −#define STRING_SERIAL 101 | |
| 185 | −#define STRING_MIDI_GADGET 250 | |
| 87 | +#define STRING_MANUFACTURER_IDX 0 | |
| 88 | +#define STRING_PRODUCT_IDX 1 | |
| 89 | +#define STRING_DESCRIPTION_IDX 2 | |
| 186 | 90 | |
| 187 | −/* We only have the one configuration, it's number 1. */ | |
| 188 | −#define GMIDI_CONFIG 1 | |
| 189 | − | |
| 190 | −/* We have two interfaces- AudioControl and MIDIStreaming */ | |
| 191 | −#define GMIDI_AC_INTERFACE 0 | |
| 192 | −#define GMIDI_MS_INTERFACE 1 | |
| 193 | −#define GMIDI_NUM_INTERFACES 2 | |
| 194 | − | |
| 195 | −DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); | |
| 196 | −DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | |
| 197 | −DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); | |
| 198 | − | |
| 199 | −/* B.1 Device Descriptor */ | |
| 200 | 91 | static struct usb_device_descriptor device_desc = { |
| 201 | 92 | .bLength = USB_DT_DEVICE_SIZE, |
| 202 | 93 | .bDescriptorType = USB_DT_DEVICE, |
| 203 | − .bcdUSB = cpu_to_le16(0x0200), | |
| 94 | + .bcdUSB = __constant_cpu_to_le16(0x0200), | |
| 204 | 95 | .bDeviceClass = USB_CLASS_PER_INTERFACE, |
| 205 | − .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), | |
| 206 | − .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), | |
| 207 | − .iManufacturer = STRING_MANUFACTURER, | |
| 208 | − .iProduct = STRING_PRODUCT, | |
| 96 | + .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), | |
| 97 | + .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), | |
| 98 | + /* .iManufacturer = DYNAMIC */ | |
| 99 | + /* .iProduct = DYNAMIC */ | |
| 209 | 100 | .bNumConfigurations = 1, |
| 210 | 101 | }; |
| 211 | 102 | |
| 212 | −/* B.2 Configuration Descriptor */ | |
| 213 | −static struct usb_config_descriptor config_desc = { | |
| 214 | − .bLength = USB_DT_CONFIG_SIZE, | |
| 215 | − .bDescriptorType = USB_DT_CONFIG, | |
| 216 | − /* compute wTotalLength on the fly */ | |
| 217 | − .bNumInterfaces = GMIDI_NUM_INTERFACES, | |
| 218 | − .bConfigurationValue = GMIDI_CONFIG, | |
| 219 | − .iConfiguration = STRING_MIDI_GADGET, | |
| 220 | − /* | |
| 221 | − * FIXME: When embedding this driver in a device, | |
| 222 | − * these need to be set to reflect the actual | |
| 223 | − * power properties of the device. Is it selfpowered? | |
| 224 | − */ | |
| 225 | − .bmAttributes = USB_CONFIG_ATT_ONE, | |
| 226 | − .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, | |
| 227 | −}; | |
| 228 | − | |
| 229 | −/* B.3.1 Standard AC Interface Descriptor */ | |
| 230 | −static const struct usb_interface_descriptor ac_interface_desc = { | |
| 231 | − .bLength = USB_DT_INTERFACE_SIZE, | |
| 232 | − .bDescriptorType = USB_DT_INTERFACE, | |
| 233 | − .bInterfaceNumber = GMIDI_AC_INTERFACE, | |
| 234 | − .bNumEndpoints = 0, | |
| 235 | − .bInterfaceClass = USB_CLASS_AUDIO, | |
| 236 | − .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | |
| 237 | − .iInterface = STRING_MIDI_GADGET, | |
| 238 | −}; | |
| 239 | − | |
| 240 | −/* B.3.2 Class-Specific AC Interface Descriptor */ | |
| 241 | −static const struct uac1_ac_header_descriptor_1 ac_header_desc = { | |
| 242 | − .bLength = UAC_DT_AC_HEADER_SIZE(1), | |
| 243 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 244 | − .bDescriptorSubtype = USB_MS_HEADER, | |
| 245 | − .bcdADC = cpu_to_le16(0x0100), | |
| 246 | − .wTotalLength = cpu_to_le16(UAC_DT_AC_HEADER_SIZE(1)), | |
| 247 | − .bInCollection = 1, | |
| 248 | − .baInterfaceNr = { | |
| 249 | − [0] = GMIDI_MS_INTERFACE, | |
| 250 | − } | |
| 251 | −}; | |
| 252 | − | |
| 253 | −/* B.4.1 Standard MS Interface Descriptor */ | |
| 254 | −static const struct usb_interface_descriptor ms_interface_desc = { | |
| 255 | − .bLength = USB_DT_INTERFACE_SIZE, | |
| 256 | − .bDescriptorType = USB_DT_INTERFACE, | |
| 257 | − .bInterfaceNumber = GMIDI_MS_INTERFACE, | |
| 258 | − .bNumEndpoints = 2, | |
| 259 | − .bInterfaceClass = USB_CLASS_AUDIO, | |
| 260 | − .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, | |
| 261 | − .iInterface = STRING_MIDI_GADGET, | |
| 103 | +static struct usb_string strings_dev[] = { | |
| 104 | + [STRING_MANUFACTURER_IDX].s = "Grey Innovation", | |
| 105 | + [STRING_PRODUCT_IDX].s = "MIDI Gadget", | |
| 106 | + [STRING_DESCRIPTION_IDX].s = "MIDI", | |
| 107 | + { } /* end of list */ | |
| 262 | 108 | }; |
| 263 | 109 | |
| 264 | −/* B.4.2 Class-Specific MS Interface Descriptor */ | |
| 265 | −static const struct usb_ms_header_descriptor ms_header_desc = { | |
| 266 | − .bLength = USB_DT_MS_HEADER_SIZE, | |
| 267 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 268 | − .bDescriptorSubtype = USB_MS_HEADER, | |
| 269 | − .bcdMSC = cpu_to_le16(0x0100), | |
| 270 | − .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE | |
| 271 | − + 2*USB_DT_MIDI_IN_SIZE | |
| 272 | − + 2*USB_DT_MIDI_OUT_SIZE(1)), | |
| 273 | −}; | |
| 274 | − | |
| 275 | −#define JACK_IN_EMB 1 | |
| 276 | −#define JACK_IN_EXT 2 | |
| 277 | −#define JACK_OUT_EMB 3 | |
| 278 | −#define JACK_OUT_EXT 4 | |
| 279 | − | |
| 280 | −/* B.4.3 MIDI IN Jack Descriptors */ | |
| 281 | −static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = { | |
| 282 | − .bLength = USB_DT_MIDI_IN_SIZE, | |
| 283 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 284 | − .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, | |
| 285 | − .bJackType = USB_MS_EMBEDDED, | |
| 286 | − .bJackID = JACK_IN_EMB, | |
| 287 | −}; | |
| 288 | − | |
| 289 | −static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = { | |
| 290 | − .bLength = USB_DT_MIDI_IN_SIZE, | |
| 291 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 292 | − .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, | |
| 293 | − .bJackType = USB_MS_EXTERNAL, | |
| 294 | − .bJackID = JACK_IN_EXT, | |
| 295 | −}; | |
| 296 | − | |
| 297 | −/* B.4.4 MIDI OUT Jack Descriptors */ | |
| 298 | −static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = { | |
| 299 | − .bLength = USB_DT_MIDI_OUT_SIZE(1), | |
| 300 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 301 | − .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, | |
| 302 | − .bJackType = USB_MS_EMBEDDED, | |
| 303 | − .bJackID = JACK_OUT_EMB, | |
| 304 | − .bNrInputPins = 1, | |
| 305 | − .pins = { | |
| 306 | − [0] = { | |
| 307 | − .baSourceID = JACK_IN_EXT, | |
| 308 | − .baSourcePin = 1, | |
| 309 | − } | |
| 310 | − } | |
| 311 | −}; | |
| 312 | − | |
| 313 | −static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = { | |
| 314 | − .bLength = USB_DT_MIDI_OUT_SIZE(1), | |
| 315 | − .bDescriptorType = USB_DT_CS_INTERFACE, | |
| 316 | − .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, | |
| 317 | − .bJackType = USB_MS_EXTERNAL, | |
| 318 | − .bJackID = JACK_OUT_EXT, | |
| 319 | − .bNrInputPins = 1, | |
| 320 | − .pins = { | |
| 321 | − [0] = { | |
| 322 | − .baSourceID = JACK_IN_EMB, | |
| 323 | − .baSourcePin = 1, | |
| 324 | − } | |
| 325 | − } | |
| 326 | −}; | |
| 327 | − | |
| 328 | −/* B.5.1 Standard Bulk OUT Endpoint Descriptor */ | |
| 329 | −static struct usb_endpoint_descriptor bulk_out_desc = { | |
| 330 | − .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
| 331 | − .bDescriptorType = USB_DT_ENDPOINT, | |
| 332 | − .bEndpointAddress = USB_DIR_OUT, | |
| 333 | − .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 334 | −}; | |
| 335 | − | |
| 336 | −/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */ | |
| 337 | −static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = { | |
| 338 | − .bLength = USB_DT_MS_ENDPOINT_SIZE(1), | |
| 339 | − .bDescriptorType = USB_DT_CS_ENDPOINT, | |
| 340 | − .bDescriptorSubtype = USB_MS_GENERAL, | |
| 341 | − .bNumEmbMIDIJack = 1, | |
| 342 | − .baAssocJackID = { | |
| 343 | − [0] = JACK_IN_EMB, | |
| 344 | − } | |
| 345 | −}; | |
| 346 | − | |
| 347 | −/* B.6.1 Standard Bulk IN Endpoint Descriptor */ | |
| 348 | −static struct usb_endpoint_descriptor bulk_in_desc = { | |
| 349 | − .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
| 350 | − .bDescriptorType = USB_DT_ENDPOINT, | |
| 351 | − .bEndpointAddress = USB_DIR_IN, | |
| 352 | − .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 353 | −}; | |
| 354 | − | |
| 355 | −/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */ | |
| 356 | −static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = { | |
| 357 | − .bLength = USB_DT_MS_ENDPOINT_SIZE(1), | |
| 358 | − .bDescriptorType = USB_DT_CS_ENDPOINT, | |
| 359 | − .bDescriptorSubtype = USB_MS_GENERAL, | |
| 360 | − .bNumEmbMIDIJack = 1, | |
| 361 | − .baAssocJackID = { | |
| 362 | − [0] = JACK_OUT_EMB, | |
| 363 | − } | |
| 364 | −}; | |
| 365 | − | |
| 366 | −static const struct usb_descriptor_header *gmidi_function [] = { | |
| 367 | − (struct usb_descriptor_header *)&ac_interface_desc, | |
| 368 | − (struct usb_descriptor_header *)&ac_header_desc, | |
| 369 | − (struct usb_descriptor_header *)&ms_interface_desc, | |
| 370 | − | |
| 371 | − (struct usb_descriptor_header *)&ms_header_desc, | |
| 372 | − (struct usb_descriptor_header *)&jack_in_emb_desc, | |
| 373 | − (struct usb_descriptor_header *)&jack_in_ext_desc, | |
| 374 | − (struct usb_descriptor_header *)&jack_out_emb_desc, | |
| 375 | − (struct usb_descriptor_header *)&jack_out_ext_desc, | |
| 376 | − /* If you add more jacks, update ms_header_desc.wTotalLength */ | |
| 377 | − | |
| 378 | − (struct usb_descriptor_header *)&bulk_out_desc, | |
| 379 | − (struct usb_descriptor_header *)&ms_out_desc, | |
| 380 | − (struct usb_descriptor_header *)&bulk_in_desc, | |
| 381 | − (struct usb_descriptor_header *)&ms_in_desc, | |
| 382 | − NULL, | |
| 383 | −}; | |
| 384 | − | |
| 385 | −static char manufacturer[50]; | |
| 386 | −static char product_desc[40] = "MIDI Gadget"; | |
| 387 | −static char serial_number[20]; | |
| 388 | − | |
| 389 | −/* static strings, in UTF-8 */ | |
| 390 | −static struct usb_string strings [] = { | |
| 391 | − { STRING_MANUFACTURER, manufacturer, }, | |
| 392 | − { STRING_PRODUCT, product_desc, }, | |
| 393 | − { STRING_SERIAL, serial_number, }, | |
| 394 | − { STRING_MIDI_GADGET, longname, }, | |
| 395 | − { } /* end of list */ | |
| 396 | −}; | |
| 397 | − | |
| 398 | −static struct usb_gadget_strings stringtab = { | |
| 110 | +static struct usb_gadget_strings stringtab_dev = { | |
| 399 | 111 | .language = 0x0409, /* en-us */ |
| 400 | − .strings = strings, | |
| 112 | + .strings = strings_dev, | |
| 401 | 113 | }; |
| 402 | 114 | |
| 403 | −static int config_buf(struct usb_gadget *gadget, | |
| 404 | − u8 *buf, u8 type, unsigned index) | |
| 405 | −{ | |
| 406 | − int len; | |
| 407 | − | |
| 408 | − /* only one configuration */ | |
| 409 | − if (index != 0) { | |
| 410 | − return -EINVAL; | |
| 411 | − } | |
| 412 | − len = usb_gadget_config_buf(&config_desc, | |
| 413 | − buf, USB_BUFSIZ, gmidi_function); | |
| 414 | − if (len < 0) { | |
| 415 | − return len; | |
| 416 | − } | |
| 417 | − ((struct usb_config_descriptor *)buf)->bDescriptorType = type; | |
| 418 | − return len; | |
| 419 | −} | |
| 420 | − | |
| 421 | −static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) | |
| 422 | −{ | |
| 423 | − struct usb_request *req; | |
| 424 | − | |
| 425 | − req = usb_ep_alloc_request(ep, GFP_ATOMIC); | |
| 426 | − if (req) { | |
| 427 | − req->length = length; | |
| 428 | − req->buf = kmalloc(length, GFP_ATOMIC); | |
| 429 | − if (!req->buf) { | |
| 430 | − usb_ep_free_request(ep, req); | |
| 431 | − req = NULL; | |
| 432 | − } | |
| 433 | − } | |
| 434 | − return req; | |
| 435 | −} | |
| 436 | − | |
| 437 | −static void free_ep_req(struct usb_ep *ep, struct usb_request *req) | |
| 438 | −{ | |
| 439 | − kfree(req->buf); | |
| 440 | − usb_ep_free_request(ep, req); | |
| 441 | −} | |
| 442 | − | |
| 443 | −static const uint8_t gmidi_cin_length[] = { | |
| 444 | − 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | |
| 115 | +static struct usb_gadget_strings *dev_strings[] = { | |
| 116 | + &stringtab_dev, | |
| 117 | + NULL, | |
| 445 | 118 | }; |
| 446 | 119 | |
| 447 | −/* | |
| 448 | − * Receives a chunk of MIDI data. | |
| 449 | − */ | |
| 450 | −static void gmidi_read_data(struct usb_ep *ep, int cable, | |
| 451 | − uint8_t *data, int length) | |
| 452 | −{ | |
| 453 | − struct gmidi_device *dev = ep->driver_data; | |
| 454 | − /* cable is ignored, because for now we only have one. */ | |
| 455 | − | |
| 456 | − if (!dev->out_substream) { | |
| 457 | − /* Nobody is listening - throw it on the floor. */ | |
| 458 | − return; | |
| 459 | − } | |
| 460 | − if (!test_bit(dev->out_substream->number, &dev->out_triggered)) { | |
| 461 | − return; | |
| 462 | − } | |
| 463 | − snd_rawmidi_receive(dev->out_substream, data, length); | |
| 464 | −} | |
| 465 | − | |
| 466 | −static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req) | |
| 467 | −{ | |
| 468 | − unsigned i; | |
| 469 | − u8 *buf = req->buf; | |
| 470 | − | |
| 471 | − for (i = 0; i + 3 < req->actual; i += 4) { | |
| 472 | − if (buf[i] != 0) { | |
| 473 | − int cable = buf[i] >> 4; | |
| 474 | − int length = gmidi_cin_length[buf[i] & 0x0f]; | |
| 475 | − gmidi_read_data(ep, cable, &buf[i + 1], length); | |
| 476 | − } | |
| 477 | − } | |
| 478 | −} | |
| 479 | − | |
| 480 | −static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) | |
| 481 | −{ | |
| 482 | − struct gmidi_device *dev = ep->driver_data; | |
| 483 | − int status = req->status; | |
| 484 | − | |
| 485 | − switch (status) { | |
| 486 | − case 0: /* normal completion */ | |
| 487 | − if (ep == dev->out_ep) { | |
| 488 | − /* we received stuff. | |
| 489 | − req is queued again, below */ | |
| 490 | − gmidi_handle_out_data(ep, req); | |
| 491 | − } else if (ep == dev->in_ep) { | |
| 492 | − /* our transmit completed. | |
| 493 | − see if there's more to go. | |
| 494 | − gmidi_transmit eats req, don't queue it again. */ | |
| 495 | − gmidi_transmit(dev, req); | |
| 496 | − return; | |
| 497 | − } | |
| 498 | − break; | |
| 499 | − | |
| 500 | − /* this endpoint is normally active while we're configured */ | |
| 501 | − case -ECONNABORTED: /* hardware forced ep reset */ | |
| 502 | − case -ECONNRESET: /* request dequeued */ | |
| 503 | − case -ESHUTDOWN: /* disconnect from host */ | |
| 504 | − VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, | |
| 505 | − req->actual, req->length); | |
| 506 | − if (ep == dev->out_ep) { | |
| 507 | − gmidi_handle_out_data(ep, req); | |
| 508 | − } | |
| 509 | − free_ep_req(ep, req); | |
| 510 | − return; | |
| 511 | − | |
| 512 | − case -EOVERFLOW: /* buffer overrun on read means that | |
| 513 | − * we didn't provide a big enough | |
| 514 | − * buffer. | |
| 515 | − */ | |
| 516 | − default: | |
| 517 | − DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, | |
| 518 | − status, req->actual, req->length); | |
| 519 | − break; | |
| 520 | − case -EREMOTEIO: /* short read */ | |
| 521 | − break; | |
| 522 | − } | |
| 523 | − | |
| 524 | − status = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 525 | − if (status) { | |
| 526 | − ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", | |
| 527 | − ep->name, req->length, status); | |
| 528 | − usb_ep_set_halt(ep); | |
| 529 | − /* FIXME recover later ... somehow */ | |
| 530 | − } | |
| 531 | −} | |
| 532 | − | |
| 533 | −static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags) | |
| 534 | −{ | |
| 535 | − int err = 0; | |
| 536 | − struct usb_request *req; | |
| 537 | − struct usb_ep *ep; | |
| 538 | − unsigned i; | |
| 539 | − | |
| 540 | − dev->in_ep->desc = &bulk_in_desc; | |
| 541 | − err = usb_ep_enable(dev->in_ep); | |
| 542 | − if (err) { | |
| 543 | − ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err); | |
| 544 | − goto fail; | |
| 545 | − } | |
| 546 | − dev->in_ep->driver_data = dev; | |
| 547 | − | |
| 548 | − dev->out_ep->desc = &bulk_out_desc; | |
| 549 | − err = usb_ep_enable(dev->out_ep); | |
| 550 | − if (err) { | |
| 551 | − ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err); | |
| 552 | − goto fail; | |
| 553 | − } | |
| 554 | − dev->out_ep->driver_data = dev; | |
| 555 | − | |
| 556 | − /* allocate a bunch of read buffers and queue them all at once. */ | |
| 557 | − ep = dev->out_ep; | |
| 558 | − for (i = 0; i < qlen && err == 0; i++) { | |
| 559 | − req = alloc_ep_req(ep, buflen); | |
| 560 | − if (req) { | |
| 561 | − req->complete = gmidi_complete; | |
| 562 | − err = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 563 | − if (err) { | |
| 564 | − DBG(dev, "%s queue req: %d\n", ep->name, err); | |
| 565 | − } | |
| 566 | − } else { | |
| 567 | − err = -ENOMEM; | |
| 568 | − } | |
| 569 | − } | |
| 570 | −fail: | |
| 571 | − /* caller is responsible for cleanup on error */ | |
| 572 | − return err; | |
| 573 | −} | |
| 574 | − | |
| 575 | − | |
| 576 | −static void gmidi_reset_config(struct gmidi_device *dev) | |
| 577 | −{ | |
| 578 | − if (dev->config == 0) { | |
| 579 | − return; | |
| 580 | − } | |
| 581 | − | |
| 582 | − DBG(dev, "reset config\n"); | |
| 583 | − | |
| 584 | − /* just disable endpoints, forcing completion of pending i/o. | |
| 585 | − * all our completion handlers free their requests in this case. | |
| 586 | − */ | |
| 587 | − usb_ep_disable(dev->in_ep); | |
| 588 | − usb_ep_disable(dev->out_ep); | |
| 589 | − dev->config = 0; | |
| 590 | −} | |
| 591 | − | |
| 592 | −/* change our operational config. this code must agree with the code | |
| 593 | − * that returns config descriptors, and altsetting code. | |
| 594 | − * | |
| 595 | − * it's also responsible for power management interactions. some | |
| 596 | − * configurations might not work with our current power sources. | |
| 597 | − * | |
| 598 | − * note that some device controller hardware will constrain what this | |
| 599 | − * code can do, perhaps by disallowing more than one configuration or | |
| 600 | − * by limiting configuration choices (like the pxa2xx). | |
| 601 | − */ | |
| 602 | −static int | |
| 603 | −gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) | |
| 604 | −{ | |
| 605 | − int result = 0; | |
| 606 | − struct usb_gadget *gadget = dev->gadget; | |
| 607 | − | |
| 608 | −#if 0 | |
| 609 | − /* FIXME */ | |
| 610 | − /* Hacking this bit out fixes a bug where on receipt of two | |
| 611 | − USB_REQ_SET_CONFIGURATION messages, we end up with no | |
| 612 | − buffered OUT requests waiting for data. This is clearly | |
| 613 | − hiding a bug elsewhere, because if the config didn't | |
| 614 | − change then we really shouldn't do anything. */ | |
| 615 | − /* Having said that, when we do "change" from config 1 | |
| 616 | − to config 1, we at least gmidi_reset_config() which | |
| 617 | − clears out any requests on endpoints, so it's not like | |
| 618 | − we leak or anything. */ | |
| 619 | − if (number == dev->config) { | |
| 620 | − return 0; | |
| 621 | − } | |
| 622 | −#endif | |
| 623 | − | |
| 624 | − gmidi_reset_config(dev); | |
| 625 | − | |
| 626 | − switch (number) { | |
| 627 | − case GMIDI_CONFIG: | |
| 628 | − result = set_gmidi_config(dev, gfp_flags); | |
| 629 | − break; | |
| 630 | − default: | |
| 631 | − result = -EINVAL; | |
| 632 | − /* FALL THROUGH */ | |
| 633 | − case 0: | |
| 634 | − return result; | |
| 635 | − } | |
| 636 | − | |
| 637 | − if (!result && (!dev->in_ep || !dev->out_ep)) { | |
| 638 | − result = -ENODEV; | |
| 639 | − } | |
| 640 | − if (result) { | |
| 641 | − gmidi_reset_config(dev); | |
| 642 | − } else { | |
| 643 | − char *speed; | |
| 644 | − | |
| 645 | − switch (gadget->speed) { | |
| 646 | − case USB_SPEED_LOW: speed = "low"; break; | |
| 647 | − case USB_SPEED_FULL: speed = "full"; break; | |
| 648 | − case USB_SPEED_HIGH: speed = "high"; break; | |
| 649 | − default: speed = "?"; break; | |
| 650 | − } | |
| 651 | − | |
| 652 | − dev->config = number; | |
| 653 | − INFO(dev, "%s speed\n", speed); | |
| 654 | − } | |
| 655 | − return result; | |
| 656 | −} | |
| 657 | − | |
| 658 | − | |
| 659 | −static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req) | |
| 660 | −{ | |
| 661 | − if (req->status || req->actual != req->length) { | |
| 662 | − DBG((struct gmidi_device *) ep->driver_data, | |
| 663 | − "setup complete --> %d, %d/%d\n", | |
| 664 | − req->status, req->actual, req->length); | |
| 665 | − } | |
| 666 | −} | |
| 667 | − | |
| 668 | −/* | |
| 669 | − * The setup() callback implements all the ep0 functionality that's | |
| 670 | − * not handled lower down, in hardware or the hardware driver (like | |
| 671 | − * device and endpoint feature flags, and their status). It's all | |
| 672 | − * housekeeping for the gadget function we're implementing. Most of | |
| 673 | − * the work is in config-specific setup. | |
| 674 | − */ | |
| 675 | −static int gmidi_setup(struct usb_gadget *gadget, | |
| 676 | − const struct usb_ctrlrequest *ctrl) | |
| 677 | −{ | |
| 678 | − struct gmidi_device *dev = get_gadget_data(gadget); | |
| 679 | − struct usb_request *req = dev->req; | |
| 680 | − int value = -EOPNOTSUPP; | |
| 681 | − u16 w_index = le16_to_cpu(ctrl->wIndex); | |
| 682 | − u16 w_value = le16_to_cpu(ctrl->wValue); | |
| 683 | − u16 w_length = le16_to_cpu(ctrl->wLength); | |
| 684 | − | |
| 685 | − /* usually this stores reply data in the pre-allocated ep0 buffer, | |
| 686 | − * but config change events will reconfigure hardware. | |
| 687 | − */ | |
| 688 | − req->zero = 0; | |
| 689 | − switch (ctrl->bRequest) { | |
| 690 | − | |
| 691 | − case USB_REQ_GET_DESCRIPTOR: | |
| 692 | − if (ctrl->bRequestType != USB_DIR_IN) { | |
| 693 | − goto unknown; | |
| 694 | − } | |
| 695 | − switch (w_value >> 8) { | |
| 696 | − | |
| 697 | − case USB_DT_DEVICE: | |
| 698 | − device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; | |
| 699 | − value = min(w_length, (u16) sizeof(device_desc)); | |
| 700 | − memcpy(req->buf, &device_desc, value); | |
| 701 | − break; | |
| 702 | − case USB_DT_CONFIG: | |
| 703 | − value = config_buf(gadget, req->buf, | |
| 704 | − w_value >> 8, | |
| 705 | − w_value & 0xff); | |
| 706 | − if (value >= 0) { | |
| 707 | − value = min(w_length, (u16)value); | |
| 708 | − } | |
| 709 | − break; | |
| 710 | − | |
| 711 | − case USB_DT_STRING: | |
| 712 | − /* wIndex == language code. | |
| 713 | − * this driver only handles one language, you can | |
| 714 | − * add string tables for other languages, using | |
| 715 | − * any UTF-8 characters | |
| 716 | − */ | |
| 717 | − value = usb_gadget_get_string(&stringtab, | |
| 718 | − w_value & 0xff, req->buf); | |
| 719 | − if (value >= 0) { | |
| 720 | − value = min(w_length, (u16)value); | |
| 721 | − } | |
| 722 | − break; | |
| 723 | − } | |
| 724 | − break; | |
| 725 | − | |
| 726 | − /* currently two configs, two speeds */ | |
| 727 | − case USB_REQ_SET_CONFIGURATION: | |
| 728 | − if (ctrl->bRequestType != 0) { | |
| 729 | − goto unknown; | |
| 730 | − } | |
| 731 | − if (gadget->a_hnp_support) { | |
| 732 | − DBG(dev, "HNP available\n"); | |
| 733 | − } else if (gadget->a_alt_hnp_support) { | |
| 734 | − DBG(dev, "HNP needs a different root port\n"); | |
| 735 | − } else { | |
| 736 | − VDBG(dev, "HNP inactive\n"); | |
| 737 | − } | |
| 738 | − spin_lock(&dev->lock); | |
| 739 | − value = gmidi_set_config(dev, w_value, GFP_ATOMIC); | |
| 740 | − spin_unlock(&dev->lock); | |
| 741 | − break; | |
| 742 | − case USB_REQ_GET_CONFIGURATION: | |
| 743 | − if (ctrl->bRequestType != USB_DIR_IN) { | |
| 744 | − goto unknown; | |
| 745 | − } | |
| 746 | − *(u8 *)req->buf = dev->config; | |
| 747 | − value = min(w_length, (u16)1); | |
| 748 | − break; | |
| 749 | − | |
| 750 | − /* until we add altsetting support, or other interfaces, | |
| 751 | − * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) | |
| 752 | − * and already killed pending endpoint I/O. | |
| 753 | − */ | |
| 754 | − case USB_REQ_SET_INTERFACE: | |
| 755 | − if (ctrl->bRequestType != USB_RECIP_INTERFACE) { | |
| 756 | − goto unknown; | |
| 757 | − } | |
| 758 | − spin_lock(&dev->lock); | |
| 759 | − if (dev->config && w_index < GMIDI_NUM_INTERFACES | |
| 760 | − && w_value == 0) | |
| 761 | − { | |
| 762 | − u8 config = dev->config; | |
| 763 | − | |
| 764 | − /* resets interface configuration, forgets about | |
| 765 | − * previous transaction state (queued bufs, etc) | |
| 766 | − * and re-inits endpoint state (toggle etc) | |
| 767 | − * no response queued, just zero status == success. | |
| 768 | − * if we had more than one interface we couldn't | |
| 769 | − * use this "reset the config" shortcut. | |
| 770 | − */ | |
| 771 | − gmidi_reset_config(dev); | |
| 772 | − gmidi_set_config(dev, config, GFP_ATOMIC); | |
| 773 | − value = 0; | |
| 774 | − } | |
| 775 | − spin_unlock(&dev->lock); | |
| 776 | − break; | |
| 777 | − case USB_REQ_GET_INTERFACE: | |
| 778 | − if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) { | |
| 779 | − goto unknown; | |
| 780 | − } | |
| 781 | − if (!dev->config) { | |
| 782 | − break; | |
| 783 | − } | |
| 784 | − if (w_index >= GMIDI_NUM_INTERFACES) { | |
| 785 | − value = -EDOM; | |
| 786 | − break; | |
| 787 | − } | |
| 788 | − *(u8 *)req->buf = 0; | |
| 789 | − value = min(w_length, (u16)1); | |
| 790 | − break; | |
| 791 | − | |
| 792 | − default: | |
| 793 | −unknown: | |
| 794 | − VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", | |
| 795 | − ctrl->bRequestType, ctrl->bRequest, | |
| 796 | − w_value, w_index, w_length); | |
| 797 | − } | |
| 798 | − | |
| 799 | − /* respond with data transfer before status phase? */ | |
| 800 | − if (value >= 0) { | |
| 801 | − req->length = value; | |
| 802 | − req->zero = value < w_length; | |
| 803 | − value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); | |
| 804 | − if (value < 0) { | |
| 805 | − DBG(dev, "ep_queue --> %d\n", value); | |
| 806 | − req->status = 0; | |
| 807 | − gmidi_setup_complete(gadget->ep0, req); | |
| 808 | − } | |
| 809 | − } | |
| 810 | − | |
| 811 | − /* device either stalls (value < 0) or reports success */ | |
| 812 | − return value; | |
| 813 | −} | |
| 814 | − | |
| 815 | −static void gmidi_disconnect(struct usb_gadget *gadget) | |
| 816 | −{ | |
| 817 | − struct gmidi_device *dev = get_gadget_data(gadget); | |
| 818 | − unsigned long flags; | |
| 819 | − | |
| 820 | − spin_lock_irqsave(&dev->lock, flags); | |
| 821 | − gmidi_reset_config(dev); | |
| 822 | − | |
| 823 | − /* a more significant application might have some non-usb | |
| 824 | − * activities to quiesce here, saving resources like power | |
| 825 | − * or pushing the notification up a network stack. | |
| 826 | − */ | |
| 827 | − spin_unlock_irqrestore(&dev->lock, flags); | |
| 828 | − | |
| 829 | − /* next we may get setup() calls to enumerate new connections; | |
| 830 | − * or an unbind() during shutdown (including removing module). | |
| 831 | − */ | |
| 832 | −} | |
| 833 | − | |
| 834 | −static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget) | |
| 835 | −{ | |
| 836 | − struct gmidi_device *dev = get_gadget_data(gadget); | |
| 837 | − struct snd_card *card; | |
| 838 | − | |
| 839 | − DBG(dev, "unbind\n"); | |
| 840 | − | |
| 841 | − card = dev->card; | |
| 842 | − dev->card = NULL; | |
| 843 | − if (card) { | |
| 844 | − snd_card_free(card); | |
| 845 | − } | |
| 846 | − | |
| 847 | − /* we've already been disconnected ... no i/o is active */ | |
| 848 | − if (dev->req) { | |
| 849 | − dev->req->length = USB_BUFSIZ; | |
| 850 | − free_ep_req(gadget->ep0, dev->req); | |
| 851 | − } | |
| 852 | − kfree(dev); | |
| 853 | − set_gadget_data(gadget, NULL); | |
| 854 | −} | |
| 855 | − | |
| 856 | −static int gmidi_snd_free(struct snd_device *device) | |
| 120 | +static int __exit midi_unbind(struct usb_composite_dev *dev) | |
| 857 | 121 | { |
| 858 | 122 | return 0; |
| 859 | 123 | } |
| 860 | 124 | |
| 861 | −static void gmidi_transmit_packet(struct usb_request *req, uint8_t p0, | |
| 862 | − uint8_t p1, uint8_t p2, uint8_t p3) | |
| 863 | −{ | |
| 864 | − unsigned length = req->length; | |
| 865 | − u8 *buf = (u8 *)req->buf + length; | |
| 866 | − | |
| 867 | − buf[0] = p0; | |
| 868 | − buf[1] = p1; | |
| 869 | − buf[2] = p2; | |
| 870 | − buf[3] = p3; | |
| 871 | − req->length = length + 4; | |
| 872 | −} | |
| 873 | − | |
| 874 | −/* | |
| 875 | − * Converts MIDI commands to USB MIDI packets. | |
| 876 | − */ | |
| 877 | −static void gmidi_transmit_byte(struct usb_request *req, | |
| 878 | − struct gmidi_in_port *port, uint8_t b) | |
| 879 | −{ | |
| 880 | − uint8_t p0 = port->cable; | |
| 881 | − | |
| 882 | − if (b >= 0xf8) { | |
| 883 | − gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0); | |
| 884 | − } else if (b >= 0xf0) { | |
| 885 | − switch (b) { | |
| 886 | − case 0xf0: | |
| 887 | − port->data[0] = b; | |
| 888 | − port->state = STATE_SYSEX_1; | |
| 889 | − break; | |
| 890 | − case 0xf1: | |
| 891 | − case 0xf3: | |
| 892 | − port->data[0] = b; | |
| 893 | − port->state = STATE_1PARAM; | |
| 894 | − break; | |
| 895 | − case 0xf2: | |
| 896 | − port->data[0] = b; | |
| 897 | − port->state = STATE_2PARAM_1; | |
| 898 | − break; | |
| 899 | − case 0xf4: | |
| 900 | − case 0xf5: | |
| 901 | − port->state = STATE_UNKNOWN; | |
| 902 | − break; | |
| 903 | − case 0xf6: | |
| 904 | − gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0); | |
| 905 | − port->state = STATE_UNKNOWN; | |
| 906 | − break; | |
| 907 | − case 0xf7: | |
| 908 | − switch (port->state) { | |
| 909 | − case STATE_SYSEX_0: | |
| 910 | − gmidi_transmit_packet(req, | |
| 911 | − p0 | 0x05, 0xf7, 0, 0); | |
| 912 | − break; | |
| 913 | − case STATE_SYSEX_1: | |
| 914 | − gmidi_transmit_packet(req, | |
| 915 | − p0 | 0x06, port->data[0], 0xf7, 0); | |
| 916 | − break; | |
| 917 | − case STATE_SYSEX_2: | |
| 918 | − gmidi_transmit_packet(req, | |
| 919 | − p0 | 0x07, port->data[0], | |
| 920 | − port->data[1], 0xf7); | |
| 921 | − break; | |
| 922 | − } | |
| 923 | − port->state = STATE_UNKNOWN; | |
| 924 | − break; | |
| 925 | − } | |
| 926 | − } else if (b >= 0x80) { | |
| 927 | − port->data[0] = b; | |
| 928 | − if (b >= 0xc0 && b <= 0xdf) | |
| 929 | − port->state = STATE_1PARAM; | |
| 930 | − else | |
| 931 | − port->state = STATE_2PARAM_1; | |
| 932 | − } else { /* b < 0x80 */ | |
| 933 | − switch (port->state) { | |
| 934 | − case STATE_1PARAM: | |
| 935 | − if (port->data[0] < 0xf0) { | |
| 936 | − p0 |= port->data[0] >> 4; | |
| 937 | − } else { | |
| 938 | − p0 |= 0x02; | |
| 939 | − port->state = STATE_UNKNOWN; | |
| 940 | − } | |
| 941 | − gmidi_transmit_packet(req, p0, port->data[0], b, 0); | |
| 942 | − break; | |
| 943 | − case STATE_2PARAM_1: | |
| 944 | − port->data[1] = b; | |
| 945 | − port->state = STATE_2PARAM_2; | |
| 946 | − break; | |
| 947 | − case STATE_2PARAM_2: | |
| 948 | − if (port->data[0] < 0xf0) { | |
| 949 | − p0 |= port->data[0] >> 4; | |
| 950 | − port->state = STATE_2PARAM_1; | |
| 951 | − } else { | |
| 952 | − p0 |= 0x03; | |
| 953 | − port->state = STATE_UNKNOWN; | |
| 954 | − } | |
| 955 | − gmidi_transmit_packet(req, | |
| 956 | − p0, port->data[0], port->data[1], b); | |
| 957 | − break; | |
| 958 | − case STATE_SYSEX_0: | |
| 959 | − port->data[0] = b; | |
| 960 | − port->state = STATE_SYSEX_1; | |
| 961 | − break; | |
| 962 | − case STATE_SYSEX_1: | |
| 963 | − port->data[1] = b; | |
| 964 | − port->state = STATE_SYSEX_2; | |
| 965 | − break; | |
| 966 | − case STATE_SYSEX_2: | |
| 967 | − gmidi_transmit_packet(req, | |
| 968 | − p0 | 0x04, port->data[0], port->data[1], b); | |
| 969 | − port->state = STATE_SYSEX_0; | |
| 970 | − break; | |
| 971 | − } | |
| 972 | − } | |
| 973 | −} | |
| 974 | − | |
| 975 | −static void gmidi_transmit(struct gmidi_device *dev, struct usb_request *req) | |
| 976 | −{ | |
| 977 | − struct usb_ep *ep = dev->in_ep; | |
| 978 | − struct gmidi_in_port *port = &dev->in_port; | |
| 979 | − | |
| 980 | − if (!ep) { | |
| 981 | − return; | |
| 982 | − } | |
| 983 | − if (!req) { | |
| 984 | − req = alloc_ep_req(ep, buflen); | |
| 985 | − } | |
| 986 | − if (!req) { | |
| 987 | − ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n"); | |
| 988 | − return; | |
| 989 | − } | |
| 990 | − req->length = 0; | |
| 991 | − req->complete = gmidi_complete; | |
| 992 | − | |
| 993 | − if (port->active) { | |
| 994 | − while (req->length + 3 < buflen) { | |
| 995 | − uint8_t b; | |
| 996 | − if (snd_rawmidi_transmit(dev->in_substream, &b, 1) | |
| 997 | − != 1) | |
| 998 | − { | |
| 999 | − port->active = 0; | |
| 1000 | − break; | |
| 1001 | − } | |
| 1002 | − gmidi_transmit_byte(req, port, b); | |
| 1003 | − } | |
| 1004 | − } | |
| 1005 | − if (req->length > 0) { | |
| 1006 | − usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 1007 | − } else { | |
| 1008 | − free_ep_req(ep, req); | |
| 1009 | − } | |
| 1010 | −} | |
| 1011 | − | |
| 1012 | −static void gmidi_in_tasklet(unsigned long data) | |
| 1013 | −{ | |
| 1014 | − struct gmidi_device *dev = (struct gmidi_device *)data; | |
| 1015 | − | |
| 1016 | − gmidi_transmit(dev, NULL); | |
| 1017 | −} | |
| 1018 | − | |
| 1019 | −static int gmidi_in_open(struct snd_rawmidi_substream *substream) | |
| 1020 | −{ | |
| 1021 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1022 | − | |
| 1023 | − VDBG(dev, "gmidi_in_open\n"); | |
| 1024 | − dev->in_substream = substream; | |
| 1025 | − dev->in_port.state = STATE_UNKNOWN; | |
| 1026 | − return 0; | |
| 1027 | −} | |
| 1028 | − | |
| 1029 | −static int gmidi_in_close(struct snd_rawmidi_substream *substream) | |
| 1030 | −{ | |
| 1031 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1032 | − | |
| 1033 | − VDBG(dev, "gmidi_in_close\n"); | |
| 1034 | − return 0; | |
| 1035 | −} | |
| 1036 | − | |
| 1037 | −static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) | |
| 1038 | −{ | |
| 1039 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1040 | − | |
| 1041 | − VDBG(dev, "gmidi_in_trigger %d\n", up); | |
| 1042 | − dev->in_port.active = up; | |
| 1043 | − if (up) { | |
| 1044 | − tasklet_hi_schedule(&dev->tasklet); | |
| 1045 | − } | |
| 1046 | −} | |
| 1047 | − | |
| 1048 | −static int gmidi_out_open(struct snd_rawmidi_substream *substream) | |
| 1049 | −{ | |
| 1050 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1051 | − | |
| 1052 | − VDBG(dev, "gmidi_out_open\n"); | |
| 1053 | − dev->out_substream = substream; | |
| 1054 | − return 0; | |
| 1055 | −} | |
| 1056 | − | |
| 1057 | −static int gmidi_out_close(struct snd_rawmidi_substream *substream) | |
| 1058 | −{ | |
| 1059 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1060 | − | |
| 1061 | − VDBG(dev, "gmidi_out_close\n"); | |
| 1062 | − return 0; | |
| 1063 | −} | |
| 1064 | − | |
| 1065 | −static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up) | |
| 1066 | −{ | |
| 1067 | − struct gmidi_device *dev = substream->rmidi->private_data; | |
| 1068 | − | |
| 1069 | − VDBG(dev, "gmidi_out_trigger %d\n", up); | |
| 1070 | − if (up) { | |
| 1071 | − set_bit(substream->number, &dev->out_triggered); | |
| 1072 | − } else { | |
| 1073 | − clear_bit(substream->number, &dev->out_triggered); | |
| 1074 | − } | |
| 1075 | −} | |
| 1076 | − | |
| 1077 | −static struct snd_rawmidi_ops gmidi_in_ops = { | |
| 1078 | − .open = gmidi_in_open, | |
| 1079 | − .close = gmidi_in_close, | |
| 1080 | − .trigger = gmidi_in_trigger, | |
| 125 | +static struct usb_configuration midi_config = { | |
| 126 | + .label = "MIDI Gadget", | |
| 127 | + .bConfigurationValue = 1, | |
| 128 | + /* .iConfiguration = DYNAMIC */ | |
| 129 | + .bmAttributes = USB_CONFIG_ATT_ONE, | |
| 130 | + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, | |
| 1081 | 131 | }; |
| 1082 | 132 | |
| 1083 | −static struct snd_rawmidi_ops gmidi_out_ops = { | |
| 1084 | − .open = gmidi_out_open, | |
| 1085 | − .close = gmidi_out_close, | |
| 1086 | − .trigger = gmidi_out_trigger | |
| 1087 | −}; | |
| 1088 | − | |
| 1089 | −/* register as a sound "card" */ | |
| 1090 | −static int gmidi_register_card(struct gmidi_device *dev) | |
| 133 | +static int __init midi_bind_config(struct usb_configuration *c) | |
| 1091 | 134 | { |
| 1092 | − struct snd_card *card; | |
| 1093 | − struct snd_rawmidi *rmidi; | |
| 1094 | − int err; | |
| 1095 | − int out_ports = 1; | |
| 1096 | − int in_ports = 1; | |
| 1097 | − static struct snd_device_ops ops = { | |
| 1098 | − .dev_free = gmidi_snd_free, | |
| 1099 | − }; | |
| 1100 | − | |
| 1101 | − err = snd_card_create(index, id, THIS_MODULE, 0, &card); | |
| 1102 | − if (err < 0) { | |
| 1103 | − ERROR(dev, "snd_card_create failed\n"); | |
| 1104 | − goto fail; | |
| 1105 | − } | |
| 1106 | − dev->card = card; | |
| 1107 | − | |
| 1108 | − err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops); | |
| 1109 | − if (err < 0) { | |
| 1110 | − ERROR(dev, "snd_device_new failed: error %d\n", err); | |
| 1111 | − goto fail; | |
| 1112 | − } | |
| 1113 | − | |
| 1114 | − strcpy(card->driver, longname); | |
| 1115 | − strcpy(card->longname, longname); | |
| 1116 | − strcpy(card->shortname, shortname); | |
| 1117 | − | |
| 1118 | − /* Set up rawmidi */ | |
| 1119 | − dev->in_port.dev = dev; | |
| 1120 | − dev->in_port.active = 0; | |
| 1121 | − snd_component_add(card, "MIDI"); | |
| 1122 | − err = snd_rawmidi_new(card, "USB MIDI Gadget", 0, | |
| 1123 | − out_ports, in_ports, &rmidi); | |
| 1124 | − if (err < 0) { | |
| 1125 | − ERROR(dev, "snd_rawmidi_new failed: error %d\n", err); | |
| 1126 | − goto fail; | |
| 1127 | − } | |
| 1128 | − dev->rmidi = rmidi; | |
| 1129 | − strcpy(rmidi->name, card->shortname); | |
| 1130 | − rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | |
| 1131 | − SNDRV_RAWMIDI_INFO_INPUT | | |
| 1132 | − SNDRV_RAWMIDI_INFO_DUPLEX; | |
| 1133 | − rmidi->private_data = dev; | |
| 1134 | − | |
| 1135 | − /* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT. | |
| 1136 | − It's an upside-down world being a gadget. */ | |
| 1137 | − snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); | |
| 1138 | − snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); | |
| 1139 | − | |
| 1140 | − snd_card_set_dev(card, &dev->gadget->dev); | |
| 1141 | − | |
| 1142 | − /* register it - we're ready to go */ | |
| 1143 | − err = snd_card_register(card); | |
| 1144 | − if (err < 0) { | |
| 1145 | − ERROR(dev, "snd_card_register failed\n"); | |
| 1146 | − goto fail; | |
| 1147 | − } | |
| 1148 | − | |
| 1149 | − VDBG(dev, "gmidi_register_card finished ok\n"); | |
| 1150 | − return 0; | |
| 1151 | − | |
| 1152 | −fail: | |
| 1153 | − if (dev->card) { | |
| 1154 | − snd_card_free(dev->card); | |
| 1155 | − dev->card = NULL; | |
| 1156 | − } | |
| 1157 | − return err; | |
| 135 | + return f_midi_bind_config(c, index, id, | |
| 136 | + in_ports, out_ports, | |
| 137 | + buflen, qlen); | |
| 1158 | 138 | } |
| 1159 | 139 | |
| 1160 | −/* | |
| 1161 | − * Creates an output endpoint, and initializes output ports. | |
| 1162 | − */ | |
| 1163 | −static int __init gmidi_bind(struct usb_gadget *gadget) | |
| 140 | +static int __init midi_bind(struct usb_composite_dev *cdev) | |
| 1164 | 141 | { |
| 1165 | − struct gmidi_device *dev; | |
| 1166 | − struct usb_ep *in_ep, *out_ep; | |
| 1167 | − int gcnum, err = 0; | |
| 142 | + struct usb_gadget *gadget = cdev->gadget; | |
| 143 | + int gcnum, status; | |
| 1168 | 144 | |
| 1169 | − /* support optional vendor/distro customization */ | |
| 1170 | − if (idVendor) { | |
| 1171 | − if (!idProduct) { | |
| 1172 | − pr_err("idVendor needs idProduct!\n"); | |
| 1173 | − return -ENODEV; | |
| 1174 | − } | |
| 1175 | − device_desc.idVendor = cpu_to_le16(idVendor); | |
| 1176 | − device_desc.idProduct = cpu_to_le16(idProduct); | |
| 1177 | − if (bcdDevice) { | |
| 1178 | − device_desc.bcdDevice = cpu_to_le16(bcdDevice); | |
| 1179 | − } | |
| 1180 | − } | |
| 1181 | − if (iManufacturer) { | |
| 1182 | − strlcpy(manufacturer, iManufacturer, sizeof(manufacturer)); | |
| 1183 | − } else { | |
| 1184 | − snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", | |
| 1185 | − init_utsname()->sysname, init_utsname()->release, | |
| 1186 | − gadget->name); | |
| 1187 | − } | |
| 1188 | − if (iProduct) { | |
| 1189 | − strlcpy(product_desc, iProduct, sizeof(product_desc)); | |
| 1190 | − } | |
| 1191 | − if (iSerialNumber) { | |
| 1192 | − device_desc.iSerialNumber = STRING_SERIAL, | |
| 1193 | − strlcpy(serial_number, iSerialNumber, sizeof(serial_number)); | |
| 1194 | − } | |
| 145 | + status = usb_string_id(cdev); | |
| 146 | + if (status < 0) | |
| 147 | + return status; | |
| 148 | + strings_dev[STRING_MANUFACTURER_IDX].id = status; | |
| 149 | + device_desc.iManufacturer = status; | |
| 1195 | 150 | |
| 1196 | − /* Bulk-only drivers like this one SHOULD be able to | |
| 1197 | − * autoconfigure on any sane usb controller driver, | |
| 1198 | − * but there may also be important quirks to address. | |
| 1199 | − */ | |
| 1200 | − usb_ep_autoconfig_reset(gadget); | |
| 1201 | − in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc); | |
| 1202 | − if (!in_ep) { | |
| 1203 | −autoconf_fail: | |
| 1204 | − pr_err("%s: can't autoconfigure on %s\n", | |
| 1205 | − shortname, gadget->name); | |
| 1206 | − return -ENODEV; | |
| 1207 | − } | |
| 1208 | − EP_IN_NAME = in_ep->name; | |
| 1209 | − in_ep->driver_data = in_ep; /* claim */ | |
| 151 | + status = usb_string_id(cdev); | |
| 152 | + if (status < 0) | |
| 153 | + return status; | |
| 154 | + strings_dev[STRING_PRODUCT_IDX].id = status; | |
| 155 | + device_desc.iProduct = status; | |
| 1210 | 156 | |
| 1211 | − out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc); | |
| 1212 | − if (!out_ep) { | |
| 1213 | − goto autoconf_fail; | |
| 1214 | − } | |
| 1215 | − EP_OUT_NAME = out_ep->name; | |
| 1216 | − out_ep->driver_data = out_ep; /* claim */ | |
| 157 | + /* config description */ | |
| 158 | + status = usb_string_id(cdev); | |
| 159 | + if (status < 0) | |
| 160 | + return status; | |
| 161 | + strings_dev[STRING_DESCRIPTION_IDX].id = status; | |
| 162 | + | |
| 163 | + midi_config.iConfiguration = status; | |
| 1217 | 164 | |
| 1218 | 165 | gcnum = usb_gadget_controller_number(gadget); |
| 1219 | − if (gcnum >= 0) { | |
| 1220 | − device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | |
| 1221 | − } else { | |
| 166 | + if (gcnum < 0) { | |
| 1222 | 167 | /* gmidi is so simple (no altsettings) that |
| 1223 | 168 | * it SHOULD NOT have problems with bulk-capable hardware. |
| 1224 | 169 | * so warn about unrecognized controllers, don't panic. |
| 1225 | 170 | */ |
| 1226 | 171 | pr_warning("%s: controller '%s' not recognized\n", |
| 1227 | − shortname, gadget->name); | |
| 172 | + __func__, gadget->name); | |
| 1228 | 173 | device_desc.bcdDevice = cpu_to_le16(0x9999); |
| 174 | + } else { | |
| 175 | + device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | |
| 1229 | 176 | } |
| 1230 | 177 | |
| 178 | + status = usb_add_config(cdev, &midi_config, midi_bind_config); | |
| 179 | + if (status < 0) | |
| 180 | + return status; | |
| 1231 | 181 | |
| 1232 | − /* ok, we made sense of the hardware ... */ | |
| 1233 | − dev = kzalloc(sizeof(*dev), GFP_KERNEL); | |
| 1234 | − if (!dev) { | |
| 1235 | − return -ENOMEM; | |
| 1236 | − } | |
| 1237 | − spin_lock_init(&dev->lock); | |
| 1238 | − dev->gadget = gadget; | |
| 1239 | − dev->in_ep = in_ep; | |
| 1240 | − dev->out_ep = out_ep; | |
| 1241 | − set_gadget_data(gadget, dev); | |
| 1242 | − tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev); | |
| 1243 | − | |
| 1244 | − /* preallocate control response and buffer */ | |
| 1245 | − dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ); | |
| 1246 | − if (!dev->req) { | |
| 1247 | − err = -ENOMEM; | |
| 1248 | − goto fail; | |
| 1249 | − } | |
| 1250 | − | |
| 1251 | − dev->req->complete = gmidi_setup_complete; | |
| 1252 | − | |
| 1253 | − gadget->ep0->driver_data = dev; | |
| 1254 | − | |
| 1255 | − INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); | |
| 1256 | − INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, | |
| 1257 | − EP_OUT_NAME, EP_IN_NAME); | |
| 1258 | − | |
| 1259 | − /* register as an ALSA sound card */ | |
| 1260 | − err = gmidi_register_card(dev); | |
| 1261 | − if (err < 0) { | |
| 1262 | − goto fail; | |
| 1263 | − } | |
| 1264 | − | |
| 1265 | − VDBG(dev, "gmidi_bind finished ok\n"); | |
| 182 | + pr_info("%s\n", longname); | |
| 1266 | 183 | return 0; |
| 1267 | − | |
| 1268 | −fail: | |
| 1269 | − gmidi_unbind(gadget); | |
| 1270 | − return err; | |
| 1271 | −} | |
| 1272 | − | |
| 1273 | − | |
| 1274 | −static void gmidi_suspend(struct usb_gadget *gadget) | |
| 1275 | −{ | |
| 1276 | − struct gmidi_device *dev = get_gadget_data(gadget); | |
| 1277 | − | |
| 1278 | − if (gadget->speed == USB_SPEED_UNKNOWN) { | |
| 1279 | − return; | |
| 1280 | − } | |
| 1281 | − | |
| 1282 | − DBG(dev, "suspend\n"); | |
| 1283 | −} | |
| 1284 | − | |
| 1285 | −static void gmidi_resume(struct usb_gadget *gadget) | |
| 1286 | −{ | |
| 1287 | − struct gmidi_device *dev = get_gadget_data(gadget); | |
| 1288 | − | |
| 1289 | − DBG(dev, "resume\n"); | |
| 1290 | 184 | } |
| 1291 | 185 | |
| 1292 | − | |
| 1293 | −static struct usb_gadget_driver gmidi_driver = { | |
| 1294 | − .speed = USB_SPEED_FULL, | |
| 1295 | − .function = (char *)longname, | |
| 1296 | − .unbind = gmidi_unbind, | |
| 1297 | − | |
| 1298 | − .setup = gmidi_setup, | |
| 1299 | − .disconnect = gmidi_disconnect, | |
| 1300 | − | |
| 1301 | − .suspend = gmidi_suspend, | |
| 1302 | − .resume = gmidi_resume, | |
| 1303 | − | |
| 1304 | − .driver = { | |
| 1305 | − .name = (char *)shortname, | |
| 1306 | − .owner = THIS_MODULE, | |
| 1307 | − }, | |
| 186 | +static struct usb_composite_driver midi_driver = { | |
| 187 | + .name = (char *) longname, | |
| 188 | + .dev = &device_desc, | |
| 189 | + .strings = dev_strings, | |
| 190 | + .max_speed = USB_SPEED_HIGH, | |
| 191 | + .unbind = __exit_p(midi_unbind), | |
| 1308 | 192 | }; |
| 1309 | 193 | |
| 1310 | −static int __init gmidi_init(void) | |
| 194 | +static int __init midi_init(void) | |
| 1311 | 195 | { |
| 1312 | − return usb_gadget_probe_driver(&gmidi_driver, gmidi_bind); | |
| 196 | + return usb_composite_probe(&midi_driver, midi_bind); | |
| 1313 | 197 | } |
| 1314 | −module_init(gmidi_init); | |
| 198 | +module_init(midi_init); | |
| 1315 | 199 | |
| 1316 | −static void __exit gmidi_cleanup(void) | |
| 200 | +static void __exit midi_cleanup(void) | |
| 1317 | 201 | { |
| 1318 | − usb_gadget_unregister_driver(&gmidi_driver); | |
| 202 | + usb_composite_unregister(&midi_driver); | |
| 1319 | 203 | } |
| 1320 | −module_exit(gmidi_cleanup); | |
| 204 | +module_exit(midi_cleanup); | |
| 1321 | 205 | |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | |
| @@ -689,7 +689,7 @@ static int imx_ep_enable(struct usb_ep *usb_ep, · 688 unmodified lines | ||
| 689 | 689 | return -EINVAL; |
| 690 | 690 | } |
| 691 | 691 | |
| 692 | − if (imx_ep->fifosize < le16_to_cpu(desc->wMaxPacketSize)) { | |
| 692 | + if (imx_ep->fifosize < usb_endpoint_maxp(desc)) { | |
| 693 | 693 | D_ERR(imx_usb->dev, |
| 694 | 694 | "<%s> bad %s maxpacket\n", __func__, usb_ep->name); |
| 695 | 695 | return -ERANGE; |
| @@ -1478,7 +1478,7 @@ static int __init imx_udc_probe(struct platform_device *pdev) · 782 unmodified lines | ||
| 1478 | 1478 | |
| 1479 | 1479 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) { |
| 1480 | 1480 | ret = request_irq(imx_usb->usbd_int[i], intr_handler(i), |
| 1481 | − IRQF_DISABLED, driver_name, imx_usb); | |
| 1481 | + 0, driver_name, imx_usb); | |
| 1482 | 1482 | if (ret) { |
| 1483 | 1483 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", |
| 1484 | 1484 | imx_usb->usbd_int[i], ret); |
| @@ -8,11 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | 11 | */ |
| 17 | 12 | |
| 18 | 13 | #ifndef __LINUX_USB_GADGET_IMX_H |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | |
| @@ -5,16 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | 6 | * under the terms and conditions of the GNU General Public License, |
| 7 | 7 | * version 2, as published by the Free Software Foundation. |
| 8 | − * | |
| 9 | − * This program is distributed in the hope it will be useful, but WITHOUT | |
| 10 | − * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 11 | − * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 12 | − * more details. | |
| 13 | − * | |
| 14 | − * You should have received a copy of the GNU General Public License along with | |
| 15 | − * this program; if not, write to the Free Software Foundation, Inc., | |
| 16 | − * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
| 17 | − * | |
| 18 | 8 | */ |
| 19 | 9 | |
| 20 | 10 | |
| @@ -60,9 +50,6 @@ static const char driver_name[] = "langwell_udc"; · 39 unmodified lines | ||
| 60 | 50 | static const char driver_desc[] = DRIVER_DESC; |
| 61 | 51 | |
| 62 | 52 | |
| 63 | −/* controller device global variable */ | |
| 64 | −static struct langwell_udc *the_controller; | |
| 65 | − | |
| 66 | 53 | /* for endpoint 0 operations */ |
| 67 | 54 | static const struct usb_endpoint_descriptor |
| 68 | 55 | langwell_ep0_desc = { |
| @@ -283,7 +270,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, · 214 unmodified lines | ||
| 283 | 270 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) |
| 284 | 271 | return -ESHUTDOWN; |
| 285 | 272 | |
| 286 | − max = le16_to_cpu(desc->wMaxPacketSize); | |
| 273 | + max = usb_endpoint_maxp(desc); | |
| 287 | 274 | |
| 288 | 275 | /* |
| 289 | 276 | * disable HW zero length termination select |
| @@ -1321,9 +1308,12 @@ static int langwell_pullup(struct usb_gadget *_gadget, int is_on) · 1031 unmodified lines | ||
| 1321 | 1308 | return 0; |
| 1322 | 1309 | } |
| 1323 | 1310 | |
| 1324 | −static int langwell_start(struct usb_gadget_driver *driver, | |
| 1325 | − int (*bind)(struct usb_gadget *)); | |
| 1326 | −static int langwell_stop(struct usb_gadget_driver *driver); | |
| 1311 | +static int langwell_start(struct usb_gadget *g, | |
| 1312 | + struct usb_gadget_driver *driver); | |
| 1313 | + | |
| 1314 | +static int langwell_stop(struct usb_gadget *g, | |
| 1315 | + struct usb_gadget_driver *driver); | |
| 1316 | + | |
| 1327 | 1317 | /* device controller usb_gadget_ops structure */ |
| 1328 | 1318 | static const struct usb_gadget_ops langwell_ops = { |
| 1329 | 1319 | |
| @@ -1345,8 +1335,8 @@ static const struct usb_gadget_ops langwell_ops = { · 15 unmodified lines | ||
| 1345 | 1335 | /* D+ pullup, software-controlled connect/disconnect to USB host */ |
| 1346 | 1336 | .pullup = langwell_pullup, |
| 1347 | 1337 | |
| 1348 | − .start = langwell_start, | |
| 1349 | − .stop = langwell_stop, | |
| 1338 | + .udc_start = langwell_start, | |
| 1339 | + .udc_stop = langwell_stop, | |
| 1350 | 1340 | }; |
| 1351 | 1341 | |
| 1352 | 1342 | |
| @@ -1561,7 +1551,7 @@ static void stop_activity(struct langwell_udc *dev, · 208 unmodified lines | ||
| 1561 | 1551 | static ssize_t show_function(struct device *_dev, |
| 1562 | 1552 | struct device_attribute *attr, char *buf) |
| 1563 | 1553 | { |
| 1564 | − struct langwell_udc *dev = the_controller; | |
| 1554 | + struct langwell_udc *dev = dev_get_drvdata(_dev); | |
| 1565 | 1555 | |
| 1566 | 1556 | if (!dev->driver || !dev->driver->function |
| 1567 | 1557 | || strlen(dev->driver->function) > PAGE_SIZE) |
| @@ -1572,11 +1562,25 @@ static ssize_t show_function(struct device *_dev, · 4 unmodified lines | ||
| 1572 | 1562 | static DEVICE_ATTR(function, S_IRUGO, show_function, NULL); |
| 1573 | 1563 | |
| 1574 | 1564 | |
| 1565 | +static inline enum usb_device_speed lpm_device_speed(u32 reg) | |
| 1566 | +{ | |
| 1567 | + switch (LPM_PSPD(reg)) { | |
| 1568 | + case LPM_SPEED_HIGH: | |
| 1569 | + return USB_SPEED_HIGH; | |
| 1570 | + case LPM_SPEED_FULL: | |
| 1571 | + return USB_SPEED_FULL; | |
| 1572 | + case LPM_SPEED_LOW: | |
| 1573 | + return USB_SPEED_LOW; | |
| 1574 | + default: | |
| 1575 | + return USB_SPEED_UNKNOWN; | |
| 1576 | + } | |
| 1577 | +} | |
| 1578 | + | |
| 1575 | 1579 | /* device "langwell_udc" sysfs attribute file */ |
| 1576 | 1580 | static ssize_t show_langwell_udc(struct device *_dev, |
| 1577 | 1581 | struct device_attribute *attr, char *buf) |
| 1578 | 1582 | { |
| 1579 | − struct langwell_udc *dev = the_controller; | |
| 1583 | + struct langwell_udc *dev = dev_get_drvdata(_dev); | |
| 1580 | 1584 | struct langwell_request *req; |
| 1581 | 1585 | struct langwell_ep *ep = NULL; |
| 1582 | 1586 | char *next; |
| @@ -1700,20 +1704,7 @@ static ssize_t show_langwell_udc(struct device *_dev, · 117 unmodified lines | ||
| 1700 | 1704 | "BmAttributes: %d\n\n", |
| 1701 | 1705 | LPM_PTS(tmp_reg), |
| 1702 | 1706 | (tmp_reg & LPM_STS) ? 1 : 0, |
| 1703 | − ({ | |
| 1704 | − char *s; | |
| 1705 | − switch (LPM_PSPD(tmp_reg)) { | |
| 1706 | − case LPM_SPEED_FULL: | |
| 1707 | − s = "Full Speed"; break; | |
| 1708 | − case LPM_SPEED_LOW: | |
| 1709 | − s = "Low Speed"; break; | |
| 1710 | − case LPM_SPEED_HIGH: | |
| 1711 | − s = "High Speed"; break; | |
| 1712 | − default: | |
| 1713 | − s = "Unknown Speed"; break; | |
| 1714 | − } | |
| 1715 | − s; | |
| 1716 | − }), | |
| 1707 | + usb_speed_string(lpm_device_speed(tmp_reg)), | |
| 1717 | 1708 | (tmp_reg & LPM_PFSC) ? "Force Full Speed" : "Not Force", |
| 1718 | 1709 | (tmp_reg & LPM_PHCD) ? "Disabled" : "Enabled", |
| 1719 | 1710 | LPM_BA(tmp_reg)); |
| @@ -1821,7 +1812,7 @@ static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL); · 101 unmodified lines | ||
| 1821 | 1812 | static ssize_t store_remote_wakeup(struct device *_dev, |
| 1822 | 1813 | struct device_attribute *attr, const char *buf, size_t count) |
| 1823 | 1814 | { |
| 1824 | − struct langwell_udc *dev = the_controller; | |
| 1815 | + struct langwell_udc *dev = dev_get_drvdata(_dev); | |
| 1825 | 1816 | unsigned long flags; |
| 1826 | 1817 | ssize_t rc = count; |
| 1827 | 1818 | |
| @@ -1857,21 +1848,15 @@ static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup); · 29 unmodified lines | ||
| 1857 | 1848 | * the driver might get unbound. |
| 1858 | 1849 | */ |
| 1859 | 1850 | |
| 1860 | −static int langwell_start(struct usb_gadget_driver *driver, | |
| 1861 | − int (*bind)(struct usb_gadget *)) | |
| 1851 | +static int langwell_start(struct usb_gadget *g, | |
| 1852 | + struct usb_gadget_driver *driver) | |
| 1862 | 1853 | { |
| 1863 | − struct langwell_udc *dev = the_controller; | |
| 1854 | + struct langwell_udc *dev = gadget_to_langwell(g); | |
| 1864 | 1855 | unsigned long flags; |
| 1865 | 1856 | int retval; |
| 1866 | 1857 | |
| 1867 | − if (!dev) | |
| 1868 | − return -ENODEV; | |
| 1869 | − | |
| 1870 | 1858 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| 1871 | 1859 | |
| 1872 | − if (dev->driver) | |
| 1873 | − return -EBUSY; | |
| 1874 | − | |
| 1875 | 1860 | spin_lock_irqsave(&dev->lock, flags); |
| 1876 | 1861 | |
| 1877 | 1862 | /* hook up the driver ... */ |
| @@ -1881,18 +1866,9 @@ static int langwell_start(struct usb_gadget_driver *driver, · 3 unmodified lines | ||
| 1881 | 1866 | |
| 1882 | 1867 | spin_unlock_irqrestore(&dev->lock, flags); |
| 1883 | 1868 | |
| 1884 | − retval = bind(&dev->gadget); | |
| 1885 | − if (retval) { | |
| 1886 | − dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n", | |
| 1887 | − driver->driver.name, retval); | |
| 1888 | − dev->driver = NULL; | |
| 1889 | − dev->gadget.dev.driver = NULL; | |
| 1890 | − return retval; | |
| 1891 | − } | |
| 1892 | − | |
| 1893 | 1869 | retval = device_create_file(&dev->pdev->dev, &dev_attr_function); |
| 1894 | 1870 | if (retval) |
| 1895 | − goto err_unbind; | |
| 1871 | + goto err; | |
| 1896 | 1872 | |
| 1897 | 1873 | dev->usb_state = USB_STATE_ATTACHED; |
| 1898 | 1874 | dev->ep0_state = WAIT_FOR_SETUP; |
| @@ -1909,31 +1885,27 @@ static int langwell_start(struct usb_gadget_driver *driver, · 10 unmodified lines | ||
| 1909 | 1885 | dev_info(&dev->pdev->dev, "register driver: %s\n", |
| 1910 | 1886 | driver->driver.name); |
| 1911 | 1887 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
| 1888 | + | |
| 1912 | 1889 | return 0; |
| 1913 | 1890 | |
| 1914 | −err_unbind: | |
| 1915 | − driver->unbind(&dev->gadget); | |
| 1891 | +err: | |
| 1916 | 1892 | dev->gadget.dev.driver = NULL; |
| 1917 | 1893 | dev->driver = NULL; |
| 1918 | 1894 | |
| 1919 | 1895 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
| 1896 | + | |
| 1920 | 1897 | return retval; |
| 1921 | 1898 | } |
| 1922 | 1899 | |
| 1923 | 1900 | /* unregister gadget driver */ |
| 1924 | −static int langwell_stop(struct usb_gadget_driver *driver) | |
| 1901 | +static int langwell_stop(struct usb_gadget *g, | |
| 1902 | + struct usb_gadget_driver *driver) | |
| 1925 | 1903 | { |
| 1926 | − struct langwell_udc *dev = the_controller; | |
| 1904 | + struct langwell_udc *dev = gadget_to_langwell(g); | |
| 1927 | 1905 | unsigned long flags; |
| 1928 | 1906 | |
| 1929 | − if (!dev) | |
| 1930 | − return -ENODEV; | |
| 1931 | − | |
| 1932 | 1907 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| 1933 | 1908 | |
| 1934 | − if (unlikely(!driver || !driver->unbind)) | |
| 1935 | − return -EINVAL; | |
| 1936 | − | |
| 1937 | 1909 | /* exit PHY low power suspend */ |
| 1938 | 1910 | if (dev->pdev->device != 0x0829) |
| 1939 | 1911 | langwell_phy_low_power(dev, 0); |
| @@ -1956,8 +1928,6 @@ static int langwell_stop(struct usb_gadget_driver *driver) · 16 unmodified lines | ||
| 1956 | 1928 | stop_activity(dev, driver); |
| 1957 | 1929 | spin_unlock_irqrestore(&dev->lock, flags); |
| 1958 | 1930 | |
| 1959 | − /* unbind gadget driver */ | |
| 1960 | − driver->unbind(&dev->gadget); | |
| 1961 | 1931 | dev->gadget.dev.driver = NULL; |
| 1962 | 1932 | dev->driver = NULL; |
| 1963 | 1933 | |
| @@ -1966,6 +1936,7 @@ static int langwell_stop(struct usb_gadget_driver *driver) · 2 unmodified lines | ||
| 1966 | 1936 | dev_info(&dev->pdev->dev, "unregistered driver '%s'\n", |
| 1967 | 1937 | driver->driver.name); |
| 1968 | 1938 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
| 1939 | + | |
| 1969 | 1940 | return 0; |
| 1970 | 1941 | } |
| 1971 | 1942 | |
| @@ -2657,12 +2628,10 @@ done: · 685 unmodified lines | ||
| 2657 | 2628 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
| 2658 | 2629 | } |
| 2659 | 2630 | |
| 2660 | − | |
| 2661 | 2631 | /* port change detect interrupt handler */ |
| 2662 | 2632 | static void handle_port_change(struct langwell_udc *dev) |
| 2663 | 2633 | { |
| 2664 | 2634 | u32 portsc1, devlc; |
| 2665 | − u32 speed; | |
| 2666 | 2635 | |
| 2667 | 2636 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| 2668 | 2637 | |
| @@ -2677,24 +2646,9 @@ static void handle_port_change(struct langwell_udc *dev) · 8 unmodified lines | ||
| 2677 | 2646 | /* bus reset is finished */ |
| 2678 | 2647 | if (!(portsc1 & PORTS_PR)) { |
| 2679 | 2648 | /* get the speed */ |
| 2680 | − speed = LPM_PSPD(devlc); | |
| 2681 | − switch (speed) { | |
| 2682 | − case LPM_SPEED_HIGH: | |
| 2683 | − dev->gadget.speed = USB_SPEED_HIGH; | |
| 2684 | − break; | |
| 2685 | − case LPM_SPEED_FULL: | |
| 2686 | − dev->gadget.speed = USB_SPEED_FULL; | |
| 2687 | − break; | |
| 2688 | − case LPM_SPEED_LOW: | |
| 2689 | − dev->gadget.speed = USB_SPEED_LOW; | |
| 2690 | − break; | |
| 2691 | − default: | |
| 2692 | − dev->gadget.speed = USB_SPEED_UNKNOWN; | |
| 2693 | − break; | |
| 2694 | − } | |
| 2695 | − dev_vdbg(&dev->pdev->dev, | |
| 2696 | − "speed = %d, dev->gadget.speed = %d\n", | |
| 2697 | − speed, dev->gadget.speed); | |
| 2649 | + dev->gadget.speed = lpm_device_speed(devlc); | |
| 2650 | + dev_vdbg(&dev->pdev->dev, "dev->gadget.speed = %d\n", | |
| 2651 | + dev->gadget.speed); | |
| 2698 | 2652 | } |
| 2699 | 2653 | |
| 2700 | 2654 | /* LPM L0 to L1 */ |
| @@ -2999,7 +2953,7 @@ static irqreturn_t langwell_irq(int irq, void *_dev) · 298 unmodified lines | ||
| 2999 | 2953 | /* release device structure */ |
| 3000 | 2954 | static void gadget_release(struct device *_dev) |
| 3001 | 2955 | { |
| 3002 | − struct langwell_udc *dev = the_controller; | |
| 2956 | + struct langwell_udc *dev = dev_get_drvdata(_dev); | |
| 3003 | 2957 | |
| 3004 | 2958 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| 3005 | 2959 | |
| @@ -3057,7 +3011,7 @@ static void sram_deinit(struct langwell_udc *dev) · 51 unmodified lines | ||
| 3057 | 3011 | /* tear down the binding between this driver and the pci device */ |
| 3058 | 3012 | static void langwell_udc_remove(struct pci_dev *pdev) |
| 3059 | 3013 | { |
| 3060 | − struct langwell_udc *dev = the_controller; | |
| 3014 | + struct langwell_udc *dev = pci_get_drvdata(pdev); | |
| 3061 | 3015 | |
| 3062 | 3016 | DECLARE_COMPLETION(done); |
| 3063 | 3017 | |
| @@ -3124,8 +3078,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) · 60 unmodified lines | ||
| 3124 | 3078 | |
| 3125 | 3079 | /* free dev, wait for the release() finished */ |
| 3126 | 3080 | wait_for_completion(&done); |
| 3127 | − | |
| 3128 | − the_controller = NULL; | |
| 3129 | 3081 | } |
| 3130 | 3082 | |
| 3131 | 3083 | |
| @@ -3144,11 +3096,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, · 12 unmodified lines | ||
| 3144 | 3096 | size_t size; |
| 3145 | 3097 | int retval; |
| 3146 | 3098 | |
| 3147 | − if (the_controller) { | |
| 3148 | − dev_warn(&pdev->dev, "ignoring\n"); | |
| 3149 | − return -EBUSY; | |
| 3150 | − } | |
| 3151 | − | |
| 3152 | 3099 | /* alloc, and start init */ |
| 3153 | 3100 | dev = kzalloc(sizeof *dev, GFP_KERNEL); |
| 3154 | 3101 | if (dev == NULL) { |
| @@ -3368,8 +3315,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, · 213 unmodified lines | ||
| 3368 | 3315 | "After langwell_udc_probe(), print all registers:\n"); |
| 3369 | 3316 | print_all_registers(dev); |
| 3370 | 3317 | |
| 3371 | − the_controller = dev; | |
| 3372 | − | |
| 3373 | 3318 | retval = device_register(&dev->gadget.dev); |
| 3374 | 3319 | if (retval) |
| 3375 | 3320 | goto error; |
| @@ -3404,7 +3349,7 @@ error: · 28 unmodified lines | ||
| 3404 | 3349 | /* device controller suspend */ |
| 3405 | 3350 | static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) |
| 3406 | 3351 | { |
| 3407 | − struct langwell_udc *dev = the_controller; | |
| 3352 | + struct langwell_udc *dev = pci_get_drvdata(pdev); | |
| 3408 | 3353 | |
| 3409 | 3354 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| 3410 | 3355 | |
| @@ -3452,7 +3397,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) · 41 unmodified lines | ||
| 3452 | 3397 | /* device controller resume */ |
| 3453 | 3398 | static int langwell_udc_resume(struct pci_dev *pdev) |
| 3454 | 3399 | { |
| 3455 | − struct langwell_udc *dev = the_controller; | |
| 3400 | + struct langwell_udc *dev = pci_get_drvdata(pdev); | |
| 3456 | 3401 | size_t size; |
| 3457 | 3402 | |
| 3458 | 3403 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| @@ -3534,7 +3479,7 @@ static int langwell_udc_resume(struct pci_dev *pdev) · 75 unmodified lines | ||
| 3534 | 3479 | /* pci driver shutdown */ |
| 3535 | 3480 | static void langwell_udc_shutdown(struct pci_dev *pdev) |
| 3536 | 3481 | { |
| 3537 | − struct langwell_udc *dev = the_controller; | |
| 3482 | + struct langwell_udc *dev = pci_get_drvdata(pdev); | |
| 3538 | 3483 | u32 usbmode; |
| 3539 | 3484 | |
| 3540 | 3485 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
| @@ -5,16 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | 6 | * under the terms and conditions of the GNU General Public License, |
| 7 | 7 | * version 2, as published by the Free Software Foundation. |
| 8 | − * | |
| 9 | − * This program is distributed in the hope it will be useful, but WITHOUT | |
| 10 | − * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 11 | − * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 12 | − * more details. | |
| 13 | − * | |
| 14 | − * You should have received a copy of the GNU General Public License along with | |
| 15 | − * this program; if not, write to the Free Software Foundation, Inc., | |
| 16 | − * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
| 17 | − * | |
| 18 | 8 | */ |
| 19 | 9 | |
| 20 | 10 | #include <linux/usb/langwell_udc.h> |
| @@ -231,3 +221,5 @@ struct langwell_udc { · 210 unmodified lines | ||
| 231 | 221 | u16 dev_status; |
| 232 | 222 | }; |
| 233 | 223 | |
| 224 | +#define gadget_to_langwell(g) container_of((g), struct langwell_udc, gadget) | |
| 225 | + | |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | #include <linux/module.h> |
| @@ -370,7 +360,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, · 346 unmodified lines | ||
| 370 | 360 | |
| 371 | 361 | ep->pipectr = get_pipectr_addr(pipenum); |
| 372 | 362 | ep->pipenum = pipenum; |
| 373 | − ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 363 | + ep->ep.maxpacket = usb_endpoint_maxp(desc); | |
| 374 | 364 | m66592->pipenum2ep[pipenum] = ep; |
| 375 | 365 | m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep; |
| 376 | 366 | INIT_LIST_HEAD(&ep->queue); |
| @@ -447,7 +437,7 @@ static int alloc_pipe_config(struct m66592_ep *ep, · 70 unmodified lines | ||
| 447 | 437 | ep->type = info.type; |
| 448 | 438 | |
| 449 | 439 | info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
| 450 | − info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 440 | + info.maxpacket = usb_endpoint_maxp(desc); | |
| 451 | 441 | info.interval = desc->bInterval; |
| 452 | 442 | if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) |
| 453 | 443 | info.dir_in = 1; |
| @@ -1674,7 +1664,7 @@ static int __init m66592_probe(struct platform_device *pdev) · 1220 unmodified lines | ||
| 1674 | 1664 | m66592->timer.data = (unsigned long)m66592; |
| 1675 | 1665 | m66592->reg = reg; |
| 1676 | 1666 | |
| 1677 | − ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED, | |
| 1667 | + ret = request_irq(ires->start, m66592_irq, IRQF_SHARED, | |
| 1678 | 1668 | udc_name, m66592); |
| 1679 | 1669 | if (ret < 0) { |
| 1680 | 1670 | pr_err("request_irq error (%d)\n", ret); |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | #ifndef __M66592_UDC_H__ |
| @@ -10,15 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | 13 | */ |
| 23 | 14 | |
| 24 | 15 | |
| @@ -169,7 +160,7 @@ static struct usb_composite_driver msg_driver = { · 144 unmodified lines | ||
| 169 | 160 | .name = "g_mass_storage", |
| 170 | 161 | .dev = &msg_device_desc, |
| 171 | 162 | .iProduct = DRIVER_DESC, |
| 172 | − .max_speed = USB_SPEED_HIGH, | |
| 163 | + .max_speed = USB_SPEED_SUPER, | |
| 173 | 164 | .needs_serial = 1, |
| 174 | 165 | }; |
| 175 | 166 | |
| @@ -10,15 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | 13 | */ |
| 23 | 14 | |
| 24 | 15 | |
| @@ -1,3 +1,11 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License as published by the | |
| 6 | + * Free Software Foundation; either version 2 of the License, or (at your | |
| 7 | + * option) any later version. | |
| 8 | + */ | |
| 1 | 9 | |
| 2 | 10 | #ifndef __MV_UDC_H |
| 3 | 11 | #define __MV_UDC_H |
| @@ -194,14 +202,25 @@ struct mv_udc { · 190 unmodified lines | ||
| 194 | 202 | unsigned int ep0_dir; |
| 195 | 203 | |
| 196 | 204 | unsigned int dev_addr; |
| 205 | + unsigned int test_mode; | |
| 197 | 206 | |
| 198 | 207 | int errors; |
| 199 | 208 | unsigned softconnect:1, |
| 200 | 209 | vbus_active:1, |
| 201 | 210 | remote_wakeup:1, |
| 202 | 211 | softconnected:1, |
| 203 | − force_fs:1; | |
| 204 | − struct clk *clk; | |
| 212 | + force_fs:1, | |
| 213 | + clock_gating:1, | |
| 214 | + active:1; | |
| 215 | + | |
| 216 | + struct work_struct vbus_work; | |
| 217 | + struct workqueue_struct *qwork; | |
| 218 | + | |
| 219 | + struct mv_usb_platform_data *pdata; | |
| 220 | + | |
| 221 | + /* some SOC has mutiple clock sources for USB*/ | |
| 222 | + unsigned int clknum; | |
| 223 | + struct clk *clk[0]; | |
| 205 | 224 | }; |
| 206 | 225 | |
| 207 | 226 | /* endpoint data structure */ |
| @@ -225,6 +244,7 @@ struct mv_req { · 17 unmodified lines | ||
| 225 | 244 | struct mv_dtd *dtd, *head, *tail; |
| 226 | 245 | struct mv_ep *ep; |
| 227 | 246 | struct list_head queue; |
| 247 | + unsigned int test_mode; | |
| 228 | 248 | unsigned dtd_count; |
| 229 | 249 | unsigned mapped:1; |
| 230 | 250 | }; |
| @@ -289,6 +309,4 @@ struct mv_dtd { · 58 unmodified lines | ||
| 289 | 309 | struct mv_dtd *next_dtd_virt; |
| 290 | 310 | }; |
| 291 | 311 | |
| 292 | −extern int mv_udc_phy_init(unsigned int base); | |
| 293 | − | |
| 294 | 312 | #endif |
| @@ -1,3 +1,14 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | |
| 3 | + * Author: Chao Xie <chao.xie@marvell.com> | |
| 4 | + * Neil Zhang <zhangwm@marvell.com> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify it | |
| 7 | + * under the terms of the GNU General Public License as published by the | |
| 8 | + * Free Software Foundation; either version 2 of the License, or (at your | |
| 9 | + * option) any later version. | |
| 10 | + */ | |
| 11 | + | |
| 1 | 12 | #include <linux/module.h> |
| 2 | 13 | #include <linux/pci.h> |
| 3 | 14 | #include <linux/dma-mapping.h> |
| @@ -22,6 +33,7 @@ · 18 unmodified lines | ||
| 22 | 33 | #include <linux/irq.h> |
| 23 | 34 | #include <linux/platform_device.h> |
| 24 | 35 | #include <linux/clk.h> |
| 36 | +#include <linux/platform_data/mv_usb.h> | |
| 25 | 37 | #include <asm/system.h> |
| 26 | 38 | #include <asm/unaligned.h> |
| 27 | 39 | |
| @@ -45,6 +57,8 @@ · 17 unmodified lines | ||
| 45 | 57 | #define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) |
| 46 | 58 | #define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT) |
| 47 | 59 | |
| 60 | +static DECLARE_COMPLETION(release_done); | |
| 61 | + | |
| 48 | 62 | static const char driver_name[] = "mv_udc"; |
| 49 | 63 | static const char driver_desc[] = DRIVER_DESC; |
| 50 | 64 | |
| @@ -53,6 +67,7 @@ static struct mv_udc *the_controller; · 2 unmodified lines | ||
| 53 | 67 | int mv_usb_otgsc; |
| 54 | 68 | |
| 55 | 69 | static void nuke(struct mv_ep *ep, int status); |
| 70 | +static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver); | |
| 56 | 71 | |
| 57 | 72 | /* for endpoint 0 operations */ |
| 58 | 73 | static const struct usb_endpoint_descriptor mv_ep0_desc = { |
| @@ -82,14 +97,16 @@ static void ep0_reset(struct mv_udc *udc) · 23 unmodified lines | ||
| 82 | 97 | (EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS) |
| 83 | 98 | | EP_QUEUE_HEAD_IOS; |
| 84 | 99 | |
| 100 | + ep->dqh->next_dtd_ptr = EP_QUEUE_HEAD_NEXT_TERMINATE; | |
| 101 | + | |
| 85 | 102 | epctrlx = readl(&udc->op_regs->epctrlx[0]); |
| 86 | 103 | if (i) { /* TX */ |
| 87 | − epctrlx |= EPCTRL_TX_ENABLE | EPCTRL_TX_DATA_TOGGLE_RST | |
| 104 | + epctrlx |= EPCTRL_TX_ENABLE | |
| 88 | 105 | | (USB_ENDPOINT_XFER_CONTROL |
| 89 | 106 | << EPCTRL_TX_EP_TYPE_SHIFT); |
| 90 | 107 | |
| 91 | 108 | } else { /* RX */ |
| 92 | − epctrlx |= EPCTRL_RX_ENABLE | EPCTRL_RX_DATA_TOGGLE_RST | |
| 109 | + epctrlx |= EPCTRL_RX_ENABLE | |
| 93 | 110 | | (USB_ENDPOINT_XFER_CONTROL |
| 94 | 111 | << EPCTRL_RX_EP_TYPE_SHIFT); |
| 95 | 112 | } |
| @@ -122,6 +139,7 @@ static int process_ep_req(struct mv_udc *udc, int index, · 26 unmodified lines | ||
| 122 | 139 | int i, direction; |
| 123 | 140 | int retval = 0; |
| 124 | 141 | u32 errors; |
| 142 | + u32 bit_pos; | |
| 125 | 143 | |
| 126 | 144 | curr_dqh = &udc->ep_dqh[index]; |
| 127 | 145 | direction = index % 2; |
| @@ -139,10 +157,20 @@ static int process_ep_req(struct mv_udc *udc, int index, · 11 unmodified lines | ||
| 139 | 157 | |
| 140 | 158 | errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK; |
| 141 | 159 | if (!errors) { |
| 142 | − remaining_length += | |
| 160 | + remaining_length = | |
| 143 | 161 | (curr_dtd->size_ioc_sts & DTD_PACKET_SIZE) |
| 144 | 162 | >> DTD_LENGTH_BIT_POS; |
| 145 | 163 | actual -= remaining_length; |
| 164 | + | |
| 165 | + if (remaining_length) { | |
| 166 | + if (direction) { | |
| 167 | + dev_dbg(&udc->dev->dev, | |
| 168 | + "TX dTD remains data\n"); | |
| 169 | + retval = -EPROTO; | |
| 170 | + break; | |
| 171 | + } else | |
| 172 | + break; | |
| 173 | + } | |
| 146 | 174 | } else { |
| 147 | 175 | dev_info(&udc->dev->dev, |
| 148 | 176 | "complete_tr error: ep=%d %s: error = 0x%x\n", |
| @@ -164,6 +192,20 @@ static int process_ep_req(struct mv_udc *udc, int index, · 15 unmodified lines | ||
| 164 | 192 | if (retval) |
| 165 | 193 | return retval; |
| 166 | 194 | |
| 195 | + if (direction == EP_DIR_OUT) | |
| 196 | + bit_pos = 1 << curr_req->ep->ep_num; | |
| 197 | + else | |
| 198 | + bit_pos = 1 << (16 + curr_req->ep->ep_num); | |
| 199 | + | |
| 200 | + while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) { | |
| 201 | + if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) { | |
| 202 | + while (readl(&udc->op_regs->epstatus) & bit_pos) | |
| 203 | + udelay(1); | |
| 204 | + break; | |
| 205 | + } | |
| 206 | + udelay(1); | |
| 207 | + } | |
| 208 | + | |
| 167 | 209 | curr_req->req.actual = actual; |
| 168 | 210 | |
| 169 | 211 | return 0; |
| @@ -481,6 +523,7 @@ static int mv_ep_enable(struct usb_ep *_ep, · 311 unmodified lines | ||
| 481 | 523 | u16 max = 0; |
| 482 | 524 | u32 bit_pos, epctrlx, direction; |
| 483 | 525 | unsigned char zlt = 0, ios = 0, mult = 0; |
| 526 | + unsigned long flags; | |
| 484 | 527 | |
| 485 | 528 | ep = container_of(_ep, struct mv_ep, ep); |
| 486 | 529 | udc = ep->udc; |
| @@ -493,7 +536,7 @@ static int mv_ep_enable(struct usb_ep *_ep, · 6 unmodified lines | ||
| 493 | 536 | return -ESHUTDOWN; |
| 494 | 537 | |
| 495 | 538 | direction = ep_dir(ep); |
| 496 | − max = le16_to_cpu(desc->wMaxPacketSize); | |
| 539 | + max = usb_endpoint_maxp(desc); | |
| 497 | 540 | |
| 498 | 541 | /* |
| 499 | 542 | * disable HW zero length termination select |
| @@ -501,9 +544,6 @@ static int mv_ep_enable(struct usb_ep *_ep, · 1 unmodified line | ||
| 501 | 544 | */ |
| 502 | 545 | zlt = 1; |
| 503 | 546 | |
| 504 | − /* Get the endpoint queue head address */ | |
| 505 | − dqh = (struct mv_dqh *)ep->dqh; | |
| 506 | − | |
| 507 | 547 | bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num); |
| 508 | 548 | |
| 509 | 549 | /* Check if the Endpoint is Primed */ |
| @@ -532,7 +572,7 @@ static int mv_ep_enable(struct usb_ep *_ep, · 22 unmodified lines | ||
| 532 | 572 | case USB_ENDPOINT_XFER_ISOC: |
| 533 | 573 | /* Calculate transactions needed for high bandwidth iso */ |
| 534 | 574 | mult = (unsigned char)(1 + ((max >> 11) & 0x03)); |
| 535 | − max = max & 0x8ff; /* bit 0~10 */ | |
| 575 | + max = max & 0x7ff; /* bit 0~10 */ | |
| 536 | 576 | /* 3 transactions at most */ |
| 537 | 577 | if (mult > 3) |
| 538 | 578 | goto en_done; |
| @@ -540,6 +580,10 @@ static int mv_ep_enable(struct usb_ep *_ep, · 1 unmodified line | ||
| 540 | 580 | default: |
| 541 | 581 | goto en_done; |
| 542 | 582 | } |
| 583 | + | |
| 584 | + spin_lock_irqsave(&udc->lock, flags); | |
| 585 | + /* Get the endpoint queue head address */ | |
| 586 | + dqh = ep->dqh; | |
| 543 | 587 | dqh->max_packet_length = (max << EP_QUEUE_HEAD_MAX_PKT_LEN_POS) |
| 544 | 588 | | (mult << EP_QUEUE_HEAD_MULT_POS) |
| 545 | 589 | | (zlt ? EP_QUEUE_HEAD_ZLT_SEL : 0) |
| @@ -572,18 +616,20 @@ static int mv_ep_enable(struct usb_ep *_ep, · 26 unmodified lines | ||
| 572 | 616 | */ |
| 573 | 617 | epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]); |
| 574 | 618 | if ((epctrlx & EPCTRL_RX_ENABLE) == 0) { |
| 575 | − epctrlx |= ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 619 | + epctrlx |= (USB_ENDPOINT_XFER_BULK | |
| 576 | 620 | << EPCTRL_RX_EP_TYPE_SHIFT); |
| 577 | 621 | writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]); |
| 578 | 622 | } |
| 579 | 623 | |
| 580 | 624 | epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]); |
| 581 | 625 | if ((epctrlx & EPCTRL_TX_ENABLE) == 0) { |
| 582 | − epctrlx |= ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 626 | + epctrlx |= (USB_ENDPOINT_XFER_BULK | |
| 583 | 627 | << EPCTRL_TX_EP_TYPE_SHIFT); |
| 584 | 628 | writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]); |
| 585 | 629 | } |
| 586 | 630 | |
| 631 | + spin_unlock_irqrestore(&udc->lock, flags); | |
| 632 | + | |
| 587 | 633 | return 0; |
| 588 | 634 | en_done: |
| 589 | 635 | return -EINVAL; |
| @@ -595,6 +641,7 @@ static int mv_ep_disable(struct usb_ep *_ep) · 5 unmodified lines | ||
| 595 | 641 | struct mv_ep *ep; |
| 596 | 642 | struct mv_dqh *dqh; |
| 597 | 643 | u32 bit_pos, epctrlx, direction; |
| 644 | + unsigned long flags; | |
| 598 | 645 | |
| 599 | 646 | ep = container_of(_ep, struct mv_ep, ep); |
| 600 | 647 | if ((_ep == NULL) || !ep->desc) |
| @@ -605,6 +652,8 @@ static int mv_ep_disable(struct usb_ep *_ep) · 4 unmodified lines | ||
| 605 | 652 | /* Get the endpoint queue head address */ |
| 606 | 653 | dqh = ep->dqh; |
| 607 | 654 | |
| 655 | + spin_lock_irqsave(&udc->lock, flags); | |
| 656 | + | |
| 608 | 657 | direction = ep_dir(ep); |
| 609 | 658 | bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num); |
| 610 | 659 | |
| @@ -623,6 +672,9 @@ static int mv_ep_disable(struct usb_ep *_ep) · 12 unmodified lines | ||
| 623 | 672 | |
| 624 | 673 | ep->desc = NULL; |
| 625 | 674 | ep->stopped = 1; |
| 675 | + | |
| 676 | + spin_unlock_irqrestore(&udc->lock, flags); | |
| 677 | + | |
| 626 | 678 | return 0; |
| 627 | 679 | } |
| 628 | 680 | |
| @@ -655,37 +707,28 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep) · 26 unmodified lines | ||
| 655 | 707 | { |
| 656 | 708 | struct mv_udc *udc; |
| 657 | 709 | u32 bit_pos, direction; |
| 658 | − struct mv_ep *ep = container_of(_ep, struct mv_ep, ep); | |
| 710 | + struct mv_ep *ep; | |
| 659 | 711 | unsigned int loops; |
| 660 | 712 | |
| 713 | + if (!_ep) | |
| 714 | + return; | |
| 715 | + | |
| 716 | + ep = container_of(_ep, struct mv_ep, ep); | |
| 717 | + if (!ep->desc) | |
| 718 | + return; | |
| 719 | + | |
| 661 | 720 | udc = ep->udc; |
| 662 | 721 | direction = ep_dir(ep); |
| 663 | − bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num); | |
| 664 | − /* | |
| 665 | − * Flushing will halt the pipe | |
| 666 | − * Write 1 to the Flush register | |
| 667 | − */ | |
| 668 | − writel(bit_pos, &udc->op_regs->epflush); | |
| 669 | 722 | |
| 670 | − /* Wait until flushing completed */ | |
| 671 | − loops = LOOPS(FLUSH_TIMEOUT); | |
| 672 | − while (readl(&udc->op_regs->epflush) & bit_pos) { | |
| 673 | − /* | |
| 674 | − * ENDPTFLUSH bit should be cleared to indicate this | |
| 675 | − * operation is complete | |
| 676 | − */ | |
| 677 | − if (loops == 0) { | |
| 678 | − dev_err(&udc->dev->dev, | |
| 679 | − "TIMEOUT for ENDPTFLUSH=0x%x, bit_pos=0x%x\n", | |
| 680 | − (unsigned)readl(&udc->op_regs->epflush), | |
| 681 | − (unsigned)bit_pos); | |
| 682 | − return; | |
| 683 | − } | |
| 684 | − loops--; | |
| 685 | − udelay(LOOPS_USEC); | |
| 686 | − } | |
| 723 | + if (ep->ep_num == 0) | |
| 724 | + bit_pos = (1 << 16) | 1; | |
| 725 | + else if (direction == EP_DIR_OUT) | |
| 726 | + bit_pos = 1 << ep->ep_num; | |
| 727 | + else | |
| 728 | + bit_pos = 1 << (16 + ep->ep_num); | |
| 729 | + | |
| 687 | 730 | loops = LOOPS(EPSTATUS_TIMEOUT); |
| 688 | − while (readl(&udc->op_regs->epstatus) & bit_pos) { | |
| 731 | + do { | |
| 689 | 732 | unsigned int inter_loops; |
| 690 | 733 | |
| 691 | 734 | if (loops == 0) { |
| @@ -700,7 +743,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep) · 8 unmodified lines | ||
| 700 | 743 | |
| 701 | 744 | /* Wait until flushing completed */ |
| 702 | 745 | inter_loops = LOOPS(FLUSH_TIMEOUT); |
| 703 | − while (readl(&udc->op_regs->epflush) & bit_pos) { | |
| 746 | + while (readl(&udc->op_regs->epflush)) { | |
| 704 | 747 | /* |
| 705 | 748 | * ENDPTFLUSH bit should be cleared to indicate this |
| 706 | 749 | * operation is complete |
| @@ -717,7 +760,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep) · 10 unmodified lines | ||
| 717 | 760 | udelay(LOOPS_USEC); |
| 718 | 761 | } |
| 719 | 762 | loops--; |
| 720 | − } | |
| 763 | + } while (readl(&udc->op_regs->epstatus) & bit_pos); | |
| 721 | 764 | } |
| 722 | 765 | |
| 723 | 766 | /* queues (submits) an I/O request to an endpoint */ |
| @@ -987,6 +1030,22 @@ static struct usb_ep_ops mv_ep_ops = { · 263 unmodified lines | ||
| 987 | 1030 | .fifo_flush = mv_ep_fifo_flush, /* flush fifo */ |
| 988 | 1031 | }; |
| 989 | 1032 | |
| 1033 | +static void udc_clock_enable(struct mv_udc *udc) | |
| 1034 | +{ | |
| 1035 | + unsigned int i; | |
| 1036 | + | |
| 1037 | + for (i = 0; i < udc->clknum; i++) | |
| 1038 | + clk_enable(udc->clk[i]); | |
| 1039 | +} | |
| 1040 | + | |
| 1041 | +static void udc_clock_disable(struct mv_udc *udc) | |
| 1042 | +{ | |
| 1043 | + unsigned int i; | |
| 1044 | + | |
| 1045 | + for (i = 0; i < udc->clknum; i++) | |
| 1046 | + clk_disable(udc->clk[i]); | |
| 1047 | +} | |
| 1048 | + | |
| 990 | 1049 | static void udc_stop(struct mv_udc *udc) |
| 991 | 1050 | { |
| 992 | 1051 | u32 tmp; |
| @@ -1075,6 +1134,40 @@ static int udc_reset(struct mv_udc *udc) · 82 unmodified lines | ||
| 1075 | 1134 | return 0; |
| 1076 | 1135 | } |
| 1077 | 1136 | |
| 1137 | +static int mv_udc_enable(struct mv_udc *udc) | |
| 1138 | +{ | |
| 1139 | + int retval; | |
| 1140 | + | |
| 1141 | + if (udc->clock_gating == 0 || udc->active) | |
| 1142 | + return 0; | |
| 1143 | + | |
| 1144 | + dev_dbg(&udc->dev->dev, "enable udc\n"); | |
| 1145 | + udc_clock_enable(udc); | |
| 1146 | + if (udc->pdata->phy_init) { | |
| 1147 | + retval = udc->pdata->phy_init(udc->phy_regs); | |
| 1148 | + if (retval) { | |
| 1149 | + dev_err(&udc->dev->dev, | |
| 1150 | + "init phy error %d\n", retval); | |
| 1151 | + udc_clock_disable(udc); | |
| 1152 | + return retval; | |
| 1153 | + } | |
| 1154 | + } | |
| 1155 | + udc->active = 1; | |
| 1156 | + | |
| 1157 | + return 0; | |
| 1158 | +} | |
| 1159 | + | |
| 1160 | +static void mv_udc_disable(struct mv_udc *udc) | |
| 1161 | +{ | |
| 1162 | + if (udc->clock_gating && udc->active) { | |
| 1163 | + dev_dbg(&udc->dev->dev, "disable udc\n"); | |
| 1164 | + if (udc->pdata->phy_deinit) | |
| 1165 | + udc->pdata->phy_deinit(udc->phy_regs); | |
| 1166 | + udc_clock_disable(udc); | |
| 1167 | + udc->active = 0; | |
| 1168 | + } | |
| 1169 | +} | |
| 1170 | + | |
| 1078 | 1171 | static int mv_udc_get_frame(struct usb_gadget *gadget) |
| 1079 | 1172 | { |
| 1080 | 1173 | struct mv_udc *udc; |
| @@ -1110,22 +1203,68 @@ static int mv_udc_wakeup(struct usb_gadget *gadget) · 29 unmodified lines | ||
| 1110 | 1203 | return 0; |
| 1111 | 1204 | } |
| 1112 | 1205 | |
| 1206 | +static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active) | |
| 1207 | +{ | |
| 1208 | + struct mv_udc *udc; | |
| 1209 | + unsigned long flags; | |
| 1210 | + int retval = 0; | |
| 1211 | + | |
| 1212 | + udc = container_of(gadget, struct mv_udc, gadget); | |
| 1213 | + spin_lock_irqsave(&udc->lock, flags); | |
| 1214 | + | |
| 1215 | + dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n", | |
| 1216 | + __func__, udc->softconnect, udc->vbus_active); | |
| 1217 | + | |
| 1218 | + udc->vbus_active = (is_active != 0); | |
| 1219 | + if (udc->driver && udc->softconnect && udc->vbus_active) { | |
| 1220 | + retval = mv_udc_enable(udc); | |
| 1221 | + if (retval == 0) { | |
| 1222 | + /* Clock is disabled, need re-init registers */ | |
| 1223 | + udc_reset(udc); | |
| 1224 | + ep0_reset(udc); | |
| 1225 | + udc_start(udc); | |
| 1226 | + } | |
| 1227 | + } else if (udc->driver && udc->softconnect) { | |
| 1228 | + /* stop all the transfer in queue*/ | |
| 1229 | + stop_activity(udc, udc->driver); | |
| 1230 | + udc_stop(udc); | |
| 1231 | + mv_udc_disable(udc); | |
| 1232 | + } | |
| 1233 | + | |
| 1234 | + spin_unlock_irqrestore(&udc->lock, flags); | |
| 1235 | + return retval; | |
| 1236 | +} | |
| 1237 | + | |
| 1113 | 1238 | static int mv_udc_pullup(struct usb_gadget *gadget, int is_on) |
| 1114 | 1239 | { |
| 1115 | 1240 | struct mv_udc *udc; |
| 1116 | 1241 | unsigned long flags; |
| 1242 | + int retval = 0; | |
| 1117 | 1243 | |
| 1118 | 1244 | udc = container_of(gadget, struct mv_udc, gadget); |
| 1119 | 1245 | spin_lock_irqsave(&udc->lock, flags); |
| 1120 | 1246 | |
| 1247 | + dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n", | |
| 1248 | + __func__, udc->softconnect, udc->vbus_active); | |
| 1249 | + | |
| 1121 | 1250 | udc->softconnect = (is_on != 0); |
| 1122 | − if (udc->driver && udc->softconnect) | |
| 1123 | − udc_start(udc); | |
| 1124 | − else | |
| 1251 | + if (udc->driver && udc->softconnect && udc->vbus_active) { | |
| 1252 | + retval = mv_udc_enable(udc); | |
| 1253 | + if (retval == 0) { | |
| 1254 | + /* Clock is disabled, need re-init registers */ | |
| 1255 | + udc_reset(udc); | |
| 1256 | + ep0_reset(udc); | |
| 1257 | + udc_start(udc); | |
| 1258 | + } | |
| 1259 | + } else if (udc->driver && udc->vbus_active) { | |
| 1260 | + /* stop all the transfer in queue*/ | |
| 1261 | + stop_activity(udc, udc->driver); | |
| 1125 | 1262 | udc_stop(udc); |
| 1263 | + mv_udc_disable(udc); | |
| 1264 | + } | |
| 1126 | 1265 | |
| 1127 | 1266 | spin_unlock_irqrestore(&udc->lock, flags); |
| 1128 | − return 0; | |
| 1267 | + return retval; | |
| 1129 | 1268 | } |
| 1130 | 1269 | |
| 1131 | 1270 | static int mv_udc_start(struct usb_gadget_driver *driver, |
| @@ -1140,17 +1279,15 @@ static const struct usb_gadget_ops mv_ops = { · 8 unmodified lines | ||
| 1140 | 1279 | /* tries to wake up the host connected to this gadget */ |
| 1141 | 1280 | .wakeup = mv_udc_wakeup, |
| 1142 | 1281 | |
| 1282 | + /* notify controller that VBUS is powered or not */ | |
| 1283 | + .vbus_session = mv_udc_vbus_session, | |
| 1284 | + | |
| 1143 | 1285 | /* D+ pullup, software-controlled connect/disconnect to USB host */ |
| 1144 | 1286 | .pullup = mv_udc_pullup, |
| 1145 | 1287 | .start = mv_udc_start, |
| 1146 | 1288 | .stop = mv_udc_stop, |
| 1147 | 1289 | }; |
| 1148 | 1290 | |
| 1149 | −static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter) | |
| 1150 | −{ | |
| 1151 | − dev_info(&udc->dev->dev, "Test Mode is not support yet\n"); | |
| 1152 | −} | |
| 1153 | − | |
| 1154 | 1291 | static int eps_init(struct mv_udc *udc) |
| 1155 | 1292 | { |
| 1156 | 1293 | struct mv_ep *ep; |
| @@ -1257,7 +1394,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver, · 100 unmodified lines | ||
| 1257 | 1394 | |
| 1258 | 1395 | udc->usb_state = USB_STATE_ATTACHED; |
| 1259 | 1396 | udc->ep0_state = WAIT_FOR_SETUP; |
| 1260 | − udc->ep0_dir = USB_DIR_OUT; | |
| 1397 | + udc->ep0_dir = EP_DIR_OUT; | |
| 1261 | 1398 | |
| 1262 | 1399 | spin_unlock_irqrestore(&udc->lock, flags); |
| 1263 | 1400 | |
| @@ -1269,9 +1406,13 @@ static int mv_udc_start(struct usb_gadget_driver *driver, · 5 unmodified lines | ||
| 1269 | 1406 | udc->gadget.dev.driver = NULL; |
| 1270 | 1407 | return retval; |
| 1271 | 1408 | } |
| 1272 | − udc_reset(udc); | |
| 1273 | − ep0_reset(udc); | |
| 1274 | − udc_start(udc); | |
| 1409 | + | |
| 1410 | + /* pullup is always on */ | |
| 1411 | + mv_udc_pullup(&udc->gadget, 1); | |
| 1412 | + | |
| 1413 | + /* When boot with cable attached, there will be no vbus irq occurred */ | |
| 1414 | + if (udc->qwork) | |
| 1415 | + queue_work(udc->qwork, &udc->vbus_work); | |
| 1275 | 1416 | |
| 1276 | 1417 | return 0; |
| 1277 | 1418 | } |
| @@ -1284,13 +1425,16 @@ static int mv_udc_stop(struct usb_gadget_driver *driver) · 6 unmodified lines | ||
| 1284 | 1425 | if (!udc) |
| 1285 | 1426 | return -ENODEV; |
| 1286 | 1427 | |
| 1287 | − udc_stop(udc); | |
| 1288 | − | |
| 1289 | 1428 | spin_lock_irqsave(&udc->lock, flags); |
| 1290 | 1429 | |
| 1430 | + mv_udc_enable(udc); | |
| 1431 | + udc_stop(udc); | |
| 1432 | + | |
| 1291 | 1433 | /* stop all usb activities */ |
| 1292 | 1434 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
| 1293 | 1435 | stop_activity(udc, driver); |
| 1436 | + mv_udc_disable(udc); | |
| 1437 | + | |
| 1294 | 1438 | spin_unlock_irqrestore(&udc->lock, flags); |
| 1295 | 1439 | |
| 1296 | 1440 | /* unbind gadget driver */ |
| @@ -1301,6 +1445,31 @@ static int mv_udc_stop(struct usb_gadget_driver *driver) · 4 unmodified lines | ||
| 1301 | 1445 | return 0; |
| 1302 | 1446 | } |
| 1303 | 1447 | |
| 1448 | +static void mv_set_ptc(struct mv_udc *udc, u32 mode) | |
| 1449 | +{ | |
| 1450 | + u32 portsc; | |
| 1451 | + | |
| 1452 | + portsc = readl(&udc->op_regs->portsc[0]); | |
| 1453 | + portsc |= mode << 16; | |
| 1454 | + writel(portsc, &udc->op_regs->portsc[0]); | |
| 1455 | +} | |
| 1456 | + | |
| 1457 | +static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req) | |
| 1458 | +{ | |
| 1459 | + struct mv_udc *udc = the_controller; | |
| 1460 | + struct mv_req *req = container_of(_req, struct mv_req, req); | |
| 1461 | + unsigned long flags; | |
| 1462 | + | |
| 1463 | + dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode); | |
| 1464 | + | |
| 1465 | + spin_lock_irqsave(&udc->lock, flags); | |
| 1466 | + if (req->test_mode) { | |
| 1467 | + mv_set_ptc(udc, req->test_mode); | |
| 1468 | + req->test_mode = 0; | |
| 1469 | + } | |
| 1470 | + spin_unlock_irqrestore(&udc->lock, flags); | |
| 1471 | +} | |
| 1472 | + | |
| 1304 | 1473 | static int |
| 1305 | 1474 | udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) |
| 1306 | 1475 | { |
| @@ -1310,6 +1479,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) · 3 unmodified lines | ||
| 1310 | 1479 | |
| 1311 | 1480 | ep = &udc->eps[0]; |
| 1312 | 1481 | udc->ep0_dir = direction; |
| 1482 | + udc->ep0_state = WAIT_FOR_OUT_STATUS; | |
| 1313 | 1483 | |
| 1314 | 1484 | req = udc->status_req; |
| 1315 | 1485 | |
| @@ -1323,9 +1493,21 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) · 7 unmodified lines | ||
| 1323 | 1493 | req->ep = ep; |
| 1324 | 1494 | req->req.status = -EINPROGRESS; |
| 1325 | 1495 | req->req.actual = 0; |
| 1326 | − req->req.complete = NULL; | |
| 1496 | + if (udc->test_mode) { | |
| 1497 | + req->req.complete = prime_status_complete; | |
| 1498 | + req->test_mode = udc->test_mode; | |
| 1499 | + udc->test_mode = 0; | |
| 1500 | + } else | |
| 1501 | + req->req.complete = NULL; | |
| 1327 | 1502 | req->dtd_count = 0; |
| 1328 | 1503 | |
| 1504 | + if (req->req.dma == DMA_ADDR_INVALID) { | |
| 1505 | + req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, | |
| 1506 | + req->req.buf, req->req.length, | |
| 1507 | + ep_dir(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 1508 | + req->mapped = 1; | |
| 1509 | + } | |
| 1510 | + | |
| 1329 | 1511 | /* prime the data phase */ |
| 1330 | 1512 | if (!req_to_dtd(req)) |
| 1331 | 1513 | retval = queue_dtd(ep, req); |
| @@ -1346,6 +1528,17 @@ out: · 14 unmodified lines | ||
| 1346 | 1528 | return retval; |
| 1347 | 1529 | } |
| 1348 | 1530 | |
| 1531 | +static void mv_udc_testmode(struct mv_udc *udc, u16 index) | |
| 1532 | +{ | |
| 1533 | + if (index <= TEST_FORCE_EN) { | |
| 1534 | + udc->test_mode = index; | |
| 1535 | + if (udc_prime_status(udc, EP_DIR_IN, 0, true)) | |
| 1536 | + ep0_stall(udc); | |
| 1537 | + } else | |
| 1538 | + dev_err(&udc->dev->dev, | |
| 1539 | + "This test mode(%d) is not supported\n", index); | |
| 1540 | +} | |
| 1541 | + | |
| 1349 | 1542 | static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) |
| 1350 | 1543 | { |
| 1351 | 1544 | udc->dev_addr = (u8)setup->wValue; |
| @@ -1360,7 +1553,7 @@ static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) · 8 unmodified lines | ||
| 1360 | 1553 | static void ch9getstatus(struct mv_udc *udc, u8 ep_num, |
| 1361 | 1554 | struct usb_ctrlrequest *setup) |
| 1362 | 1555 | { |
| 1363 | − u16 status; | |
| 1556 | + u16 status = 0; | |
| 1364 | 1557 | int retval; |
| 1365 | 1558 | |
| 1366 | 1559 | if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) |
| @@ -1388,6 +1581,8 @@ static void ch9getstatus(struct mv_udc *udc, u8 ep_num, · 21 unmodified lines | ||
| 1388 | 1581 | retval = udc_prime_status(udc, EP_DIR_IN, status, false); |
| 1389 | 1582 | if (retval) |
| 1390 | 1583 | ep0_stall(udc); |
| 1584 | + else | |
| 1585 | + udc->ep0_state = DATA_STATE_XMIT; | |
| 1391 | 1586 | } |
| 1392 | 1587 | |
| 1393 | 1588 | static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) |
| @@ -1402,9 +1597,6 @@ static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) · 8 unmodified lines | ||
| 1402 | 1597 | case USB_DEVICE_REMOTE_WAKEUP: |
| 1403 | 1598 | udc->remote_wakeup = 0; |
| 1404 | 1599 | break; |
| 1405 | − case USB_DEVICE_TEST_MODE: | |
| 1406 | − mv_udc_testmode(udc, 0, false); | |
| 1407 | − break; | |
| 1408 | 1600 | default: |
| 1409 | 1601 | goto out; |
| 1410 | 1602 | } |
| @@ -1433,8 +1625,6 @@ static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) · 22 unmodified lines | ||
| 1433 | 1625 | |
| 1434 | 1626 | if (udc_prime_status(udc, EP_DIR_IN, 0, true)) |
| 1435 | 1627 | ep0_stall(udc); |
| 1436 | − else | |
| 1437 | − udc->ep0_state = DATA_STATE_XMIT; | |
| 1438 | 1628 | out: |
| 1439 | 1629 | return; |
| 1440 | 1630 | } |
| @@ -1452,16 +1642,16 @@ static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) · 11 unmodified lines | ||
| 1452 | 1642 | break; |
| 1453 | 1643 | case USB_DEVICE_TEST_MODE: |
| 1454 | 1644 | if (setup->wIndex & 0xFF |
| 1455 | − && udc->gadget.speed != USB_SPEED_HIGH) | |
| 1456 | − goto out; | |
| 1457 | − if (udc->usb_state == USB_STATE_CONFIGURED | |
| 1458 | − || udc->usb_state == USB_STATE_ADDRESS | |
| 1459 | − || udc->usb_state == USB_STATE_DEFAULT) | |
| 1460 | − mv_udc_testmode(udc, | |
| 1461 | − setup->wIndex & 0xFF00, true); | |
| 1462 | − else | |
| 1463 | − goto out; | |
| 1464 | − break; | |
| 1645 | + || udc->gadget.speed != USB_SPEED_HIGH) | |
| 1646 | + ep0_stall(udc); | |
| 1647 | + | |
| 1648 | + if (udc->usb_state != USB_STATE_CONFIGURED | |
| 1649 | + && udc->usb_state != USB_STATE_ADDRESS | |
| 1650 | + && udc->usb_state != USB_STATE_DEFAULT) | |
| 1651 | + ep0_stall(udc); | |
| 1652 | + | |
| 1653 | + mv_udc_testmode(udc, (setup->wIndex >> 8)); | |
| 1654 | + goto out; | |
| 1465 | 1655 | default: |
| 1466 | 1656 | goto out; |
| 1467 | 1657 | } |
| @@ -1599,8 +1789,7 @@ static void get_setup_data(struct mv_udc *udc, u8 ep_num, u8 *buffer_ptr) · 131 unmodified lines | ||
| 1599 | 1789 | dqh = &udc->ep_dqh[ep_num * 2 + EP_DIR_OUT]; |
| 1600 | 1790 | |
| 1601 | 1791 | /* Clear bit in ENDPTSETUPSTAT */ |
| 1602 | − temp = readl(&udc->op_regs->epsetupstat); | |
| 1603 | − writel(temp | (1 << ep_num), &udc->op_regs->epsetupstat); | |
| 1792 | + writel((1 << ep_num), &udc->op_regs->epsetupstat); | |
| 1604 | 1793 | |
| 1605 | 1794 | /* while a hazard exists when setup package arrives */ |
| 1606 | 1795 | do { |
| @@ -1871,23 +2060,57 @@ static irqreturn_t mv_udc_irq(int irq, void *dev) · 264 unmodified lines | ||
| 1871 | 2060 | return IRQ_HANDLED; |
| 1872 | 2061 | } |
| 1873 | 2062 | |
| 2063 | +static irqreturn_t mv_udc_vbus_irq(int irq, void *dev) | |
| 2064 | +{ | |
| 2065 | + struct mv_udc *udc = (struct mv_udc *)dev; | |
| 2066 | + | |
| 2067 | + /* polling VBUS and init phy may cause too much time*/ | |
| 2068 | + if (udc->qwork) | |
| 2069 | + queue_work(udc->qwork, &udc->vbus_work); | |
| 2070 | + | |
| 2071 | + return IRQ_HANDLED; | |
| 2072 | +} | |
| 2073 | + | |
| 2074 | +static void mv_udc_vbus_work(struct work_struct *work) | |
| 2075 | +{ | |
| 2076 | + struct mv_udc *udc; | |
| 2077 | + unsigned int vbus; | |
| 2078 | + | |
| 2079 | + udc = container_of(work, struct mv_udc, vbus_work); | |
| 2080 | + if (!udc->pdata->vbus) | |
| 2081 | + return; | |
| 2082 | + | |
| 2083 | + vbus = udc->pdata->vbus->poll(); | |
| 2084 | + dev_info(&udc->dev->dev, "vbus is %d\n", vbus); | |
| 2085 | + | |
| 2086 | + if (vbus == VBUS_HIGH) | |
| 2087 | + mv_udc_vbus_session(&udc->gadget, 1); | |
| 2088 | + else if (vbus == VBUS_LOW) | |
| 2089 | + mv_udc_vbus_session(&udc->gadget, 0); | |
| 2090 | +} | |
| 2091 | + | |
| 1874 | 2092 | /* release device structure */ |
| 1875 | 2093 | static void gadget_release(struct device *_dev) |
| 1876 | 2094 | { |
| 1877 | 2095 | struct mv_udc *udc = the_controller; |
| 1878 | 2096 | |
| 1879 | 2097 | complete(udc->done); |
| 1880 | − kfree(udc); | |
| 1881 | 2098 | } |
| 1882 | 2099 | |
| 1883 | −static int mv_udc_remove(struct platform_device *dev) | |
| 2100 | +static int __devexit mv_udc_remove(struct platform_device *dev) | |
| 1884 | 2101 | { |
| 1885 | 2102 | struct mv_udc *udc = the_controller; |
| 1886 | − DECLARE_COMPLETION(done); | |
| 2103 | + int clk_i; | |
| 1887 | 2104 | |
| 1888 | 2105 | usb_del_gadget_udc(&udc->gadget); |
| 1889 | 2106 | |
| 1890 | − udc->done = &done; | |
| 2107 | + if (udc->qwork) { | |
| 2108 | + flush_workqueue(udc->qwork); | |
| 2109 | + destroy_workqueue(udc->qwork); | |
| 2110 | + } | |
| 2111 | + | |
| 2112 | + if (udc->pdata && udc->pdata->vbus && udc->clock_gating) | |
| 2113 | + free_irq(udc->pdata->vbus->irq, &dev->dev); | |
| 1891 | 2114 | |
| 1892 | 2115 | /* free memory allocated in probe */ |
| 1893 | 2116 | if (udc->dtd_pool) |
| @@ -1902,6 +2125,8 @@ static int mv_udc_remove(struct platform_device *dev) · 8 unmodified lines | ||
| 1902 | 2125 | if (udc->irq) |
| 1903 | 2126 | free_irq(udc->irq, &dev->dev); |
| 1904 | 2127 | |
| 2128 | + mv_udc_disable(udc); | |
| 2129 | + | |
| 1905 | 2130 | if (udc->cap_regs) |
| 1906 | 2131 | iounmap(udc->cap_regs); |
| 1907 | 2132 | udc->cap_regs = NULL; |
| @@ -1915,45 +2140,62 @@ static int mv_udc_remove(struct platform_device *dev) · 7 unmodified lines | ||
| 1915 | 2140 | kfree(udc->status_req); |
| 1916 | 2141 | } |
| 1917 | 2142 | |
| 2143 | + for (clk_i = 0; clk_i <= udc->clknum; clk_i++) | |
| 2144 | + clk_put(udc->clk[clk_i]); | |
| 2145 | + | |
| 1918 | 2146 | device_unregister(&udc->gadget.dev); |
| 1919 | 2147 | |
| 1920 | 2148 | /* free dev, wait for the release() finished */ |
| 1921 | − wait_for_completion(&done); | |
| 2149 | + wait_for_completion(udc->done); | |
| 2150 | + kfree(udc); | |
| 1922 | 2151 | |
| 1923 | 2152 | the_controller = NULL; |
| 1924 | 2153 | |
| 1925 | 2154 | return 0; |
| 1926 | 2155 | } |
| 1927 | 2156 | |
| 1928 | −int mv_udc_probe(struct platform_device *dev) | |
| 2157 | +static int __devinit mv_udc_probe(struct platform_device *dev) | |
| 1929 | 2158 | { |
| 2159 | + struct mv_usb_platform_data *pdata = dev->dev.platform_data; | |
| 1930 | 2160 | struct mv_udc *udc; |
| 1931 | 2161 | int retval = 0; |
| 2162 | + int clk_i = 0; | |
| 1932 | 2163 | struct resource *r; |
| 1933 | 2164 | size_t size; |
| 1934 | 2165 | |
| 1935 | − udc = kzalloc(sizeof *udc, GFP_KERNEL); | |
| 2166 | + if (pdata == NULL) { | |
| 2167 | + dev_err(&dev->dev, "missing platform_data\n"); | |
| 2168 | + return -ENODEV; | |
| 2169 | + } | |
| 2170 | + | |
| 2171 | + size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum; | |
| 2172 | + udc = kzalloc(size, GFP_KERNEL); | |
| 1936 | 2173 | if (udc == NULL) { |
| 1937 | 2174 | dev_err(&dev->dev, "failed to allocate memory for udc\n"); |
| 1938 | − retval = -ENOMEM; | |
| 1939 | − goto error; | |
| 2175 | + return -ENOMEM; | |
| 1940 | 2176 | } |
| 1941 | 2177 | |
| 2178 | + the_controller = udc; | |
| 2179 | + udc->done = &release_done; | |
| 2180 | + udc->pdata = dev->dev.platform_data; | |
| 1942 | 2181 | spin_lock_init(&udc->lock); |
| 1943 | 2182 | |
| 1944 | 2183 | udc->dev = dev; |
| 1945 | 2184 | |
| 1946 | − udc->clk = clk_get(&dev->dev, "U2OCLK"); | |
| 1947 | − if (IS_ERR(udc->clk)) { | |
| 1948 | − retval = PTR_ERR(udc->clk); | |
| 1949 | − goto error; | |
| 2185 | + udc->clknum = pdata->clknum; | |
| 2186 | + for (clk_i = 0; clk_i < udc->clknum; clk_i++) { | |
| 2187 | + udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]); | |
| 2188 | + if (IS_ERR(udc->clk[clk_i])) { | |
| 2189 | + retval = PTR_ERR(udc->clk[clk_i]); | |
| 2190 | + goto err_put_clk; | |
| 2191 | + } | |
| 1950 | 2192 | } |
| 1951 | 2193 | |
| 1952 | − r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2o"); | |
| 2194 | + r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs"); | |
| 1953 | 2195 | if (r == NULL) { |
| 1954 | 2196 | dev_err(&dev->dev, "no I/O memory resource defined\n"); |
| 1955 | 2197 | retval = -ENODEV; |
| 1956 | − goto error; | |
| 2198 | + goto err_put_clk; | |
| 1957 | 2199 | } |
| 1958 | 2200 | |
| 1959 | 2201 | udc->cap_regs = (struct mv_cap_regs __iomem *) |
| @@ -1961,29 +2203,31 @@ int mv_udc_probe(struct platform_device *dev) · 1 unmodified line | ||
| 1961 | 2203 | if (udc->cap_regs == NULL) { |
| 1962 | 2204 | dev_err(&dev->dev, "failed to map I/O memory\n"); |
| 1963 | 2205 | retval = -EBUSY; |
| 1964 | − goto error; | |
| 2206 | + goto err_put_clk; | |
| 1965 | 2207 | } |
| 1966 | 2208 | |
| 1967 | − r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2ophy"); | |
| 2209 | + r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs"); | |
| 1968 | 2210 | if (r == NULL) { |
| 1969 | 2211 | dev_err(&dev->dev, "no phy I/O memory resource defined\n"); |
| 1970 | 2212 | retval = -ENODEV; |
| 1971 | − goto error; | |
| 2213 | + goto err_iounmap_capreg; | |
| 1972 | 2214 | } |
| 1973 | 2215 | |
| 1974 | 2216 | udc->phy_regs = (unsigned int)ioremap(r->start, resource_size(r)); |
| 1975 | 2217 | if (udc->phy_regs == 0) { |
| 1976 | 2218 | dev_err(&dev->dev, "failed to map phy I/O memory\n"); |
| 1977 | 2219 | retval = -EBUSY; |
| 1978 | − goto error; | |
| 2220 | + goto err_iounmap_capreg; | |
| 1979 | 2221 | } |
| 1980 | 2222 | |
| 1981 | 2223 | /* we will acces controller register, so enable the clk */ |
| 1982 | − clk_enable(udc->clk); | |
| 1983 | − retval = mv_udc_phy_init(udc->phy_regs); | |
| 1984 | − if (retval) { | |
| 1985 | − dev_err(&dev->dev, "phy initialization error %d\n", retval); | |
| 1986 | − goto error; | |
| 2224 | + udc_clock_enable(udc); | |
| 2225 | + if (pdata->phy_init) { | |
| 2226 | + retval = pdata->phy_init(udc->phy_regs); | |
| 2227 | + if (retval) { | |
| 2228 | + dev_err(&dev->dev, "phy init error %d\n", retval); | |
| 2229 | + goto err_iounmap_phyreg; | |
| 2230 | + } | |
| 1987 | 2231 | } |
| 1988 | 2232 | |
| 1989 | 2233 | udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs |
| @@ -1991,6 +2235,13 @@ int mv_udc_probe(struct platform_device *dev) · 1 unmodified line | ||
| 1991 | 2235 | & CAPLENGTH_MASK)); |
| 1992 | 2236 | udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK; |
| 1993 | 2237 | |
| 2238 | + /* | |
| 2239 | + * some platform will use usb to download image, it may not disconnect | |
| 2240 | + * usb gadget before loading kernel. So first stop udc here. | |
| 2241 | + */ | |
| 2242 | + udc_stop(udc); | |
| 2243 | + writel(0xFFFFFFFF, &udc->op_regs->usbsts); | |
| 2244 | + | |
| 1994 | 2245 | size = udc->max_eps * sizeof(struct mv_dqh) *2; |
| 1995 | 2246 | size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1); |
| 1996 | 2247 | udc->ep_dqh = dma_alloc_coherent(&dev->dev, size, |
| @@ -1999,7 +2250,7 @@ int mv_udc_probe(struct platform_device *dev) · 2 unmodified lines | ||
| 1999 | 2250 | if (udc->ep_dqh == NULL) { |
| 2000 | 2251 | dev_err(&dev->dev, "allocate dQH memory failed\n"); |
| 2001 | 2252 | retval = -ENOMEM; |
| 2002 | − goto error; | |
| 2253 | + goto err_disable_clock; | |
| 2003 | 2254 | } |
| 2004 | 2255 | udc->ep_dqh_size = size; |
| 2005 | 2256 | |
| @@ -2012,7 +2263,7 @@ int mv_udc_probe(struct platform_device *dev) · 6 unmodified lines | ||
| 2012 | 2263 | |
| 2013 | 2264 | if (!udc->dtd_pool) { |
| 2014 | 2265 | retval = -ENOMEM; |
| 2015 | − goto error; | |
| 2266 | + goto err_free_dma; | |
| 2016 | 2267 | } |
| 2017 | 2268 | |
| 2018 | 2269 | size = udc->max_eps * sizeof(struct mv_ep) *2; |
| @@ -2020,7 +2271,7 @@ int mv_udc_probe(struct platform_device *dev) · 1 unmodified line | ||
| 2020 | 2271 | if (udc->eps == NULL) { |
| 2021 | 2272 | dev_err(&dev->dev, "allocate ep memory failed\n"); |
| 2022 | 2273 | retval = -ENOMEM; |
| 2023 | − goto error; | |
| 2274 | + goto err_destroy_dma; | |
| 2024 | 2275 | } |
| 2025 | 2276 | |
| 2026 | 2277 | /* initialize ep0 status request structure */ |
| @@ -2028,13 +2279,13 @@ int mv_udc_probe(struct platform_device *dev) · 1 unmodified line | ||
| 2028 | 2279 | if (!udc->status_req) { |
| 2029 | 2280 | dev_err(&dev->dev, "allocate status_req memory failed\n"); |
| 2030 | 2281 | retval = -ENOMEM; |
| 2031 | − goto error; | |
| 2282 | + goto err_free_eps; | |
| 2032 | 2283 | } |
| 2033 | 2284 | INIT_LIST_HEAD(&udc->status_req->queue); |
| 2034 | 2285 | |
| 2035 | 2286 | /* allocate a small amount of memory to get valid address */ |
| 2036 | 2287 | udc->status_req->req.buf = kzalloc(8, GFP_KERNEL); |
| 2037 | − udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf); | |
| 2288 | + udc->status_req->req.dma = DMA_ADDR_INVALID; | |
| 2038 | 2289 | |
| 2039 | 2290 | udc->resume_state = USB_STATE_NOTATTACHED; |
| 2040 | 2291 | udc->usb_state = USB_STATE_POWERED; |
| @@ -2045,15 +2296,15 @@ int mv_udc_probe(struct platform_device *dev) · 4 unmodified lines | ||
| 2045 | 2296 | if (r == NULL) { |
| 2046 | 2297 | dev_err(&dev->dev, "no IRQ resource defined\n"); |
| 2047 | 2298 | retval = -ENODEV; |
| 2048 | − goto error; | |
| 2299 | + goto err_free_status_req; | |
| 2049 | 2300 | } |
| 2050 | 2301 | udc->irq = r->start; |
| 2051 | 2302 | if (request_irq(udc->irq, mv_udc_irq, |
| 2052 | − IRQF_DISABLED | IRQF_SHARED, driver_name, udc)) { | |
| 2303 | + IRQF_SHARED, driver_name, udc)) { | |
| 2053 | 2304 | dev_err(&dev->dev, "Request irq %d for UDC failed\n", |
| 2054 | 2305 | udc->irq); |
| 2055 | 2306 | retval = -ENODEV; |
| 2056 | − goto error; | |
| 2307 | + goto err_free_status_req; | |
| 2057 | 2308 | } |
| 2058 | 2309 | |
| 2059 | 2310 | /* initialize gadget structure */ |
| @@ -2072,18 +2323,82 @@ int mv_udc_probe(struct platform_device *dev) · 12 unmodified lines | ||
| 2072 | 2323 | |
| 2073 | 2324 | retval = device_register(&udc->gadget.dev); |
| 2074 | 2325 | if (retval) |
| 2075 | − goto error; | |
| 2326 | + goto err_free_irq; | |
| 2076 | 2327 | |
| 2077 | 2328 | eps_init(udc); |
| 2078 | 2329 | |
| 2079 | − the_controller = udc; | |
| 2330 | + /* VBUS detect: we can disable/enable clock on demand.*/ | |
| 2331 | + if (pdata->vbus) { | |
| 2332 | + udc->clock_gating = 1; | |
| 2333 | + retval = request_threaded_irq(pdata->vbus->irq, NULL, | |
| 2334 | + mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc); | |
| 2335 | + if (retval) { | |
| 2336 | + dev_info(&dev->dev, | |
| 2337 | + "Can not request irq for VBUS, " | |
| 2338 | + "disable clock gating\n"); | |
| 2339 | + udc->clock_gating = 0; | |
| 2340 | + } | |
| 2341 | + | |
| 2342 | + udc->qwork = create_singlethread_workqueue("mv_udc_queue"); | |
| 2343 | + if (!udc->qwork) { | |
| 2344 | + dev_err(&dev->dev, "cannot create workqueue\n"); | |
| 2345 | + retval = -ENOMEM; | |
| 2346 | + goto err_unregister; | |
| 2347 | + } | |
| 2348 | + | |
| 2349 | + INIT_WORK(&udc->vbus_work, mv_udc_vbus_work); | |
| 2350 | + } | |
| 2351 | + | |
| 2352 | + /* | |
| 2353 | + * When clock gating is supported, we can disable clk and phy. | |
| 2354 | + * If not, it means that VBUS detection is not supported, we | |
| 2355 | + * have to enable vbus active all the time to let controller work. | |
| 2356 | + */ | |
| 2357 | + if (udc->clock_gating) { | |
| 2358 | + if (udc->pdata->phy_deinit) | |
| 2359 | + udc->pdata->phy_deinit(udc->phy_regs); | |
| 2360 | + udc_clock_disable(udc); | |
| 2361 | + } else | |
| 2362 | + udc->vbus_active = 1; | |
| 2080 | 2363 | |
| 2081 | 2364 | retval = usb_add_gadget_udc(&dev->dev, &udc->gadget); |
| 2082 | − if (!retval) | |
| 2083 | − return retval; | |
| 2084 | −error: | |
| 2085 | − if (udc) | |
| 2086 | − mv_udc_remove(udc->dev); | |
| 2365 | + if (retval) | |
| 2366 | + goto err_unregister; | |
| 2367 | + | |
| 2368 | + dev_info(&dev->dev, "successful probe UDC device %s clock gating.\n", | |
| 2369 | + udc->clock_gating ? "with" : "without"); | |
| 2370 | + | |
| 2371 | + return 0; | |
| 2372 | + | |
| 2373 | +err_unregister: | |
| 2374 | + if (udc->pdata && udc->pdata->vbus && udc->clock_gating) | |
| 2375 | + free_irq(pdata->vbus->irq, &dev->dev); | |
| 2376 | + device_unregister(&udc->gadget.dev); | |
| 2377 | +err_free_irq: | |
| 2378 | + free_irq(udc->irq, &dev->dev); | |
| 2379 | +err_free_status_req: | |
| 2380 | + kfree(udc->status_req->req.buf); | |
| 2381 | + kfree(udc->status_req); | |
| 2382 | +err_free_eps: | |
| 2383 | + kfree(udc->eps); | |
| 2384 | +err_destroy_dma: | |
| 2385 | + dma_pool_destroy(udc->dtd_pool); | |
| 2386 | +err_free_dma: | |
| 2387 | + dma_free_coherent(&dev->dev, udc->ep_dqh_size, | |
| 2388 | + udc->ep_dqh, udc->ep_dqh_dma); | |
| 2389 | +err_disable_clock: | |
| 2390 | + if (udc->pdata->phy_deinit) | |
| 2391 | + udc->pdata->phy_deinit(udc->phy_regs); | |
| 2392 | + udc_clock_disable(udc); | |
| 2393 | +err_iounmap_phyreg: | |
| 2394 | + iounmap((void *)udc->phy_regs); | |
| 2395 | +err_iounmap_capreg: | |
| 2396 | + iounmap(udc->cap_regs); | |
| 2397 | +err_put_clk: | |
| 2398 | + for (clk_i--; clk_i >= 0; clk_i--) | |
| 2399 | + clk_put(udc->clk[clk_i]); | |
| 2400 | + the_controller = NULL; | |
| 2401 | + kfree(udc); | |
| 2087 | 2402 | return retval; |
| 2088 | 2403 | } |
| 2089 | 2404 | |
| @@ -2102,11 +2417,16 @@ static int mv_udc_resume(struct device *_dev) · 12 unmodified lines | ||
| 2102 | 2417 | struct mv_udc *udc = the_controller; |
| 2103 | 2418 | int retval; |
| 2104 | 2419 | |
| 2105 | − retval = mv_udc_phy_init(udc->phy_regs); | |
| 2106 | − if (retval) { | |
| 2107 | − dev_err(_dev, "phy initialization error %d\n", retval); | |
| 2108 | − return retval; | |
| 2420 | + if (udc->pdata->phy_init) { | |
| 2421 | + retval = udc->pdata->phy_init(udc->phy_regs); | |
| 2422 | + if (retval) { | |
| 2423 | + dev_err(&udc->dev->dev, | |
| 2424 | + "init phy error %d when resume back\n", | |
| 2425 | + retval); | |
| 2426 | + return retval; | |
| 2427 | + } | |
| 2109 | 2428 | } |
| 2429 | + | |
| 2110 | 2430 | udc_reset(udc); |
| 2111 | 2431 | ep0_reset(udc); |
| 2112 | 2432 | udc_start(udc); |
| @@ -2120,9 +2440,21 @@ static const struct dev_pm_ops mv_udc_pm_ops = { · 7 unmodified lines | ||
| 2120 | 2440 | }; |
| 2121 | 2441 | #endif |
| 2122 | 2442 | |
| 2443 | +static void mv_udc_shutdown(struct platform_device *dev) | |
| 2444 | +{ | |
| 2445 | + struct mv_udc *udc = the_controller; | |
| 2446 | + u32 mode; | |
| 2447 | + | |
| 2448 | + /* reset controller mode to IDLE */ | |
| 2449 | + mode = readl(&udc->op_regs->usbmode); | |
| 2450 | + mode &= ~3; | |
| 2451 | + writel(mode, &udc->op_regs->usbmode); | |
| 2452 | +} | |
| 2453 | + | |
| 2123 | 2454 | static struct platform_driver udc_driver = { |
| 2124 | 2455 | .probe = mv_udc_probe, |
| 2125 | 2456 | .remove = __exit_p(mv_udc_remove), |
| 2457 | + .shutdown = mv_udc_shutdown, | |
| 2126 | 2458 | .driver = { |
| 2127 | 2459 | .owner = THIS_MODULE, |
| 2128 | 2460 | .name = "pxa-u2o", |
| @@ -1,214 +0,0 @@ | ||
| 1 | −#include <linux/delay.h> | |
| 2 | −#include <linux/timer.h> | |
| 3 | −#include <linux/io.h> | |
| 4 | −#include <linux/errno.h> | |
| 5 | − | |
| 6 | −#include <mach/cputype.h> | |
| 7 | − | |
| 8 | −#ifdef CONFIG_ARCH_MMP | |
| 9 | − | |
| 10 | −#define UTMI_REVISION 0x0 | |
| 11 | −#define UTMI_CTRL 0x4 | |
| 12 | −#define UTMI_PLL 0x8 | |
| 13 | −#define UTMI_TX 0xc | |
| 14 | −#define UTMI_RX 0x10 | |
| 15 | −#define UTMI_IVREF 0x14 | |
| 16 | −#define UTMI_T0 0x18 | |
| 17 | −#define UTMI_T1 0x1c | |
| 18 | −#define UTMI_T2 0x20 | |
| 19 | −#define UTMI_T3 0x24 | |
| 20 | −#define UTMI_T4 0x28 | |
| 21 | −#define UTMI_T5 0x2c | |
| 22 | −#define UTMI_RESERVE 0x30 | |
| 23 | −#define UTMI_USB_INT 0x34 | |
| 24 | −#define UTMI_DBG_CTL 0x38 | |
| 25 | −#define UTMI_OTG_ADDON 0x3c | |
| 26 | − | |
| 27 | −/* For UTMICTRL Register */ | |
| 28 | −#define UTMI_CTRL_USB_CLK_EN (1 << 31) | |
| 29 | −/* pxa168 */ | |
| 30 | −#define UTMI_CTRL_SUSPEND_SET1 (1 << 30) | |
| 31 | −#define UTMI_CTRL_SUSPEND_SET2 (1 << 29) | |
| 32 | −#define UTMI_CTRL_RXBUF_PDWN (1 << 24) | |
| 33 | −#define UTMI_CTRL_TXBUF_PDWN (1 << 11) | |
| 34 | − | |
| 35 | −#define UTMI_CTRL_INPKT_DELAY_SHIFT 30 | |
| 36 | −#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT 28 | |
| 37 | −#define UTMI_CTRL_PU_REF_SHIFT 20 | |
| 38 | −#define UTMI_CTRL_ARC_PULLDN_SHIFT 12 | |
| 39 | −#define UTMI_CTRL_PLL_PWR_UP_SHIFT 1 | |
| 40 | −#define UTMI_CTRL_PWR_UP_SHIFT 0 | |
| 41 | −/* For UTMI_PLL Register */ | |
| 42 | −#define UTMI_PLL_CLK_BLK_EN_SHIFT 24 | |
| 43 | −#define UTMI_PLL_FBDIV_SHIFT 4 | |
| 44 | −#define UTMI_PLL_REFDIV_SHIFT 0 | |
| 45 | −#define UTMI_PLL_FBDIV_MASK 0x00000FF0 | |
| 46 | −#define UTMI_PLL_REFDIV_MASK 0x0000000F | |
| 47 | −#define UTMI_PLL_ICP_MASK 0x00007000 | |
| 48 | −#define UTMI_PLL_KVCO_MASK 0x00031000 | |
| 49 | −#define UTMI_PLL_PLLCALI12_SHIFT 29 | |
| 50 | −#define UTMI_PLL_PLLCALI12_MASK (0x3 << 29) | |
| 51 | −#define UTMI_PLL_PLLVDD18_SHIFT 27 | |
| 52 | −#define UTMI_PLL_PLLVDD18_MASK (0x3 << 27) | |
| 53 | −#define UTMI_PLL_PLLVDD12_SHIFT 25 | |
| 54 | −#define UTMI_PLL_PLLVDD12_MASK (0x3 << 25) | |
| 55 | −#define UTMI_PLL_KVCO_SHIFT 15 | |
| 56 | −#define UTMI_PLL_ICP_SHIFT 12 | |
| 57 | −/* For UTMI_TX Register */ | |
| 58 | −#define UTMI_TX_REG_EXT_FS_RCAL_SHIFT 27 | |
| 59 | −#define UTMI_TX_REG_EXT_FS_RCAL_MASK (0xf << 27) | |
| 60 | −#define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK 26 | |
| 61 | −#define UTMI_TX_REG_EXT_FS_RCAL_EN (0x1 << 26) | |
| 62 | −#define UTMI_TX_LOW_VDD_EN_SHIFT 11 | |
| 63 | −#define UTMI_TX_IMPCAL_VTH_SHIFT 14 | |
| 64 | −#define UTMI_TX_IMPCAL_VTH_MASK (0x7 << 14) | |
| 65 | −#define UTMI_TX_CK60_PHSEL_SHIFT 17 | |
| 66 | −#define UTMI_TX_CK60_PHSEL_MASK (0xf << 17) | |
| 67 | −#define UTMI_TX_TXVDD12_SHIFT 22 | |
| 68 | −#define UTMI_TX_TXVDD12_MASK (0x3 << 22) | |
| 69 | −#define UTMI_TX_AMP_SHIFT 0 | |
| 70 | −#define UTMI_TX_AMP_MASK (0x7 << 0) | |
| 71 | −/* For UTMI_RX Register */ | |
| 72 | −#define UTMI_RX_SQ_THRESH_SHIFT 4 | |
| 73 | −#define UTMI_RX_SQ_THRESH_MASK (0xf << 4) | |
| 74 | −#define UTMI_REG_SQ_LENGTH_SHIFT 15 | |
| 75 | −#define UTMI_REG_SQ_LENGTH_MASK (0x3 << 15) | |
| 76 | − | |
| 77 | −#define REG_RCAL_START 0x00001000 | |
| 78 | −#define VCOCAL_START 0x00200000 | |
| 79 | −#define KVCO_EXT 0x00400000 | |
| 80 | −#define PLL_READY 0x00800000 | |
| 81 | −#define CLK_BLK_EN 0x01000000 | |
| 82 | −#endif | |
| 83 | − | |
| 84 | −static unsigned int u2o_read(unsigned int base, unsigned int offset) | |
| 85 | −{ | |
| 86 | − return readl(base + offset); | |
| 87 | −} | |
| 88 | − | |
| 89 | −static void u2o_set(unsigned int base, unsigned int offset, unsigned int value) | |
| 90 | −{ | |
| 91 | − unsigned int reg; | |
| 92 | − | |
| 93 | − reg = readl(base + offset); | |
| 94 | − reg |= value; | |
| 95 | − writel(reg, base + offset); | |
| 96 | − readl(base + offset); | |
| 97 | −} | |
| 98 | − | |
| 99 | −static void u2o_clear(unsigned int base, unsigned int offset, | |
| 100 | − unsigned int value) | |
| 101 | −{ | |
| 102 | − unsigned int reg; | |
| 103 | − | |
| 104 | − reg = readl(base + offset); | |
| 105 | − reg &= ~value; | |
| 106 | − writel(reg, base + offset); | |
| 107 | − readl(base + offset); | |
| 108 | −} | |
| 109 | − | |
| 110 | −static void u2o_write(unsigned int base, unsigned int offset, | |
| 111 | − unsigned int value) | |
| 112 | −{ | |
| 113 | − writel(value, base + offset); | |
| 114 | − readl(base + offset); | |
| 115 | −} | |
| 116 | − | |
| 117 | −#ifdef CONFIG_ARCH_MMP | |
| 118 | −int mv_udc_phy_init(unsigned int base) | |
| 119 | −{ | |
| 120 | − unsigned long timeout; | |
| 121 | − | |
| 122 | − /* Initialize the USB PHY power */ | |
| 123 | − if (cpu_is_pxa910()) { | |
| 124 | − u2o_set(base, UTMI_CTRL, (1 << UTMI_CTRL_INPKT_DELAY_SOF_SHIFT) | |
| 125 | − | (1 << UTMI_CTRL_PU_REF_SHIFT)); | |
| 126 | − } | |
| 127 | − | |
| 128 | − u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PLL_PWR_UP_SHIFT); | |
| 129 | − u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PWR_UP_SHIFT); | |
| 130 | − | |
| 131 | − /* UTMI_PLL settings */ | |
| 132 | − u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK | |
| 133 | − | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK | |
| 134 | − | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK | |
| 135 | − | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK); | |
| 136 | − | |
| 137 | − u2o_set(base, UTMI_PLL, (0xee << UTMI_PLL_FBDIV_SHIFT) | |
| 138 | − | (0xb << UTMI_PLL_REFDIV_SHIFT) | |
| 139 | − | (3 << UTMI_PLL_PLLVDD18_SHIFT) | |
| 140 | − | (3 << UTMI_PLL_PLLVDD12_SHIFT) | |
| 141 | − | (3 << UTMI_PLL_PLLCALI12_SHIFT) | |
| 142 | − | (1 << UTMI_PLL_ICP_SHIFT) | (3 << UTMI_PLL_KVCO_SHIFT)); | |
| 143 | − | |
| 144 | − /* UTMI_TX */ | |
| 145 | − u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK | |
| 146 | − | UTMI_TX_TXVDD12_MASK | |
| 147 | − | UTMI_TX_CK60_PHSEL_MASK | UTMI_TX_IMPCAL_VTH_MASK | |
| 148 | − | UTMI_TX_REG_EXT_FS_RCAL_MASK | UTMI_TX_AMP_MASK); | |
| 149 | − u2o_set(base, UTMI_TX, (3 << UTMI_TX_TXVDD12_SHIFT) | |
| 150 | − | (4 << UTMI_TX_CK60_PHSEL_SHIFT) | |
| 151 | − | (4 << UTMI_TX_IMPCAL_VTH_SHIFT) | |
| 152 | − | (8 << UTMI_TX_REG_EXT_FS_RCAL_SHIFT) | |
| 153 | − | (3 << UTMI_TX_AMP_SHIFT)); | |
| 154 | − | |
| 155 | − /* UTMI_RX */ | |
| 156 | − u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK | |
| 157 | − | UTMI_REG_SQ_LENGTH_MASK); | |
| 158 | − if (cpu_is_pxa168()) | |
| 159 | − u2o_set(base, UTMI_RX, (7 << UTMI_RX_SQ_THRESH_SHIFT) | |
| 160 | − | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); | |
| 161 | − else | |
| 162 | − u2o_set(base, UTMI_RX, (0x7 << UTMI_RX_SQ_THRESH_SHIFT) | |
| 163 | − | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); | |
| 164 | − | |
| 165 | − /* UTMI_IVREF */ | |
| 166 | − if (cpu_is_pxa168()) | |
| 167 | − /* | |
| 168 | − * fixing Microsoft Altair board interface with NEC hub issue - | |
| 169 | − * Set UTMI_IVREF from 0x4a3 to 0x4bf | |
| 170 | − */ | |
| 171 | − u2o_write(base, UTMI_IVREF, 0x4bf); | |
| 172 | − | |
| 173 | − /* calibrate */ | |
| 174 | − timeout = jiffies + 100; | |
| 175 | − while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { | |
| 176 | − if (time_after(jiffies, timeout)) | |
| 177 | − return -ETIME; | |
| 178 | − cpu_relax(); | |
| 179 | − } | |
| 180 | − | |
| 181 | − /* toggle VCOCAL_START bit of UTMI_PLL */ | |
| 182 | − udelay(200); | |
| 183 | − u2o_set(base, UTMI_PLL, VCOCAL_START); | |
| 184 | − udelay(40); | |
| 185 | − u2o_clear(base, UTMI_PLL, VCOCAL_START); | |
| 186 | − | |
| 187 | − /* toggle REG_RCAL_START bit of UTMI_TX */ | |
| 188 | − udelay(200); | |
| 189 | − u2o_set(base, UTMI_TX, REG_RCAL_START); | |
| 190 | − udelay(40); | |
| 191 | − u2o_clear(base, UTMI_TX, REG_RCAL_START); | |
| 192 | − udelay(200); | |
| 193 | − | |
| 194 | − /* make sure phy is ready */ | |
| 195 | − timeout = jiffies + 100; | |
| 196 | − while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { | |
| 197 | − if (time_after(jiffies, timeout)) | |
| 198 | − return -ETIME; | |
| 199 | − cpu_relax(); | |
| 200 | − } | |
| 201 | − | |
| 202 | − if (cpu_is_pxa168()) { | |
| 203 | − u2o_set(base, UTMI_RESERVE, 1 << 5); | |
| 204 | − /* Turn on UTMI PHY OTG extension */ | |
| 205 | − u2o_write(base, UTMI_OTG_ADDON, 1); | |
| 206 | − } | |
| 207 | − return 0; | |
| 208 | −} | |
| 209 | −#else | |
| 210 | −int mv_udc_phy_init(unsigned int base) | |
| 211 | −{ | |
| 212 | − return 0; | |
| 213 | −} | |
| 214 | −#endif | |
| @@ -14,15 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | * it under the terms of the GNU General Public License as published by |
| 15 | 15 | * the Free Software Foundation; either version 2 of the License, or |
| 16 | 16 | * (at your option) any later version. |
| 17 | − * | |
| 18 | − * This program is distributed in the hope that it will be useful, | |
| 19 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 20 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 21 | − * GNU General Public License for more details. | |
| 22 | − * | |
| 23 | − * You should have received a copy of the GNU General Public License | |
| 24 | − * along with this program; if not, write to the Free Software | |
| 25 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 26 | 17 | */ |
| 27 | 18 | |
| 28 | 19 | /* #define DEBUG */ |
| @@ -10,12 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * |
| 11 | 11 | * This source code is offered for use in the public domain. You may |
| 12 | 12 | * use, modify or distribute it freely. |
| 13 | − * | |
| 14 | − * This code is distributed in the hope that it will be useful but | |
| 15 | − * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY | |
| 16 | − * DISCLAIMED. This includes but is not limited to warranties of | |
| 17 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| 18 | − * | |
| 19 | 13 | */ |
| 20 | 14 | |
| 21 | 15 | #ifndef _LINUX_NDIS_H |
| @@ -204,7 +204,7 @@ net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) · 203 unmodified lines | ||
| 204 | 204 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) |
| 205 | 205 | return -ESHUTDOWN; |
| 206 | 206 | |
| 207 | − max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; | |
| 207 | + max = usb_endpoint_maxp(desc) & 0x1fff; | |
| 208 | 208 | |
| 209 | 209 | spin_lock_irqsave(&dev->lock, flags); |
| 210 | 210 | _ep->maxpacket = max & 0x7fff; |
| @@ -1172,17 +1172,18 @@ net2272_pullup(struct usb_gadget *_gadget, int is_on) · 961 unmodified lines | ||
| 1172 | 1172 | return 0; |
| 1173 | 1173 | } |
| 1174 | 1174 | |
| 1175 | −static int net2272_start(struct usb_gadget_driver *driver, | |
| 1176 | − int (*bind)(struct usb_gadget *)); | |
| 1177 | −static int net2272_stop(struct usb_gadget_driver *driver); | |
| 1175 | +static int net2272_start(struct usb_gadget *_gadget, | |
| 1176 | + struct usb_gadget_driver *driver); | |
| 1177 | +static int net2272_stop(struct usb_gadget *_gadget, | |
| 1178 | + struct usb_gadget_driver *driver); | |
| 1178 | 1179 | |
| 1179 | 1180 | static const struct usb_gadget_ops net2272_ops = { |
| 1180 | − .get_frame = net2272_get_frame, | |
| 1181 | − .wakeup = net2272_wakeup, | |
| 1181 | + .get_frame = net2272_get_frame, | |
| 1182 | + .wakeup = net2272_wakeup, | |
| 1182 | 1183 | .set_selfpowered = net2272_set_selfpowered, |
| 1183 | − .pullup = net2272_pullup, | |
| 1184 | − .start = net2272_start, | |
| 1185 | − .stop = net2272_stop, | |
| 1184 | + .pullup = net2272_pullup, | |
| 1185 | + .udc_start = net2272_start, | |
| 1186 | + .udc_stop = net2272_stop, | |
| 1186 | 1187 | }; |
| 1187 | 1188 | |
| 1188 | 1189 | /*---------------------------------------------------------------------------*/ |
| @@ -1356,8 +1357,6 @@ net2272_set_fifo_mode(struct net2272 *dev, int mode) · 167 unmodified lines | ||
| 1356 | 1357 | |
| 1357 | 1358 | /*---------------------------------------------------------------------------*/ |
| 1358 | 1359 | |
| 1359 | −static struct net2272 *the_controller; | |
| 1360 | − | |
| 1361 | 1360 | static void |
| 1362 | 1361 | net2272_usb_reset(struct net2272 *dev) |
| 1363 | 1362 | { |
| @@ -1453,20 +1452,17 @@ net2272_ep0_start(struct net2272 *dev) · 89 unmodified lines | ||
| 1453 | 1452 | * disconnect is reported. then a host may connect again, or |
| 1454 | 1453 | * the driver might get unbound. |
| 1455 | 1454 | */ |
| 1456 | −static int net2272_start(struct usb_gadget_driver *driver, | |
| 1457 | − int (*bind)(struct usb_gadget *)) | |
| 1455 | +static int net2272_start(struct usb_gadget *_gadget, | |
| 1456 | + struct usb_gadget_driver *driver) | |
| 1458 | 1457 | { |
| 1459 | − struct net2272 *dev = the_controller; | |
| 1460 | − int ret; | |
| 1458 | + struct net2272 *dev; | |
| 1461 | 1459 | unsigned i; |
| 1462 | 1460 | |
| 1463 | − if (!driver || !bind || !driver->unbind || !driver->setup || | |
| 1461 | + if (!driver || !driver->unbind || !driver->setup || | |
| 1464 | 1462 | driver->speed != USB_SPEED_HIGH) |
| 1465 | 1463 | return -EINVAL; |
| 1466 | − if (!dev) | |
| 1467 | − return -ENODEV; | |
| 1468 | − if (dev->driver) | |
| 1469 | − return -EBUSY; | |
| 1464 | + | |
| 1465 | + dev = container_of(_gadget, struct net2272, gadget); | |
| 1470 | 1466 | |
| 1471 | 1467 | for (i = 0; i < 4; ++i) |
| 1472 | 1468 | dev->ep[i].irqs = 0; |
| @@ -1475,14 +1471,6 @@ static int net2272_start(struct usb_gadget_driver *driver, · 2 unmodified lines | ||
| 1475 | 1471 | driver->driver.bus = NULL; |
| 1476 | 1472 | dev->driver = driver; |
| 1477 | 1473 | dev->gadget.dev.driver = &driver->driver; |
| 1478 | − ret = bind(&dev->gadget); | |
| 1479 | − if (ret) { | |
| 1480 | − dev_dbg(dev->dev, "bind to driver %s --> %d\n", | |
| 1481 | − driver->driver.name, ret); | |
| 1482 | − dev->driver = NULL; | |
| 1483 | − dev->gadget.dev.driver = NULL; | |
| 1484 | − return ret; | |
| 1485 | − } | |
| 1486 | 1474 | |
| 1487 | 1475 | /* ... then enable host detection and ep0; and we're ready |
| 1488 | 1476 | * for set_configuration as well as eventual disconnect. |
| @@ -1510,33 +1498,21 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver) · 21 unmodified lines | ||
| 1510 | 1498 | for (i = 0; i < 4; ++i) |
| 1511 | 1499 | net2272_dequeue_all(&dev->ep[i]); |
| 1512 | 1500 | |
| 1513 | − /* report disconnect; the driver is already quiesced */ | |
| 1514 | − if (driver) { | |
| 1515 | − spin_unlock(&dev->lock); | |
| 1516 | − driver->disconnect(&dev->gadget); | |
| 1517 | − spin_lock(&dev->lock); | |
| 1518 | − | |
| 1519 | − } | |
| 1520 | 1501 | net2272_usb_reinit(dev); |
| 1521 | 1502 | } |
| 1522 | 1503 | |
| 1523 | −static int net2272_stop(struct usb_gadget_driver *driver) | |
| 1504 | +static int net2272_stop(struct usb_gadget *_gadget, | |
| 1505 | + struct usb_gadget_driver *driver) | |
| 1524 | 1506 | { |
| 1525 | − struct net2272 *dev = the_controller; | |
| 1507 | + struct net2272 *dev; | |
| 1526 | 1508 | unsigned long flags; |
| 1527 | 1509 | |
| 1528 | − if (!dev) | |
| 1529 | − return -ENODEV; | |
| 1530 | − if (!driver || driver != dev->driver) | |
| 1531 | − return -EINVAL; | |
| 1510 | + dev = container_of(_gadget, struct net2272, gadget); | |
| 1532 | 1511 | |
| 1533 | 1512 | spin_lock_irqsave(&dev->lock, flags); |
| 1534 | 1513 | stop_activity(dev, driver); |
| 1535 | 1514 | spin_unlock_irqrestore(&dev->lock, flags); |
| 1536 | 1515 | |
| 1537 | − net2272_pullup(&dev->gadget, 0); | |
| 1538 | − | |
| 1539 | − driver->unbind(&dev->gadget); | |
| 1540 | 1516 | dev->gadget.dev.driver = NULL; |
| 1541 | 1517 | dev->driver = NULL; |
| 1542 | 1518 | |
| @@ -1764,8 +1740,8 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) · 221 unmodified lines | ||
| 1764 | 1740 | dev->gadget.speed = USB_SPEED_HIGH; |
| 1765 | 1741 | else |
| 1766 | 1742 | dev->gadget.speed = USB_SPEED_FULL; |
| 1767 | − dev_dbg(dev->dev, "%s speed\n", | |
| 1768 | − (dev->gadget.speed == USB_SPEED_HIGH) ? "high" : "full"); | |
| 1743 | + dev_dbg(dev->dev, "%s\n", | |
| 1744 | + usb_speed_string(dev->gadget.speed)); | |
| 1769 | 1745 | } |
| 1770 | 1746 | |
| 1771 | 1747 | ep = &dev->ep[0]; |
| @@ -2238,7 +2214,6 @@ net2272_remove(struct net2272 *dev) · 466 unmodified lines | ||
| 2238 | 2214 | device_remove_file(dev->dev, &dev_attr_registers); |
| 2239 | 2215 | |
| 2240 | 2216 | dev_info(dev->dev, "unbind\n"); |
| 2241 | − the_controller = NULL; | |
| 2242 | 2217 | } |
| 2243 | 2218 | |
| 2244 | 2219 | static struct net2272 * __devinit |
| @@ -2246,11 +2221,6 @@ net2272_probe_init(struct device *dev, unsigned int irq) · 1 unmodified line | ||
| 2246 | 2221 | { |
| 2247 | 2222 | struct net2272 *ret; |
| 2248 | 2223 | |
| 2249 | − if (the_controller) { | |
| 2250 | − dev_warn(dev, "ignoring\n"); | |
| 2251 | − return ERR_PTR(-EBUSY); | |
| 2252 | − } | |
| 2253 | − | |
| 2254 | 2224 | if (!irq) { |
| 2255 | 2225 | dev_dbg(dev, "No IRQ!\n"); |
| 2256 | 2226 | return ERR_PTR(-ENODEV); |
| @@ -2307,8 +2277,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags) · 50 unmodified lines | ||
| 2307 | 2277 | dma_mode_string()); |
| 2308 | 2278 | dev_info(dev->dev, "version: %s\n", driver_vers); |
| 2309 | 2279 | |
| 2310 | − the_controller = dev; | |
| 2311 | − | |
| 2312 | 2280 | ret = device_register(&dev->gadget.dev); |
| 2313 | 2281 | if (ret) |
| 2314 | 2282 | goto err_irq; |
| @@ -2684,8 +2652,6 @@ net2272_plat_probe(struct platform_device *pdev) · 369 unmodified lines | ||
| 2684 | 2652 | dev_info(&pdev->dev, "running in 16-bit, %sbyte swap local bus mode\n", |
| 2685 | 2653 | (net2272_read(dev, LOCCTL) & (1 << BYTE_SWAP)) ? "" : "no "); |
| 2686 | 2654 | |
| 2687 | − the_controller = dev; | |
| 2688 | − | |
| 2689 | 2655 | return 0; |
| 2690 | 2656 | |
| 2691 | 2657 | err_io: |
| @@ -33,15 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | * it under the terms of the GNU General Public License as published by |
| 34 | 34 | * the Free Software Foundation; either version 2 of the License, or |
| 35 | 35 | * (at your option) any later version. |
| 36 | − * | |
| 37 | − * This program is distributed in the hope that it will be useful, | |
| 38 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 39 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 40 | − * GNU General Public License for more details. | |
| 41 | − * | |
| 42 | − * You should have received a copy of the GNU General Public License | |
| 43 | − * along with this program; if not, write to the Free Software | |
| 44 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 45 | 36 | */ |
| 46 | 37 | |
| 47 | 38 | #undef DEBUG /* messages on error and most fault paths */ |
| @@ -169,7 +160,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) · 121 unmodified lines | ||
| 169 | 160 | return -EDOM; |
| 170 | 161 | |
| 171 | 162 | /* sanity check ep-e/ep-f since their fifos are small */ |
| 172 | − max = le16_to_cpu (desc->wMaxPacketSize) & 0x1fff; | |
| 163 | + max = usb_endpoint_maxp (desc) & 0x1fff; | |
| 173 | 164 | if (ep->num > 4 && max > 64) |
| 174 | 165 | return -ERANGE; |
| 175 | 166 | |
| @@ -1410,17 +1401,18 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on) · 1234 unmodified lines | ||
| 1410 | 1401 | return 0; |
| 1411 | 1402 | } |
| 1412 | 1403 | |
| 1413 | −static int net2280_start(struct usb_gadget_driver *driver, | |
| 1414 | − int (*bind)(struct usb_gadget *)); | |
| 1415 | −static int net2280_stop(struct usb_gadget_driver *driver); | |
| 1404 | +static int net2280_start(struct usb_gadget *_gadget, | |
| 1405 | + struct usb_gadget_driver *driver); | |
| 1406 | +static int net2280_stop(struct usb_gadget *_gadget, | |
| 1407 | + struct usb_gadget_driver *driver); | |
| 1416 | 1408 | |
| 1417 | 1409 | static const struct usb_gadget_ops net2280_ops = { |
| 1418 | 1410 | .get_frame = net2280_get_frame, |
| 1419 | 1411 | .wakeup = net2280_wakeup, |
| 1420 | 1412 | .set_selfpowered = net2280_set_selfpowered, |
| 1421 | 1413 | .pullup = net2280_pullup, |
| 1422 | − .start = net2280_start, | |
| 1423 | − .stop = net2280_stop, | |
| 1414 | + .udc_start = net2280_start, | |
| 1415 | + .udc_stop = net2280_stop, | |
| 1424 | 1416 | }; |
| 1425 | 1417 | |
| 1426 | 1418 | /*-------------------------------------------------------------------------*/ |
| @@ -1640,7 +1632,7 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf) · 213 unmodified lines | ||
| 1640 | 1632 | default: |
| 1641 | 1633 | val = "iso"; break; |
| 1642 | 1634 | }; val; }), |
| 1643 | − le16_to_cpu (d->wMaxPacketSize) & 0x1fff, | |
| 1635 | + usb_endpoint_maxp (d) & 0x1fff, | |
| 1644 | 1636 | ep->dma ? "dma" : "pio", ep->fifo_size |
| 1645 | 1637 | ); |
| 1646 | 1638 | } else /* ep0 should only have one transfer queued */ |
| @@ -1753,8 +1745,6 @@ static void set_fifo_mode (struct net2280 *dev, int mode) · 106 unmodified lines | ||
| 1753 | 1745 | * perhaps to bind specific drivers to specific devices. |
| 1754 | 1746 | */ |
| 1755 | 1747 | |
| 1756 | −static struct net2280 *the_controller; | |
| 1757 | − | |
| 1758 | 1748 | static void usb_reset (struct net2280 *dev) |
| 1759 | 1749 | { |
| 1760 | 1750 | u32 tmp; |
| @@ -1880,10 +1870,10 @@ static void ep0_start (struct net2280 *dev) · 119 unmodified lines | ||
| 1880 | 1870 | * disconnect is reported. then a host may connect again, or |
| 1881 | 1871 | * the driver might get unbound. |
| 1882 | 1872 | */ |
| 1883 | −static int net2280_start(struct usb_gadget_driver *driver, | |
| 1884 | − int (*bind)(struct usb_gadget *)) | |
| 1873 | +static int net2280_start(struct usb_gadget *_gadget, | |
| 1874 | + struct usb_gadget_driver *driver) | |
| 1885 | 1875 | { |
| 1886 | − struct net2280 *dev = the_controller; | |
| 1876 | + struct net2280 *dev; | |
| 1887 | 1877 | int retval; |
| 1888 | 1878 | unsigned i; |
| 1889 | 1879 | |
| @@ -1891,14 +1881,11 @@ static int net2280_start(struct usb_gadget_driver *driver, · 1 unmodified line | ||
| 1891 | 1881 | * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE) |
| 1892 | 1882 | * "must not be used in normal operation" |
| 1893 | 1883 | */ |
| 1894 | − if (!driver | |
| 1895 | − || driver->speed != USB_SPEED_HIGH | |
| 1896 | − || !bind || !driver->setup) | |
| 1884 | + if (!driver || driver->speed != USB_SPEED_HIGH | |
| 1885 | + || !driver->setup) | |
| 1897 | 1886 | return -EINVAL; |
| 1898 | − if (!dev) | |
| 1899 | − return -ENODEV; | |
| 1900 | − if (dev->driver) | |
| 1901 | − return -EBUSY; | |
| 1887 | + | |
| 1888 | + dev = container_of (_gadget, struct net2280, gadget); | |
| 1902 | 1889 | |
| 1903 | 1890 | for (i = 0; i < 7; i++) |
| 1904 | 1891 | dev->ep [i].irqs = 0; |
| @@ -1908,14 +1895,6 @@ static int net2280_start(struct usb_gadget_driver *driver, · 3 unmodified lines | ||
| 1908 | 1895 | driver->driver.bus = NULL; |
| 1909 | 1896 | dev->driver = driver; |
| 1910 | 1897 | dev->gadget.dev.driver = &driver->driver; |
| 1911 | − retval = bind(&dev->gadget); | |
| 1912 | − if (retval) { | |
| 1913 | − DEBUG (dev, "bind to driver %s --> %d\n", | |
| 1914 | − driver->driver.name, retval); | |
| 1915 | − dev->driver = NULL; | |
| 1916 | − dev->gadget.dev.driver = NULL; | |
| 1917 | − return retval; | |
| 1918 | − } | |
| 1919 | 1898 | |
| 1920 | 1899 | retval = device_create_file (&dev->pdev->dev, &dev_attr_function); |
| 1921 | 1900 | if (retval) goto err_unbind; |
| @@ -1961,33 +1940,21 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver) · 39 unmodified lines | ||
| 1961 | 1940 | for (i = 0; i < 7; i++) |
| 1962 | 1941 | nuke (&dev->ep [i]); |
| 1963 | 1942 | |
| 1964 | − /* report disconnect; the driver is already quiesced */ | |
| 1965 | − if (driver) { | |
| 1966 | − spin_unlock (&dev->lock); | |
| 1967 | − driver->disconnect (&dev->gadget); | |
| 1968 | − spin_lock (&dev->lock); | |
| 1969 | − } | |
| 1970 | − | |
| 1971 | 1943 | usb_reinit (dev); |
| 1972 | 1944 | } |
| 1973 | 1945 | |
| 1974 | −static int net2280_stop(struct usb_gadget_driver *driver) | |
| 1946 | +static int net2280_stop(struct usb_gadget *_gadget, | |
| 1947 | + struct usb_gadget_driver *driver) | |
| 1975 | 1948 | { |
| 1976 | − struct net2280 *dev = the_controller; | |
| 1949 | + struct net2280 *dev; | |
| 1977 | 1950 | unsigned long flags; |
| 1978 | 1951 | |
| 1979 | − if (!dev) | |
| 1980 | − return -ENODEV; | |
| 1981 | − if (!driver || driver != dev->driver || !driver->unbind) | |
| 1982 | − return -EINVAL; | |
| 1952 | + dev = container_of (_gadget, struct net2280, gadget); | |
| 1983 | 1953 | |
| 1984 | 1954 | spin_lock_irqsave (&dev->lock, flags); |
| 1985 | 1955 | stop_activity (dev, driver); |
| 1986 | 1956 | spin_unlock_irqrestore (&dev->lock, flags); |
| 1987 | 1957 | |
| 1988 | − net2280_pullup (&dev->gadget, 0); | |
| 1989 | − | |
| 1990 | − driver->unbind (&dev->gadget); | |
| 1991 | 1958 | dev->gadget.dev.driver = NULL; |
| 1992 | 1959 | dev->driver = NULL; |
| 1993 | 1960 | |
| @@ -2266,9 +2233,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) · 272 unmodified lines | ||
| 2266 | 2233 | else |
| 2267 | 2234 | dev->gadget.speed = USB_SPEED_FULL; |
| 2268 | 2235 | net2280_led_speed (dev, dev->gadget.speed); |
| 2269 | − DEBUG (dev, "%s speed\n", | |
| 2270 | − (dev->gadget.speed == USB_SPEED_HIGH) | |
| 2271 | − ? "high" : "full"); | |
| 2236 | + DEBUG(dev, "%s\n", usb_speed_string(dev->gadget.speed)); | |
| 2272 | 2237 | } |
| 2273 | 2238 | |
| 2274 | 2239 | ep = &dev->ep [0]; |
| @@ -2709,8 +2674,6 @@ static void net2280_remove (struct pci_dev *pdev) · 434 unmodified lines | ||
| 2709 | 2674 | pci_set_drvdata (pdev, NULL); |
| 2710 | 2675 | |
| 2711 | 2676 | INFO (dev, "unbind\n"); |
| 2712 | − | |
| 2713 | − the_controller = NULL; | |
| 2714 | 2677 | } |
| 2715 | 2678 | |
| 2716 | 2679 | /* wrap this driver around the specified device, but |
| @@ -2724,14 +2687,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) · 7 unmodified lines | ||
| 2724 | 2687 | void __iomem *base = NULL; |
| 2725 | 2688 | int retval, i; |
| 2726 | 2689 | |
| 2727 | − /* if you want to support more than one controller in a system, | |
| 2728 | − * usb_gadget_driver_{register,unregister}() must change. | |
| 2729 | − */ | |
| 2730 | − if (the_controller) { | |
| 2731 | − dev_warn (&pdev->dev, "ignoring\n"); | |
| 2732 | − return -EBUSY; | |
| 2733 | − } | |
| 2734 | − | |
| 2735 | 2690 | /* alloc, and start init */ |
| 2736 | 2691 | dev = kzalloc (sizeof *dev, GFP_KERNEL); |
| 2737 | 2692 | if (dev == NULL){ |
| @@ -2858,8 +2813,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) · 120 unmodified lines | ||
| 2858 | 2813 | use_dma |
| 2859 | 2814 | ? (use_dma_chaining ? "chaining" : "enabled") |
| 2860 | 2815 | : "disabled"); |
| 2861 | − the_controller = dev; | |
| 2862 | − | |
| 2863 | 2816 | retval = device_register (&dev->gadget.dev); |
| 2864 | 2817 | if (retval) goto done; |
| 2865 | 2818 | retval = device_create_file (&pdev->dev, &dev_attr_registers); |
| @@ -11,15 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | * it under the terms of the GNU General Public License as published by |
| 12 | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | 13 | * (at your option) any later version. |
| 14 | − * | |
| 15 | − * This program is distributed in the hope that it will be useful, | |
| 16 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − * GNU General Public License for more details. | |
| 19 | − * | |
| 20 | − * You should have received a copy of the GNU General Public License | |
| 21 | − * along with this program; if not, write to the Free Software | |
| 22 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 23 | 14 | */ |
| 24 | 15 | |
| 25 | 16 | #include <linux/usb/net2280.h> |
| @@ -10,15 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | 13 | */ |
| 23 | 14 | |
| 24 | 15 | #undef DEBUG |
| @@ -166,15 +157,14 @@ static int omap_ep_enable(struct usb_ep *_ep, · 141 unmodified lines | ||
| 166 | 157 | if (!_ep || !desc || ep->desc |
| 167 | 158 | || desc->bDescriptorType != USB_DT_ENDPOINT |
| 168 | 159 | || ep->bEndpointAddress != desc->bEndpointAddress |
| 169 | − || ep->maxpacket < le16_to_cpu | |
| 170 | − (desc->wMaxPacketSize)) { | |
| 160 | + || ep->maxpacket < usb_endpoint_maxp(desc)) { | |
| 171 | 161 | DBG("%s, bad ep or descriptor\n", __func__); |
| 172 | 162 | return -EINVAL; |
| 173 | 163 | } |
| 174 | − maxp = le16_to_cpu (desc->wMaxPacketSize); | |
| 164 | + maxp = usb_endpoint_maxp(desc); | |
| 175 | 165 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK |
| 176 | 166 | && maxp != ep->maxpacket) |
| 177 | − || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket | |
| 167 | + || usb_endpoint_maxp(desc) > ep->maxpacket | |
| 178 | 168 | || !desc->wMaxPacketSize) { |
| 179 | 169 | DBG("%s, bad %s maxpacket\n", __func__, _ep->name); |
| 180 | 170 | return -ERANGE; |
| @@ -2968,7 +2958,7 @@ known: · 2787 unmodified lines | ||
| 2968 | 2958 | } |
| 2969 | 2959 | #ifdef USE_ISO |
| 2970 | 2960 | status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, |
| 2971 | − IRQF_DISABLED, "omap_udc iso", udc); | |
| 2961 | + 0, "omap_udc iso", udc); | |
| 2972 | 2962 | if (status != 0) { |
| 2973 | 2963 | ERR("can't get irq %d, err %d\n", |
| 2974 | 2964 | (int) pdev->resource[3].start, status); |
| @@ -4,15 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | 5 | * it under the terms of the GNU General Public License as published by |
| 6 | 6 | * the Free Software Foundation; version 2 of the License. |
| 7 | − * | |
| 8 | − * This program is distributed in the hope that it will be useful, | |
| 9 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11 | − * GNU General Public License for more details. | |
| 12 | − * | |
| 13 | − * You should have received a copy of the GNU General Public License | |
| 14 | − * along with this program; if not, write to the Free Software | |
| 15 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | |
| 16 | 7 | */ |
| 17 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 18 | 9 | #include <linux/kernel.h> |
| @@ -947,7 +938,7 @@ static void pch_udc_ep_enable(struct pch_udc_ep *ep, · 928 unmodified lines | ||
| 947 | 938 | else |
| 948 | 939 | buff_size = UDC_EPOUT_BUFF_SIZE; |
| 949 | 940 | pch_udc_ep_set_bufsz(ep, buff_size, ep->in); |
| 950 | − pch_udc_ep_set_maxpkt(ep, le16_to_cpu(desc->wMaxPacketSize)); | |
| 941 | + pch_udc_ep_set_maxpkt(ep, usb_endpoint_maxp(desc)); | |
| 951 | 942 | pch_udc_ep_set_nak(ep); |
| 952 | 943 | pch_udc_ep_fifo_flush(ep, ep->in); |
| 953 | 944 | /* Configure the endpoint */ |
| @@ -957,7 +948,7 @@ static void pch_udc_ep_enable(struct pch_udc_ep *ep, · 3 unmodified lines | ||
| 957 | 948 | (cfg->cur_cfg << UDC_CSR_NE_CFG_SHIFT) | |
| 958 | 949 | (cfg->cur_intf << UDC_CSR_NE_INTF_SHIFT) | |
| 959 | 950 | (cfg->cur_alt << UDC_CSR_NE_ALT_SHIFT) | |
| 960 | − le16_to_cpu(desc->wMaxPacketSize) << UDC_CSR_NE_MAX_PKT_SHIFT; | |
| 951 | + usb_endpoint_maxp(desc) << UDC_CSR_NE_MAX_PKT_SHIFT; | |
| 961 | 952 | |
| 962 | 953 | if (ep->in) |
| 963 | 954 | pch_udc_write_csr(ep->dev, val, UDC_EPIN_IDX(ep->num)); |
| @@ -1466,7 +1457,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep, · 502 unmodified lines | ||
| 1466 | 1457 | ep->desc = desc; |
| 1467 | 1458 | ep->halted = 0; |
| 1468 | 1459 | pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc); |
| 1469 | − ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 1460 | + ep->ep.maxpacket = usb_endpoint_maxp(desc); | |
| 1470 | 1461 | pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); |
| 1471 | 1462 | spin_unlock_irqrestore(&dev->lock, iflags); |
| 1472 | 1463 | return 0; |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | #include <linux/module.h> |
| @@ -971,23 +962,15 @@ printer_set_config(struct printer_dev *dev, unsigned number) · 948 unmodified lines | ||
| 971 | 962 | usb_gadget_vbus_draw(dev->gadget, |
| 972 | 963 | dev->gadget->is_otg ? 8 : 100); |
| 973 | 964 | } else { |
| 974 | − char *speed; | |
| 975 | 965 | unsigned power; |
| 976 | 966 | |
| 977 | 967 | power = 2 * config_desc.bMaxPower; |
| 978 | 968 | usb_gadget_vbus_draw(dev->gadget, power); |
| 979 | 969 | |
| 980 | − switch (gadget->speed) { | |
| 981 | − case USB_SPEED_FULL: speed = "full"; break; | |
| 982 | −#ifdef CONFIG_USB_GADGET_DUALSPEED | |
| 983 | − case USB_SPEED_HIGH: speed = "high"; break; | |
| 984 | −#endif | |
| 985 | − default: speed = "?"; break; | |
| 986 | − } | |
| 987 | − | |
| 988 | 970 | dev->config = number; |
| 989 | − INFO(dev, "%s speed config #%d: %d mA, %s\n", | |
| 990 | − speed, number, power, driver_desc); | |
| 971 | + INFO(dev, "%s config #%d: %d mA, %s\n", | |
| 972 | + usb_speed_string(gadget->speed), | |
| 973 | + number, power, driver_desc); | |
| 991 | 974 | } |
| 992 | 975 | return result; |
| 993 | 976 | } |
| @@ -1611,7 +1594,7 @@ cleanup(void) · 617 unmodified lines | ||
| 1611 | 1594 | if (status) |
| 1612 | 1595 | ERROR(dev, "usb_gadget_unregister_driver %x\n", status); |
| 1613 | 1596 | |
| 1614 | − unregister_chrdev_region(g_printer_devno, 2); | |
| 1597 | + unregister_chrdev_region(g_printer_devno, 1); | |
| 1615 | 1598 | class_destroy(usb_gadget_class); |
| 1616 | 1599 | mutex_unlock(&usb_printer_gadget.lock_printer_io); |
| 1617 | 1600 | } |
| @@ -11,16 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | * it under the terms of the GNU General Public License as published by |
| 12 | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | 13 | * (at your option) any later version. |
| 14 | − * | |
| 15 | − * This program is distributed in the hope that it will be useful, | |
| 16 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − * GNU General Public License for more details. | |
| 19 | − * | |
| 20 | − * You should have received a copy of the GNU General Public License | |
| 21 | − * along with this program; if not, write to the Free Software | |
| 22 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 23 | − * | |
| 24 | 14 | */ |
| 25 | 15 | |
| 26 | 16 | /* #define VERBOSE_DEBUG */ |
| @@ -232,8 +222,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, · 205 unmodified lines | ||
| 232 | 222 | if (!_ep || !desc || ep->desc || _ep->name == ep0name |
| 233 | 223 | || desc->bDescriptorType != USB_DT_ENDPOINT |
| 234 | 224 | || ep->bEndpointAddress != desc->bEndpointAddress |
| 235 | − || ep->fifo_size < le16_to_cpu | |
| 236 | − (desc->wMaxPacketSize)) { | |
| 225 | + || ep->fifo_size < usb_endpoint_maxp (desc)) { | |
| 237 | 226 | DMSG("%s, bad ep or descriptor\n", __func__); |
| 238 | 227 | return -EINVAL; |
| 239 | 228 | } |
| @@ -248,7 +237,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, · 8 unmodified lines | ||
| 248 | 237 | |
| 249 | 238 | /* hardware _could_ do smaller, but driver doesn't */ |
| 250 | 239 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK |
| 251 | − && le16_to_cpu (desc->wMaxPacketSize) | |
| 240 | + && usb_endpoint_maxp (desc) | |
| 252 | 241 | != BULK_FIFO_SIZE) |
| 253 | 242 | || !desc->wMaxPacketSize) { |
| 254 | 243 | DMSG("%s, bad %s maxpacket\n", __func__, _ep->name); |
| @@ -264,7 +253,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, · 9 unmodified lines | ||
| 264 | 253 | ep->desc = desc; |
| 265 | 254 | ep->stopped = 0; |
| 266 | 255 | ep->pio_irqs = 0; |
| 267 | − ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize); | |
| 256 | + ep->ep.maxpacket = usb_endpoint_maxp (desc); | |
| 268 | 257 | |
| 269 | 258 | /* flush fifo (mostly for OUT buffers) */ |
| 270 | 259 | pxa25x_ep_fifo_flush (_ep); |
| @@ -401,7 +390,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) · 130 unmodified lines | ||
| 401 | 390 | { |
| 402 | 391 | unsigned max; |
| 403 | 392 | |
| 404 | − max = le16_to_cpu(ep->desc->wMaxPacketSize); | |
| 393 | + max = usb_endpoint_maxp(ep->desc); | |
| 405 | 394 | do { |
| 406 | 395 | unsigned count; |
| 407 | 396 | int is_last, is_short; |
| @@ -671,8 +660,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 263 unmodified lines | ||
| 671 | 660 | * we can report per-packet status. that also helps with dma. |
| 672 | 661 | */ |
| 673 | 662 | if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC |
| 674 | − && req->req.length > le16_to_cpu | |
| 675 | − (ep->desc->wMaxPacketSize))) | |
| 663 | + && req->req.length > usb_endpoint_maxp (ep->desc))) | |
| 676 | 664 | return -EMSGSIZE; |
| 677 | 665 | |
| 678 | 666 | DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", |
| @@ -1105,7 +1093,7 @@ udc_seq_show(struct seq_file *m, void *_d) · 426 unmodified lines | ||
| 1105 | 1093 | tmp = *dev->ep [i].reg_udccs; |
| 1106 | 1094 | seq_printf(m, |
| 1107 | 1095 | "%s max %d %s udccs %02x irqs %lu\n", |
| 1108 | − ep->ep.name, le16_to_cpu(desc->wMaxPacketSize), | |
| 1096 | + ep->ep.name, usb_endpoint_maxp(desc), | |
| 1109 | 1097 | "pio", tmp, ep->pio_irqs); |
| 1110 | 1098 | /* TODO translate all five groups of udccs bits! */ |
| 1111 | 1099 | |
| @@ -2202,7 +2190,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) · 1090 unmodified lines | ||
| 2202 | 2190 | |
| 2203 | 2191 | /* irq setup after old hardware state is cleaned up */ |
| 2204 | 2192 | retval = request_irq(irq, pxa25x_udc_irq, |
| 2205 | − IRQF_DISABLED, driver_name, dev); | |
| 2193 | + 0, driver_name, dev); | |
| 2206 | 2194 | if (retval != 0) { |
| 2207 | 2195 | pr_err("%s: can't get irq %d, err %d\n", |
| 2208 | 2196 | driver_name, irq, retval); |
| @@ -2214,7 +2202,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 2214 | 2202 | if (machine_is_lubbock()) { |
| 2215 | 2203 | retval = request_irq(LUBBOCK_USB_DISC_IRQ, |
| 2216 | 2204 | lubbock_vbus_irq, |
| 2217 | − IRQF_DISABLED | IRQF_SAMPLE_RANDOM, | |
| 2205 | + IRQF_SAMPLE_RANDOM, | |
| 2218 | 2206 | driver_name, dev); |
| 2219 | 2207 | if (retval != 0) { |
| 2220 | 2208 | pr_err("%s: can't get irq %i, err %d\n", |
| @@ -2223,7 +2211,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 2223 | 2211 | } |
| 2224 | 2212 | retval = request_irq(LUBBOCK_USB_IRQ, |
| 2225 | 2213 | lubbock_vbus_irq, |
| 2226 | − IRQF_DISABLED | IRQF_SAMPLE_RANDOM, | |
| 2214 | + IRQF_SAMPLE_RANDOM, | |
| 2227 | 2215 | driver_name, dev); |
| 2228 | 2216 | if (retval != 0) { |
| 2229 | 2217 | pr_err("%s: can't get irq %i, err %d\n", |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | #ifndef __LINUX_USB_GADGET_PXA25X_H |
| @@ -161,8 +152,6 @@ static struct pxa25x_udc *the_controller; · 137 unmodified lines | ||
| 161 | 152 | |
| 162 | 153 | #ifdef DEBUG |
| 163 | 154 | |
| 164 | −static int is_vbus_present(void); | |
| 165 | − | |
| 166 | 155 | static const char *state_name[] = { |
| 167 | 156 | "EP0_IDLE", |
| 168 | 157 | "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE", |
| @@ -214,8 +203,7 @@ dump_state(struct pxa25x_udc *dev) · 45 unmodified lines | ||
| 214 | 203 | u32 tmp; |
| 215 | 204 | unsigned i; |
| 216 | 205 | |
| 217 | − DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n", | |
| 218 | − is_vbus_present() ? "host " : "disconnected", | |
| 206 | + DMSG("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n", | |
| 219 | 207 | state_name[dev->ep0state], |
| 220 | 208 | UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL); |
| 221 | 209 | dump_udccr("udccr"); |
| @@ -232,9 +220,6 @@ dump_state(struct pxa25x_udc *dev) · 10 unmodified lines | ||
| 232 | 220 | } else |
| 233 | 221 | DMSG("ep0 driver '%s'\n", dev->driver->driver.name); |
| 234 | 222 | |
| 235 | − if (!is_vbus_present()) | |
| 236 | − return; | |
| 237 | − | |
| 238 | 223 | dump_udccs0 ("udccs0"); |
| 239 | 224 | DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n", |
| 240 | 225 | dev->stats.write.bytes, dev->stats.write.ops, |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | #include <linux/module.h> |
| 23 | 13 | #include <linux/kernel.h> |
| @@ -1439,7 +1429,7 @@ static int pxa_ep_enable(struct usb_ep *_ep, · 1415 unmodified lines | ||
| 1439 | 1429 | return -EINVAL; |
| 1440 | 1430 | } |
| 1441 | 1431 | |
| 1442 | − if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { | |
| 1432 | + if (ep->fifo_size < usb_endpoint_maxp(desc)) { | |
| 1443 | 1433 | ep_err(ep, "bad maxpacket\n"); |
| 1444 | 1434 | return -ERANGE; |
| 1445 | 1435 | } |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | #ifndef __LINUX_USB_GADGET_PXA27X_H |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | #include <linux/module.h> |
| @@ -28,13 +18,14 @@ · 4 unmodified lines | ||
| 28 | 18 | #include <linux/clk.h> |
| 29 | 19 | #include <linux/err.h> |
| 30 | 20 | #include <linux/slab.h> |
| 21 | +#include <linux/dma-mapping.h> | |
| 31 | 22 | |
| 32 | 23 | #include <linux/usb/ch9.h> |
| 33 | 24 | #include <linux/usb/gadget.h> |
| 34 | 25 | |
| 35 | 26 | #include "r8a66597-udc.h" |
| 36 | 27 | |
| 37 | −#define DRIVER_VERSION "2009-08-18" | |
| 28 | +#define DRIVER_VERSION "2011-09-26" | |
| 38 | 29 | |
| 39 | 30 | static const char udc_name[] = "r8a66597_udc"; |
| 40 | 31 | static const char *r8a66597_ep_name[] = { |
| @@ -115,13 +106,15 @@ static inline u16 control_reg_get_pid(struct r8a66597 *r8a66597, u16 pipenum) · 74 unmodified lines | ||
| 115 | 106 | u16 pid = 0; |
| 116 | 107 | unsigned long offset; |
| 117 | 108 | |
| 118 | − if (pipenum == 0) | |
| 109 | + if (pipenum == 0) { | |
| 119 | 110 | pid = r8a66597_read(r8a66597, DCPCTR) & PID; |
| 120 | − else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 111 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 121 | 112 | offset = get_pipectr_addr(pipenum); |
| 122 | 113 | pid = r8a66597_read(r8a66597, offset) & PID; |
| 123 | − } else | |
| 124 | − printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | |
| 114 | + } else { | |
| 115 | + dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n", | |
| 116 | + pipenum); | |
| 117 | + } | |
| 125 | 118 | |
| 126 | 119 | return pid; |
| 127 | 120 | } |
| @@ -131,13 +124,15 @@ static inline void control_reg_set_pid(struct r8a66597 *r8a66597, u16 pipenum, · 3 unmodified lines | ||
| 131 | 124 | { |
| 132 | 125 | unsigned long offset; |
| 133 | 126 | |
| 134 | − if (pipenum == 0) | |
| 127 | + if (pipenum == 0) { | |
| 135 | 128 | r8a66597_mdfy(r8a66597, pid, PID, DCPCTR); |
| 136 | − else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 129 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 137 | 130 | offset = get_pipectr_addr(pipenum); |
| 138 | 131 | r8a66597_mdfy(r8a66597, pid, PID, offset); |
| 139 | − } else | |
| 140 | − printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | |
| 132 | + } else { | |
| 133 | + dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n", | |
| 134 | + pipenum); | |
| 135 | + } | |
| 141 | 136 | } |
| 142 | 137 | |
| 143 | 138 | static inline void pipe_start(struct r8a66597 *r8a66597, u16 pipenum) |
| @@ -160,13 +155,15 @@ static inline u16 control_reg_get(struct r8a66597 *r8a66597, u16 pipenum) · 16 unmodified lines | ||
| 160 | 155 | u16 ret = 0; |
| 161 | 156 | unsigned long offset; |
| 162 | 157 | |
| 163 | − if (pipenum == 0) | |
| 158 | + if (pipenum == 0) { | |
| 164 | 159 | ret = r8a66597_read(r8a66597, DCPCTR); |
| 165 | − else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 160 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 166 | 161 | offset = get_pipectr_addr(pipenum); |
| 167 | 162 | ret = r8a66597_read(r8a66597, offset); |
| 168 | − } else | |
| 169 | − printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | |
| 163 | + } else { | |
| 164 | + dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n", | |
| 165 | + pipenum); | |
| 166 | + } | |
| 170 | 167 | |
| 171 | 168 | return ret; |
| 172 | 169 | } |
| @@ -177,13 +174,63 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum) · 4 unmodified lines | ||
| 177 | 174 | |
| 178 | 175 | pipe_stop(r8a66597, pipenum); |
| 179 | 176 | |
| 180 | − if (pipenum == 0) | |
| 177 | + if (pipenum == 0) { | |
| 181 | 178 | r8a66597_bset(r8a66597, SQCLR, DCPCTR); |
| 182 | − else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 179 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 183 | 180 | offset = get_pipectr_addr(pipenum); |
| 184 | 181 | r8a66597_bset(r8a66597, SQCLR, offset); |
| 185 | − } else | |
| 186 | − printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum); | |
| 182 | + } else { | |
| 183 | + dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n", | |
| 184 | + pipenum); | |
| 185 | + } | |
| 186 | +} | |
| 187 | + | |
| 188 | +static void control_reg_sqset(struct r8a66597 *r8a66597, u16 pipenum) | |
| 189 | +{ | |
| 190 | + unsigned long offset; | |
| 191 | + | |
| 192 | + pipe_stop(r8a66597, pipenum); | |
| 193 | + | |
| 194 | + if (pipenum == 0) { | |
| 195 | + r8a66597_bset(r8a66597, SQSET, DCPCTR); | |
| 196 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 197 | + offset = get_pipectr_addr(pipenum); | |
| 198 | + r8a66597_bset(r8a66597, SQSET, offset); | |
| 199 | + } else { | |
| 200 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 201 | + "unexpect pipe num(%d)\n", pipenum); | |
| 202 | + } | |
| 203 | +} | |
| 204 | + | |
| 205 | +static u16 control_reg_sqmon(struct r8a66597 *r8a66597, u16 pipenum) | |
| 206 | +{ | |
| 207 | + unsigned long offset; | |
| 208 | + | |
| 209 | + if (pipenum == 0) { | |
| 210 | + return r8a66597_read(r8a66597, DCPCTR) & SQMON; | |
| 211 | + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { | |
| 212 | + offset = get_pipectr_addr(pipenum); | |
| 213 | + return r8a66597_read(r8a66597, offset) & SQMON; | |
| 214 | + } else { | |
| 215 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 216 | + "unexpect pipe num(%d)\n", pipenum); | |
| 217 | + } | |
| 218 | + | |
| 219 | + return 0; | |
| 220 | +} | |
| 221 | + | |
| 222 | +static u16 save_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum) | |
| 223 | +{ | |
| 224 | + return control_reg_sqmon(r8a66597, pipenum); | |
| 225 | +} | |
| 226 | + | |
| 227 | +static void restore_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum, | |
| 228 | + u16 toggle) | |
| 229 | +{ | |
| 230 | + if (toggle) | |
| 231 | + control_reg_sqset(r8a66597, pipenum); | |
| 232 | + else | |
| 233 | + control_reg_sqclr(r8a66597, pipenum); | |
| 187 | 234 | } |
| 188 | 235 | |
| 189 | 236 | static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum) |
| @@ -222,18 +269,51 @@ static inline unsigned short mbw_value(struct r8a66597 *r8a66597) · 32 unmodified lines | ||
| 222 | 269 | return MBW_16; |
| 223 | 270 | } |
| 224 | 271 | |
| 272 | +static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum, | |
| 273 | + u16 isel, u16 fifosel) | |
| 274 | +{ | |
| 275 | + u16 tmp, mask, loop; | |
| 276 | + int i = 0; | |
| 277 | + | |
| 278 | + if (!pipenum) { | |
| 279 | + mask = ISEL | CURPIPE; | |
| 280 | + loop = isel; | |
| 281 | + } else { | |
| 282 | + mask = CURPIPE; | |
| 283 | + loop = pipenum; | |
| 284 | + } | |
| 285 | + r8a66597_mdfy(r8a66597, loop, mask, fifosel); | |
| 286 | + | |
| 287 | + do { | |
| 288 | + tmp = r8a66597_read(r8a66597, fifosel); | |
| 289 | + if (i++ > 1000000) { | |
| 290 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 291 | + "r8a66597: register%x, loop %x " | |
| 292 | + "is timeout\n", fifosel, loop); | |
| 293 | + break; | |
| 294 | + } | |
| 295 | + ndelay(1); | |
| 296 | + } while ((tmp & mask) != loop); | |
| 297 | +} | |
| 298 | + | |
| 225 | 299 | static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum) |
| 226 | 300 | { |
| 227 | 301 | struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; |
| 228 | 302 | |
| 229 | 303 | if (ep->use_dma) |
| 230 | − return; | |
| 304 | + r8a66597_bclr(r8a66597, DREQE, ep->fifosel); | |
| 231 | 305 | |
| 232 | 306 | r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel); |
| 233 | 307 | |
| 234 | 308 | ndelay(450); |
| 235 | 309 | |
| 236 | − r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); | |
| 310 | + if (r8a66597_is_sudmac(r8a66597) && ep->use_dma) | |
| 311 | + r8a66597_bclr(r8a66597, mbw_value(r8a66597), ep->fifosel); | |
| 312 | + else | |
| 313 | + r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); | |
| 314 | + | |
| 315 | + if (ep->use_dma) | |
| 316 | + r8a66597_bset(r8a66597, DREQE, ep->fifosel); | |
| 237 | 317 | } |
| 238 | 318 | |
| 239 | 319 | static int pipe_buffer_setting(struct r8a66597 *r8a66597, |
| @@ -297,17 +377,18 @@ static void pipe_buffer_release(struct r8a66597 *r8a66597, · 57 unmodified lines | ||
| 297 | 377 | if (info->pipe == 0) |
| 298 | 378 | return; |
| 299 | 379 | |
| 300 | − if (is_bulk_pipe(info->pipe)) | |
| 380 | + if (is_bulk_pipe(info->pipe)) { | |
| 301 | 381 | r8a66597->bulk--; |
| 302 | − else if (is_interrupt_pipe(info->pipe)) | |
| 382 | + } else if (is_interrupt_pipe(info->pipe)) { | |
| 303 | 383 | r8a66597->interrupt--; |
| 304 | − else if (is_isoc_pipe(info->pipe)) { | |
| 384 | + } else if (is_isoc_pipe(info->pipe)) { | |
| 305 | 385 | r8a66597->isochronous--; |
| 306 | 386 | if (info->type == R8A66597_BULK) |
| 307 | 387 | r8a66597->bulk--; |
| 308 | − } else | |
| 309 | − printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n", | |
| 310 | − info->pipe); | |
| 388 | + } else { | |
| 389 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 390 | + "ep_release: unexpect pipenum (%d)\n", info->pipe); | |
| 391 | + } | |
| 311 | 392 | } |
| 312 | 393 | |
| 313 | 394 | static void pipe_initialize(struct r8a66597_ep *ep) |
| @@ -337,11 +418,17 @@ static void r8a66597_ep_setting(struct r8a66597 *r8a66597, · 23 unmodified lines | ||
| 337 | 418 | ep->fifoaddr = CFIFO; |
| 338 | 419 | ep->fifosel = CFIFOSEL; |
| 339 | 420 | ep->fifoctr = CFIFOCTR; |
| 340 | − ep->fifotrn = 0; | |
| 341 | 421 | |
| 342 | 422 | ep->pipectr = get_pipectr_addr(pipenum); |
| 423 | + if (is_bulk_pipe(pipenum) || is_isoc_pipe(pipenum)) { | |
| 424 | + ep->pipetre = get_pipetre_addr(pipenum); | |
| 425 | + ep->pipetrn = get_pipetrn_addr(pipenum); | |
| 426 | + } else { | |
| 427 | + ep->pipetre = 0; | |
| 428 | + ep->pipetrn = 0; | |
| 429 | + } | |
| 343 | 430 | ep->pipenum = pipenum; |
| 344 | − ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 431 | + ep->ep.maxpacket = usb_endpoint_maxp(desc); | |
| 345 | 432 | r8a66597->pipenum2ep[pipenum] = ep; |
| 346 | 433 | r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK] |
| 347 | 434 | = ep; |
| @@ -381,7 +468,8 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, · 33 unmodified lines | ||
| 381 | 468 | case USB_ENDPOINT_XFER_BULK: |
| 382 | 469 | if (r8a66597->bulk >= R8A66597_MAX_NUM_BULK) { |
| 383 | 470 | if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) { |
| 384 | − printk(KERN_ERR "bulk pipe is insufficient\n"); | |
| 471 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 472 | + "bulk pipe is insufficient\n"); | |
| 385 | 473 | return -ENODEV; |
| 386 | 474 | } else { |
| 387 | 475 | info.pipe = R8A66597_BASE_PIPENUM_ISOC |
| @@ -397,7 +485,8 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, · 9 unmodified lines | ||
| 397 | 485 | break; |
| 398 | 486 | case USB_ENDPOINT_XFER_INT: |
| 399 | 487 | if (r8a66597->interrupt >= R8A66597_MAX_NUM_INT) { |
| 400 | − printk(KERN_ERR "interrupt pipe is insufficient\n"); | |
| 488 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 489 | + "interrupt pipe is insufficient\n"); | |
| 401 | 490 | return -ENODEV; |
| 402 | 491 | } |
| 403 | 492 | info.pipe = R8A66597_BASE_PIPENUM_INT + r8a66597->interrupt; |
| @@ -406,7 +495,8 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, · 2 unmodified lines | ||
| 406 | 495 | break; |
| 407 | 496 | case USB_ENDPOINT_XFER_ISOC: |
| 408 | 497 | if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) { |
| 409 | − printk(KERN_ERR "isochronous pipe is insufficient\n"); | |
| 498 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 499 | + "isochronous pipe is insufficient\n"); | |
| 410 | 500 | return -ENODEV; |
| 411 | 501 | } |
| 412 | 502 | info.pipe = R8A66597_BASE_PIPENUM_ISOC + r8a66597->isochronous; |
| @@ -414,13 +504,13 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, · 1 unmodified line | ||
| 414 | 504 | counter = &r8a66597->isochronous; |
| 415 | 505 | break; |
| 416 | 506 | default: |
| 417 | − printk(KERN_ERR "unexpect xfer type\n"); | |
| 507 | + dev_err(r8a66597_to_dev(r8a66597), "unexpect xfer type\n"); | |
| 418 | 508 | return -EINVAL; |
| 419 | 509 | } |
| 420 | 510 | ep->type = info.type; |
| 421 | 511 | |
| 422 | 512 | info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
| 423 | − info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 513 | + info.maxpacket = usb_endpoint_maxp(desc); | |
| 424 | 514 | info.interval = desc->bInterval; |
| 425 | 515 | if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) |
| 426 | 516 | info.dir_in = 1; |
| @@ -429,7 +519,8 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, · 2 unmodified lines | ||
| 429 | 519 | |
| 430 | 520 | ret = pipe_buffer_setting(r8a66597, &info); |
| 431 | 521 | if (ret < 0) { |
| 432 | − printk(KERN_ERR "pipe_buffer_setting fail\n"); | |
| 522 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 523 | + "pipe_buffer_setting fail\n"); | |
| 433 | 524 | return ret; |
| 434 | 525 | } |
| 435 | 526 | |
| @@ -495,6 +586,124 @@ static void start_ep0_write(struct r8a66597_ep *ep, · 59 unmodified lines | ||
| 495 | 586 | } |
| 496 | 587 | } |
| 497 | 588 | |
| 589 | +static void disable_fifosel(struct r8a66597 *r8a66597, u16 pipenum, | |
| 590 | + u16 fifosel) | |
| 591 | +{ | |
| 592 | + u16 tmp; | |
| 593 | + | |
| 594 | + tmp = r8a66597_read(r8a66597, fifosel) & CURPIPE; | |
| 595 | + if (tmp == pipenum) | |
| 596 | + r8a66597_change_curpipe(r8a66597, 0, 0, fifosel); | |
| 597 | +} | |
| 598 | + | |
| 599 | +static void change_bfre_mode(struct r8a66597 *r8a66597, u16 pipenum, | |
| 600 | + int enable) | |
| 601 | +{ | |
| 602 | + struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; | |
| 603 | + u16 tmp, toggle; | |
| 604 | + | |
| 605 | + /* check current BFRE bit */ | |
| 606 | + r8a66597_write(r8a66597, pipenum, PIPESEL); | |
| 607 | + tmp = r8a66597_read(r8a66597, PIPECFG) & R8A66597_BFRE; | |
| 608 | + if ((enable && tmp) || (!enable && !tmp)) | |
| 609 | + return; | |
| 610 | + | |
| 611 | + /* change BFRE bit */ | |
| 612 | + pipe_stop(r8a66597, pipenum); | |
| 613 | + disable_fifosel(r8a66597, pipenum, CFIFOSEL); | |
| 614 | + disable_fifosel(r8a66597, pipenum, D0FIFOSEL); | |
| 615 | + disable_fifosel(r8a66597, pipenum, D1FIFOSEL); | |
| 616 | + | |
| 617 | + toggle = save_usb_toggle(r8a66597, pipenum); | |
| 618 | + | |
| 619 | + r8a66597_write(r8a66597, pipenum, PIPESEL); | |
| 620 | + if (enable) | |
| 621 | + r8a66597_bset(r8a66597, R8A66597_BFRE, PIPECFG); | |
| 622 | + else | |
| 623 | + r8a66597_bclr(r8a66597, R8A66597_BFRE, PIPECFG); | |
| 624 | + | |
| 625 | + /* initialize for internal BFRE flag */ | |
| 626 | + r8a66597_bset(r8a66597, ACLRM, ep->pipectr); | |
| 627 | + r8a66597_bclr(r8a66597, ACLRM, ep->pipectr); | |
| 628 | + | |
| 629 | + restore_usb_toggle(r8a66597, pipenum, toggle); | |
| 630 | +} | |
| 631 | + | |
| 632 | +static int sudmac_alloc_channel(struct r8a66597 *r8a66597, | |
| 633 | + struct r8a66597_ep *ep, | |
| 634 | + struct r8a66597_request *req) | |
| 635 | +{ | |
| 636 | + struct r8a66597_dma *dma; | |
| 637 | + | |
| 638 | + if (!r8a66597_is_sudmac(r8a66597)) | |
| 639 | + return -ENODEV; | |
| 640 | + | |
| 641 | + /* Check transfer type */ | |
| 642 | + if (!is_bulk_pipe(ep->pipenum)) | |
| 643 | + return -EIO; | |
| 644 | + | |
| 645 | + if (r8a66597->dma.used) | |
| 646 | + return -EBUSY; | |
| 647 | + | |
| 648 | + /* set SUDMAC parameters */ | |
| 649 | + dma = &r8a66597->dma; | |
| 650 | + dma->used = 1; | |
| 651 | + if (ep->desc->bEndpointAddress & USB_DIR_IN) { | |
| 652 | + dma->dir = 1; | |
| 653 | + } else { | |
| 654 | + dma->dir = 0; | |
| 655 | + change_bfre_mode(r8a66597, ep->pipenum, 1); | |
| 656 | + } | |
| 657 | + | |
| 658 | + /* set r8a66597_ep paramters */ | |
| 659 | + ep->use_dma = 1; | |
| 660 | + ep->dma = dma; | |
| 661 | + ep->fifoaddr = D0FIFO; | |
| 662 | + ep->fifosel = D0FIFOSEL; | |
| 663 | + ep->fifoctr = D0FIFOCTR; | |
| 664 | + | |
| 665 | + /* dma mapping */ | |
| 666 | + req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597), | |
| 667 | + req->req.buf, req->req.length, | |
| 668 | + dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 669 | + | |
| 670 | + return 0; | |
| 671 | +} | |
| 672 | + | |
| 673 | +static void sudmac_free_channel(struct r8a66597 *r8a66597, | |
| 674 | + struct r8a66597_ep *ep, | |
| 675 | + struct r8a66597_request *req) | |
| 676 | +{ | |
| 677 | + if (!r8a66597_is_sudmac(r8a66597)) | |
| 678 | + return; | |
| 679 | + | |
| 680 | + dma_unmap_single(r8a66597_to_dev(ep->r8a66597), | |
| 681 | + req->req.dma, req->req.length, | |
| 682 | + ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 683 | + | |
| 684 | + r8a66597_bclr(r8a66597, DREQE, ep->fifosel); | |
| 685 | + r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel); | |
| 686 | + | |
| 687 | + ep->dma->used = 0; | |
| 688 | + ep->use_dma = 0; | |
| 689 | + ep->fifoaddr = CFIFO; | |
| 690 | + ep->fifosel = CFIFOSEL; | |
| 691 | + ep->fifoctr = CFIFOCTR; | |
| 692 | +} | |
| 693 | + | |
| 694 | +static void sudmac_start(struct r8a66597 *r8a66597, struct r8a66597_ep *ep, | |
| 695 | + struct r8a66597_request *req) | |
| 696 | +{ | |
| 697 | + BUG_ON(req->req.length == 0); | |
| 698 | + | |
| 699 | + r8a66597_sudmac_write(r8a66597, LBA_WAIT, CH0CFG); | |
| 700 | + r8a66597_sudmac_write(r8a66597, req->req.dma, CH0BA); | |
| 701 | + r8a66597_sudmac_write(r8a66597, req->req.length, CH0BBC); | |
| 702 | + r8a66597_sudmac_write(r8a66597, CH0ENDE, DINTCTRL); | |
| 703 | + | |
| 704 | + r8a66597_sudmac_write(r8a66597, DEN, CH0DEN); | |
| 705 | +} | |
| 706 | + | |
| 498 | 707 | static void start_packet_write(struct r8a66597_ep *ep, |
| 499 | 708 | struct r8a66597_request *req) |
| 500 | 709 | { |
| @@ -505,11 +714,29 @@ static void start_packet_write(struct r8a66597_ep *ep, · 4 unmodified lines | ||
| 505 | 714 | disable_irq_empty(r8a66597, ep->pipenum); |
| 506 | 715 | pipe_start(r8a66597, ep->pipenum); |
| 507 | 716 | |
| 508 | − tmp = r8a66597_read(r8a66597, ep->fifoctr); | |
| 509 | − if (unlikely((tmp & FRDY) == 0)) | |
| 510 | − pipe_irq_enable(r8a66597, ep->pipenum); | |
| 511 | − else | |
| 512 | − irq_packet_write(ep, req); | |
| 717 | + if (req->req.length == 0) { | |
| 718 | + transfer_complete(ep, req, 0); | |
| 719 | + } else { | |
| 720 | + r8a66597_write(r8a66597, ~(1 << ep->pipenum), BRDYSTS); | |
| 721 | + if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { | |
| 722 | + /* PIO mode */ | |
| 723 | + pipe_change(r8a66597, ep->pipenum); | |
| 724 | + disable_irq_empty(r8a66597, ep->pipenum); | |
| 725 | + pipe_start(r8a66597, ep->pipenum); | |
| 726 | + tmp = r8a66597_read(r8a66597, ep->fifoctr); | |
| 727 | + if (unlikely((tmp & FRDY) == 0)) | |
| 728 | + pipe_irq_enable(r8a66597, ep->pipenum); | |
| 729 | + else | |
| 730 | + irq_packet_write(ep, req); | |
| 731 | + } else { | |
| 732 | + /* DMA mode */ | |
| 733 | + pipe_change(r8a66597, ep->pipenum); | |
| 734 | + disable_irq_nrdy(r8a66597, ep->pipenum); | |
| 735 | + pipe_start(r8a66597, ep->pipenum); | |
| 736 | + enable_irq_nrdy(r8a66597, ep->pipenum); | |
| 737 | + sudmac_start(r8a66597, ep, req); | |
| 738 | + } | |
| 739 | + } | |
| 513 | 740 | } |
| 514 | 741 | |
| 515 | 742 | static void start_packet_read(struct r8a66597_ep *ep, |
| @@ -524,17 +751,26 @@ static void start_packet_read(struct r8a66597_ep *ep, · 8 unmodified lines | ||
| 524 | 751 | pipe_start(r8a66597, pipenum); |
| 525 | 752 | pipe_irq_enable(r8a66597, pipenum); |
| 526 | 753 | } else { |
| 527 | − if (ep->use_dma) { | |
| 528 | − r8a66597_bset(r8a66597, TRCLR, ep->fifosel); | |
| 529 | − pipe_change(r8a66597, pipenum); | |
| 530 | − r8a66597_bset(r8a66597, TRENB, ep->fifosel); | |
| 754 | + pipe_stop(r8a66597, pipenum); | |
| 755 | + if (ep->pipetre) { | |
| 756 | + enable_irq_nrdy(r8a66597, pipenum); | |
| 757 | + r8a66597_write(r8a66597, TRCLR, ep->pipetre); | |
| 531 | 758 | r8a66597_write(r8a66597, |
| 532 | − (req->req.length + ep->ep.maxpacket - 1) | |
| 533 | − / ep->ep.maxpacket, | |
| 534 | − ep->fifotrn); | |
| 759 | + DIV_ROUND_UP(req->req.length, ep->ep.maxpacket), | |
| 760 | + ep->pipetrn); | |
| 761 | + r8a66597_bset(r8a66597, TRENB, ep->pipetre); | |
| 762 | + } | |
| 763 | + | |
| 764 | + if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { | |
| 765 | + /* PIO mode */ | |
| 766 | + change_bfre_mode(r8a66597, ep->pipenum, 0); | |
| 767 | + pipe_start(r8a66597, pipenum); /* trigger once */ | |
| 768 | + pipe_irq_enable(r8a66597, pipenum); | |
| 769 | + } else { | |
| 770 | + pipe_change(r8a66597, pipenum); | |
| 771 | + sudmac_start(r8a66597, ep, req); | |
| 772 | + pipe_start(r8a66597, pipenum); /* trigger once */ | |
| 535 | 773 | } |
| 536 | − pipe_start(r8a66597, pipenum); /* trigger once */ | |
| 537 | − pipe_irq_enable(r8a66597, pipenum); | |
| 538 | 774 | } |
| 539 | 775 | } |
| 540 | 776 | |
| @@ -564,7 +800,8 @@ static void start_ep0(struct r8a66597_ep *ep, struct r8a66597_request *req) · 23 unmodified lines | ||
| 564 | 800 | control_end(ep->r8a66597, 0); |
| 565 | 801 | break; |
| 566 | 802 | default: |
| 567 | − printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq); | |
| 803 | + dev_err(r8a66597_to_dev(ep->r8a66597), | |
| 804 | + "start_ep0: unexpect ctsq(%x)\n", ctsq); | |
| 568 | 805 | break; |
| 569 | 806 | } |
| 570 | 807 | } |
| @@ -690,6 +927,9 @@ __acquires(r8a66597->lock) · 119 unmodified lines | ||
| 690 | 927 | if (!list_empty(&ep->queue)) |
| 691 | 928 | restart = 1; |
| 692 | 929 | |
| 930 | + if (ep->use_dma) | |
| 931 | + sudmac_free_channel(ep->r8a66597, ep, req); | |
| 932 | + | |
| 693 | 933 | spin_unlock(&ep->r8a66597->lock); |
| 694 | 934 | req->req.complete(&ep->ep, &req->req); |
| 695 | 935 | spin_lock(&ep->r8a66597->lock); |
| @@ -718,7 +958,8 @@ static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req) · 22 unmodified lines | ||
| 718 | 958 | do { |
| 719 | 959 | tmp = r8a66597_read(r8a66597, ep->fifoctr); |
| 720 | 960 | if (i++ > 100000) { |
| 721 | − printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus" | |
| 961 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 962 | + "pipe0 is busy. maybe cpu i/o bus " | |
| 722 | 963 | "conflict. please power off this controller."); |
| 723 | 964 | return; |
| 724 | 965 | } |
| @@ -733,7 +974,7 @@ static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req) · 8 unmodified lines | ||
| 733 | 974 | /* write fifo */ |
| 734 | 975 | if (req->req.buf) { |
| 735 | 976 | if (size > 0) |
| 736 | − r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size); | |
| 977 | + r8a66597_write_fifo(r8a66597, ep, buf, size); | |
| 737 | 978 | if ((size == 0) || ((size % ep->ep.maxpacket) != 0)) |
| 738 | 979 | r8a66597_bset(r8a66597, BVAL, ep->fifoctr); |
| 739 | 980 | } |
| @@ -769,7 +1010,8 @@ static void irq_packet_write(struct r8a66597_ep *ep, · 29 unmodified lines | ||
| 769 | 1010 | if (unlikely((tmp & FRDY) == 0)) { |
| 770 | 1011 | pipe_stop(r8a66597, pipenum); |
| 771 | 1012 | pipe_irq_disable(r8a66597, pipenum); |
| 772 | − printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum); | |
| 1013 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 1014 | + "write fifo not ready. pipnum=%d\n", pipenum); | |
| 773 | 1015 | return; |
| 774 | 1016 | } |
| 775 | 1017 | |
| @@ -780,7 +1022,7 @@ static void irq_packet_write(struct r8a66597_ep *ep, · 4 unmodified lines | ||
| 780 | 1022 | |
| 781 | 1023 | /* write fifo */ |
| 782 | 1024 | if (req->req.buf) { |
| 783 | − r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size); | |
| 1025 | + r8a66597_write_fifo(r8a66597, ep, buf, size); | |
| 784 | 1026 | if ((size == 0) |
| 785 | 1027 | || ((size % ep->ep.maxpacket) != 0) |
| 786 | 1028 | || ((bufsize != ep->ep.maxpacket) |
| @@ -819,7 +1061,7 @@ static void irq_packet_read(struct r8a66597_ep *ep, · 32 unmodified lines | ||
| 819 | 1061 | req->req.status = -EPIPE; |
| 820 | 1062 | pipe_stop(r8a66597, pipenum); |
| 821 | 1063 | pipe_irq_disable(r8a66597, pipenum); |
| 822 | − printk(KERN_ERR "read fifo not ready"); | |
| 1064 | + dev_err(r8a66597_to_dev(r8a66597), "read fifo not ready"); | |
| 823 | 1065 | return; |
| 824 | 1066 | } |
| 825 | 1067 | |
| @@ -1095,7 +1337,7 @@ static void r8a66597_update_usb_speed(struct r8a66597 *r8a66597) · 269 unmodified lines | ||
| 1095 | 1337 | break; |
| 1096 | 1338 | default: |
| 1097 | 1339 | r8a66597->gadget.speed = USB_SPEED_UNKNOWN; |
| 1098 | − printk(KERN_ERR "USB speed unknown\n"); | |
| 1340 | + dev_err(r8a66597_to_dev(r8a66597), "USB speed unknown\n"); | |
| 1099 | 1341 | } |
| 1100 | 1342 | } |
| 1101 | 1343 | |
| @@ -1158,11 +1400,71 @@ __acquires(r8a66597->lock) · 56 unmodified lines | ||
| 1158 | 1400 | control_end(r8a66597, 0); |
| 1159 | 1401 | break; |
| 1160 | 1402 | default: |
| 1161 | − printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq); | |
| 1403 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 1404 | + "ctrl_stage: unexpect ctsq(%x)\n", ctsq); | |
| 1162 | 1405 | break; |
| 1163 | 1406 | } |
| 1164 | 1407 | } |
| 1165 | 1408 | |
| 1409 | +static void sudmac_finish(struct r8a66597 *r8a66597, struct r8a66597_ep *ep) | |
| 1410 | +{ | |
| 1411 | + u16 pipenum; | |
| 1412 | + struct r8a66597_request *req; | |
| 1413 | + u32 len; | |
| 1414 | + int i = 0; | |
| 1415 | + | |
| 1416 | + pipenum = ep->pipenum; | |
| 1417 | + pipe_change(r8a66597, pipenum); | |
| 1418 | + | |
| 1419 | + while (!(r8a66597_read(r8a66597, ep->fifoctr) & FRDY)) { | |
| 1420 | + udelay(1); | |
| 1421 | + if (unlikely(i++ >= 10000)) { /* timeout = 10 msec */ | |
| 1422 | + dev_err(r8a66597_to_dev(r8a66597), | |
| 1423 | + "%s: FRDY was not set (%d)\n", | |
| 1424 | + __func__, pipenum); | |
| 1425 | + return; | |
| 1426 | + } | |
| 1427 | + } | |
| 1428 | + | |
| 1429 | + r8a66597_bset(r8a66597, BCLR, ep->fifoctr); | |
| 1430 | + req = get_request_from_ep(ep); | |
| 1431 | + | |
| 1432 | + /* prepare parameters */ | |
| 1433 | + len = r8a66597_sudmac_read(r8a66597, CH0CBC); | |
| 1434 | + req->req.actual += len; | |
| 1435 | + | |
| 1436 | + /* clear */ | |
| 1437 | + r8a66597_sudmac_write(r8a66597, CH0STCLR, DSTSCLR); | |
| 1438 | + | |
| 1439 | + /* check transfer finish */ | |
| 1440 | + if ((!req->req.zero && (req->req.actual == req->req.length)) | |
| 1441 | + || (len % ep->ep.maxpacket)) { | |
| 1442 | + if (ep->dma->dir) { | |
| 1443 | + disable_irq_ready(r8a66597, pipenum); | |
| 1444 | + enable_irq_empty(r8a66597, pipenum); | |
| 1445 | + } else { | |
| 1446 | + /* Clear the interrupt flag for next transfer */ | |
| 1447 | + r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); | |
| 1448 | + transfer_complete(ep, req, 0); | |
| 1449 | + } | |
| 1450 | + } | |
| 1451 | +} | |
| 1452 | + | |
| 1453 | +static void r8a66597_sudmac_irq(struct r8a66597 *r8a66597) | |
| 1454 | +{ | |
| 1455 | + u32 irqsts; | |
| 1456 | + struct r8a66597_ep *ep; | |
| 1457 | + u16 pipenum; | |
| 1458 | + | |
| 1459 | + irqsts = r8a66597_sudmac_read(r8a66597, DINTSTS); | |
| 1460 | + if (irqsts & CH0ENDS) { | |
| 1461 | + r8a66597_sudmac_write(r8a66597, CH0ENDC, DINTSTSCLR); | |
| 1462 | + pipenum = (r8a66597_read(r8a66597, D0FIFOSEL) & CURPIPE); | |
| 1463 | + ep = r8a66597->pipenum2ep[pipenum]; | |
| 1464 | + sudmac_finish(r8a66597, ep); | |
| 1465 | + } | |
| 1466 | +} | |
| 1467 | + | |
| 1166 | 1468 | static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) |
| 1167 | 1469 | { |
| 1168 | 1470 | struct r8a66597 *r8a66597 = _r8a66597; |
| @@ -1173,6 +1475,9 @@ static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) · 4 unmodified lines | ||
| 1173 | 1475 | u16 savepipe; |
| 1174 | 1476 | u16 mask0; |
| 1175 | 1477 | |
| 1478 | + if (r8a66597_is_sudmac(r8a66597)) | |
| 1479 | + r8a66597_sudmac_irq(r8a66597); | |
| 1480 | + | |
| 1176 | 1481 | spin_lock(&r8a66597->lock); |
| 1177 | 1482 | |
| 1178 | 1483 | intsts0 = r8a66597_read(r8a66597, INTSTS0); |
| @@ -1433,23 +1738,18 @@ static struct usb_ep_ops r8a66597_ep_ops = { · 254 unmodified lines | ||
| 1433 | 1738 | }; |
| 1434 | 1739 | |
| 1435 | 1740 | /*-------------------------------------------------------------------------*/ |
| 1436 | −static struct r8a66597 *the_controller; | |
| 1437 | − | |
| 1438 | −static int r8a66597_start(struct usb_gadget_driver *driver, | |
| 1439 | − int (*bind)(struct usb_gadget *)) | |
| 1741 | +static int r8a66597_start(struct usb_gadget *gadget, | |
| 1742 | + struct usb_gadget_driver *driver) | |
| 1440 | 1743 | { |
| 1441 | − struct r8a66597 *r8a66597 = the_controller; | |
| 1744 | + struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); | |
| 1442 | 1745 | int retval; |
| 1443 | 1746 | |
| 1444 | 1747 | if (!driver |
| 1445 | 1748 | || driver->speed != USB_SPEED_HIGH |
| 1446 | − || !bind | |
| 1447 | 1749 | || !driver->setup) |
| 1448 | 1750 | return -EINVAL; |
| 1449 | 1751 | if (!r8a66597) |
| 1450 | 1752 | return -ENODEV; |
| 1451 | − if (r8a66597->driver) | |
| 1452 | − return -EBUSY; | |
| 1453 | 1753 | |
| 1454 | 1754 | /* hook up the driver */ |
| 1455 | 1755 | driver->driver.bus = NULL; |
| @@ -1458,14 +1758,8 @@ static int r8a66597_start(struct usb_gadget_driver *driver, · 2 unmodified lines | ||
| 1458 | 1758 | |
| 1459 | 1759 | retval = device_add(&r8a66597->gadget.dev); |
| 1460 | 1760 | if (retval) { |
| 1461 | − printk(KERN_ERR "device_add error (%d)\n", retval); | |
| 1462 | − goto error; | |
| 1463 | − } | |
| 1464 | − | |
| 1465 | − retval = bind(&r8a66597->gadget); | |
| 1466 | − if (retval) { | |
| 1467 | − printk(KERN_ERR "bind to driver error (%d)\n", retval); | |
| 1468 | − device_del(&r8a66597->gadget.dev); | |
| 1761 | + dev_err(r8a66597_to_dev(r8a66597), "device_add error (%d)\n", | |
| 1762 | + retval); | |
| 1469 | 1763 | goto error; |
| 1470 | 1764 | } |
| 1471 | 1765 | |
| @@ -1489,23 +1783,17 @@ error: · 17 unmodified lines | ||
| 1489 | 1783 | return retval; |
| 1490 | 1784 | } |
| 1491 | 1785 | |
| 1492 | −static int r8a66597_stop(struct usb_gadget_driver *driver) | |
| 1786 | +static int r8a66597_stop(struct usb_gadget *gadget, | |
| 1787 | + struct usb_gadget_driver *driver) | |
| 1493 | 1788 | { |
| 1494 | − struct r8a66597 *r8a66597 = the_controller; | |
| 1789 | + struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); | |
| 1495 | 1790 | unsigned long flags; |
| 1496 | 1791 | |
| 1497 | − if (driver != r8a66597->driver || !driver->unbind) | |
| 1498 | − return -EINVAL; | |
| 1499 | − | |
| 1500 | 1792 | spin_lock_irqsave(&r8a66597->lock, flags); |
| 1501 | − if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN) | |
| 1502 | − r8a66597_usb_disconnect(r8a66597); | |
| 1503 | 1793 | r8a66597_bclr(r8a66597, VBSE, INTENB0); |
| 1504 | 1794 | disable_controller(r8a66597); |
| 1505 | 1795 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
| 1506 | 1796 | |
| 1507 | − driver->unbind(&r8a66597->gadget); | |
| 1508 | − | |
| 1509 | 1797 | device_del(&r8a66597->gadget.dev); |
| 1510 | 1798 | r8a66597->driver = NULL; |
| 1511 | 1799 | return 0; |
| @@ -1535,8 +1823,8 @@ static int r8a66597_pullup(struct usb_gadget *gadget, int is_on) · 23 unmodified lines | ||
| 1535 | 1823 | |
| 1536 | 1824 | static struct usb_gadget_ops r8a66597_gadget_ops = { |
| 1537 | 1825 | .get_frame = r8a66597_get_frame, |
| 1538 | − .start = r8a66597_start, | |
| 1539 | − .stop = r8a66597_stop, | |
| 1826 | + .udc_start = r8a66597_start, | |
| 1827 | + .udc_stop = r8a66597_stop, | |
| 1540 | 1828 | .pullup = r8a66597_pullup, |
| 1541 | 1829 | }; |
| 1542 | 1830 | |
| @@ -1547,6 +1835,8 @@ static int __exit r8a66597_remove(struct platform_device *pdev) · 4 unmodified lines | ||
| 1547 | 1835 | usb_del_gadget_udc(&r8a66597->gadget); |
| 1548 | 1836 | del_timer_sync(&r8a66597->timer); |
| 1549 | 1837 | iounmap(r8a66597->reg); |
| 1838 | + if (r8a66597->pdata->sudmac) | |
| 1839 | + iounmap(r8a66597->sudmac_reg); | |
| 1550 | 1840 | free_irq(platform_get_irq(pdev, 0), r8a66597); |
| 1551 | 1841 | r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); |
| 1552 | 1842 | #ifdef CONFIG_HAVE_CLK |
| @@ -1563,6 +1853,26 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r) · 10 unmodified lines | ||
| 1563 | 1853 | { |
| 1564 | 1854 | } |
| 1565 | 1855 | |
| 1856 | +static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597, | |
| 1857 | + struct platform_device *pdev) | |
| 1858 | +{ | |
| 1859 | + struct resource *res; | |
| 1860 | + | |
| 1861 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac"); | |
| 1862 | + if (!res) { | |
| 1863 | + dev_err(&pdev->dev, "platform_get_resource error(sudmac).\n"); | |
| 1864 | + return -ENODEV; | |
| 1865 | + } | |
| 1866 | + | |
| 1867 | + r8a66597->sudmac_reg = ioremap(res->start, resource_size(res)); | |
| 1868 | + if (r8a66597->sudmac_reg == NULL) { | |
| 1869 | + dev_err(&pdev->dev, "ioremap error(sudmac).\n"); | |
| 1870 | + return -ENOMEM; | |
| 1871 | + } | |
| 1872 | + | |
| 1873 | + return 0; | |
| 1874 | +} | |
| 1875 | + | |
| 1566 | 1876 | static int __init r8a66597_probe(struct platform_device *pdev) |
| 1567 | 1877 | { |
| 1568 | 1878 | #ifdef CONFIG_HAVE_CLK |
| @@ -1579,7 +1889,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 1579 | 1889 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1580 | 1890 | if (!res) { |
| 1581 | 1891 | ret = -ENODEV; |
| 1582 | − printk(KERN_ERR "platform_get_resource error.\n"); | |
| 1892 | + dev_err(&pdev->dev, "platform_get_resource error.\n"); | |
| 1583 | 1893 | goto clean_up; |
| 1584 | 1894 | } |
| 1585 | 1895 | |
| @@ -1589,14 +1899,14 @@ static int __init r8a66597_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 1589 | 1899 | |
| 1590 | 1900 | if (irq < 0) { |
| 1591 | 1901 | ret = -ENODEV; |
| 1592 | − printk(KERN_ERR "platform_get_irq error.\n"); | |
| 1902 | + dev_err(&pdev->dev, "platform_get_irq error.\n"); | |
| 1593 | 1903 | goto clean_up; |
| 1594 | 1904 | } |
| 1595 | 1905 | |
| 1596 | 1906 | reg = ioremap(res->start, resource_size(res)); |
| 1597 | 1907 | if (reg == NULL) { |
| 1598 | 1908 | ret = -ENOMEM; |
| 1599 | − printk(KERN_ERR "ioremap error.\n"); | |
| 1909 | + dev_err(&pdev->dev, "ioremap error.\n"); | |
| 1600 | 1910 | goto clean_up; |
| 1601 | 1911 | } |
| 1602 | 1912 | |
| @@ -1604,7 +1914,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 1604 | 1914 | r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL); |
| 1605 | 1915 | if (r8a66597 == NULL) { |
| 1606 | 1916 | ret = -ENOMEM; |
| 1607 | − printk(KERN_ERR "kzalloc error\n"); | |
| 1917 | + dev_err(&pdev->dev, "kzalloc error\n"); | |
| 1608 | 1918 | goto clean_up; |
| 1609 | 1919 | } |
| 1610 | 1920 | |
| @@ -1640,13 +1950,18 @@ static int __init r8a66597_probe(struct platform_device *pdev) · 29 unmodified lines | ||
| 1640 | 1950 | clk_enable(r8a66597->clk); |
| 1641 | 1951 | } |
| 1642 | 1952 | #endif |
| 1953 | + if (r8a66597->pdata->sudmac) { | |
| 1954 | + ret = r8a66597_sudmac_ioremap(r8a66597, pdev); | |
| 1955 | + if (ret < 0) | |
| 1956 | + goto clean_up2; | |
| 1957 | + } | |
| 1643 | 1958 | |
| 1644 | 1959 | disable_controller(r8a66597); /* make sure controller is disabled */ |
| 1645 | 1960 | |
| 1646 | − ret = request_irq(irq, r8a66597_irq, IRQF_DISABLED | IRQF_SHARED, | |
| 1961 | + ret = request_irq(irq, r8a66597_irq, IRQF_SHARED, | |
| 1647 | 1962 | udc_name, r8a66597); |
| 1648 | 1963 | if (ret < 0) { |
| 1649 | − printk(KERN_ERR "request_irq error (%d)\n", ret); | |
| 1964 | + dev_err(&pdev->dev, "request_irq error (%d)\n", ret); | |
| 1650 | 1965 | goto clean_up2; |
| 1651 | 1966 | } |
| 1652 | 1967 | |
| @@ -1672,13 +1987,10 @@ static int __init r8a66597_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 1672 | 1987 | r8a66597->ep[0].fifoaddr = CFIFO; |
| 1673 | 1988 | r8a66597->ep[0].fifosel = CFIFOSEL; |
| 1674 | 1989 | r8a66597->ep[0].fifoctr = CFIFOCTR; |
| 1675 | − r8a66597->ep[0].fifotrn = 0; | |
| 1676 | 1990 | r8a66597->ep[0].pipectr = get_pipectr_addr(0); |
| 1677 | 1991 | r8a66597->pipenum2ep[0] = &r8a66597->ep[0]; |
| 1678 | 1992 | r8a66597->epaddr2ep[0] = &r8a66597->ep[0]; |
| 1679 | 1993 | |
| 1680 | − the_controller = r8a66597; | |
| 1681 | − | |
| 1682 | 1994 | r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep, |
| 1683 | 1995 | GFP_KERNEL); |
| 1684 | 1996 | if (r8a66597->ep0_req == NULL) |
| @@ -1705,6 +2017,8 @@ clean_up2: · 20 unmodified lines | ||
| 1705 | 2017 | #endif |
| 1706 | 2018 | clean_up: |
| 1707 | 2019 | if (r8a66597) { |
| 2020 | + if (r8a66597->sudmac_reg) | |
| 2021 | + iounmap(r8a66597->sudmac_reg); | |
| 1708 | 2022 | if (r8a66597->ep0_req) |
| 1709 | 2023 | r8a66597_free_request(&r8a66597->ep[0].ep, |
| 1710 | 2024 | r8a66597->ep0_req); |
| @@ -8,16 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; version 2 of the License. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | − * | |
| 21 | 11 | */ |
| 22 | 12 | |
| 23 | 13 | #ifndef __R8A66597_H__ |
| @@ -53,6 +43,7 @@ · 29 unmodified lines | ||
| 53 | 43 | ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \ |
| 54 | 44 | (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC))) |
| 55 | 45 | |
| 46 | +#define r8a66597_is_sudmac(r8a66597) (r8a66597->pdata->sudmac) | |
| 56 | 47 | struct r8a66597_pipe_info { |
| 57 | 48 | u16 pipe; |
| 58 | 49 | u16 epnum; |
| @@ -70,6 +61,7 @@ struct r8a66597_request { · 11 unmodified lines | ||
| 70 | 61 | struct r8a66597_ep { |
| 71 | 62 | struct usb_ep ep; |
| 72 | 63 | struct r8a66597 *r8a66597; |
| 64 | + struct r8a66597_dma *dma; | |
| 73 | 65 | |
| 74 | 66 | struct list_head queue; |
| 75 | 67 | unsigned busy:1; |
| @@ -85,13 +77,20 @@ struct r8a66597_ep { · 9 unmodified lines | ||
| 85 | 77 | unsigned char fifoaddr; |
| 86 | 78 | unsigned char fifosel; |
| 87 | 79 | unsigned char fifoctr; |
| 88 | − unsigned char fifotrn; | |
| 89 | 80 | unsigned char pipectr; |
| 81 | + unsigned char pipetre; | |
| 82 | + unsigned char pipetrn; | |
| 83 | +}; | |
| 84 | + | |
| 85 | +struct r8a66597_dma { | |
| 86 | + unsigned used:1; | |
| 87 | + unsigned dir:1; /* 1 = IN(write), 0 = OUT(read) */ | |
| 90 | 88 | }; |
| 91 | 89 | |
| 92 | 90 | struct r8a66597 { |
| 93 | 91 | spinlock_t lock; |
| 94 | 92 | void __iomem *reg; |
| 93 | + void __iomem *sudmac_reg; | |
| 95 | 94 | |
| 96 | 95 | #ifdef CONFIG_HAVE_CLK |
| 97 | 96 | struct clk *clk; |
| @@ -104,6 +103,7 @@ struct r8a66597 { · 6 unmodified lines | ||
| 104 | 103 | struct r8a66597_ep ep[R8A66597_MAX_NUM_PIPE]; |
| 105 | 104 | struct r8a66597_ep *pipenum2ep[R8A66597_MAX_NUM_PIPE]; |
| 106 | 105 | struct r8a66597_ep *epaddr2ep[16]; |
| 106 | + struct r8a66597_dma dma; | |
| 107 | 107 | |
| 108 | 108 | struct timer_list timer; |
| 109 | 109 | struct usb_request *ep0_req; /* for internal request */ |
| @@ -124,6 +124,7 @@ struct r8a66597 { · 14 unmodified lines | ||
| 124 | 124 | #define gadget_to_r8a66597(_gadget) \ |
| 125 | 125 | container_of(_gadget, struct r8a66597, gadget) |
| 126 | 126 | #define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget) |
| 127 | +#define r8a66597_to_dev(r8a66597) (r8a66597->gadget.dev.parent) | |
| 127 | 128 | |
| 128 | 129 | static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) |
| 129 | 130 | { |
| @@ -182,12 +183,27 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, · 52 unmodified lines | ||
| 182 | 183 | iowrite16(val, r8a66597->reg + offset); |
| 183 | 184 | } |
| 184 | 185 | |
| 186 | +static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | |
| 187 | + u16 val, u16 pat, unsigned long offset) | |
| 188 | +{ | |
| 189 | + u16 tmp; | |
| 190 | + tmp = r8a66597_read(r8a66597, offset); | |
| 191 | + tmp = tmp & (~pat); | |
| 192 | + tmp = tmp | val; | |
| 193 | + r8a66597_write(r8a66597, tmp, offset); | |
| 194 | +} | |
| 195 | + | |
| 196 | +#define r8a66597_bclr(r8a66597, val, offset) \ | |
| 197 | + r8a66597_mdfy(r8a66597, 0, val, offset) | |
| 198 | +#define r8a66597_bset(r8a66597, val, offset) \ | |
| 199 | + r8a66597_mdfy(r8a66597, val, 0, offset) | |
| 200 | + | |
| 185 | 201 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, |
| 186 | − unsigned long offset, | |
| 202 | + struct r8a66597_ep *ep, | |
| 187 | 203 | unsigned char *buf, |
| 188 | 204 | int len) |
| 189 | 205 | { |
| 190 | − void __iomem *fifoaddr = r8a66597->reg + offset; | |
| 206 | + void __iomem *fifoaddr = r8a66597->reg + ep->fifoaddr; | |
| 191 | 207 | int adj = 0; |
| 192 | 208 | int i; |
| 193 | 209 | |
| @@ -215,18 +231,12 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, · 21 unmodified lines | ||
| 215 | 231 | adj = 0x01; /* 16-bit wide */ |
| 216 | 232 | } |
| 217 | 233 | |
| 234 | + if (r8a66597->pdata->wr0_shorted_to_wr1) | |
| 235 | + r8a66597_bclr(r8a66597, MBW_16, ep->fifosel); | |
| 218 | 236 | for (i = 0; i < len; i++) |
| 219 | 237 | iowrite8(buf[i], fifoaddr + adj - (i & adj)); |
| 220 | −} | |
| 221 | − | |
| 222 | −static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | |
| 223 | − u16 val, u16 pat, unsigned long offset) | |
| 224 | −{ | |
| 225 | − u16 tmp; | |
| 226 | − tmp = r8a66597_read(r8a66597, offset); | |
| 227 | − tmp = tmp & (~pat); | |
| 228 | − tmp = tmp | val; | |
| 229 | − r8a66597_write(r8a66597, tmp, offset); | |
| 238 | + if (r8a66597->pdata->wr0_shorted_to_wr1) | |
| 239 | + r8a66597_bclr(r8a66597, MBW_16, ep->fifosel); | |
| 230 | 240 | } |
| 231 | 241 | |
| 232 | 242 | static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) |
| @@ -251,12 +261,21 @@ static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) · 18 unmodified lines | ||
| 251 | 261 | return clock; |
| 252 | 262 | } |
| 253 | 263 | |
| 254 | −#define r8a66597_bclr(r8a66597, val, offset) \ | |
| 255 | − r8a66597_mdfy(r8a66597, 0, val, offset) | |
| 256 | −#define r8a66597_bset(r8a66597, val, offset) \ | |
| 257 | − r8a66597_mdfy(r8a66597, val, 0, offset) | |
| 264 | +static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597, | |
| 265 | + unsigned long offset) | |
| 266 | +{ | |
| 267 | + return ioread32(r8a66597->sudmac_reg + offset); | |
| 268 | +} | |
| 269 | + | |
| 270 | +static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val, | |
| 271 | + unsigned long offset) | |
| 272 | +{ | |
| 273 | + iowrite32(val, r8a66597->sudmac_reg + offset); | |
| 274 | +} | |
| 258 | 275 | |
| 259 | 276 | #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) |
| 277 | +#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) | |
| 278 | +#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) | |
| 260 | 279 | |
| 261 | 280 | #define enable_irq_ready(r8a66597, pipenum) \ |
| 262 | 281 | enable_pipe_irq(r8a66597, pipenum, BRDYENB) |
| @@ -1951,30 +1951,26 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) · 1950 unmodified lines | ||
| 1951 | 1951 | case S3C_DSTS_EnumSpd_FS: |
| 1952 | 1952 | case S3C_DSTS_EnumSpd_FS48: |
| 1953 | 1953 | hsotg->gadget.speed = USB_SPEED_FULL; |
| 1954 | − dev_info(hsotg->dev, "new device is full-speed\n"); | |
| 1955 | − | |
| 1956 | 1954 | ep0_mps = EP0_MPS_LIMIT; |
| 1957 | 1955 | ep_mps = 64; |
| 1958 | 1956 | break; |
| 1959 | 1957 | |
| 1960 | 1958 | case S3C_DSTS_EnumSpd_HS: |
| 1961 | − dev_info(hsotg->dev, "new device is high-speed\n"); | |
| 1962 | 1959 | hsotg->gadget.speed = USB_SPEED_HIGH; |
| 1963 | − | |
| 1964 | 1960 | ep0_mps = EP0_MPS_LIMIT; |
| 1965 | 1961 | ep_mps = 512; |
| 1966 | 1962 | break; |
| 1967 | 1963 | |
| 1968 | 1964 | case S3C_DSTS_EnumSpd_LS: |
| 1969 | 1965 | hsotg->gadget.speed = USB_SPEED_LOW; |
| 1970 | − dev_info(hsotg->dev, "new device is low-speed\n"); | |
| 1971 | − | |
| 1972 | 1966 | /* note, we don't actually support LS in this driver at the |
| 1973 | 1967 | * moment, and the documentation seems to imply that it isn't |
| 1974 | 1968 | * supported by the PHYs on some of the devices. |
| 1975 | 1969 | */ |
| 1976 | 1970 | break; |
| 1977 | 1971 | } |
| 1972 | + dev_info(hsotg->dev, "new device is %s\n", | |
| 1973 | + usb_speed_string(hsotg->gadget.speed)); | |
| 1978 | 1974 | |
| 1979 | 1975 | /* we should now know the maximum packet size for an |
| 1980 | 1976 | * endpoint, so set the endpoints to a default value. */ |
| @@ -2297,7 +2293,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, · 316 unmodified lines | ||
| 2297 | 2293 | return -EINVAL; |
| 2298 | 2294 | } |
| 2299 | 2295 | |
| 2300 | − mps = le16_to_cpu(desc->wMaxPacketSize); | |
| 2296 | + mps = usb_endpoint_maxp(desc); | |
| 2301 | 2297 | |
| 2302 | 2298 | /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ |
| 2303 | 2299 | |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/clk.h> |
| 27 | 27 | #include <linux/usb/ch9.h> |
| 28 | 28 | #include <linux/usb/gadget.h> |
| 29 | +#include <linux/usb/otg.h> | |
| 29 | 30 | #include <linux/prefetch.h> |
| 30 | 31 | |
| 31 | 32 | #include <mach/regs-s3c2443-clock.h> |
| @@ -137,6 +138,7 @@ struct s3c_hsudc { · 105 unmodified lines | ||
| 137 | 138 | struct usb_gadget_driver *driver; |
| 138 | 139 | struct device *dev; |
| 139 | 140 | struct s3c24xx_hsudc_platdata *pd; |
| 141 | + struct otg_transceiver *transceiver; | |
| 140 | 142 | spinlock_t lock; |
| 141 | 143 | void __iomem *regs; |
| 142 | 144 | struct resource *mem_rsrc; |
| @@ -759,11 +761,11 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, · 616 unmodified lines | ||
| 759 | 761 | if (!_ep || !desc || hsep->desc || _ep->name == ep0name |
| 760 | 762 | || desc->bDescriptorType != USB_DT_ENDPOINT |
| 761 | 763 | || hsep->bEndpointAddress != desc->bEndpointAddress |
| 762 | − || ep_maxpacket(hsep) < le16_to_cpu(desc->wMaxPacketSize)) | |
| 764 | + || ep_maxpacket(hsep) < usb_endpoint_maxp(desc)) | |
| 763 | 765 | return -EINVAL; |
| 764 | 766 | |
| 765 | 767 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK |
| 766 | − && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(hsep)) | |
| 768 | + && usb_endpoint_maxp(desc) != ep_maxpacket(hsep)) | |
| 767 | 769 | || !desc->wMaxPacketSize) |
| 768 | 770 | return -ERANGE; |
| 769 | 771 | |
| @@ -779,7 +781,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, · 9 unmodified lines | ||
| 779 | 781 | |
| 780 | 782 | hsep->stopped = hsep->wedge = 0; |
| 781 | 783 | hsep->desc = desc; |
| 782 | − hsep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | |
| 784 | + hsep->ep.maxpacket = usb_endpoint_maxp(desc); | |
| 783 | 785 | |
| 784 | 786 | s3c_hsudc_set_halt(_ep, 0); |
| 785 | 787 | __set_bit(ep_index(hsep), hsudc->regs + S3C_EIER); |
| @@ -1171,6 +1173,22 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, · 385 unmodified lines | ||
| 1171 | 1173 | return ret; |
| 1172 | 1174 | } |
| 1173 | 1175 | |
| 1176 | + /* connect to bus through transceiver */ | |
| 1177 | + if (hsudc->transceiver) { | |
| 1178 | + ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget); | |
| 1179 | + if (ret) { | |
| 1180 | + dev_err(hsudc->dev, "%s: can't bind to transceiver\n", | |
| 1181 | + hsudc->gadget.name); | |
| 1182 | + driver->unbind(&hsudc->gadget); | |
| 1183 | + | |
| 1184 | + device_del(&hsudc->gadget.dev); | |
| 1185 | + | |
| 1186 | + hsudc->driver = NULL; | |
| 1187 | + hsudc->gadget.dev.driver = NULL; | |
| 1188 | + return ret; | |
| 1189 | + } | |
| 1190 | + } | |
| 1191 | + | |
| 1174 | 1192 | enable_irq(hsudc->irq); |
| 1175 | 1193 | dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name); |
| 1176 | 1194 | |
| @@ -1201,6 +1219,9 @@ static int s3c_hsudc_stop(struct usb_gadget_driver *driver) · 24 unmodified lines | ||
| 1201 | 1219 | s3c_hsudc_stop_activity(hsudc, driver); |
| 1202 | 1220 | spin_unlock_irqrestore(&hsudc->lock, flags); |
| 1203 | 1221 | |
| 1222 | + if (hsudc->transceiver) | |
| 1223 | + (void) otg_set_peripheral(hsudc->transceiver, NULL); | |
| 1224 | + | |
| 1204 | 1225 | driver->unbind(&hsudc->gadget); |
| 1205 | 1226 | device_del(&hsudc->gadget.dev); |
| 1206 | 1227 | disable_irq(hsudc->irq); |
| @@ -1220,10 +1241,24 @@ static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget) · 13 unmodified lines | ||
| 1220 | 1241 | return s3c_hsudc_read_frameno(to_hsudc(gadget)); |
| 1221 | 1242 | } |
| 1222 | 1243 | |
| 1244 | +static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) | |
| 1245 | +{ | |
| 1246 | + struct s3c_hsudc *hsudc = the_controller; | |
| 1247 | + | |
| 1248 | + if (!hsudc) | |
| 1249 | + return -ENODEV; | |
| 1250 | + | |
| 1251 | + if (hsudc->transceiver) | |
| 1252 | + return otg_set_power(hsudc->transceiver, mA); | |
| 1253 | + | |
| 1254 | + return -EOPNOTSUPP; | |
| 1255 | +} | |
| 1256 | + | |
| 1223 | 1257 | static struct usb_gadget_ops s3c_hsudc_gadget_ops = { |
| 1224 | 1258 | .get_frame = s3c_hsudc_gadget_getframe, |
| 1225 | 1259 | .start = s3c_hsudc_start, |
| 1226 | 1260 | .stop = s3c_hsudc_stop, |
| 1261 | + .vbus_draw = s3c_hsudc_vbus_draw, | |
| 1227 | 1262 | }; |
| 1228 | 1263 | |
| 1229 | 1264 | static int s3c_hsudc_probe(struct platform_device *pdev) |
| @@ -1247,6 +1282,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 1247 | 1282 | hsudc->dev = dev; |
| 1248 | 1283 | hsudc->pd = pdev->dev.platform_data; |
| 1249 | 1284 | |
| 1285 | + hsudc->transceiver = otg_get_transceiver(); | |
| 1286 | + | |
| 1250 | 1287 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1251 | 1288 | if (!res) { |
| 1252 | 1289 | dev_err(dev, "unable to obtain driver resource data\n"); |
| @@ -1269,19 +1306,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 1269 | 1306 | goto err_remap; |
| 1270 | 1307 | } |
| 1271 | 1308 | |
| 1272 | − ret = platform_get_irq(pdev, 0); | |
| 1273 | − if (ret < 0) { | |
| 1274 | − dev_err(dev, "unable to obtain IRQ number\n"); | |
| 1275 | − goto err_irq; | |
| 1276 | − } | |
| 1277 | − hsudc->irq = ret; | |
| 1278 | − | |
| 1279 | − ret = request_irq(hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc); | |
| 1280 | − if (ret < 0) { | |
| 1281 | − dev_err(dev, "irq request failed\n"); | |
| 1282 | − goto err_irq; | |
| 1283 | − } | |
| 1284 | − | |
| 1285 | 1309 | spin_lock_init(&hsudc->lock); |
| 1286 | 1310 | |
| 1287 | 1311 | device_initialize(&hsudc->gadget.dev); |
| @@ -1299,6 +1323,19 @@ static int s3c_hsudc_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 1299 | 1323 | |
| 1300 | 1324 | s3c_hsudc_setup_ep(hsudc); |
| 1301 | 1325 | |
| 1326 | + ret = platform_get_irq(pdev, 0); | |
| 1327 | + if (ret < 0) { | |
| 1328 | + dev_err(dev, "unable to obtain IRQ number\n"); | |
| 1329 | + goto err_irq; | |
| 1330 | + } | |
| 1331 | + hsudc->irq = ret; | |
| 1332 | + | |
| 1333 | + ret = request_irq(hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc); | |
| 1334 | + if (ret < 0) { | |
| 1335 | + dev_err(dev, "irq request failed\n"); | |
| 1336 | + goto err_irq; | |
| 1337 | + } | |
| 1338 | + | |
| 1302 | 1339 | hsudc->uclk = clk_get(&pdev->dev, "usb-device"); |
| 1303 | 1340 | if (IS_ERR(hsudc->uclk)) { |
| 1304 | 1341 | dev_err(dev, "failed to find usb-device clock source\n"); |
| @@ -10,16 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | 12 | * (at your option) any later version. |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | − * GNU General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public License | |
| 20 | − * along with this program; if not, write to the Free Software | |
| 21 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | − * | |
| 23 | 13 | */ |
| 24 | 14 | |
| 25 | 15 | #include <linux/module.h> |
| @@ -1082,7 +1072,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, · 1056 unmodified lines | ||
| 1082 | 1072 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) |
| 1083 | 1073 | return -ESHUTDOWN; |
| 1084 | 1074 | |
| 1085 | − max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; | |
| 1075 | + max = usb_endpoint_maxp(desc) & 0x1fff; | |
| 1086 | 1076 | |
| 1087 | 1077 | local_irq_save (flags); |
| 1088 | 1078 | _ep->maxpacket = max & 0x7ff; |
| @@ -1903,7 +1893,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) · 814 unmodified lines | ||
| 1903 | 1893 | |
| 1904 | 1894 | /* irq setup after old hardware state is cleaned up */ |
| 1905 | 1895 | retval = request_irq(IRQ_USBD, s3c2410_udc_irq, |
| 1906 | − IRQF_DISABLED, gadget_name, udc); | |
| 1896 | + 0, gadget_name, udc); | |
| 1907 | 1897 | |
| 1908 | 1898 | if (retval != 0) { |
| 1909 | 1899 | dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval); |
| @@ -1927,7 +1917,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 1927 | 1917 | } |
| 1928 | 1918 | |
| 1929 | 1919 | retval = request_irq(irq, s3c2410_udc_vbus_irq, |
| 1930 | − IRQF_DISABLED | IRQF_TRIGGER_RISING | |
| 1920 | + IRQF_TRIGGER_RISING | |
| 1931 | 1921 | | IRQF_TRIGGER_FALLING | IRQF_SHARED, |
| 1932 | 1922 | gadget_name, udc); |
| 1933 | 1923 | |
| @@ -9,16 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | − * | |
| 22 | 12 | */ |
| 23 | 13 | |
| 24 | 14 | #ifndef _S3C2410_UDC_H |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | |
| @@ -52,6 +43,12 @@ · 28 unmodified lines | ||
| 52 | 43 | * characters rather then a pointer to void. |
| 53 | 44 | */ |
| 54 | 45 | |
| 46 | +/* | |
| 47 | + * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers | |
| 48 | + * sets the number of pipeline buffers (length of the fsg_buffhd array). | |
| 49 | + * The valid range of num_buffers is: num >= 2 && num <= 4. | |
| 50 | + */ | |
| 51 | + | |
| 55 | 52 | |
| 56 | 53 | #include <linux/usb/storage.h> |
| 57 | 54 | #include <scsi/scsi.h> |
| @@ -247,6 +244,8 @@ struct fsg_lun { · 189 unmodified lines | ||
| 247 | 244 | u32 sense_data_info; |
| 248 | 245 | u32 unit_attention_data; |
| 249 | 246 | |
| 247 | + unsigned int blkbits; /* Bits of logical block size of bound block device */ | |
| 248 | + unsigned int blksize; /* logical block size of bound block device */ | |
| 250 | 249 | struct device dev; |
| 251 | 250 | }; |
| 252 | 251 | |
| @@ -262,8 +261,31 @@ static struct fsg_lun *fsg_lun_from_dev(struct device *dev) · 9 unmodified lines | ||
| 262 | 261 | #define EP0_BUFSIZE 256 |
| 263 | 262 | #define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ |
| 264 | 263 | |
| 265 | −/* Number of buffers we will use. 2 is enough for double-buffering */ | |
| 266 | −#define FSG_NUM_BUFFERS 2 | |
| 264 | +#ifdef CONFIG_USB_GADGET_DEBUG_FILES | |
| 265 | + | |
| 266 | +static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; | |
| 267 | +module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO); | |
| 268 | +MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers"); | |
| 269 | + | |
| 270 | +#else | |
| 271 | + | |
| 272 | +/* | |
| 273 | + * Number of buffers we will use. | |
| 274 | + * 2 is usually enough for good buffering pipeline | |
| 275 | + */ | |
| 276 | +#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS | |
| 277 | + | |
| 278 | +#endif /* CONFIG_USB_DEBUG */ | |
| 279 | + | |
| 280 | +/* check if fsg_num_buffers is within a valid range */ | |
| 281 | +static inline int fsg_num_buffers_validate(void) | |
| 282 | +{ | |
| 283 | + if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) | |
| 284 | + return 0; | |
| 285 | + pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", | |
| 286 | + fsg_num_buffers, 2 ,4); | |
| 287 | + return -EINVAL; | |
| 288 | +} | |
| 267 | 289 | |
| 268 | 290 | /* Default size of buffer length. */ |
| 269 | 291 | #define FSG_BUFLEN ((u32)16384) |
| @@ -493,12 +515,128 @@ static struct usb_descriptor_header *fsg_hs_function[] = { · 223 unmodified lines | ||
| 493 | 515 | NULL, |
| 494 | 516 | }; |
| 495 | 517 | |
| 518 | +static struct usb_endpoint_descriptor | |
| 519 | +fsg_ss_bulk_in_desc = { | |
| 520 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 521 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 522 | + | |
| 523 | + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ | |
| 524 | + .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 525 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 526 | +}; | |
| 527 | + | |
| 528 | +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { | |
| 529 | + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | |
| 530 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 531 | + | |
| 532 | + /*.bMaxBurst = DYNAMIC, */ | |
| 533 | +}; | |
| 534 | + | |
| 535 | +static struct usb_endpoint_descriptor | |
| 536 | +fsg_ss_bulk_out_desc = { | |
| 537 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 538 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 539 | + | |
| 540 | + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ | |
| 541 | + .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
| 542 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 543 | +}; | |
| 544 | + | |
| 545 | +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { | |
| 546 | + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | |
| 547 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 548 | + | |
| 549 | + /*.bMaxBurst = DYNAMIC, */ | |
| 550 | +}; | |
| 551 | + | |
| 552 | +#ifndef FSG_NO_INTR_EP | |
| 553 | + | |
| 554 | +static struct usb_endpoint_descriptor | |
| 555 | +fsg_ss_intr_in_desc = { | |
| 556 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 557 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 558 | + | |
| 559 | + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ | |
| 560 | + .bmAttributes = USB_ENDPOINT_XFER_INT, | |
| 561 | + .wMaxPacketSize = cpu_to_le16(2), | |
| 562 | + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ | |
| 563 | +}; | |
| 564 | + | |
| 565 | +static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { | |
| 566 | + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | |
| 567 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 568 | + | |
| 569 | + .wBytesPerInterval = cpu_to_le16(2), | |
| 570 | +}; | |
| 571 | + | |
| 572 | +#ifndef FSG_NO_OTG | |
| 573 | +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2 | |
| 574 | +#else | |
| 575 | +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1 | |
| 576 | +#endif | |
| 577 | + | |
| 578 | +#endif | |
| 579 | + | |
| 580 | +static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = { | |
| 581 | + .bLength = USB_DT_USB_EXT_CAP_SIZE, | |
| 582 | + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, | |
| 583 | + .bDevCapabilityType = USB_CAP_TYPE_EXT, | |
| 584 | + | |
| 585 | + .bmAttributes = cpu_to_le32(USB_LPM_SUPPORT), | |
| 586 | +}; | |
| 587 | + | |
| 588 | +static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { | |
| 589 | + .bLength = USB_DT_USB_SS_CAP_SIZE, | |
| 590 | + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, | |
| 591 | + .bDevCapabilityType = USB_SS_CAP_TYPE, | |
| 592 | + | |
| 593 | + /* .bmAttributes = LTM is not supported yet */ | |
| 594 | + | |
| 595 | + .wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION | |
| 596 | + | USB_FULL_SPEED_OPERATION | |
| 597 | + | USB_HIGH_SPEED_OPERATION | |
| 598 | + | USB_5GBPS_OPERATION), | |
| 599 | + .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, | |
| 600 | + .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, | |
| 601 | + .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, | |
| 602 | +}; | |
| 603 | + | |
| 604 | +static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { | |
| 605 | + .bLength = USB_DT_BOS_SIZE, | |
| 606 | + .bDescriptorType = USB_DT_BOS, | |
| 607 | + | |
| 608 | + .wTotalLength = USB_DT_BOS_SIZE | |
| 609 | + + USB_DT_USB_EXT_CAP_SIZE | |
| 610 | + + USB_DT_USB_SS_CAP_SIZE, | |
| 611 | + | |
| 612 | + .bNumDeviceCaps = 2, | |
| 613 | +}; | |
| 614 | + | |
| 615 | +static struct usb_descriptor_header *fsg_ss_function[] = { | |
| 616 | +#ifndef FSG_NO_OTG | |
| 617 | + (struct usb_descriptor_header *) &fsg_otg_desc, | |
| 618 | +#endif | |
| 619 | + (struct usb_descriptor_header *) &fsg_intf_desc, | |
| 620 | + (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, | |
| 621 | + (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, | |
| 622 | + (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, | |
| 623 | + (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, | |
| 624 | +#ifndef FSG_NO_INTR_EP | |
| 625 | + (struct usb_descriptor_header *) &fsg_ss_intr_in_desc, | |
| 626 | + (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, | |
| 627 | +#endif | |
| 628 | + NULL, | |
| 629 | +}; | |
| 630 | + | |
| 496 | 631 | /* Maxpacket and other transfer characteristics vary by speed. */ |
| 497 | 632 | static __maybe_unused struct usb_endpoint_descriptor * |
| 498 | 633 | fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, |
| 499 | − struct usb_endpoint_descriptor *hs) | |
| 634 | + struct usb_endpoint_descriptor *hs, | |
| 635 | + struct usb_endpoint_descriptor *ss) | |
| 500 | 636 | { |
| 501 | − if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | |
| 637 | + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) | |
| 638 | + return ss; | |
| 639 | + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | |
| 502 | 640 | return hs; |
| 503 | 641 | return fs; |
| 504 | 642 | } |
| @@ -580,13 +718,24 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) · 75 unmodified lines | ||
| 580 | 718 | rc = (int) size; |
| 581 | 719 | goto out; |
| 582 | 720 | } |
| 583 | − num_sectors = size >> 9; /* File size in 512-byte blocks */ | |
| 721 | + | |
| 722 | + if (curlun->cdrom) { | |
| 723 | + curlun->blksize = 2048; | |
| 724 | + curlun->blkbits = 11; | |
| 725 | + } else if (inode->i_bdev) { | |
| 726 | + curlun->blksize = bdev_logical_block_size(inode->i_bdev); | |
| 727 | + curlun->blkbits = blksize_bits(curlun->blksize); | |
| 728 | + } else { | |
| 729 | + curlun->blksize = 512; | |
| 730 | + curlun->blkbits = 9; | |
| 731 | + } | |
| 732 | + | |
| 733 | + num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */ | |
| 584 | 734 | min_sectors = 1; |
| 585 | 735 | if (curlun->cdrom) { |
| 586 | − num_sectors &= ~3; /* Reduce to a multiple of 2048 */ | |
| 587 | − min_sectors = 300*4; /* Smallest track is 300 frames */ | |
| 588 | − if (num_sectors >= 256*60*75*4) { | |
| 589 | − num_sectors = (256*60*75 - 1) * 4; | |
| 736 | + min_sectors = 300; /* Smallest track is 300 frames */ | |
| 737 | + if (num_sectors >= 256*60*75) { | |
| 738 | + num_sectors = 256*60*75 - 1; | |
| 590 | 739 | LINFO(curlun, "file too big: %s\n", filename); |
| 591 | 740 | LINFO(curlun, "using only first %d blocks\n", |
| 592 | 741 | (int) num_sectors); |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | /* #define VERBOSE_DEBUG */ |
| @@ -9,15 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * it under the terms of the GNU General Public License as published by |
| 10 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | 11 | * (at your option) any later version. |
| 12 | − * | |
| 13 | − * This program is distributed in the hope that it will be useful, | |
| 14 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − * GNU General Public License for more details. | |
| 17 | − * | |
| 18 | − * You should have received a copy of the GNU General Public License | |
| 19 | − * along with this program; if not, write to the Free Software | |
| 20 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | 12 | */ |
| 22 | 13 | |
| 23 | 14 | #ifndef __U_ETHER_H |
| @@ -552,9 +552,8 @@ recycle: · 551 unmodified lines | ||
| 552 | 552 | /* Push from tty to ldisc; without low_latency set this is handled by |
| 553 | 553 | * a workqueue, so we won't get callbacks and can hold port_lock |
| 554 | 554 | */ |
| 555 | − if (tty && do_push) { | |
| 555 | + if (tty && do_push) | |
| 556 | 556 | tty_flip_buffer_push(tty); |
| 557 | − } | |
| 558 | 557 | |
| 559 | 558 | |
| 560 | 559 | /* We want our data queue to become empty ASAP, keeping data |
| @@ -356,7 +356,7 @@ static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store); · 355 unmodified lines | ||
| 356 | 356 | static ssize_t usb_udc_softconn_store(struct device *dev, |
| 357 | 357 | struct device_attribute *attr, const char *buf, size_t n) |
| 358 | 358 | { |
| 359 | − struct usb_udc *udc = dev_get_drvdata(dev); | |
| 359 | + struct usb_udc *udc = container_of(dev, struct usb_udc, dev); | |
| 360 | 360 | |
| 361 | 361 | if (sysfs_streq(buf, "connect")) { |
| 362 | 362 | usb_gadget_connect(udc->gadget); |
| @@ -375,23 +375,8 @@ static ssize_t usb_udc_speed_show(struct device *dev, · 12 unmodified lines | ||
| 375 | 375 | struct device_attribute *attr, char *buf) |
| 376 | 376 | { |
| 377 | 377 | struct usb_udc *udc = container_of(dev, struct usb_udc, dev); |
| 378 | − struct usb_gadget *gadget = udc->gadget; | |
| 379 | − | |
| 380 | − switch (gadget->speed) { | |
| 381 | − case USB_SPEED_LOW: | |
| 382 | − return snprintf(buf, PAGE_SIZE, "low-speed\n"); | |
| 383 | − case USB_SPEED_FULL: | |
| 384 | − return snprintf(buf, PAGE_SIZE, "full-speed\n"); | |
| 385 | − case USB_SPEED_HIGH: | |
| 386 | − return snprintf(buf, PAGE_SIZE, "high-speed\n"); | |
| 387 | − case USB_SPEED_WIRELESS: | |
| 388 | − return snprintf(buf, PAGE_SIZE, "wireless\n"); | |
| 389 | − case USB_SPEED_SUPER: | |
| 390 | − return snprintf(buf, PAGE_SIZE, "super-speed\n"); | |
| 391 | − case USB_SPEED_UNKNOWN: /* FALLTHROUGH */ | |
| 392 | − default: | |
| 393 | − return snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); | |
| 394 | − } | |
| 378 | + return snprintf(buf, PAGE_SIZE, "%s\n", | |
| 379 | + usb_speed_string(udc->gadget->speed)); | |
| 395 | 380 | } |
| 396 | 381 | static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL); |
| 397 | 382 | |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #ifndef _UVC_GADGET_H_ |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #include <linux/kernel.h> |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #include <linux/kernel.h> |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 13 | 12 | |
| 14 | 13 | #include <linux/kernel.h> |
| @@ -8,8 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | 11 | */ |
| 12 | + | |
| 13 | 13 | #include <linux/kernel.h> |
| 14 | 14 | #include <linux/device.h> |
| 15 | 15 | #include <linux/usb/video.h> |
| @@ -8,15 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | 10 | * (at your option) any later version. |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | 11 | */ |
| 21 | 12 | |
| 22 | 13 | |
| @@ -19,7 +19,7 @@ config USB_C67X00_HCD · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | config USB_XHCI_HCD |
| 21 | 21 | tristate "xHCI HCD (USB 3.0) support (EXPERIMENTAL)" |
| 22 | − depends on USB && PCI && EXPERIMENTAL | |
| 22 | + depends on USB && USB_ARCH_HAS_XHCI && EXPERIMENTAL | |
| 23 | 23 | ---help--- |
| 24 | 24 | The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 |
| 25 | 25 | "SuperSpeed" host controller hardware. |
| @@ -515,6 +515,19 @@ config USB_R8A66597_HCD · 489 unmodified lines | ||
| 515 | 515 | To compile this driver as a module, choose M here: the |
| 516 | 516 | module will be called r8a66597-hcd. |
| 517 | 517 | |
| 518 | +config USB_RENESAS_USBHS_HCD | |
| 519 | + tristate "Renesas USBHS HCD support" | |
| 520 | + depends on USB | |
| 521 | + depends on USB_RENESAS_USBHS | |
| 522 | + help | |
| 523 | + The Renesas USBHS is a USB 2.0 host and peripheral controller. | |
| 524 | + | |
| 525 | + Enable this option if your board has this chip, and you want | |
| 526 | + to use it as a host controller. If unsure, say N. | |
| 527 | + | |
| 528 | + To compile this driver as a module, choose M here: the | |
| 529 | + module will be called renesas-usbhs. | |
| 530 | + | |
| 518 | 531 | config USB_WHCI_HCD |
| 519 | 532 | tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" |
| 520 | 533 | depends on EXPERIMENTAL |
| @@ -544,11 +557,11 @@ config USB_HWA_HCD · 23 unmodified lines | ||
| 544 | 557 | will be called "hwa-hc". |
| 545 | 558 | |
| 546 | 559 | config USB_IMX21_HCD |
| 547 | − tristate "iMX21 HCD support" | |
| 548 | − depends on USB && ARM && MACH_MX21 | |
| 560 | + tristate "i.MX21 HCD support" | |
| 561 | + depends on USB && ARM && ARCH_MXC | |
| 549 | 562 | help |
| 550 | 563 | This driver enables support for the on-chip USB host in the |
| 551 | − iMX21 processor. | |
| 564 | + i.MX21 processor. | |
| 552 | 565 | |
| 553 | 566 | To compile this driver as a module, choose M here: the |
| 554 | 567 | module will be called "imx21-hcd". |
| @@ -578,3 +591,10 @@ config USB_OCTEON_OHCI · 23 unmodified lines | ||
| 578 | 591 | config USB_OCTEON2_COMMON |
| 579 | 592 | bool |
| 580 | 593 | default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI |
| 594 | + | |
| 595 | +config USB_PXA168_EHCI | |
| 596 | + bool "Marvell PXA168 on-chip EHCI HCD support" | |
| 597 | + depends on USB_EHCI_HCD && ARCH_MMP | |
| 598 | + help | |
| 599 | + Enable support for Marvell PXA168 SoC's on-chip EHCI | |
| 600 | + host controller | |
| @@ -11,8 +11,9 @@ fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o |
| 13 | 13 | |
| 14 | −xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o | |
| 14 | +xhci-hcd-y := xhci.o xhci-mem.o | |
| 15 | 15 | xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o |
| 16 | +xhci-hcd-$(CONFIG_PCI) += xhci-pci.o | |
| 16 | 17 | |
| 17 | 18 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ |
| 18 | 19 | |
| @@ -163,7 +163,7 @@ static int ehci_ath79_probe(struct platform_device *pdev) · 162 unmodified lines | ||
| 163 | 163 | goto err_release_region; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 166 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 167 | 167 | if (ret) |
| 168 | 168 | goto err_iounmap; |
| 169 | 169 | |
| @@ -181,7 +181,7 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) · 180 unmodified lines | ||
| 181 | 181 | ehci->hcs_params = readl(&ehci->caps->hcs_params); |
| 182 | 182 | |
| 183 | 183 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
| 184 | − IRQF_DISABLED | IRQF_SHARED); | |
| 184 | + IRQF_SHARED); | |
| 185 | 185 | if (ret == 0) { |
| 186 | 186 | platform_set_drvdata(pdev, hcd); |
| 187 | 187 | return ret; |
| @@ -293,7 +293,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) · 105 unmodified lines | ||
| 293 | 293 | /* here we "know" root ports should always stay powered */ |
| 294 | 294 | ehci_port_power(ehci, 1); |
| 295 | 295 | |
| 296 | − hcd->state = HC_STATE_SUSPENDED; | |
| 296 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 297 | 297 | |
| 298 | 298 | return 0; |
| 299 | 299 | } |
| @@ -697,6 +697,19 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) · 696 unmodified lines | ||
| 697 | 697 | } |
| 698 | 698 | #undef DBG_SCHED_LIMIT |
| 699 | 699 | |
| 700 | +static const char *rh_state_string(struct ehci_hcd *ehci) | |
| 701 | +{ | |
| 702 | + switch (ehci->rh_state) { | |
| 703 | + case EHCI_RH_HALTED: | |
| 704 | + return "halted"; | |
| 705 | + case EHCI_RH_SUSPENDED: | |
| 706 | + return "suspended"; | |
| 707 | + case EHCI_RH_RUNNING: | |
| 708 | + return "running"; | |
| 709 | + } | |
| 710 | + return "?"; | |
| 711 | +} | |
| 712 | + | |
| 700 | 713 | static ssize_t fill_registers_buffer(struct debug_buffer *buf) |
| 701 | 714 | { |
| 702 | 715 | struct usb_hcd *hcd; |
| @@ -730,11 +743,11 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) · 27 unmodified lines | ||
| 730 | 743 | temp = scnprintf (next, size, |
| 731 | 744 | "bus %s, device %s\n" |
| 732 | 745 | "%s\n" |
| 733 | − "EHCI %x.%02x, hcd state %d\n", | |
| 746 | + "EHCI %x.%02x, rh state %s\n", | |
| 734 | 747 | hcd->self.controller->bus->name, |
| 735 | 748 | dev_name(hcd->self.controller), |
| 736 | 749 | hcd->product_desc, |
| 737 | − i >> 8, i & 0x0ff, hcd->state); | |
| 750 | + i >> 8, i & 0x0ff, rh_state_string(ehci)); | |
| 738 | 751 | size -= temp; |
| 739 | 752 | next += temp; |
| 740 | 753 | |
| @@ -808,7 +821,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) · 67 unmodified lines | ||
| 808 | 821 | next += temp; |
| 809 | 822 | |
| 810 | 823 | temp = scnprintf (next, size, "uframe %04x\n", |
| 811 | − ehci_readl(ehci, &ehci->regs->frame_index)); | |
| 824 | + ehci_read_frame_index(ehci)); | |
| 812 | 825 | size -= temp; |
| 813 | 826 | next += temp; |
| 814 | 827 | |
| @@ -134,7 +134,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | /* Don't need to set host mode here. It will be done by tdi_reset() */ |
| 136 | 136 | |
| 137 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 137 | + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 138 | 138 | if (retval != 0) |
| 139 | 139 | goto err4; |
| 140 | 140 | |
| @@ -392,7 +392,7 @@ static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) · 251 unmodified lines | ||
| 392 | 392 | |
| 393 | 393 | dev_dbg(dev, "suspending...\n"); |
| 394 | 394 | |
| 395 | − hcd->state = HC_STATE_SUSPENDED; | |
| 395 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 396 | 396 | dev->power.power_state = PMSG_SUSPEND; |
| 397 | 397 | |
| 398 | 398 | /* ignore non-host interrupts */ |
| @@ -481,7 +481,7 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev) · 82 unmodified lines | ||
| 481 | 481 | ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); |
| 482 | 482 | |
| 483 | 483 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
| 484 | − hcd->state = HC_STATE_RUNNING; | |
| 484 | + ehci->rh_state = EHCI_RH_RUNNING; | |
| 485 | 485 | dev->power.power_state = PMSG_ON; |
| 486 | 486 | |
| 487 | 487 | tmp = ehci_readl(ehci, &ehci->regs->command); |
| @@ -95,7 +95,7 @@ static const char hcd_name [] = "ehci_hcd"; · 94 unmodified lines | ||
| 95 | 95 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
| 96 | 96 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ |
| 97 | 97 | #define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1) |
| 98 | − /* 200-ms async qh unlink delay */ | |
| 98 | + /* 5-ms async qh unlink delay */ | |
| 99 | 99 | |
| 100 | 100 | /* Initial IRQ latency: faster than hw default */ |
| 101 | 101 | static int log2_irq_thresh = 0; // 0 to 6 |
| @@ -238,7 +238,7 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, · 136 unmodified lines | ||
| 238 | 238 | error = handshake(ehci, ptr, mask, done, usec); |
| 239 | 239 | if (error) { |
| 240 | 240 | ehci_halt(ehci); |
| 241 | − ehci_to_hcd(ehci)->state = HC_STATE_HALT; | |
| 241 | + ehci->rh_state = EHCI_RH_HALTED; | |
| 242 | 242 | ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n", |
| 243 | 243 | ptr, mask, done, error); |
| 244 | 244 | } |
| @@ -278,7 +278,7 @@ static int ehci_reset (struct ehci_hcd *ehci) · 33 unmodified lines | ||
| 278 | 278 | command |= CMD_RESET; |
| 279 | 279 | dbg_cmd (ehci, "reset", command); |
| 280 | 280 | ehci_writel(ehci, command, &ehci->regs->command); |
| 281 | − ehci_to_hcd(ehci)->state = HC_STATE_HALT; | |
| 281 | + ehci->rh_state = EHCI_RH_HALTED; | |
| 282 | 282 | ehci->next_statechange = jiffies; |
| 283 | 283 | retval = handshake (ehci, &ehci->regs->command, |
| 284 | 284 | CMD_RESET, 0, 250 * 1000); |
| @@ -307,7 +307,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) · 22 unmodified lines | ||
| 307 | 307 | u32 temp; |
| 308 | 308 | |
| 309 | 309 | #ifdef DEBUG |
| 310 | − if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | |
| 310 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 311 | 311 | BUG (); |
| 312 | 312 | #endif |
| 313 | 313 | |
| @@ -356,7 +356,7 @@ static void ehci_iaa_watchdog(unsigned long param) · 42 unmodified lines | ||
| 356 | 356 | */ |
| 357 | 357 | if (ehci->reclaim |
| 358 | 358 | && !timer_pending(&ehci->iaa_watchdog) |
| 359 | − && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | |
| 359 | + && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 360 | 360 | u32 cmd, status; |
| 361 | 361 | |
| 362 | 362 | /* If we get here, IAA is *REALLY* late. It's barely |
| @@ -496,7 +496,7 @@ static void ehci_work (struct ehci_hcd *ehci) · 133 unmodified lines | ||
| 496 | 496 | * misplace IRQs, and should let us run completely without IRQs. |
| 497 | 497 | * such lossage has been observed on both VT6202 and VT8235. |
| 498 | 498 | */ |
| 499 | − if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && | |
| 499 | + if (ehci->rh_state == EHCI_RH_RUNNING && | |
| 500 | 500 | (ehci->async->qh_next.ptr != NULL || |
| 501 | 501 | ehci->periodic_sched != 0)) |
| 502 | 502 | timer_action (ehci, TIMER_IO_WATCHDOG); |
| @@ -516,7 +516,7 @@ static void ehci_stop (struct usb_hcd *hcd) · 13 unmodified lines | ||
| 516 | 516 | del_timer_sync(&ehci->iaa_watchdog); |
| 517 | 517 | |
| 518 | 518 | spin_lock_irq(&ehci->lock); |
| 519 | − if (HC_IS_RUNNING (hcd->state)) | |
| 519 | + if (ehci->rh_state == EHCI_RH_RUNNING) | |
| 520 | 520 | ehci_quiesce (ehci); |
| 521 | 521 | |
| 522 | 522 | ehci_silence_controller(ehci); |
| @@ -741,7 +741,7 @@ static int ehci_run (struct usb_hcd *hcd) · 218 unmodified lines | ||
| 741 | 741 | * be started before the port switching actions could complete. |
| 742 | 742 | */ |
| 743 | 743 | down_write(&ehci_cf_port_reset_rwsem); |
| 744 | − hcd->state = HC_STATE_RUNNING; | |
| 744 | + ehci->rh_state = EHCI_RH_RUNNING; | |
| 745 | 745 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
| 746 | 746 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
| 747 | 747 | msleep(5); |
| @@ -768,6 +768,35 @@ static int ehci_run (struct usb_hcd *hcd) · 20 unmodified lines | ||
| 768 | 768 | return 0; |
| 769 | 769 | } |
| 770 | 770 | |
| 771 | +static int __maybe_unused ehci_setup (struct usb_hcd *hcd) | |
| 772 | +{ | |
| 773 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 774 | + int retval; | |
| 775 | + | |
| 776 | + ehci->regs = (void __iomem *)ehci->caps + | |
| 777 | + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 778 | + dbg_hcs_params(ehci, "reset"); | |
| 779 | + dbg_hcc_params(ehci, "reset"); | |
| 780 | + | |
| 781 | + /* cache this readonly data; minimize chip reads */ | |
| 782 | + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 783 | + | |
| 784 | + ehci->sbrn = HCD_USB2; | |
| 785 | + | |
| 786 | + retval = ehci_halt(ehci); | |
| 787 | + if (retval) | |
| 788 | + return retval; | |
| 789 | + | |
| 790 | + /* data structure init */ | |
| 791 | + retval = ehci_init(hcd); | |
| 792 | + if (retval) | |
| 793 | + return retval; | |
| 794 | + | |
| 795 | + ehci_reset(ehci); | |
| 796 | + | |
| 797 | + return 0; | |
| 798 | +} | |
| 799 | + | |
| 771 | 800 | /*-------------------------------------------------------------------------*/ |
| 772 | 801 | |
| 773 | 802 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) |
| @@ -788,7 +817,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) · 14 unmodified lines | ||
| 788 | 817 | |
| 789 | 818 | /* Shared IRQ? */ |
| 790 | 819 | masked_status = status & INTR_MASK; |
| 791 | − if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) { | |
| 820 | + if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { | |
| 792 | 821 | spin_unlock(&ehci->lock); |
| 793 | 822 | return IRQ_NONE; |
| 794 | 823 | } |
| @@ -952,7 +981,7 @@ static int ehci_urb_enqueue ( · 157 unmodified lines | ||
| 952 | 981 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
| 953 | 982 | { |
| 954 | 983 | /* failfast */ |
| 955 | − if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim) | |
| 984 | + if (ehci->rh_state != EHCI_RH_RUNNING && ehci->reclaim) | |
| 956 | 985 | end_unlink_async(ehci); |
| 957 | 986 | |
| 958 | 987 | /* If the QH isn't linked then there's nothing we can do |
| @@ -1079,7 +1108,7 @@ rescan: · 120 unmodified lines | ||
| 1079 | 1108 | goto idle_timeout; |
| 1080 | 1109 | } |
| 1081 | 1110 | |
| 1082 | − if (!HC_IS_RUNNING (hcd->state)) | |
| 1111 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 1083 | 1112 | qh->qh_state = QH_STATE_IDLE; |
| 1084 | 1113 | switch (qh->qh_state) { |
| 1085 | 1114 | case QH_STATE_LINKED: |
| @@ -1166,8 +1195,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) · 80 unmodified lines | ||
| 1166 | 1195 | static int ehci_get_frame (struct usb_hcd *hcd) |
| 1167 | 1196 | { |
| 1168 | 1197 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 1169 | − return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) % | |
| 1170 | − ehci->periodic_size; | |
| 1198 | + return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size; | |
| 1171 | 1199 | } |
| 1172 | 1200 | |
| 1173 | 1201 | /*-------------------------------------------------------------------------*/ |
| @@ -1291,6 +1319,16 @@ MODULE_LICENSE ("GPL"); · 117 unmodified lines | ||
| 1291 | 1319 | #define PLATFORM_DRIVER ehci_grlib_driver |
| 1292 | 1320 | #endif |
| 1293 | 1321 | |
| 1322 | +#ifdef CONFIG_USB_PXA168_EHCI | |
| 1323 | +#include "ehci-pxa168.c" | |
| 1324 | +#define PLATFORM_DRIVER ehci_pxa168_driver | |
| 1325 | +#endif | |
| 1326 | + | |
| 1327 | +#ifdef CONFIG_NLM_XLR | |
| 1328 | +#include "ehci-xls.c" | |
| 1329 | +#define PLATFORM_DRIVER ehci_xls_driver | |
| 1330 | +#endif | |
| 1331 | + | |
| 1294 | 1332 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
| 1295 | 1333 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ |
| 1296 | 1334 | !defined(XILINX_OF_PLATFORM_DRIVER) |
| @@ -236,10 +236,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 235 unmodified lines | ||
| 236 | 236 | } |
| 237 | 237 | |
| 238 | 238 | /* stop schedules, clean any completed work */ |
| 239 | − if (HC_IS_RUNNING(hcd->state)) { | |
| 239 | + if (ehci->rh_state == EHCI_RH_RUNNING) | |
| 240 | 240 | ehci_quiesce (ehci); |
| 241 | − hcd->state = HC_STATE_QUIESCING; | |
| 242 | − } | |
| 243 | 241 | ehci->command = ehci_readl(ehci, &ehci->regs->command); |
| 244 | 242 | ehci_work(ehci); |
| 245 | 243 | |
| @@ -313,7 +311,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 67 unmodified lines | ||
| 313 | 311 | |
| 314 | 312 | /* turn off now-idle HC */ |
| 315 | 313 | ehci_halt (ehci); |
| 316 | − hcd->state = HC_STATE_SUSPENDED; | |
| 314 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 317 | 315 | |
| 318 | 316 | if (ehci->reclaim) |
| 319 | 317 | end_unlink_async(ehci); |
| @@ -382,6 +380,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 62 unmodified lines | ||
| 382 | 380 | |
| 383 | 381 | /* restore CMD_RUN, framelist size, and irq threshold */ |
| 384 | 382 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
| 383 | + ehci->rh_state = EHCI_RH_RUNNING; | |
| 385 | 384 | |
| 386 | 385 | /* Some controller/firmware combinations need a delay during which |
| 387 | 386 | * they set up the port statuses. See Bugzilla #8190. */ |
| @@ -451,7 +450,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 63 unmodified lines | ||
| 451 | 450 | } |
| 452 | 451 | |
| 453 | 452 | ehci->next_statechange = jiffies + msecs_to_jiffies(5); |
| 454 | − hcd->state = HC_STATE_RUNNING; | |
| 455 | 453 | |
| 456 | 454 | /* Now we can safely re-enable irqs */ |
| 457 | 455 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); |
| @@ -563,7 +561,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) · 105 unmodified lines | ||
| 563 | 561 | u32 ppcd = 0; |
| 564 | 562 | |
| 565 | 563 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ |
| 566 | − if (!HC_IS_RUNNING(hcd->state)) | |
| 564 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 567 | 565 | return 0; |
| 568 | 566 | |
| 569 | 567 | /* init status to no-changes */ |
| @@ -236,7 +236,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) · 235 unmodified lines | ||
| 236 | 236 | priv->hcd = hcd; |
| 237 | 237 | platform_set_drvdata(pdev, priv); |
| 238 | 238 | |
| 239 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 239 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 240 | 240 | if (ret) |
| 241 | 241 | goto err_add; |
| 242 | 242 | |
| @@ -155,7 +155,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) · 154 unmodified lines | ||
| 155 | 155 | /* cache this readonly data; minimize chip reads */ |
| 156 | 156 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
| 157 | 157 | |
| 158 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 158 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 159 | 159 | if (ret) { |
| 160 | 160 | dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); |
| 161 | 161 | goto err3; |
| @@ -228,7 +228,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) · 227 unmodified lines | ||
| 228 | 228 | /* cache this readonly data; minimize chip reads */ |
| 229 | 229 | omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); |
| 230 | 230 | |
| 231 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 231 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 232 | 232 | if (ret) { |
| 233 | 233 | dev_err(dev, "failed to add hcd with err %d\n", ret); |
| 234 | 234 | goto err_add_hcd; |
| @@ -277,7 +277,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) · 276 unmodified lines | ||
| 277 | 277 | printk(KERN_WARNING "Orion ehci -USB phy version isn't supported.\n"); |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | − err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); | |
| 280 | + err = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 281 | 281 | if (err) |
| 282 | 282 | goto err4; |
| 283 | 283 | |
| @@ -224,6 +224,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 223 unmodified lines | ||
| 224 | 224 | pci_dev_put(p_smbus); |
| 225 | 225 | } |
| 226 | 226 | break; |
| 227 | + case PCI_VENDOR_ID_NETMOS: | |
| 228 | + /* MosChip frame-index-register bug */ | |
| 229 | + ehci_info(ehci, "applying MosChip frame-index workaround\n"); | |
| 230 | + ehci->frame_index_bug = 1; | |
| 231 | + break; | |
| 227 | 232 | } |
| 228 | 233 | |
| 229 | 234 | /* optional debug port, normally in the first BAR */ |
| @@ -439,7 +444,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) · 209 unmodified lines | ||
| 439 | 444 | /* here we "know" root ports should always stay powered */ |
| 440 | 445 | ehci_port_power(ehci, 1); |
| 441 | 446 | |
| 442 | − hcd->state = HC_STATE_SUSPENDED; | |
| 447 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 443 | 448 | return 0; |
| 444 | 449 | } |
| 445 | 450 | #endif |
| @@ -167,7 +167,7 @@ static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) · 166 unmodified lines | ||
| 167 | 167 | |
| 168 | 168 | ps3_system_bus_set_drvdata(dev, hcd); |
| 169 | 169 | |
| 170 | − result = usb_add_hcd(hcd, virq, IRQF_DISABLED); | |
| 170 | + result = usb_add_hcd(hcd, virq, 0); | |
| 171 | 171 | |
| 172 | 172 | if (result) { |
| 173 | 173 | dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", |
| @@ -0,0 +1,363 @@ | ||
| 1 | +/* | |
| 2 | + * drivers/usb/host/ehci-pxa168.c | |
| 3 | + * | |
| 4 | + * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> | |
| 5 | + * | |
| 6 | + * Based on drivers/usb/host/ehci-orion.c | |
| 7 | + * | |
| 8 | + * This file is licensed under the terms of the GNU General Public | |
| 9 | + * License version 2. This program is licensed "as is" without any | |
| 10 | + * warranty of any kind, whether express or implied. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/kernel.h> | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/platform_device.h> | |
| 16 | +#include <linux/clk.h> | |
| 17 | +#include <mach/pxa168.h> | |
| 18 | + | |
| 19 | +#define USB_PHY_CTRL_REG 0x4 | |
| 20 | +#define USB_PHY_PLL_REG 0x8 | |
| 21 | +#define USB_PHY_TX_REG 0xc | |
| 22 | + | |
| 23 | +#define FBDIV_SHIFT 4 | |
| 24 | + | |
| 25 | +#define ICP_SHIFT 12 | |
| 26 | +#define ICP_15 2 | |
| 27 | +#define ICP_20 3 | |
| 28 | +#define ICP_25 4 | |
| 29 | + | |
| 30 | +#define KVCO_SHIFT 15 | |
| 31 | + | |
| 32 | +#define PLLCALI12_SHIFT 25 | |
| 33 | +#define CALI12_VDD 0 | |
| 34 | +#define CALI12_09 1 | |
| 35 | +#define CALI12_10 2 | |
| 36 | +#define CALI12_11 3 | |
| 37 | + | |
| 38 | +#define PLLVDD12_SHIFT 27 | |
| 39 | +#define VDD12_VDD 0 | |
| 40 | +#define VDD12_10 1 | |
| 41 | +#define VDD12_11 2 | |
| 42 | +#define VDD12_12 3 | |
| 43 | + | |
| 44 | +#define PLLVDD18_SHIFT 29 | |
| 45 | +#define VDD18_19 0 | |
| 46 | +#define VDD18_20 1 | |
| 47 | +#define VDD18_21 2 | |
| 48 | +#define VDD18_22 3 | |
| 49 | + | |
| 50 | + | |
| 51 | +#define PLL_READY (1 << 23) | |
| 52 | +#define VCOCAL_START (1 << 21) | |
| 53 | +#define REG_RCAL_START (1 << 12) | |
| 54 | + | |
| 55 | +struct pxa168_usb_drv_data { | |
| 56 | + struct ehci_hcd ehci; | |
| 57 | + struct clk *pxa168_usb_clk; | |
| 58 | + struct resource *usb_phy_res; | |
| 59 | + void __iomem *usb_phy_reg_base; | |
| 60 | +}; | |
| 61 | + | |
| 62 | +static int ehci_pxa168_setup(struct usb_hcd *hcd) | |
| 63 | +{ | |
| 64 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 65 | + int retval; | |
| 66 | + | |
| 67 | + ehci_reset(ehci); | |
| 68 | + retval = ehci_halt(ehci); | |
| 69 | + if (retval) | |
| 70 | + return retval; | |
| 71 | + | |
| 72 | + /* | |
| 73 | + * data structure init | |
| 74 | + */ | |
| 75 | + retval = ehci_init(hcd); | |
| 76 | + if (retval) | |
| 77 | + return retval; | |
| 78 | + | |
| 79 | + hcd->has_tt = 1; | |
| 80 | + | |
| 81 | + ehci_port_power(ehci, 0); | |
| 82 | + | |
| 83 | + return retval; | |
| 84 | +} | |
| 85 | + | |
| 86 | +static const struct hc_driver ehci_pxa168_hc_driver = { | |
| 87 | + .description = hcd_name, | |
| 88 | + .product_desc = "Marvell PXA168 EHCI", | |
| 89 | + .hcd_priv_size = sizeof(struct pxa168_usb_drv_data), | |
| 90 | + | |
| 91 | + /* | |
| 92 | + * generic hardware linkage | |
| 93 | + */ | |
| 94 | + .irq = ehci_irq, | |
| 95 | + .flags = HCD_MEMORY | HCD_USB2, | |
| 96 | + | |
| 97 | + /* | |
| 98 | + * basic lifecycle operations | |
| 99 | + */ | |
| 100 | + .reset = ehci_pxa168_setup, | |
| 101 | + .start = ehci_run, | |
| 102 | + .stop = ehci_stop, | |
| 103 | + .shutdown = ehci_shutdown, | |
| 104 | + | |
| 105 | + /* | |
| 106 | + * managing i/o requests and associated device resources | |
| 107 | + */ | |
| 108 | + .urb_enqueue = ehci_urb_enqueue, | |
| 109 | + .urb_dequeue = ehci_urb_dequeue, | |
| 110 | + .endpoint_disable = ehci_endpoint_disable, | |
| 111 | + .endpoint_reset = ehci_endpoint_reset, | |
| 112 | + | |
| 113 | + /* | |
| 114 | + * scheduling support | |
| 115 | + */ | |
| 116 | + .get_frame_number = ehci_get_frame, | |
| 117 | + | |
| 118 | + /* | |
| 119 | + * root hub support | |
| 120 | + */ | |
| 121 | + .hub_status_data = ehci_hub_status_data, | |
| 122 | + .hub_control = ehci_hub_control, | |
| 123 | + .bus_suspend = ehci_bus_suspend, | |
| 124 | + .bus_resume = ehci_bus_resume, | |
| 125 | + .relinquish_port = ehci_relinquish_port, | |
| 126 | + .port_handed_over = ehci_port_handed_over, | |
| 127 | + | |
| 128 | + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | |
| 129 | +}; | |
| 130 | + | |
| 131 | +static int pxa168_usb_phy_init(struct platform_device *pdev) | |
| 132 | +{ | |
| 133 | + struct resource *res; | |
| 134 | + void __iomem *usb_phy_reg_base; | |
| 135 | + struct pxa168_usb_pdata *pdata; | |
| 136 | + struct pxa168_usb_drv_data *drv_data; | |
| 137 | + struct usb_hcd *hcd = platform_get_drvdata(pdev); | |
| 138 | + unsigned long reg_val; | |
| 139 | + int pll_retry_cont = 10000, err = 0; | |
| 140 | + | |
| 141 | + drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; | |
| 142 | + pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data; | |
| 143 | + | |
| 144 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
| 145 | + if (!res) { | |
| 146 | + dev_err(&pdev->dev, | |
| 147 | + "Found HC with no PHY register addr. Check %s setup!\n", | |
| 148 | + dev_name(&pdev->dev)); | |
| 149 | + return -ENODEV; | |
| 150 | + } | |
| 151 | + | |
| 152 | + if (!request_mem_region(res->start, resource_size(res), | |
| 153 | + ehci_pxa168_hc_driver.description)) { | |
| 154 | + dev_dbg(&pdev->dev, "controller already in use\n"); | |
| 155 | + return -EBUSY; | |
| 156 | + } | |
| 157 | + | |
| 158 | + usb_phy_reg_base = ioremap(res->start, resource_size(res)); | |
| 159 | + if (usb_phy_reg_base == NULL) { | |
| 160 | + dev_dbg(&pdev->dev, "error mapping memory\n"); | |
| 161 | + err = -EFAULT; | |
| 162 | + goto err1; | |
| 163 | + } | |
| 164 | + drv_data->usb_phy_reg_base = usb_phy_reg_base; | |
| 165 | + drv_data->usb_phy_res = res; | |
| 166 | + | |
| 167 | + /* If someone wants to init USB phy in board specific way */ | |
| 168 | + if (pdata && pdata->phy_init) | |
| 169 | + return pdata->phy_init(usb_phy_reg_base); | |
| 170 | + | |
| 171 | + /* Power up the PHY and PLL */ | |
| 172 | + writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3, | |
| 173 | + usb_phy_reg_base + USB_PHY_CTRL_REG); | |
| 174 | + | |
| 175 | + /* Configure PHY PLL */ | |
| 176 | + reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff); | |
| 177 | + reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT | | |
| 178 | + CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT | | |
| 179 | + ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb); | |
| 180 | + writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG); | |
| 181 | + | |
| 182 | + /* Make sure PHY PLL is ready */ | |
| 183 | + while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { | |
| 184 | + if (!(pll_retry_cont--)) { | |
| 185 | + dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); | |
| 186 | + err = -EIO; | |
| 187 | + goto err2; | |
| 188 | + } | |
| 189 | + } | |
| 190 | + | |
| 191 | + /* Toggle VCOCAL_START bit of U2PLL for PLL calibration */ | |
| 192 | + udelay(200); | |
| 193 | + writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START, | |
| 194 | + usb_phy_reg_base + USB_PHY_PLL_REG); | |
| 195 | + udelay(40); | |
| 196 | + writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START, | |
| 197 | + usb_phy_reg_base + USB_PHY_PLL_REG); | |
| 198 | + | |
| 199 | + /* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */ | |
| 200 | + udelay(400); | |
| 201 | + writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START, | |
| 202 | + usb_phy_reg_base + USB_PHY_TX_REG); | |
| 203 | + udelay(40); | |
| 204 | + writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START, | |
| 205 | + usb_phy_reg_base + USB_PHY_TX_REG); | |
| 206 | + | |
| 207 | + /* Make sure PHY PLL is ready again */ | |
| 208 | + pll_retry_cont = 0; | |
| 209 | + while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { | |
| 210 | + if (!(pll_retry_cont--)) { | |
| 211 | + dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); | |
| 212 | + err = -EIO; | |
| 213 | + goto err2; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + | |
| 217 | + return 0; | |
| 218 | +err2: | |
| 219 | + iounmap(usb_phy_reg_base); | |
| 220 | +err1: | |
| 221 | + release_mem_region(res->start, resource_size(res)); | |
| 222 | + return err; | |
| 223 | +} | |
| 224 | + | |
| 225 | +static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) | |
| 226 | +{ | |
| 227 | + struct resource *res; | |
| 228 | + struct usb_hcd *hcd; | |
| 229 | + struct ehci_hcd *ehci; | |
| 230 | + struct pxa168_usb_drv_data *drv_data; | |
| 231 | + void __iomem *regs; | |
| 232 | + int irq, err = 0; | |
| 233 | + | |
| 234 | + if (usb_disabled()) | |
| 235 | + return -ENODEV; | |
| 236 | + | |
| 237 | + pr_debug("Initializing pxa168-SoC USB Host Controller\n"); | |
| 238 | + | |
| 239 | + irq = platform_get_irq(pdev, 0); | |
| 240 | + if (irq <= 0) { | |
| 241 | + dev_err(&pdev->dev, | |
| 242 | + "Found HC with no IRQ. Check %s setup!\n", | |
| 243 | + dev_name(&pdev->dev)); | |
| 244 | + err = -ENODEV; | |
| 245 | + goto err1; | |
| 246 | + } | |
| 247 | + | |
| 248 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 249 | + if (!res) { | |
| 250 | + dev_err(&pdev->dev, | |
| 251 | + "Found HC with no register addr. Check %s setup!\n", | |
| 252 | + dev_name(&pdev->dev)); | |
| 253 | + err = -ENODEV; | |
| 254 | + goto err1; | |
| 255 | + } | |
| 256 | + | |
| 257 | + if (!request_mem_region(res->start, resource_size(res), | |
| 258 | + ehci_pxa168_hc_driver.description)) { | |
| 259 | + dev_dbg(&pdev->dev, "controller already in use\n"); | |
| 260 | + err = -EBUSY; | |
| 261 | + goto err1; | |
| 262 | + } | |
| 263 | + | |
| 264 | + regs = ioremap(res->start, resource_size(res)); | |
| 265 | + if (regs == NULL) { | |
| 266 | + dev_dbg(&pdev->dev, "error mapping memory\n"); | |
| 267 | + err = -EFAULT; | |
| 268 | + goto err2; | |
| 269 | + } | |
| 270 | + | |
| 271 | + hcd = usb_create_hcd(&ehci_pxa168_hc_driver, | |
| 272 | + &pdev->dev, dev_name(&pdev->dev)); | |
| 273 | + if (!hcd) { | |
| 274 | + err = -ENOMEM; | |
| 275 | + goto err3; | |
| 276 | + } | |
| 277 | + | |
| 278 | + drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; | |
| 279 | + | |
| 280 | + /* Enable USB clock */ | |
| 281 | + drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK"); | |
| 282 | + if (IS_ERR(drv_data->pxa168_usb_clk)) { | |
| 283 | + dev_err(&pdev->dev, "Couldn't get USB clock\n"); | |
| 284 | + err = PTR_ERR(drv_data->pxa168_usb_clk); | |
| 285 | + goto err4; | |
| 286 | + } | |
| 287 | + clk_enable(drv_data->pxa168_usb_clk); | |
| 288 | + | |
| 289 | + err = pxa168_usb_phy_init(pdev); | |
| 290 | + if (err) { | |
| 291 | + dev_err(&pdev->dev, "USB PHY initialization failed\n"); | |
| 292 | + goto err5; | |
| 293 | + } | |
| 294 | + | |
| 295 | + hcd->rsrc_start = res->start; | |
| 296 | + hcd->rsrc_len = resource_size(res); | |
| 297 | + hcd->regs = regs; | |
| 298 | + | |
| 299 | + ehci = hcd_to_ehci(hcd); | |
| 300 | + ehci->caps = hcd->regs + 0x100; | |
| 301 | + ehci->regs = hcd->regs + 0x100 + | |
| 302 | + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 303 | + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 304 | + hcd->has_tt = 1; | |
| 305 | + ehci->sbrn = 0x20; | |
| 306 | + | |
| 307 | + err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); | |
| 308 | + if (err) | |
| 309 | + goto err5; | |
| 310 | + | |
| 311 | + return 0; | |
| 312 | + | |
| 313 | +err5: | |
| 314 | + clk_disable(drv_data->pxa168_usb_clk); | |
| 315 | + clk_put(drv_data->pxa168_usb_clk); | |
| 316 | +err4: | |
| 317 | + usb_put_hcd(hcd); | |
| 318 | +err3: | |
| 319 | + iounmap(regs); | |
| 320 | +err2: | |
| 321 | + release_mem_region(res->start, resource_size(res)); | |
| 322 | +err1: | |
| 323 | + dev_err(&pdev->dev, "init %s fail, %d\n", | |
| 324 | + dev_name(&pdev->dev), err); | |
| 325 | + | |
| 326 | + return err; | |
| 327 | +} | |
| 328 | + | |
| 329 | +static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev) | |
| 330 | +{ | |
| 331 | + struct usb_hcd *hcd = platform_get_drvdata(pdev); | |
| 332 | + struct pxa168_usb_drv_data *drv_data = | |
| 333 | + (struct pxa168_usb_drv_data *)hcd->hcd_priv; | |
| 334 | + | |
| 335 | + usb_remove_hcd(hcd); | |
| 336 | + | |
| 337 | + /* Power down PHY & PLL */ | |
| 338 | + writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3), | |
| 339 | + drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG); | |
| 340 | + | |
| 341 | + clk_disable(drv_data->pxa168_usb_clk); | |
| 342 | + clk_put(drv_data->pxa168_usb_clk); | |
| 343 | + | |
| 344 | + iounmap(hcd->regs); | |
| 345 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 346 | + | |
| 347 | + iounmap(drv_data->usb_phy_reg_base); | |
| 348 | + release_mem_region(drv_data->usb_phy_res->start, | |
| 349 | + resource_size(drv_data->usb_phy_res)); | |
| 350 | + | |
| 351 | + usb_put_hcd(hcd); | |
| 352 | + | |
| 353 | + return 0; | |
| 354 | +} | |
| 355 | + | |
| 356 | +MODULE_ALIAS("platform:pxa168-ehci"); | |
| 357 | + | |
| 358 | +static struct platform_driver ehci_pxa168_driver = { | |
| 359 | + .probe = ehci_pxa168_drv_probe, | |
| 360 | + .remove = __exit_p(ehci_pxa168_drv_remove), | |
| 361 | + .shutdown = usb_hcd_platform_shutdown, | |
| 362 | + .driver.name = "pxa168-ehci", | |
| 363 | +}; | |
| @@ -111,8 +111,6 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) · 110 unmodified lines | ||
| 111 | 111 | } |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | − /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | |
| 115 | − wmb (); | |
| 116 | 114 | hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
| 117 | 115 | } |
| 118 | 116 | |
| @@ -153,7 +151,7 @@ static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, · 34 unmodified lines | ||
| 153 | 151 | spin_lock_irqsave(&ehci->lock, flags); |
| 154 | 152 | qh->clearing_tt = 0; |
| 155 | 153 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) |
| 156 | − && HC_IS_RUNNING(hcd->state)) | |
| 154 | + && ehci->rh_state == EHCI_RH_RUNNING) | |
| 157 | 155 | qh_link_async(ehci, qh); |
| 158 | 156 | spin_unlock_irqrestore(&ehci->lock, flags); |
| 159 | 157 | } |
| @@ -425,7 +423,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) · 265 unmodified lines | ||
| 425 | 423 | |
| 426 | 424 | /* stop scanning when we reach qtds the hc is using */ |
| 427 | 425 | } else if (likely (!stopped |
| 428 | − && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { | |
| 426 | + && ehci->rh_state == EHCI_RH_RUNNING)) { | |
| 429 | 427 | break; |
| 430 | 428 | |
| 431 | 429 | /* scan the whole queue for unlinks whenever it stops */ |
| @@ -433,7 +431,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) · 1 unmodified line | ||
| 433 | 431 | stopped = 1; |
| 434 | 432 | |
| 435 | 433 | /* cancel everything if we halt, suspend, etc */ |
| 436 | − if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) | |
| 434 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 437 | 435 | last_status = -ESHUTDOWN; |
| 438 | 436 | |
| 439 | 437 | /* this qtd is active; skip it unless a previous qtd |
| @@ -724,7 +722,8 @@ qh_urb_transaction ( · 284 unmodified lines | ||
| 724 | 722 | |
| 725 | 723 | /* |
| 726 | 724 | * control requests may need a terminating data "status" ack; |
| 727 | − * bulk ones may need a terminating short packet (zero length). | |
| 725 | + * other OUT ones may need a terminating short packet | |
| 726 | + * (zero length). | |
| 728 | 727 | */ |
| 729 | 728 | if (likely (urb->transfer_buffer_length != 0)) { |
| 730 | 729 | int one_more = 0; |
| @@ -733,7 +732,7 @@ qh_urb_transaction ( · 2 unmodified lines | ||
| 733 | 732 | one_more = 1; |
| 734 | 733 | token ^= 0x0100; /* "in" <--> "out" */ |
| 735 | 734 | token |= QTD_TOGGLE; /* force DATA1 */ |
| 736 | − } else if (usb_pipebulk (urb->pipe) | |
| 735 | + } else if (usb_pipeout(urb->pipe) | |
| 737 | 736 | && (urb->transfer_flags & URB_ZERO_PACKET) |
| 738 | 737 | && !(urb->transfer_buffer_length % maxpacket)) { |
| 739 | 738 | one_more = 1; |
| @@ -977,9 +976,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) · 237 unmodified lines | ||
| 977 | 976 | /* in case a clear of CMD_ASE didn't take yet */ |
| 978 | 977 | (void)handshake(ehci, &ehci->regs->status, |
| 979 | 978 | STS_ASS, 0, 150); |
| 980 | − cmd |= CMD_ASE | CMD_RUN; | |
| 979 | + cmd |= CMD_ASE; | |
| 981 | 980 | ehci_writel(ehci, cmd, &ehci->regs->command); |
| 982 | − ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | |
| 983 | 981 | /* posted write need not be known to HC yet ... */ |
| 984 | 982 | } |
| 985 | 983 | } |
| @@ -1058,7 +1056,7 @@ static struct ehci_qh *qh_append_tds ( · 72 unmodified lines | ||
| 1058 | 1056 | */ |
| 1059 | 1057 | token = qtd->hw_token; |
| 1060 | 1058 | qtd->hw_token = HALT_BIT(ehci); |
| 1061 | − wmb (); | |
| 1059 | + | |
| 1062 | 1060 | dummy = qh->dummy; |
| 1063 | 1061 | |
| 1064 | 1062 | dma = dummy->qtd_dma; |
| @@ -1168,14 +1166,13 @@ static void end_unlink_async (struct ehci_hcd *ehci) · 103 unmodified lines | ||
| 1168 | 1166 | |
| 1169 | 1167 | qh_completions (ehci, qh); |
| 1170 | 1168 | |
| 1171 | − if (!list_empty (&qh->qtd_list) | |
| 1172 | − && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | |
| 1169 | + if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 1173 | 1170 | qh_link_async (ehci, qh); |
| 1174 | − else { | |
| 1171 | + } else { | |
| 1175 | 1172 | /* it's not free to turn the async schedule on/off; leave it |
| 1176 | 1173 | * active but idle for a while once it empties. |
| 1177 | 1174 | */ |
| 1178 | − if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) | |
| 1175 | + if (ehci->rh_state == EHCI_RH_RUNNING | |
| 1179 | 1176 | && ehci->async->qh_next.qh == NULL) |
| 1180 | 1177 | timer_action (ehci, TIMER_ASYNC_OFF); |
| 1181 | 1178 | } |
| @@ -1211,7 +1208,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) · 29 unmodified lines | ||
| 1211 | 1208 | /* stop async schedule right now? */ |
| 1212 | 1209 | if (unlikely (qh == ehci->async)) { |
| 1213 | 1210 | /* can't get here without STS_ASS set */ |
| 1214 | − if (ehci_to_hcd(ehci)->state != HC_STATE_HALT | |
| 1211 | + if (ehci->rh_state != EHCI_RH_HALTED | |
| 1215 | 1212 | && !ehci->reclaim) { |
| 1216 | 1213 | /* ... and CMD_IAAD clear */ |
| 1217 | 1214 | ehci_writel(ehci, cmd & ~CMD_ASE, |
| @@ -1237,7 +1234,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) · 19 unmodified lines | ||
| 1237 | 1234 | wmb (); |
| 1238 | 1235 | |
| 1239 | 1236 | /* If the controller isn't running, we don't have to wait for it */ |
| 1240 | − if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { | |
| 1237 | + if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) { | |
| 1241 | 1238 | /* if (unlikely (qh->reclaim != 0)) |
| 1242 | 1239 | * this will recurse, probably not much |
| 1243 | 1240 | */ |
| @@ -1260,7 +1257,7 @@ static void scan_async (struct ehci_hcd *ehci) · 16 unmodified lines | ||
| 1260 | 1257 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; |
| 1261 | 1258 | |
| 1262 | 1259 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); |
| 1263 | − stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); | |
| 1260 | + stopped = (ehci->rh_state != EHCI_RH_RUNNING); | |
| 1264 | 1261 | |
| 1265 | 1262 | ehci->qh_scan_next = ehci->async->qh_next.qh; |
| 1266 | 1263 | while (ehci->qh_scan_next) { |
| @@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 135 unmodified lines | ||
| 136 | 136 | /* cache this readonly data; minimize chip reads */ |
| 137 | 137 | ehci->hcs_params = readl(&ehci->caps->hcs_params); |
| 138 | 138 | |
| 139 | − err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 139 | + err = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 140 | 140 | if (err) { |
| 141 | 141 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
| 142 | 142 | goto fail; |
| @@ -270,7 +270,7 @@ static int s5p_ehci_resume(struct device *dev) · 127 unmodified lines | ||
| 270 | 270 | /* here we "know" root ports should always stay powered */ |
| 271 | 271 | ehci_port_power(ehci, 1); |
| 272 | 272 | |
| 273 | − hcd->state = HC_STATE_SUSPENDED; | |
| 273 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 274 | 274 | |
| 275 | 275 | return 0; |
| 276 | 276 | } |
| @@ -36,6 +36,27 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | static int ehci_get_frame (struct usb_hcd *hcd); |
| 38 | 38 | |
| 39 | +#ifdef CONFIG_PCI | |
| 40 | + | |
| 41 | +static unsigned ehci_read_frame_index(struct ehci_hcd *ehci) | |
| 42 | +{ | |
| 43 | + unsigned uf; | |
| 44 | + | |
| 45 | + /* | |
| 46 | + * The MosChip MCS9990 controller updates its microframe counter | |
| 47 | + * a little before the frame counter, and occasionally we will read | |
| 48 | + * the invalid intermediate value. Avoid problems by checking the | |
| 49 | + * microframe number (the low-order 3 bits); if they are 0 then | |
| 50 | + * re-read the register to get the correct value. | |
| 51 | + */ | |
| 52 | + uf = ehci_readl(ehci, &ehci->regs->frame_index); | |
| 53 | + if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0))) | |
| 54 | + uf = ehci_readl(ehci, &ehci->regs->frame_index); | |
| 55 | + return uf; | |
| 56 | +} | |
| 57 | + | |
| 58 | +#endif | |
| 59 | + | |
| 39 | 60 | /*-------------------------------------------------------------------------*/ |
| 40 | 61 | |
| 41 | 62 | /* |
| @@ -479,10 +500,9 @@ static int enable_periodic (struct ehci_hcd *ehci) · 437 unmodified lines | ||
| 479 | 500 | cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; |
| 480 | 501 | ehci_writel(ehci, cmd, &ehci->regs->command); |
| 481 | 502 | /* posted write ... PSS happens later */ |
| 482 | − ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | |
| 483 | 503 | |
| 484 | 504 | /* make sure ehci_work scans these */ |
| 485 | − ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) | |
| 505 | + ehci->next_uframe = ehci_read_frame_index(ehci) | |
| 486 | 506 | % (ehci->periodic_size << 3); |
| 487 | 507 | if (unlikely(ehci->broken_periodic)) |
| 488 | 508 | ehci->last_periodic_enable = ktime_get_real(); |
| @@ -677,7 +697,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) · 188 unmodified lines | ||
| 677 | 697 | |
| 678 | 698 | /* reschedule QH iff another request is queued */ |
| 679 | 699 | if (!list_empty(&qh->qtd_list) && |
| 680 | − HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | |
| 700 | + ehci->rh_state == EHCI_RH_RUNNING) { | |
| 681 | 701 | rc = qh_schedule(ehci, qh); |
| 682 | 702 | |
| 683 | 703 | /* An error here likely indicates handshake failure |
| @@ -1409,7 +1429,7 @@ iso_stream_schedule ( · 725 unmodified lines | ||
| 1409 | 1429 | goto fail; |
| 1410 | 1430 | } |
| 1411 | 1431 | |
| 1412 | − now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1); | |
| 1432 | + now = ehci_read_frame_index(ehci) & (mod - 1); | |
| 1413 | 1433 | |
| 1414 | 1434 | /* Typical case: reuse current schedule, stream is still active. |
| 1415 | 1435 | * Hopefully there are no gaps from the host falling behind |
| @@ -2275,8 +2295,8 @@ scan_periodic (struct ehci_hcd *ehci) · 859 unmodified lines | ||
| 2275 | 2295 | * Touches as few pages as possible: cache-friendly. |
| 2276 | 2296 | */ |
| 2277 | 2297 | now_uframe = ehci->next_uframe; |
| 2278 | − if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | |
| 2279 | − clock = ehci_readl(ehci, &ehci->regs->frame_index); | |
| 2298 | + if (ehci->rh_state == EHCI_RH_RUNNING) { | |
| 2299 | + clock = ehci_read_frame_index(ehci); | |
| 2280 | 2300 | clock_frame = (clock >> 3) & (ehci->periodic_size - 1); |
| 2281 | 2301 | } else { |
| 2282 | 2302 | clock = now_uframe + mod - 1; |
| @@ -2310,7 +2330,7 @@ restart: · 27 unmodified lines | ||
| 2310 | 2330 | union ehci_shadow temp; |
| 2311 | 2331 | int live; |
| 2312 | 2332 | |
| 2313 | − live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state); | |
| 2333 | + live = (ehci->rh_state == EHCI_RH_RUNNING); | |
| 2314 | 2334 | switch (hc32_to_cpu(ehci, type)) { |
| 2315 | 2335 | case Q_TYPE_QH: |
| 2316 | 2336 | /* handle any completions */ |
| @@ -2435,7 +2455,7 @@ restart: · 118 unmodified lines | ||
| 2435 | 2455 | * We can't advance our scan without collecting the ISO |
| 2436 | 2456 | * transfers that are still pending in this frame. |
| 2437 | 2457 | */ |
| 2438 | − if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | |
| 2458 | + if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 2439 | 2459 | ehci->next_uframe = now_uframe; |
| 2440 | 2460 | break; |
| 2441 | 2461 | } |
| @@ -2451,12 +2471,11 @@ restart: · 9 unmodified lines | ||
| 2451 | 2471 | if (now_uframe == clock) { |
| 2452 | 2472 | unsigned now; |
| 2453 | 2473 | |
| 2454 | − if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) | |
| 2474 | + if (ehci->rh_state != EHCI_RH_RUNNING | |
| 2455 | 2475 | || ehci->periodic_sched == 0) |
| 2456 | 2476 | break; |
| 2457 | 2477 | ehci->next_uframe = now_uframe; |
| 2458 | − now = ehci_readl(ehci, &ehci->regs->frame_index) & | |
| 2459 | − (mod - 1); | |
| 2478 | + now = ehci_read_frame_index(ehci) & (mod - 1); | |
| 2460 | 2479 | if (now_uframe == now) |
| 2461 | 2480 | break; |
| 2462 | 2481 | |
| @@ -168,7 +168,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) · 167 unmodified lines | ||
| 168 | 168 | clk_enable(priv->fclk); |
| 169 | 169 | clk_enable(priv->iclk); |
| 170 | 170 | |
| 171 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 171 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 172 | 172 | if (ret != 0) { |
| 173 | 173 | dev_err(&pdev->dev, "Failed to add hcd"); |
| 174 | 174 | goto fail_add_hcd; |
| @@ -154,7 +154,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) · 153 unmodified lines | ||
| 154 | 154 | ehci->clk = usbh_clk; |
| 155 | 155 | |
| 156 | 156 | spear_start_ehci(ehci); |
| 157 | − retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); | |
| 157 | + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 158 | 158 | if (retval) |
| 159 | 159 | goto fail_add_hcd; |
| 160 | 160 | |
| @@ -674,7 +674,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) · 673 unmodified lines | ||
| 674 | 674 | } |
| 675 | 675 | #endif |
| 676 | 676 | |
| 677 | − err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 677 | + err = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 678 | 678 | if (err) { |
| 679 | 679 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
| 680 | 680 | goto fail; |
| @@ -133,7 +133,7 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) · 132 unmodified lines | ||
| 133 | 133 | ehci_port_power(ehci, 1); |
| 134 | 134 | |
| 135 | 135 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
| 136 | − IRQF_DISABLED | IRQF_SHARED); | |
| 136 | + IRQF_SHARED); | |
| 137 | 137 | if (ret == 0) { |
| 138 | 138 | platform_set_drvdata(pdev, hcd); |
| 139 | 139 | return ret; |
| @@ -0,0 +1,161 @@ | ||
| 1 | +/* | |
| 2 | + * EHCI HCD for Netlogic XLS processors. | |
| 3 | + * | |
| 4 | + * (C) Copyright 2011 Netlogic Microsystems Inc. | |
| 5 | + * | |
| 6 | + * Based on various ehci-*.c drivers | |
| 7 | + * | |
| 8 | + * This file is subject to the terms and conditions of the GNU General Public | |
| 9 | + * License. See the file COPYING in the main directory of this archive for | |
| 10 | + * more details. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/platform_device.h> | |
| 14 | + | |
| 15 | +static int ehci_xls_setup(struct usb_hcd *hcd) | |
| 16 | +{ | |
| 17 | + int retval; | |
| 18 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 19 | + | |
| 20 | + ehci->caps = hcd->regs; | |
| 21 | + ehci->regs = hcd->regs + | |
| 22 | + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 23 | + dbg_hcs_params(ehci, "reset"); | |
| 24 | + dbg_hcc_params(ehci, "reset"); | |
| 25 | + | |
| 26 | + /* cache this readonly data; minimize chip reads */ | |
| 27 | + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 28 | + | |
| 29 | + retval = ehci_halt(ehci); | |
| 30 | + if (retval) | |
| 31 | + return retval; | |
| 32 | + | |
| 33 | + /* data structure init */ | |
| 34 | + retval = ehci_init(hcd); | |
| 35 | + if (retval) | |
| 36 | + return retval; | |
| 37 | + | |
| 38 | + ehci_reset(ehci); | |
| 39 | + | |
| 40 | + return retval; | |
| 41 | +} | |
| 42 | + | |
| 43 | +int ehci_xls_probe_internal(const struct hc_driver *driver, | |
| 44 | + struct platform_device *pdev) | |
| 45 | +{ | |
| 46 | + struct usb_hcd *hcd; | |
| 47 | + struct resource *res; | |
| 48 | + int retval, irq; | |
| 49 | + | |
| 50 | + /* Get our IRQ from an earlier registered Platform Resource */ | |
| 51 | + irq = platform_get_irq(pdev, 0); | |
| 52 | + if (irq < 0) { | |
| 53 | + dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", | |
| 54 | + dev_name(&pdev->dev)); | |
| 55 | + return -ENODEV; | |
| 56 | + } | |
| 57 | + | |
| 58 | + /* Get our Memory Handle */ | |
| 59 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 60 | + if (!res) { | |
| 61 | + dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n", | |
| 62 | + dev_name(&pdev->dev)); | |
| 63 | + return -ENODEV; | |
| 64 | + } | |
| 65 | + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | |
| 66 | + if (!hcd) { | |
| 67 | + retval = -ENOMEM; | |
| 68 | + goto err1; | |
| 69 | + } | |
| 70 | + | |
| 71 | + hcd->rsrc_start = res->start; | |
| 72 | + hcd->rsrc_len = res->end - res->start + 1; | |
| 73 | + | |
| 74 | + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | |
| 75 | + driver->description)) { | |
| 76 | + dev_dbg(&pdev->dev, "controller already in use\n"); | |
| 77 | + retval = -EBUSY; | |
| 78 | + goto err2; | |
| 79 | + } | |
| 80 | + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | |
| 81 | + | |
| 82 | + if (hcd->regs == NULL) { | |
| 83 | + dev_dbg(&pdev->dev, "error mapping memory\n"); | |
| 84 | + retval = -EFAULT; | |
| 85 | + goto err3; | |
| 86 | + } | |
| 87 | + | |
| 88 | + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 89 | + if (retval != 0) | |
| 90 | + goto err4; | |
| 91 | + return retval; | |
| 92 | + | |
| 93 | +err4: | |
| 94 | + iounmap(hcd->regs); | |
| 95 | +err3: | |
| 96 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 97 | +err2: | |
| 98 | + usb_put_hcd(hcd); | |
| 99 | +err1: | |
| 100 | + dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), | |
| 101 | + retval); | |
| 102 | + return retval; | |
| 103 | +} | |
| 104 | + | |
| 105 | +static struct hc_driver ehci_xls_hc_driver = { | |
| 106 | + .description = hcd_name, | |
| 107 | + .product_desc = "XLS EHCI Host Controller", | |
| 108 | + .hcd_priv_size = sizeof(struct ehci_hcd), | |
| 109 | + .irq = ehci_irq, | |
| 110 | + .flags = HCD_USB2 | HCD_MEMORY, | |
| 111 | + .reset = ehci_xls_setup, | |
| 112 | + .start = ehci_run, | |
| 113 | + .stop = ehci_stop, | |
| 114 | + .shutdown = ehci_shutdown, | |
| 115 | + | |
| 116 | + .urb_enqueue = ehci_urb_enqueue, | |
| 117 | + .urb_dequeue = ehci_urb_dequeue, | |
| 118 | + .endpoint_disable = ehci_endpoint_disable, | |
| 119 | + .endpoint_reset = ehci_endpoint_reset, | |
| 120 | + | |
| 121 | + .get_frame_number = ehci_get_frame, | |
| 122 | + | |
| 123 | + .hub_status_data = ehci_hub_status_data, | |
| 124 | + .hub_control = ehci_hub_control, | |
| 125 | + .bus_suspend = ehci_bus_suspend, | |
| 126 | + .bus_resume = ehci_bus_resume, | |
| 127 | + .relinquish_port = ehci_relinquish_port, | |
| 128 | + .port_handed_over = ehci_port_handed_over, | |
| 129 | + | |
| 130 | + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | |
| 131 | +}; | |
| 132 | + | |
| 133 | +static int ehci_xls_probe(struct platform_device *pdev) | |
| 134 | +{ | |
| 135 | + if (usb_disabled()) | |
| 136 | + return -ENODEV; | |
| 137 | + | |
| 138 | + return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev); | |
| 139 | +} | |
| 140 | + | |
| 141 | +static int ehci_xls_remove(struct platform_device *pdev) | |
| 142 | +{ | |
| 143 | + struct usb_hcd *hcd = platform_get_drvdata(pdev); | |
| 144 | + | |
| 145 | + usb_remove_hcd(hcd); | |
| 146 | + iounmap(hcd->regs); | |
| 147 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 148 | + usb_put_hcd(hcd); | |
| 149 | + return 0; | |
| 150 | +} | |
| 151 | + | |
| 152 | +MODULE_ALIAS("ehci-xls"); | |
| 153 | + | |
| 154 | +static struct platform_driver ehci_xls_driver = { | |
| 155 | + .probe = ehci_xls_probe, | |
| 156 | + .remove = ehci_xls_remove, | |
| 157 | + .shutdown = usb_hcd_platform_shutdown, | |
| 158 | + .driver = { | |
| 159 | + .name = "ehci-xls", | |
| 160 | + }, | |
| 161 | +}; | |
| @@ -62,6 +62,12 @@ struct ehci_stats { · 61 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ |
| 64 | 64 | |
| 65 | +enum ehci_rh_state { | |
| 66 | + EHCI_RH_HALTED, | |
| 67 | + EHCI_RH_SUSPENDED, | |
| 68 | + EHCI_RH_RUNNING | |
| 69 | +}; | |
| 70 | + | |
| 65 | 71 | struct ehci_hcd { /* one per controller */ |
| 66 | 72 | /* glue to PCI and HCD framework */ |
| 67 | 73 | struct ehci_caps __iomem *caps; |
| @@ -70,6 +76,7 @@ struct ehci_hcd { /* one per controller */ · 2 unmodified lines | ||
| 70 | 76 | |
| 71 | 77 | __u32 hcs_params; /* cached register copy */ |
| 72 | 78 | spinlock_t lock; |
| 79 | + enum ehci_rh_state rh_state; | |
| 73 | 80 | |
| 74 | 81 | /* async schedule support */ |
| 75 | 82 | struct ehci_qh *async; |
| @@ -139,6 +146,7 @@ struct ehci_hcd { /* one per controller */ · 63 unmodified lines | ||
| 139 | 146 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ |
| 140 | 147 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ |
| 141 | 148 | unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ |
| 149 | + unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ | |
| 142 | 150 | |
| 143 | 151 | /* required for usb32 quirk */ |
| 144 | 152 | #define OHCI_CTRL_HCFS (3 << 6) |
| @@ -740,6 +748,22 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) · 595 unmodified lines | ||
| 740 | 748 | |
| 741 | 749 | /*-------------------------------------------------------------------------*/ |
| 742 | 750 | |
| 751 | +#ifdef CONFIG_PCI | |
| 752 | + | |
| 753 | +/* For working around the MosChip frame-index-register bug */ | |
| 754 | +static unsigned ehci_read_frame_index(struct ehci_hcd *ehci); | |
| 755 | + | |
| 756 | +#else | |
| 757 | + | |
| 758 | +static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) | |
| 759 | +{ | |
| 760 | + return ehci_readl(ehci, &ehci->regs->frame_index); | |
| 761 | +} | |
| 762 | + | |
| 763 | +#endif | |
| 764 | + | |
| 765 | +/*-------------------------------------------------------------------------*/ | |
| 766 | + | |
| 743 | 767 | #ifndef DEBUG |
| 744 | 768 | #define STUB_DEBUG_FILES |
| 745 | 769 | #endif /* DEBUG */ |
| @@ -621,12 +621,15 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev) · 620 unmodified lines | ||
| 621 | 621 | goto err_pram; |
| 622 | 622 | } |
| 623 | 623 | |
| 624 | − pram_addr = cpm_muram_alloc_fixed(iprop[2], FHCI_PRAM_SIZE); | |
| 624 | + pram_addr = cpm_muram_alloc(FHCI_PRAM_SIZE, 64); | |
| 625 | 625 | if (IS_ERR_VALUE(pram_addr)) { |
| 626 | 626 | dev_err(dev, "failed to allocate usb pram\n"); |
| 627 | 627 | ret = -ENOMEM; |
| 628 | 628 | goto err_pram; |
| 629 | 629 | } |
| 630 | + | |
| 631 | + qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, QE_CR_SUBBLOCK_USB, | |
| 632 | + QE_CR_PROTOCOL_UNSPECIFIED, pram_addr); | |
| 630 | 633 | fhci->pram = cpm_muram_addr(pram_addr); |
| 631 | 634 | |
| 632 | 635 | /* GPIOs and pins */ |
| @@ -686,7 +689,7 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev) · 53 unmodified lines | ||
| 686 | 689 | } |
| 687 | 690 | |
| 688 | 691 | ret = request_irq(fhci->timer->irq, fhci_frame_limit_timer_irq, |
| 689 | − IRQF_DISABLED, "qe timer (usb)", hcd); | |
| 692 | + 0, "qe timer (usb)", hcd); | |
| 690 | 693 | if (ret) { |
| 691 | 694 | dev_err(dev, "failed to request timer irq"); |
| 692 | 695 | goto err_timer_irq; |
| @@ -745,7 +748,7 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev) · 52 unmodified lines | ||
| 745 | 748 | out_be16(&fhci->regs->usb_event, 0xffff); |
| 746 | 749 | out_be16(&fhci->regs->usb_mask, 0); |
| 747 | 750 | |
| 748 | − ret = usb_add_hcd(hcd, usb_irq, IRQF_DISABLED); | |
| 751 | + ret = usb_add_hcd(hcd, usb_irq, 0); | |
| 749 | 752 | if (ret < 0) |
| 750 | 753 | goto err_add_hcd; |
| 751 | 754 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Freescale QUICC Engine USB Host Controller Driver |
| 3 | 3 | * |
| 4 | − * Copyright (c) Freescale Semicondutor, Inc. 2006. | |
| 4 | + * Copyright (c) Freescale Semicondutor, Inc. 2006, 2011. | |
| 5 | 5 | * Shlomi Gridish <gridish@freescale.com> |
| 6 | 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> |
| 7 | 7 | * Copyright (c) Logic Product Development, Inc. 2007 |
| @@ -810,9 +810,11 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) · 802 unmodified lines | ||
| 810 | 810 | ed->dev_addr = usb_pipedevice(urb->pipe); |
| 811 | 811 | ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe, |
| 812 | 812 | usb_pipeout(urb->pipe)); |
| 813 | + /* setup stage */ | |
| 813 | 814 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, |
| 814 | 815 | USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); |
| 815 | 816 | |
| 817 | + /* data stage */ | |
| 816 | 818 | if (data_len > 0) { |
| 817 | 819 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, |
| 818 | 820 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : |
| @@ -820,9 +822,18 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) · 1 unmodified line | ||
| 820 | 822 | USB_TD_TOGGLE_DATA1, data, data_len, 0, 0, |
| 821 | 823 | true); |
| 822 | 824 | } |
| 823 | − td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | |
| 824 | − usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT, | |
| 825 | − USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); | |
| 825 | + | |
| 826 | + /* status stage */ | |
| 827 | + if (data_len > 0) | |
| 828 | + td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | |
| 829 | + (usb_pipeout(urb->pipe) ? FHCI_TA_IN : | |
| 830 | + FHCI_TA_OUT), | |
| 831 | + USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); | |
| 832 | + else | |
| 833 | + td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | |
| 834 | + FHCI_TA_IN, | |
| 835 | + USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); | |
| 836 | + | |
| 826 | 837 | urb_state = US_CTRL_SETUP; |
| 827 | 838 | break; |
| 828 | 839 | case FHCI_TF_ISO: |
| @@ -1891,7 +1891,7 @@ static int imx21_probe(struct platform_device *pdev) · 1890 unmodified lines | ||
| 1891 | 1891 | dev_info(imx21->dev, "Hardware HC revision: 0x%02X\n", |
| 1892 | 1892 | (readl(imx21->regs + USBOTG_HWMODE) >> 16) & 0xFF); |
| 1893 | 1893 | |
| 1894 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 1894 | + ret = usb_add_hcd(hcd, irq, 0); | |
| 1895 | 1895 | if (ret != 0) { |
| 1896 | 1896 | dev_err(imx21->dev, "usb_add_hcd() returned %d\n", ret); |
| 1897 | 1897 | goto failed_add_hcd; |
| @@ -1639,7 +1639,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev) · 1638 unmodified lines | ||
| 1639 | 1639 | goto err6; |
| 1640 | 1640 | } |
| 1641 | 1641 | |
| 1642 | − ret = usb_add_hcd(hcd, irq, irqflags | IRQF_DISABLED); | |
| 1642 | + ret = usb_add_hcd(hcd, irq, irqflags); | |
| 1643 | 1643 | if (ret) |
| 1644 | 1644 | goto err6; |
| 1645 | 1645 | |
| @@ -2358,7 +2358,7 @@ static int isp1362_hc_reset(struct usb_hcd *hcd) · 2357 unmodified lines | ||
| 2358 | 2358 | unsigned long flags; |
| 2359 | 2359 | int clkrdy = 0; |
| 2360 | 2360 | |
| 2361 | − pr_info("%s:\n", __func__); | |
| 2361 | + pr_debug("%s:\n", __func__); | |
| 2362 | 2362 | |
| 2363 | 2363 | if (isp1362_hcd->board && isp1362_hcd->board->reset) { |
| 2364 | 2364 | isp1362_hcd->board->reset(hcd->self.controller, 1); |
| @@ -2395,7 +2395,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd) · 30 unmodified lines | ||
| 2395 | 2395 | unsigned long flags; |
| 2396 | 2396 | u32 tmp; |
| 2397 | 2397 | |
| 2398 | − pr_info("%s:\n", __func__); | |
| 2398 | + pr_debug("%s:\n", __func__); | |
| 2399 | 2399 | |
| 2400 | 2400 | del_timer_sync(&hcd->rh_timer); |
| 2401 | 2401 | |
| @@ -2523,7 +2523,7 @@ static int isp1362_hc_start(struct usb_hcd *hcd) · 121 unmodified lines | ||
| 2523 | 2523 | u16 chipid; |
| 2524 | 2524 | unsigned long flags; |
| 2525 | 2525 | |
| 2526 | − pr_info("%s:\n", __func__); | |
| 2526 | + pr_debug("%s:\n", __func__); | |
| 2527 | 2527 | |
| 2528 | 2528 | spin_lock_irqsave(&isp1362_hcd->lock, flags); |
| 2529 | 2529 | chipid = isp1362_read_reg16(isp1362_hcd, HCCHIPID); |
| @@ -2773,7 +2773,7 @@ static int __devinit isp1362_probe(struct platform_device *pdev) · 243 unmodified lines | ||
| 2773 | 2773 | if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL) |
| 2774 | 2774 | irq_flags |= IRQF_TRIGGER_LOW; |
| 2775 | 2775 | |
| 2776 | − retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_DISABLED | IRQF_SHARED); | |
| 2776 | + retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_SHARED); | |
| 2777 | 2777 | if (retval != 0) |
| 2778 | 2778 | goto err6; |
| 2779 | 2779 | pr_info("%s, irq %d\n", hcd->product_desc, irq); |
| @@ -21,8 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/uaccess.h> |
| 22 | 22 | #include <linux/io.h> |
| 23 | 23 | #include <linux/mm.h> |
| 24 | +#include <linux/timer.h> | |
| 24 | 25 | #include <asm/unaligned.h> |
| 25 | 26 | #include <asm/cacheflush.h> |
| 27 | +#include <linux/gpio.h> | |
| 26 | 28 | |
| 27 | 29 | #include "isp1760-hcd.h" |
| 28 | 30 | |
| @@ -39,7 +41,6 @@ struct isp1760_hcd { · 10 unmodified lines | ||
| 39 | 41 | int int_done_map; |
| 40 | 42 | struct memory_chunk memory_pool[BLOCKS]; |
| 41 | 43 | struct list_head controlqhs, bulkqhs, interruptqhs; |
| 42 | − int active_ptds; | |
| 43 | 44 | |
| 44 | 45 | /* periodic schedule support */ |
| 45 | 46 | #define DEFAULT_I_TDPS 1024 |
| @@ -48,6 +49,8 @@ struct isp1760_hcd { · 2 unmodified lines | ||
| 48 | 49 | unsigned long reset_done; |
| 49 | 50 | unsigned long next_statechange; |
| 50 | 51 | unsigned int devflags; |
| 52 | + | |
| 53 | + int rst_gpio; | |
| 51 | 54 | }; |
| 52 | 55 | |
| 53 | 56 | static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) |
| @@ -114,6 +117,7 @@ struct isp1760_qh { · 60 unmodified lines | ||
| 114 | 117 | u32 toggle; |
| 115 | 118 | u32 ping; |
| 116 | 119 | int slot; |
| 120 | + int tt_buffer_dirty; /* See USB2.0 spec section 11.17.5 */ | |
| 117 | 121 | }; |
| 118 | 122 | |
| 119 | 123 | struct urb_listitem { |
| @@ -432,6 +436,18 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) · 312 unmodified lines | ||
| 432 | 436 | int result; |
| 433 | 437 | u32 scratch, hwmode; |
| 434 | 438 | |
| 439 | + /* low-level chip reset */ | |
| 440 | + if (gpio_is_valid(priv->rst_gpio)) { | |
| 441 | + unsigned int rst_lvl; | |
| 442 | + | |
| 443 | + rst_lvl = (priv->devflags & | |
| 444 | + ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0; | |
| 445 | + | |
| 446 | + gpio_set_value(priv->rst_gpio, rst_lvl); | |
| 447 | + mdelay(50); | |
| 448 | + gpio_set_value(priv->rst_gpio, !rst_lvl); | |
| 449 | + } | |
| 450 | + | |
| 435 | 451 | /* Setup HW Mode Control: This assumes a level active-low interrupt */ |
| 436 | 452 | hwmode = HW_DATA_BUS_32BIT; |
| 437 | 453 | |
| @@ -489,10 +505,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) · 51 unmodified lines | ||
| 489 | 505 | 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? |
| 490 | 506 | "analog" : "digital"); |
| 491 | 507 | |
| 492 | − /* This is weird: at the first plug-in of a device there seems to be | |
| 493 | − one packet queued that never gets returned? */ | |
| 494 | − priv->active_ptds = -1; | |
| 495 | − | |
| 496 | 508 | /* ATL reset */ |
| 497 | 509 | reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET); |
| 498 | 510 | mdelay(10); |
| @@ -514,83 +526,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) · 15 unmodified lines | ||
| 514 | 526 | return priv_init(hcd); |
| 515 | 527 | } |
| 516 | 528 | |
| 517 | −static void isp1760_init_maps(struct usb_hcd *hcd) | |
| 518 | −{ | |
| 519 | − /*set last maps, for iso its only 1, else 32 tds bitmap*/ | |
| 520 | − reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000); | |
| 521 | − reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000); | |
| 522 | − reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001); | |
| 523 | − | |
| 524 | − reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff); | |
| 525 | − reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff); | |
| 526 | − reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff); | |
| 527 | − | |
| 528 | − reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, | |
| 529 | − ATL_BUF_FILL | INT_BUF_FILL); | |
| 530 | −} | |
| 531 | − | |
| 532 | −static void isp1760_enable_interrupts(struct usb_hcd *hcd) | |
| 533 | −{ | |
| 534 | − reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0); | |
| 535 | − reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff); | |
| 536 | − reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0); | |
| 537 | − reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff); | |
| 538 | − reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0); | |
| 539 | − reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff); | |
| 540 | − /* step 23 passed */ | |
| 541 | −} | |
| 542 | − | |
| 543 | −static int isp1760_run(struct usb_hcd *hcd) | |
| 544 | −{ | |
| 545 | − int retval; | |
| 546 | − u32 temp; | |
| 547 | − u32 command; | |
| 548 | − u32 chipid; | |
| 549 | − | |
| 550 | − hcd->uses_new_polling = 1; | |
| 551 | − | |
| 552 | − hcd->state = HC_STATE_RUNNING; | |
| 553 | − isp1760_enable_interrupts(hcd); | |
| 554 | − temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL); | |
| 555 | − reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN); | |
| 556 | − | |
| 557 | − command = reg_read32(hcd->regs, HC_USBCMD); | |
| 558 | − command &= ~(CMD_LRESET|CMD_RESET); | |
| 559 | − command |= CMD_RUN; | |
| 560 | − reg_write32(hcd->regs, HC_USBCMD, command); | |
| 561 | − | |
| 562 | − retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000); | |
| 563 | − if (retval) | |
| 564 | − return retval; | |
| 565 | − | |
| 566 | − /* | |
| 567 | − * XXX | |
| 568 | − * Spec says to write FLAG_CF as last config action, priv code grabs | |
| 569 | − * the semaphore while doing so. | |
| 570 | − */ | |
| 571 | − down_write(&ehci_cf_port_reset_rwsem); | |
| 572 | − reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF); | |
| 573 | − | |
| 574 | − retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000); | |
| 575 | − up_write(&ehci_cf_port_reset_rwsem); | |
| 576 | − if (retval) | |
| 577 | − return retval; | |
| 578 | − | |
| 579 | − chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG); | |
| 580 | − dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n", | |
| 581 | − chipid & 0xffff, chipid >> 16); | |
| 582 | − | |
| 583 | − /* PTD Register Init Part 2, Step 28 */ | |
| 584 | − /* enable INTs */ | |
| 585 | − isp1760_init_maps(hcd); | |
| 586 | − | |
| 587 | − /* GRR this is run-once init(), being done every time the HC starts. | |
| 588 | − * So long as they're part of class devices, we can't do it init() | |
| 589 | − * since the class device isn't created that early. | |
| 590 | − */ | |
| 591 | − return 0; | |
| 592 | −} | |
| 593 | − | |
| 594 | 529 | static u32 base_to_chip(u32 base) |
| 595 | 530 | { |
| 596 | 531 | return ((base - 0x400) >> 3); |
| @@ -813,28 +748,29 @@ static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot, · 216 unmodified lines | ||
| 813 | 748 | WARN_ON(slots[slot].qh); |
| 814 | 749 | WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC); |
| 815 | 750 | |
| 816 | − slots[slot].qtd = qtd; | |
| 817 | − slots[slot].qh = qh; | |
| 818 | − qh->slot = slot; | |
| 819 | − qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since | |
| 820 | − interrupt routine may preempt and expects this value. */ | |
| 821 | − ptd_write(hcd->regs, ptd_offset, slot, ptd); | |
| 822 | − priv->active_ptds++; | |
| 823 | − | |
| 824 | 751 | /* Make sure done map has not triggered from some unlinked transfer */ |
| 825 | 752 | if (ptd_offset == ATL_PTD_OFFSET) { |
| 826 | 753 | priv->atl_done_map |= reg_read32(hcd->regs, |
| 827 | 754 | HC_ATL_PTD_DONEMAP_REG); |
| 828 | − priv->atl_done_map &= ~(1 << qh->slot); | |
| 755 | + priv->atl_done_map &= ~(1 << slot); | |
| 756 | + } else { | |
| 757 | + priv->int_done_map |= reg_read32(hcd->regs, | |
| 758 | + HC_INT_PTD_DONEMAP_REG); | |
| 759 | + priv->int_done_map &= ~(1 << slot); | |
| 760 | + } | |
| 761 | + | |
| 762 | + qh->slot = slot; | |
| 763 | + qtd->status = QTD_XFER_STARTED; | |
| 764 | + slots[slot].timestamp = jiffies; | |
| 765 | + slots[slot].qtd = qtd; | |
| 766 | + slots[slot].qh = qh; | |
| 767 | + ptd_write(hcd->regs, ptd_offset, slot, ptd); | |
| 829 | 768 | |
| 769 | + if (ptd_offset == ATL_PTD_OFFSET) { | |
| 830 | 770 | skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); |
| 831 | 771 | skip_map &= ~(1 << qh->slot); |
| 832 | 772 | reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); |
| 833 | 773 | } else { |
| 834 | − priv->int_done_map |= reg_read32(hcd->regs, | |
| 835 | − HC_INT_PTD_DONEMAP_REG); | |
| 836 | − priv->int_done_map &= ~(1 << qh->slot); | |
| 837 | − | |
| 838 | 774 | skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); |
| 839 | 775 | skip_map &= ~(1 << qh->slot); |
| 840 | 776 | reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); |
| @@ -858,10 +794,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, · 17 unmodified lines | ||
| 858 | 794 | if (qtd->status < QTD_XFER_COMPLETE) |
| 859 | 795 | break; |
| 860 | 796 | |
| 861 | − if (list_is_last(&qtd->qtd_list, &qh->qtd_list)) | |
| 862 | − last_qtd = 1; | |
| 863 | − else | |
| 864 | − last_qtd = qtd->urb != qtd_next->urb; | |
| 797 | + last_qtd = last_qtd_of_urb(qtd, qh); | |
| 865 | 798 | |
| 866 | 799 | if ((!last_qtd) && (qtd->status == QTD_RETIRE)) |
| 867 | 800 | qtd_next->status = QTD_RETIRE; |
| @@ -902,7 +835,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, · 34 unmodified lines | ||
| 902 | 835 | urb_listitem = kmem_cache_zalloc(urb_listitem_cachep, |
| 903 | 836 | GFP_ATOMIC); |
| 904 | 837 | if (unlikely(!urb_listitem)) |
| 905 | − break; | |
| 838 | + break; /* Try again on next call */ | |
| 906 | 839 | urb_listitem->urb = qtd->urb; |
| 907 | 840 | list_add_tail(&urb_listitem->urb_list, urb_list); |
| 908 | 841 | } |
| @@ -928,6 +861,10 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) · 19 unmodified lines | ||
| 928 | 861 | return; |
| 929 | 862 | } |
| 930 | 863 | |
| 864 | + /* Make sure this endpoint's TT buffer is clean before queueing ptds */ | |
| 865 | + if (qh->tt_buffer_dirty) | |
| 866 | + return; | |
| 867 | + | |
| 931 | 868 | if (usb_pipeint(list_entry(qh->qtd_list.next, struct isp1760_qtd, |
| 932 | 869 | qtd_list)->urb->pipe)) { |
| 933 | 870 | ptd_offset = INT_PTD_OFFSET; |
| @@ -1168,11 +1105,9 @@ static int check_atl_transfer(struct usb_hcd *hcd, struct ptd *ptd, · 234 unmodified lines | ||
| 1168 | 1105 | return PTD_STATE_QTD_DONE; |
| 1169 | 1106 | } |
| 1170 | 1107 | |
| 1171 | −static irqreturn_t isp1760_irq(struct usb_hcd *hcd) | |
| 1108 | +static void handle_done_ptds(struct usb_hcd *hcd) | |
| 1172 | 1109 | { |
| 1173 | 1110 | struct isp1760_hcd *priv = hcd_to_priv(hcd); |
| 1174 | − u32 imask; | |
| 1175 | − irqreturn_t irqret = IRQ_NONE; | |
| 1176 | 1111 | struct ptd ptd; |
| 1177 | 1112 | struct isp1760_qh *qh; |
| 1178 | 1113 | int slot; |
| @@ -1181,27 +1116,14 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd) · 2 unmodified lines | ||
| 1181 | 1116 | u32 ptd_offset; |
| 1182 | 1117 | struct isp1760_qtd *qtd; |
| 1183 | 1118 | int modified; |
| 1184 | − static int last_active_ptds; | |
| 1185 | − int int_skip_map, atl_skip_map; | |
| 1186 | − | |
| 1187 | − spin_lock(&priv->lock); | |
| 1188 | − | |
| 1189 | − if (!(hcd->state & HC_STATE_RUNNING)) | |
| 1190 | − goto leave; | |
| 1191 | − | |
| 1192 | − imask = reg_read32(hcd->regs, HC_INTERRUPT_REG); | |
| 1193 | − if (unlikely(!imask)) | |
| 1194 | − goto leave; | |
| 1195 | − reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */ | |
| 1119 | + int skip_map; | |
| 1196 | 1120 | |
| 1197 | − int_skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); | |
| 1198 | − atl_skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); | |
| 1199 | − priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); | |
| 1200 | − priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); | |
| 1201 | − priv->int_done_map &= ~int_skip_map; | |
| 1202 | − priv->atl_done_map &= ~atl_skip_map; | |
| 1121 | + skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); | |
| 1122 | + priv->int_done_map &= ~skip_map; | |
| 1123 | + skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); | |
| 1124 | + priv->atl_done_map &= ~skip_map; | |
| 1203 | 1125 | |
| 1204 | − modified = priv->int_done_map | priv->atl_done_map; | |
| 1126 | + modified = priv->int_done_map || priv->atl_done_map; | |
| 1205 | 1127 | |
| 1206 | 1128 | while (priv->int_done_map || priv->atl_done_map) { |
| 1207 | 1129 | if (priv->int_done_map) { |
| @@ -1240,7 +1162,6 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd) · 32 unmodified lines | ||
| 1240 | 1162 | slots[slot].qtd = NULL; |
| 1241 | 1163 | qh = slots[slot].qh; |
| 1242 | 1164 | slots[slot].qh = NULL; |
| 1243 | − priv->active_ptds--; | |
| 1244 | 1165 | qh->slot = -1; |
| 1245 | 1166 | |
| 1246 | 1167 | WARN_ON(qtd->status != QTD_XFER_STARTED); |
| @@ -1281,6 +1202,15 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd) · 34 unmodified lines | ||
| 1281 | 1202 | |
| 1282 | 1203 | case PTD_STATE_URB_RETIRE: |
| 1283 | 1204 | qtd->status = QTD_RETIRE; |
| 1205 | + if ((qtd->urb->dev->speed != USB_SPEED_HIGH) && | |
| 1206 | + (qtd->urb->status != -EPIPE) && | |
| 1207 | + (qtd->urb->status != -EREMOTEIO)) { | |
| 1208 | + qh->tt_buffer_dirty = 1; | |
| 1209 | + if (usb_hub_clear_tt_buffer(qtd->urb)) | |
| 1210 | + /* Clear failed; let's hope things work | |
| 1211 | + anyway */ | |
| 1212 | + qh->tt_buffer_dirty = 0; | |
| 1213 | + } | |
| 1284 | 1214 | qtd = NULL; |
| 1285 | 1215 | qh->toggle = 0; |
| 1286 | 1216 | qh->ping = 0; |
| @@ -1311,22 +1241,28 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd) · 24 unmodified lines | ||
| 1311 | 1241 | |
| 1312 | 1242 | if (modified) |
| 1313 | 1243 | schedule_ptds(hcd); |
| 1244 | +} | |
| 1314 | 1245 | |
| 1315 | − /* ISP1760 Errata 2 explains that interrupts may be missed (or not | |
| 1316 | − happen?) if two USB devices are running simultaneously. Perhaps | |
| 1317 | − this happens when a PTD is finished during interrupt handling; | |
| 1318 | − enable SOF interrupts if PTDs are still scheduled when exiting this | |
| 1319 | − interrupt handler, just to be safe. */ | |
| 1246 | +static irqreturn_t isp1760_irq(struct usb_hcd *hcd) | |
| 1247 | +{ | |
| 1248 | + struct isp1760_hcd *priv = hcd_to_priv(hcd); | |
| 1249 | + u32 imask; | |
| 1250 | + irqreturn_t irqret = IRQ_NONE; | |
| 1320 | 1251 | |
| 1321 | − if (priv->active_ptds != last_active_ptds) { | |
| 1322 | − if (priv->active_ptds > 0) | |
| 1323 | − reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, | |
| 1324 | − INTERRUPT_ENABLE_SOT_MASK); | |
| 1325 | − else | |
| 1326 | − reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, | |
| 1327 | − INTERRUPT_ENABLE_MASK); | |
| 1328 | − last_active_ptds = priv->active_ptds; | |
| 1329 | − } | |
| 1252 | + spin_lock(&priv->lock); | |
| 1253 | + | |
| 1254 | + if (!(hcd->state & HC_STATE_RUNNING)) | |
| 1255 | + goto leave; | |
| 1256 | + | |
| 1257 | + imask = reg_read32(hcd->regs, HC_INTERRUPT_REG); | |
| 1258 | + if (unlikely(!imask)) | |
| 1259 | + goto leave; | |
| 1260 | + reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */ | |
| 1261 | + | |
| 1262 | + priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); | |
| 1263 | + priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); | |
| 1264 | + | |
| 1265 | + handle_done_ptds(hcd); | |
| 1330 | 1266 | |
| 1331 | 1267 | irqret = IRQ_HANDLED; |
| 1332 | 1268 | leave: |
| @@ -1335,6 +1271,138 @@ leave: · 2 unmodified lines | ||
| 1335 | 1271 | return irqret; |
| 1336 | 1272 | } |
| 1337 | 1273 | |
| 1274 | +/* | |
| 1275 | + * Workaround for problem described in chip errata 2: | |
| 1276 | + * | |
| 1277 | + * Sometimes interrupts are not generated when ATL (not INT?) completion occurs. | |
| 1278 | + * One solution suggested in the errata is to use SOF interrupts _instead_of_ | |
| 1279 | + * ATL done interrupts (the "instead of" might be important since it seems | |
| 1280 | + * enabling ATL interrupts also causes the chip to sometimes - rarely - "forget" | |
| 1281 | + * to set the PTD's done bit in addition to not generating an interrupt!). | |
| 1282 | + * | |
| 1283 | + * So if we use SOF + ATL interrupts, we sometimes get stale PTDs since their | |
| 1284 | + * done bit is not being set. This is bad - it blocks the endpoint until reboot. | |
| 1285 | + * | |
| 1286 | + * If we use SOF interrupts only, we get latency between ptd completion and the | |
| 1287 | + * actual handling. This is very noticeable in testusb runs which takes several | |
| 1288 | + * minutes longer without ATL interrupts. | |
| 1289 | + * | |
| 1290 | + * A better solution is to run the code below every SLOT_CHECK_PERIOD ms. If it | |
| 1291 | + * finds active ATL slots which are older than SLOT_TIMEOUT ms, it checks the | |
| 1292 | + * slot's ACTIVE and VALID bits. If these are not set, the ptd is considered | |
| 1293 | + * completed and its done map bit is set. | |
| 1294 | + * | |
| 1295 | + * The values of SLOT_TIMEOUT and SLOT_CHECK_PERIOD have been arbitrarily chosen | |
| 1296 | + * not to cause too much lag when this HW bug occurs, while still hopefully | |
| 1297 | + * ensuring that the check does not falsely trigger. | |
| 1298 | + */ | |
| 1299 | +#define SLOT_TIMEOUT 300 | |
| 1300 | +#define SLOT_CHECK_PERIOD 200 | |
| 1301 | +static struct timer_list errata2_timer; | |
| 1302 | + | |
| 1303 | +void errata2_function(unsigned long data) | |
| 1304 | +{ | |
| 1305 | + struct usb_hcd *hcd = (struct usb_hcd *) data; | |
| 1306 | + struct isp1760_hcd *priv = hcd_to_priv(hcd); | |
| 1307 | + int slot; | |
| 1308 | + struct ptd ptd; | |
| 1309 | + unsigned long spinflags; | |
| 1310 | + | |
| 1311 | + spin_lock_irqsave(&priv->lock, spinflags); | |
| 1312 | + | |
| 1313 | + for (slot = 0; slot < 32; slot++) | |
| 1314 | + if (priv->atl_slots[slot].qh && time_after(jiffies, | |
| 1315 | + priv->atl_slots[slot].timestamp + | |
| 1316 | + SLOT_TIMEOUT * HZ / 1000)) { | |
| 1317 | + ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); | |
| 1318 | + if (!FROM_DW0_VALID(ptd.dw0) && | |
| 1319 | + !FROM_DW3_ACTIVE(ptd.dw3)) | |
| 1320 | + priv->atl_done_map |= 1 << slot; | |
| 1321 | + } | |
| 1322 | + | |
| 1323 | + if (priv->atl_done_map) | |
| 1324 | + handle_done_ptds(hcd); | |
| 1325 | + | |
| 1326 | + spin_unlock_irqrestore(&priv->lock, spinflags); | |
| 1327 | + | |
| 1328 | + errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000; | |
| 1329 | + add_timer(&errata2_timer); | |
| 1330 | +} | |
| 1331 | + | |
| 1332 | +static int isp1760_run(struct usb_hcd *hcd) | |
| 1333 | +{ | |
| 1334 | + int retval; | |
| 1335 | + u32 temp; | |
| 1336 | + u32 command; | |
| 1337 | + u32 chipid; | |
| 1338 | + | |
| 1339 | + hcd->uses_new_polling = 1; | |
| 1340 | + | |
| 1341 | + hcd->state = HC_STATE_RUNNING; | |
| 1342 | + | |
| 1343 | + /* Set PTD interrupt AND & OR maps */ | |
| 1344 | + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0); | |
| 1345 | + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff); | |
| 1346 | + reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0); | |
| 1347 | + reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff); | |
| 1348 | + reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0); | |
| 1349 | + reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff); | |
| 1350 | + /* step 23 passed */ | |
| 1351 | + | |
| 1352 | + temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL); | |
| 1353 | + reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN); | |
| 1354 | + | |
| 1355 | + command = reg_read32(hcd->regs, HC_USBCMD); | |
| 1356 | + command &= ~(CMD_LRESET|CMD_RESET); | |
| 1357 | + command |= CMD_RUN; | |
| 1358 | + reg_write32(hcd->regs, HC_USBCMD, command); | |
| 1359 | + | |
| 1360 | + retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000); | |
| 1361 | + if (retval) | |
| 1362 | + return retval; | |
| 1363 | + | |
| 1364 | + /* | |
| 1365 | + * XXX | |
| 1366 | + * Spec says to write FLAG_CF as last config action, priv code grabs | |
| 1367 | + * the semaphore while doing so. | |
| 1368 | + */ | |
| 1369 | + down_write(&ehci_cf_port_reset_rwsem); | |
| 1370 | + reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF); | |
| 1371 | + | |
| 1372 | + retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000); | |
| 1373 | + up_write(&ehci_cf_port_reset_rwsem); | |
| 1374 | + if (retval) | |
| 1375 | + return retval; | |
| 1376 | + | |
| 1377 | + init_timer(&errata2_timer); | |
| 1378 | + errata2_timer.function = errata2_function; | |
| 1379 | + errata2_timer.data = (unsigned long) hcd; | |
| 1380 | + errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000; | |
| 1381 | + add_timer(&errata2_timer); | |
| 1382 | + | |
| 1383 | + chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG); | |
| 1384 | + dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n", | |
| 1385 | + chipid & 0xffff, chipid >> 16); | |
| 1386 | + | |
| 1387 | + /* PTD Register Init Part 2, Step 28 */ | |
| 1388 | + | |
| 1389 | + /* Setup registers controlling PTD checking */ | |
| 1390 | + reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000); | |
| 1391 | + reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000); | |
| 1392 | + reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001); | |
| 1393 | + reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff); | |
| 1394 | + reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff); | |
| 1395 | + reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff); | |
| 1396 | + reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, | |
| 1397 | + ATL_BUF_FILL | INT_BUF_FILL); | |
| 1398 | + | |
| 1399 | + /* GRR this is run-once init(), being done every time the HC starts. | |
| 1400 | + * So long as they're part of class devices, we can't do it init() | |
| 1401 | + * since the class device isn't created that early. | |
| 1402 | + */ | |
| 1403 | + return 0; | |
| 1404 | +} | |
| 1405 | + | |
| 1338 | 1406 | static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len) |
| 1339 | 1407 | { |
| 1340 | 1408 | qtd->data_buffer = databuffer; |
| @@ -1503,7 +1571,6 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, · 162 unmodified lines | ||
| 1503 | 1571 | packetize_urb(hcd, urb, &new_qtds, mem_flags); |
| 1504 | 1572 | if (list_empty(&new_qtds)) |
| 1505 | 1573 | return -ENOMEM; |
| 1506 | − urb->hcpriv = NULL; /* Used to signal unlink to interrupt handler */ | |
| 1507 | 1574 | |
| 1508 | 1575 | retval = 0; |
| 1509 | 1576 | spin_lock_irqsave(&priv->lock, spinflags); |
| @@ -1531,6 +1598,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, · 21 unmodified lines | ||
| 1531 | 1598 | qh = qh_alloc(GFP_ATOMIC); |
| 1532 | 1599 | if (!qh) { |
| 1533 | 1600 | retval = -ENOMEM; |
| 1601 | + usb_hcd_unlink_urb_from_ep(hcd, urb); | |
| 1534 | 1602 | goto out; |
| 1535 | 1603 | } |
| 1536 | 1604 | list_add_tail(&qh->qh_list, ep_queue); |
| @@ -1570,7 +1638,41 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb, · 33 unmodified lines | ||
| 1570 | 1638 | } |
| 1571 | 1639 | |
| 1572 | 1640 | qh->slot = -1; |
| 1573 | − priv->active_ptds--; | |
| 1641 | +} | |
| 1642 | + | |
| 1643 | +/* | |
| 1644 | + * Retire the qtds beginning at 'qtd' and belonging all to the same urb, killing | |
| 1645 | + * any active transfer belonging to the urb in the process. | |
| 1646 | + */ | |
| 1647 | +static void dequeue_urb_from_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh, | |
| 1648 | + struct isp1760_qtd *qtd) | |
| 1649 | +{ | |
| 1650 | + struct urb *urb; | |
| 1651 | + int urb_was_running; | |
| 1652 | + | |
| 1653 | + urb = qtd->urb; | |
| 1654 | + urb_was_running = 0; | |
| 1655 | + list_for_each_entry_from(qtd, &qh->qtd_list, qtd_list) { | |
| 1656 | + if (qtd->urb != urb) | |
| 1657 | + break; | |
| 1658 | + | |
| 1659 | + if (qtd->status >= QTD_XFER_STARTED) | |
| 1660 | + urb_was_running = 1; | |
| 1661 | + if (last_qtd_of_urb(qtd, qh) && | |
| 1662 | + (qtd->status >= QTD_XFER_COMPLETE)) | |
| 1663 | + urb_was_running = 0; | |
| 1664 | + | |
| 1665 | + if (qtd->status == QTD_XFER_STARTED) | |
| 1666 | + kill_transfer(hcd, urb, qh); | |
| 1667 | + qtd->status = QTD_RETIRE; | |
| 1668 | + } | |
| 1669 | + | |
| 1670 | + if ((urb->dev->speed != USB_SPEED_HIGH) && urb_was_running) { | |
| 1671 | + qh->tt_buffer_dirty = 1; | |
| 1672 | + if (usb_hub_clear_tt_buffer(urb)) | |
| 1673 | + /* Clear failed; let's hope things work anyway */ | |
| 1674 | + qh->tt_buffer_dirty = 0; | |
| 1675 | + } | |
| 1574 | 1676 | } |
| 1575 | 1677 | |
| 1576 | 1678 | static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, |
| @@ -1595,9 +1697,8 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, · 18 unmodified lines | ||
| 1595 | 1697 | |
| 1596 | 1698 | list_for_each_entry(qtd, &qh->qtd_list, qtd_list) |
| 1597 | 1699 | if (qtd->urb == urb) { |
| 1598 | − if (qtd->status == QTD_XFER_STARTED) | |
| 1599 | − kill_transfer(hcd, urb, qh); | |
| 1600 | − qtd->status = QTD_RETIRE; | |
| 1700 | + dequeue_urb_from_qtd(hcd, qh, qtd); | |
| 1701 | + break; | |
| 1601 | 1702 | } |
| 1602 | 1703 | |
| 1603 | 1704 | urb->status = status; |
| @@ -1622,12 +1723,11 @@ static void isp1760_endpoint_disable(struct usb_hcd *hcd, · 18 unmodified lines | ||
| 1622 | 1723 | if (!qh) |
| 1623 | 1724 | goto out; |
| 1624 | 1725 | |
| 1625 | − list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { | |
| 1626 | − if (qtd->status == QTD_XFER_STARTED) | |
| 1627 | − kill_transfer(hcd, qtd->urb, qh); | |
| 1628 | − qtd->status = QTD_RETIRE; | |
| 1629 | − qtd->urb->status = -ECONNRESET; | |
| 1630 | − } | |
| 1726 | + list_for_each_entry(qtd, &qh->qtd_list, qtd_list) | |
| 1727 | + if (qtd->status != QTD_RETIRE) { | |
| 1728 | + dequeue_urb_from_qtd(hcd, qh, qtd); | |
| 1729 | + qtd->urb->status = -ECONNRESET; | |
| 1730 | + } | |
| 1631 | 1731 | |
| 1632 | 1732 | ep->hcpriv = NULL; |
| 1633 | 1733 | /* Cannot free qh here since it will be parsed by schedule_ptds() */ |
| @@ -2021,6 +2121,8 @@ static void isp1760_stop(struct usb_hcd *hcd) · 387 unmodified lines | ||
| 2021 | 2121 | struct isp1760_hcd *priv = hcd_to_priv(hcd); |
| 2022 | 2122 | u32 temp; |
| 2023 | 2123 | |
| 2124 | + del_timer(&errata2_timer); | |
| 2125 | + | |
| 2024 | 2126 | isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, |
| 2025 | 2127 | NULL, 0); |
| 2026 | 2128 | mdelay(20); |
| @@ -2048,6 +2150,23 @@ static void isp1760_shutdown(struct usb_hcd *hcd) · 21 unmodified lines | ||
| 2048 | 2150 | reg_write32(hcd->regs, HC_USBCMD, command); |
| 2049 | 2151 | } |
| 2050 | 2152 | |
| 2153 | +static void isp1760_clear_tt_buffer_complete(struct usb_hcd *hcd, | |
| 2154 | + struct usb_host_endpoint *ep) | |
| 2155 | +{ | |
| 2156 | + struct isp1760_hcd *priv = hcd_to_priv(hcd); | |
| 2157 | + struct isp1760_qh *qh = ep->hcpriv; | |
| 2158 | + unsigned long spinflags; | |
| 2159 | + | |
| 2160 | + if (!qh) | |
| 2161 | + return; | |
| 2162 | + | |
| 2163 | + spin_lock_irqsave(&priv->lock, spinflags); | |
| 2164 | + qh->tt_buffer_dirty = 0; | |
| 2165 | + schedule_ptds(hcd); | |
| 2166 | + spin_unlock_irqrestore(&priv->lock, spinflags); | |
| 2167 | +} | |
| 2168 | + | |
| 2169 | + | |
| 2051 | 2170 | static const struct hc_driver isp1760_hc_driver = { |
| 2052 | 2171 | .description = "isp1760-hcd", |
| 2053 | 2172 | .product_desc = "NXP ISP1760 USB Host Controller", |
| @@ -2064,6 +2183,7 @@ static const struct hc_driver isp1760_hc_driver = { · 10 unmodified lines | ||
| 2064 | 2183 | .get_frame_number = isp1760_get_frame, |
| 2065 | 2184 | .hub_status_data = isp1760_hub_status_data, |
| 2066 | 2185 | .hub_control = isp1760_hub_control, |
| 2186 | + .clear_tt_buffer_complete = isp1760_clear_tt_buffer_complete, | |
| 2067 | 2187 | }; |
| 2068 | 2188 | |
| 2069 | 2189 | int __init init_kmem_once(void) |
| @@ -2102,6 +2222,7 @@ void deinit_kmem_cache(void) · 32 unmodified lines | ||
| 2102 | 2222 | |
| 2103 | 2223 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
| 2104 | 2224 | int irq, unsigned long irqflags, |
| 2225 | + int rst_gpio, | |
| 2105 | 2226 | struct device *dev, const char *busname, |
| 2106 | 2227 | unsigned int devflags) |
| 2107 | 2228 | { |
| @@ -2121,6 +2242,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, · 13 unmodified lines | ||
| 2121 | 2242 | |
| 2122 | 2243 | priv = hcd_to_priv(hcd); |
| 2123 | 2244 | priv->devflags = devflags; |
| 2245 | + priv->rst_gpio = rst_gpio; | |
| 2124 | 2246 | init_memory(priv); |
| 2125 | 2247 | hcd->regs = ioremap(res_start, res_len); |
| 2126 | 2248 | if (!hcd->regs) { |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | /* exports for if */ |
| 5 | 5 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
| 6 | 6 | int irq, unsigned long irqflags, |
| 7 | + int rst_gpio, | |
| 7 | 8 | struct device *dev, const char *busname, |
| 8 | 9 | unsigned int devflags); |
| 9 | 10 | int init_kmem_once(void); |
| @@ -73,7 +74,6 @@ void deinit_kmem_cache(void); · 63 unmodified lines | ||
| 73 | 74 | #define HC_EOT_INT (1 << 3) |
| 74 | 75 | #define HC_SOT_INT (1 << 1) |
| 75 | 76 | #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT) |
| 76 | −#define INTERRUPT_ENABLE_SOT_MASK (HC_SOT_INT) | |
| 77 | 77 | |
| 78 | 78 | #define HC_ISO_IRQ_MASK_OR_REG 0x318 |
| 79 | 79 | #define HC_INT_IRQ_MASK_OR_REG 0x31C |
| @@ -107,6 +107,7 @@ struct ptd { · 27 unmodified lines | ||
| 107 | 107 | struct slotinfo { |
| 108 | 108 | struct isp1760_qh *qh; |
| 109 | 109 | struct isp1760_qtd *qtd; |
| 110 | + unsigned long timestamp; | |
| 110 | 111 | }; |
| 111 | 112 | |
| 112 | 113 | |
| @@ -126,6 +127,7 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, · 13 unmodified lines | ||
| 126 | 127 | #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ |
| 127 | 128 | #define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ |
| 128 | 129 | #define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ |
| 130 | +#define ISP1760_FLAG_RESET_ACTIVE_HIGH 0x80000000 /* RESET GPIO active high */ | |
| 129 | 131 | |
| 130 | 132 | /* chip memory management */ |
| 131 | 133 | struct memory_chunk { |
| @@ -188,6 +190,7 @@ struct memory_chunk { · 56 unmodified lines | ||
| 188 | 190 | #define DW3_BABBLE_BIT (1 << 29) |
| 189 | 191 | #define DW3_HALT_BIT (1 << 30) |
| 190 | 192 | #define DW3_ACTIVE_BIT (1 << 31) |
| 193 | +#define FROM_DW3_ACTIVE(x) (((x) >> 31) & 0x01) | |
| 191 | 194 | |
| 192 | 195 | #define INT_UNDERRUN (1 << 2) |
| 193 | 196 | #define INT_BABBLE (1 << 1) |
| @@ -17,19 +17,28 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include "isp1760-hcd.h" |
| 19 | 19 | |
| 20 | −#ifdef CONFIG_PPC_OF | |
| 20 | +#ifdef CONFIG_OF | |
| 21 | +#include <linux/slab.h> | |
| 21 | 22 | #include <linux/of.h> |
| 22 | 23 | #include <linux/of_platform.h> |
| 24 | +#include <linux/of_address.h> | |
| 25 | +#include <linux/of_irq.h> | |
| 26 | +#include <linux/of_gpio.h> | |
| 23 | 27 | #endif |
| 24 | 28 | |
| 25 | 29 | #ifdef CONFIG_PCI |
| 26 | 30 | #include <linux/pci.h> |
| 27 | 31 | #endif |
| 28 | 32 | |
| 29 | −#ifdef CONFIG_PPC_OF | |
| 33 | +#ifdef CONFIG_OF | |
| 34 | +struct isp1760 { | |
| 35 | + struct usb_hcd *hcd; | |
| 36 | + int rst_gpio; | |
| 37 | +}; | |
| 38 | + | |
| 30 | 39 | static int of_isp1760_probe(struct platform_device *dev) |
| 31 | 40 | { |
| 32 | − struct usb_hcd *hcd; | |
| 41 | + struct isp1760 *drvdata; | |
| 33 | 42 | struct device_node *dp = dev->dev.of_node; |
| 34 | 43 | struct resource *res; |
| 35 | 44 | struct resource memory; |
| @@ -39,6 +48,11 @@ static int of_isp1760_probe(struct platform_device *dev) · 3 unmodified lines | ||
| 39 | 48 | int ret; |
| 40 | 49 | const unsigned int *prop; |
| 41 | 50 | unsigned int devflags = 0; |
| 51 | + enum of_gpio_flags gpio_flags; | |
| 52 | + | |
| 53 | + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); | |
| 54 | + if (!drvdata) | |
| 55 | + return -ENOMEM; | |
| 42 | 56 | |
| 43 | 57 | ret = of_address_to_resource(dp, 0, &memory); |
| 44 | 58 | if (ret) |
| @@ -78,32 +92,57 @@ static int of_isp1760_probe(struct platform_device *dev) · 33 unmodified lines | ||
| 78 | 92 | if (of_get_property(dp, "dreq-polarity", NULL) != NULL) |
| 79 | 93 | devflags |= ISP1760_FLAG_DREQ_POL_HIGH; |
| 80 | 94 | |
| 81 | − hcd = isp1760_register(memory.start, res_len, virq, | |
| 82 | − IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), | |
| 83 | − devflags); | |
| 84 | − if (IS_ERR(hcd)) { | |
| 85 | − ret = PTR_ERR(hcd); | |
| 86 | − goto release_reg; | |
| 95 | + drvdata->rst_gpio = of_get_gpio_flags(dp, 0, &gpio_flags); | |
| 96 | + if (gpio_is_valid(drvdata->rst_gpio)) { | |
| 97 | + ret = gpio_request(drvdata->rst_gpio, dev_name(&dev->dev)); | |
| 98 | + if (!ret) { | |
| 99 | + if (!(gpio_flags & OF_GPIO_ACTIVE_LOW)) { | |
| 100 | + devflags |= ISP1760_FLAG_RESET_ACTIVE_HIGH; | |
| 101 | + gpio_direction_output(drvdata->rst_gpio, 0); | |
| 102 | + } else { | |
| 103 | + gpio_direction_output(drvdata->rst_gpio, 1); | |
| 104 | + } | |
| 105 | + } else { | |
| 106 | + drvdata->rst_gpio = ret; | |
| 107 | + } | |
| 87 | 108 | } |
| 88 | 109 | |
| 89 | − dev_set_drvdata(&dev->dev, hcd); | |
| 110 | + drvdata->hcd = isp1760_register(memory.start, res_len, virq, | |
| 111 | + IRQF_SHARED, drvdata->rst_gpio, | |
| 112 | + &dev->dev, dev_name(&dev->dev), | |
| 113 | + devflags); | |
| 114 | + if (IS_ERR(drvdata->hcd)) { | |
| 115 | + ret = PTR_ERR(drvdata->hcd); | |
| 116 | + goto free_gpio; | |
| 117 | + } | |
| 118 | + | |
| 119 | + dev_set_drvdata(&dev->dev, drvdata); | |
| 90 | 120 | return ret; |
| 91 | 121 | |
| 122 | +free_gpio: | |
| 123 | + if (gpio_is_valid(drvdata->rst_gpio)) | |
| 124 | + gpio_free(drvdata->rst_gpio); | |
| 92 | 125 | release_reg: |
| 93 | 126 | release_mem_region(memory.start, res_len); |
| 127 | + kfree(drvdata); | |
| 94 | 128 | return ret; |
| 95 | 129 | } |
| 96 | 130 | |
| 97 | 131 | static int of_isp1760_remove(struct platform_device *dev) |
| 98 | 132 | { |
| 99 | − struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); | |
| 133 | + struct isp1760 *drvdata = dev_get_drvdata(&dev->dev); | |
| 100 | 134 | |
| 101 | 135 | dev_set_drvdata(&dev->dev, NULL); |
| 102 | 136 | |
| 103 | − usb_remove_hcd(hcd); | |
| 104 | − iounmap(hcd->regs); | |
| 105 | − release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 106 | − usb_put_hcd(hcd); | |
| 137 | + usb_remove_hcd(drvdata->hcd); | |
| 138 | + iounmap(drvdata->hcd->regs); | |
| 139 | + release_mem_region(drvdata->hcd->rsrc_start, drvdata->hcd->rsrc_len); | |
| 140 | + usb_put_hcd(drvdata->hcd); | |
| 141 | + | |
| 142 | + if (gpio_is_valid(drvdata->rst_gpio)) | |
| 143 | + gpio_free(drvdata->rst_gpio); | |
| 144 | + | |
| 145 | + kfree(drvdata); | |
| 107 | 146 | return 0; |
| 108 | 147 | } |
| 109 | 148 | |
| @@ -240,7 +279,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, · 130 unmodified lines | ||
| 240 | 279 | |
| 241 | 280 | dev->dev.dma_mask = NULL; |
| 242 | 281 | hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, |
| 243 | − IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), | |
| 282 | + IRQF_SHARED, -ENOENT, &dev->dev, dev_name(&dev->dev), | |
| 244 | 283 | devflags); |
| 245 | 284 | if (IS_ERR(hcd)) { |
| 246 | 285 | ret_status = -ENODEV; |
| @@ -313,7 +352,7 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) · 66 unmodified lines | ||
| 313 | 352 | resource_size_t mem_size; |
| 314 | 353 | struct isp1760_platform_data *priv = pdev->dev.platform_data; |
| 315 | 354 | unsigned int devflags = 0; |
| 316 | − unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; | |
| 355 | + unsigned long irqflags = IRQF_SHARED; | |
| 317 | 356 | |
| 318 | 357 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 319 | 358 | if (!mem_res) { |
| @@ -351,7 +390,8 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) · 31 unmodified lines | ||
| 351 | 390 | } |
| 352 | 391 | |
| 353 | 392 | hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, |
| 354 | − irqflags, &pdev->dev, dev_name(&pdev->dev), devflags); | |
| 393 | + irqflags, -ENOENT, | |
| 394 | + &pdev->dev, dev_name(&pdev->dev), devflags); | |
| 355 | 395 | if (IS_ERR(hcd)) { |
| 356 | 396 | pr_warning("isp1760: Failed to register the HCD device\n"); |
| 357 | 397 | ret = -ENODEV; |
| @@ -396,7 +436,7 @@ static int __init isp1760_init(void) · 38 unmodified lines | ||
| 396 | 436 | ret = platform_driver_register(&isp1760_plat_driver); |
| 397 | 437 | if (!ret) |
| 398 | 438 | any_ret = 0; |
| 399 | −#ifdef CONFIG_PPC_OF | |
| 439 | +#ifdef CONFIG_OF | |
| 400 | 440 | ret = platform_driver_register(&isp1760_of_driver); |
| 401 | 441 | if (!ret) |
| 402 | 442 | any_ret = 0; |
| @@ -416,7 +456,7 @@ module_init(isp1760_init); · 13 unmodified lines | ||
| 416 | 456 | static void __exit isp1760_exit(void) |
| 417 | 457 | { |
| 418 | 458 | platform_driver_unregister(&isp1760_plat_driver); |
| 419 | −#ifdef CONFIG_PPC_OF | |
| 459 | +#ifdef CONFIG_OF | |
| 420 | 460 | platform_driver_unregister(&isp1760_of_driver); |
| 421 | 461 | #endif |
| 422 | 462 | #ifdef CONFIG_PCI |
| @@ -111,7 +111,7 @@ static int ohci_ath79_probe(struct platform_device *pdev) · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 113 | 113 | |
| 114 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 114 | + ret = usb_add_hcd(hcd, irq, 0); | |
| 115 | 115 | if (ret) |
| 116 | 116 | goto err_stop_hcd; |
| 117 | 117 | |
| @@ -218,7 +218,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) · 217 unmodified lines | ||
| 218 | 218 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 219 | 219 | |
| 220 | 220 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
| 221 | − IRQF_DISABLED | IRQF_SHARED); | |
| 221 | + IRQF_SHARED); | |
| 222 | 222 | if (ret == 0) { |
| 223 | 223 | platform_set_drvdata(pdev, hcd); |
| 224 | 224 | return ret; |
| @@ -344,7 +344,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, · 343 unmodified lines | ||
| 344 | 344 | error = -ENODEV; |
| 345 | 345 | goto err4; |
| 346 | 346 | } |
| 347 | − error = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 347 | + error = usb_add_hcd(hcd, irq, 0); | |
| 348 | 348 | if (error) |
| 349 | 349 | goto err4; |
| 350 | 350 | |
| @@ -81,7 +81,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, · 80 unmodified lines | ||
| 81 | 81 | |
| 82 | 82 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 83 | 83 | |
| 84 | − retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED); | |
| 84 | + retval = usb_add_hcd(hcd, pdev->resource[1].start, 0); | |
| 85 | 85 | if (retval == 0) |
| 86 | 86 | return retval; |
| 87 | 87 | |
| @@ -1114,6 +1114,11 @@ MODULE_LICENSE ("GPL"); · 1113 unmodified lines | ||
| 1114 | 1114 | #define PLATFORM_DRIVER ohci_hcd_ath79_driver |
| 1115 | 1115 | #endif |
| 1116 | 1116 | |
| 1117 | +#ifdef CONFIG_NLM_XLR | |
| 1118 | +#include "ohci-xls.c" | |
| 1119 | +#define PLATFORM_DRIVER ohci_xls_driver | |
| 1120 | +#endif | |
| 1121 | + | |
| 1117 | 1122 | #if !defined(PCI_DRIVER) && \ |
| 1118 | 1123 | !defined(PLATFORM_DRIVER) && \ |
| 1119 | 1124 | !defined(OMAP1_PLATFORM_DRIVER) && \ |
| @@ -356,10 +356,7 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd) · 355 unmodified lines | ||
| 356 | 356 | msleep(20); |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | − /* Does the root hub have a port wakeup pending? */ | |
| 360 | − if (ohci_readl(ohci, &ohci->regs->intrstatus) & | |
| 361 | − (OHCI_INTR_RD | OHCI_INTR_RHSC)) | |
| 362 | − usb_hcd_resume_root_hub(hcd); | |
| 359 | + usb_hcd_resume_root_hub(hcd); | |
| 363 | 360 | } |
| 364 | 361 | |
| 365 | 362 | /* Carry out polling-, autostop-, and autoresume-related state changes */ |
| @@ -164,7 +164,7 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev) · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | ohci_hcd_init(ohci); |
| 166 | 166 | |
| 167 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 167 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 168 | 168 | if (ret) { |
| 169 | 169 | dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); |
| 170 | 170 | goto err3; |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * This file is licenced under the GPL. |
| 15 | 15 | */ |
| 16 | 16 | |
| 17 | −#include <linux/signal.h> /* IRQF_DISABLED */ | |
| 17 | +#include <linux/signal.h> | |
| 18 | 18 | #include <linux/jiffies.h> |
| 19 | 19 | #include <linux/platform_device.h> |
| 20 | 20 | #include <linux/clk.h> |
| @@ -363,7 +363,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, · 342 unmodified lines | ||
| 363 | 363 | retval = -ENXIO; |
| 364 | 364 | goto err3; |
| 365 | 365 | } |
| 366 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 366 | + retval = usb_add_hcd(hcd, irq, 0); | |
| 367 | 367 | if (retval) |
| 368 | 368 | goto err3; |
| 369 | 369 | |
| @@ -149,7 +149,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) · 148 unmodified lines | ||
| 149 | 149 | |
| 150 | 150 | res = platform_get_resource_byname(pdev, |
| 151 | 151 | IORESOURCE_MEM, "ohci"); |
| 152 | − if (!ret) { | |
| 152 | + if (!res) { | |
| 153 | 153 | dev_err(dev, "UHH OHCI get resource failed\n"); |
| 154 | 154 | return -ENOMEM; |
| 155 | 155 | } |
| @@ -180,7 +180,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) · 24 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 182 | 182 | |
| 183 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 183 | + ret = usb_add_hcd(hcd, irq, 0); | |
| 184 | 184 | if (ret) { |
| 185 | 185 | dev_dbg(dev, "failed to add hcd with err %d\n", ret); |
| 186 | 186 | goto err_add_hcd; |
| @@ -398,7 +398,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) · 397 unmodified lines | ||
| 398 | 398 | ohci_hcd_init(ohci); |
| 399 | 399 | |
| 400 | 400 | dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); |
| 401 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 401 | + ret = usb_add_hcd(hcd, irq, 0); | |
| 402 | 402 | if (ret == 0) |
| 403 | 403 | return ret; |
| 404 | 404 | |
| @@ -107,7 +107,7 @@ int usb_hcd_pnx8550_probe (const struct hc_driver *driver, · 106 unmodified lines | ||
| 107 | 107 | |
| 108 | 108 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 109 | 109 | |
| 110 | − retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); | |
| 110 | + retval = usb_add_hcd(hcd, dev->resource[1].start, 0); | |
| 111 | 111 | if (retval == 0) |
| 112 | 112 | return retval; |
| 113 | 113 | |
| @@ -143,7 +143,7 @@ static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op) · 142 unmodified lines | ||
| 143 | 143 | |
| 144 | 144 | ohci_hcd_init(ohci); |
| 145 | 145 | |
| 146 | − rv = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 146 | + rv = usb_add_hcd(hcd, irq, 0); | |
| 147 | 147 | if (rv == 0) |
| 148 | 148 | return 0; |
| 149 | 149 | |
| @@ -80,7 +80,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, · 79 unmodified lines | ||
| 80 | 80 | #endif |
| 81 | 81 | ohci_hcd_init(ohci); |
| 82 | 82 | |
| 83 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 83 | + retval = usb_add_hcd(hcd, irq, 0); | |
| 84 | 84 | if (retval == 0) |
| 85 | 85 | return retval; |
| 86 | 86 | |
| @@ -164,7 +164,7 @@ static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev) · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | ps3_system_bus_set_drvdata(dev, hcd); |
| 166 | 166 | |
| 167 | − result = usb_add_hcd(hcd, virq, IRQF_DISABLED); | |
| 167 | + result = usb_add_hcd(hcd, virq, 0); | |
| 168 | 168 | |
| 169 | 169 | if (result) { |
| 170 | 170 | dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", |
| @@ -359,7 +359,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device · 358 unmodified lines | ||
| 359 | 359 | |
| 360 | 360 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 361 | 361 | |
| 362 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 362 | + retval = usb_add_hcd(hcd, irq, 0); | |
| 363 | 363 | if (retval == 0) |
| 364 | 364 | return retval; |
| 365 | 365 | |
| @@ -428,7 +428,7 @@ static struct ed *ed_get ( · 427 unmodified lines | ||
| 428 | 428 | ed->type = usb_pipetype(pipe); |
| 429 | 429 | |
| 430 | 430 | info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << 7; |
| 431 | − info |= le16_to_cpu(ep->desc.wMaxPacketSize) << 16; | |
| 431 | + info |= usb_endpoint_maxp(&ep->desc) << 16; | |
| 432 | 432 | if (udev->speed == USB_SPEED_LOW) |
| 433 | 433 | info |= ED_LOWSPEED; |
| 434 | 434 | /* only control transfers store pids in tds */ |
| @@ -444,7 +444,7 @@ static struct ed *ed_get ( · 9 unmodified lines | ||
| 444 | 444 | ed->load = usb_calc_bus_time ( |
| 445 | 445 | udev->speed, !is_out, |
| 446 | 446 | ed->type == PIPE_ISOCHRONOUS, |
| 447 | − le16_to_cpu(ep->desc.wMaxPacketSize)) | |
| 447 | + usb_endpoint_maxp(&ep->desc)) | |
| 448 | 448 | / 1000; |
| 449 | 449 | } |
| 450 | 450 | } |
| @@ -384,7 +384,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, · 383 unmodified lines | ||
| 384 | 384 | |
| 385 | 385 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 386 | 386 | |
| 387 | − retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); | |
| 387 | + retval = usb_add_hcd(hcd, dev->resource[1].start, 0); | |
| 388 | 388 | if (retval != 0) |
| 389 | 389 | goto err_ioremap; |
| 390 | 390 | |
| @@ -143,7 +143,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, · 142 unmodified lines | ||
| 143 | 143 | sa1111_start_hc(dev); |
| 144 | 144 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 145 | 145 | |
| 146 | − retval = usb_add_hcd(hcd, dev->irq[1], IRQF_DISABLED); | |
| 146 | + retval = usb_add_hcd(hcd, dev->irq[1], 0); | |
| 147 | 147 | if (retval == 0) |
| 148 | 148 | return retval; |
| 149 | 149 | |
| @@ -109,7 +109,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev) · 108 unmodified lines | ||
| 109 | 109 | hcd->regs = (void __iomem *)res->start; |
| 110 | 110 | hcd->rsrc_start = res->start; |
| 111 | 111 | hcd->rsrc_len = resource_size(res); |
| 112 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 112 | + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 113 | 113 | if (ret != 0) { |
| 114 | 114 | err("Failed to add hcd"); |
| 115 | 115 | usb_put_hcd(hcd); |
| @@ -165,7 +165,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) · 164 unmodified lines | ||
| 165 | 165 | |
| 166 | 166 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 167 | 167 | |
| 168 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 168 | + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | |
| 169 | 169 | if (retval) |
| 170 | 170 | goto err5; |
| 171 | 171 | |
| @@ -152,7 +152,7 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) · 151 unmodified lines | ||
| 152 | 152 | spear_start_ohci(ohci_p); |
| 153 | 153 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 154 | 154 | |
| 155 | − retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), IRQF_DISABLED); | |
| 155 | + retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); | |
| 156 | 156 | if (retval == 0) |
| 157 | 157 | return retval; |
| 158 | 158 | |
| @@ -169,7 +169,7 @@ static int ssb_ohci_attach(struct ssb_device *dev) · 168 unmodified lines | ||
| 169 | 169 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); |
| 170 | 170 | if (!hcd->regs) |
| 171 | 171 | goto err_put_hcd; |
| 172 | − err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | |
| 172 | + err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); | |
| 173 | 173 | if (err) |
| 174 | 174 | goto err_iounmap; |
| 175 | 175 | |
| @@ -244,7 +244,7 @@ static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) · 243 unmodified lines | ||
| 244 | 244 | ohci = hcd_to_ohci(hcd); |
| 245 | 245 | ohci_hcd_init(ohci); |
| 246 | 246 | |
| 247 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | |
| 247 | + ret = usb_add_hcd(hcd, irq, 0); | |
| 248 | 248 | if (ret) |
| 249 | 249 | goto err_add_hcd; |
| 250 | 250 | |
| @@ -0,0 +1,151 @@ | ||
| 1 | +/* | |
| 2 | + * OHCI HCD for Netlogic XLS processors. | |
| 3 | + * | |
| 4 | + * (C) Copyright 2011 Netlogic Microsystems Inc. | |
| 5 | + * | |
| 6 | + * Based on ohci-au1xxx.c, and other Linux OHCI drivers. | |
| 7 | + * | |
| 8 | + * This file is subject to the terms and conditions of the GNU General Public | |
| 9 | + * License. See the file COPYING in the main directory of this archive for | |
| 10 | + * more details. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/platform_device.h> | |
| 14 | +#include <linux/signal.h> | |
| 15 | + | |
| 16 | +static int ohci_xls_probe_internal(const struct hc_driver *driver, | |
| 17 | + struct platform_device *dev) | |
| 18 | +{ | |
| 19 | + struct resource *res; | |
| 20 | + struct usb_hcd *hcd; | |
| 21 | + int retval, irq; | |
| 22 | + | |
| 23 | + /* Get our IRQ from an earlier registered Platform Resource */ | |
| 24 | + irq = platform_get_irq(dev, 0); | |
| 25 | + if (irq < 0) { | |
| 26 | + dev_err(&dev->dev, "Found HC with no IRQ\n"); | |
| 27 | + return -ENODEV; | |
| 28 | + } | |
| 29 | + | |
| 30 | + /* Get our Memory Handle */ | |
| 31 | + res = platform_get_resource(dev, IORESOURCE_MEM, 0); | |
| 32 | + if (!res) { | |
| 33 | + dev_err(&dev->dev, "MMIO Handle incorrect!\n"); | |
| 34 | + return -ENODEV; | |
| 35 | + } | |
| 36 | + | |
| 37 | + hcd = usb_create_hcd(driver, &dev->dev, "XLS"); | |
| 38 | + if (!hcd) { | |
| 39 | + retval = -ENOMEM; | |
| 40 | + goto err1; | |
| 41 | + } | |
| 42 | + hcd->rsrc_start = res->start; | |
| 43 | + hcd->rsrc_len = res->end - res->start + 1; | |
| 44 | + | |
| 45 | + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | |
| 46 | + driver->description)) { | |
| 47 | + dev_dbg(&dev->dev, "Controller already in use\n"); | |
| 48 | + retval = -EBUSY; | |
| 49 | + goto err2; | |
| 50 | + } | |
| 51 | + | |
| 52 | + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | |
| 53 | + if (hcd->regs == NULL) { | |
| 54 | + dev_dbg(&dev->dev, "error mapping memory\n"); | |
| 55 | + retval = -EFAULT; | |
| 56 | + goto err3; | |
| 57 | + } | |
| 58 | + | |
| 59 | + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | |
| 60 | + if (retval != 0) | |
| 61 | + goto err4; | |
| 62 | + return retval; | |
| 63 | + | |
| 64 | +err4: | |
| 65 | + iounmap(hcd->regs); | |
| 66 | +err3: | |
| 67 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 68 | +err2: | |
| 69 | + usb_put_hcd(hcd); | |
| 70 | +err1: | |
| 71 | + dev_err(&dev->dev, "init fail, %d\n", retval); | |
| 72 | + return retval; | |
| 73 | +} | |
| 74 | + | |
| 75 | +static int ohci_xls_reset(struct usb_hcd *hcd) | |
| 76 | +{ | |
| 77 | + struct ohci_hcd *ohci = hcd_to_ohci(hcd); | |
| 78 | + | |
| 79 | + ohci_hcd_init(ohci); | |
| 80 | + return ohci_init(ohci); | |
| 81 | +} | |
| 82 | + | |
| 83 | +static int __devinit ohci_xls_start(struct usb_hcd *hcd) | |
| 84 | +{ | |
| 85 | + struct ohci_hcd *ohci; | |
| 86 | + int ret; | |
| 87 | + | |
| 88 | + ohci = hcd_to_ohci(hcd); | |
| 89 | + ret = ohci_run(ohci); | |
| 90 | + if (ret < 0) { | |
| 91 | + err("can't start %s", hcd->self.bus_name); | |
| 92 | + ohci_stop(hcd); | |
| 93 | + return ret; | |
| 94 | + } | |
| 95 | + return 0; | |
| 96 | +} | |
| 97 | + | |
| 98 | +static struct hc_driver ohci_xls_hc_driver = { | |
| 99 | + .description = hcd_name, | |
| 100 | + .product_desc = "XLS OHCI Host Controller", | |
| 101 | + .hcd_priv_size = sizeof(struct ohci_hcd), | |
| 102 | + .irq = ohci_irq, | |
| 103 | + .flags = HCD_MEMORY | HCD_USB11, | |
| 104 | + .reset = ohci_xls_reset, | |
| 105 | + .start = ohci_xls_start, | |
| 106 | + .stop = ohci_stop, | |
| 107 | + .shutdown = ohci_shutdown, | |
| 108 | + .urb_enqueue = ohci_urb_enqueue, | |
| 109 | + .urb_dequeue = ohci_urb_dequeue, | |
| 110 | + .endpoint_disable = ohci_endpoint_disable, | |
| 111 | + .get_frame_number = ohci_get_frame, | |
| 112 | + .hub_status_data = ohci_hub_status_data, | |
| 113 | + .hub_control = ohci_hub_control, | |
| 114 | +#ifdef CONFIG_PM | |
| 115 | + .bus_suspend = ohci_bus_suspend, | |
| 116 | + .bus_resume = ohci_bus_resume, | |
| 117 | +#endif | |
| 118 | + .start_port_reset = ohci_start_port_reset, | |
| 119 | +}; | |
| 120 | + | |
| 121 | +static int ohci_xls_probe(struct platform_device *dev) | |
| 122 | +{ | |
| 123 | + int ret; | |
| 124 | + | |
| 125 | + pr_debug("In ohci_xls_probe"); | |
| 126 | + if (usb_disabled()) | |
| 127 | + return -ENODEV; | |
| 128 | + ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev); | |
| 129 | + return ret; | |
| 130 | +} | |
| 131 | + | |
| 132 | +static int ohci_xls_remove(struct platform_device *dev) | |
| 133 | +{ | |
| 134 | + struct usb_hcd *hcd = platform_get_drvdata(dev); | |
| 135 | + | |
| 136 | + usb_remove_hcd(hcd); | |
| 137 | + iounmap(hcd->regs); | |
| 138 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | |
| 139 | + usb_put_hcd(hcd); | |
| 140 | + return 0; | |
| 141 | +} | |
| 142 | + | |
| 143 | +static struct platform_driver ohci_xls_driver = { | |
| 144 | + .probe = ohci_xls_probe, | |
| 145 | + .remove = ohci_xls_remove, | |
| 146 | + .shutdown = usb_hcd_platform_shutdown, | |
| 147 | + .driver = { | |
| 148 | + .name = "ohci-xls-0", | |
| 149 | + .owner = THIS_MODULE, | |
| 150 | + }, | |
| 151 | +}; | |
| @@ -959,7 +959,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, · 958 unmodified lines | ||
| 959 | 959 | info.pipenum = get_empty_pipenum(r8a66597, ep); |
| 960 | 960 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); |
| 961 | 961 | info.epnum = usb_endpoint_num(ep); |
| 962 | − info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); | |
| 962 | + info.maxpacket = usb_endpoint_maxp(ep); | |
| 963 | 963 | info.type = get_r8a66597_type(usb_endpoint_type(ep)); |
| 964 | 964 | info.bufnum = get_bufnum(info.pipenum); |
| 965 | 965 | info.buf_bsize = get_buf_bsize(info.pipenum); |
| @@ -2519,7 +2519,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) · 1553 unmodified lines | ||
| 2519 | 2519 | hcd->rsrc_start = res->start; |
| 2520 | 2520 | hcd->has_tt = 1; |
| 2521 | 2521 | |
| 2522 | − ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger); | |
| 2522 | + ret = usb_add_hcd(hcd, irq, irq_trigger); | |
| 2523 | 2523 | if (ret != 0) { |
| 2524 | 2524 | dev_err(&pdev->dev, "Failed to add hcd\n"); |
| 2525 | 2525 | goto clean_up3; |
| @@ -1729,7 +1729,7 @@ sl811h_probe(struct platform_device *dev) · 1728 unmodified lines | ||
| 1729 | 1729 | * Use resource IRQ flags if set by platform device setup. |
| 1730 | 1730 | */ |
| 1731 | 1731 | irqflags |= IRQF_SHARED; |
| 1732 | − retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | irqflags); | |
| 1732 | + retval = usb_add_hcd(hcd, irq, irqflags); | |
| 1733 | 1733 | if (retval != 0) |
| 1734 | 1734 | goto err6; |
| 1735 | 1735 | |
| @@ -294,50 +294,50 @@ __acquires(uhci->lock) · 293 unmodified lines | ||
| 294 | 294 | * and that remote wakeups should be enabled. |
| 295 | 295 | */ |
| 296 | 296 | egsm_enable = USBCMD_EGSM; |
| 297 | − uhci->RD_enable = 1; | |
| 298 | 297 | int_enable = USBINTR_RESUME; |
| 299 | 298 | wakeup_enable = 1; |
| 300 | 299 | |
| 301 | − /* In auto-stop mode wakeups must always be detected, but | |
| 302 | − * Resume-Detect interrupts may be prohibited. (In the absence | |
| 303 | − * of CONFIG_PM, they are always disallowed.) | |
| 300 | + /* | |
| 301 | + * In auto-stop mode, we must be able to detect new connections. | |
| 302 | + * The user can force us to poll by disabling remote wakeup; | |
| 303 | + * otherwise we will use the EGSM/RD mechanism. | |
| 304 | 304 | */ |
| 305 | 305 | if (auto_stop) { |
| 306 | 306 | if (!device_may_wakeup(&rhdev->dev)) |
| 307 | − int_enable = 0; | |
| 307 | + egsm_enable = int_enable = 0; | |
| 308 | + } | |
| 308 | 309 | |
| 309 | − /* In bus-suspend mode wakeups may be disabled, but if they are | |
| 310 | − * allowed then so are Resume-Detect interrupts. | |
| 311 | − */ | |
| 312 | − } else { | |
| 313 | 310 | #ifdef CONFIG_PM |
| 311 | + /* | |
| 312 | + * In bus-suspend mode, we use the wakeup setting specified | |
| 313 | + * for the root hub. | |
| 314 | + */ | |
| 315 | + else { | |
| 314 | 316 | if (!rhdev->do_remote_wakeup) |
| 315 | 317 | wakeup_enable = 0; |
| 316 | −#endif | |
| 317 | 318 | } |
| 319 | +#endif | |
| 318 | 320 | |
| 319 | − /* EGSM causes the root hub to echo a 'K' signal (resume) out any | |
| 320 | − * port which requests a remote wakeup. According to the USB spec, | |
| 321 | − * every hub is supposed to do this. But if we are ignoring | |
| 322 | − * remote-wakeup requests anyway then there's no point to it. | |
| 323 | − * We also shouldn't enable EGSM if it's broken. | |
| 324 | − */ | |
| 325 | − if (!wakeup_enable || global_suspend_mode_is_broken(uhci)) | |
| 326 | − egsm_enable = 0; | |
| 327 | − | |
| 328 | − /* If we're ignoring wakeup events then there's no reason to | |
| 329 | − * enable Resume-Detect interrupts. We also shouldn't enable | |
| 330 | − * them if they are broken or disallowed. | |
| 321 | + /* | |
| 322 | + * UHCI doesn't distinguish between wakeup requests from downstream | |
| 323 | + * devices and local connect/disconnect events. There's no way to | |
| 324 | + * enable one without the other; both are controlled by EGSM. Thus | |
| 325 | + * if wakeups are disallowed then EGSM must be turned off -- in which | |
| 326 | + * case remote wakeup requests from downstream during system sleep | |
| 327 | + * will be lost. | |
| 328 | + * | |
| 329 | + * In addition, if EGSM is broken then we can't use it. Likewise, | |
| 330 | + * if Resume-Detect interrupts are broken then we can't use them. | |
| 331 | 331 | * |
| 332 | − * This logic may lead us to enabling RD but not EGSM. The UHCI | |
| 333 | − * spec foolishly says that RD works only when EGSM is on, but | |
| 334 | − * there's no harm in enabling it anyway -- perhaps some chips | |
| 335 | − * will implement it! | |
| 332 | + * Finally, neither EGSM nor RD is useful by itself. Without EGSM, | |
| 333 | + * the RD status bit will never get set. Without RD, the controller | |
| 334 | + * won't generate interrupts to tell the system about wakeup events. | |
| 336 | 335 | */ |
| 337 | − if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) || | |
| 338 | − !int_enable) | |
| 339 | − uhci->RD_enable = int_enable = 0; | |
| 336 | + if (!wakeup_enable || global_suspend_mode_is_broken(uhci) || | |
| 337 | + resume_detect_interrupts_are_broken(uhci)) | |
| 338 | + egsm_enable = int_enable = 0; | |
| 340 | 339 | |
| 340 | + uhci->RD_enable = !!int_enable; | |
| 341 | 341 | uhci_writew(uhci, int_enable, USBINTR); |
| 342 | 342 | uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD); |
| 343 | 343 | mb(); |
| @@ -364,10 +364,12 @@ __acquires(uhci->lock) · 20 unmodified lines | ||
| 364 | 364 | uhci->rh_state = new_state; |
| 365 | 365 | uhci->is_stopped = UHCI_IS_STOPPED; |
| 366 | 366 | |
| 367 | − /* If interrupts don't work and remote wakeup is enabled then | |
| 368 | − * the suspended root hub needs to be polled. | |
| 367 | + /* | |
| 368 | + * If remote wakeup is enabled but either EGSM or RD interrupts | |
| 369 | + * doesn't work, then we won't get an interrupt when a wakeup event | |
| 370 | + * occurs. Thus the suspended root hub needs to be polled. | |
| 369 | 371 | */ |
| 370 | − if (!int_enable && wakeup_enable) | |
| 372 | + if (wakeup_enable && (!int_enable || !egsm_enable)) | |
| 371 | 373 | set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
| 372 | 374 | else |
| 373 | 375 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
| @@ -280,7 +280,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, · 279 unmodified lines | ||
| 280 | 280 | qh->load = usb_calc_bus_time(udev->speed, |
| 281 | 281 | usb_endpoint_dir_in(&hep->desc), |
| 282 | 282 | qh->type == USB_ENDPOINT_XFER_ISOC, |
| 283 | − le16_to_cpu(hep->desc.wMaxPacketSize)) | |
| 283 | + usb_endpoint_maxp(&hep->desc)) | |
| 284 | 284 | / 1000 + 1; |
| 285 | 285 | |
| 286 | 286 | } else { /* Skeleton QH */ |
| @@ -792,7 +792,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, · 505 unmodified lines | ||
| 792 | 792 | { |
| 793 | 793 | struct uhci_td *td; |
| 794 | 794 | unsigned long destination, status; |
| 795 | − int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); | |
| 795 | + int maxsze = usb_endpoint_maxp(&qh->hep->desc); | |
| 796 | 796 | int len = urb->transfer_buffer_length; |
| 797 | 797 | dma_addr_t data = urb->transfer_dma; |
| 798 | 798 | __hc32 *plink; |
| @@ -918,7 +918,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, · 119 unmodified lines | ||
| 918 | 918 | { |
| 919 | 919 | struct uhci_td *td; |
| 920 | 920 | unsigned long destination, status; |
| 921 | − int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); | |
| 921 | + int maxsze = usb_endpoint_maxp(&qh->hep->desc); | |
| 922 | 922 | int len = urb->transfer_buffer_length; |
| 923 | 923 | int this_sg_len; |
| 924 | 924 | dma_addr_t data; |
| @@ -65,6 +65,12 @@ · 64 unmodified lines | ||
| 65 | 65 | /* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ |
| 66 | 66 | #define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) |
| 67 | 67 | |
| 68 | +/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ | |
| 69 | +#define XHCI_L1C (1 << 16) | |
| 70 | + | |
| 71 | +/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ | |
| 72 | +#define XHCI_HLC (1 << 19) | |
| 73 | + | |
| 68 | 74 | /* command register values to disable interrupts and halt the HC */ |
| 69 | 75 | /* start/stop HC execution - do not write unless HC is halted*/ |
| 70 | 76 | #define XHCI_CMD_RUN (1 << 0) |
| @@ -28,6 +28,25 @@ · 27 unmodified lines | ||
| 28 | 28 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ |
| 29 | 29 | PORT_RC | PORT_PLC | PORT_PE) |
| 30 | 30 | |
| 31 | +/* usb 1.1 root hub device descriptor */ | |
| 32 | +static u8 usb_bos_descriptor [] = { | |
| 33 | + USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */ | |
| 34 | + USB_DT_BOS, /* __u8 bDescriptorType */ | |
| 35 | + 0x0F, 0x00, /* __le16 wTotalLength, 15 bytes */ | |
| 36 | + 0x1, /* __u8 bNumDeviceCaps */ | |
| 37 | + /* First device capability */ | |
| 38 | + USB_DT_USB_SS_CAP_SIZE, /* __u8 bLength, 10 bytes */ | |
| 39 | + USB_DT_DEVICE_CAPABILITY, /* Device Capability */ | |
| 40 | + USB_SS_CAP_TYPE, /* bDevCapabilityType, SUPERSPEED_USB */ | |
| 41 | + 0x00, /* bmAttributes, LTM off by default */ | |
| 42 | + USB_5GBPS_OPERATION, 0x00, /* wSpeedsSupported, 5Gbps only */ | |
| 43 | + 0x03, /* bFunctionalitySupport, | |
| 44 | + USB 3.0 speed only */ | |
| 45 | + 0x00, /* bU1DevExitLat, set later. */ | |
| 46 | + 0x00, 0x00 /* __le16 bU2DevExitLat, set later. */ | |
| 47 | +}; | |
| 48 | + | |
| 49 | + | |
| 31 | 50 | static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, |
| 32 | 51 | struct usb_hub_descriptor *desc, int ports) |
| 33 | 52 | { |
| @@ -232,7 +251,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, · 198 unmodified lines | ||
| 232 | 251 | continue; |
| 233 | 252 | speed = xhci->devs[i]->udev->speed; |
| 234 | 253 | if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3)) |
| 235 | − && xhci->devs[i]->port == port) { | |
| 254 | + && xhci->devs[i]->fake_port == port) { | |
| 236 | 255 | slot_id = i; |
| 237 | 256 | break; |
| 238 | 257 | } |
| @@ -392,13 +411,39 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array) · 153 unmodified lines | ||
| 392 | 411 | return max_ports; |
| 393 | 412 | } |
| 394 | 413 | |
| 414 | +void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | |
| 415 | + int port_id, u32 link_state) | |
| 416 | +{ | |
| 417 | + u32 temp; | |
| 418 | + | |
| 419 | + temp = xhci_readl(xhci, port_array[port_id]); | |
| 420 | + temp = xhci_port_state_to_neutral(temp); | |
| 421 | + temp &= ~PORT_PLS_MASK; | |
| 422 | + temp |= PORT_LINK_STROBE | link_state; | |
| 423 | + xhci_writel(xhci, temp, port_array[port_id]); | |
| 424 | +} | |
| 425 | + | |
| 426 | +/* Test and clear port RWC bit */ | |
| 427 | +void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | |
| 428 | + int port_id, u32 port_bit) | |
| 429 | +{ | |
| 430 | + u32 temp; | |
| 431 | + | |
| 432 | + temp = xhci_readl(xhci, port_array[port_id]); | |
| 433 | + if (temp & port_bit) { | |
| 434 | + temp = xhci_port_state_to_neutral(temp); | |
| 435 | + temp |= port_bit; | |
| 436 | + xhci_writel(xhci, temp, port_array[port_id]); | |
| 437 | + } | |
| 438 | +} | |
| 439 | + | |
| 395 | 440 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
| 396 | 441 | u16 wIndex, char *buf, u16 wLength) |
| 397 | 442 | { |
| 398 | 443 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| 399 | 444 | int max_ports; |
| 400 | 445 | unsigned long flags; |
| 401 | − u32 temp, temp1, status; | |
| 446 | + u32 temp, status; | |
| 402 | 447 | int retval = 0; |
| 403 | 448 | __le32 __iomem **port_array; |
| 404 | 449 | int slot_id; |
| @@ -429,6 +474,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 24 unmodified lines | ||
| 429 | 474 | xhci_hub_descriptor(hcd, xhci, |
| 430 | 475 | (struct usb_hub_descriptor *) buf); |
| 431 | 476 | break; |
| 477 | + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: | |
| 478 | + if ((wValue & 0xff00) != (USB_DT_BOS << 8)) | |
| 479 | + goto error; | |
| 480 | + | |
| 481 | + if (hcd->speed != HCD_USB3) | |
| 482 | + goto error; | |
| 483 | + | |
| 484 | + memcpy(buf, &usb_bos_descriptor, | |
| 485 | + USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); | |
| 486 | + temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); | |
| 487 | + buf[12] = HCS_U1_LATENCY(temp); | |
| 488 | + put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); | |
| 489 | + | |
| 490 | + spin_unlock_irqrestore(&xhci->lock, flags); | |
| 491 | + return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; | |
| 432 | 492 | case GetPortStatus: |
| 433 | 493 | if (!wIndex || wIndex > max_ports) |
| 434 | 494 | goto error; |
| @@ -472,11 +532,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 37 unmodified lines | ||
| 472 | 532 | xhci_dbg(xhci, "Resume USB2 port %d\n", |
| 473 | 533 | wIndex + 1); |
| 474 | 534 | bus_state->resume_done[wIndex] = 0; |
| 475 | − temp1 = xhci_port_state_to_neutral(temp); | |
| 476 | − temp1 &= ~PORT_PLS_MASK; | |
| 477 | − temp1 |= PORT_LINK_STROBE | XDEV_U0; | |
| 478 | − xhci_writel(xhci, temp1, port_array[wIndex]); | |
| 479 | − | |
| 535 | + xhci_set_link_state(xhci, port_array, wIndex, | |
| 536 | + XDEV_U0); | |
| 480 | 537 | xhci_dbg(xhci, "set port %d resume\n", |
| 481 | 538 | wIndex + 1); |
| 482 | 539 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, |
| @@ -551,10 +608,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 68 unmodified lines | ||
| 551 | 608 | switch (wValue) { |
| 552 | 609 | case USB_PORT_FEAT_SUSPEND: |
| 553 | 610 | temp = xhci_readl(xhci, port_array[wIndex]); |
| 611 | + if ((temp & PORT_PLS_MASK) != XDEV_U0) { | |
| 612 | + /* Resume the port to U0 first */ | |
| 613 | + xhci_set_link_state(xhci, port_array, wIndex, | |
| 614 | + XDEV_U0); | |
| 615 | + spin_unlock_irqrestore(&xhci->lock, flags); | |
| 616 | + msleep(10); | |
| 617 | + spin_lock_irqsave(&xhci->lock, flags); | |
| 618 | + } | |
| 554 | 619 | /* In spec software should not attempt to suspend |
| 555 | 620 | * a port unless the port reports that it is in the |
| 556 | 621 | * enabled (PED = ‘1’,PLS < ‘3’) state. |
| 557 | 622 | */ |
| 623 | + temp = xhci_readl(xhci, port_array[wIndex]); | |
| 558 | 624 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) |
| 559 | 625 | || (temp & PORT_PLS_MASK) >= XDEV_U3) { |
| 560 | 626 | xhci_warn(xhci, "USB core suspending device " |
| @@ -573,10 +639,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 12 unmodified lines | ||
| 573 | 639 | xhci_stop_device(xhci, slot_id, 1); |
| 574 | 640 | spin_lock_irqsave(&xhci->lock, flags); |
| 575 | 641 | |
| 576 | − temp = xhci_port_state_to_neutral(temp); | |
| 577 | − temp &= ~PORT_PLS_MASK; | |
| 578 | − temp |= PORT_LINK_STROBE | XDEV_U3; | |
| 579 | − xhci_writel(xhci, temp, port_array[wIndex]); | |
| 642 | + xhci_set_link_state(xhci, port_array, wIndex, XDEV_U3); | |
| 580 | 643 | |
| 581 | 644 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 582 | 645 | msleep(10); /* wait device to enter */ |
| @@ -610,10 +673,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 27 unmodified lines | ||
| 610 | 673 | } |
| 611 | 674 | } |
| 612 | 675 | |
| 613 | − temp = xhci_port_state_to_neutral(temp); | |
| 614 | − temp &= ~PORT_PLS_MASK; | |
| 615 | − temp |= PORT_LINK_STROBE | link_state; | |
| 616 | − xhci_writel(xhci, temp, port_array[wIndex]); | |
| 676 | + xhci_set_link_state(xhci, port_array, wIndex, | |
| 677 | + link_state); | |
| 617 | 678 | |
| 618 | 679 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 619 | 680 | msleep(20); /* wait device to enter */ |
| @@ -677,24 +738,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 57 unmodified lines | ||
| 677 | 738 | if ((temp & PORT_PE) == 0) |
| 678 | 739 | goto error; |
| 679 | 740 | |
| 680 | − temp = xhci_port_state_to_neutral(temp); | |
| 681 | − temp &= ~PORT_PLS_MASK; | |
| 682 | − temp |= PORT_LINK_STROBE | XDEV_RESUME; | |
| 683 | − xhci_writel(xhci, temp, | |
| 684 | − port_array[wIndex]); | |
| 685 | − | |
| 686 | − spin_unlock_irqrestore(&xhci->lock, | |
| 687 | − flags); | |
| 741 | + xhci_set_link_state(xhci, port_array, wIndex, | |
| 742 | + XDEV_RESUME); | |
| 743 | + spin_unlock_irqrestore(&xhci->lock, flags); | |
| 688 | 744 | msleep(20); |
| 689 | 745 | spin_lock_irqsave(&xhci->lock, flags); |
| 690 | − | |
| 691 | − temp = xhci_readl(xhci, | |
| 692 | − port_array[wIndex]); | |
| 693 | − temp = xhci_port_state_to_neutral(temp); | |
| 694 | − temp &= ~PORT_PLS_MASK; | |
| 695 | − temp |= PORT_LINK_STROBE | XDEV_U0; | |
| 696 | − xhci_writel(xhci, temp, | |
| 697 | − port_array[wIndex]); | |
| 746 | + xhci_set_link_state(xhci, port_array, wIndex, | |
| 747 | + XDEV_U0); | |
| 698 | 748 | } |
| 699 | 749 | bus_state->port_c_suspend |= 1 << wIndex; |
| 700 | 750 | |
| @@ -910,25 +960,18 @@ int xhci_bus_resume(struct usb_hcd *hcd) · 209 unmodified lines | ||
| 910 | 960 | if (test_bit(port_index, &bus_state->bus_suspended) && |
| 911 | 961 | (temp & PORT_PLS_MASK)) { |
| 912 | 962 | if (DEV_SUPERSPEED(temp)) { |
| 913 | − temp = xhci_port_state_to_neutral(temp); | |
| 914 | − temp &= ~PORT_PLS_MASK; | |
| 915 | − temp |= PORT_LINK_STROBE | XDEV_U0; | |
| 916 | − xhci_writel(xhci, temp, port_array[port_index]); | |
| 963 | + xhci_set_link_state(xhci, port_array, | |
| 964 | + port_index, XDEV_U0); | |
| 917 | 965 | } else { |
| 918 | − temp = xhci_port_state_to_neutral(temp); | |
| 919 | − temp &= ~PORT_PLS_MASK; | |
| 920 | − temp |= PORT_LINK_STROBE | XDEV_RESUME; | |
| 921 | − xhci_writel(xhci, temp, port_array[port_index]); | |
| 966 | + xhci_set_link_state(xhci, port_array, | |
| 967 | + port_index, XDEV_RESUME); | |
| 922 | 968 | |
| 923 | 969 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 924 | 970 | msleep(20); |
| 925 | 971 | spin_lock_irqsave(&xhci->lock, flags); |
| 926 | 972 | |
| 927 | − temp = xhci_readl(xhci, port_array[port_index]); | |
| 928 | − temp = xhci_port_state_to_neutral(temp); | |
| 929 | − temp &= ~PORT_PLS_MASK; | |
| 930 | − temp |= PORT_LINK_STROBE | XDEV_U0; | |
| 931 | − xhci_writel(xhci, temp, port_array[port_index]); | |
| 973 | + xhci_set_link_state(xhci, port_array, | |
| 974 | + port_index, XDEV_U0); | |
| 932 | 975 | } |
| 933 | 976 | /* wait for the port to enter U0 and report port link |
| 934 | 977 | * state change. |
| @@ -938,12 +981,8 @@ int xhci_bus_resume(struct usb_hcd *hcd) · 3 unmodified lines | ||
| 938 | 981 | spin_lock_irqsave(&xhci->lock, flags); |
| 939 | 982 | |
| 940 | 983 | /* Clear PLC */ |
| 941 | − temp = xhci_readl(xhci, port_array[port_index]); | |
| 942 | − if (temp & PORT_PLC) { | |
| 943 | − temp = xhci_port_state_to_neutral(temp); | |
| 944 | − temp |= PORT_PLC; | |
| 945 | − xhci_writel(xhci, temp, port_array[port_index]); | |
| 946 | − } | |
| 984 | + xhci_test_and_clear_bit(xhci, port_array, port_index, | |
| 985 | + PORT_PLC); | |
| 947 | 986 | |
| 948 | 987 | slot_id = xhci_find_slot_id_by_port(hcd, |
| 949 | 988 | xhci, port_index + 1); |
| @@ -61,8 +61,6 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, gfp_t flag · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) |
| 63 | 63 | { |
| 64 | − if (!seg) | |
| 65 | − return; | |
| 66 | 64 | if (seg->trbs) { |
| 67 | 65 | xhci_dbg(xhci, "Freeing DMA segment at %p (virtual) 0x%llx (DMA)\n", |
| 68 | 66 | seg->trbs, (unsigned long long)seg->dma); |
| @@ -81,7 +79,7 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) · 12 unmodified lines | ||
| 81 | 79 | * related flags, such as End TRB, Toggle Cycle, and no snoop. |
| 82 | 80 | */ |
| 83 | 81 | static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, |
| 84 | − struct xhci_segment *next, bool link_trbs) | |
| 82 | + struct xhci_segment *next, bool link_trbs, bool isoc) | |
| 85 | 83 | { |
| 86 | 84 | u32 val; |
| 87 | 85 | |
| @@ -97,7 +95,9 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, · 9 unmodified lines | ||
| 97 | 95 | val &= ~TRB_TYPE_BITMASK; |
| 98 | 96 | val |= TRB_TYPE(TRB_LINK); |
| 99 | 97 | /* Always set the chain bit with 0.95 hardware */ |
| 100 | − if (xhci_link_trb_quirk(xhci)) | |
| 98 | + /* Set chain bit for isoc rings on AMD 0.96 host */ | |
| 99 | + if (xhci_link_trb_quirk(xhci) || | |
| 100 | + (isoc && (xhci->quirks & XHCI_AMD_0x96_HOST))) | |
| 101 | 101 | val |= TRB_CHAIN; |
| 102 | 102 | prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); |
| 103 | 103 | } |
| @@ -112,18 +112,20 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) · 8 unmodified lines | ||
| 112 | 112 | struct xhci_segment *seg; |
| 113 | 113 | struct xhci_segment *first_seg; |
| 114 | 114 | |
| 115 | − if (!ring || !ring->first_seg) | |
| 115 | + if (!ring) | |
| 116 | 116 | return; |
| 117 | − first_seg = ring->first_seg; | |
| 118 | − seg = first_seg->next; | |
| 119 | − xhci_dbg(xhci, "Freeing ring at %p\n", ring); | |
| 120 | − while (seg != first_seg) { | |
| 121 | − struct xhci_segment *next = seg->next; | |
| 122 | − xhci_segment_free(xhci, seg); | |
| 123 | − seg = next; | |
| 117 | + if (ring->first_seg) { | |
| 118 | + first_seg = ring->first_seg; | |
| 119 | + seg = first_seg->next; | |
| 120 | + xhci_dbg(xhci, "Freeing ring at %p\n", ring); | |
| 121 | + while (seg != first_seg) { | |
| 122 | + struct xhci_segment *next = seg->next; | |
| 123 | + xhci_segment_free(xhci, seg); | |
| 124 | + seg = next; | |
| 125 | + } | |
| 126 | + xhci_segment_free(xhci, first_seg); | |
| 127 | + ring->first_seg = NULL; | |
| 124 | 128 | } |
| 125 | − xhci_segment_free(xhci, first_seg); | |
| 126 | − ring->first_seg = NULL; | |
| 127 | 129 | kfree(ring); |
| 128 | 130 | } |
| 129 | 131 | |
| @@ -152,7 +154,7 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring) · 22 unmodified lines | ||
| 152 | 154 | * See section 4.9.1 and figures 15 and 16. |
| 153 | 155 | */ |
| 154 | 156 | static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, |
| 155 | − unsigned int num_segs, bool link_trbs, gfp_t flags) | |
| 157 | + unsigned int num_segs, bool link_trbs, bool isoc, gfp_t flags) | |
| 156 | 158 | { |
| 157 | 159 | struct xhci_ring *ring; |
| 158 | 160 | struct xhci_segment *prev; |
| @@ -178,12 +180,12 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, · 19 unmodified lines | ||
| 178 | 180 | next = xhci_segment_alloc(xhci, flags); |
| 179 | 181 | if (!next) |
| 180 | 182 | goto fail; |
| 181 | − xhci_link_segments(xhci, prev, next, link_trbs); | |
| 183 | + xhci_link_segments(xhci, prev, next, link_trbs, isoc); | |
| 182 | 184 | |
| 183 | 185 | prev = next; |
| 184 | 186 | num_segs--; |
| 185 | 187 | } |
| 186 | − xhci_link_segments(xhci, prev, ring->first_seg, link_trbs); | |
| 188 | + xhci_link_segments(xhci, prev, ring->first_seg, link_trbs, isoc); | |
| 187 | 189 | |
| 188 | 190 | if (link_trbs) { |
| 189 | 191 | /* See section 4.9.2.1 and 6.4.4.1 */ |
| @@ -229,14 +231,14 @@ void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci, · 39 unmodified lines | ||
| 229 | 231 | * pointers to the beginning of the ring. |
| 230 | 232 | */ |
| 231 | 233 | static void xhci_reinit_cached_ring(struct xhci_hcd *xhci, |
| 232 | − struct xhci_ring *ring) | |
| 234 | + struct xhci_ring *ring, bool isoc) | |
| 233 | 235 | { |
| 234 | 236 | struct xhci_segment *seg = ring->first_seg; |
| 235 | 237 | do { |
| 236 | 238 | memset(seg->trbs, 0, |
| 237 | 239 | sizeof(union xhci_trb)*TRBS_PER_SEGMENT); |
| 238 | 240 | /* All endpoint rings have link TRBs */ |
| 239 | − xhci_link_segments(xhci, seg, seg->next, 1); | |
| 241 | + xhci_link_segments(xhci, seg, seg->next, 1, isoc); | |
| 240 | 242 | seg = seg->next; |
| 241 | 243 | } while (seg != ring->first_seg); |
| 242 | 244 | xhci_initialize_ring_info(ring); |
| @@ -315,7 +317,7 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, · 72 unmodified lines | ||
| 315 | 317 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
| 316 | 318 | |
| 317 | 319 | if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) |
| 318 | − pci_free_consistent(pdev, | |
| 320 | + dma_free_coherent(&pdev->dev, | |
| 319 | 321 | sizeof(struct xhci_stream_ctx)*num_stream_ctxs, |
| 320 | 322 | stream_ctx, dma); |
| 321 | 323 | else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE) |
| @@ -343,9 +345,9 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, · 21 unmodified lines | ||
| 343 | 345 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
| 344 | 346 | |
| 345 | 347 | if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) |
| 346 | − return pci_alloc_consistent(pdev, | |
| 348 | + return dma_alloc_coherent(&pdev->dev, | |
| 347 | 349 | sizeof(struct xhci_stream_ctx)*num_stream_ctxs, |
| 348 | − dma); | |
| 350 | + dma, mem_flags); | |
| 349 | 351 | else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE) |
| 350 | 352 | return dma_pool_alloc(xhci->small_streams_pool, |
| 351 | 353 | mem_flags, dma); |
| @@ -540,7 +542,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, · 188 unmodified lines | ||
| 540 | 542 | */ |
| 541 | 543 | for (cur_stream = 1; cur_stream < num_streams; cur_stream++) { |
| 542 | 544 | stream_info->stream_rings[cur_stream] = |
| 543 | − xhci_ring_alloc(xhci, 1, true, mem_flags); | |
| 545 | + xhci_ring_alloc(xhci, 1, true, false, mem_flags); | |
| 544 | 546 | cur_ring = stream_info->stream_rings[cur_stream]; |
| 545 | 547 | if (!cur_ring) |
| 546 | 548 | goto cleanup_rings; |
| @@ -687,11 +689,103 @@ static void xhci_init_endpoint_timer(struct xhci_hcd *xhci, · 140 unmodified lines | ||
| 687 | 689 | ep->xhci = xhci; |
| 688 | 690 | } |
| 689 | 691 | |
| 690 | −/* All the xhci_tds in the ring's TD list should be freed at this point */ | |
| 692 | +static void xhci_free_tt_info(struct xhci_hcd *xhci, | |
| 693 | + struct xhci_virt_device *virt_dev, | |
| 694 | + int slot_id) | |
| 695 | +{ | |
| 696 | + struct list_head *tt; | |
| 697 | + struct list_head *tt_list_head; | |
| 698 | + struct list_head *tt_next; | |
| 699 | + struct xhci_tt_bw_info *tt_info; | |
| 700 | + | |
| 701 | + /* If the device never made it past the Set Address stage, | |
| 702 | + * it may not have the real_port set correctly. | |
| 703 | + */ | |
| 704 | + if (virt_dev->real_port == 0 || | |
| 705 | + virt_dev->real_port > HCS_MAX_PORTS(xhci->hcs_params1)) { | |
| 706 | + xhci_dbg(xhci, "Bad real port.\n"); | |
| 707 | + return; | |
| 708 | + } | |
| 709 | + | |
| 710 | + tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts); | |
| 711 | + if (list_empty(tt_list_head)) | |
| 712 | + return; | |
| 713 | + | |
| 714 | + list_for_each(tt, tt_list_head) { | |
| 715 | + tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); | |
| 716 | + if (tt_info->slot_id == slot_id) | |
| 717 | + break; | |
| 718 | + } | |
| 719 | + /* Cautionary measure in case the hub was disconnected before we | |
| 720 | + * stored the TT information. | |
| 721 | + */ | |
| 722 | + if (tt_info->slot_id != slot_id) | |
| 723 | + return; | |
| 724 | + | |
| 725 | + tt_next = tt->next; | |
| 726 | + tt_info = list_entry(tt, struct xhci_tt_bw_info, | |
| 727 | + tt_list); | |
| 728 | + /* Multi-TT hubs will have more than one entry */ | |
| 729 | + do { | |
| 730 | + list_del(tt); | |
| 731 | + kfree(tt_info); | |
| 732 | + tt = tt_next; | |
| 733 | + if (list_empty(tt_list_head)) | |
| 734 | + break; | |
| 735 | + tt_next = tt->next; | |
| 736 | + tt_info = list_entry(tt, struct xhci_tt_bw_info, | |
| 737 | + tt_list); | |
| 738 | + } while (tt_info->slot_id == slot_id); | |
| 739 | +} | |
| 740 | + | |
| 741 | +int xhci_alloc_tt_info(struct xhci_hcd *xhci, | |
| 742 | + struct xhci_virt_device *virt_dev, | |
| 743 | + struct usb_device *hdev, | |
| 744 | + struct usb_tt *tt, gfp_t mem_flags) | |
| 745 | +{ | |
| 746 | + struct xhci_tt_bw_info *tt_info; | |
| 747 | + unsigned int num_ports; | |
| 748 | + int i, j; | |
| 749 | + | |
| 750 | + if (!tt->multi) | |
| 751 | + num_ports = 1; | |
| 752 | + else | |
| 753 | + num_ports = hdev->maxchild; | |
| 754 | + | |
| 755 | + for (i = 0; i < num_ports; i++, tt_info++) { | |
| 756 | + struct xhci_interval_bw_table *bw_table; | |
| 757 | + | |
| 758 | + tt_info = kzalloc(sizeof(*tt_info), mem_flags); | |
| 759 | + if (!tt_info) | |
| 760 | + goto free_tts; | |
| 761 | + INIT_LIST_HEAD(&tt_info->tt_list); | |
| 762 | + list_add(&tt_info->tt_list, | |
| 763 | + &xhci->rh_bw[virt_dev->real_port - 1].tts); | |
| 764 | + tt_info->slot_id = virt_dev->udev->slot_id; | |
| 765 | + if (tt->multi) | |
| 766 | + tt_info->ttport = i+1; | |
| 767 | + bw_table = &tt_info->bw_table; | |
| 768 | + for (j = 0; j < XHCI_MAX_INTERVAL; j++) | |
| 769 | + INIT_LIST_HEAD(&bw_table->interval_bw[j].endpoints); | |
| 770 | + } | |
| 771 | + return 0; | |
| 772 | + | |
| 773 | +free_tts: | |
| 774 | + xhci_free_tt_info(xhci, virt_dev, virt_dev->udev->slot_id); | |
| 775 | + return -ENOMEM; | |
| 776 | +} | |
| 777 | + | |
| 778 | + | |
| 779 | +/* All the xhci_tds in the ring's TD list should be freed at this point. | |
| 780 | + * Should be called with xhci->lock held if there is any chance the TT lists | |
| 781 | + * will be manipulated by the configure endpoint, allocate device, or update | |
| 782 | + * hub functions while this function is removing the TT entries from the list. | |
| 783 | + */ | |
| 691 | 784 | void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) |
| 692 | 785 | { |
| 693 | 786 | struct xhci_virt_device *dev; |
| 694 | 787 | int i; |
| 788 | + int old_active_eps = 0; | |
| 695 | 789 | |
| 696 | 790 | /* Slot ID 0 is reserved */ |
| 697 | 791 | if (slot_id == 0 || !xhci->devs[slot_id]) |
| @@ -702,13 +796,29 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) · 4 unmodified lines | ||
| 702 | 796 | if (!dev) |
| 703 | 797 | return; |
| 704 | 798 | |
| 799 | + if (dev->tt_info) | |
| 800 | + old_active_eps = dev->tt_info->active_eps; | |
| 801 | + | |
| 705 | 802 | for (i = 0; i < 31; ++i) { |
| 706 | 803 | if (dev->eps[i].ring) |
| 707 | 804 | xhci_ring_free(xhci, dev->eps[i].ring); |
| 708 | 805 | if (dev->eps[i].stream_info) |
| 709 | 806 | xhci_free_stream_info(xhci, |
| 710 | 807 | dev->eps[i].stream_info); |
| 808 | + /* Endpoints on the TT/root port lists should have been removed | |
| 809 | + * when usb_disable_device() was called for the device. | |
| 810 | + * We can't drop them anyway, because the udev might have gone | |
| 811 | + * away by this point, and we can't tell what speed it was. | |
| 812 | + */ | |
| 813 | + if (!list_empty(&dev->eps[i].bw_endpoint_list)) | |
| 814 | + xhci_warn(xhci, "Slot %u endpoint %u " | |
| 815 | + "not removed from BW list!\n", | |
| 816 | + slot_id, i); | |
| 711 | 817 | } |
| 818 | + /* If this is a hub, free the TT(s) from the TT list */ | |
| 819 | + xhci_free_tt_info(xhci, dev, slot_id); | |
| 820 | + /* If necessary, update the number of active TTs on this root port */ | |
| 821 | + xhci_update_tt_active_eps(xhci, dev, old_active_eps); | |
| 712 | 822 | |
| 713 | 823 | if (dev->ring_cache) { |
| 714 | 824 | for (i = 0; i < dev->num_rings_cached; i++) |
| @@ -762,10 +872,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, · 47 unmodified lines | ||
| 762 | 872 | for (i = 0; i < 31; i++) { |
| 763 | 873 | xhci_init_endpoint_timer(xhci, &dev->eps[i]); |
| 764 | 874 | INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); |
| 875 | + INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list); | |
| 765 | 876 | } |
| 766 | 877 | |
| 767 | 878 | /* Allocate endpoint 0 ring */ |
| 768 | − dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags); | |
| 879 | + dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, false, flags); | |
| 769 | 880 | if (!dev->eps[0].ring) |
| 770 | 881 | goto fail; |
| 771 | 882 | |
| @@ -921,9 +1032,40 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud · 149 unmodified lines | ||
| 921 | 1032 | for (top_dev = udev; top_dev->parent && top_dev->parent->parent; |
| 922 | 1033 | top_dev = top_dev->parent) |
| 923 | 1034 | /* Found device below root hub */; |
| 924 | − dev->port = top_dev->portnum; | |
| 1035 | + dev->fake_port = top_dev->portnum; | |
| 1036 | + dev->real_port = port_num; | |
| 925 | 1037 | xhci_dbg(xhci, "Set root hub portnum to %d\n", port_num); |
| 926 | − xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->port); | |
| 1038 | + xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->fake_port); | |
| 1039 | + | |
| 1040 | + /* Find the right bandwidth table that this device will be a part of. | |
| 1041 | + * If this is a full speed device attached directly to a root port (or a | |
| 1042 | + * decendent of one), it counts as a primary bandwidth domain, not a | |
| 1043 | + * secondary bandwidth domain under a TT. An xhci_tt_info structure | |
| 1044 | + * will never be created for the HS root hub. | |
| 1045 | + */ | |
| 1046 | + if (!udev->tt || !udev->tt->hub->parent) { | |
| 1047 | + dev->bw_table = &xhci->rh_bw[port_num - 1].bw_table; | |
| 1048 | + } else { | |
| 1049 | + struct xhci_root_port_bw_info *rh_bw; | |
| 1050 | + struct xhci_tt_bw_info *tt_bw; | |
| 1051 | + | |
| 1052 | + rh_bw = &xhci->rh_bw[port_num - 1]; | |
| 1053 | + /* Find the right TT. */ | |
| 1054 | + list_for_each_entry(tt_bw, &rh_bw->tts, tt_list) { | |
| 1055 | + if (tt_bw->slot_id != udev->tt->hub->slot_id) | |
| 1056 | + continue; | |
| 1057 | + | |
| 1058 | + if (!dev->udev->tt->multi || | |
| 1059 | + (udev->tt->multi && | |
| 1060 | + tt_bw->ttport == dev->udev->ttport)) { | |
| 1061 | + dev->bw_table = &tt_bw->bw_table; | |
| 1062 | + dev->tt_info = tt_bw; | |
| 1063 | + break; | |
| 1064 | + } | |
| 1065 | + } | |
| 1066 | + if (!dev->tt_info) | |
| 1067 | + xhci_warn(xhci, "WARN: Didn't find a matching TT\n"); | |
| 1068 | + } | |
| 927 | 1069 | |
| 928 | 1070 | /* Is this a LS/FS device under an external HS hub? */ |
| 929 | 1071 | if (udev->tt && udev->tt->hub->parent) { |
| @@ -1141,8 +1283,8 @@ static u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci, · 211 unmodified lines | ||
| 1141 | 1283 | if (udev->speed == USB_SPEED_SUPER) |
| 1142 | 1284 | return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); |
| 1143 | 1285 | |
| 1144 | − max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); | |
| 1145 | − max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) & 0x1800) >> 11; | |
| 1286 | + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); | |
| 1287 | + max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; | |
| 1146 | 1288 | /* A 0 in max burst means 1 transfer per ESIT */ |
| 1147 | 1289 | return max_packet * (max_burst + 1); |
| 1148 | 1290 | } |
| @@ -1175,10 +1317,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, · 26 unmodified lines | ||
| 1175 | 1317 | */ |
| 1176 | 1318 | if (usb_endpoint_xfer_isoc(&ep->desc)) |
| 1177 | 1319 | virt_dev->eps[ep_index].new_ring = |
| 1178 | − xhci_ring_alloc(xhci, 8, true, mem_flags); | |
| 1320 | + xhci_ring_alloc(xhci, 8, true, true, mem_flags); | |
| 1179 | 1321 | else |
| 1180 | 1322 | virt_dev->eps[ep_index].new_ring = |
| 1181 | − xhci_ring_alloc(xhci, 1, true, mem_flags); | |
| 1323 | + xhci_ring_alloc(xhci, 1, true, false, mem_flags); | |
| 1182 | 1324 | if (!virt_dev->eps[ep_index].new_ring) { |
| 1183 | 1325 | /* Attempt to use the ring cache */ |
| 1184 | 1326 | if (virt_dev->num_rings_cached == 0) |
| @@ -1187,7 +1329,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, · 2 unmodified lines | ||
| 1187 | 1329 | virt_dev->ring_cache[virt_dev->num_rings_cached]; |
| 1188 | 1330 | virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; |
| 1189 | 1331 | virt_dev->num_rings_cached--; |
| 1190 | − xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); | |
| 1332 | + xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, | |
| 1333 | + usb_endpoint_xfer_isoc(&ep->desc) ? true : false); | |
| 1191 | 1334 | } |
| 1192 | 1335 | virt_dev->eps[ep_index].skip = false; |
| 1193 | 1336 | ep_ring = virt_dev->eps[ep_index].new_ring; |
| @@ -1211,7 +1354,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, · 17 unmodified lines | ||
| 1211 | 1354 | /* Set the max packet size and max burst */ |
| 1212 | 1355 | switch (udev->speed) { |
| 1213 | 1356 | case USB_SPEED_SUPER: |
| 1214 | − max_packet = le16_to_cpu(ep->desc.wMaxPacketSize); | |
| 1357 | + max_packet = usb_endpoint_maxp(&ep->desc); | |
| 1215 | 1358 | ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); |
| 1216 | 1359 | /* dig out max burst from ep companion desc */ |
| 1217 | 1360 | max_packet = ep->ss_ep_comp.bMaxBurst; |
| @@ -1223,14 +1366,14 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, · 5 unmodified lines | ||
| 1223 | 1366 | */ |
| 1224 | 1367 | if (usb_endpoint_xfer_isoc(&ep->desc) || |
| 1225 | 1368 | usb_endpoint_xfer_int(&ep->desc)) { |
| 1226 | − max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) | |
| 1369 | + max_burst = (usb_endpoint_maxp(&ep->desc) | |
| 1227 | 1370 | & 0x1800) >> 11; |
| 1228 | 1371 | ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst)); |
| 1229 | 1372 | } |
| 1230 | 1373 | /* Fall through */ |
| 1231 | 1374 | case USB_SPEED_FULL: |
| 1232 | 1375 | case USB_SPEED_LOW: |
| 1233 | − max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); | |
| 1376 | + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); | |
| 1234 | 1377 | ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); |
| 1235 | 1378 | break; |
| 1236 | 1379 | default: |
| @@ -1286,6 +1429,70 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, · 49 unmodified lines | ||
| 1286 | 1429 | */ |
| 1287 | 1430 | } |
| 1288 | 1431 | |
| 1432 | +void xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info) | |
| 1433 | +{ | |
| 1434 | + bw_info->ep_interval = 0; | |
| 1435 | + bw_info->mult = 0; | |
| 1436 | + bw_info->num_packets = 0; | |
| 1437 | + bw_info->max_packet_size = 0; | |
| 1438 | + bw_info->type = 0; | |
| 1439 | + bw_info->max_esit_payload = 0; | |
| 1440 | +} | |
| 1441 | + | |
| 1442 | +void xhci_update_bw_info(struct xhci_hcd *xhci, | |
| 1443 | + struct xhci_container_ctx *in_ctx, | |
| 1444 | + struct xhci_input_control_ctx *ctrl_ctx, | |
| 1445 | + struct xhci_virt_device *virt_dev) | |
| 1446 | +{ | |
| 1447 | + struct xhci_bw_info *bw_info; | |
| 1448 | + struct xhci_ep_ctx *ep_ctx; | |
| 1449 | + unsigned int ep_type; | |
| 1450 | + int i; | |
| 1451 | + | |
| 1452 | + for (i = 1; i < 31; ++i) { | |
| 1453 | + bw_info = &virt_dev->eps[i].bw_info; | |
| 1454 | + | |
| 1455 | + /* We can't tell what endpoint type is being dropped, but | |
| 1456 | + * unconditionally clearing the bandwidth info for non-periodic | |
| 1457 | + * endpoints should be harmless because the info will never be | |
| 1458 | + * set in the first place. | |
| 1459 | + */ | |
| 1460 | + if (!EP_IS_ADDED(ctrl_ctx, i) && EP_IS_DROPPED(ctrl_ctx, i)) { | |
| 1461 | + /* Dropped endpoint */ | |
| 1462 | + xhci_clear_endpoint_bw_info(bw_info); | |
| 1463 | + continue; | |
| 1464 | + } | |
| 1465 | + | |
| 1466 | + if (EP_IS_ADDED(ctrl_ctx, i)) { | |
| 1467 | + ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, i); | |
| 1468 | + ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); | |
| 1469 | + | |
| 1470 | + /* Ignore non-periodic endpoints */ | |
| 1471 | + if (ep_type != ISOC_OUT_EP && ep_type != INT_OUT_EP && | |
| 1472 | + ep_type != ISOC_IN_EP && | |
| 1473 | + ep_type != INT_IN_EP) | |
| 1474 | + continue; | |
| 1475 | + | |
| 1476 | + /* Added or changed endpoint */ | |
| 1477 | + bw_info->ep_interval = CTX_TO_EP_INTERVAL( | |
| 1478 | + le32_to_cpu(ep_ctx->ep_info)); | |
| 1479 | + /* Number of packets and mult are zero-based in the | |
| 1480 | + * input context, but we want one-based for the | |
| 1481 | + * interval table. | |
| 1482 | + */ | |
| 1483 | + bw_info->mult = CTX_TO_EP_MULT( | |
| 1484 | + le32_to_cpu(ep_ctx->ep_info)) + 1; | |
| 1485 | + bw_info->num_packets = CTX_TO_MAX_BURST( | |
| 1486 | + le32_to_cpu(ep_ctx->ep_info2)) + 1; | |
| 1487 | + bw_info->max_packet_size = MAX_PACKET_DECODED( | |
| 1488 | + le32_to_cpu(ep_ctx->ep_info2)); | |
| 1489 | + bw_info->type = ep_type; | |
| 1490 | + bw_info->max_esit_payload = CTX_TO_MAX_ESIT_PAYLOAD( | |
| 1491 | + le32_to_cpu(ep_ctx->tx_info)); | |
| 1492 | + } | |
| 1493 | + } | |
| 1494 | +} | |
| 1495 | + | |
| 1289 | 1496 | /* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy. |
| 1290 | 1497 | * Useful when you want to change one particular aspect of the endpoint and then |
| 1291 | 1498 | * issue a configure endpoint command. |
| @@ -1344,10 +1551,9 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) · 52 unmodified lines | ||
| 1344 | 1551 | if (!xhci->scratchpad) |
| 1345 | 1552 | goto fail_sp; |
| 1346 | 1553 | |
| 1347 | − xhci->scratchpad->sp_array = | |
| 1348 | − pci_alloc_consistent(to_pci_dev(dev), | |
| 1554 | + xhci->scratchpad->sp_array = dma_alloc_coherent(dev, | |
| 1349 | 1555 | num_sp * sizeof(u64), |
| 1350 | − &xhci->scratchpad->sp_dma); | |
| 1556 | + &xhci->scratchpad->sp_dma, flags); | |
| 1351 | 1557 | if (!xhci->scratchpad->sp_array) |
| 1352 | 1558 | goto fail_sp2; |
| 1353 | 1559 | |
| @@ -1364,8 +1570,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) · 10 unmodified lines | ||
| 1364 | 1570 | xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); |
| 1365 | 1571 | for (i = 0; i < num_sp; i++) { |
| 1366 | 1572 | dma_addr_t dma; |
| 1367 | − void *buf = pci_alloc_consistent(to_pci_dev(dev), | |
| 1368 | − xhci->page_size, &dma); | |
| 1573 | + void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, | |
| 1574 | + flags); | |
| 1369 | 1575 | if (!buf) |
| 1370 | 1576 | goto fail_sp5; |
| 1371 | 1577 | |
| @@ -1378,7 +1584,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) · 6 unmodified lines | ||
| 1378 | 1584 | |
| 1379 | 1585 | fail_sp5: |
| 1380 | 1586 | for (i = i - 1; i >= 0; i--) { |
| 1381 | − pci_free_consistent(to_pci_dev(dev), xhci->page_size, | |
| 1587 | + dma_free_coherent(dev, xhci->page_size, | |
| 1382 | 1588 | xhci->scratchpad->sp_buffers[i], |
| 1383 | 1589 | xhci->scratchpad->sp_dma_buffers[i]); |
| 1384 | 1590 | } |
| @@ -1388,7 +1594,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) · 3 unmodified lines | ||
| 1388 | 1594 | kfree(xhci->scratchpad->sp_buffers); |
| 1389 | 1595 | |
| 1390 | 1596 | fail_sp3: |
| 1391 | − pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64), | |
| 1597 | + dma_free_coherent(dev, num_sp * sizeof(u64), | |
| 1392 | 1598 | xhci->scratchpad->sp_array, |
| 1393 | 1599 | xhci->scratchpad->sp_dma); |
| 1394 | 1600 | |
| @@ -1412,13 +1618,13 @@ static void scratchpad_free(struct xhci_hcd *xhci) · 17 unmodified lines | ||
| 1412 | 1618 | num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); |
| 1413 | 1619 | |
| 1414 | 1620 | for (i = 0; i < num_sp; i++) { |
| 1415 | − pci_free_consistent(pdev, xhci->page_size, | |
| 1621 | + dma_free_coherent(&pdev->dev, xhci->page_size, | |
| 1416 | 1622 | xhci->scratchpad->sp_buffers[i], |
| 1417 | 1623 | xhci->scratchpad->sp_dma_buffers[i]); |
| 1418 | 1624 | } |
| 1419 | 1625 | kfree(xhci->scratchpad->sp_dma_buffers); |
| 1420 | 1626 | kfree(xhci->scratchpad->sp_buffers); |
| 1421 | − pci_free_consistent(pdev, num_sp * sizeof(u64), | |
| 1627 | + dma_free_coherent(&pdev->dev, num_sp * sizeof(u64), | |
| 1422 | 1628 | xhci->scratchpad->sp_array, |
| 1423 | 1629 | xhci->scratchpad->sp_dma); |
| 1424 | 1630 | kfree(xhci->scratchpad); |
| @@ -1463,18 +1669,10 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, · 38 unmodified lines | ||
| 1463 | 1669 | |
| 1464 | 1670 | void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv) |
| 1465 | 1671 | { |
| 1466 | − int last; | |
| 1467 | − | |
| 1468 | − if (!urb_priv) | |
| 1469 | − return; | |
| 1470 | − | |
| 1471 | − last = urb_priv->length - 1; | |
| 1472 | − if (last >= 0) { | |
| 1473 | − int i; | |
| 1474 | − for (i = 0; i <= last; i++) | |
| 1475 | − kfree(urb_priv->td[i]); | |
| 1672 | + if (urb_priv) { | |
| 1673 | + kfree(urb_priv->td[0]); | |
| 1674 | + kfree(urb_priv); | |
| 1476 | 1675 | } |
| 1477 | − kfree(urb_priv); | |
| 1478 | 1676 | } |
| 1479 | 1677 | |
| 1480 | 1678 | void xhci_free_command(struct xhci_hcd *xhci, |
| @@ -1489,6 +1687,8 @@ void xhci_free_command(struct xhci_hcd *xhci, · 8 unmodified lines | ||
| 1489 | 1687 | void xhci_mem_cleanup(struct xhci_hcd *xhci) |
| 1490 | 1688 | { |
| 1491 | 1689 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
| 1690 | + struct dev_info *dev_info, *next; | |
| 1691 | + unsigned long flags; | |
| 1492 | 1692 | int size; |
| 1493 | 1693 | int i; |
| 1494 | 1694 | |
| @@ -1500,7 +1700,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) · 5 unmodified lines | ||
| 1500 | 1700 | } |
| 1501 | 1701 | size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); |
| 1502 | 1702 | if (xhci->erst.entries) |
| 1503 | − pci_free_consistent(pdev, size, | |
| 1703 | + dma_free_coherent(&pdev->dev, size, | |
| 1504 | 1704 | xhci->erst.entries, xhci->erst.erst_dma_addr); |
| 1505 | 1705 | xhci->erst.entries = NULL; |
| 1506 | 1706 | xhci_dbg(xhci, "Freed ERST\n"); |
| @@ -1540,17 +1740,25 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) · 33 unmodified lines | ||
| 1540 | 1740 | |
| 1541 | 1741 | xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr); |
| 1542 | 1742 | if (xhci->dcbaa) |
| 1543 | − pci_free_consistent(pdev, sizeof(*xhci->dcbaa), | |
| 1743 | + dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa), | |
| 1544 | 1744 | xhci->dcbaa, xhci->dcbaa->dma); |
| 1545 | 1745 | xhci->dcbaa = NULL; |
| 1546 | 1746 | |
| 1547 | 1747 | scratchpad_free(xhci); |
| 1548 | 1748 | |
| 1749 | + spin_lock_irqsave(&xhci->lock, flags); | |
| 1750 | + list_for_each_entry_safe(dev_info, next, &xhci->lpm_failed_devs, list) { | |
| 1751 | + list_del(&dev_info->list); | |
| 1752 | + kfree(dev_info); | |
| 1753 | + } | |
| 1754 | + spin_unlock_irqrestore(&xhci->lock, flags); | |
| 1755 | + | |
| 1549 | 1756 | xhci->num_usb2_ports = 0; |
| 1550 | 1757 | xhci->num_usb3_ports = 0; |
| 1551 | 1758 | kfree(xhci->usb2_ports); |
| 1552 | 1759 | kfree(xhci->usb3_ports); |
| 1553 | 1760 | kfree(xhci->port_array); |
| 1761 | + kfree(xhci->rh_bw); | |
| 1554 | 1762 | |
| 1555 | 1763 | xhci->page_size = 0; |
| 1556 | 1764 | xhci->page_shift = 0; |
| @@ -1762,6 +1970,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, · 205 unmodified lines | ||
| 1762 | 1970 | if (port_offset == 0 || (port_offset + port_count - 1) > num_ports) |
| 1763 | 1971 | /* WTF? "Valid values are ‘1’ to MaxPorts" */ |
| 1764 | 1972 | return; |
| 1973 | + | |
| 1974 | + /* Check the host's USB2 LPM capability */ | |
| 1975 | + if ((xhci->hci_version == 0x96) && (major_revision != 0x03) && | |
| 1976 | + (temp & XHCI_L1C)) { | |
| 1977 | + xhci_dbg(xhci, "xHCI 0.96: support USB2 software lpm\n"); | |
| 1978 | + xhci->sw_lpm_support = 1; | |
| 1979 | + } | |
| 1980 | + | |
| 1981 | + if ((xhci->hci_version >= 0x100) && (major_revision != 0x03)) { | |
| 1982 | + xhci_dbg(xhci, "xHCI 1.0: support USB2 software lpm\n"); | |
| 1983 | + xhci->sw_lpm_support = 1; | |
| 1984 | + if (temp & XHCI_HLC) { | |
| 1985 | + xhci_dbg(xhci, "xHCI 1.0: support USB2 hardware lpm\n"); | |
| 1986 | + xhci->hw_lpm_support = 1; | |
| 1987 | + } | |
| 1988 | + } | |
| 1989 | + | |
| 1765 | 1990 | port_offset--; |
| 1766 | 1991 | for (i = port_offset; i < (port_offset + port_count); i++) { |
| 1767 | 1992 | /* Duplicate entry. Ignore the port if the revisions differ. */ |
| @@ -1806,7 +2031,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) · 38 unmodified lines | ||
| 1806 | 2031 | __le32 __iomem *addr; |
| 1807 | 2032 | u32 offset; |
| 1808 | 2033 | unsigned int num_ports; |
| 1809 | − int i, port_index; | |
| 2034 | + int i, j, port_index; | |
| 1810 | 2035 | |
| 1811 | 2036 | addr = &xhci->cap_regs->hcc_params; |
| 1812 | 2037 | offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); |
| @@ -1821,6 +2046,18 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) · 8 unmodified lines | ||
| 1821 | 2046 | if (!xhci->port_array) |
| 1822 | 2047 | return -ENOMEM; |
| 1823 | 2048 | |
| 2049 | + xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags); | |
| 2050 | + if (!xhci->rh_bw) | |
| 2051 | + return -ENOMEM; | |
| 2052 | + for (i = 0; i < num_ports; i++) { | |
| 2053 | + struct xhci_interval_bw_table *bw_table; | |
| 2054 | + | |
| 2055 | + INIT_LIST_HEAD(&xhci->rh_bw[i].tts); | |
| 2056 | + bw_table = &xhci->rh_bw[i].bw_table; | |
| 2057 | + for (j = 0; j < XHCI_MAX_INTERVAL; j++) | |
| 2058 | + INIT_LIST_HEAD(&bw_table->interval_bw[j].endpoints); | |
| 2059 | + } | |
| 2060 | + | |
| 1824 | 2061 | /* |
| 1825 | 2062 | * For whatever reason, the first capability offset is from the |
| 1826 | 2063 | * capability register base, not from the HCCPARAMS register. |
| @@ -1959,8 +2196,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) · 132 unmodified lines | ||
| 1959 | 2196 | * Section 5.4.8 - doorbell array must be |
| 1960 | 2197 | * "physically contiguous and 64-byte (cache line) aligned". |
| 1961 | 2198 | */ |
| 1962 | − xhci->dcbaa = pci_alloc_consistent(to_pci_dev(dev), | |
| 1963 | − sizeof(*xhci->dcbaa), &dma); | |
| 2199 | + xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, | |
| 2200 | + GFP_KERNEL); | |
| 1964 | 2201 | if (!xhci->dcbaa) |
| 1965 | 2202 | goto fail; |
| 1966 | 2203 | memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); |
| @@ -1994,14 +2231,14 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) · 27 unmodified lines | ||
| 1994 | 2231 | dma_pool_create("xHCI 1KB stream ctx arrays", |
| 1995 | 2232 | dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0); |
| 1996 | 2233 | /* Any stream context array bigger than MEDIUM_STREAM_ARRAY_SIZE |
| 1997 | − * will be allocated with pci_alloc_consistent() | |
| 2234 | + * will be allocated with dma_alloc_coherent() | |
| 1998 | 2235 | */ |
| 1999 | 2236 | |
| 2000 | 2237 | if (!xhci->small_streams_pool || !xhci->medium_streams_pool) |
| 2001 | 2238 | goto fail; |
| 2002 | 2239 | |
| 2003 | 2240 | /* Set up the command ring to have one segments for now. */ |
| 2004 | − xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, flags); | |
| 2241 | + xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, false, flags); | |
| 2005 | 2242 | if (!xhci->cmd_ring) |
| 2006 | 2243 | goto fail; |
| 2007 | 2244 | xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); |
| @@ -2032,14 +2269,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) · 24 unmodified lines | ||
| 2032 | 2269 | * the event ring segment table (ERST). Section 4.9.3. |
| 2033 | 2270 | */ |
| 2034 | 2271 | xhci_dbg(xhci, "// Allocating event ring\n"); |
| 2035 | − xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, flags); | |
| 2272 | + xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, false, | |
| 2273 | + flags); | |
| 2036 | 2274 | if (!xhci->event_ring) |
| 2037 | 2275 | goto fail; |
| 2038 | 2276 | if (xhci_check_trb_in_td_math(xhci, flags) < 0) |
| 2039 | 2277 | goto fail; |
| 2040 | 2278 | |
| 2041 | − xhci->erst.entries = pci_alloc_consistent(to_pci_dev(dev), | |
| 2042 | − sizeof(struct xhci_erst_entry)*ERST_NUM_SEGS, &dma); | |
| 2279 | + xhci->erst.entries = dma_alloc_coherent(dev, | |
| 2280 | + sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma, | |
| 2281 | + GFP_KERNEL); | |
| 2043 | 2282 | if (!xhci->erst.entries) |
| 2044 | 2283 | goto fail; |
| 2045 | 2284 | xhci_dbg(xhci, "// Allocated event ring segment table at 0x%llx\n", |
| @@ -2102,6 +2341,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) · 56 unmodified lines | ||
| 2102 | 2341 | if (xhci_setup_port_arrays(xhci, flags)) |
| 2103 | 2342 | goto fail; |
| 2104 | 2343 | |
| 2344 | + INIT_LIST_HEAD(&xhci->lpm_failed_devs); | |
| 2345 | + | |
| 2105 | 2346 | return 0; |
| 2106 | 2347 | |
| 2107 | 2348 | fail: |
| @@ -51,61 +51,9 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) · 50 unmodified lines | ||
| 51 | 51 | return 0; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | −/* called during probe() after chip reset completes */ | |
| 55 | −static int xhci_pci_setup(struct usb_hcd *hcd) | |
| 54 | +static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) | |
| 56 | 55 | { |
| 57 | − struct xhci_hcd *xhci; | |
| 58 | − struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | |
| 59 | − int retval; | |
| 60 | − u32 temp; | |
| 61 | − | |
| 62 | − hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; | |
| 63 | − | |
| 64 | − if (usb_hcd_is_primary_hcd(hcd)) { | |
| 65 | − xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); | |
| 66 | − if (!xhci) | |
| 67 | − return -ENOMEM; | |
| 68 | − *((struct xhci_hcd **) hcd->hcd_priv) = xhci; | |
| 69 | − xhci->main_hcd = hcd; | |
| 70 | − /* Mark the first roothub as being USB 2.0. | |
| 71 | − * The xHCI driver will register the USB 3.0 roothub. | |
| 72 | − */ | |
| 73 | − hcd->speed = HCD_USB2; | |
| 74 | − hcd->self.root_hub->speed = USB_SPEED_HIGH; | |
| 75 | − /* | |
| 76 | − * USB 2.0 roothub under xHCI has an integrated TT, | |
| 77 | − * (rate matching hub) as opposed to having an OHCI/UHCI | |
| 78 | − * companion controller. | |
| 79 | − */ | |
| 80 | − hcd->has_tt = 1; | |
| 81 | − } else { | |
| 82 | − /* xHCI private pointer was set in xhci_pci_probe for the second | |
| 83 | − * registered roothub. | |
| 84 | − */ | |
| 85 | − xhci = hcd_to_xhci(hcd); | |
| 86 | − temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | |
| 87 | − if (HCC_64BIT_ADDR(temp)) { | |
| 88 | − xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); | |
| 89 | − dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)); | |
| 90 | − } else { | |
| 91 | − dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)); | |
| 92 | − } | |
| 93 | − return 0; | |
| 94 | − } | |
| 95 | − | |
| 96 | − xhci->cap_regs = hcd->regs; | |
| 97 | − xhci->op_regs = hcd->regs + | |
| 98 | − HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase)); | |
| 99 | − xhci->run_regs = hcd->regs + | |
| 100 | − (xhci_readl(xhci, &xhci->cap_regs->run_regs_off) & RTSOFF_MASK); | |
| 101 | − /* Cache read-only capability registers */ | |
| 102 | − xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1); | |
| 103 | − xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2); | |
| 104 | − xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); | |
| 105 | − xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); | |
| 106 | − xhci->hci_version = HC_VERSION(xhci->hcc_params); | |
| 107 | − xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | |
| 108 | − xhci_print_registers(xhci); | |
| 56 | + struct pci_dev *pdev = to_pci_dev(dev); | |
| 109 | 57 | |
| 110 | 58 | /* Look for vendor-specific quirks */ |
| 111 | 59 | if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && |
| @@ -128,6 +76,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd) · 16 unmodified lines | ||
| 128 | 76 | if (pdev->vendor == PCI_VENDOR_ID_NEC) |
| 129 | 77 | xhci->quirks |= XHCI_NEC_HOST; |
| 130 | 78 | |
| 79 | + if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96) | |
| 80 | + xhci->quirks |= XHCI_AMD_0x96_HOST; | |
| 81 | + | |
| 131 | 82 | /* AMD PLL quirk */ |
| 132 | 83 | if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) |
| 133 | 84 | xhci->quirks |= XHCI_AMD_PLL_FIX; |
| @@ -136,39 +87,29 @@ static int xhci_pci_setup(struct usb_hcd *hcd) · 2 unmodified lines | ||
| 136 | 87 | xhci->quirks |= XHCI_SPURIOUS_SUCCESS; |
| 137 | 88 | xhci->quirks |= XHCI_EP_LIMIT_QUIRK; |
| 138 | 89 | xhci->limit_active_eps = 64; |
| 90 | + xhci->quirks |= XHCI_SW_BW_CHECKING; | |
| 139 | 91 | } |
| 140 | 92 | if (pdev->vendor == PCI_VENDOR_ID_ETRON && |
| 141 | 93 | pdev->device == PCI_DEVICE_ID_ASROCK_P67) { |
| 142 | 94 | xhci->quirks |= XHCI_RESET_ON_RESUME; |
| 143 | 95 | xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); |
| 144 | 96 | } |
| 97 | +} | |
| 145 | 98 | |
| 146 | − /* Make sure the HC is halted. */ | |
| 147 | − retval = xhci_halt(xhci); | |
| 148 | − if (retval) | |
| 149 | − goto error; | |
| 99 | +/* called during probe() after chip reset completes */ | |
| 100 | +static int xhci_pci_setup(struct usb_hcd *hcd) | |
| 101 | +{ | |
| 102 | + struct xhci_hcd *xhci; | |
| 103 | + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | |
| 104 | + int retval; | |
| 150 | 105 | |
| 151 | − xhci_dbg(xhci, "Resetting HCD\n"); | |
| 152 | − /* Reset the internal HC memory state and registers. */ | |
| 153 | − retval = xhci_reset(xhci); | |
| 106 | + retval = xhci_gen_setup(hcd, xhci_pci_quirks); | |
| 154 | 107 | if (retval) |
| 155 | − goto error; | |
| 156 | − xhci_dbg(xhci, "Reset complete\n"); | |
| 157 | − | |
| 158 | − temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | |
| 159 | − if (HCC_64BIT_ADDR(temp)) { | |
| 160 | − xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); | |
| 161 | − dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)); | |
| 162 | − } else { | |
| 163 | − dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)); | |
| 164 | − } | |
| 108 | + return retval; | |
| 165 | 109 | |
| 166 | − xhci_dbg(xhci, "Calling HCD init\n"); | |
| 167 | − /* Initialize HCD and host controller data structures. */ | |
| 168 | − retval = xhci_init(hcd); | |
| 169 | − if (retval) | |
| 170 | − goto error; | |
| 171 | − xhci_dbg(xhci, "Called HCD init\n"); | |
| 110 | + xhci = hcd_to_xhci(hcd); | |
| 111 | + if (!usb_hcd_is_primary_hcd(hcd)) | |
| 112 | + return 0; | |
| 172 | 113 | |
| 173 | 114 | pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); |
| 174 | 115 | xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn); |
| @@ -178,7 +119,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd) · 3 unmodified lines | ||
| 178 | 119 | if (!retval) |
| 179 | 120 | return retval; |
| 180 | 121 | |
| 181 | −error: | |
| 182 | 122 | kfree(xhci); |
| 183 | 123 | return retval; |
| 184 | 124 | } |
| @@ -222,7 +162,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 37 unmodified lines | ||
| 222 | 162 | *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; |
| 223 | 163 | |
| 224 | 164 | retval = usb_add_hcd(xhci->shared_hcd, dev->irq, |
| 225 | − IRQF_DISABLED | IRQF_SHARED); | |
| 165 | + IRQF_SHARED); | |
| 226 | 166 | if (retval) |
| 227 | 167 | goto put_usb3_hcd; |
| 228 | 168 | /* Roothub already marked as USB 3.0 speed */ |
| @@ -344,6 +284,11 @@ static const struct hc_driver xhci_pci_hc_driver = { · 115 unmodified lines | ||
| 344 | 284 | .hub_status_data = xhci_hub_status_data, |
| 345 | 285 | .bus_suspend = xhci_bus_suspend, |
| 346 | 286 | .bus_resume = xhci_bus_resume, |
| 287 | + /* | |
| 288 | + * call back when device connected and addressed | |
| 289 | + */ | |
| 290 | + .update_device = xhci_update_device, | |
| 291 | + .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, | |
| 347 | 292 | }; |
| 348 | 293 | |
| 349 | 294 | /*-------------------------------------------------------------------------*/ |
| @@ -375,12 +320,12 @@ static struct pci_driver xhci_pci_driver = { · 25 unmodified lines | ||
| 375 | 320 | #endif |
| 376 | 321 | }; |
| 377 | 322 | |
| 378 | −int xhci_register_pci(void) | |
| 323 | +int __init xhci_register_pci(void) | |
| 379 | 324 | { |
| 380 | 325 | return pci_register_driver(&xhci_pci_driver); |
| 381 | 326 | } |
| 382 | 327 | |
| 383 | −void xhci_unregister_pci(void) | |
| 328 | +void __exit xhci_unregister_pci(void) | |
| 384 | 329 | { |
| 385 | 330 | pci_unregister_driver(&xhci_pci_driver); |
| 386 | 331 | } |
| @@ -185,7 +185,7 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer · 184 unmodified lines | ||
| 185 | 185 | * prepare_transfer()? |
| 186 | 186 | */ |
| 187 | 187 | static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, |
| 188 | − bool consumer, bool more_trbs_coming) | |
| 188 | + bool consumer, bool more_trbs_coming, bool isoc) | |
| 189 | 189 | { |
| 190 | 190 | u32 chain; |
| 191 | 191 | union xhci_trb *next; |
| @@ -212,11 +212,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, · 20 unmodified lines | ||
| 212 | 212 | if (!chain && !more_trbs_coming) |
| 213 | 213 | break; |
| 214 | 214 | |
| 215 | − /* If we're not dealing with 0.95 hardware, | |
| 215 | + /* If we're not dealing with 0.95 hardware or | |
| 216 | + * isoc rings on AMD 0.96 host, | |
| 216 | 217 | * carry over the chain bit of the previous TRB |
| 217 | 218 | * (which may mean the chain bit is cleared). |
| 218 | 219 | */ |
| 219 | − if (!xhci_link_trb_quirk(xhci)) { | |
| 220 | + if (!(isoc && (xhci->quirks & XHCI_AMD_0x96_HOST)) | |
| 221 | + && !xhci_link_trb_quirk(xhci)) { | |
| 220 | 222 | next->link.control &= |
| 221 | 223 | cpu_to_le32(~TRB_CHAIN); |
| 222 | 224 | next->link.control |= |
| @@ -1329,10 +1331,8 @@ static void handle_port_status(struct xhci_hcd *xhci, · 1106 unmodified lines | ||
| 1329 | 1331 | |
| 1330 | 1332 | if (DEV_SUPERSPEED(temp)) { |
| 1331 | 1333 | xhci_dbg(xhci, "resume SS port %d\n", port_id); |
| 1332 | − temp = xhci_port_state_to_neutral(temp); | |
| 1333 | − temp &= ~PORT_PLS_MASK; | |
| 1334 | − temp |= PORT_LINK_STROBE | XDEV_U0; | |
| 1335 | − xhci_writel(xhci, temp, port_array[faked_port_index]); | |
| 1334 | + xhci_set_link_state(xhci, port_array, faked_port_index, | |
| 1335 | + XDEV_U0); | |
| 1336 | 1336 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, |
| 1337 | 1337 | faked_port_index); |
| 1338 | 1338 | if (!slot_id) { |
| @@ -1342,10 +1342,8 @@ static void handle_port_status(struct xhci_hcd *xhci, · 3 unmodified lines | ||
| 1342 | 1342 | xhci_ring_device(xhci, slot_id); |
| 1343 | 1343 | xhci_dbg(xhci, "resume SS port %d finished\n", port_id); |
| 1344 | 1344 | /* Clear PORT_PLC */ |
| 1345 | − temp = xhci_readl(xhci, port_array[faked_port_index]); | |
| 1346 | − temp = xhci_port_state_to_neutral(temp); | |
| 1347 | − temp |= PORT_PLC; | |
| 1348 | − xhci_writel(xhci, temp, port_array[faked_port_index]); | |
| 1345 | + xhci_test_and_clear_bit(xhci, port_array, | |
| 1346 | + faked_port_index, PORT_PLC); | |
| 1349 | 1347 | } else { |
| 1350 | 1348 | xhci_dbg(xhci, "resume HS port %d\n", port_id); |
| 1351 | 1349 | bus_state->resume_done[faked_port_index] = jiffies + |
| @@ -1356,6 +1354,10 @@ static void handle_port_status(struct xhci_hcd *xhci, · 4 unmodified lines | ||
| 1356 | 1354 | } |
| 1357 | 1355 | } |
| 1358 | 1356 | |
| 1357 | + if (hcd->speed != HCD_USB3) | |
| 1358 | + xhci_test_and_clear_bit(xhci, port_array, faked_port_index, | |
| 1359 | + PORT_PLC); | |
| 1360 | + | |
| 1359 | 1361 | cleanup: |
| 1360 | 1362 | /* Update event ring dequeue pointer before dropping the lock */ |
| 1361 | 1363 | inc_deq(xhci, xhci->event_ring, true); |
| @@ -2192,7 +2194,8 @@ cleanup: · 830 unmodified lines | ||
| 2192 | 2194 | if ((urb->actual_length != urb->transfer_buffer_length && |
| 2193 | 2195 | (urb->transfer_flags & |
218 more lines aren’t shown here.
This diff is large: its 1341 lines aren’t shown here.
This diff is large: its 343 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 304 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 329 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 279 lines aren’t shown here.
This diff is large: its 1313 lines aren’t shown here.
This diff is large: its 401 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 293 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.