Pull USB patches from Greg Kroah-Hartman: "Here's the big USB patch set for the 3.6-rc1 merge window. Lots of little changes in here, primarily for gadget controllers and drivers. There's some scsi changes that I think also went in through the scsi tree, but they merge just fine. All of these patches have been in the linux-next tree for a while now. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fix up trivial conflicts in include/scsi/scsi_device.h (same libata conflict that Jeff had already encountered) * tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (207 commits) usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams usb: Add quirk detection based on interface information usb: s3c-hsotg: Add header file protection macros in s3c-hsotg.h USB: ehci-s5p: Add vbus setup function to the s5p ehci glue layer USB: add USB_VENDOR_AND_INTERFACE_INFO() macro USB: notify phy when root hub port connect change USB: remove 8 bytes of padding from usb_host_interface on 64 bit builds USB: option: add ZTE MF821D USB: sierra: QMI mode MC7710 moved to qcserial USB: qcserial: adding Sierra Wireless devices USB: qcserial: support generic Qualcomm serial ports USB: qcserial: make probe more flexible USB: qcserial: centralize probe exit path USB: qcserial: consolidate usb_set_interface calls USB: ehci-s5p: Add support for device tree USB: ohci-exynos: Add support for device tree USB: ehci-omap: fix compile failure(v1) usb: host: tegra: pass correct pointer in ehci_setup() USB: ehci-fsl: Update ifdef check to work on 64-bit ppc USB: serial: keyspan: Removed unrequired parentheses. ...
Unified · Split
| @@ -208,3 +208,15 @@ Description: · 207 unmodified lines | ||
| 208 | 208 | such as ACPI. This file will read either "removable" or |
| 209 | 209 | "fixed" if the information is available, and "unknown" |
| 210 | 210 | otherwise. |
| 211 | + | |
| 212 | +What: /sys/bus/usb/devices/.../ltm_capable | |
| 213 | +Date: July 2012 | |
| 214 | +Contact: Sarah Sharp <sarah.a.sharp@linux.intel.com> | |
| 215 | +Description: | |
| 216 | + USB 3.0 devices may optionally support Latency Tolerance | |
| 217 | + Messaging (LTM). They indicate their support by setting a bit | |
| 218 | + in the bmAttributes field of their SuperSpeed BOS descriptors. | |
| 219 | + If that bit is set for the device, ltm_capable will read "yes". | |
| 220 | + If the device doesn't support LTM, the file will read "no". | |
| 221 | + The file will be present for all speeds of USB devices, and will | |
| 222 | + always read "no" for USB 1.1 and USB 2.0 devices. | |
| @@ -0,0 +1,18 @@ | ||
| 1 | +* Freescale i.MX ci13xxx usb controllers | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | +- compatible: Should be "fsl,imx27-usb" | |
| 5 | +- reg: Should contain registers location and length | |
| 6 | +- interrupts: Should contain controller interrupt | |
| 7 | + | |
| 8 | +Optional properties: | |
| 9 | +- fsl,usbphy: phandler of usb phy that connects to the only one port | |
| 10 | +- vbus-supply: regulator for vbus | |
| 11 | + | |
| 12 | +Examples: | |
| 13 | +usb@02184000 { /* USB OTG */ | |
| 14 | + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; | |
| 15 | + reg = <0x02184000 0x200>; | |
| 16 | + interrupts = <0 43 0x04>; | |
| 17 | + fsl,usbphy = <&usbphy1>; | |
| 18 | +}; | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +* Freescale MXS USB Phy Device | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | +- compatible: Should be "fsl,imx23-usbphy" | |
| 5 | +- reg: Should contain registers location and length | |
| 6 | +- interrupts: Should contain phy interrupt | |
| 7 | + | |
| 8 | +Example: | |
| 9 | +usbphy1: usbphy@020c9000 { | |
| 10 | + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; | |
| 11 | + reg = <0x020c9000 0x1000>; | |
| 12 | + interrupts = <0 44 0x04>; | |
| 13 | +}; | |
| @@ -0,0 +1,226 @@ | ||
| 1 | +* Overview | |
| 2 | + | |
| 3 | + Mass Storage Gadget (or MSG) acts as a USB Mass Storage device, | |
| 4 | + appearing to the host as a disk or a CD-ROM drive. It supports | |
| 5 | + multiple logical units (LUNs). Backing storage for each LUN is | |
| 6 | + provided by a regular file or a block device, access can be limited | |
| 7 | + to read-only, and gadget can indicate that it is removable and/or | |
| 8 | + CD-ROM (the latter implies read-only access). | |
| 9 | + | |
| 10 | + Its requirements are modest; only a bulk-in and a bulk-out endpoint | |
| 11 | + are needed. The memory requirement amounts to two 16K buffers. | |
| 12 | + Support is included for full-speed, high-speed and SuperSpeed | |
| 13 | + operation. | |
| 14 | + | |
| 15 | + Note that the driver is slightly non-portable in that it assumes | |
| 16 | + a single memory/DMA buffer will be useable for bulk-in and bulk-out | |
| 17 | + endpoints. With most device controllers this is not an issue, but | |
| 18 | + there may be some with hardware restrictions that prevent a buffer | |
| 19 | + from being used by more than one endpoint. | |
| 20 | + | |
| 21 | + This document describes how to use the gadget from user space, its | |
| 22 | + relation to mass storage function (or MSF) and different gadgets | |
| 23 | + using it, and how it differs from File Storage Gadget (or FSG). It | |
| 24 | + will talk only briefly about how to use MSF within composite | |
| 25 | + gadgets. | |
| 26 | + | |
| 27 | +* Module parameters | |
| 28 | + | |
| 29 | + The mass storage gadget accepts the following mass storage specific | |
| 30 | + module parameters: | |
| 31 | + | |
| 32 | + - file=filename[,filename...] | |
| 33 | + | |
| 34 | + This parameter lists paths to files or block devices used for | |
| 35 | + backing storage for each logical unit. There may be at most | |
| 36 | + FSG_MAX_LUNS (8) LUNs set. If more files are specified, they will | |
| 37 | + be silently ignored. See also “luns” parameter. | |
| 38 | + | |
| 39 | + *BEWARE* that if a file is used as a backing storage, it may not | |
| 40 | + be modified by any other process. This is because the host | |
| 41 | + assumes the data does not change without its knowledge. It may be | |
| 42 | + read, but (if the logical unit is writable) due to buffering on | |
| 43 | + the host side, the contents are not well defined. | |
| 44 | + | |
| 45 | + The size of the logical unit will be rounded down to a full | |
| 46 | + logical block. The logical block size is 2048 bytes for LUNs | |
| 47 | + simulating CD-ROM, block size of the device if the backing file is | |
| 48 | + a block device, or 512 bytes otherwise. | |
| 49 | + | |
| 50 | + - removable=b[,b...] | |
| 51 | + | |
| 52 | + This parameter specifies whether each logical unit should be | |
| 53 | + removable. “b” here is either “y”, “Y” or “1” for true or “n”, | |
| 54 | + “N” or “0” for false. | |
| 55 | + | |
| 56 | + If this option is set for a logical unit, gadget will accept an | |
| 57 | + “eject” SCSI request (Start/Stop Unit). When it is sent, the | |
| 58 | + backing file will be closed to simulate ejection and the logical | |
| 59 | + unit will not be mountable by the host until a new backing file is | |
| 60 | + specified by userspace on the device (see “sysfs entries” | |
| 61 | + section). | |
| 62 | + | |
| 63 | + If a logical unit is not removable (the default), a backing file | |
| 64 | + must be specified for it with the “file” parameter as the module | |
| 65 | + is loaded. The same applies if the module is built in, no | |
| 66 | + exceptions. | |
| 67 | + | |
| 68 | + The default value of the flag is false, *HOWEVER* it used to be | |
| 69 | + true. This has been changed to better match File Storage Gadget | |
| 70 | + and because it seems like a saner default after all. Thus to | |
| 71 | + maintain compatibility with older kernels, it's best to specify | |
| 72 | + the default values. Also, if one relied on old default, explicit | |
| 73 | + “n” needs to be specified now. | |
| 74 | + | |
| 75 | + Note that “removable” means the logical unit's media can be | |
| 76 | + ejected or removed (as is true for a CD-ROM drive or a card | |
| 77 | + reader). It does *not* mean that the entire gadget can be | |
| 78 | + unplugged from the host; the proper term for that is | |
| 79 | + “hot-unpluggable”. | |
| 80 | + | |
| 81 | + - cdrom=b[,b...] | |
| 82 | + | |
| 83 | + This parameter specifies whether each logical unit should simulate | |
| 84 | + CD-ROM. The default is false. | |
| 85 | + | |
| 86 | + - ro=b[,b...] | |
| 87 | + | |
| 88 | + This parameter specifies whether each logical unit should be | |
| 89 | + reported as read only. This will prevent host from modifying the | |
| 90 | + backing files. | |
| 91 | + | |
| 92 | + Note that if this flag for given logical unit is false but the | |
| 93 | + backing file could not be opened in read/write mode, the gadget | |
| 94 | + will fall back to read only mode anyway. | |
| 95 | + | |
| 96 | + The default value for non-CD-ROM logical units is false; for | |
| 97 | + logical units simulating CD-ROM it is forced to true. | |
| 98 | + | |
| 99 | + - nofua=b[,b...] | |
| 100 | + | |
| 101 | + This parameter specifies whether FUA flag should be ignored in SCSI | |
| 102 | + Write10 and Write12 commands sent to given logical units. | |
| 103 | + | |
| 104 | + MS Windows mounts removable storage in “Removal optimised mode” by | |
| 105 | + default. All the writes to the media are synchronous, which is | |
| 106 | + achieved by setting the FUA (Force Unit Access) bit in SCSI | |
| 107 | + Write(10,12) commands. This forces each write to wait until the | |
| 108 | + data has actually been written out and prevents I/O requests | |
| 109 | + aggregation in block layer dramatically decreasing performance. | |
| 110 | + | |
| 111 | + Note that this may mean that if the device is powered from USB and | |
| 112 | + the user unplugs the device without unmounting it first (which at | |
| 113 | + least some Windows users do), the data may be lost. | |
| 114 | + | |
| 115 | + The default value is false. | |
| 116 | + | |
| 117 | + - luns=N | |
| 118 | + | |
| 119 | + This parameter specifies number of logical units the gadget will | |
| 120 | + have. It is limited by FSG_MAX_LUNS (8) and higher value will be | |
| 121 | + capped. | |
| 122 | + | |
| 123 | + If this parameter is provided, and the number of files specified | |
| 124 | + in “file” argument is greater then the value of “luns”, all excess | |
| 125 | + files will be ignored. | |
| 126 | + | |
| 127 | + If this parameter is not present, the number of logical units will | |
| 128 | + be deduced from the number of files specified in the “file” | |
| 129 | + parameter. If the file parameter is missing as well, one is | |
| 130 | + assumed. | |
| 131 | + | |
| 132 | + - stall=b | |
| 133 | + | |
| 134 | + Specifies whether the gadget is allowed to halt bulk endpoints. | |
| 135 | + The default is determined according to the type of USB device | |
| 136 | + controller, but usually true. | |
| 137 | + | |
| 138 | + In addition to the above, the gadget also accepts the following | |
| 139 | + parameters defined by the composite framework (they are common to | |
| 140 | + all composite gadgets so just a quick listing): | |
| 141 | + | |
| 142 | + - idVendor -- USB Vendor ID (16 bit integer) | |
| 143 | + - idProduct -- USB Product ID (16 bit integer) | |
| 144 | + - bcdDevice -- USB Device version (BCD) (16 bit integer) | |
| 145 | + - iManufacturer -- USB Manufacturer string (string) | |
| 146 | + - iProduct -- USB Product string (string) | |
| 147 | + - iSerialNumber -- SerialNumber string (sting) | |
| 148 | + | |
| 149 | +* sysfs entries | |
| 150 | + | |
| 151 | + For each logical unit, the gadget creates a directory in the sysfs | |
| 152 | + hierarchy. Inside of it the following three files are created: | |
| 153 | + | |
| 154 | + - file | |
| 155 | + | |
| 156 | + When read it returns the path to the backing file for the given | |
| 157 | + logical unit. If there is no backing file (possible only if the | |
| 158 | + logical unit is removable), the content is empty. | |
| 159 | + | |
| 160 | + When written into, it changes the backing file for given logical | |
| 161 | + unit. This change can be performed even if given logical unit is | |
| 162 | + not specified as removable (but that may look strange to the | |
| 163 | + host). It may fail, however, if host disallowed medium removal | |
| 164 | + with the Prevent-Allow Medium Removal SCSI command. | |
| 165 | + | |
| 166 | + - ro | |
| 167 | + | |
| 168 | + Reflects the state of ro flag for the given logical unit. It can | |
| 169 | + be read any time, and written to when there is no backing file | |
| 170 | + open for given logical unit. | |
| 171 | + | |
| 172 | + - nofua | |
| 173 | + | |
| 174 | + Reflects the state of nofua flag for given logical unit. It can | |
| 175 | + be read and written. | |
| 176 | + | |
| 177 | + Other then those, as usual, the values of module parameters can be | |
| 178 | + read from /sys/module/g_mass_storage/parameters/* files. | |
| 179 | + | |
| 180 | +* Other gadgets using mass storage function | |
| 181 | + | |
| 182 | + The Mass Storage Gadget uses the Mass Storage Function to handle | |
| 183 | + mass storage protocol. As a composite function, MSF may be used by | |
| 184 | + other gadgets as well (eg. g_multi and acm_ms). | |
| 185 | + | |
| 186 | + All of the information in previous sections are valid for other | |
| 187 | + gadgets using MSF, except that support for mass storage related | |
| 188 | + module parameters may be missing, or the parameters may have | |
| 189 | + a prefix. To figure out whether any of this is true one needs to | |
| 190 | + consult the gadget's documentation or its source code. | |
| 191 | + | |
| 192 | + For examples of how to include mass storage function in gadgets, one | |
| 193 | + may take a look at mass_storage.c, acm_ms.c and multi.c (sorted by | |
| 194 | + complexity). | |
| 195 | + | |
| 196 | +* Relation to file storage gadget | |
| 197 | + | |
| 198 | + The Mass Storage Function and thus the Mass Storage Gadget has been | |
| 199 | + based on the File Storage Gadget. The difference between the two is | |
| 200 | + that MSG is a composite gadget (ie. uses the composite framework) | |
| 201 | + while file storage gadget is a traditional gadget. From userspace | |
| 202 | + point of view this distinction does not really matter, but from | |
| 203 | + kernel hacker's point of view, this means that (i) MSG does not | |
| 204 | + duplicate code needed for handling basic USB protocol commands and | |
| 205 | + (ii) MSF can be used in any other composite gadget. | |
| 206 | + | |
| 207 | + Because of that, File Storage Gadget has been deprecated and | |
| 208 | + scheduled to be removed in Linux 3.8. All users need to transition | |
| 209 | + to the Mass Storage Gadget by that time. The two gadgets behave | |
| 210 | + mostly the same from the outside except: | |
| 211 | + | |
| 212 | + 1. In FSG the “removable” and “cdrom” module parameters set the flag | |
| 213 | + for all logical units whereas in MSG they accept a list of y/n | |
| 214 | + values for each logical unit. If one uses only a single logical | |
| 215 | + unit this does not matter, but if there are more, the y/n value | |
| 216 | + needs to be repeated for each logical unit. | |
| 217 | + | |
| 218 | + 2. FSG's “serial”, “vendor”, “product” and “release” module | |
| 219 | + parameters are handled in MSG by the composite layer's parameters | |
| 220 | + named respectively: “iSerialnumber”, “idVendor”, “idProduct” and | |
| 221 | + “bcdDevice”. | |
| 222 | + | |
| 223 | + 3. MSG does not support FSG's test mode, thus “transport”, | |
| 224 | + “protocol” and “buflen” FSG's module parameters are not | |
| 225 | + supported. MSG always uses SCSI protocol with bulk only | |
| 226 | + transport mode and 16 KiB buffers. | |
| @@ -3376,15 +3376,15 @@ static struct omap_clk omap3xxx_clks[] = { · 3375 unmodified lines | ||
| 3376 | 3376 | CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), |
| 3377 | 3377 | CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), |
| 3378 | 3378 | CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), |
| 3379 | − CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), | |
| 3380 | − CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), | |
| 3381 | − CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), | |
| 3382 | − CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), | |
| 3383 | − CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), | |
| 3384 | − CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), | |
| 3379 | + CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX), | |
| 3380 | + CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX), | |
| 3381 | + CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), | |
| 3382 | + CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), | |
| 3383 | + CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), | |
| 3384 | + CLK(NULL, "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), | |
| 3385 | 3385 | CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), |
| 3386 | 3386 | CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), |
| 3387 | − CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), | |
| 3387 | + CLK(NULL, "init_60m_fclk", &dummy_ck, CK_3XXX), | |
| 3388 | 3388 | CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), |
| 3389 | 3389 | CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), |
| 3390 | 3390 | CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), |
| @@ -2517,7 +2517,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) · 2516 unmodified lines | ||
| 2517 | 2517 | dev_err(di->dev, "%s mask and set failed\n", __func__); |
| 2518 | 2518 | |
| 2519 | 2519 | usb_unregister_notifier(di->usb_phy, &di->nb); |
| 2520 | − usb_put_transceiver(di->usb_phy); | |
| 2520 | + usb_put_phy(di->usb_phy); | |
| 2521 | 2521 | |
| 2522 | 2522 | /* Delete the work queue */ |
| 2523 | 2523 | destroy_workqueue(di->charger_wq); |
| @@ -2688,8 +2688,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) · 164 unmodified lines | ||
| 2688 | 2688 | goto free_ac; |
| 2689 | 2689 | } |
| 2690 | 2690 | |
| 2691 | − di->usb_phy = usb_get_transceiver(); | |
| 2692 | − if (!di->usb_phy) { | |
| 2691 | + di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2692 | + if (IS_ERR_OR_NULL(di->usb_phy)) { | |
| 2693 | 2693 | dev_err(di->dev, "failed to get usb transceiver\n"); |
| 2694 | 2694 | ret = -EINVAL; |
| 2695 | 2695 | goto free_usb; |
| @@ -2747,7 +2747,7 @@ free_irq: · 51 unmodified lines | ||
| 2747 | 2747 | free_irq(irq, di); |
| 2748 | 2748 | } |
| 2749 | 2749 | put_usb_phy: |
| 2750 | − usb_put_transceiver(di->usb_phy); | |
| 2750 | + usb_put_phy(di->usb_phy); | |
| 2751 | 2751 | free_usb: |
| 2752 | 2752 | power_supply_unregister(&di->usb_chg.psy); |
| 2753 | 2753 | free_ac: |
| @@ -415,8 +415,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) · 414 unmodified lines | ||
| 415 | 415 | if (!isp) |
| 416 | 416 | return -ENOMEM; |
| 417 | 417 | |
| 418 | − isp->phy = usb_get_transceiver(); | |
| 419 | − if (!isp->phy) | |
| 418 | + isp->phy = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 419 | + if (IS_ERR_OR_NULL(isp->phy)) | |
| 420 | 420 | goto fail0; |
| 421 | 421 | |
| 422 | 422 | isp->dev = &pdev->dev; |
| @@ -475,7 +475,7 @@ fail2: · 52 unmodified lines | ||
| 475 | 475 | power_supply_unregister(&isp->psy); |
| 476 | 476 | fail1: |
| 477 | 477 | isp1704_charger_set_power(isp, 0); |
| 478 | − usb_put_transceiver(isp->phy); | |
| 478 | + usb_put_phy(isp->phy); | |
| 479 | 479 | fail0: |
| 480 | 480 | kfree(isp); |
| 481 | 481 | |
| @@ -490,7 +490,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 490 | 490 | |
| 491 | 491 | usb_unregister_notifier(isp->phy, &isp->nb); |
| 492 | 492 | power_supply_unregister(&isp->psy); |
| 493 | − usb_put_transceiver(isp->phy); | |
| 493 | + usb_put_phy(isp->phy); | |
| 494 | 494 | isp1704_charger_set_power(isp, 0); |
| 495 | 495 | kfree(isp); |
| 496 | 496 | |
| @@ -321,12 +321,12 @@ static int pda_power_probe(struct platform_device *pdev) · 320 unmodified lines | ||
| 321 | 321 | } |
| 322 | 322 | |
| 323 | 323 | #ifdef CONFIG_USB_OTG_UTILS |
| 324 | − transceiver = usb_get_transceiver(); | |
| 325 | − if (transceiver && !pdata->is_usb_online) { | |
| 326 | − pdata->is_usb_online = otg_is_usb_online; | |
| 327 | − } | |
| 328 | − if (transceiver && !pdata->is_ac_online) { | |
| 329 | − pdata->is_ac_online = otg_is_ac_online; | |
| 324 | + transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 325 | + if (!IS_ERR_OR_NULL(transceiver)) { | |
| 326 | + if (!pdata->is_usb_online) | |
| 327 | + pdata->is_usb_online = otg_is_usb_online; | |
| 328 | + if (!pdata->is_ac_online) | |
| 329 | + pdata->is_ac_online = otg_is_ac_online; | |
| 330 | 330 | } |
| 331 | 331 | #endif |
| 332 | 332 | |
| @@ -373,7 +373,7 @@ static int pda_power_probe(struct platform_device *pdev) · 40 unmodified lines | ||
| 373 | 373 | } |
| 374 | 374 | |
| 375 | 375 | #ifdef CONFIG_USB_OTG_UTILS |
| 376 | − if (transceiver && pdata->use_otg_notifier) { | |
| 376 | + if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) { | |
| 377 | 377 | otg_nb.notifier_call = otg_handle_notification; |
| 378 | 378 | ret = usb_register_notifier(transceiver, &otg_nb); |
| 379 | 379 | if (ret) { |
| @@ -408,8 +408,8 @@ usb_supply_failed: · 28 unmodified lines | ||
| 408 | 408 | if (pdata->is_ac_online && ac_irq) |
| 409 | 409 | free_irq(ac_irq->start, &pda_psy_ac); |
| 410 | 410 | #ifdef CONFIG_USB_OTG_UTILS |
| 411 | − if (transceiver) | |
| 412 | − usb_put_transceiver(transceiver); | |
| 411 | + if (!IS_ERR_OR_NULL(transceiver)) | |
| 412 | + usb_put_phy(transceiver); | |
| 413 | 413 | #endif |
| 414 | 414 | ac_irq_failed: |
| 415 | 415 | if (pdata->is_ac_online) |
| @@ -443,8 +443,8 @@ static int pda_power_remove(struct platform_device *pdev) · 27 unmodified lines | ||
| 443 | 443 | if (pdata->is_ac_online) |
| 444 | 444 | power_supply_unregister(&pda_psy_ac); |
| 445 | 445 | #ifdef CONFIG_USB_OTG_UTILS |
| 446 | − if (transceiver) | |
| 447 | − usb_put_transceiver(transceiver); | |
| 446 | + if (!IS_ERR_OR_NULL(transceiver)) | |
| 447 | + usb_put_phy(transceiver); | |
| 448 | 448 | #endif |
| 449 | 449 | if (ac_draw) { |
| 450 | 450 | regulator_put(ac_draw); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/init.h> |
| 16 | 16 | #include <linux/module.h> |
| 17 | 17 | #include <linux/slab.h> |
| 18 | +#include <linux/err.h> | |
| 18 | 19 | #include <linux/platform_device.h> |
| 19 | 20 | #include <linux/interrupt.h> |
| 20 | 21 | #include <linux/i2c/twl.h> |
| @@ -479,8 +480,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) · 458 unmodified lines | ||
| 479 | 480 | |
| 480 | 481 | INIT_WORK(&bci->work, twl4030_bci_usb_work); |
| 481 | 482 | |
| 482 | − bci->transceiver = usb_get_transceiver(); | |
| 483 | − if (bci->transceiver != NULL) { | |
| 483 | + bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 484 | + if (!IS_ERR_OR_NULL(bci->transceiver)) { | |
| 484 | 485 | bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; |
| 485 | 486 | usb_register_notifier(bci->transceiver, &bci->usb_nb); |
| 486 | 487 | } |
| @@ -507,9 +508,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 507 | 508 | return 0; |
| 508 | 509 | |
| 509 | 510 | fail_unmask_interrupts: |
| 510 | − if (bci->transceiver != NULL) { | |
| 511 | + if (!IS_ERR_OR_NULL(bci->transceiver)) { | |
| 511 | 512 | usb_unregister_notifier(bci->transceiver, &bci->usb_nb); |
| 512 | − usb_put_transceiver(bci->transceiver); | |
| 513 | + usb_put_phy(bci->transceiver); | |
| 513 | 514 | } |
| 514 | 515 | free_irq(bci->irq_bci, bci); |
| 515 | 516 | fail_bci_irq: |
| @@ -538,9 +539,9 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) · 22 unmodified lines | ||
| 538 | 539 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, |
| 539 | 540 | TWL4030_INTERRUPTS_BCIIMR2A); |
| 540 | 541 | |
| 541 | − if (bci->transceiver != NULL) { | |
| 542 | + if (!IS_ERR_OR_NULL(bci->transceiver)) { | |
| 542 | 543 | usb_unregister_notifier(bci->transceiver, &bci->usb_nb); |
| 543 | − usb_put_transceiver(bci->transceiver); | |
| 544 | + usb_put_phy(bci->transceiver); | |
| 544 | 545 | } |
| 545 | 546 | free_irq(bci->irq_bci, bci); |
| 546 | 547 | free_irq(bci->irq_chg, bci); |
| @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | config USB_CHIPIDEA_HOST |
| 22 | 22 | bool "ChipIdea host controller" |
| 23 | + select USB_EHCI_ROOT_HUB_TT | |
| 23 | 24 | help |
| 24 | 25 | Say Y here to enable host controller functionality of the |
| 25 | 26 | ChipIdea driver. |
| @@ -5,10 +5,15 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o · 4 unmodified lines | ||
| 5 | 5 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o |
| 6 | 6 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o |
| 7 | 7 | |
| 8 | +# Glue/Bridge layers go here | |
| 9 | + | |
| 10 | +obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o | |
| 11 | + | |
| 12 | +# PCI doesn't provide stubs, need to check | |
| 8 | 13 | ifneq ($(CONFIG_PCI),) |
| 9 | 14 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o |
| 10 | 15 | endif |
| 11 | 16 | |
| 12 | −ifneq ($(CONFIG_ARCH_MSM),) | |
| 13 | − obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o | |
| 17 | +ifneq ($(CONFIG_OF_DEVICE),) | |
| 18 | + obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o | |
| 14 | 19 | endif |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | * @name: string description of the endpoint |
| 37 | 37 | * @qh: queue head for this endpoint |
| 38 | 38 | * @wedge: is the endpoint wedged |
| 39 | − * @udc: pointer to the controller | |
| 39 | + * @ci: pointer to the controller | |
| 40 | 40 | * @lock: pointer to controller's spinlock |
| 41 | 41 | * @td_pool: pointer to controller's TD pool |
| 42 | 42 | */ |
| @@ -54,7 +54,7 @@ struct ci13xxx_ep { · 11 unmodified lines | ||
| 54 | 54 | int wedge; |
| 55 | 55 | |
| 56 | 56 | /* global resources */ |
| 57 | − struct ci13xxx *udc; | |
| 57 | + struct ci13xxx *ci; | |
| 58 | 58 | spinlock_t *lock; |
| 59 | 59 | struct dma_pool *td_pool; |
| 60 | 60 | }; |
| @@ -125,7 +125,7 @@ struct hw_bank { · 64 unmodified lines | ||
| 125 | 125 | * @remote_wakeup: host-enabled remote wakeup |
| 126 | 126 | * @suspended: suspended by host |
| 127 | 127 | * @test_mode: the selected test mode |
| 128 | − * @udc_driver: platform specific information supplied by parent device | |
| 128 | + * @platdata: platform specific information supplied by parent device | |
| 129 | 129 | * @vbus_active: is VBUS active |
| 130 | 130 | * @transceiver: pointer to USB PHY, if any |
| 131 | 131 | * @hcd: pointer to usb_hcd for ehci host driver |
| @@ -158,8 +158,10 @@ struct ci13xxx { · 26 unmodified lines | ||
| 158 | 158 | u8 suspended; |
| 159 | 159 | u8 test_mode; |
| 160 | 160 | |
| 161 | − struct ci13xxx_udc_driver *udc_driver; | |
| 161 | + struct ci13xxx_platform_data *platdata; | |
| 162 | 162 | int vbus_active; |
| 163 | + /* FIXME: some day, we'll not use global phy */ | |
| 164 | + bool global_phy; | |
| 163 | 165 | struct usb_phy *transceiver; |
| 164 | 166 | struct usb_hcd *hcd; |
| 165 | 167 | }; |
| @@ -250,9 +252,9 @@ static inline int ffs_nr(u32 x) · 84 unmodified lines | ||
| 250 | 252 | * |
| 251 | 253 | * This function returns register contents |
| 252 | 254 | */ |
| 253 | −static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask) | |
| 255 | +static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) | |
| 254 | 256 | { |
| 255 | − return ioread32(udc->hw_bank.regmap[reg]) & mask; | |
| 257 | + return ioread32(ci->hw_bank.regmap[reg]) & mask; | |
| 256 | 258 | } |
| 257 | 259 | |
| 258 | 260 | /** |
| @@ -261,14 +263,14 @@ static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask) · 2 unmodified lines | ||
| 261 | 263 | * @mask: bitfield mask |
| 262 | 264 | * @data: new value |
| 263 | 265 | */ |
| 264 | −static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, | |
| 266 | +static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | |
| 265 | 267 | u32 mask, u32 data) |
| 266 | 268 | { |
| 267 | 269 | if (~mask) |
| 268 | − data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask) | |
| 270 | + data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask) | |
| 269 | 271 | | (data & mask); |
| 270 | 272 | |
| 271 | − iowrite32(data, udc->hw_bank.regmap[reg]); | |
| 273 | + iowrite32(data, ci->hw_bank.regmap[reg]); | |
| 272 | 274 | } |
| 273 | 275 | |
| 274 | 276 | /** |
| @@ -278,12 +280,12 @@ static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, · 3 unmodified lines | ||
| 278 | 280 | * |
| 279 | 281 | * This function returns register contents |
| 280 | 282 | */ |
| 281 | −static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg, | |
| 283 | +static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, | |
| 282 | 284 | u32 mask) |
| 283 | 285 | { |
| 284 | − u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask; | |
| 286 | + u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; | |
| 285 | 287 | |
| 286 | − iowrite32(val, udc->hw_bank.regmap[reg]); | |
| 288 | + iowrite32(val, ci->hw_bank.regmap[reg]); | |
| 287 | 289 | return val; |
| 288 | 290 | } |
| 289 | 291 | |
| @@ -295,12 +297,12 @@ static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg, · 5 unmodified lines | ||
| 295 | 297 | * |
| 296 | 298 | * This function returns register contents |
| 297 | 299 | */ |
| 298 | −static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg, | |
| 300 | +static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | |
| 299 | 301 | u32 mask, u32 data) |
| 300 | 302 | { |
| 301 | − u32 val = hw_read(udc, reg, ~0); | |
| 303 | + u32 val = hw_read(ci, reg, ~0); | |
| 302 | 304 | |
| 303 | − hw_write(udc, reg, mask, data); | |
| 305 | + hw_write(ci, reg, mask, data); | |
| 304 | 306 | return (val & mask) >> ffs_nr(mask); |
| 305 | 307 | } |
| 306 | 308 | |
| @@ -0,0 +1,198 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2012 Freescale Semiconductor, Inc. | |
| 3 | + * Copyright (C) 2012 Marek Vasut <marex@denx.de> | |
| 4 | + * on behalf of DENX Software Engineering GmbH | |
| 5 | + * | |
| 6 | + * The code contained herein is licensed under the GNU General Public | |
| 7 | + * License. You may obtain a copy of the GNU General Public License | |
| 8 | + * Version 2 or later at the following locations: | |
| 9 | + * | |
| 10 | + * http://www.opensource.org/licenses/gpl-license.html | |
| 11 | + * http://www.gnu.org/copyleft/gpl.html | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/of_platform.h> | |
| 16 | +#include <linux/of_gpio.h> | |
| 17 | +#include <linux/platform_device.h> | |
| 18 | +#include <linux/pm_runtime.h> | |
| 19 | +#include <linux/dma-mapping.h> | |
| 20 | +#include <linux/usb/chipidea.h> | |
| 21 | +#include <linux/clk.h> | |
| 22 | +#include <linux/regulator/consumer.h> | |
| 23 | + | |
| 24 | +#include "ci.h" | |
| 25 | + | |
| 26 | +#define pdev_to_phy(pdev) \ | |
| 27 | + ((struct usb_phy *)platform_get_drvdata(pdev)) | |
| 28 | + | |
| 29 | +struct ci13xxx_imx_data { | |
| 30 | + struct device_node *phy_np; | |
| 31 | + struct usb_phy *phy; | |
| 32 | + struct platform_device *ci_pdev; | |
| 33 | + struct clk *clk; | |
| 34 | + struct regulator *reg_vbus; | |
| 35 | +}; | |
| 36 | + | |
| 37 | +static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = { | |
| 38 | + .name = "ci13xxx_imx", | |
| 39 | + .flags = CI13XXX_REQUIRE_TRANSCEIVER | | |
| 40 | + CI13XXX_PULLUP_ON_VBUS | | |
| 41 | + CI13XXX_DISABLE_STREAMING, | |
| 42 | + .capoffset = DEF_CAPOFFSET, | |
| 43 | +}; | |
| 44 | + | |
| 45 | +static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) | |
| 46 | +{ | |
| 47 | + struct ci13xxx_imx_data *data; | |
| 48 | + struct platform_device *plat_ci, *phy_pdev; | |
| 49 | + struct device_node *phy_np; | |
| 50 | + struct resource *res; | |
| 51 | + struct regulator *reg_vbus; | |
| 52 | + int ret; | |
| 53 | + | |
| 54 | + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | |
| 55 | + if (!data) { | |
| 56 | + dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); | |
| 57 | + return -ENOMEM; | |
| 58 | + } | |
| 59 | + | |
| 60 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 61 | + if (!res) { | |
| 62 | + dev_err(&pdev->dev, "Can't get device resources!\n"); | |
| 63 | + return -ENOENT; | |
| 64 | + } | |
| 65 | + | |
| 66 | + data->clk = devm_clk_get(&pdev->dev, NULL); | |
| 67 | + if (IS_ERR(data->clk)) { | |
| 68 | + dev_err(&pdev->dev, | |
| 69 | + "Failed to get clock, err=%ld\n", PTR_ERR(data->clk)); | |
| 70 | + return PTR_ERR(data->clk); | |
| 71 | + } | |
| 72 | + | |
| 73 | + ret = clk_prepare_enable(data->clk); | |
| 74 | + if (ret) { | |
| 75 | + dev_err(&pdev->dev, | |
| 76 | + "Failed to prepare or enable clock, err=%d\n", ret); | |
| 77 | + return ret; | |
| 78 | + } | |
| 79 | + | |
| 80 | + phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0); | |
| 81 | + if (phy_np) { | |
| 82 | + data->phy_np = phy_np; | |
| 83 | + phy_pdev = of_find_device_by_node(phy_np); | |
| 84 | + if (phy_pdev) { | |
| 85 | + struct usb_phy *phy; | |
| 86 | + phy = pdev_to_phy(phy_pdev); | |
| 87 | + if (phy && | |
| 88 | + try_module_get(phy_pdev->dev.driver->owner)) { | |
| 89 | + usb_phy_init(phy); | |
| 90 | + data->phy = phy; | |
| 91 | + } | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + /* we only support host now, so enable vbus here */ | |
| 96 | + reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); | |
| 97 | + if (!IS_ERR(reg_vbus)) { | |
| 98 | + ret = regulator_enable(reg_vbus); | |
| 99 | + if (ret) { | |
| 100 | + dev_err(&pdev->dev, | |
| 101 | + "Failed to enable vbus regulator, err=%d\n", | |
| 102 | + ret); | |
| 103 | + goto put_np; | |
| 104 | + } | |
| 105 | + data->reg_vbus = reg_vbus; | |
| 106 | + } else { | |
| 107 | + reg_vbus = NULL; | |
| 108 | + } | |
| 109 | + | |
| 110 | + ci13xxx_imx_platdata.phy = data->phy; | |
| 111 | + | |
| 112 | + if (!pdev->dev.dma_mask) { | |
| 113 | + pdev->dev.dma_mask = devm_kzalloc(&pdev->dev, | |
| 114 | + sizeof(*pdev->dev.dma_mask), GFP_KERNEL); | |
| 115 | + if (!pdev->dev.dma_mask) { | |
| 116 | + ret = -ENOMEM; | |
| 117 | + dev_err(&pdev->dev, "Failed to alloc dma_mask!\n"); | |
| 118 | + goto err; | |
| 119 | + } | |
| 120 | + *pdev->dev.dma_mask = DMA_BIT_MASK(32); | |
| 121 | + dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask); | |
| 122 | + } | |
| 123 | + plat_ci = ci13xxx_add_device(&pdev->dev, | |
| 124 | + pdev->resource, pdev->num_resources, | |
| 125 | + &ci13xxx_imx_platdata); | |
| 126 | + if (IS_ERR(plat_ci)) { | |
| 127 | + ret = PTR_ERR(plat_ci); | |
| 128 | + dev_err(&pdev->dev, | |
| 129 | + "Can't register ci_hdrc platform device, err=%d\n", | |
| 130 | + ret); | |
| 131 | + goto err; | |
| 132 | + } | |
| 133 | + | |
| 134 | + data->ci_pdev = plat_ci; | |
| 135 | + platform_set_drvdata(pdev, data); | |
| 136 | + | |
| 137 | + pm_runtime_no_callbacks(&pdev->dev); | |
| 138 | + pm_runtime_enable(&pdev->dev); | |
| 139 | + | |
| 140 | + return 0; | |
| 141 | + | |
| 142 | +err: | |
| 143 | + if (reg_vbus) | |
| 144 | + regulator_disable(reg_vbus); | |
| 145 | +put_np: | |
| 146 | + if (phy_np) | |
| 147 | + of_node_put(phy_np); | |
| 148 | + clk_disable_unprepare(data->clk); | |
| 149 | + return ret; | |
| 150 | +} | |
| 151 | + | |
| 152 | +static int __devexit ci13xxx_imx_remove(struct platform_device *pdev) | |
| 153 | +{ | |
| 154 | + struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); | |
| 155 | + | |
| 156 | + pm_runtime_disable(&pdev->dev); | |
| 157 | + ci13xxx_remove_device(data->ci_pdev); | |
| 158 | + | |
| 159 | + if (data->reg_vbus) | |
| 160 | + regulator_disable(data->reg_vbus); | |
| 161 | + | |
| 162 | + if (data->phy) { | |
| 163 | + usb_phy_shutdown(data->phy); | |
| 164 | + module_put(data->phy->dev->driver->owner); | |
| 165 | + } | |
| 166 | + | |
| 167 | + of_node_put(data->phy_np); | |
| 168 | + | |
| 169 | + clk_disable_unprepare(data->clk); | |
| 170 | + | |
| 171 | + platform_set_drvdata(pdev, NULL); | |
| 172 | + | |
| 173 | + return 0; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static const struct of_device_id ci13xxx_imx_dt_ids[] = { | |
| 177 | + { .compatible = "fsl,imx27-usb", }, | |
| 178 | + { /* sentinel */ } | |
| 179 | +}; | |
| 180 | +MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids); | |
| 181 | + | |
| 182 | +static struct platform_driver ci13xxx_imx_driver = { | |
| 183 | + .probe = ci13xxx_imx_probe, | |
| 184 | + .remove = __devexit_p(ci13xxx_imx_remove), | |
| 185 | + .driver = { | |
| 186 | + .name = "imx_usb", | |
| 187 | + .owner = THIS_MODULE, | |
| 188 | + .of_match_table = ci13xxx_imx_dt_ids, | |
| 189 | + }, | |
| 190 | +}; | |
| 191 | + | |
| 192 | +module_platform_driver(ci13xxx_imx_driver); | |
| 193 | + | |
| 194 | +MODULE_ALIAS("platform:imx-usb"); | |
| 195 | +MODULE_LICENSE("GPL v2"); | |
| 196 | +MODULE_DESCRIPTION("CI13xxx i.MX USB binding"); | |
| 197 | +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
| 198 | +MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | |
| @@ -15,11 +15,11 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include "ci.h" |
| 17 | 17 | |
| 18 | −#define MSM_USB_BASE (udc->hw_bank.abs) | |
| 18 | +#define MSM_USB_BASE (ci->hw_bank.abs) | |
| 19 | 19 | |
| 20 | −static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) | |
| 20 | +static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) | |
| 21 | 21 | { |
| 22 | − struct device *dev = udc->gadget.dev.parent; | |
| 22 | + struct device *dev = ci->gadget.dev.parent; | |
| 23 | 23 | int val; |
| 24 | 24 | |
| 25 | 25 | switch (event) { |
| @@ -34,18 +34,18 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) · 8 unmodified lines | ||
| 34 | 34 | * Put the transceiver in non-driving mode. Otherwise host |
| 35 | 35 | * may not detect soft-disconnection. |
| 36 | 36 | */ |
| 37 | − val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL); | |
| 37 | + val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); | |
| 38 | 38 | val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; |
| 39 | 39 | val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; |
| 40 | − usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); | |
| 40 | + usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); | |
| 41 | 41 | break; |
| 42 | 42 | default: |
| 43 | − dev_dbg(dev, "unknown ci13xxx_udc event\n"); | |
| 43 | + dev_dbg(dev, "unknown ci13xxx event\n"); | |
| 44 | 44 | break; |
| 45 | 45 | } |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | −static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { | |
| 48 | +static struct ci13xxx_platform_data ci13xxx_msm_platdata = { | |
| 49 | 49 | .name = "ci13xxx_msm", |
| 50 | 50 | .flags = CI13XXX_REGS_SHARED | |
| 51 | 51 | CI13XXX_REQUIRE_TRANSCEIVER | |
| @@ -55,56 +55,45 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { · 3 unmodified lines | ||
| 55 | 55 | .notify_event = ci13xxx_msm_notify_event, |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | −static int ci13xxx_msm_probe(struct platform_device *pdev) | |
| 58 | +static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) | |
| 59 | 59 | { |
| 60 | 60 | struct platform_device *plat_ci; |
| 61 | − int ret; | |
| 62 | 61 | |
| 63 | 62 | dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); |
| 64 | 63 | |
| 65 | − plat_ci = platform_device_alloc("ci_hdrc", -1); | |
| 66 | − if (!plat_ci) { | |
| 67 | − dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n"); | |
| 68 | − return -ENOMEM; | |
| 64 | + plat_ci = ci13xxx_add_device(&pdev->dev, | |
| 65 | + pdev->resource, pdev->num_resources, | |
| 66 | + &ci13xxx_msm_platdata); | |
| 67 | + if (IS_ERR(plat_ci)) { | |
| 68 | + dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | |
| 69 | + return PTR_ERR(plat_ci); | |
| 69 | 70 | } |
| 70 | 71 | |
| 71 | − ret = platform_device_add_resources(plat_ci, pdev->resource, | |
| 72 | − pdev->num_resources); | |
| 73 | − if (ret) { | |
| 74 | − dev_err(&pdev->dev, "can't add resources to platform device\n"); | |
| 75 | − goto put_platform; | |
| 76 | − } | |
| 77 | − | |
| 78 | − ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver, | |
| 79 | − sizeof(ci13xxx_msm_udc_driver)); | |
| 80 | − if (ret) | |
| 81 | − goto put_platform; | |
| 82 | − | |
| 83 | − ret = platform_device_add(plat_ci); | |
| 84 | − if (ret) | |
| 85 | − goto put_platform; | |
| 72 | + platform_set_drvdata(pdev, plat_ci); | |
| 86 | 73 | |
| 87 | 74 | pm_runtime_no_callbacks(&pdev->dev); |
| 88 | 75 | pm_runtime_enable(&pdev->dev); |
| 89 | 76 | |
| 90 | 77 | return 0; |
| 78 | +} | |
| 79 | + | |
| 80 | +static int __devexit ci13xxx_msm_remove(struct platform_device *pdev) | |
| 81 | +{ | |
| 82 | + struct platform_device *plat_ci = platform_get_drvdata(pdev); | |
| 91 | 83 | |
| 92 | −put_platform: | |
| 93 | − platform_device_put(plat_ci); | |
| 84 | + pm_runtime_disable(&pdev->dev); | |
| 85 | + ci13xxx_remove_device(plat_ci); | |
| 94 | 86 | |
| 95 | − return ret; | |
| 87 | + return 0; | |
| 96 | 88 | } |
| 97 | 89 | |
| 98 | 90 | static struct platform_driver ci13xxx_msm_driver = { |
| 99 | 91 | .probe = ci13xxx_msm_probe, |
| 92 | + .remove = __devexit_p(ci13xxx_msm_remove), | |
| 100 | 93 | .driver = { .name = "msm_hsusb", }, |
| 101 | 94 | }; |
| 102 | −MODULE_ALIAS("platform:msm_hsusb"); | |
| 103 | 95 | |
| 104 | −static int __init ci13xxx_msm_init(void) | |
| 105 | −{ | |
| 106 | − return platform_driver_register(&ci13xxx_msm_driver); | |
| 107 | −} | |
| 108 | −module_init(ci13xxx_msm_init); | |
| 96 | +module_platform_driver(ci13xxx_msm_driver); | |
| 109 | 97 | |
| 98 | +MODULE_ALIAS("platform:msm_hsusb"); | |
| 110 | 99 | MODULE_LICENSE("GPL v2"); |
| @@ -23,17 +23,17 @@ · 22 unmodified lines | ||
| 23 | 23 | /****************************************************************************** |
| 24 | 24 | * PCI block |
| 25 | 25 | *****************************************************************************/ |
| 26 | −struct ci13xxx_udc_driver pci_driver = { | |
| 26 | +struct ci13xxx_platform_data pci_platdata = { | |
| 27 | 27 | .name = UDC_DRIVER_NAME, |
| 28 | 28 | .capoffset = DEF_CAPOFFSET, |
| 29 | 29 | }; |
| 30 | 30 | |
| 31 | −struct ci13xxx_udc_driver langwell_pci_driver = { | |
| 31 | +struct ci13xxx_platform_data langwell_pci_platdata = { | |
| 32 | 32 | .name = UDC_DRIVER_NAME, |
| 33 | 33 | .capoffset = 0, |
| 34 | 34 | }; |
| 35 | 35 | |
| 36 | −struct ci13xxx_udc_driver penwell_pci_driver = { | |
| 36 | +struct ci13xxx_platform_data penwell_pci_platdata = { | |
| 37 | 37 | .name = UDC_DRIVER_NAME, |
| 38 | 38 | .capoffset = 0, |
| 39 | 39 | .power_budget = 200, |
| @@ -51,12 +51,12 @@ struct ci13xxx_udc_driver penwell_pci_driver = { · 11 unmodified lines | ||
| 51 | 51 | static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, |
| 52 | 52 | const struct pci_device_id *id) |
| 53 | 53 | { |
| 54 | − struct ci13xxx_udc_driver *driver = (void *)id->driver_data; | |
| 54 | + struct ci13xxx_platform_data *platdata = (void *)id->driver_data; | |
| 55 | 55 | struct platform_device *plat_ci; |
| 56 | 56 | struct resource res[3]; |
| 57 | 57 | int retval = 0, nres = 2; |
| 58 | 58 | |
| 59 | − if (!driver) { | |
| 59 | + if (!platdata) { | |
| 60 | 60 | dev_err(&pdev->dev, "device doesn't provide driver data\n"); |
| 61 | 61 | return -ENODEV; |
| 62 | 62 | } |
| @@ -75,13 +75,6 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, · 12 unmodified lines | ||
| 75 | 75 | pci_set_master(pdev); |
| 76 | 76 | pci_try_set_mwi(pdev); |
| 77 | 77 | |
| 78 | − plat_ci = platform_device_alloc("ci_hdrc", -1); | |
| 79 | − if (!plat_ci) { | |
| 80 | − dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n"); | |
| 81 | − retval = -ENOMEM; | |
| 82 | − goto disable_device; | |
| 83 | − } | |
| 84 | − | |
| 85 | 78 | memset(res, 0, sizeof(res)); |
| 86 | 79 | res[0].start = pci_resource_start(pdev, 0); |
| 87 | 80 | res[0].end = pci_resource_end(pdev, 0); |
| @@ -89,32 +82,17 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, · 1 unmodified line | ||
| 89 | 82 | res[1].start = pdev->irq; |
| 90 | 83 | res[1].flags = IORESOURCE_IRQ; |
| 91 | 84 | |
| 92 | − retval = platform_device_add_resources(plat_ci, res, nres); | |
| 93 | − if (retval) { | |
| 94 | − dev_err(&pdev->dev, "can't add resources to platform device\n"); | |
| 95 | − goto put_platform; | |
| 85 | + plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata); | |
| 86 | + if (IS_ERR(plat_ci)) { | |
| 87 | + dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | |
| 88 | + retval = PTR_ERR(plat_ci); | |
| 89 | + goto disable_device; | |
| 96 | 90 | } |
| 97 | 91 | |
| 98 | − retval = platform_device_add_data(plat_ci, driver, sizeof(*driver)); | |
| 99 | − if (retval) | |
| 100 | − goto put_platform; | |
| 101 | − | |
| 102 | − dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask); | |
| 103 | − plat_ci->dev.dma_mask = pdev->dev.dma_mask; | |
| 104 | − plat_ci->dev.dma_parms = pdev->dev.dma_parms; | |
| 105 | − plat_ci->dev.parent = &pdev->dev; | |
| 106 | − | |
| 107 | 92 | pci_set_drvdata(pdev, plat_ci); |
| 108 | 93 | |
| 109 | − retval = platform_device_add(plat_ci); | |
| 110 | − if (retval) | |
| 111 | − goto put_platform; | |
| 112 | − | |
| 113 | 94 | return 0; |
| 114 | 95 | |
| 115 | − put_platform: | |
| 116 | − pci_set_drvdata(pdev, NULL); | |
| 117 | − platform_device_put(plat_ci); | |
| 118 | 96 | disable_device: |
| 119 | 97 | pci_disable_device(pdev); |
| 120 | 98 | done: |
| @@ -133,7 +111,7 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) · 12 unmodified lines | ||
| 133 | 111 | { |
| 134 | 112 | struct platform_device *plat_ci = pci_get_drvdata(pdev); |
| 135 | 113 | |
| 136 | − platform_device_unregister(plat_ci); | |
| 114 | + ci13xxx_remove_device(plat_ci); | |
| 137 | 115 | pci_set_drvdata(pdev, NULL); |
| 138 | 116 | pci_disable_device(pdev); |
| 139 | 117 | } |
| @@ -147,19 +125,19 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) · 7 unmodified lines | ||
| 147 | 125 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { |
| 148 | 126 | { |
| 149 | 127 | PCI_DEVICE(0x153F, 0x1004), |
| 150 | − .driver_data = (kernel_ulong_t)&pci_driver, | |
| 128 | + .driver_data = (kernel_ulong_t)&pci_platdata, | |
| 151 | 129 | }, |
| 152 | 130 | { |
| 153 | 131 | PCI_DEVICE(0x153F, 0x1006), |
| 154 | − .driver_data = (kernel_ulong_t)&pci_driver, | |
| 132 | + .driver_data = (kernel_ulong_t)&pci_platdata, | |
| 155 | 133 | }, |
| 156 | 134 | { |
| 157 | 135 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), |
| 158 | − .driver_data = (kernel_ulong_t)&langwell_pci_driver, | |
| 136 | + .driver_data = (kernel_ulong_t)&langwell_pci_platdata, | |
| 159 | 137 | }, |
| 160 | 138 | { |
| 161 | 139 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), |
| 162 | − .driver_data = (kernel_ulong_t)&penwell_pci_driver, | |
| 140 | + .driver_data = (kernel_ulong_t)&penwell_pci_platdata, | |
| 163 | 141 | }, |
| 164 | 142 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } |
| 165 | 143 | }; |
| @@ -56,6 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #include <linux/init.h> |
| 57 | 57 | #include <linux/platform_device.h> |
| 58 | 58 | #include <linux/module.h> |
| 59 | +#include <linux/idr.h> | |
| 59 | 60 | #include <linux/interrupt.h> |
| 60 | 61 | #include <linux/io.h> |
| 61 | 62 | #include <linux/irq.h> |
| @@ -179,7 +180,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) · 117 unmodified lines | ||
| 179 | 180 | ci->hw_bank.abs = base; |
| 180 | 181 | |
| 181 | 182 | ci->hw_bank.cap = ci->hw_bank.abs; |
| 182 | − ci->hw_bank.cap += ci->udc_driver->capoffset; | |
| 183 | + ci->hw_bank.cap += ci->platdata->capoffset; | |
| 183 | 184 | ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap); |
| 184 | 185 | |
| 185 | 186 | hw_alloc_regmap(ci, false); |
| @@ -227,11 +228,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) · 41 unmodified lines | ||
| 227 | 228 | udelay(10); /* not RTOS friendly */ |
| 228 | 229 | |
| 229 | 230 | |
| 230 | − if (ci->udc_driver->notify_event) | |
| 231 | − ci->udc_driver->notify_event(ci, | |
| 231 | + if (ci->platdata->notify_event) | |
| 232 | + ci->platdata->notify_event(ci, | |
| 232 | 233 | CI13XXX_CONTROLLER_RESET_EVENT); |
| 233 | 234 | |
| 234 | − if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING) | |
| 235 | + if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | |
| 235 | 236 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
| 236 | 237 | |
| 237 | 238 | /* USBMODE should be configured step by step */ |
| @@ -332,6 +333,59 @@ static irqreturn_t ci_irq(int irq, void *data) · 94 unmodified lines | ||
| 332 | 333 | return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); |
| 333 | 334 | } |
| 334 | 335 | |
| 336 | +static DEFINE_IDA(ci_ida); | |
| 337 | + | |
| 338 | +struct platform_device *ci13xxx_add_device(struct device *dev, | |
| 339 | + struct resource *res, int nres, | |
| 340 | + struct ci13xxx_platform_data *platdata) | |
| 341 | +{ | |
| 342 | + struct platform_device *pdev; | |
| 343 | + int id, ret; | |
| 344 | + | |
| 345 | + id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); | |
| 346 | + if (id < 0) | |
| 347 | + return ERR_PTR(id); | |
| 348 | + | |
| 349 | + pdev = platform_device_alloc("ci_hdrc", id); | |
| 350 | + if (!pdev) { | |
| 351 | + ret = -ENOMEM; | |
| 352 | + goto put_id; | |
| 353 | + } | |
| 354 | + | |
| 355 | + pdev->dev.parent = dev; | |
| 356 | + pdev->dev.dma_mask = dev->dma_mask; | |
| 357 | + pdev->dev.dma_parms = dev->dma_parms; | |
| 358 | + dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); | |
| 359 | + | |
| 360 | + ret = platform_device_add_resources(pdev, res, nres); | |
| 361 | + if (ret) | |
| 362 | + goto err; | |
| 363 | + | |
| 364 | + ret = platform_device_add_data(pdev, platdata, sizeof(*platdata)); | |
| 365 | + if (ret) | |
| 366 | + goto err; | |
| 367 | + | |
| 368 | + ret = platform_device_add(pdev); | |
| 369 | + if (ret) | |
| 370 | + goto err; | |
| 371 | + | |
| 372 | + return pdev; | |
| 373 | + | |
| 374 | +err: | |
| 375 | + platform_device_put(pdev); | |
| 376 | +put_id: | |
| 377 | + ida_simple_remove(&ci_ida, id); | |
| 378 | + return ERR_PTR(ret); | |
| 379 | +} | |
| 380 | +EXPORT_SYMBOL_GPL(ci13xxx_add_device); | |
| 381 | + | |
| 382 | +void ci13xxx_remove_device(struct platform_device *pdev) | |
| 383 | +{ | |
| 384 | + platform_device_unregister(pdev); | |
| 385 | + ida_simple_remove(&ci_ida, pdev->id); | |
| 386 | +} | |
| 387 | +EXPORT_SYMBOL_GPL(ci13xxx_remove_device); | |
| 388 | + | |
| 335 | 389 | static int __devinit ci_hdrc_probe(struct platform_device *pdev) |
| 336 | 390 | { |
| 337 | 391 | struct device *dev = &pdev->dev; |
| @@ -364,7 +418,11 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) · 26 unmodified lines | ||
| 364 | 418 | } |
| 365 | 419 | |
| 366 | 420 | ci->dev = dev; |
| 367 | − ci->udc_driver = dev->platform_data; | |
| 421 | + ci->platdata = dev->platform_data; | |
| 422 | + if (ci->platdata->phy) | |
| 423 | + ci->transceiver = ci->platdata->phy; | |
| 424 | + else | |
| 425 | + ci->global_phy = true; | |
| 368 | 426 | |
| 369 | 427 | ret = hw_device_init(ci, base); |
| 370 | 428 | if (ret < 0) { |
| @@ -419,7 +477,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) · 48 unmodified lines | ||
| 419 | 477 | } |
| 420 | 478 | |
| 421 | 479 | platform_set_drvdata(pdev, ci); |
| 422 | − ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name, | |
| 480 | + ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, | |
| 423 | 481 | ci); |
| 424 | 482 | if (ret) |
| 425 | 483 | goto stop; |
| @@ -68,15 +68,15 @@ void dbg_interrupt(u32 intmask) · 67 unmodified lines | ||
| 68 | 68 | * |
| 69 | 69 | * This function returns number of registers read |
| 70 | 70 | */ |
| 71 | −static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size) | |
| 71 | +static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size) | |
| 72 | 72 | { |
| 73 | 73 | unsigned i; |
| 74 | 74 | |
| 75 | − if (size > udc->hw_bank.size) | |
| 76 | − size = udc->hw_bank.size; | |
| 75 | + if (size > ci->hw_bank.size) | |
| 76 | + size = ci->hw_bank.size; | |
| 77 | 77 | |
| 78 | 78 | for (i = 0; i < size; i++) |
| 79 | − buf[i] = hw_read(udc, i * sizeof(u32), ~0); | |
| 79 | + buf[i] = hw_read(ci, i * sizeof(u32), ~0); | |
| 80 | 80 | |
| 81 | 81 | return size; |
| 82 | 82 | } |
| @@ -88,18 +88,18 @@ static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size) · 5 unmodified lines | ||
| 88 | 88 | * |
| 89 | 89 | * This function returns an error code |
| 90 | 90 | */ |
| 91 | −static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data) | |
| 91 | +static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data) | |
| 92 | 92 | { |
| 93 | 93 | /* align */ |
| 94 | 94 | addr /= sizeof(u32); |
| 95 | 95 | |
| 96 | − if (addr >= udc->hw_bank.size) | |
| 96 | + if (addr >= ci->hw_bank.size) | |
| 97 | 97 | return -EINVAL; |
| 98 | 98 | |
| 99 | 99 | /* align */ |
| 100 | 100 | addr *= sizeof(u32); |
| 101 | 101 | |
| 102 | − hw_write(udc, addr, ~0, data); | |
| 102 | + hw_write(ci, addr, ~0, data); | |
| 103 | 103 | return 0; |
| 104 | 104 | } |
| 105 | 105 | |
| @@ -110,13 +110,13 @@ static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data) · 4 unmodified lines | ||
| 110 | 110 | * |
| 111 | 111 | * This function returns an error code |
| 112 | 112 | */ |
| 113 | −static int hw_intr_clear(struct ci13xxx *udc, int n) | |
| 113 | +static int hw_intr_clear(struct ci13xxx *ci, int n) | |
| 114 | 114 | { |
| 115 | 115 | if (n >= REG_BITS) |
| 116 | 116 | return -EINVAL; |
| 117 | 117 | |
| 118 | − hw_write(udc, OP_USBINTR, BIT(n), 0); | |
| 119 | − hw_write(udc, OP_USBSTS, BIT(n), BIT(n)); | |
| 118 | + hw_write(ci, OP_USBINTR, BIT(n), 0); | |
| 119 | + hw_write(ci, OP_USBSTS, BIT(n), BIT(n)); | |
| 120 | 120 | return 0; |
| 121 | 121 | } |
| 122 | 122 | |
| @@ -127,15 +127,15 @@ static int hw_intr_clear(struct ci13xxx *udc, int n) · 4 unmodified lines | ||
| 127 | 127 | * |
| 128 | 128 | * This function returns an error code |
| 129 | 129 | */ |
| 130 | −static int hw_intr_force(struct ci13xxx *udc, int n) | |
| 130 | +static int hw_intr_force(struct ci13xxx *ci, int n) | |
| 131 | 131 | { |
| 132 | 132 | if (n >= REG_BITS) |
| 133 | 133 | return -EINVAL; |
| 134 | 134 | |
| 135 | − hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); | |
| 136 | − hw_write(udc, OP_USBINTR, BIT(n), BIT(n)); | |
| 137 | − hw_write(udc, OP_USBSTS, BIT(n), BIT(n)); | |
| 138 | − hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0); | |
| 135 | + hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); | |
| 136 | + hw_write(ci, OP_USBINTR, BIT(n), BIT(n)); | |
| 137 | + hw_write(ci, OP_USBSTS, BIT(n), BIT(n)); | |
| 138 | + hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0); | |
| 139 | 139 | return 0; |
| 140 | 140 | } |
| 141 | 141 | |
| @@ -147,12 +147,12 @@ static int hw_intr_force(struct ci13xxx *udc, int n) · 5 unmodified lines | ||
| 147 | 147 | static ssize_t show_device(struct device *dev, struct device_attribute *attr, |
| 148 | 148 | char *buf) |
| 149 | 149 | { |
| 150 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 151 | − struct usb_gadget *gadget = &udc->gadget; | |
| 150 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 151 | + struct usb_gadget *gadget = &ci->gadget; | |
| 152 | 152 | int n = 0; |
| 153 | 153 | |
| 154 | 154 | if (attr == NULL || buf == NULL) { |
| 155 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 155 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 156 | 156 | return 0; |
| 157 | 157 | } |
| 158 | 158 | |
| @@ -188,8 +188,8 @@ static DEVICE_ATTR(device, S_IRUSR, show_device, NULL); · 29 unmodified lines | ||
| 188 | 188 | static ssize_t show_driver(struct device *dev, struct device_attribute *attr, |
| 189 | 189 | char *buf) |
| 190 | 190 | { |
| 191 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 192 | − struct usb_gadget_driver *driver = udc->driver; | |
| 191 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 192 | + struct usb_gadget_driver *driver = ci->driver; | |
| 193 | 193 | int n = 0; |
| 194 | 194 | |
| 195 | 195 | if (attr == NULL || buf == NULL) { |
| @@ -412,22 +412,22 @@ static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events); · 216 unmodified lines | ||
| 412 | 412 | static ssize_t show_inters(struct device *dev, struct device_attribute *attr, |
| 413 | 413 | char *buf) |
| 414 | 414 | { |
| 415 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 415 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 416 | 416 | unsigned long flags; |
| 417 | 417 | u32 intr; |
| 418 | 418 | unsigned i, j, n = 0; |
| 419 | 419 | |
| 420 | 420 | if (attr == NULL || buf == NULL) { |
| 421 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 421 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 422 | 422 | return 0; |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | − spin_lock_irqsave(&udc->lock, flags); | |
| 425 | + spin_lock_irqsave(&ci->lock, flags); | |
| 426 | 426 | |
| 427 | 427 | /*n += scnprintf(buf + n, PAGE_SIZE - n, |
| 428 | − "status = %08x\n", hw_read_intr_status(udc)); | |
| 428 | + "status = %08x\n", hw_read_intr_status(ci)); | |
| 429 | 429 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| 430 | − "enable = %08x\n", hw_read_intr_enable(udc));*/ | |
| 430 | + "enable = %08x\n", hw_read_intr_enable(ci));*/ | |
| 431 | 431 | |
| 432 | 432 | n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n", |
| 433 | 433 | isr_statistics.test); |
| @@ -471,7 +471,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr, · 37 unmodified lines | ||
| 471 | 471 | n += scnprintf(buf + n, PAGE_SIZE - n, "\n"); |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 474 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 475 | 475 | |
| 476 | 476 | return n; |
| 477 | 477 | } |
| @@ -485,31 +485,31 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr, · 7 unmodified lines | ||
| 485 | 485 | static ssize_t store_inters(struct device *dev, struct device_attribute *attr, |
| 486 | 486 | const char *buf, size_t count) |
| 487 | 487 | { |
| 488 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 488 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 489 | 489 | unsigned long flags; |
| 490 | 490 | unsigned en, bit; |
| 491 | 491 | |
| 492 | 492 | if (attr == NULL || buf == NULL) { |
| 493 | − dev_err(udc->dev, "EINVAL\n"); | |
| 493 | + dev_err(ci->dev, "EINVAL\n"); | |
| 494 | 494 | goto done; |
| 495 | 495 | } |
| 496 | 496 | |
| 497 | 497 | if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) { |
| 498 | − dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n"); | |
| 498 | + dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n"); | |
| 499 | 499 | goto done; |
| 500 | 500 | } |
| 501 | 501 | |
| 502 | − spin_lock_irqsave(&udc->lock, flags); | |
| 502 | + spin_lock_irqsave(&ci->lock, flags); | |
| 503 | 503 | if (en) { |
| 504 | − if (hw_intr_force(udc, bit)) | |
| 504 | + if (hw_intr_force(ci, bit)) | |
| 505 | 505 | dev_err(dev, "invalid bit number\n"); |
| 506 | 506 | else |
| 507 | 507 | isr_statistics.test++; |
| 508 | 508 | } else { |
| 509 | − if (hw_intr_clear(udc, bit)) | |
| 509 | + if (hw_intr_clear(ci, bit)) | |
| 510 | 510 | dev_err(dev, "invalid bit number\n"); |
| 511 | 511 | } |
| 512 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 512 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 513 | 513 | |
| 514 | 514 | done: |
| 515 | 515 | return count; |
| @@ -524,18 +524,18 @@ static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters); · 8 unmodified lines | ||
| 524 | 524 | static ssize_t show_port_test(struct device *dev, |
| 525 | 525 | struct device_attribute *attr, char *buf) |
| 526 | 526 | { |
| 527 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 527 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 528 | 528 | unsigned long flags; |
| 529 | 529 | unsigned mode; |
| 530 | 530 | |
| 531 | 531 | if (attr == NULL || buf == NULL) { |
| 532 | − dev_err(udc->dev, "EINVAL\n"); | |
| 532 | + dev_err(ci->dev, "EINVAL\n"); | |
| 533 | 533 | return 0; |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | − spin_lock_irqsave(&udc->lock, flags); | |
| 537 | − mode = hw_port_test_get(udc); | |
| 538 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 536 | + spin_lock_irqsave(&ci->lock, flags); | |
| 537 | + mode = hw_port_test_get(ci); | |
| 538 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 539 | 539 | |
| 540 | 540 | return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode); |
| 541 | 541 | } |
| @@ -549,24 +549,24 @@ static ssize_t store_port_test(struct device *dev, · 7 unmodified lines | ||
| 549 | 549 | struct device_attribute *attr, |
| 550 | 550 | const char *buf, size_t count) |
| 551 | 551 | { |
| 552 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 552 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 553 | 553 | unsigned long flags; |
| 554 | 554 | unsigned mode; |
| 555 | 555 | |
| 556 | 556 | if (attr == NULL || buf == NULL) { |
| 557 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 557 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 558 | 558 | goto done; |
| 559 | 559 | } |
| 560 | 560 | |
| 561 | 561 | if (sscanf(buf, "%u", &mode) != 1) { |
| 562 | − dev_err(udc->dev, "<mode>: set port test mode"); | |
| 562 | + dev_err(ci->dev, "<mode>: set port test mode"); | |
| 563 | 563 | goto done; |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | − spin_lock_irqsave(&udc->lock, flags); | |
| 567 | − if (hw_port_test_set(udc, mode)) | |
| 568 | − dev_err(udc->dev, "invalid mode\n"); | |
| 569 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 566 | + spin_lock_irqsave(&ci->lock, flags); | |
| 567 | + if (hw_port_test_set(ci, mode)) | |
| 568 | + dev_err(ci->dev, "invalid mode\n"); | |
| 569 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 570 | 570 | |
| 571 | 571 | done: |
| 572 | 572 | return count; |
| @@ -582,20 +582,20 @@ static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR, · 9 unmodified lines | ||
| 582 | 582 | static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, |
| 583 | 583 | char *buf) |
| 584 | 584 | { |
| 585 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 585 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 586 | 586 | unsigned long flags; |
| 587 | 587 | unsigned i, j, n = 0; |
| 588 | 588 | |
| 589 | 589 | if (attr == NULL || buf == NULL) { |
| 590 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 590 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 591 | 591 | return 0; |
| 592 | 592 | } |
| 593 | 593 | |
| 594 | − spin_lock_irqsave(&udc->lock, flags); | |
| 595 | − for (i = 0; i < udc->hw_ep_max/2; i++) { | |
| 596 | − struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i]; | |
| 594 | + spin_lock_irqsave(&ci->lock, flags); | |
| 595 | + for (i = 0; i < ci->hw_ep_max/2; i++) { | |
| 596 | + struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; | |
| 597 | 597 | struct ci13xxx_ep *mEpTx = |
| 598 | − &udc->ci13xxx_ep[i + udc->hw_ep_max/2]; | |
| 598 | + &ci->ci13xxx_ep[i + ci->hw_ep_max/2]; | |
| 599 | 599 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| 600 | 600 | "EP=%02i: RX=%08X TX=%08X\n", |
| 601 | 601 | i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); |
| @@ -606,7 +606,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, · 4 unmodified lines | ||
| 606 | 606 | *((u32 *)mEpTx->qh.ptr + j)); |
| 607 | 607 | } |
| 608 | 608 | } |
| 609 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 609 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 610 | 610 | |
| 611 | 611 | return n; |
| 612 | 612 | } |
| @@ -621,25 +621,25 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); · 8 unmodified lines | ||
| 621 | 621 | static ssize_t show_registers(struct device *dev, |
| 622 | 622 | struct device_attribute *attr, char *buf) |
| 623 | 623 | { |
| 624 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 624 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 625 | 625 | unsigned long flags; |
| 626 | 626 | u32 *dump; |
| 627 | 627 | unsigned i, k, n = 0; |
| 628 | 628 | |
| 629 | 629 | if (attr == NULL || buf == NULL) { |
| 630 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 630 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 631 | 631 | return 0; |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | 634 | dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); |
| 635 | 635 | if (!dump) { |
| 636 | − dev_err(udc->dev, "%s: out of memory\n", __func__); | |
| 636 | + dev_err(ci->dev, "%s: out of memory\n", __func__); | |
| 637 | 637 | return 0; |
| 638 | 638 | } |
| 639 | 639 | |
| 640 | − spin_lock_irqsave(&udc->lock, flags); | |
| 641 | − k = hw_register_read(udc, dump, DUMP_ENTRIES); | |
| 642 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 640 | + spin_lock_irqsave(&ci->lock, flags); | |
| 641 | + k = hw_register_read(ci, dump, DUMP_ENTRIES); | |
| 642 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 643 | 643 | |
| 644 | 644 | for (i = 0; i < k; i++) { |
| 645 | 645 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| @@ -660,24 +660,24 @@ static ssize_t store_registers(struct device *dev, · 14 unmodified lines | ||
| 660 | 660 | struct device_attribute *attr, |
| 661 | 661 | const char *buf, size_t count) |
| 662 | 662 | { |
| 663 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 663 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 664 | 664 | unsigned long addr, data, flags; |
| 665 | 665 | |
| 666 | 666 | if (attr == NULL || buf == NULL) { |
| 667 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 667 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 668 | 668 | goto done; |
| 669 | 669 | } |
| 670 | 670 | |
| 671 | 671 | if (sscanf(buf, "%li %li", &addr, &data) != 2) { |
| 672 | − dev_err(udc->dev, | |
| 672 | + dev_err(ci->dev, | |
| 673 | 673 | "<addr> <data>: write data to register address\n"); |
| 674 | 674 | goto done; |
| 675 | 675 | } |
| 676 | 676 | |
| 677 | − spin_lock_irqsave(&udc->lock, flags); | |
| 678 | − if (hw_register_write(udc, addr, data)) | |
| 679 | − dev_err(udc->dev, "invalid address range\n"); | |
| 680 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 677 | + spin_lock_irqsave(&ci->lock, flags); | |
| 678 | + if (hw_register_write(ci, addr, data)) | |
| 679 | + dev_err(ci->dev, "invalid address range\n"); | |
| 680 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 681 | 681 | |
| 682 | 682 | done: |
| 683 | 683 | return count; |
| @@ -693,34 +693,34 @@ static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR, · 9 unmodified lines | ||
| 693 | 693 | static ssize_t show_requests(struct device *dev, struct device_attribute *attr, |
| 694 | 694 | char *buf) |
| 695 | 695 | { |
| 696 | − struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | |
| 696 | + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); | |
| 697 | 697 | unsigned long flags; |
| 698 | 698 | struct list_head *ptr = NULL; |
| 699 | 699 | struct ci13xxx_req *req = NULL; |
| 700 | 700 | unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); |
| 701 | 701 | |
| 702 | 702 | if (attr == NULL || buf == NULL) { |
| 703 | − dev_err(udc->dev, "[%s] EINVAL\n", __func__); | |
| 703 | + dev_err(ci->dev, "[%s] EINVAL\n", __func__); | |
| 704 | 704 | return 0; |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | − spin_lock_irqsave(&udc->lock, flags); | |
| 708 | − for (i = 0; i < udc->hw_ep_max; i++) | |
| 709 | − list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) | |
| 707 | + spin_lock_irqsave(&ci->lock, flags); | |
| 708 | + for (i = 0; i < ci->hw_ep_max; i++) | |
| 709 | + list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) | |
| 710 | 710 | { |
| 711 | 711 | req = list_entry(ptr, struct ci13xxx_req, queue); |
| 712 | 712 | |
| 713 | 713 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| 714 | 714 | "EP=%02i: TD=%08X %s\n", |
| 715 | − i % udc->hw_ep_max/2, (u32)req->dma, | |
| 716 | − ((i < udc->hw_ep_max/2) ? "RX" : "TX")); | |
| 715 | + i % ci->hw_ep_max/2, (u32)req->dma, | |
| 716 | + ((i < ci->hw_ep_max/2) ? "RX" : "TX")); | |
| 717 | 717 | |
| 718 | 718 | for (j = 0; j < qSize; j++) |
| 719 | 719 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| 720 | 720 | " %04X: %08X\n", j, |
| 721 | 721 | *((u32 *)req->ptr + j)); |
| 722 | 722 | } |
| 723 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 723 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 724 | 724 | |
| 725 | 725 | return n; |
| 726 | 726 | } |
| @@ -116,7 +116,8 @@ static int host_start(struct ci13xxx *ci) · 115 unmodified lines | ||
| 116 | 116 | hcd->regs = ci->hw_bank.abs; |
| 117 | 117 | hcd->has_tt = 1; |
| 118 | 118 | |
| 119 | − hcd->power_budget = ci->udc_driver->power_budget; | |
| 119 | + hcd->power_budget = ci->platdata->power_budget; | |
| 120 | + hcd->phy = ci->transceiver; | |
| 120 | 121 | |
| 121 | 122 | ehci = hcd_to_ehci(hcd); |
| 122 | 123 | ehci->caps = ci->hw_bank.cap; |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/device.h> |
| 15 | 15 | #include <linux/dmapool.h> |
| 16 | 16 | #include <linux/dma-mapping.h> |
| 17 | +#include <linux/err.h> | |
| 17 | 18 | #include <linux/init.h> |
| 18 | 19 | #include <linux/platform_device.h> |
| 19 | 20 | #include <linux/module.h> |
| @@ -66,11 +67,11 @@ static inline int hw_ep_bit(int num, int dir) · 46 unmodified lines | ||
| 66 | 67 | return num + (dir ? 16 : 0); |
| 67 | 68 | } |
| 68 | 69 | |
| 69 | −static inline int ep_to_bit(struct ci13xxx *udc, int n) | |
| 70 | +static inline int ep_to_bit(struct ci13xxx *ci, int n) | |
| 70 | 71 | { |
| 71 | − int fill = 16 - udc->hw_ep_max / 2; | |
| 72 | + int fill = 16 - ci->hw_ep_max / 2; | |
| 72 | 73 | |
| 73 | − if (n >= udc->hw_ep_max / 2) | |
| 74 | + if (n >= ci->hw_ep_max / 2) | |
| 74 | 75 | n += fill; |
| 75 | 76 | |
| 76 | 77 | return n; |
| @@ -83,17 +84,17 @@ static inline int ep_to_bit(struct ci13xxx *udc, int n) · 6 unmodified lines | ||
| 83 | 84 | * |
| 84 | 85 | * This function returns an error code |
| 85 | 86 | */ |
| 86 | −static int hw_device_state(struct ci13xxx *udc, u32 dma) | |
| 87 | +static int hw_device_state(struct ci13xxx *ci, u32 dma) | |
| 87 | 88 | { |
| 88 | 89 | if (dma) { |
| 89 | − hw_write(udc, OP_ENDPTLISTADDR, ~0, dma); | |
| 90 | + hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); | |
| 90 | 91 | /* interrupt, error, port change, reset, sleep/suspend */ |
| 91 | − hw_write(udc, OP_USBINTR, ~0, | |
| 92 | + hw_write(ci, OP_USBINTR, ~0, | |
| 92 | 93 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); |
| 93 | − hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS); | |
| 94 | + hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); | |
| 94 | 95 | } else { |
| 95 | − hw_write(udc, OP_USBCMD, USBCMD_RS, 0); | |
| 96 | − hw_write(udc, OP_USBINTR, ~0, 0); | |
| 96 | + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); | |
| 97 | + hw_write(ci, OP_USBINTR, ~0, 0); | |
| 97 | 98 | } |
| 98 | 99 | return 0; |
| 99 | 100 | } |
| @@ -105,16 +106,16 @@ static int hw_device_state(struct ci13xxx *udc, u32 dma) · 5 unmodified lines | ||
| 105 | 106 | * |
| 106 | 107 | * This function returns an error code |
| 107 | 108 | */ |
| 108 | −static int hw_ep_flush(struct ci13xxx *udc, int num, int dir) | |
| 109 | +static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) | |
| 109 | 110 | { |
| 110 | 111 | int n = hw_ep_bit(num, dir); |
| 111 | 112 | |
| 112 | 113 | do { |
| 113 | 114 | /* flush any pending transfer */ |
| 114 | − hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n)); | |
| 115 | − while (hw_read(udc, OP_ENDPTFLUSH, BIT(n))) | |
| 115 | + hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); | |
| 116 | + while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) | |
| 116 | 117 | cpu_relax(); |
| 117 | − } while (hw_read(udc, OP_ENDPTSTAT, BIT(n))); | |
| 118 | + } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); | |
| 118 | 119 | |
| 119 | 120 | return 0; |
| 120 | 121 | } |
| @@ -126,10 +127,10 @@ static int hw_ep_flush(struct ci13xxx *udc, int num, int dir) · 5 unmodified lines | ||
| 126 | 127 | * |
| 127 | 128 | * This function returns an error code |
| 128 | 129 | */ |
| 129 | −static int hw_ep_disable(struct ci13xxx *udc, int num, int dir) | |
| 130 | +static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) | |
| 130 | 131 | { |
| 131 | − hw_ep_flush(udc, num, dir); | |
| 132 | − hw_write(udc, OP_ENDPTCTRL + num, | |
| 132 | + hw_ep_flush(ci, num, dir); | |
| 133 | + hw_write(ci, OP_ENDPTCTRL + num, | |
| 133 | 134 | dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); |
| 134 | 135 | return 0; |
| 135 | 136 | } |
| @@ -142,7 +143,7 @@ static int hw_ep_disable(struct ci13xxx *udc, int num, int dir) · 6 unmodified lines | ||
| 142 | 143 | * |
| 143 | 144 | * This function returns an error code |
| 144 | 145 | */ |
| 145 | −static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) | |
| 146 | +static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) | |
| 146 | 147 | { |
| 147 | 148 | u32 mask, data; |
| 148 | 149 | |
| @@ -165,7 +166,7 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) · 16 unmodified lines | ||
| 165 | 166 | mask |= ENDPTCTRL_RXE; /* enable */ |
| 166 | 167 | data |= ENDPTCTRL_RXE; |
| 167 | 168 | } |
| 168 | − hw_write(udc, OP_ENDPTCTRL + num, mask, data); | |
| 169 | + hw_write(ci, OP_ENDPTCTRL + num, mask, data); | |
| 169 | 170 | return 0; |
| 170 | 171 | } |
| 171 | 172 | |
| @@ -176,11 +177,11 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) · 4 unmodified lines | ||
| 176 | 177 | * |
| 177 | 178 | * This function returns 1 if endpoint halted |
| 178 | 179 | */ |
| 179 | −static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir) | |
| 180 | +static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) | |
| 180 | 181 | { |
| 181 | 182 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; |
| 182 | 183 | |
| 183 | − return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0; | |
| 184 | + return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; | |
| 184 | 185 | } |
| 185 | 186 | |
| 186 | 187 | /** |
| @@ -190,10 +191,10 @@ static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir) · 3 unmodified lines | ||
| 190 | 191 | * |
| 191 | 192 | * This function returns setup status |
| 192 | 193 | */ |
| 193 | −static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n) | |
| 194 | +static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) | |
| 194 | 195 | { |
| 195 | − n = ep_to_bit(udc, n); | |
| 196 | − return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n)); | |
| 196 | + n = ep_to_bit(ci, n); | |
| 197 | + return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); | |
| 197 | 198 | } |
| 198 | 199 | |
| 199 | 200 | /** |
| @@ -204,18 +205,18 @@ static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n) · 4 unmodified lines | ||
| 204 | 205 | * |
| 205 | 206 | * This function returns an error code |
| 206 | 207 | */ |
| 207 | −static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl) | |
| 208 | +static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) | |
| 208 | 209 | { |
| 209 | 210 | int n = hw_ep_bit(num, dir); |
| 210 | 211 | |
| 211 | − if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num))) | |
| 212 | + if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) | |
| 212 | 213 | return -EAGAIN; |
| 213 | 214 | |
| 214 | − hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n)); | |
| 215 | + hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); | |
| 215 | 216 | |
| 216 | − while (hw_read(udc, OP_ENDPTPRIME, BIT(n))) | |
| 217 | + while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) | |
| 217 | 218 | cpu_relax(); |
| 218 | − if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num))) | |
| 219 | + if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) | |
| 219 | 220 | return -EAGAIN; |
| 220 | 221 | |
| 221 | 222 | /* status shoult be tested according with manual but it doesn't work */ |
| @@ -231,7 +232,7 @@ static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl) · 9 unmodified lines | ||
| 231 | 232 | * |
| 232 | 233 | * This function returns an error code |
| 233 | 234 | */ |
| 234 | −static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) | |
| 235 | +static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) | |
| 235 | 236 | { |
| 236 | 237 | if (value != 0 && value != 1) |
| 237 | 238 | return -EINVAL; |
| @@ -242,9 +243,9 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) · 4 unmodified lines | ||
| 242 | 243 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; |
| 243 | 244 | |
| 244 | 245 | /* data toggle - reserved for EP0 but it's in ESS */ |
| 245 | − hw_write(udc, reg, mask_xs|mask_xr, | |
| 246 | + hw_write(ci, reg, mask_xs|mask_xr, | |
| 246 | 247 | value ? mask_xs : mask_xr); |
| 247 | − } while (value != hw_ep_get_halt(udc, num, dir)); | |
| 248 | + } while (value != hw_ep_get_halt(ci, num, dir)); | |
| 248 | 249 | |
| 249 | 250 | return 0; |
| 250 | 251 | } |
| @@ -254,10 +255,10 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) · 3 unmodified lines | ||
| 254 | 255 | * |
| 255 | 256 | * This function returns true if high speed port |
| 256 | 257 | */ |
| 257 | −static int hw_port_is_high_speed(struct ci13xxx *udc) | |
| 258 | +static int hw_port_is_high_speed(struct ci13xxx *ci) | |
| 258 | 259 | { |
| 259 | − return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) : | |
| 260 | − hw_read(udc, OP_PORTSC, PORTSC_HSP); | |
| 260 | + return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : | |
| 261 | + hw_read(ci, OP_PORTSC, PORTSC_HSP); | |
| 261 | 262 | } |
| 262 | 263 | |
| 263 | 264 | /** |
| @@ -265,9 +266,9 @@ static int hw_port_is_high_speed(struct ci13xxx *udc) · 1 unmodified line | ||
| 265 | 266 | * |
| 266 | 267 | * This function returns register data |
| 267 | 268 | */ |
| 268 | −static u32 hw_read_intr_enable(struct ci13xxx *udc) | |
| 269 | +static u32 hw_read_intr_enable(struct ci13xxx *ci) | |
| 269 | 270 | { |
| 270 | − return hw_read(udc, OP_USBINTR, ~0); | |
| 271 | + return hw_read(ci, OP_USBINTR, ~0); | |
| 271 | 272 | } |
| 272 | 273 | |
| 273 | 274 | /** |
| @@ -275,9 +276,9 @@ static u32 hw_read_intr_enable(struct ci13xxx *udc) · 1 unmodified line | ||
| 275 | 276 | * |
| 276 | 277 | * This function returns register data |
| 277 | 278 | */ |
| 278 | −static u32 hw_read_intr_status(struct ci13xxx *udc) | |
| 279 | +static u32 hw_read_intr_status(struct ci13xxx *ci) | |
| 279 | 280 | { |
| 280 | − return hw_read(udc, OP_USBSTS, ~0); | |
| 281 | + return hw_read(ci, OP_USBSTS, ~0); | |
| 281 | 282 | } |
| 282 | 283 | |
| 283 | 284 | /** |
| @@ -287,10 +288,10 @@ static u32 hw_read_intr_status(struct ci13xxx *udc) · 3 unmodified lines | ||
| 287 | 288 | * |
| 288 | 289 | * This function returns complete status |
| 289 | 290 | */ |
| 290 | −static int hw_test_and_clear_complete(struct ci13xxx *udc, int n) | |
| 291 | +static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) | |
| 291 | 292 | { |
| 292 | − n = ep_to_bit(udc, n); | |
| 293 | − return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n)); | |
| 293 | + n = ep_to_bit(ci, n); | |
| 294 | + return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); | |
| 294 | 295 | } |
| 295 | 296 | |
| 296 | 297 | /** |
| @@ -299,11 +300,11 @@ static int hw_test_and_clear_complete(struct ci13xxx *udc, int n) · 2 unmodified lines | ||
| 299 | 300 | * |
| 300 | 301 | * This function returns active interrutps |
| 301 | 302 | */ |
| 302 | −static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc) | |
| 303 | +static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) | |
| 303 | 304 | { |
| 304 | − u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc); | |
| 305 | + u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); | |
| 305 | 306 | |
| 306 | − hw_write(udc, OP_USBSTS, ~0, reg); | |
| 307 | + hw_write(ci, OP_USBSTS, ~0, reg); | |
| 307 | 308 | return reg; |
| 308 | 309 | } |
| 309 | 310 | |
| @@ -313,9 +314,9 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc) · 3 unmodified lines | ||
| 313 | 314 | * |
| 314 | 315 | * This function returns guard value |
| 315 | 316 | */ |
| 316 | −static int hw_test_and_clear_setup_guard(struct ci13xxx *udc) | |
| 317 | +static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) | |
| 317 | 318 | { |
| 318 | − return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0); | |
| 319 | + return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); | |
| 319 | 320 | } |
| 320 | 321 | |
| 321 | 322 | /** |
| @@ -324,9 +325,9 @@ static int hw_test_and_clear_setup_guard(struct ci13xxx *udc) · 2 unmodified lines | ||
| 324 | 325 | * |
| 325 | 326 | * This function returns guard value |
| 326 | 327 | */ |
| 327 | −static int hw_test_and_set_setup_guard(struct ci13xxx *udc) | |
| 328 | +static int hw_test_and_set_setup_guard(struct ci13xxx *ci) | |
| 328 | 329 | { |
| 329 | − return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | |
| 330 | + return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | |
| 330 | 331 | } |
| 331 | 332 | |
| 332 | 333 | /** |
| @@ -336,9 +337,9 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *udc) · 3 unmodified lines | ||
| 336 | 337 | * This function explicitly sets the address, without the "USBADRA" (advance) |
| 337 | 338 | * feature, which is not supported by older versions of the controller. |
| 338 | 339 | */ |
| 339 | −static void hw_usb_set_address(struct ci13xxx *udc, u8 value) | |
| 340 | +static void hw_usb_set_address(struct ci13xxx *ci, u8 value) | |
| 340 | 341 | { |
| 341 | − hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR, | |
| 342 | + hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, | |
| 342 | 343 | value << ffs_nr(DEVICEADDR_USBADR)); |
| 343 | 344 | } |
| 344 | 345 | |
| @@ -348,21 +349,21 @@ static void hw_usb_set_address(struct ci13xxx *udc, u8 value) · 3 unmodified lines | ||
| 348 | 349 | * |
| 349 | 350 | * This function returns an error code |
| 350 | 351 | */ |
| 351 | −static int hw_usb_reset(struct ci13xxx *udc) | |
| 352 | +static int hw_usb_reset(struct ci13xxx *ci) | |
| 352 | 353 | { |
| 353 | − hw_usb_set_address(udc, 0); | |
| 354 | + hw_usb_set_address(ci, 0); | |
| 354 | 355 | |
| 355 | 356 | /* ESS flushes only at end?!? */ |
| 356 | − hw_write(udc, OP_ENDPTFLUSH, ~0, ~0); | |
| 357 | + hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); | |
| 357 | 358 | |
| 358 | 359 | /* clear setup token semaphores */ |
| 359 | − hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0); | |
| 360 | + hw_write(ci, OP_ENDPTSETUPSTAT, 0, 0); | |
| 360 | 361 | |
| 361 | 362 | /* clear complete status */ |
| 362 | − hw_write(udc, OP_ENDPTCOMPLETE, 0, 0); | |
| 363 | + hw_write(ci, OP_ENDPTCOMPLETE, 0, 0); | |
| 363 | 364 | |
| 364 | 365 | /* wait until all bits cleared */ |
| 365 | − while (hw_read(udc, OP_ENDPTPRIME, ~0)) | |
| 366 | + while (hw_read(ci, OP_ENDPTPRIME, ~0)) | |
| 366 | 367 | udelay(10); /* not RTOS friendly */ |
| 367 | 368 | |
| 368 | 369 | /* reset all endpoints ? */ |
| @@ -394,7 +395,7 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep) · 25 unmodified lines | ||
| 394 | 395 | */ |
| 395 | 396 | static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) |
| 396 | 397 | { |
| 397 | − struct ci13xxx *udc = mEp->udc; | |
| 398 | + struct ci13xxx *ci = mEp->ci; | |
| 398 | 399 | unsigned i; |
| 399 | 400 | int ret = 0; |
| 400 | 401 | unsigned length = mReq->req.length; |
| @@ -417,7 +418,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) · 16 unmodified lines | ||
| 417 | 418 | if (!mReq->req.no_interrupt) |
| 418 | 419 | mReq->zptr->token |= TD_IOC; |
| 419 | 420 | } |
| 420 | − ret = usb_gadget_map_request(&udc->gadget, &mReq->req, mEp->dir); | |
| 421 | + ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir); | |
| 421 | 422 | if (ret) |
| 422 | 423 | return ret; |
| 423 | 424 | |
| @@ -453,13 +454,13 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) · 29 unmodified lines | ||
| 453 | 454 | else |
| 454 | 455 | mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK; |
| 455 | 456 | wmb(); |
| 456 | − if (hw_read(udc, OP_ENDPTPRIME, BIT(n))) | |
| 457 | + if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) | |
| 457 | 458 | goto done; |
| 458 | 459 | do { |
| 459 | − hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); | |
| 460 | − tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n)); | |
| 461 | − } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW)); | |
| 462 | − hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0); | |
| 460 | + hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); | |
| 461 | + tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); | |
| 462 | + } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); | |
| 463 | + hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); | |
| 463 | 464 | if (tmp_stat) |
| 464 | 465 | goto done; |
| 465 | 466 | } |
| @@ -471,7 +472,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) · 5 unmodified lines | ||
| 471 | 472 | |
| 472 | 473 | wmb(); /* synchronize before ep prime */ |
| 473 | 474 | |
| 474 | − ret = hw_ep_prime(udc, mEp->num, mEp->dir, | |
| 475 | + ret = hw_ep_prime(ci, mEp->num, mEp->dir, | |
| 475 | 476 | mEp->type == USB_ENDPOINT_XFER_CONTROL); |
| 476 | 477 | done: |
| 477 | 478 | return ret; |
| @@ -501,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) · 23 unmodified lines | ||
| 501 | 502 | |
| 502 | 503 | mReq->req.status = 0; |
| 503 | 504 | |
| 504 | − usb_gadget_unmap_request(&mEp->udc->gadget, &mReq->req, mEp->dir); | |
| 505 | + usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir); | |
| 505 | 506 | |
| 506 | 507 | mReq->req.status = mReq->ptr->token & TD_STATUS; |
| 507 | 508 | if ((TD_STATUS_HALTED & mReq->req.status) != 0) |
| @@ -533,7 +534,7 @@ __acquires(mEp->lock) · 25 unmodified lines | ||
| 533 | 534 | if (mEp == NULL) |
| 534 | 535 | return -EINVAL; |
| 535 | 536 | |
| 536 | − hw_ep_flush(mEp->udc, mEp->num, mEp->dir); | |
| 537 | + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | |
| 537 | 538 | |
| 538 | 539 | while (!list_empty(&mEp->qh.queue)) { |
| 539 | 540 | |
| @@ -562,33 +563,33 @@ __acquires(mEp->lock) · 22 unmodified lines | ||
| 562 | 563 | static int _gadget_stop_activity(struct usb_gadget *gadget) |
| 563 | 564 | { |
| 564 | 565 | struct usb_ep *ep; |
| 565 | − struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | |
| 566 | + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | |
| 566 | 567 | unsigned long flags; |
| 567 | 568 | |
| 568 | − spin_lock_irqsave(&udc->lock, flags); | |
| 569 | − udc->gadget.speed = USB_SPEED_UNKNOWN; | |
| 570 | − udc->remote_wakeup = 0; | |
| 571 | − udc->suspended = 0; | |
| 572 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 569 | + spin_lock_irqsave(&ci->lock, flags); | |
| 570 | + ci->gadget.speed = USB_SPEED_UNKNOWN; | |
| 571 | + ci->remote_wakeup = 0; | |
| 572 | + ci->suspended = 0; | |
| 573 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 573 | 574 | |
| 574 | 575 | /* flush all endpoints */ |
| 575 | 576 | gadget_for_each_ep(ep, gadget) { |
| 576 | 577 | usb_ep_fifo_flush(ep); |
| 577 | 578 | } |
| 578 | − usb_ep_fifo_flush(&udc->ep0out->ep); | |
| 579 | − usb_ep_fifo_flush(&udc->ep0in->ep); | |
| 579 | + usb_ep_fifo_flush(&ci->ep0out->ep); | |
| 580 | + usb_ep_fifo_flush(&ci->ep0in->ep); | |
| 580 | 581 | |
| 581 | − if (udc->driver) | |
| 582 | − udc->driver->disconnect(gadget); | |
| 582 | + if (ci->driver) | |
| 583 | + ci->driver->disconnect(gadget); | |
| 583 | 584 | |
| 584 | 585 | /* make sure to disable all endpoints */ |
| 585 | 586 | gadget_for_each_ep(ep, gadget) { |
| 586 | 587 | usb_ep_disable(ep); |
| 587 | 588 | } |
| 588 | 589 | |
| 589 | − if (udc->status != NULL) { | |
| 590 | − usb_ep_free_request(&udc->ep0in->ep, udc->status); | |
| 591 | − udc->status = NULL; | |
| 590 | + if (ci->status != NULL) { | |
| 591 | + usb_ep_free_request(&ci->ep0in->ep, ci->status); | |
| 592 | + ci->status = NULL; | |
| 592 | 593 | } |
| 593 | 594 | |
| 594 | 595 | return 0; |
| @@ -599,36 +600,36 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) · 4 unmodified lines | ||
| 599 | 600 | *****************************************************************************/ |
| 600 | 601 | /** |
| 601 | 602 | * isr_reset_handler: USB reset interrupt handler |
| 602 | − * @udc: UDC device | |
| 603 | + * @ci: UDC device | |
| 603 | 604 | * |
| 604 | 605 | * This function resets USB engine after a bus reset occurred |
| 605 | 606 | */ |
| 606 | −static void isr_reset_handler(struct ci13xxx *udc) | |
| 607 | −__releases(udc->lock) | |
| 608 | −__acquires(udc->lock) | |
| 607 | +static void isr_reset_handler(struct ci13xxx *ci) | |
| 608 | +__releases(ci->lock) | |
| 609 | +__acquires(ci->lock) | |
| 609 | 610 | { |
| 610 | 611 | int retval; |
| 611 | 612 | |
| 612 | 613 | dbg_event(0xFF, "BUS RST", 0); |
| 613 | 614 | |
| 614 | − spin_unlock(&udc->lock); | |
| 615 | − retval = _gadget_stop_activity(&udc->gadget); | |
| 615 | + spin_unlock(&ci->lock); | |
| 616 | + retval = _gadget_stop_activity(&ci->gadget); | |
| 616 | 617 | if (retval) |
| 617 | 618 | goto done; |
| 618 | 619 | |
| 619 | − retval = hw_usb_reset(udc); | |
| 620 | + retval = hw_usb_reset(ci); | |
| 620 | 621 | if (retval) |
| 621 | 622 | goto done; |
| 622 | 623 | |
| 623 | − udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC); | |
| 624 | − if (udc->status == NULL) | |
| 624 | + ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC); | |
| 625 | + if (ci->status == NULL) | |
| 625 | 626 | retval = -ENOMEM; |
| 626 | 627 | |
| 627 | 628 | done: |
| 628 | − spin_lock(&udc->lock); | |
| 629 | + spin_lock(&ci->lock); | |
| 629 | 630 | |
| 630 | 631 | if (retval) |
| 631 | − dev_err(udc->dev, "error: %i\n", retval); | |
| 632 | + dev_err(ci->dev, "error: %i\n", retval); | |
| 632 | 633 | } |
| 633 | 634 | |
| 634 | 635 | /** |
| @@ -649,17 +650,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) · 14 unmodified lines | ||
| 649 | 650 | |
| 650 | 651 | /** |
| 651 | 652 | * isr_get_status_response: get_status request response |
| 652 | − * @udc: udc struct | |
| 653 | + * @ci: ci struct | |
| 653 | 654 | * @setup: setup request packet |
| 654 | 655 | * |
| 655 | 656 | * This function returns an error code |
| 656 | 657 | */ |
| 657 | −static int isr_get_status_response(struct ci13xxx *udc, | |
| 658 | +static int isr_get_status_response(struct ci13xxx *ci, | |
| 658 | 659 | struct usb_ctrlrequest *setup) |
| 659 | 660 | __releases(mEp->lock) |
| 660 | 661 | __acquires(mEp->lock) |
| 661 | 662 | { |
| 662 | − struct ci13xxx_ep *mEp = udc->ep0in; | |
| 663 | + struct ci13xxx_ep *mEp = ci->ep0in; | |
| 663 | 664 | struct usb_request *req = NULL; |
| 664 | 665 | gfp_t gfp_flags = GFP_ATOMIC; |
| 665 | 666 | int dir, num, retval; |
| @@ -683,14 +684,14 @@ __acquires(mEp->lock) · 17 unmodified lines | ||
| 683 | 684 | |
| 684 | 685 | if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { |
| 685 | 686 | /* Assume that device is bus powered for now. */ |
| 686 | − *(u16 *)req->buf = udc->remote_wakeup << 1; | |
| 687 | + *(u16 *)req->buf = ci->remote_wakeup << 1; | |
| 687 | 688 | retval = 0; |
| 688 | 689 | } else if ((setup->bRequestType & USB_RECIP_MASK) \ |
| 689 | 690 | == USB_RECIP_ENDPOINT) { |
| 690 | 691 | dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? |
| 691 | 692 | TX : RX; |
| 692 | 693 | num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; |
| 693 | − *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir); | |
| 694 | + *(u16 *)req->buf = hw_ep_get_halt(ci, num, dir); | |
| 694 | 695 | } |
| 695 | 696 | /* else do nothing; reserved for future use */ |
| 696 | 697 | |
| @@ -722,39 +723,39 @@ __acquires(mEp->lock) · 25 unmodified lines | ||
| 722 | 723 | static void |
| 723 | 724 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) |
| 724 | 725 | { |
| 725 | − struct ci13xxx *udc = req->context; | |
| 726 | + struct ci13xxx *ci = req->context; | |
| 726 | 727 | unsigned long flags; |
| 727 | 728 | |
| 728 | − if (udc->setaddr) { | |
| 729 | − hw_usb_set_address(udc, udc->address); | |
| 730 | − udc->setaddr = false; | |
| 729 | + if (ci->setaddr) { | |
| 730 | + hw_usb_set_address(ci, ci->address); | |
| 731 | + ci->setaddr = false; | |
| 731 | 732 | } |
| 732 | 733 | |
| 733 | − spin_lock_irqsave(&udc->lock, flags); | |
| 734 | − if (udc->test_mode) | |
| 735 | − hw_port_test_set(udc, udc->test_mode); | |
| 736 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 734 | + spin_lock_irqsave(&ci->lock, flags); | |
| 735 | + if (ci->test_mode) | |
| 736 | + hw_port_test_set(ci, ci->test_mode); | |
| 737 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 737 | 738 | } |
| 738 | 739 | |
| 739 | 740 | /** |
| 740 | 741 | * isr_setup_status_phase: queues the status phase of a setup transation |
| 741 | − * @udc: udc struct | |
| 742 | + * @ci: ci struct | |
| 742 | 743 | * |
| 743 | 744 | * This function returns an error code |
| 744 | 745 | */ |
| 745 | −static int isr_setup_status_phase(struct ci13xxx *udc) | |
| 746 | +static int isr_setup_status_phase(struct ci13xxx *ci) | |
| 746 | 747 | __releases(mEp->lock) |
| 747 | 748 | __acquires(mEp->lock) |
| 748 | 749 | { |
| 749 | 750 | int retval; |
| 750 | 751 | struct ci13xxx_ep *mEp; |
| 751 | 752 | |
| 752 | − mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in; | |
| 753 | − udc->status->context = udc; | |
| 754 | − udc->status->complete = isr_setup_status_complete; | |
| 753 | + mEp = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; | |
| 754 | + ci->status->context = ci; | |
| 755 | + ci->status->complete = isr_setup_status_complete; | |
| 755 | 756 | |
| 756 | 757 | spin_unlock(mEp->lock); |
| 757 | − retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC); | |
| 758 | + retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC); | |
| 758 | 759 | spin_lock(mEp->lock); |
| 759 | 760 | |
| 760 | 761 | return retval; |
| @@ -789,7 +790,7 @@ __acquires(mEp->lock) · 28 unmodified lines | ||
| 789 | 790 | spin_unlock(mEp->lock); |
| 790 | 791 | if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && |
| 791 | 792 | mReq->req.length) |
| 792 | − mEpTemp = mEp->udc->ep0in; | |
| 793 | + mEpTemp = mEp->ci->ep0in; | |
| 793 | 794 | mReq->req.complete(&mEpTemp->ep, &mReq->req); |
| 794 | 795 | spin_lock(mEp->lock); |
| 795 | 796 | } |
| @@ -805,48 +806,48 @@ __acquires(mEp->lock) · 9 unmodified lines | ||
| 805 | 806 | |
| 806 | 807 | /** |
| 807 | 808 | * isr_tr_complete_handler: transaction complete interrupt handler |
| 808 | − * @udc: UDC descriptor | |
| 809 | + * @ci: UDC descriptor | |
| 809 | 810 | * |
| 810 | 811 | * This function handles traffic events |
| 811 | 812 | */ |
| 812 | −static void isr_tr_complete_handler(struct ci13xxx *udc) | |
| 813 | −__releases(udc->lock) | |
| 814 | −__acquires(udc->lock) | |
| 813 | +static void isr_tr_complete_handler(struct ci13xxx *ci) | |
| 814 | +__releases(ci->lock) | |
| 815 | +__acquires(ci->lock) | |
| 815 | 816 | { |
| 816 | 817 | unsigned i; |
| 817 | 818 | u8 tmode = 0; |
| 818 | 819 | |
| 819 | − for (i = 0; i < udc->hw_ep_max; i++) { | |
| 820 | − struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | |
| 820 | + for (i = 0; i < ci->hw_ep_max; i++) { | |
| 821 | + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | |
| 821 | 822 | int type, num, dir, err = -EINVAL; |
| 822 | 823 | struct usb_ctrlrequest req; |
| 823 | 824 | |
| 824 | 825 | if (mEp->ep.desc == NULL) |
| 825 | 826 | continue; /* not configured */ |
| 826 | 827 | |
| 827 | − if (hw_test_and_clear_complete(udc, i)) { | |
| 828 | + if (hw_test_and_clear_complete(ci, i)) { | |
| 828 | 829 | err = isr_tr_complete_low(mEp); |
| 829 | 830 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { |
| 830 | 831 | if (err > 0) /* needs status phase */ |
| 831 | − err = isr_setup_status_phase(udc); | |
| 832 | + err = isr_setup_status_phase(ci); | |
| 832 | 833 | if (err < 0) { |
| 833 | 834 | dbg_event(_usb_addr(mEp), |
| 834 | 835 | "ERROR", err); |
| 835 | − spin_unlock(&udc->lock); | |
| 836 | + spin_unlock(&ci->lock); | |
| 836 | 837 | if (usb_ep_set_halt(&mEp->ep)) |
| 837 | − dev_err(udc->dev, | |
| 838 | + dev_err(ci->dev, | |
| 838 | 839 | "error: ep_set_halt\n"); |
| 839 | − spin_lock(&udc->lock); | |
| 840 | + spin_lock(&ci->lock); | |
| 840 | 841 | } |
| 841 | 842 | } |
| 842 | 843 | } |
| 843 | 844 | |
| 844 | 845 | if (mEp->type != USB_ENDPOINT_XFER_CONTROL || |
| 845 | − !hw_test_and_clear_setup_status(udc, i)) | |
| 846 | + !hw_test_and_clear_setup_status(ci, i)) | |
| 846 | 847 | continue; |
| 847 | 848 | |
| 848 | 849 | if (i != 0) { |
| 849 | − dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i); | |
| 850 | + dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i); | |
| 850 | 851 | continue; |
| 851 | 852 | } |
| 852 | 853 | |
| @@ -854,18 +855,18 @@ __acquires(udc->lock) · 1 unmodified line | ||
| 854 | 855 | * Flush data and handshake transactions of previous |
| 855 | 856 | * setup packet. |
| 856 | 857 | */ |
| 857 | − _ep_nuke(udc->ep0out); | |
| 858 | − _ep_nuke(udc->ep0in); | |
| 858 | + _ep_nuke(ci->ep0out); | |
| 859 | + _ep_nuke(ci->ep0in); | |
| 859 | 860 | |
| 860 | 861 | /* read_setup_packet */ |
| 861 | 862 | do { |
| 862 | − hw_test_and_set_setup_guard(udc); | |
| 863 | + hw_test_and_set_setup_guard(ci); | |
| 863 | 864 | memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); |
| 864 | − } while (!hw_test_and_clear_setup_guard(udc)); | |
| 865 | + } while (!hw_test_and_clear_setup_guard(ci)); | |
| 865 | 866 | |
| 866 | 867 | type = req.bRequestType; |
| 867 | 868 | |
| 868 | − udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | |
| 869 | + ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | |
| 869 | 870 | |
| 870 | 871 | dbg_setup(_usb_addr(mEp), &req); |
| 871 | 872 | |
| @@ -880,23 +881,23 @@ __acquires(udc->lock) · 8 unmodified lines | ||
| 880 | 881 | dir = num & USB_ENDPOINT_DIR_MASK; |
| 881 | 882 | num &= USB_ENDPOINT_NUMBER_MASK; |
| 882 | 883 | if (dir) /* TX */ |
| 883 | − num += udc->hw_ep_max/2; | |
| 884 | − if (!udc->ci13xxx_ep[num].wedge) { | |
| 885 | − spin_unlock(&udc->lock); | |
| 884 | + num += ci->hw_ep_max/2; | |
| 885 | + if (!ci->ci13xxx_ep[num].wedge) { | |
| 886 | + spin_unlock(&ci->lock); | |
| 886 | 887 | err = usb_ep_clear_halt( |
| 887 | − &udc->ci13xxx_ep[num].ep); | |
| 888 | − spin_lock(&udc->lock); | |
| 888 | + &ci->ci13xxx_ep[num].ep); | |
| 889 | + spin_lock(&ci->lock); | |
| 889 | 890 | if (err) |
| 890 | 891 | break; |
| 891 | 892 | } |
| 892 | − err = isr_setup_status_phase(udc); | |
| 893 | + err = isr_setup_status_phase(ci); | |
| 893 | 894 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && |
| 894 | 895 | le16_to_cpu(req.wValue) == |
| 895 | 896 | USB_DEVICE_REMOTE_WAKEUP) { |
| 896 | 897 | if (req.wLength != 0) |
| 897 | 898 | break; |
| 898 | − udc->remote_wakeup = 0; | |
| 899 | − err = isr_setup_status_phase(udc); | |
| 899 | + ci->remote_wakeup = 0; | |
| 900 | + err = isr_setup_status_phase(ci); | |
| 900 | 901 | } else { |
| 901 | 902 | goto delegate; |
| 902 | 903 | } |
| @@ -909,7 +910,7 @@ __acquires(udc->lock) · 6 unmodified lines | ||
| 909 | 910 | if (le16_to_cpu(req.wLength) != 2 || |
| 910 | 911 | le16_to_cpu(req.wValue) != 0) |
| 911 | 912 | break; |
| 912 | − err = isr_get_status_response(udc, &req); | |
| 913 | + err = isr_get_status_response(ci, &req); | |
| 913 | 914 | break; |
| 914 | 915 | case USB_REQ_SET_ADDRESS: |
| 915 | 916 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) |
| @@ -917,9 +918,9 @@ __acquires(udc->lock) · 1 unmodified line | ||
| 917 | 918 | if (le16_to_cpu(req.wLength) != 0 || |
| 918 | 919 | le16_to_cpu(req.wIndex) != 0) |
| 919 | 920 | break; |
| 920 | − udc->address = (u8)le16_to_cpu(req.wValue); | |
| 921 | − udc->setaddr = true; | |
| 922 | − err = isr_setup_status_phase(udc); | |
| 921 | + ci->address = (u8)le16_to_cpu(req.wValue); | |
| 922 | + ci->setaddr = true; | |
| 923 | + err = isr_setup_status_phase(ci); | |
| 923 | 924 | break; |
| 924 | 925 | case USB_REQ_SET_FEATURE: |
| 925 | 926 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && |
| @@ -931,20 +932,20 @@ __acquires(udc->lock) · 5 unmodified lines | ||
| 931 | 932 | dir = num & USB_ENDPOINT_DIR_MASK; |
| 932 | 933 | num &= USB_ENDPOINT_NUMBER_MASK; |
| 933 | 934 | if (dir) /* TX */ |
| 934 | − num += udc->hw_ep_max/2; | |
| 935 | + num += ci->hw_ep_max/2; | |
| 935 | 936 | |
| 936 | − spin_unlock(&udc->lock); | |
| 937 | − err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep); | |
| 938 | − spin_lock(&udc->lock); | |
| 937 | + spin_unlock(&ci->lock); | |
| 938 | + err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep); | |
| 939 | + spin_lock(&ci->lock); | |
| 939 | 940 | if (!err) |
| 940 | − isr_setup_status_phase(udc); | |
| 941 | + isr_setup_status_phase(ci); | |
| 941 | 942 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { |
| 942 | 943 | if (req.wLength != 0) |
| 943 | 944 | break; |
| 944 | 945 | switch (le16_to_cpu(req.wValue)) { |
| 945 | 946 | case USB_DEVICE_REMOTE_WAKEUP: |
| 946 | − udc->remote_wakeup = 1; | |
| 947 | − err = isr_setup_status_phase(udc); | |
| 947 | + ci->remote_wakeup = 1; | |
| 948 | + err = isr_setup_status_phase(ci); | |
| 948 | 949 | break; |
| 949 | 950 | case USB_DEVICE_TEST_MODE: |
| 950 | 951 | tmode = le16_to_cpu(req.wIndex) >> 8; |
| @@ -954,9 +955,9 @@ __acquires(udc->lock) · 3 unmodified lines | ||
| 954 | 955 | case TEST_SE0_NAK: |
| 955 | 956 | case TEST_PACKET: |
| 956 | 957 | case TEST_FORCE_EN: |
| 957 | − udc->test_mode = tmode; | |
| 958 | + ci->test_mode = tmode; | |
| 958 | 959 | err = isr_setup_status_phase( |
| 959 | − udc); | |
| 960 | + ci); | |
| 960 | 961 | break; |
| 961 | 962 | default: |
| 962 | 963 | break; |
| @@ -971,21 +972,21 @@ __acquires(udc->lock) · 8 unmodified lines | ||
| 971 | 972 | default: |
| 972 | 973 | delegate: |
| 973 | 974 | if (req.wLength == 0) /* no data phase */ |
| 974 | − udc->ep0_dir = TX; | |
| 975 | + ci->ep0_dir = TX; | |
| 975 | 976 | |
| 976 | − spin_unlock(&udc->lock); | |
| 977 | − err = udc->driver->setup(&udc->gadget, &req); | |
| 978 | − spin_lock(&udc->lock); | |
| 977 | + spin_unlock(&ci->lock); | |
| 978 | + err = ci->driver->setup(&ci->gadget, &req); | |
| 979 | + spin_lock(&ci->lock); | |
| 979 | 980 | break; |
| 980 | 981 | } |
| 981 | 982 | |
| 982 | 983 | if (err < 0) { |
| 983 | 984 | dbg_event(_usb_addr(mEp), "ERROR", err); |
| 984 | 985 | |
| 985 | − spin_unlock(&udc->lock); | |
| 986 | + spin_unlock(&ci->lock); | |
| 986 | 987 | if (usb_ep_set_halt(&mEp->ep)) |
| 987 | − dev_err(udc->dev, "error: ep_set_halt\n"); | |
| 988 | − spin_lock(&udc->lock); | |
| 988 | + dev_err(ci->dev, "error: ep_set_halt\n"); | |
| 989 | + spin_lock(&ci->lock); | |
| 989 | 990 | } |
| 990 | 991 | } |
| 991 | 992 | } |
| @@ -1015,7 +1016,7 @@ static int ep_enable(struct usb_ep *ep, · 23 unmodified lines | ||
| 1015 | 1016 | mEp->ep.desc = desc; |
| 1016 | 1017 | |
| 1017 | 1018 | if (!list_empty(&mEp->qh.queue)) |
| 1018 | − dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n"); | |
| 1019 | + dev_warn(mEp->ci->dev, "enabling a non-empty endpoint!\n"); | |
| 1019 | 1020 | |
| 1020 | 1021 | mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; |
| 1021 | 1022 | mEp->num = usb_endpoint_num(desc); |
| @@ -1043,7 +1044,7 @@ static int ep_enable(struct usb_ep *ep, · 21 unmodified lines | ||
| 1043 | 1044 | * is always enabled |
| 1044 | 1045 | */ |
| 1045 | 1046 | if (mEp->num) |
| 1046 | − retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type); | |
| 1047 | + retval |= hw_ep_enable(mEp->ci, mEp->num, mEp->dir, mEp->type); | |
| 1047 | 1048 | |
| 1048 | 1049 | spin_unlock_irqrestore(mEp->lock, flags); |
| 1049 | 1050 | return retval; |
| @@ -1074,7 +1075,7 @@ static int ep_disable(struct usb_ep *ep) · 24 unmodified lines | ||
| 1074 | 1075 | dbg_event(_usb_addr(mEp), "DISABLE", 0); |
| 1075 | 1076 | |
| 1076 | 1077 | retval |= _ep_nuke(mEp); |
| 1077 | − retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir); | |
| 1078 | + retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir); | |
| 1078 | 1079 | |
| 1079 | 1080 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) |
| 1080 | 1081 | mEp->dir = (mEp->dir == TX) ? RX : TX; |
| @@ -1131,7 +1132,7 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) · 50 unmodified lines | ||
| 1131 | 1132 | if (ep == NULL || req == NULL) { |
| 1132 | 1133 | return; |
| 1133 | 1134 | } else if (!list_empty(&mReq->queue)) { |
| 1134 | − dev_err(mEp->udc->dev, "freeing queued request\n"); | |
| 1135 | + dev_err(mEp->ci->dev, "freeing queued request\n"); | |
| 1135 | 1136 | return; |
| 1136 | 1137 | } |
| 1137 | 1138 | |
| @@ -1156,7 +1157,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, · 18 unmodified lines | ||
| 1156 | 1157 | { |
| 1157 | 1158 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); |
| 1158 | 1159 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); |
| 1159 | − struct ci13xxx *udc = mEp->udc; | |
| 1160 | + struct ci13xxx *ci = mEp->ci; | |
| 1160 | 1161 | int retval = 0; |
| 1161 | 1162 | unsigned long flags; |
| 1162 | 1163 | |
| @@ -1167,12 +1168,12 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, · 4 unmodified lines | ||
| 1167 | 1168 | |
| 1168 | 1169 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { |
| 1169 | 1170 | if (req->length) |
| 1170 | − mEp = (udc->ep0_dir == RX) ? | |
| 1171 | − udc->ep0out : udc->ep0in; | |
| 1171 | + mEp = (ci->ep0_dir == RX) ? | |
| 1172 | + ci->ep0out : ci->ep0in; | |
| 1172 | 1173 | if (!list_empty(&mEp->qh.queue)) { |
| 1173 | 1174 | _ep_nuke(mEp); |
| 1174 | 1175 | retval = -EOVERFLOW; |
| 1175 | − dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n", | |
| 1176 | + dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", | |
| 1176 | 1177 | _usb_addr(mEp)); |
| 1177 | 1178 | } |
| 1178 | 1179 | } |
| @@ -1180,14 +1181,14 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, · 1 unmodified line | ||
| 1180 | 1181 | /* first nuke then test link, e.g. previous status has not sent */ |
| 1181 | 1182 | if (!list_empty(&mReq->queue)) { |
| 1182 | 1183 | retval = -EBUSY; |
| 1183 | − dev_err(mEp->udc->dev, "request already in queue\n"); | |
| 1184 | + dev_err(mEp->ci->dev, "request already in queue\n"); | |
| 1184 | 1185 | goto done; |
| 1185 | 1186 | } |
| 1186 | 1187 | |
| 1187 | 1188 | if (req->length > 4 * CI13XXX_PAGE_SIZE) { |
| 1188 | 1189 | req->length = 4 * CI13XXX_PAGE_SIZE; |
| 1189 | 1190 | retval = -EMSGSIZE; |
| 1190 | − dev_warn(mEp->udc->dev, "request length truncated\n"); | |
| 1191 | + dev_warn(mEp->ci->dev, "request length truncated\n"); | |
| 1191 | 1192 | } |
| 1192 | 1193 | |
| 1193 | 1194 | dbg_queue(_usb_addr(mEp), req, retval); |
| @@ -1230,12 +1231,12 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) · 36 unmodified lines | ||
| 1230 | 1231 | |
| 1231 | 1232 | dbg_event(_usb_addr(mEp), "DEQUEUE", 0); |
| 1232 | 1233 | |
| 1233 | − hw_ep_flush(mEp->udc, mEp->num, mEp->dir); | |
| 1234 | + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | |
| 1234 | 1235 | |
| 1235 | 1236 | /* pop request */ |
| 1236 | 1237 | list_del_init(&mReq->queue); |
| 1237 | 1238 | |
| 1238 | − usb_gadget_unmap_request(&mEp->udc->gadget, req, mEp->dir); | |
| 1239 | + usb_gadget_unmap_request(&mEp->ci->gadget, req, mEp->dir); | |
| 1239 | 1240 | |
| 1240 | 1241 | req->status = -ECONNRESET; |
| 1241 | 1242 | |
| @@ -1277,7 +1278,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) · 35 unmodified lines | ||
| 1277 | 1278 | direction = mEp->dir; |
| 1278 | 1279 | do { |
| 1279 | 1280 | dbg_event(_usb_addr(mEp), "HALT", value); |
| 1280 | − retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value); | |
| 1281 | + retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value); | |
| 1281 | 1282 | |
| 1282 | 1283 | if (!value) |
| 1283 | 1284 | mEp->wedge = 0; |
| @@ -1325,14 +1326,14 @@ static void ep_fifo_flush(struct usb_ep *ep) · 41 unmodified lines | ||
| 1325 | 1326 | unsigned long flags; |
| 1326 | 1327 | |
| 1327 | 1328 | if (ep == NULL) { |
| 1328 | − dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); | |
| 1329 | + dev_err(mEp->ci->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); | |
| 1329 | 1330 | return; |
| 1330 | 1331 | } |
| 1331 | 1332 | |
| 1332 | 1333 | spin_lock_irqsave(mEp->lock, flags); |
| 1333 | 1334 | |
| 1334 | 1335 | dbg_event(_usb_addr(mEp), "FFLUSH", 0); |
| 1335 | − hw_ep_flush(mEp->udc, mEp->num, mEp->dir); | |
| 1336 | + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | |
| 1336 | 1337 | |
| 1337 | 1338 | spin_unlock_irqrestore(mEp->lock, flags); |
| 1338 | 1339 | } |
| @@ -1358,30 +1359,30 @@ static const struct usb_ep_ops usb_ep_ops = { · 19 unmodified lines | ||
| 1358 | 1359 | *****************************************************************************/ |
| 1359 | 1360 | static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) |
| 1360 | 1361 | { |
| 1361 | − struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | |
| 1362 | + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | |
| 1362 | 1363 | unsigned long flags; |
| 1363 | 1364 | int gadget_ready = 0; |
| 1364 | 1365 | |
| 1365 | − if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS)) | |
| 1366 | + if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) | |
| 1366 | 1367 | return -EOPNOTSUPP; |
| 1367 | 1368 | |
| 1368 | − spin_lock_irqsave(&udc->lock, flags); | |
| 1369 | − udc->vbus_active = is_active; | |
| 1370 | − if (udc->driver) | |
| 1369 | + spin_lock_irqsave(&ci->lock, flags); | |
| 1370 | + ci->vbus_active = is_active; | |
| 1371 | + if (ci->driver) | |
| 1371 | 1372 | gadget_ready = 1; |
| 1372 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 1373 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 1373 | 1374 | |
| 1374 | 1375 | if (gadget_ready) { |
| 1375 | 1376 | if (is_active) { |
| 1376 | 1377 | pm_runtime_get_sync(&_gadget->dev); |
| 1377 | − hw_device_reset(udc, USBMODE_CM_DC); | |
| 1378 | − hw_device_state(udc, udc->ep0out->qh.dma); | |
| 1378 | + hw_device_reset(ci, USBMODE_CM_DC); | |
| 1379 | + hw_device_state(ci, ci->ep0out->qh.dma); | |
| 1379 | 1380 | } else { |
| 1380 | − hw_device_state(udc, 0); | |
| 1381 | − if (udc->udc_driver->notify_event) | |
| 1382 | − udc->udc_driver->notify_event(udc, | |
| 1381 | + hw_device_state(ci, 0); | |
| 1382 | + if (ci->platdata->notify_event) | |
| 1383 | + ci->platdata->notify_event(ci, | |
| 1383 | 1384 | CI13XXX_CONTROLLER_STOPPED_EVENT); |
| 1384 | − _gadget_stop_activity(&udc->gadget); | |
| 1385 | + _gadget_stop_activity(&ci->gadget); | |
| 1385 | 1386 | pm_runtime_put_sync(&_gadget->dev); |
| 1386 | 1387 | } |
| 1387 | 1388 | } |
| @@ -1391,31 +1392,31 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) · 3 unmodified lines | ||
| 1391 | 1392 | |
| 1392 | 1393 | static int ci13xxx_wakeup(struct usb_gadget *_gadget) |
| 1393 | 1394 | { |
| 1394 | − struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | |
| 1395 | + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | |
| 1395 | 1396 | unsigned long flags; |
| 1396 | 1397 | int ret = 0; |
| 1397 | 1398 | |
| 1398 | − spin_lock_irqsave(&udc->lock, flags); | |
| 1399 | − if (!udc->remote_wakeup) { | |
| 1399 | + spin_lock_irqsave(&ci->lock, flags); | |
| 1400 | + if (!ci->remote_wakeup) { | |
| 1400 | 1401 | ret = -EOPNOTSUPP; |
| 1401 | 1402 | goto out; |
| 1402 | 1403 | } |
| 1403 | − if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) { | |
| 1404 | + if (!hw_read(ci, OP_PORTSC, PORTSC_SUSP)) { | |
| 1404 | 1405 | ret = -EINVAL; |
| 1405 | 1406 | goto out; |
| 1406 | 1407 | } |
| 1407 | − hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); | |
| 1408 | + hw_write(ci, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); | |
| 1408 | 1409 | out: |
| 1409 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 1410 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 1410 | 1411 | return ret; |
| 1411 | 1412 | } |
| 1412 | 1413 | |
| 1413 | 1414 | static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) |
| 1414 | 1415 | { |
| 1415 | − struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | |
| 1416 | + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | |
| 1416 | 1417 | |
| 1417 | − if (udc->transceiver) | |
| 1418 | − return usb_phy_set_power(udc->transceiver, mA); | |
| 1418 | + if (ci->transceiver) | |
| 1419 | + return usb_phy_set_power(ci->transceiver, mA); | |
| 1419 | 1420 | return -ENOTSUPP; |
| 1420 | 1421 | } |
| 1421 | 1422 | |
| @@ -1436,28 +1437,28 @@ static const struct usb_gadget_ops usb_gadget_ops = { · 14 unmodified lines | ||
| 1436 | 1437 | .udc_stop = ci13xxx_stop, |
| 1437 | 1438 | }; |
| 1438 | 1439 | |
| 1439 | −static int init_eps(struct ci13xxx *udc) | |
| 1440 | +static int init_eps(struct ci13xxx *ci) | |
| 1440 | 1441 | { |
| 1441 | 1442 | int retval = 0, i, j; |
| 1442 | 1443 | |
| 1443 | − for (i = 0; i < udc->hw_ep_max/2; i++) | |
| 1444 | + for (i = 0; i < ci->hw_ep_max/2; i++) | |
| 1444 | 1445 | for (j = RX; j <= TX; j++) { |
| 1445 | − int k = i + j * udc->hw_ep_max/2; | |
| 1446 | − struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; | |
| 1446 | + int k = i + j * ci->hw_ep_max/2; | |
| 1447 | + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[k]; | |
| 1447 | 1448 | |
| 1448 | 1449 | scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, |
| 1449 | 1450 | (j == TX) ? "in" : "out"); |
| 1450 | 1451 | |
| 1451 | − mEp->udc = udc; | |
| 1452 | − mEp->lock = &udc->lock; | |
| 1453 | − mEp->td_pool = udc->td_pool; | |
| 1452 | + mEp->ci = ci; | |
| 1453 | + mEp->lock = &ci->lock; | |
| 1454 | + mEp->td_pool = ci->td_pool; | |
| 1454 | 1455 | |
| 1455 | 1456 | mEp->ep.name = mEp->name; |
| 1456 | 1457 | mEp->ep.ops = &usb_ep_ops; |
| 1457 | 1458 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; |
| 1458 | 1459 | |
| 1459 | 1460 | INIT_LIST_HEAD(&mEp->qh.queue); |
| 1460 | − mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, | |
| 1461 | + mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, | |
| 1461 | 1462 | &mEp->qh.dma); |
| 1462 | 1463 | if (mEp->qh.ptr == NULL) |
| 1463 | 1464 | retval = -ENOMEM; |
| @@ -1470,14 +1471,14 @@ static int init_eps(struct ci13xxx *udc) · 6 unmodified lines | ||
| 1470 | 1471 | */ |
| 1471 | 1472 | if (i == 0) { |
| 1472 | 1473 | if (j == RX) |
| 1473 | − udc->ep0out = mEp; | |
| 1474 | + ci->ep0out = mEp; | |
| 1474 | 1475 | else |
| 1475 | − udc->ep0in = mEp; | |
| 1476 | + ci->ep0in = mEp; | |
| 1476 | 1477 | |
| 1477 | 1478 | continue; |
| 1478 | 1479 | } |
| 1479 | 1480 | |
| 1480 | − list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); | |
| 1481 | + list_add_tail(&mEp->ep.ep_list, &ci->gadget.ep_list); | |
| 1481 | 1482 | } |
| 1482 | 1483 | |
| 1483 | 1484 | return retval; |
| @@ -1493,7 +1494,7 @@ static int init_eps(struct ci13xxx *udc) · 9 unmodified lines | ||
| 1493 | 1494 | static int ci13xxx_start(struct usb_gadget *gadget, |
| 1494 | 1495 | struct usb_gadget_driver *driver) |
| 1495 | 1496 | { |
| 1496 | − struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | |
| 1497 | + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | |
| 1497 | 1498 | unsigned long flags; |
| 1498 | 1499 | int retval = -ENOMEM; |
| 1499 | 1500 | |
| @@ -1501,35 +1502,35 @@ static int ci13xxx_start(struct usb_gadget *gadget, · 1 unmodified line | ||
| 1501 | 1502 | return -EINVAL; |
| 1502 | 1503 | |
| 1503 | 1504 | |
| 1504 | − udc->ep0out->ep.desc = &ctrl_endpt_out_desc; | |
| 1505 | − retval = usb_ep_enable(&udc->ep0out->ep); | |
| 1505 | + ci->ep0out->ep.desc = &ctrl_endpt_out_desc; | |
| 1506 | + retval = usb_ep_enable(&ci->ep0out->ep); | |
| 1506 | 1507 | if (retval) |
| 1507 | 1508 | return retval; |
| 1508 | 1509 | |
| 1509 | − udc->ep0in->ep.desc = &ctrl_endpt_in_desc; | |
| 1510 | − retval = usb_ep_enable(&udc->ep0in->ep); | |
| 1510 | + ci->ep0in->ep.desc = &ctrl_endpt_in_desc; | |
| 1511 | + retval = usb_ep_enable(&ci->ep0in->ep); | |
| 1511 | 1512 | if (retval) |
| 1512 | 1513 | return retval; |
| 1513 | − spin_lock_irqsave(&udc->lock, flags); | |
| 1514 | − | |
| 1515 | − udc->driver = driver; | |
| 1516 | − pm_runtime_get_sync(&udc->gadget.dev); | |
| 1517 | − if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { | |
| 1518 | − if (udc->vbus_active) { | |
| 1519 | − if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) | |
| 1520 | − hw_device_reset(udc, USBMODE_CM_DC); | |
| 1514 | + spin_lock_irqsave(&ci->lock, flags); | |
| 1515 | + | |
| 1516 | + ci->driver = driver; | |
| 1517 | + pm_runtime_get_sync(&ci->gadget.dev); | |
| 1518 | + if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { | |
| 1519 | + if (ci->vbus_active) { | |
| 1520 | + if (ci->platdata->flags & CI13XXX_REGS_SHARED) | |
| 1521 | + hw_device_reset(ci, USBMODE_CM_DC); | |
| 1521 | 1522 | } else { |
| 1522 | − pm_runtime_put_sync(&udc->gadget.dev); | |
| 1523 | + pm_runtime_put_sync(&ci->gadget.dev); | |
| 1523 | 1524 | goto done; |
| 1524 | 1525 | } |
| 1525 | 1526 | } |
| 1526 | 1527 | |
| 1527 | − retval = hw_device_state(udc, udc->ep0out->qh.dma); | |
| 1528 | + retval = hw_device_state(ci, ci->ep0out->qh.dma); | |
| 1528 | 1529 | if (retval) |
| 1529 | − pm_runtime_put_sync(&udc->gadget.dev); | |
| 1530 | + pm_runtime_put_sync(&ci->gadget.dev); | |
| 1530 | 1531 | |
| 1531 | 1532 | done: |
| 1532 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 1533 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 1533 | 1534 | return retval; |
| 1534 | 1535 | } |
| 1535 | 1536 | |
| @@ -1539,25 +1540,25 @@ static int ci13xxx_start(struct usb_gadget *gadget, · 3 unmodified lines | ||
| 1539 | 1540 | static int ci13xxx_stop(struct usb_gadget *gadget, |
| 1540 | 1541 | struct usb_gadget_driver *driver) |
| 1541 | 1542 | { |
| 1542 | − struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | |
| 1543 | + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | |
| 1543 | 1544 | unsigned long flags; |
| 1544 | 1545 | |
| 1545 | − spin_lock_irqsave(&udc->lock, flags); | |
| 1546 | + spin_lock_irqsave(&ci->lock, flags); | |
| 1546 | 1547 | |
| 1547 | − if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) || | |
| 1548 | − udc->vbus_active) { | |
| 1549 | − hw_device_state(udc, 0); | |
| 1550 | − if (udc->udc_driver->notify_event) | |
| 1551 | − udc->udc_driver->notify_event(udc, | |
| 1548 | + if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || | |
| 1549 | + ci->vbus_active) { | |
| 1550 | + hw_device_state(ci, 0); | |
| 1551 | + if (ci->platdata->notify_event) | |
| 1552 | + ci->platdata->notify_event(ci, | |
| 1552 | 1553 | CI13XXX_CONTROLLER_STOPPED_EVENT); |
| 1553 | − udc->driver = NULL; | |
| 1554 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 1555 | − _gadget_stop_activity(&udc->gadget); | |
| 1556 | − spin_lock_irqsave(&udc->lock, flags); | |
| 1557 | − pm_runtime_put(&udc->gadget.dev); | |
| 1554 | + ci->driver = NULL; | |
| 1555 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 1556 | + _gadget_stop_activity(&ci->gadget); | |
| 1557 | + spin_lock_irqsave(&ci->lock, flags); | |
| 1558 | + pm_runtime_put(&ci->gadget.dev); | |
| 1558 | 1559 | } |
| 1559 | 1560 | |
| 1560 | − spin_unlock_irqrestore(&udc->lock, flags); | |
| 1561 | + spin_unlock_irqrestore(&ci->lock, flags); | |
| 1561 | 1562 | |
| 1562 | 1563 | return 0; |
| 1563 | 1564 | } |
| @@ -1566,64 +1567,64 @@ static int ci13xxx_stop(struct usb_gadget *gadget, · 2 unmodified lines | ||
| 1566 | 1567 | * BUS block |
| 1567 | 1568 | *****************************************************************************/ |
| 1568 | 1569 | /** |
| 1569 | − * udc_irq: udc interrupt handler | |
| 1570 | + * udc_irq: ci interrupt handler | |
| 1570 | 1571 | * |
| 1571 | 1572 | * This function returns IRQ_HANDLED if the IRQ has been handled |
| 1572 | 1573 | * It locks access to registers |
| 1573 | 1574 | */ |
| 1574 | −static irqreturn_t udc_irq(struct ci13xxx *udc) | |
| 1575 | +static irqreturn_t udc_irq(struct ci13xxx *ci) | |
| 1575 | 1576 | { |
| 1576 | 1577 | irqreturn_t retval; |
| 1577 | 1578 | u32 intr; |
| 1578 | 1579 | |
| 1579 | − if (udc == NULL) | |
| 1580 | + if (ci == NULL) | |
| 1580 | 1581 | return IRQ_HANDLED; |
| 1581 | 1582 | |
| 1582 | − spin_lock(&udc->lock); | |
| 1583 | + spin_lock(&ci->lock); | |
| 1583 | 1584 | |
| 1584 | − if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) { | |
| 1585 | − if (hw_read(udc, OP_USBMODE, USBMODE_CM) != | |
| 1585 | + if (ci->platdata->flags & CI13XXX_REGS_SHARED) { | |
| 1586 | + if (hw_read(ci, OP_USBMODE, USBMODE_CM) != | |
| 1586 | 1587 | USBMODE_CM_DC) { |
| 1587 | − spin_unlock(&udc->lock); | |
| 1588 | + spin_unlock(&ci->lock); | |
| 1588 | 1589 | return IRQ_NONE; |
| 1589 | 1590 | } |
| 1590 | 1591 | } |
| 1591 | − intr = hw_test_and_clear_intr_active(udc); | |
| 1592 | + intr = hw_test_and_clear_intr_active(ci); | |
| 1592 | 1593 | dbg_interrupt(intr); |
| 1593 | 1594 | |
| 1594 | 1595 | if (intr) { |
| 1595 | 1596 | /* order defines priority - do NOT change it */ |
| 1596 | 1597 | if (USBi_URI & intr) |
| 1597 | − isr_reset_handler(udc); | |
| 1598 | + isr_reset_handler(ci); | |
| 1598 | 1599 | |
| 1599 | 1600 | if (USBi_PCI & intr) { |
| 1600 | − udc->gadget.speed = hw_port_is_high_speed(udc) ? | |
| 1601 | + ci->gadget.speed = hw_port_is_high_speed(ci) ? | |
| 1601 | 1602 | USB_SPEED_HIGH : USB_SPEED_FULL; |
| 1602 | − if (udc->suspended && udc->driver->resume) { | |
| 1603 | − spin_unlock(&udc->lock); | |
| 1604 | − udc->driver->resume(&udc->gadget); | |
| 1605 | − spin_lock(&udc->lock); | |
| 1606 | − udc->suspended = 0; | |
| 1603 | + if (ci->suspended && ci->driver->resume) { | |
| 1604 | + spin_unlock(&ci->lock); | |
| 1605 | + ci->driver->resume(&ci->gadget); | |
| 1606 | + spin_lock(&ci->lock); | |
| 1607 | + ci->suspended = 0; | |
| 1607 | 1608 | } |
| 1608 | 1609 | } |
| 1609 | 1610 | |
| 1610 | 1611 | if (USBi_UI & intr) |
| 1611 | − isr_tr_complete_handler(udc); | |
| 1612 | + isr_tr_complete_handler(ci); | |
| 1612 | 1613 | |
| 1613 | 1614 | if (USBi_SLI & intr) { |
| 1614 | − if (udc->gadget.speed != USB_SPEED_UNKNOWN && | |
| 1615 | − udc->driver->suspend) { | |
| 1616 | − udc->suspended = 1; | |
| 1617 | − spin_unlock(&udc->lock); | |
| 1618 | − udc->driver->suspend(&udc->gadget); | |
| 1619 | − spin_lock(&udc->lock); | |
| 1615 | + if (ci->gadget.speed != USB_SPEED_UNKNOWN && | |
| 1616 | + ci->driver->suspend) { | |
| 1617 | + ci->suspended = 1; | |
| 1618 | + spin_unlock(&ci->lock); | |
| 1619 | + ci->driver->suspend(&ci->gadget); | |
| 1620 | + spin_lock(&ci->lock); | |
| 1620 | 1621 | } |
| 1621 | 1622 | } |
| 1622 | 1623 | retval = IRQ_HANDLED; |
| 1623 | 1624 | } else { |
| 1624 | 1625 | retval = IRQ_NONE; |
| 1625 | 1626 | } |
| 1626 | − spin_unlock(&udc->lock); | |
| 1627 | + spin_unlock(&ci->lock); | |
| 1627 | 1628 | |
| 1628 | 1629 | return retval; |
| 1629 | 1630 | } |
| @@ -1640,112 +1641,111 @@ static void udc_release(struct device *dev) · 10 unmodified lines | ||
| 1640 | 1641 | |
| 1641 | 1642 | /** |
| 1642 | 1643 | * udc_start: initialize gadget role |
| 1643 | − * @udc: chipidea controller | |
| 1644 | + * @ci: chipidea controller | |
| 1644 | 1645 | */ |
| 1645 | −static int udc_start(struct ci13xxx *udc) | |
| 1646 | +static int udc_start(struct ci13xxx *ci) | |
| 1646 | 1647 | { |
| 1647 | − struct device *dev = udc->dev; | |
| 1648 | + struct device *dev = ci->dev; | |
| 1648 | 1649 | int retval = 0; |
| 1649 | 1650 | |
| 1650 | − if (!udc) | |
| 1651 | − return -EINVAL; | |
| 1652 | − | |
| 1653 | − spin_lock_init(&udc->lock); | |
| 1651 | + spin_lock_init(&ci->lock); | |
| 1654 | 1652 | |
| 1655 | − udc->gadget.ops = &usb_gadget_ops; | |
| 1656 | − udc->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1657 | − udc->gadget.max_speed = USB_SPEED_HIGH; | |
| 1658 | − udc->gadget.is_otg = 0; | |
| 1659 | − udc->gadget.name = udc->udc_driver->name; | |
| 1653 | + ci->gadget.ops = &usb_gadget_ops; | |
| 1654 | + ci->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1655 | + ci->gadget.max_speed = USB_SPEED_HIGH; | |
| 1656 | + ci->gadget.is_otg = 0; | |
| 1657 | + ci->gadget.name = ci->platdata->name; | |
| 1660 | 1658 | |
| 1661 | − INIT_LIST_HEAD(&udc->gadget.ep_list); | |
| 1659 | + INIT_LIST_HEAD(&ci->gadget.ep_list); | |
| 1662 | 1660 | |
| 1663 | − dev_set_name(&udc->gadget.dev, "gadget"); | |
| 1664 | − udc->gadget.dev.dma_mask = dev->dma_mask; | |
| 1665 | − udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; | |
| 1666 | − udc->gadget.dev.parent = dev; | |
| 1667 | − udc->gadget.dev.release = udc_release; | |
| 1661 | + dev_set_name(&ci->gadget.dev, "gadget"); | |
| 1662 | + ci->gadget.dev.dma_mask = dev->dma_mask; | |
| 1663 | + ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; | |
| 1664 | + ci->gadget.dev.parent = dev; | |
| 1665 | + ci->gadget.dev.release = udc_release; | |
| 1668 | 1666 | |
| 1669 | 1667 | /* alloc resources */ |
| 1670 | − udc->qh_pool = dma_pool_create("ci13xxx_qh", dev, | |
| 1668 | + ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, | |
| 1671 | 1669 | sizeof(struct ci13xxx_qh), |
| 1672 | 1670 | 64, CI13XXX_PAGE_SIZE); |
| 1673 | − if (udc->qh_pool == NULL) | |
| 1671 | + if (ci->qh_pool == NULL) | |
| 1674 | 1672 | return -ENOMEM; |
| 1675 | 1673 | |
| 1676 | − udc->td_pool = dma_pool_create("ci13xxx_td", dev, | |
| 1674 | + ci->td_pool = dma_pool_create("ci13xxx_td", dev, | |
| 1677 | 1675 | sizeof(struct ci13xxx_td), |
| 1678 | 1676 | 64, CI13XXX_PAGE_SIZE); |
| 1679 | − if (udc->td_pool == NULL) { | |
| 1677 | + if (ci->td_pool == NULL) { | |
| 1680 | 1678 | retval = -ENOMEM; |
| 1681 | 1679 | goto free_qh_pool; |
| 1682 | 1680 | } |
| 1683 | 1681 | |
| 1684 | − retval = init_eps(udc); | |
| 1682 | + retval = init_eps(ci); | |
| 1685 | 1683 | if (retval) |
| 1686 | 1684 | goto free_pools; |
| 1687 | 1685 | |
| 1688 | − udc->gadget.ep0 = &udc->ep0in->ep; | |
| 1686 | + ci->gadget.ep0 = &ci->ep0in->ep; | |
| 1689 | 1687 | |
| 1690 | − udc->transceiver = usb_get_transceiver(); | |
| 1688 | + if (ci->global_phy) | |
| 1689 | + ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 1691 | 1690 | |
| 1692 | − if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | |
| 1693 | − if (udc->transceiver == NULL) { | |
| 1691 | + if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | |
| 1692 | + if (ci->transceiver == NULL) { | |
| 1694 | 1693 | retval = -ENODEV; |
| 1695 | 1694 | goto free_pools; |
| 1696 | 1695 | } |
| 1697 | 1696 | } |
| 1698 | 1697 | |
| 1699 | − if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) { | |
| 1700 | − retval = hw_device_reset(udc, USBMODE_CM_DC); | |
| 1698 | + if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) { | |
| 1699 | + retval = hw_device_reset(ci, USBMODE_CM_DC); | |
| 1701 | 1700 | if (retval) |
| 1702 | 1701 | goto put_transceiver; |
| 1703 | 1702 | } |
| 1704 | 1703 | |
| 1705 | − retval = device_register(&udc->gadget.dev); | |
| 1704 | + retval = device_register(&ci->gadget.dev); | |
| 1706 | 1705 | if (retval) { |
| 1707 | − put_device(&udc->gadget.dev); | |
| 1706 | + put_device(&ci->gadget.dev); | |
| 1708 | 1707 | goto put_transceiver; |
| 1709 | 1708 | } |
| 1710 | 1709 | |
| 1711 | − retval = dbg_create_files(&udc->gadget.dev); | |
| 1710 | + retval = dbg_create_files(&ci->gadget.dev); | |
| 1712 | 1711 | if (retval) |
| 1713 | 1712 | goto unreg_device; |
| 1714 | 1713 | |
| 1715 | − if (udc->transceiver) { | |
| 1716 | − retval = otg_set_peripheral(udc->transceiver->otg, | |
| 1717 | − &udc->gadget); | |
| 1714 | + if (!IS_ERR_OR_NULL(ci->transceiver)) { | |
| 1715 | + retval = otg_set_peripheral(ci->transceiver->otg, | |
| 1716 | + &ci->gadget); | |
| 1718 | 1717 | if (retval) |
| 1719 | 1718 | goto remove_dbg; |
| 1720 | 1719 | } |
| 1721 | 1720 | |
| 1722 | − retval = usb_add_gadget_udc(dev, &udc->gadget); | |
| 1721 | + retval = usb_add_gadget_udc(dev, &ci->gadget); | |
| 1723 | 1722 | if (retval) |
| 1724 | 1723 | goto remove_trans; |
| 1725 | 1724 | |
| 1726 | − pm_runtime_no_callbacks(&udc->gadget.dev); | |
| 1727 | − pm_runtime_enable(&udc->gadget.dev); | |
| 1725 | + pm_runtime_no_callbacks(&ci->gadget.dev); | |
| 1726 | + pm_runtime_enable(&ci->gadget.dev); | |
| 1728 | 1727 | |
| 1729 | 1728 | return retval; |
| 1730 | 1729 | |
| 1731 | 1730 | remove_trans: |
| 1732 | − if (udc->transceiver) { | |
| 1733 | − otg_set_peripheral(udc->transceiver->otg, &udc->gadget); | |
| 1734 | − usb_put_transceiver(udc->transceiver); | |
| 1731 | + if (!IS_ERR_OR_NULL(ci->transceiver)) { | |
| 1732 | + otg_set_peripheral(ci->transceiver->otg, &ci->gadget); | |
| 1733 | + if (ci->global_phy) | |
| 1734 | + usb_put_phy(ci->transceiver); | |
| 1735 | 1735 | } |
| 1736 | 1736 | |
| 1737 | 1737 | dev_err(dev, "error = %i\n", retval); |
| 1738 | 1738 | remove_dbg: |
| 1739 | − dbg_remove_files(&udc->gadget.dev); | |
| 1739 | + dbg_remove_files(&ci->gadget.dev); | |
| 1740 | 1740 | unreg_device: |
| 1741 | − device_unregister(&udc->gadget.dev); | |
| 1741 | + device_unregister(&ci->gadget.dev); | |
| 1742 | 1742 | put_transceiver: |
| 1743 | − if (udc->transceiver) | |
| 1744 | − usb_put_transceiver(udc->transceiver); | |
| 1743 | + if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) | |
| 1744 | + usb_put_phy(ci->transceiver); | |
| 1745 | 1745 | free_pools: |
| 1746 | − dma_pool_destroy(udc->td_pool); | |
| 1746 | + dma_pool_destroy(ci->td_pool); | |
| 1747 | 1747 | free_qh_pool: |
| 1748 | − dma_pool_destroy(udc->qh_pool); | |
| 1748 | + dma_pool_destroy(ci->qh_pool); | |
| 1749 | 1749 | return retval; |
| 1750 | 1750 | } |
| 1751 | 1751 | |
| @@ -1754,32 +1754,33 @@ free_qh_pool: · 2 unmodified lines | ||
| 1754 | 1754 | * |
| 1755 | 1755 | * No interrupts active, the IRQ has been released |
| 1756 | 1756 | */ |
| 1757 | −static void udc_stop(struct ci13xxx *udc) | |
| 1757 | +static void udc_stop(struct ci13xxx *ci) | |
| 1758 | 1758 | { |
| 1759 | 1759 | int i; |
| 1760 | 1760 | |
| 1761 | − if (udc == NULL) | |
| 1761 | + if (ci == NULL) | |
| 1762 | 1762 | return; |
| 1763 | 1763 | |
| 1764 | − usb_del_gadget_udc(&udc->gadget); | |
| 1764 | + usb_del_gadget_udc(&ci->gadget); | |
| 1765 | 1765 | |
| 1766 | − for (i = 0; i < udc->hw_ep_max; i++) { | |
| 1767 | − struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | |
| 1766 | + for (i = 0; i < ci->hw_ep_max; i++) { | |
| 1767 | + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | |
| 1768 | 1768 | |
| 1769 | − dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); | |
| 1769 | + dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); | |
| 1770 | 1770 | } |
| 1771 | 1771 | |
| 1772 | − dma_pool_destroy(udc->td_pool); | |
| 1773 | − dma_pool_destroy(udc->qh_pool); | |
| 1772 | + dma_pool_destroy(ci->td_pool); | |
| 1773 | + dma_pool_destroy(ci->qh_pool); | |
| 1774 | 1774 | |
| 1775 | − if (udc->transceiver) { | |
| 1776 | − otg_set_peripheral(udc->transceiver->otg, NULL); | |
| 1777 | − usb_put_transceiver(udc->transceiver); | |
| 1775 | + if (!IS_ERR_OR_NULL(ci->transceiver)) { | |
| 1776 | + otg_set_peripheral(ci->transceiver->otg, NULL); | |
| 1777 | + if (ci->global_phy) | |
| 1778 | + usb_put_phy(ci->transceiver); | |
| 1778 | 1779 | } |
| 1779 | − dbg_remove_files(&udc->gadget.dev); | |
| 1780 | − device_unregister(&udc->gadget.dev); | |
| 1780 | + dbg_remove_files(&ci->gadget.dev); | |
| 1781 | + device_unregister(&ci->gadget.dev); | |
| 1781 | 1782 | /* my kobject is dynamic, I swear! */ |
| 1782 | − memset(&udc->gadget, 0, sizeof(udc->gadget)); | |
| 1783 | + memset(&ci->gadget, 0, sizeof(ci->gadget)); | |
| 1783 | 1784 | } |
| 1784 | 1785 | |
| 1785 | 1786 | /** |
| @@ -996,7 +996,7 @@ static int acm_probe(struct usb_interface *intf, · 995 unmodified lines | ||
| 996 | 996 | case USB_CDC_CALL_MANAGEMENT_TYPE: |
| 997 | 997 | call_management_function = buffer[3]; |
| 998 | 998 | call_interface_num = buffer[4]; |
| 999 | − if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) | |
| 999 | + if ((quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) | |
| 1000 | 1000 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); |
| 1001 | 1001 | break; |
| 1002 | 1002 | default: |
| @@ -32,8 +32,6 @@ · 31 unmodified lines | ||
| 32 | 32 | #define DRIVER_AUTHOR "Oliver Neukum" |
| 33 | 33 | #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" |
| 34 | 34 | |
| 35 | −#define HUAWEI_VENDOR_ID 0x12D1 | |
| 36 | − | |
| 37 | 35 | static const struct usb_device_id wdm_ids[] = { |
| 38 | 36 | { |
| 39 | 37 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | |
| @@ -41,29 +39,6 @@ static const struct usb_device_id wdm_ids[] = { · 1 unmodified line | ||
| 41 | 39 | .bInterfaceClass = USB_CLASS_COMM, |
| 42 | 40 | .bInterfaceSubClass = USB_CDC_SUBCLASS_DMM |
| 43 | 41 | }, |
| 44 | − { | |
| 45 | − /* | |
| 46 | − * Huawei E392, E398 and possibly other Qualcomm based modems | |
| 47 | − * embed the Qualcomm QMI protocol inside CDC on CDC ECM like | |
| 48 | − * control interfaces. Userspace access to this is required | |
| 49 | − * to configure the accompanying data interface | |
| 50 | − */ | |
| 51 | − .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | |
| 52 | − USB_DEVICE_ID_MATCH_INT_INFO, | |
| 53 | − .idVendor = HUAWEI_VENDOR_ID, | |
| 54 | − .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | |
| 55 | − .bInterfaceSubClass = 1, | |
| 56 | − .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */ | |
| 57 | − }, | |
| 58 | − { | |
| 59 | − /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ | |
| 60 | − .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | |
| 61 | − USB_DEVICE_ID_MATCH_INT_INFO, | |
| 62 | − .idVendor = HUAWEI_VENDOR_ID, | |
| 63 | − .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | |
| 64 | − .bInterfaceSubClass = 1, | |
| 65 | − .bInterfaceProtocol = 57, /* NOTE: CDC ECM control interface! */ | |
| 66 | − }, | |
| 67 | 42 | { } |
| 68 | 43 | }; |
| 69 | 44 | |
| @@ -47,6 +47,7 @@ · 46 unmodified lines | ||
| 47 | 47 | #include <linux/notifier.h> |
| 48 | 48 | #include <linux/security.h> |
| 49 | 49 | #include <linux/user_namespace.h> |
| 50 | +#include <linux/scatterlist.h> | |
| 50 | 51 | #include <asm/uaccess.h> |
| 51 | 52 | #include <asm/byteorder.h> |
| 52 | 53 | #include <linux/moduleparam.h> |
| @@ -55,6 +56,7 @@ · 2 unmodified lines | ||
| 55 | 56 | |
| 56 | 57 | #define USB_MAXBUS 64 |
| 57 | 58 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
| 59 | +#define USB_SG_SIZE 16384 /* split-size for large txs */ | |
| 58 | 60 | |
| 59 | 61 | /* Mutual exclusion for removal, open, and release */ |
| 60 | 62 | DEFINE_MUTEX(usbfs_mutex); |
| @@ -285,9 +287,16 @@ static struct async *alloc_async(unsigned int numisoframes) · 224 unmodified lines | ||
| 285 | 287 | |
| 286 | 288 | static void free_async(struct async *as) |
| 287 | 289 | { |
| 290 | + int i; | |
| 291 | + | |
| 288 | 292 | put_pid(as->pid); |
| 289 | 293 | if (as->cred) |
| 290 | 294 | put_cred(as->cred); |
| 295 | + for (i = 0; i < as->urb->num_sgs; i++) { | |
| 296 | + if (sg_page(&as->urb->sg[i])) | |
| 297 | + kfree(sg_virt(&as->urb->sg[i])); | |
| 298 | + } | |
| 299 | + kfree(as->urb->sg); | |
| 291 | 300 | kfree(as->urb->transfer_buffer); |
| 292 | 301 | kfree(as->urb->setup_packet); |
| 293 | 302 | usb_free_urb(as->urb); |
| @@ -388,6 +397,53 @@ static void snoop_urb(struct usb_device *udev, · 94 unmodified lines | ||
| 388 | 397 | } |
| 389 | 398 | } |
| 390 | 399 | |
| 400 | +static void snoop_urb_data(struct urb *urb, unsigned len) | |
| 401 | +{ | |
| 402 | + int i, size; | |
| 403 | + | |
| 404 | + if (!usbfs_snoop) | |
| 405 | + return; | |
| 406 | + | |
| 407 | + if (urb->num_sgs == 0) { | |
| 408 | + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, | |
| 409 | + urb->transfer_buffer, len, 1); | |
| 410 | + return; | |
| 411 | + } | |
| 412 | + | |
| 413 | + for (i = 0; i < urb->num_sgs && len; i++) { | |
| 414 | + size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; | |
| 415 | + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, | |
| 416 | + sg_virt(&urb->sg[i]), size, 1); | |
| 417 | + len -= size; | |
| 418 | + } | |
| 419 | +} | |
| 420 | + | |
| 421 | +static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb) | |
| 422 | +{ | |
| 423 | + unsigned i, len, size; | |
| 424 | + | |
| 425 | + if (urb->number_of_packets > 0) /* Isochronous */ | |
| 426 | + len = urb->transfer_buffer_length; | |
| 427 | + else /* Non-Isoc */ | |
| 428 | + len = urb->actual_length; | |
| 429 | + | |
| 430 | + if (urb->num_sgs == 0) { | |
| 431 | + if (copy_to_user(userbuffer, urb->transfer_buffer, len)) | |
| 432 | + return -EFAULT; | |
| 433 | + return 0; | |
| 434 | + } | |
| 435 | + | |
| 436 | + for (i = 0; i < urb->num_sgs && len; i++) { | |
| 437 | + size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; | |
| 438 | + if (copy_to_user(userbuffer, sg_virt(&urb->sg[i]), size)) | |
| 439 | + return -EFAULT; | |
| 440 | + userbuffer += size; | |
| 441 | + len -= size; | |
| 442 | + } | |
| 443 | + | |
| 444 | + return 0; | |
| 445 | +} | |
| 446 | + | |
| 391 | 447 | #define AS_CONTINUATION 1 |
| 392 | 448 | #define AS_UNLINK 2 |
| 393 | 449 | |
| @@ -454,9 +510,10 @@ static void async_completed(struct urb *urb) · 60 unmodified lines | ||
| 454 | 510 | } |
| 455 | 511 | snoop(&urb->dev->dev, "urb complete\n"); |
| 456 | 512 | snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, |
| 457 | − as->status, COMPLETE, | |
| 458 | − ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_OUT) ? | |
| 459 | − NULL : urb->transfer_buffer, urb->actual_length); | |
| 513 | + as->status, COMPLETE, NULL, 0); | |
| 514 | + if ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_IN) | |
| 515 | + snoop_urb_data(urb, urb->actual_length); | |
| 516 | + | |
| 460 | 517 | if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && |
| 461 | 518 | as->status != -ENOENT) |
| 462 | 519 | cancel_bulk_urbs(ps, as->bulk_addr); |
| @@ -1114,8 +1171,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 651 unmodified lines | ||
| 1114 | 1171 | struct async *as = NULL; |
| 1115 | 1172 | struct usb_ctrlrequest *dr = NULL; |
| 1116 | 1173 | unsigned int u, totlen, isofrmlen; |
| 1117 | − int ret, ifnum = -1; | |
| 1118 | − int is_in; | |
| 1174 | + int i, ret, is_in, num_sgs = 0, ifnum = -1; | |
| 1175 | + void *buf; | |
| 1119 | 1176 | |
| 1120 | 1177 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | |
| 1121 | 1178 | USBDEVFS_URB_SHORT_NOT_OK | |
| @@ -1199,6 +1256,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 77 unmodified lines | ||
| 1199 | 1256 | goto interrupt_urb; |
| 1200 | 1257 | } |
| 1201 | 1258 | uurb->number_of_packets = 0; |
| 1259 | + num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE); | |
| 1260 | + if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize) | |
| 1261 | + num_sgs = 0; | |
| 1202 | 1262 | break; |
| 1203 | 1263 | |
| 1204 | 1264 | case USBDEVFS_URB_TYPE_INTERRUPT: |
| @@ -1255,26 +1315,67 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 50 unmodified lines | ||
| 1255 | 1315 | ret = -ENOMEM; |
| 1256 | 1316 | goto error; |
| 1257 | 1317 | } |
| 1258 | − u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length; | |
| 1318 | + | |
| 1319 | + u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + | |
| 1320 | + num_sgs * sizeof(struct scatterlist); | |
| 1259 | 1321 | ret = usbfs_increase_memory_usage(u); |
| 1260 | 1322 | if (ret) |
| 1261 | 1323 | goto error; |
| 1262 | 1324 | as->mem_usage = u; |
| 1263 | 1325 | |
| 1264 | − if (uurb->buffer_length > 0) { | |
| 1326 | + if (num_sgs) { | |
| 1327 | + as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), | |
| 1328 | + GFP_KERNEL); | |
| 1329 | + if (!as->urb->sg) { | |
| 1330 | + ret = -ENOMEM; | |
| 1331 | + goto error; | |
| 1332 | + } | |
| 1333 | + as->urb->num_sgs = num_sgs; | |
| 1334 | + sg_init_table(as->urb->sg, as->urb->num_sgs); | |
| 1335 | + | |
| 1336 | + totlen = uurb->buffer_length; | |
| 1337 | + for (i = 0; i < as->urb->num_sgs; i++) { | |
| 1338 | + u = (totlen > USB_SG_SIZE) ? USB_SG_SIZE : totlen; | |
| 1339 | + buf = kmalloc(u, GFP_KERNEL); | |
| 1340 | + if (!buf) { | |
| 1341 | + ret = -ENOMEM; | |
| 1342 | + goto error; | |
| 1343 | + } | |
| 1344 | + sg_set_buf(&as->urb->sg[i], buf, u); | |
| 1345 | + | |
| 1346 | + if (!is_in) { | |
| 1347 | + if (copy_from_user(buf, uurb->buffer, u)) { | |
| 1348 | + ret = -EFAULT; | |
| 1349 | + goto error; | |
| 1350 | + } | |
| 1351 | + } | |
| 1352 | + totlen -= u; | |
| 1353 | + } | |
| 1354 | + } else if (uurb->buffer_length > 0) { | |
| 1265 | 1355 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, |
| 1266 | 1356 | GFP_KERNEL); |
| 1267 | 1357 | if (!as->urb->transfer_buffer) { |
| 1268 | 1358 | ret = -ENOMEM; |
| 1269 | 1359 | goto error; |
| 1270 | 1360 | } |
| 1271 | − /* Isochronous input data may end up being discontiguous | |
| 1272 | − * if some of the packets are short. Clear the buffer so | |
| 1273 | − * that the gaps don't leak kernel data to userspace. | |
| 1274 | − */ | |
| 1275 | − if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) | |
| 1361 | + | |
| 1362 | + if (!is_in) { | |
| 1363 | + if (copy_from_user(as->urb->transfer_buffer, | |
| 1364 | + uurb->buffer, | |
| 1365 | + uurb->buffer_length)) { | |
| 1366 | + ret = -EFAULT; | |
| 1367 | + goto error; | |
| 1368 | + } | |
| 1369 | + } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) { | |
| 1370 | + /* | |
| 1371 | + * Isochronous input data may end up being | |
| 1372 | + * discontiguous if some of the packets are short. | |
| 1373 | + * Clear the buffer so that the gaps don't leak | |
| 1374 | + * kernel data to userspace. | |
| 1375 | + */ | |
| 1276 | 1376 | memset(as->urb->transfer_buffer, 0, |
| 1277 | 1377 | uurb->buffer_length); |
| 1378 | + } | |
| 1278 | 1379 | } |
| 1279 | 1380 | as->urb->dev = ps->dev; |
| 1280 | 1381 | as->urb->pipe = (uurb->type << 30) | |
| @@ -1328,17 +1429,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, · 47 unmodified lines | ||
| 1328 | 1429 | as->pid = get_pid(task_pid(current)); |
| 1329 | 1430 | as->cred = get_current_cred(); |
| 1330 | 1431 | security_task_getsecid(current, &as->secid); |
| 1331 | − if (!is_in && uurb->buffer_length > 0) { | |
| 1332 | − if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | |
| 1333 | − uurb->buffer_length)) { | |
| 1334 | − ret = -EFAULT; | |
| 1335 | − goto error; | |
| 1336 | − } | |
| 1337 | − } | |
| 1338 | 1432 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, |
| 1339 | 1433 | as->urb->transfer_buffer_length, 0, SUBMIT, |
| 1340 | − is_in ? NULL : as->urb->transfer_buffer, | |
| 1341 | − uurb->buffer_length); | |
| 1434 | + NULL, 0); | |
| 1435 | + if (!is_in) | |
| 1436 | + snoop_urb_data(as->urb, as->urb->transfer_buffer_length); | |
| 1437 | + | |
| 1342 | 1438 | async_newpending(as); |
| 1343 | 1439 | |
| 1344 | 1440 | if (usb_endpoint_xfer_bulk(&ep->desc)) { |
| @@ -1433,11 +1529,7 @@ static int processcompl(struct async *as, void __user * __user *arg) · 88 unmodified lines | ||
| 1433 | 1529 | unsigned int i; |
| 1434 | 1530 | |
| 1435 | 1531 | if (as->userbuffer && urb->actual_length) { |
| 1436 | − if (urb->number_of_packets > 0) /* Isochronous */ | |
| 1437 | − i = urb->transfer_buffer_length; | |
| 1438 | − else /* Non-Isoc */ | |
| 1439 | − i = urb->actual_length; | |
| 1440 | − if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) | |
| 1532 | + if (copy_urb_data_to_user(as->userbuffer, urb)) | |
| 1441 | 1533 | goto err_out; |
| 1442 | 1534 | } |
| 1443 | 1535 | if (put_user(as->status, &userurb->status)) |
| @@ -1604,10 +1696,10 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) · 160 unmodified lines | ||
| 1604 | 1696 | void __user *addr = as->userurb; |
| 1605 | 1697 | unsigned int i; |
| 1606 | 1698 | |
| 1607 | − if (as->userbuffer && urb->actual_length) | |
| 1608 | − if (copy_to_user(as->userbuffer, urb->transfer_buffer, | |
| 1609 | − urb->actual_length)) | |
| 1699 | + if (as->userbuffer && urb->actual_length) { | |
| 1700 | + if (copy_urb_data_to_user(as->userbuffer, urb)) | |
| 1610 | 1701 | return -EFAULT; |
| 1702 | + } | |
| 1611 | 1703 | if (put_user(as->status, &userurb->status)) |
| 1612 | 1704 | return -EFAULT; |
| 1613 | 1705 | if (put_user(urb->actual_length, &userurb->actual_length)) |
| @@ -1820,6 +1912,22 @@ static int proc_release_port(struct dev_state *ps, void __user *arg) · 206 unmodified lines | ||
| 1820 | 1912 | return usb_hub_release_port(ps->dev, portnum, ps); |
| 1821 | 1913 | } |
| 1822 | 1914 | |
| 1915 | +static int proc_get_capabilities(struct dev_state *ps, void __user *arg) | |
| 1916 | +{ | |
| 1917 | + __u32 caps; | |
| 1918 | + | |
| 1919 | + caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM; | |
| 1920 | + if (!ps->dev->bus->no_stop_on_short) | |
| 1921 | + caps |= USBDEVFS_CAP_BULK_CONTINUATION; | |
| 1922 | + if (ps->dev->bus->sg_tablesize) | |
| 1923 | + caps |= USBDEVFS_CAP_BULK_SCATTER_GATHER; | |
| 1924 | + | |
| 1925 | + if (put_user(caps, (__u32 __user *)arg)) | |
| 1926 | + return -EFAULT; | |
| 1927 | + | |
| 1928 | + return 0; | |
| 1929 | +} | |
| 1930 | + | |
| 1823 | 1931 | /* |
| 1824 | 1932 | * NOTE: All requests here that have interface numbers as parameters |
| 1825 | 1933 | * are assuming that somehow the configuration has been prevented from |
| @@ -1990,6 +2098,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, · 164 unmodified lines | ||
| 1990 | 2098 | snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__); |
| 1991 | 2099 | ret = proc_release_port(ps, p); |
| 1992 | 2100 | break; |
| 2101 | + case USBDEVFS_GET_CAPABILITIES: | |
| 2102 | + ret = proc_get_capabilities(ps, p); | |
| 2103 | + break; | |
| 1993 | 2104 | } |
| 1994 | 2105 | usb_unlock_device(dev); |
| 1995 | 2106 | if (ret >= 0) |
| @@ -367,6 +367,7 @@ static int usb_probe_interface(struct device *dev) · 366 unmodified lines | ||
| 367 | 367 | return error; |
| 368 | 368 | |
| 369 | 369 | err: |
| 370 | + usb_set_intfdata(intf, NULL); | |
| 370 | 371 | intf->needs_remote_wakeup = 0; |
| 371 | 372 | intf->condition = USB_INTERFACE_UNBOUND; |
| 372 | 373 | usb_cancel_queued_reset(intf); |
| @@ -606,30 +607,19 @@ int usb_match_device(struct usb_device *dev, const struct usb_device_id *id) · 233 unmodified lines | ||
| 606 | 607 | } |
| 607 | 608 | |
| 608 | 609 | /* returns 0 if no match, 1 if match */ |
| 609 | −int usb_match_one_id(struct usb_interface *interface, | |
| 610 | − const struct usb_device_id *id) | |
| 610 | +int usb_match_one_id_intf(struct usb_device *dev, | |
| 611 | + struct usb_host_interface *intf, | |
| 612 | + const struct usb_device_id *id) | |
| 611 | 613 | { |
| 612 | − struct usb_host_interface *intf; | |
| 613 | − struct usb_device *dev; | |
| 614 | − | |
| 615 | − /* proc_connectinfo in devio.c may call us with id == NULL. */ | |
| 616 | − if (id == NULL) | |
| 617 | − return 0; | |
| 618 | − | |
| 619 | − intf = interface->cur_altsetting; | |
| 620 | − dev = interface_to_usbdev(interface); | |
| 621 | − | |
| 622 | − if (!usb_match_device(dev, id)) | |
| 623 | − return 0; | |
| 624 | − | |
| 625 | − /* The interface class, subclass, and protocol should never be | |
| 614 | + /* The interface class, subclass, protocol and number should never be | |
| 626 | 615 | * checked for a match if the device class is Vendor Specific, |
| 627 | 616 | * unless the match record specifies the Vendor ID. */ |
| 628 | 617 | if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && |
| 629 | 618 | !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && |
| 630 | 619 | (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | |
| 631 | 620 | USB_DEVICE_ID_MATCH_INT_SUBCLASS | |
| 632 | − USB_DEVICE_ID_MATCH_INT_PROTOCOL))) | |
| 621 | + USB_DEVICE_ID_MATCH_INT_PROTOCOL | | |
| 622 | + USB_DEVICE_ID_MATCH_INT_NUMBER))) | |
| 633 | 623 | return 0; |
| 634 | 624 | |
| 635 | 625 | if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && |
| @@ -644,8 +634,32 @@ int usb_match_one_id(struct usb_interface *interface, · 8 unmodified lines | ||
| 644 | 634 | (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) |
| 645 | 635 | return 0; |
| 646 | 636 | |
| 637 | + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) && | |
| 638 | + (id->bInterfaceNumber != intf->desc.bInterfaceNumber)) | |
| 639 | + return 0; | |
| 640 | + | |
| 647 | 641 | return 1; |
| 648 | 642 | } |
| 643 | + | |
| 644 | +/* returns 0 if no match, 1 if match */ | |
| 645 | +int usb_match_one_id(struct usb_interface *interface, | |
| 646 | + const struct usb_device_id *id) | |
| 647 | +{ | |
| 648 | + struct usb_host_interface *intf; | |
| 649 | + struct usb_device *dev; | |
| 650 | + | |
| 651 | + /* proc_connectinfo in devio.c may call us with id == NULL. */ | |
| 652 | + if (id == NULL) | |
| 653 | + return 0; | |
| 654 | + | |
| 655 | + intf = interface->cur_altsetting; | |
| 656 | + dev = interface_to_usbdev(interface); | |
| 657 | + | |
| 658 | + if (!usb_match_device(dev, id)) | |
| 659 | + return 0; | |
| 660 | + | |
| 661 | + return usb_match_one_id_intf(dev, intf, id); | |
| 662 | +} | |
| 649 | 663 | EXPORT_SYMBOL_GPL(usb_match_one_id); |
| 650 | 664 | |
| 651 | 665 | /** |
| @@ -92,7 +92,7 @@ static int init_usb_class(void) · 91 unmodified lines | ||
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | kref_init(&usb_class->kref); |
| 95 | − usb_class->class = class_create(THIS_MODULE, "usb"); | |
| 95 | + usb_class->class = class_create(THIS_MODULE, "usbmisc"); | |
| 96 | 96 | if (IS_ERR(usb_class->class)) { |
| 97 | 97 | result = IS_ERR(usb_class->class); |
| 98 | 98 | printk(KERN_ERR "class_create failed for usb devices\n"); |
| @@ -1398,7 +1398,15 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, · 1397 unmodified lines | ||
| 1398 | 1398 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { |
| 1399 | 1399 | if (hcd->self.uses_dma) { |
| 1400 | 1400 | if (urb->num_sgs) { |
| 1401 | − int n = dma_map_sg( | |
| 1401 | + int n; | |
| 1402 | + | |
| 1403 | + /* We don't support sg for isoc transfers ! */ | |
| 1404 | + if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { | |
| 1405 | + WARN_ON(1); | |
| 1406 | + return -EINVAL; | |
| 1407 | + } | |
| 1408 | + | |
| 1409 | + n = dma_map_sg( | |
| 1402 | 1410 | hcd->self.controller, |
| 1403 | 1411 | urb->sg, |
| 1404 | 1412 | urb->num_sgs, |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/usb.h> |
| 21 | 21 | #include <linux/usbdevice_fs.h> |
| 22 | 22 | #include <linux/usb/hcd.h> |
| 23 | +#include <linux/usb/otg.h> | |
| 23 | 24 | #include <linux/usb/quirks.h> |
| 24 | 25 | #include <linux/kthread.h> |
| 25 | 26 | #include <linux/mutex.h> |
| @@ -81,7 +82,7 @@ struct usb_hub { · 55 unmodified lines | ||
| 81 | 82 | u8 indicator[USB_MAXCHILDREN]; |
| 82 | 83 | struct delayed_work leds; |
| 83 | 84 | struct delayed_work init_work; |
| 84 | − void **port_owners; | |
| 85 | + struct dev_state **port_owners; | |
| 85 | 86 | }; |
| 86 | 87 | |
| 87 | 88 | static inline int hub_is_superspeed(struct usb_device *hdev) |
| @@ -1271,7 +1272,8 @@ static int hub_configure(struct usb_hub *hub, · 1183 unmodified lines | ||
| 1271 | 1272 | |
| 1272 | 1273 | hdev->children = kzalloc(hdev->maxchild * |
| 1273 | 1274 | sizeof(struct usb_device *), GFP_KERNEL); |
| 1274 | − hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL); | |
| 1275 | + hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), | |
| 1276 | + GFP_KERNEL); | |
| 1275 | 1277 | if (!hdev->children || !hub->port_owners) { |
| 1276 | 1278 | ret = -ENOMEM; |
| 1277 | 1279 | goto fail; |
| @@ -1649,7 +1651,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) · 371 unmodified lines | ||
| 1649 | 1651 | * to one of these "claimed" ports, the program will "own" the device. |
| 1650 | 1652 | */ |
| 1651 | 1653 | static int find_port_owner(struct usb_device *hdev, unsigned port1, |
| 1652 | − void ***ppowner) | |
| 1654 | + struct dev_state ***ppowner) | |
| 1653 | 1655 | { |
| 1654 | 1656 | if (hdev->state == USB_STATE_NOTATTACHED) |
| 1655 | 1657 | return -ENODEV; |
| @@ -1664,10 +1666,11 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, · 8 unmodified lines | ||
| 1664 | 1666 | } |
| 1665 | 1667 | |
| 1666 | 1668 | /* In the following three functions, the caller must hold hdev's lock */ |
| 1667 | −int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) | |
| 1669 | +int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, | |
| 1670 | + struct dev_state *owner) | |
| 1668 | 1671 | { |
| 1669 | 1672 | int rc; |
| 1670 | − void **powner; | |
| 1673 | + struct dev_state **powner; | |
| 1671 | 1674 | |
| 1672 | 1675 | rc = find_port_owner(hdev, port1, &powner); |
| 1673 | 1676 | if (rc) |
| @@ -1678,10 +1681,11 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) · 4 unmodified lines | ||
| 1678 | 1681 | return rc; |
| 1679 | 1682 | } |
| 1680 | 1683 | |
| 1681 | −int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) | |
| 1684 | +int usb_hub_release_port(struct usb_device *hdev, unsigned port1, | |
| 1685 | + struct dev_state *owner) | |
| 1682 | 1686 | { |
| 1683 | 1687 | int rc; |
| 1684 | − void **powner; | |
| 1688 | + struct dev_state **powner; | |
| 1685 | 1689 | |
| 1686 | 1690 | rc = find_port_owner(hdev, port1, &powner); |
| 1687 | 1691 | if (rc) |
| @@ -1692,10 +1696,10 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) · 4 unmodified lines | ||
| 1692 | 1696 | return rc; |
| 1693 | 1697 | } |
| 1694 | 1698 | |
| 1695 | −void usb_hub_release_all_ports(struct usb_device *hdev, void *owner) | |
| 1699 | +void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) | |
| 1696 | 1700 | { |
| 1697 | 1701 | int n; |
| 1698 | − void **powner; | |
| 1702 | + struct dev_state **powner; | |
| 1699 | 1703 | |
| 1700 | 1704 | n = find_port_owner(hdev, 1, &powner); |
| 1701 | 1705 | if (n == 0) { |
| @@ -2065,7 +2069,7 @@ static int usb_enumerate_device(struct usb_device *udev) · 363 unmodified lines | ||
| 2065 | 2069 | if (err < 0) { |
| 2066 | 2070 | dev_err(&udev->dev, "can't read configurations, error %d\n", |
| 2067 | 2071 | err); |
| 2068 | − goto fail; | |
| 2072 | + return err; | |
| 2069 | 2073 | } |
| 2070 | 2074 | } |
| 2071 | 2075 | if (udev->wusb == 1 && udev->authorized == 0) { |
| @@ -2081,8 +2085,12 @@ static int usb_enumerate_device(struct usb_device *udev) · 9 unmodified lines | ||
| 2081 | 2085 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); |
| 2082 | 2086 | } |
| 2083 | 2087 | err = usb_enumerate_device_otg(udev); |
| 2084 | −fail: | |
| 2085 | − return err; | |
| 2088 | + if (err < 0) | |
| 2089 | + return err; | |
| 2090 | + | |
| 2091 | + usb_detect_interface_quirks(udev); | |
| 2092 | + | |
| 2093 | + return 0; | |
| 2086 | 2094 | } |
| 2087 | 2095 | |
| 2088 | 2096 | static void set_usb_port_removable(struct usb_device *udev) |
| @@ -2611,6 +2619,50 @@ static int check_port_resume_type(struct usb_device *udev, · 522 unmodified lines | ||
| 2611 | 2619 | return status; |
| 2612 | 2620 | } |
| 2613 | 2621 | |
| 2622 | +int usb_disable_ltm(struct usb_device *udev) | |
| 2623 | +{ | |
| 2624 | + struct usb_hcd *hcd = bus_to_hcd(udev->bus); | |
| 2625 | + | |
| 2626 | + /* Check if the roothub and device supports LTM. */ | |
| 2627 | + if (!usb_device_supports_ltm(hcd->self.root_hub) || | |
| 2628 | + !usb_device_supports_ltm(udev)) | |
| 2629 | + return 0; | |
| 2630 | + | |
| 2631 | + /* Clear Feature LTM Enable can only be sent if the device is | |
| 2632 | + * configured. | |
| 2633 | + */ | |
| 2634 | + if (!udev->actconfig) | |
| 2635 | + return 0; | |
| 2636 | + | |
| 2637 | + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
| 2638 | + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | |
| 2639 | + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, | |
| 2640 | + USB_CTRL_SET_TIMEOUT); | |
| 2641 | +} | |
| 2642 | +EXPORT_SYMBOL_GPL(usb_disable_ltm); | |
| 2643 | + | |
| 2644 | +void usb_enable_ltm(struct usb_device *udev) | |
| 2645 | +{ | |
| 2646 | + struct usb_hcd *hcd = bus_to_hcd(udev->bus); | |
| 2647 | + | |
| 2648 | + /* Check if the roothub and device supports LTM. */ | |
| 2649 | + if (!usb_device_supports_ltm(hcd->self.root_hub) || | |
| 2650 | + !usb_device_supports_ltm(udev)) | |
| 2651 | + return; | |
| 2652 | + | |
| 2653 | + /* Set Feature LTM Enable can only be sent if the device is | |
| 2654 | + * configured. | |
| 2655 | + */ | |
| 2656 | + if (!udev->actconfig) | |
| 2657 | + return; | |
| 2658 | + | |
| 2659 | + usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
| 2660 | + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, | |
| 2661 | + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, | |
| 2662 | + USB_CTRL_SET_TIMEOUT); | |
| 2663 | +} | |
| 2664 | +EXPORT_SYMBOL_GPL(usb_enable_ltm); | |
| 2665 | + | |
| 2614 | 2666 | #ifdef CONFIG_USB_SUSPEND |
| 2615 | 2667 | |
| 2616 | 2668 | /* |
| @@ -2706,6 +2758,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) · 89 unmodified lines | ||
| 2706 | 2758 | if (udev->usb2_hw_lpm_enabled == 1) |
| 2707 | 2759 | usb_set_usb2_hardware_lpm(udev, 0); |
| 2708 | 2760 | |
| 2761 | + if (usb_disable_ltm(udev)) { | |
| 2762 | + dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.", | |
| 2763 | + __func__); | |
| 2764 | + return -ENOMEM; | |
| 2765 | + } | |
| 2709 | 2766 | if (usb_unlocked_disable_lpm(udev)) { |
| 2710 | 2767 | dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", |
| 2711 | 2768 | __func__); |
| @@ -2735,7 +2792,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) · 23 unmodified lines | ||
| 2735 | 2792 | if (udev->usb2_hw_lpm_capable == 1) |
| 2736 | 2793 | usb_set_usb2_hardware_lpm(udev, 1); |
| 2737 | 2794 | |
| 2738 | − /* Try to enable USB3 LPM again */ | |
| 2795 | + /* Try to enable USB3 LTM and LPM again */ | |
| 2796 | + usb_enable_ltm(udev); | |
| 2739 | 2797 | usb_unlocked_enable_lpm(udev); |
| 2740 | 2798 | |
| 2741 | 2799 | /* System sleep transitions should never fail */ |
| @@ -2936,7 +2994,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) · 194 unmodified lines | ||
| 2936 | 2994 | if (udev->usb2_hw_lpm_capable == 1) |
| 2937 | 2995 | usb_set_usb2_hardware_lpm(udev, 1); |
| 2938 | 2996 | |
| 2939 | − /* Try to enable USB3 LPM */ | |
| 2997 | + /* Try to enable USB3 LTM and LPM */ | |
| 2998 | + usb_enable_ltm(udev); | |
| 2940 | 2999 | usb_unlocked_enable_lpm(udev); |
| 2941 | 3000 | } |
| 2942 | 3001 | |
| @@ -3489,6 +3548,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); · 546 unmodified lines | ||
| 3489 | 3548 | |
| 3490 | 3549 | void usb_unlocked_enable_lpm(struct usb_device *udev) { } |
| 3491 | 3550 | EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); |
| 3551 | + | |
| 3552 | +int usb_disable_ltm(struct usb_device *udev) | |
| 3553 | +{ | |
| 3554 | + return 0; | |
| 3555 | +} | |
| 3556 | +EXPORT_SYMBOL_GPL(usb_disable_ltm); | |
| 3557 | + | |
| 3558 | +void usb_enable_ltm(struct usb_device *udev) { } | |
| 3559 | +EXPORT_SYMBOL_GPL(usb_enable_ltm); | |
| 3492 | 3560 | #endif |
| 3493 | 3561 | |
| 3494 | 3562 | |
| @@ -4038,6 +4106,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, · 543 unmodified lines | ||
| 4038 | 4106 | } |
| 4039 | 4107 | } |
| 4040 | 4108 | |
| 4109 | + if (hcd->phy && !hdev->parent) { | |
| 4110 | + if (portstatus & USB_PORT_STAT_CONNECTION) | |
| 4111 | + usb_phy_notify_connect(hcd->phy, port1); | |
| 4112 | + else | |
| 4113 | + usb_phy_notify_disconnect(hcd->phy, port1); | |
| 4114 | + } | |
| 4115 | + | |
| 4041 | 4116 | /* Return now if debouncing failed or nothing is connected or |
| 4042 | 4117 | * the device was "removed". |
| 4043 | 4118 | */ |
| @@ -4672,6 +4747,23 @@ static int usb_reset_and_verify_device(struct usb_device *udev) · 628 unmodified lines | ||
| 4672 | 4747 | } |
| 4673 | 4748 | parent_hub = hdev_to_hub(parent_hdev); |
| 4674 | 4749 | |
| 4750 | + /* Disable LPM and LTM while we reset the device and reinstall the alt | |
| 4751 | + * settings. Device-initiated LPM settings, and system exit latency | |
| 4752 | + * settings are cleared when the device is reset, so we have to set | |
| 4753 | + * them up again. | |
| 4754 | + */ | |
| 4755 | + ret = usb_unlocked_disable_lpm(udev); | |
| 4756 | + if (ret) { | |
| 4757 | + dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); | |
| 4758 | + goto re_enumerate; | |
| 4759 | + } | |
| 4760 | + ret = usb_disable_ltm(udev); | |
| 4761 | + if (ret) { | |
| 4762 | + dev_err(&udev->dev, "%s Failed to disable LTM\n.", | |
| 4763 | + __func__); | |
| 4764 | + goto re_enumerate; | |
| 4765 | + } | |
| 4766 | + | |
| 4675 | 4767 | set_bit(port1, parent_hub->busy_bits); |
| 4676 | 4768 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { |
| 4677 | 4769 | |
| @@ -4699,22 +4791,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev) · 21 unmodified lines | ||
| 4699 | 4791 | goto done; |
| 4700 | 4792 | |
| 4701 | 4793 | mutex_lock(hcd->bandwidth_mutex); |
| 4702 | − /* Disable LPM while we reset the device and reinstall the alt settings. | |
| 4703 | − * Device-initiated LPM settings, and system exit latency settings are | |
| 4704 | − * cleared when the device is reset, so we have to set them up again. | |
| 4705 | − */ | |
| 4706 | − ret = usb_disable_lpm(udev); | |
| 4707 | − if (ret) { | |
| 4708 | − dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); | |
| 4709 | − mutex_unlock(hcd->bandwidth_mutex); | |
| 4710 | − goto done; | |
| 4711 | − } | |
| 4712 | 4794 | ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); |
| 4713 | 4795 | if (ret < 0) { |
| 4714 | 4796 | dev_warn(&udev->dev, |
| 4715 | 4797 | "Busted HC? Not enough HCD resources for " |
| 4716 | 4798 | "old configuration.\n"); |
| 4717 | − usb_enable_lpm(udev); | |
| 4718 | 4799 | mutex_unlock(hcd->bandwidth_mutex); |
| 4719 | 4800 | goto re_enumerate; |
| 4720 | 4801 | } |
| @@ -4726,7 +4807,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) · 5 unmodified lines | ||
| 4726 | 4807 | dev_err(&udev->dev, |
| 4727 | 4808 | "can't restore configuration #%d (error=%d)\n", |
| 4728 | 4809 | udev->actconfig->desc.bConfigurationValue, ret); |
| 4729 | − usb_enable_lpm(udev); | |
| 4730 | 4810 | mutex_unlock(hcd->bandwidth_mutex); |
| 4731 | 4811 | goto re_enumerate; |
| 4732 | 4812 | } |
| @@ -4765,17 +4845,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev) · 32 unmodified lines | ||
| 4765 | 4845 | desc->bInterfaceNumber, |
| 4766 | 4846 | desc->bAlternateSetting, |
| 4767 | 4847 | ret); |
| 4768 | − usb_unlocked_enable_lpm(udev); | |
| 4769 | 4848 | goto re_enumerate; |
| 4770 | 4849 | } |
| 4771 | 4850 | } |
| 4772 | 4851 | |
| 4773 | − /* Now that the alt settings are re-installed, enable LPM. */ | |
| 4774 | − usb_unlocked_enable_lpm(udev); | |
| 4775 | 4852 | done: |
| 4853 | + /* Now that the alt settings are re-installed, enable LTM and LPM. */ | |
| 4854 | + usb_unlocked_enable_lpm(udev); | |
| 4855 | + usb_enable_ltm(udev); | |
| 4776 | 4856 | return 0; |
| 4777 | 4857 | |
| 4778 | 4858 | re_enumerate: |
| 4859 | + /* LPM state doesn't matter when we're about to destroy the device. */ | |
| 4779 | 4860 | hub_port_logical_disconnect(parent_hub, port1); |
| 4780 | 4861 | return -ENODEV; |
| 4781 | 4862 | } |
| @@ -1174,6 +1174,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) · 1173 unmodified lines | ||
| 1174 | 1174 | put_device(&dev->actconfig->interface[i]->dev); |
| 1175 | 1175 | dev->actconfig->interface[i] = NULL; |
| 1176 | 1176 | } |
| 1177 | + usb_unlocked_disable_lpm(dev); | |
| 1178 | + usb_disable_ltm(dev); | |
| 1177 | 1179 | dev->actconfig = NULL; |
| 1178 | 1180 | if (dev->state == USB_STATE_CONFIGURED) |
| 1179 | 1181 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
| @@ -1559,7 +1561,7 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) · 379 unmodified lines | ||
| 1559 | 1561 | |
| 1560 | 1562 | if (add_uevent_var(env, |
| 1561 | 1563 | "MODALIAS=usb:" |
| 1562 | − "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | |
| 1564 | + "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02Xin%02X", | |
| 1563 | 1565 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 1564 | 1566 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| 1565 | 1567 | le16_to_cpu(usb_dev->descriptor.bcdDevice), |
| @@ -1568,7 +1570,8 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) · 2 unmodified lines | ||
| 1568 | 1570 | usb_dev->descriptor.bDeviceProtocol, |
| 1569 | 1571 | alt->desc.bInterfaceClass, |
| 1570 | 1572 | alt->desc.bInterfaceSubClass, |
| 1571 | − alt->desc.bInterfaceProtocol)) | |
| 1573 | + alt->desc.bInterfaceProtocol, | |
| 1574 | + alt->desc.bInterfaceNumber)) | |
| 1572 | 1575 | return -ENOMEM; |
| 1573 | 1576 | |
| 1574 | 1577 | return 0; |
| @@ -1791,14 +1794,15 @@ free_interfaces: · 216 unmodified lines | ||
| 1791 | 1794 | * installed, so that the xHCI driver can recalculate the U1/U2 |
| 1792 | 1795 | * timeouts. |
| 1793 | 1796 | */ |
| 1794 | − if (usb_disable_lpm(dev)) { | |
| 1797 | + if (dev->actconfig && usb_disable_lpm(dev)) { | |
| 1795 | 1798 | dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__); |
| 1796 | 1799 | mutex_unlock(hcd->bandwidth_mutex); |
| 1797 | 1800 | return -ENOMEM; |
| 1798 | 1801 | } |
| 1799 | 1802 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); |
| 1800 | 1803 | if (ret < 0) { |
| 1801 | − usb_enable_lpm(dev); | |
| 1804 | + if (dev->actconfig) | |
| 1805 | + usb_enable_lpm(dev); | |
| 1802 | 1806 | mutex_unlock(hcd->bandwidth_mutex); |
| 1803 | 1807 | usb_autosuspend_device(dev); |
| 1804 | 1808 | goto free_interfaces; |
| @@ -1818,7 +1822,7 @@ free_interfaces: · 13 unmodified lines | ||
| 1818 | 1822 | if (!cp) { |
| 1819 | 1823 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
| 1820 | 1824 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); |
| 1821 | − usb_enable_lpm(dev); | |
| 1825 | + /* Leave LPM disabled while the device is unconfigured. */ | |
| 1822 | 1826 | mutex_unlock(hcd->bandwidth_mutex); |
| 1823 | 1827 | usb_autosuspend_device(dev); |
| 1824 | 1828 | goto free_interfaces; |
| @@ -1876,6 +1880,8 @@ free_interfaces: · 51 unmodified lines | ||
| 1876 | 1880 | |
| 1877 | 1881 | /* Now that the interfaces are installed, re-enable LPM. */ |
| 1878 | 1882 | usb_unlocked_enable_lpm(dev); |
| 1883 | + /* Enable LTM if it was turned off by usb_disable_device. */ | |
| 1884 | + usb_enable_ltm(dev); | |
| 1879 | 1885 | |
| 1880 | 1886 | /* Now that all the interfaces are set up, register them |
| 1881 | 1887 | * to trigger binding of drivers to interfaces. probe() |
| @@ -15,17 +15,22 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/usb/quirks.h> |
| 16 | 16 | #include "usb.h" |
| 17 | 17 | |
| 18 | −/* List of quirky USB devices. Please keep this list ordered by: | |
| 18 | +/* Lists of quirky USB devices, split in device quirks and interface quirks. | |
| 19 | + * Device quirks are applied at the very beginning of the enumeration process, | |
| 20 | + * right after reading the device descriptor. They can thus only match on device | |
| 21 | + * information. | |
| 22 | + * | |
| 23 | + * Interface quirks are applied after reading all the configuration descriptors. | |
| 24 | + * They can match on both device and interface information. | |
| 25 | + * | |
| 26 | + * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as | |
| 27 | + * interface quirks, as they only influence the enumeration process which is run | |
| 28 | + * before processing the interface quirks. | |
| 29 | + * | |
| 30 | + * Please keep the lists ordered by: | |
| 19 | 31 | * 1) Vendor ID |
| 20 | 32 | * 2) Product ID |
| 21 | 33 | * 3) Class ID |
| 22 | − * | |
| 23 | − * as we want specific devices to be overridden first, and only after that, any | |
| 24 | − * class specific quirks. | |
| 25 | − * | |
| 26 | − * Right now the logic aborts if it finds a valid device in the table, we might | |
| 27 | − * want to change that in the future if it turns out that a whole class of | |
| 28 | − * devices is broken... | |
| 29 | 34 | */ |
| 30 | 35 | static const struct usb_device_id usb_quirk_list[] = { |
| 31 | 36 | /* CBM - Flash disk */ |
| @@ -38,53 +43,23 @@ static const struct usb_device_id usb_quirk_list[] = { · 6 unmodified lines | ||
| 38 | 43 | /* Creative SB Audigy 2 NX */ |
| 39 | 44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 40 | 45 | |
| 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 C600 */ | |
| 54 | − { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 55 | − | |
| 56 | − /* Logitech Webcam Pro 9000 */ | |
| 57 | − { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 46 | + /* Logitech Quickcam Fusion */ | |
| 47 | + { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 58 | 48 | |
| 59 | − /* Logitech Webcam C905 */ | |
| 60 | − { USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 49 | + /* Logitech Quickcam Orbit MP */ | |
| 50 | + { USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 61 | 51 | |
| 62 | − /* Logitech Webcam C210 */ | |
| 63 | − { USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 52 | + /* Logitech Quickcam Pro for Notebook */ | |
| 53 | + { USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 64 | 54 | |
| 65 | − /* Logitech Webcam C260 */ | |
| 66 | − { USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 55 | + /* Logitech Quickcam Pro 5000 */ | |
| 56 | + { USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 67 | 57 | |
| 68 | − /* Logitech Webcam C310 */ | |
| 69 | − { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 58 | + /* Logitech Quickcam OEM Dell Notebook */ | |
| 59 | + { USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 70 | 60 | |
| 71 | − /* Logitech Webcam C910 */ | |
| 72 | − { USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 73 | − | |
| 74 | − /* Logitech Webcam C160 */ | |
| 75 | − { USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 76 | − | |
| 77 | − /* Logitech Webcam C270 */ | |
| 78 | − { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 79 | − | |
| 80 | − /* Logitech Quickcam Pro 9000 */ | |
| 81 | − { USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 82 | − | |
| 83 | − /* Logitech Quickcam E3500 */ | |
| 84 | − { USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 85 | − | |
| 86 | − /* Logitech Quickcam Vision Pro */ | |
| 87 | − { USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 61 | + /* Logitech Quickcam OEM Cisco VT Camera II */ | |
| 62 | + { USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 88 | 63 | |
| 89 | 64 | /* Logitech Harmony 700-series */ |
| 90 | 65 | { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, |
| @@ -156,16 +131,57 @@ static const struct usb_device_id usb_quirk_list[] = { · 65 unmodified lines | ||
| 156 | 131 | { } /* terminating entry must be last */ |
| 157 | 132 | }; |
| 158 | 133 | |
| 159 | −static const struct usb_device_id *find_id(struct usb_device *udev) | |
| 134 | +static const struct usb_device_id usb_interface_quirk_list[] = { | |
| 135 | + /* Logitech UVC Cameras */ | |
| 136 | + { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), | |
| 137 | + .driver_info = USB_QUIRK_RESET_RESUME }, | |
| 138 | + | |
| 139 | + { } /* terminating entry must be last */ | |
| 140 | +}; | |
| 141 | + | |
| 142 | +static bool usb_match_any_interface(struct usb_device *udev, | |
| 143 | + const struct usb_device_id *id) | |
| 160 | 144 | { |
| 161 | − const struct usb_device_id *id = usb_quirk_list; | |
| 145 | + unsigned int i; | |
| 162 | 146 | |
| 163 | − for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || | |
| 164 | − id->driver_info; id++) { | |
| 165 | − if (usb_match_device(udev, id)) | |
| 166 | − return id; | |
| 147 | + for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) { | |
| 148 | + struct usb_host_config *cfg = &udev->config[i]; | |
| 149 | + unsigned int j; | |
| 150 | + | |
| 151 | + for (j = 0; j < cfg->desc.bNumInterfaces; ++j) { | |
| 152 | + struct usb_interface_cache *cache; | |
| 153 | + struct usb_host_interface *intf; | |
| 154 | + | |
| 155 | + cache = cfg->intf_cache[j]; | |
| 156 | + if (cache->num_altsetting == 0) | |
| 157 | + continue; | |
| 158 | + | |
| 159 | + intf = &cache->altsetting[0]; | |
| 160 | + if (usb_match_one_id_intf(udev, intf, id)) | |
| 161 | + return true; | |
| 162 | + } | |
| 163 | + } | |
| 164 | + | |
| 165 | + return false; | |
| 166 | +} | |
| 167 | + | |
| 168 | +static u32 __usb_detect_quirks(struct usb_device *udev, | |
| 169 | + const struct usb_device_id *id) | |
| 170 | +{ | |
| 171 | + u32 quirks = 0; | |
| 172 | + | |
| 173 | + for (; id->match_flags; id++) { | |
| 174 | + if (!usb_match_device(udev, id)) | |
| 175 | + continue; | |
| 176 | + | |
| 177 | + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) && | |
| 178 | + !usb_match_any_interface(udev, id)) | |
| 179 | + continue; | |
| 180 | + | |
| 181 | + quirks |= (u32)(id->driver_info); | |
| 167 | 182 | } |
| 168 | − return NULL; | |
| 183 | + | |
| 184 | + return quirks; | |
| 169 | 185 | } |
| 170 | 186 | |
| 171 | 187 | /* |
| @@ -173,14 +189,10 @@ static const struct usb_device_id *find_id(struct usb_device *udev) · 1 unmodified line | ||
| 173 | 189 | */ |
| 174 | 190 | void usb_detect_quirks(struct usb_device *udev) |
| 175 | 191 | { |
| 176 | − const struct usb_device_id *id = usb_quirk_list; | |
| 177 | − | |
| 178 | − id = find_id(udev); | |
| 179 | − if (id) | |
| 180 | − udev->quirks = (u32)(id->driver_info); | |
| 192 | + udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); | |
| 181 | 193 | if (udev->quirks) |
| 182 | 194 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", |
| 183 | − udev->quirks); | |
| 195 | + udev->quirks); | |
| 184 | 196 | |
| 185 | 197 | /* For the present, all devices default to USB-PERSIST enabled */ |
| 186 | 198 | #if 0 /* was: #ifdef CONFIG_PM */ |
| @@ -197,3 +209,16 @@ void usb_detect_quirks(struct usb_device *udev) · 10 unmodified lines | ||
| 197 | 209 | udev->persist_enabled = 1; |
| 198 | 210 | #endif /* CONFIG_PM */ |
| 199 | 211 | } |
| 212 | + | |
| 213 | +void usb_detect_interface_quirks(struct usb_device *udev) | |
| 214 | +{ | |
| 215 | + u32 quirks; | |
| 216 | + | |
| 217 | + quirks = __usb_detect_quirks(udev, usb_interface_quirk_list); | |
| 218 | + if (quirks == 0) | |
| 219 | + return; | |
| 220 | + | |
| 221 | + dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n", | |
| 222 | + quirks); | |
| 223 | + udev->quirks |= quirks; | |
| 224 | +} | |
| @@ -253,6 +253,15 @@ show_removable(struct device *dev, struct device_attribute *attr, char *buf) · 252 unmodified lines | ||
| 253 | 253 | } |
| 254 | 254 | static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); |
| 255 | 255 | |
| 256 | +static ssize_t | |
| 257 | +show_ltm_capable(struct device *dev, struct device_attribute *attr, char *buf) | |
| 258 | +{ | |
| 259 | + if (usb_device_supports_ltm(to_usb_device(dev))) | |
| 260 | + return sprintf(buf, "%s\n", "yes"); | |
| 261 | + return sprintf(buf, "%s\n", "no"); | |
| 262 | +} | |
| 263 | +static DEVICE_ATTR(ltm_capable, S_IRUGO, show_ltm_capable, NULL); | |
| 264 | + | |
| 256 | 265 | #ifdef CONFIG_PM |
| 257 | 266 | |
| 258 | 267 | static ssize_t |
| @@ -649,6 +658,7 @@ static struct attribute *dev_attrs[] = { · 390 unmodified lines | ||
| 649 | 658 | &dev_attr_authorized.attr, |
| 650 | 659 | &dev_attr_remove.attr, |
| 651 | 660 | &dev_attr_removable.attr, |
| 661 | + &dev_attr_ltm_capable.attr, | |
| 652 | 662 | NULL, |
| 653 | 663 | }; |
| 654 | 664 | static struct attribute_group dev_attr_grp = { |
| @@ -840,7 +850,7 @@ static ssize_t show_modalias(struct device *dev, · 185 unmodified lines | ||
| 840 | 850 | alt = intf->cur_altsetting; |
| 841 | 851 | |
| 842 | 852 | return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" |
| 843 | − "ic%02Xisc%02Xip%02X\n", | |
| 853 | + "ic%02Xisc%02Xip%02Xin%02X\n", | |
| 844 | 854 | le16_to_cpu(udev->descriptor.idVendor), |
| 845 | 855 | le16_to_cpu(udev->descriptor.idProduct), |
| 846 | 856 | le16_to_cpu(udev->descriptor.bcdDevice), |
| @@ -849,7 +859,8 @@ static ssize_t show_modalias(struct device *dev, · 2 unmodified lines | ||
| 849 | 859 | udev->descriptor.bDeviceProtocol, |
| 850 | 860 | alt->desc.bInterfaceClass, |
| 851 | 861 | alt->desc.bInterfaceSubClass, |
| 852 | − alt->desc.bInterfaceProtocol); | |
| 862 | + alt->desc.bInterfaceProtocol, | |
| 863 | + alt->desc.bInterfaceNumber); | |
| 853 | 864 | } |
| 854 | 865 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); |
| 855 | 866 | |
| @@ -396,6 +396,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, · 395 unmodified lines | ||
| 396 | 396 | dev->dev.dma_mask = bus->controller->dma_mask; |
| 397 | 397 | set_dev_node(&dev->dev, dev_to_node(bus->controller)); |
| 398 | 398 | dev->state = USB_STATE_ATTACHED; |
| 399 | + dev->lpm_disable_count = 1; | |
| 399 | 400 | atomic_set(&dev->urbnum, 0); |
| 400 | 401 | |
| 401 | 402 | INIT_LIST_HEAD(&dev->ep0.urb_list); |
| @@ -1,5 +1,7 @@ | ||
| 1 | 1 | #include <linux/pm.h> |
| 2 | 2 | |
| 3 | +struct dev_state; | |
| 4 | + | |
| 3 | 5 | /* Functions local to drivers/usb/core/ */ |
| 4 | 6 | |
| 5 | 7 | extern int usb_create_sysfs_dev_files(struct usb_device *dev); |
| @@ -24,6 +26,7 @@ extern void usb_disable_device(struct usb_device *dev, int skip_ep0); · 18 unmodified lines | ||
| 24 | 26 | extern int usb_deauthorize_device(struct usb_device *); |
| 25 | 27 | extern int usb_authorize_device(struct usb_device *); |
| 26 | 28 | extern void usb_detect_quirks(struct usb_device *udev); |
| 29 | +extern void usb_detect_interface_quirks(struct usb_device *udev); | |
| 27 | 30 | extern int usb_remove_device(struct usb_device *udev); |
| 28 | 31 | |
| 29 | 32 | extern int usb_get_device_descriptor(struct usb_device *dev, |
| @@ -35,16 +38,20 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration); · 5 unmodified lines | ||
| 35 | 38 | extern int usb_choose_configuration(struct usb_device *udev); |
| 36 | 39 | |
| 37 | 40 | extern void usb_kick_khubd(struct usb_device *dev); |
| 41 | +extern int usb_match_one_id_intf(struct usb_device *dev, | |
| 42 | + struct usb_host_interface *intf, | |
| 43 | + const struct usb_device_id *id); | |
| 38 | 44 | extern int usb_match_device(struct usb_device *dev, |
| 39 | 45 | const struct usb_device_id *id); |
| 40 | 46 | extern void usb_forced_unbind_intf(struct usb_interface *intf); |
| 41 | 47 | extern void usb_rebind_intf(struct usb_interface *intf); |
| 42 | 48 | |
| 43 | 49 | extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, |
| 44 | − void *owner); | |
| 50 | + struct dev_state *owner); | |
| 45 | 51 | extern int usb_hub_release_port(struct usb_device *hdev, unsigned port, |
| 46 | − void *owner); | |
| 47 | −extern void usb_hub_release_all_ports(struct usb_device *hdev, void *owner); | |
| 52 | + struct dev_state *owner); | |
| 53 | +extern void usb_hub_release_all_ports(struct usb_device *hdev, | |
| 54 | + struct dev_state *owner); | |
| 48 | 55 | extern bool usb_device_is_owned(struct usb_device *udev); |
| 49 | 56 | |
| 50 | 57 | extern int usb_hub_init(void); |
| @@ -148,6 +148,8 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc) · 147 unmodified lines | ||
| 148 | 148 | reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; |
| 149 | 149 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); |
| 150 | 150 | |
| 151 | + mdelay(100); | |
| 152 | + | |
| 151 | 153 | /* After PHYs are stable we can take Core out of reset state */ |
| 152 | 154 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); |
| 153 | 155 | reg &= ~DWC3_GCTL_CORESOFTRESET; |
| @@ -255,7 +257,7 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) · 101 unmodified lines | ||
| 255 | 257 | * |
| 256 | 258 | * Returns 0 on success otherwise negative errno. |
| 257 | 259 | */ |
| 258 | −static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) | |
| 260 | +static int dwc3_event_buffers_setup(struct dwc3 *dwc) | |
| 259 | 261 | { |
| 260 | 262 | struct dwc3_event_buffer *evt; |
| 261 | 263 | int n; |
| @@ -266,6 +268,8 @@ static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) · 4 unmodified lines | ||
| 266 | 268 | evt->buf, (unsigned long long) evt->dma, |
| 267 | 269 | evt->length); |
| 268 | 270 | |
| 271 | + evt->lpos = 0; | |
| 272 | + | |
| 269 | 273 | dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), |
| 270 | 274 | lower_32_bits(evt->dma)); |
| 271 | 275 | dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), |
| @@ -285,6 +289,9 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) · 13 unmodified lines | ||
| 285 | 289 | |
| 286 | 290 | for (n = 0; n < dwc->num_event_buffers; n++) { |
| 287 | 291 | evt = dwc->ev_buffs[n]; |
| 292 | + | |
| 293 | + evt->lpos = 0; | |
| 294 | + | |
| 288 | 295 | dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); |
| 289 | 296 | dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); |
| 290 | 297 | dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); |
| @@ -328,8 +335,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) · 37 unmodified lines | ||
| 328 | 335 | } |
| 329 | 336 | dwc->revision = reg; |
| 330 | 337 | |
| 331 | − dwc3_core_soft_reset(dwc); | |
| 332 | − | |
| 333 | 338 | /* issue device SoftReset too */ |
| 334 | 339 | timeout = jiffies + msecs_to_jiffies(500); |
| 335 | 340 | dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); |
| @@ -347,6 +352,8 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) · 11 unmodified lines | ||
| 347 | 352 | cpu_relax(); |
| 348 | 353 | } while (true); |
| 349 | 354 | |
| 355 | + dwc3_core_soft_reset(dwc); | |
| 356 | + | |
| 350 | 357 | dwc3_cache_hwparams(dwc); |
| 351 | 358 | |
| 352 | 359 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); |
| @@ -67,6 +67,7 @@ · 66 unmodified lines | ||
| 67 | 67 | #define DWC3_DEVICE_EVENT_CONNECT_DONE 2 |
| 68 | 68 | #define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE 3 |
| 69 | 69 | #define DWC3_DEVICE_EVENT_WAKEUP 4 |
| 70 | +#define DWC3_DEVICE_EVENT_HIBER_REQ 5 | |
| 70 | 71 | #define DWC3_DEVICE_EVENT_EOPF 6 |
| 71 | 72 | #define DWC3_DEVICE_EVENT_SOF 7 |
| 72 | 73 | #define DWC3_DEVICE_EVENT_ERRATIC_ERROR 9 |
| @@ -171,28 +172,36 @@ · 98 unmodified lines | ||
| 171 | 172 | #define DWC3_GCTL_PRTCAP_DEVICE 2 |
| 172 | 173 | #define DWC3_GCTL_PRTCAP_OTG 3 |
| 173 | 174 | |
| 174 | −#define DWC3_GCTL_CORESOFTRESET (1 << 11) | |
| 175 | −#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) | |
| 176 | −#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) | |
| 177 | −#define DWC3_GCTL_DISSCRAMBLE (1 << 3) | |
| 178 | −#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) | |
| 175 | +#define DWC3_GCTL_CORESOFTRESET (1 << 11) | |
| 176 | +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) | |
| 177 | +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) | |
| 178 | +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) | |
| 179 | +#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) | |
| 180 | +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) | |
| 179 | 181 | |
| 180 | 182 | /* Global USB2 PHY Configuration Register */ |
| 181 | −#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) | |
| 182 | −#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) | |
| 183 | +#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) | |
| 184 | +#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) | |
| 183 | 185 | |
| 184 | 186 | /* Global USB3 PIPE Control Register */ |
| 185 | −#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) | |
| 186 | −#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) | |
| 187 | +#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) | |
| 188 | +#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) | |
| 187 | 189 | |
| 188 | 190 | /* Global TX Fifo Size Register */ |
| 189 | −#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) | |
| 190 | −#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) | |
| 191 | +#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) | |
| 192 | +#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) | |
| 191 | 193 | |
| 192 | 194 | /* Global HWPARAMS1 Register */ |
| 193 | 195 | #define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) |
| 194 | 196 | #define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 |
| 195 | 197 | #define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 |
| 198 | +#define DWC3_GHWPARAMS1_EN_PWROPT_HIB 2 | |
| 199 | +#define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24) | |
| 200 | +#define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3) | |
| 201 | + | |
| 202 | +/* Global HWPARAMS4 Register */ | |
| 203 | +#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13) | |
| 204 | +#define DWC3_MAX_HIBER_SCRATCHBUFS 15 | |
| 196 | 205 | |
| 197 | 206 | /* Device Configuration Register */ |
| 198 | 207 | #define DWC3_DCFG_LPM_CAP (1 << 22) |
| @@ -206,24 +215,32 @@ · 7 unmodified lines | ||
| 206 | 215 | #define DWC3_DCFG_LOWSPEED (2 << 0) |
| 207 | 216 | #define DWC3_DCFG_FULLSPEED1 (3 << 0) |
| 208 | 217 | |
| 218 | +#define DWC3_DCFG_LPM_CAP (1 << 22) | |
| 219 | + | |
| 209 | 220 | /* Device Control Register */ |
| 210 | 221 | #define DWC3_DCTL_RUN_STOP (1 << 31) |
| 211 | 222 | #define DWC3_DCTL_CSFTRST (1 << 30) |
| 212 | 223 | #define DWC3_DCTL_LSFTRST (1 << 29) |
| 213 | 224 | |
| 214 | 225 | #define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) |
| 215 | −#define DWC3_DCTL_HIRD_THRES(n) (((n) & DWC3_DCTL_HIRD_THRES_MASK) >> 24) | |
| 226 | +#define DWC3_DCTL_HIRD_THRES(n) ((n) << 24) | |
| 216 | 227 | |
| 217 | 228 | #define DWC3_DCTL_APPL1RES (1 << 23) |
| 218 | 229 | |
| 219 | −#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) | |
| 220 | −#define DWC3_DCTL_TRGTULST(n) ((n) << 17) | |
| 221 | − | |
| 222 | −#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) | |
| 223 | −#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) | |
| 224 | −#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) | |
| 225 | −#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) | |
| 226 | −#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) | |
| 230 | +/* These apply for core versions 1.87a and earlier */ | |
| 231 | +#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) | |
| 232 | +#define DWC3_DCTL_TRGTULST(n) ((n) << 17) | |
| 233 | +#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) | |
| 234 | +#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) | |
| 235 | +#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) | |
| 236 | +#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) | |
| 237 | +#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) | |
| 238 | + | |
| 239 | +/* These apply for core versions 1.94a and later */ | |
| 240 | +#define DWC3_DCTL_KEEP_CONNECT (1 << 19) | |
| 241 | +#define DWC3_DCTL_L1_HIBER_EN (1 << 18) | |
| 242 | +#define DWC3_DCTL_CRS (1 << 17) | |
| 243 | +#define DWC3_DCTL_CSS (1 << 16) | |
| 227 | 244 | |
| 228 | 245 | #define DWC3_DCTL_INITU2ENA (1 << 12) |
| 229 | 246 | #define DWC3_DCTL_ACCEPTU2ENA (1 << 11) |
| @@ -249,6 +266,7 @@ · 19 unmodified lines | ||
| 249 | 266 | #define DWC3_DEVTEN_ERRTICERREN (1 << 9) |
| 250 | 267 | #define DWC3_DEVTEN_SOFEN (1 << 7) |
| 251 | 268 | #define DWC3_DEVTEN_EOPFEN (1 << 6) |
| 269 | +#define DWC3_DEVTEN_HIBERNATIONREQEVTEN (1 << 5) | |
| 252 | 270 | #define DWC3_DEVTEN_WKUPEVTEN (1 << 4) |
| 253 | 271 | #define DWC3_DEVTEN_ULSTCNGEN (1 << 3) |
| 254 | 272 | #define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) |
| @@ -256,7 +274,15 @@ · 1 unmodified line | ||
| 256 | 274 | #define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) |
| 257 | 275 | |
| 258 | 276 | /* Device Status Register */ |
| 277 | +#define DWC3_DSTS_DCNRD (1 << 29) | |
| 278 | + | |
| 279 | +/* This applies for core versions 1.87a and earlier */ | |
| 259 | 280 | #define DWC3_DSTS_PWRUPREQ (1 << 24) |
| 281 | + | |
| 282 | +/* These apply for core versions 1.94a and later */ | |
| 283 | +#define DWC3_DSTS_RSS (1 << 25) | |
| 284 | +#define DWC3_DSTS_SSS (1 << 24) | |
| 285 | + | |
| 260 | 286 | #define DWC3_DSTS_COREIDLE (1 << 23) |
| 261 | 287 | #define DWC3_DSTS_DEVCTRLHLT (1 << 22) |
| 262 | 288 | |
| @@ -265,7 +291,7 @@ · 2 unmodified lines | ||
| 265 | 291 | |
| 266 | 292 | #define DWC3_DSTS_RXFIFOEMPTY (1 << 17) |
| 267 | 293 | |
| 268 | −#define DWC3_DSTS_SOFFN_MASK (0x3ff << 3) | |
| 294 | +#define DWC3_DSTS_SOFFN_MASK (0x3fff << 3) | |
| 269 | 295 | #define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) |
| 270 | 296 | |
| 271 | 297 | #define DWC3_DSTS_CONNECTSPD (7 << 0) |
| @@ -280,6 +306,11 @@ · 8 unmodified lines | ||
| 280 | 306 | #define DWC3_DGCMD_SET_LMP 0x01 |
| 281 | 307 | #define DWC3_DGCMD_SET_PERIODIC_PAR 0x02 |
| 282 | 308 | #define DWC3_DGCMD_XMIT_FUNCTION 0x03 |
| 309 | + | |
| 310 | +/* These apply for core versions 1.94a and later */ | |
| 311 | +#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO 0x04 | |
| 312 | +#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI 0x05 | |
| 313 | + | |
| 283 | 314 | #define DWC3_DGCMD_SELECTED_FIFO_FLUSH 0x09 |
| 284 | 315 | #define DWC3_DGCMD_ALL_FIFO_FLUSH 0x0a |
| 285 | 316 | #define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c |
| @@ -287,6 +318,15 @@ · 1 unmodified line | ||
| 287 | 318 | |
| 288 | 319 | #define DWC3_DGCMD_STATUS(n) (((n) >> 15) & 1) |
| 289 | 320 | #define DWC3_DGCMD_CMDACT (1 << 10) |
| 321 | +#define DWC3_DGCMD_CMDIOC (1 << 8) | |
| 322 | + | |
| 323 | +/* Device Generic Command Parameter Register */ | |
| 324 | +#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT (1 << 0) | |
| 325 | +#define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0) | |
| 326 | +#define DWC3_DGCMDPAR_RX_FIFO (0 << 5) | |
| 327 | +#define DWC3_DGCMDPAR_TX_FIFO (1 << 5) | |
| 328 | +#define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0) | |
| 329 | +#define DWC3_DGCMDPAR_LOOPBACK_ENA (1 << 0) | |
| 290 | 330 | |
| 291 | 331 | /* Device Endpoint Command Register */ |
| 292 | 332 | #define DWC3_DEPCMD_PARAM_SHIFT 16 |
| @@ -303,7 +343,10 @@ · 10 unmodified lines | ||
| 303 | 343 | #define DWC3_DEPCMD_STARTTRANSFER (0x06 << 0) |
| 304 | 344 | #define DWC3_DEPCMD_CLEARSTALL (0x05 << 0) |
| 305 | 345 | #define DWC3_DEPCMD_SETSTALL (0x04 << 0) |
| 346 | +/* This applies for core versions 1.90a and earlier */ | |
| 306 | 347 | #define DWC3_DEPCMD_GETSEQNUMBER (0x03 << 0) |
| 348 | +/* This applies for core versions 1.94a and later */ | |
| 349 | +#define DWC3_DEPCMD_GETEPSTATE (0x03 << 0) | |
| 307 | 350 | #define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) |
| 308 | 351 | #define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) |
| 309 | 352 | |
| @@ -361,7 +404,8 @@ struct dwc3_event_buffer { · 51 unmodified lines | ||
| 361 | 404 | * @current_trb: index of current used trb |
| 362 | 405 | * @number: endpoint number (1 - 15) |
| 363 | 406 | * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK |
| 364 | − * @res_trans_idx: Resource transfer index | |
| 407 | + * @resource_index: Resource transfer index | |
| 408 | + * @current_uf: Current uf received through last event parameter | |
| 365 | 409 | * @interval: the intervall on which the ISOC transfer is started |
| 366 | 410 | * @name: a human readable name e.g. ep1out-bulk |
| 367 | 411 | * @direction: true for TX, false for RX |
| @@ -385,6 +429,7 @@ struct dwc3_ep { · 17 unmodified lines | ||
| 385 | 429 | #define DWC3_EP_WEDGE (1 << 2) |
| 386 | 430 | #define DWC3_EP_BUSY (1 << 4) |
| 387 | 431 | #define DWC3_EP_PENDING_REQUEST (1 << 5) |
| 432 | +#define DWC3_EP_MISSED_ISOC (1 << 6) | |
| 388 | 433 | |
| 389 | 434 | /* This last one is specific to EP0 */ |
| 390 | 435 | #define DWC3_EP0_DIR_IN (1 << 31) |
| @@ -393,7 +438,8 @@ struct dwc3_ep { · 2 unmodified lines | ||
| 393 | 438 | |
| 394 | 439 | u8 number; |
| 395 | 440 | u8 type; |
| 396 | − u8 res_trans_idx; | |
| 441 | + u8 resource_index; | |
| 442 | + u16 current_uf; | |
| 397 | 443 | u32 interval; |
| 398 | 444 | |
| 399 | 445 | char name[20]; |
| @@ -437,6 +483,8 @@ enum dwc3_link_state { · 37 unmodified lines | ||
| 437 | 483 | DWC3_LINK_STATE_HRESET = 0x09, |
| 438 | 484 | DWC3_LINK_STATE_CMPLY = 0x0a, |
| 439 | 485 | DWC3_LINK_STATE_LPBK = 0x0b, |
| 486 | + DWC3_LINK_STATE_RESET = 0x0e, | |
| 487 | + DWC3_LINK_STATE_RESUME = 0x0f, | |
| 440 | 488 | DWC3_LINK_STATE_MASK = 0x0f, |
| 441 | 489 | }; |
| 442 | 490 | |
| @@ -450,11 +498,12 @@ enum dwc3_device_state { · 7 unmodified lines | ||
| 450 | 498 | #define DWC3_TRB_SIZE_MASK (0x00ffffff) |
| 451 | 499 | #define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) |
| 452 | 500 | #define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24) |
| 453 | −#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28) >> 28)) | |
| 501 | +#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28)) >> 28) | |
| 454 | 502 | |
| 455 | 503 | #define DWC3_TRBSTS_OK 0 |
| 456 | 504 | #define DWC3_TRBSTS_MISSED_ISOC 1 |
| 457 | 505 | #define DWC3_TRBSTS_SETUP_PENDING 2 |
| 506 | +#define DWC3_TRB_STS_XFER_IN_PROG 4 | |
| 458 | 507 | |
| 459 | 508 | /* TRB Control */ |
| 460 | 509 | #define DWC3_TRB_CTRL_HWO (1 << 0) |
| @@ -543,6 +592,14 @@ struct dwc3_request { · 82 unmodified lines | ||
| 543 | 592 | unsigned queued:1; |
| 544 | 593 | }; |
| 545 | 594 | |
| 595 | +/* | |
| 596 | + * struct dwc3_scratchpad_array - hibernation scratchpad array | |
| 597 | + * (format defined by hw) | |
| 598 | + */ | |
| 599 | +struct dwc3_scratchpad_array { | |
| 600 | + __le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS]; | |
| 601 | +}; | |
| 602 | + | |
| 546 | 603 | /** |
| 547 | 604 | * struct dwc3 - representation of our controller |
| 548 | 605 | * @ctrl_req: usb control request which is used for ep0 |
| @@ -624,8 +681,10 @@ struct dwc3 { · 75 unmodified lines | ||
| 624 | 681 | #define DWC3_REVISION_180A 0x5533180a |
| 625 | 682 | #define DWC3_REVISION_183A 0x5533183a |
| 626 | 683 | #define DWC3_REVISION_185A 0x5533185a |
| 684 | +#define DWC3_REVISION_187A 0x5533187a | |
| 627 | 685 | #define DWC3_REVISION_188A 0x5533188a |
| 628 | 686 | #define DWC3_REVISION_190A 0x5533190a |
| 687 | +#define DWC3_REVISION_194A 0x5533194a | |
| 629 | 688 | #define DWC3_REVISION_200A 0x5533200a |
| 630 | 689 | #define DWC3_REVISION_202A 0x5533202a |
| 631 | 690 | #define DWC3_REVISION_210A 0x5533210a |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/platform_device.h> |
| 19 | 19 | #include <linux/platform_data/dwc3-exynos.h> |
| 20 | 20 | #include <linux/dma-mapping.h> |
| 21 | −#include <linux/module.h> | |
| 22 | 21 | #include <linux/clk.h> |
| 23 | 22 | |
| 24 | 23 | #include "core.h" |
| @@ -54,7 +54,9 @@ · 53 unmodified lines | ||
| 54 | 54 | #include "gadget.h" |
| 55 | 55 | #include "io.h" |
| 56 | 56 | |
| 57 | −static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum); | |
| 57 | +static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); | |
| 58 | +static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |
| 59 | + struct dwc3_ep *dep, struct dwc3_request *req); | |
| 58 | 60 | |
| 59 | 61 | static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) |
| 60 | 62 | { |
| @@ -111,7 +113,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, · 50 unmodified lines | ||
| 111 | 113 | } |
| 112 | 114 | |
| 113 | 115 | dep->flags |= DWC3_EP_BUSY; |
| 114 | − dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 116 | + dep->resource_index = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 115 | 117 | dep->number); |
| 116 | 118 | |
| 117 | 119 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; |
| @@ -150,16 +152,15 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, · 32 unmodified lines | ||
| 150 | 152 | return 0; |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | − ret = dwc3_ep0_start_trans(dwc, direction, | |
| 154 | − req->request.dma, req->request.length, | |
| 155 | − DWC3_TRBCTL_CONTROL_DATA); | |
| 155 | + __dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req); | |
| 156 | + | |
| 156 | 157 | dep->flags &= ~(DWC3_EP_PENDING_REQUEST | |
| 157 | 158 | DWC3_EP0_DIR_IN); |
| 158 | 159 | } else if (dwc->delayed_status) { |
| 159 | 160 | dwc->delayed_status = false; |
| 160 | 161 | |
| 161 | 162 | if (dwc->ep0state == EP0_STATUS_PHASE) |
| 162 | − dwc3_ep0_do_control_status(dwc, 1); | |
| 163 | + __dwc3_ep0_do_control_status(dwc, dwc->eps[1]); | |
| 163 | 164 | else |
| 164 | 165 | dev_dbg(dwc->dev, "too early for delayed status\n"); |
| 165 | 166 | } |
| @@ -224,6 +225,16 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) · 58 unmodified lines | ||
| 224 | 225 | dwc3_ep0_out_start(dwc); |
| 225 | 226 | } |
| 226 | 227 | |
| 228 | +int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | |
| 229 | +{ | |
| 230 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 231 | + struct dwc3 *dwc = dep->dwc; | |
| 232 | + | |
| 233 | + dwc3_ep0_stall_and_restart(dwc); | |
| 234 | + | |
| 235 | + return 0; | |
| 236 | +} | |
| 237 | + | |
| 227 | 238 | void dwc3_ep0_out_start(struct dwc3 *dwc) |
| 228 | 239 | { |
| 229 | 240 | int ret; |
| @@ -463,6 +474,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 233 unmodified lines | ||
| 463 | 474 | { |
| 464 | 475 | u32 cfg; |
| 465 | 476 | int ret; |
| 477 | + u32 reg; | |
| 466 | 478 | |
| 467 | 479 | dwc->start_config_issued = false; |
| 468 | 480 | cfg = le16_to_cpu(ctrl->wValue); |
| @@ -477,6 +489,14 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 8 unmodified lines | ||
| 477 | 489 | /* if the cfg matches and the cfg is non zero */ |
| 478 | 490 | if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { |
| 479 | 491 | dwc->dev_state = DWC3_CONFIGURED_STATE; |
| 492 | + /* | |
| 493 | + * Enable transition to U1/U2 state when | |
| 494 | + * nothing is pending from application. | |
| 495 | + */ | |
| 496 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 497 | + reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); | |
| 498 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 499 | + | |
| 480 | 500 | dwc->resize_fifos = true; |
| 481 | 501 | dev_dbg(dwc->dev, "resize fifos flag SET\n"); |
| 482 | 502 | } |
| @@ -514,8 +534,8 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) · 31 unmodified lines | ||
| 514 | 534 | |
| 515 | 535 | dwc->u1sel = timing.u1sel; |
| 516 | 536 | dwc->u1pel = timing.u1pel; |
| 517 | − dwc->u2sel = timing.u2sel; | |
| 518 | − dwc->u2pel = timing.u2pel; | |
| 537 | + dwc->u2sel = le16_to_cpu(timing.u2sel); | |
| 538 | + dwc->u2pel = le16_to_cpu(timing.u2pel); | |
| 519 | 539 | |
| 520 | 540 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 521 | 541 | if (reg & DWC3_DCTL_INITU2ENA) |
| @@ -640,11 +660,11 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, · 118 unmodified lines | ||
| 640 | 660 | const struct dwc3_event_depevt *event) |
| 641 | 661 | { |
| 642 | 662 | struct usb_ctrlrequest *ctrl = dwc->ctrl_req; |
| 643 | − int ret; | |
| 663 | + int ret = -EINVAL; | |
| 644 | 664 | u32 len; |
| 645 | 665 | |
| 646 | 666 | if (!dwc->gadget_driver) |
| 647 | − goto err; | |
| 667 | + goto out; | |
| 648 | 668 | |
| 649 | 669 | len = le16_to_cpu(ctrl->wLength); |
| 650 | 670 | if (!len) { |
| @@ -665,11 +685,9 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, · 14 unmodified lines | ||
| 665 | 685 | if (ret == USB_GADGET_DELAYED_STATUS) |
| 666 | 686 | dwc->delayed_status = true; |
| 667 | 687 | |
| 668 | − if (ret >= 0) | |
| 669 | − return; | |
| 670 | − | |
| 671 | −err: | |
| 672 | − dwc3_ep0_stall_and_restart(dwc); | |
| 688 | +out: | |
| 689 | + if (ret < 0) | |
| 690 | + dwc3_ep0_stall_and_restart(dwc); | |
| 673 | 691 | } |
| 674 | 692 | |
| 675 | 693 | static void dwc3_ep0_complete_data(struct dwc3 *dwc, |
| @@ -723,7 +741,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, · 47 unmodified lines | ||
| 723 | 741 | } |
| 724 | 742 | } |
| 725 | 743 | |
| 726 | −static void dwc3_ep0_complete_req(struct dwc3 *dwc, | |
| 744 | +static void dwc3_ep0_complete_status(struct dwc3 *dwc, | |
| 727 | 745 | const struct dwc3_event_depevt *event) |
| 728 | 746 | { |
| 729 | 747 | struct dwc3_request *r; |
| @@ -745,6 +763,7 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc, · 15 unmodified lines | ||
| 745 | 763 | dev_dbg(dwc->dev, "Invalid Test #%d\n", |
| 746 | 764 | dwc->test_mode_nr); |
| 747 | 765 | dwc3_ep0_stall_and_restart(dwc); |
| 766 | + return; | |
| 748 | 767 | } |
| 749 | 768 | } |
| 750 | 769 | |
| @@ -758,7 +777,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, · 7 unmodified lines | ||
| 758 | 777 | struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; |
| 759 | 778 | |
| 760 | 779 | dep->flags &= ~DWC3_EP_BUSY; |
| 761 | − dep->res_trans_idx = 0; | |
| 780 | + dep->resource_index = 0; | |
| 762 | 781 | dwc->setup_packet_pending = false; |
| 763 | 782 | |
| 764 | 783 | switch (dwc->ep0state) { |
| @@ -774,7 +793,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, · 9 unmodified lines | ||
| 774 | 793 | |
| 775 | 794 | case EP0_STATUS_PHASE: |
| 776 | 795 | dev_vdbg(dwc->dev, "Status Phase\n"); |
| 777 | − dwc3_ep0_complete_req(dwc, event); | |
| 796 | + dwc3_ep0_complete_status(dwc, event); | |
| 778 | 797 | break; |
| 779 | 798 | default: |
| 780 | 799 | WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state); |
| @@ -787,68 +806,81 @@ static void dwc3_ep0_do_control_setup(struct dwc3 *dwc, · 6 unmodified lines | ||
| 787 | 806 | dwc3_ep0_out_start(dwc); |
| 788 | 807 | } |
| 789 | 808 | |
| 790 | −static void dwc3_ep0_do_control_data(struct dwc3 *dwc, | |
| 791 | − const struct dwc3_event_depevt *event) | |
| 809 | +static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |
| 810 | + struct dwc3_ep *dep, struct dwc3_request *req) | |
| 792 | 811 | { |
| 793 | − struct dwc3_ep *dep; | |
| 794 | − struct dwc3_request *req; | |
| 795 | 812 | int ret; |
| 796 | 813 | |
| 797 | − dep = dwc->eps[0]; | |
| 798 | − | |
| 799 | − if (list_empty(&dep->request_list)) { | |
| 800 | − dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); | |
| 801 | − dep->flags |= DWC3_EP_PENDING_REQUEST; | |
| 802 | − | |
| 803 | − if (event->endpoint_number) | |
| 804 | − dep->flags |= DWC3_EP0_DIR_IN; | |
| 805 | − return; | |
| 806 | − } | |
| 807 | − | |
| 808 | − req = next_request(&dep->request_list); | |
| 809 | − req->direction = !!event->endpoint_number; | |
| 814 | + req->direction = !!dep->number; | |
| 810 | 815 | |
| 811 | 816 | if (req->request.length == 0) { |
| 812 | − ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 817 | + ret = dwc3_ep0_start_trans(dwc, dep->number, | |
| 813 | 818 | dwc->ctrl_req_addr, 0, |
| 814 | 819 | DWC3_TRBCTL_CONTROL_DATA); |
| 815 | − } else if ((req->request.length % dep->endpoint.maxpacket) | |
| 816 | − && (event->endpoint_number == 0)) { | |
| 820 | + } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) | |
| 821 | + && (dep->number == 0)) { | |
| 822 | + u32 transfer_size; | |
| 823 | + | |
| 817 | 824 | ret = usb_gadget_map_request(&dwc->gadget, &req->request, |
| 818 | − event->endpoint_number); | |
| 825 | + dep->number); | |
| 819 | 826 | if (ret) { |
| 820 | 827 | dev_dbg(dwc->dev, "failed to map request\n"); |
| 821 | 828 | return; |
| 822 | 829 | } |
| 823 | 830 | |
| 824 | − WARN_ON(req->request.length > dep->endpoint.maxpacket); | |
| 831 | + WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); | |
| 832 | + | |
| 833 | + transfer_size = roundup(req->request.length, | |
| 834 | + (u32) dep->endpoint.maxpacket); | |
| 825 | 835 | |
| 826 | 836 | dwc->ep0_bounced = true; |
| 827 | 837 | |
| 828 | 838 | /* |
| 829 | − * REVISIT in case request length is bigger than EP0 | |
| 830 | − * wMaxPacketSize, we will need two chained TRBs to handle | |
| 831 | − * the transfer. | |
| 839 | + * REVISIT in case request length is bigger than | |
| 840 | + * DWC3_EP0_BOUNCE_SIZE we will need two chained | |
| 841 | + * TRBs to handle the transfer. | |
| 832 | 842 | */ |
| 833 | − ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 834 | − dwc->ep0_bounce_addr, dep->endpoint.maxpacket, | |
| 843 | + ret = dwc3_ep0_start_trans(dwc, dep->number, | |
| 844 | + dwc->ep0_bounce_addr, transfer_size, | |
| 835 | 845 | DWC3_TRBCTL_CONTROL_DATA); |
| 836 | 846 | } else { |
| 837 | 847 | ret = usb_gadget_map_request(&dwc->gadget, &req->request, |
| 838 | − event->endpoint_number); | |
| 848 | + dep->number); | |
| 839 | 849 | if (ret) { |
| 840 | 850 | dev_dbg(dwc->dev, "failed to map request\n"); |
| 841 | 851 | return; |
| 842 | 852 | } |
| 843 | 853 | |
| 844 | − ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, | |
| 845 | − req->request.dma, req->request.length, | |
| 846 | − DWC3_TRBCTL_CONTROL_DATA); | |
| 854 | + ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, | |
| 855 | + req->request.length, DWC3_TRBCTL_CONTROL_DATA); | |
| 847 | 856 | } |
| 848 | 857 | |
| 849 | 858 | WARN_ON(ret < 0); |
| 850 | 859 | } |
| 851 | 860 | |
| 861 | +static void dwc3_ep0_do_control_data(struct dwc3 *dwc, | |
| 862 | + const struct dwc3_event_depevt *event) | |
| 863 | +{ | |
| 864 | + struct dwc3_ep *dep; | |
| 865 | + struct dwc3_request *req; | |
| 866 | + | |
| 867 | + dep = dwc->eps[0]; | |
| 868 | + | |
| 869 | + if (list_empty(&dep->request_list)) { | |
| 870 | + dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); | |
| 871 | + dep->flags |= DWC3_EP_PENDING_REQUEST; | |
| 872 | + | |
| 873 | + if (event->endpoint_number) | |
| 874 | + dep->flags |= DWC3_EP0_DIR_IN; | |
| 875 | + return; | |
| 876 | + } | |
| 877 | + | |
| 878 | + req = next_request(&dep->request_list); | |
| 879 | + dep = dwc->eps[event->endpoint_number]; | |
| 880 | + | |
| 881 | + __dwc3_ep0_do_control_data(dwc, dep, req); | |
| 882 | +} | |
| 883 | + | |
| 852 | 884 | static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) |
| 853 | 885 | { |
| 854 | 886 | struct dwc3 *dwc = dep->dwc; |
| @@ -861,10 +893,8 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) · 6 unmodified lines | ||
| 861 | 893 | dwc->ctrl_req_addr, 0, type); |
| 862 | 894 | } |
| 863 | 895 | |
| 864 | −static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) | |
| 896 | +static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) | |
| 865 | 897 | { |
| 866 | − struct dwc3_ep *dep = dwc->eps[epnum]; | |
| 867 | − | |
| 868 | 898 | if (dwc->resize_fifos) { |
| 869 | 899 | dev_dbg(dwc->dev, "starting to resize fifos\n"); |
| 870 | 900 | dwc3_gadget_resize_tx_fifos(dwc); |
| @@ -874,13 +904,21 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) · 3 unmodified lines | ||
| 874 | 904 | WARN_ON(dwc3_ep0_start_control_status(dep)); |
| 875 | 905 | } |
| 876 | 906 | |
| 907 | +static void dwc3_ep0_do_control_status(struct dwc3 *dwc, | |
| 908 | + const struct dwc3_event_depevt *event) | |
| 909 | +{ | |
| 910 | + struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; | |
| 911 | + | |
| 912 | + __dwc3_ep0_do_control_status(dwc, dep); | |
| 913 | +} | |
| 914 | + | |
| 877 | 915 | static void dwc3_ep0_xfernotready(struct dwc3 *dwc, |
| 878 | 916 | const struct dwc3_event_depevt *event) |
| 879 | 917 | { |
| 880 | 918 | dwc->setup_packet_pending = true; |
| 881 | 919 | |
| 882 | 920 | /* |
| 883 | − * This part is very tricky: If we has just handled | |
| 921 | + * This part is very tricky: If we have just handled | |
| 884 | 922 | * XferNotReady(Setup) and we're now expecting a |
| 885 | 923 | * XferComplete but, instead, we receive another |
| 886 | 924 | * XferNotReady(Setup), we should STALL and restart |
| @@ -974,7 +1012,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, · 87 unmodified lines | ||
| 974 | 1012 | return; |
| 975 | 1013 | } |
| 976 | 1014 | |
| 977 | − dwc3_ep0_do_control_status(dwc, event->endpoint_number); | |
| 1015 | + dwc3_ep0_do_control_status(dwc, event); | |
| 978 | 1016 | } |
| 979 | 1017 | } |
| 980 | 1018 | |
| @@ -100,6 +100,23 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) · 99 unmodified lines | ||
| 100 | 100 | int retries = 10000; |
| 101 | 101 | u32 reg; |
| 102 | 102 | |
| 103 | + /* | |
| 104 | + * Wait until device controller is ready. Only applies to 1.94a and | |
| 105 | + * later RTL. | |
| 106 | + */ | |
| 107 | + if (dwc->revision >= DWC3_REVISION_194A) { | |
| 108 | + while (--retries) { | |
| 109 | + reg = dwc3_readl(dwc->regs, DWC3_DSTS); | |
| 110 | + if (reg & DWC3_DSTS_DCNRD) | |
| 111 | + udelay(5); | |
| 112 | + else | |
| 113 | + break; | |
| 114 | + } | |
| 115 | + | |
| 116 | + if (retries <= 0) | |
| 117 | + return -ETIMEDOUT; | |
| 118 | + } | |
| 119 | + | |
| 103 | 120 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 104 | 121 | reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; |
| 105 | 122 | |
| @@ -107,7 +124,15 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) · 1 unmodified line | ||
| 107 | 124 | reg |= DWC3_DCTL_ULSTCHNGREQ(state); |
| 108 | 125 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
| 109 | 126 | |
| 127 | + /* | |
| 128 | + * The following code is racy when called from dwc3_gadget_wakeup, | |
| 129 | + * and is not needed, at least on newer versions | |
| 130 | + */ | |
| 131 | + if (dwc->revision >= DWC3_REVISION_194A) | |
| 132 | + return 0; | |
| 133 | + | |
| 110 | 134 | /* wait for a change in DSTS */ |
| 135 | + retries = 10000; | |
| 111 | 136 | while (--retries) { |
| 112 | 137 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); |
| 113 | 138 | |
| @@ -265,8 +290,8 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd) · 151 unmodified lines | ||
| 265 | 290 | return "Clear Stall"; |
| 266 | 291 | case DWC3_DEPCMD_SETSTALL: |
| 267 | 292 | return "Set Stall"; |
| 268 | − case DWC3_DEPCMD_GETSEQNUMBER: | |
| 269 | − return "Get Data Sequence Number"; | |
| 293 | + case DWC3_DEPCMD_GETEPSTATE: | |
| 294 | + return "Get Endpoint State"; | |
| 270 | 295 | case DWC3_DEPCMD_SETTRANSFRESOURCE: |
| 271 | 296 | return "Set Endpoint Transfer Resource"; |
| 272 | 297 | case DWC3_DEPCMD_SETEPCONFIG: |
| @@ -414,7 +439,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, · 141 unmodified lines | ||
| 414 | 439 | |
| 415 | 440 | params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) |
| 416 | 441 | | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) |
| 417 | − | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst); | |
| 442 | + | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); | |
| 418 | 443 | |
| 419 | 444 | params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN |
| 420 | 445 | | DWC3_DEPCFG_XFER_NOT_READY_EN; |
| @@ -530,9 +555,37 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) · 109 unmodified lines | ||
| 530 | 555 | { |
| 531 | 556 | struct dwc3_request *req; |
| 532 | 557 | |
| 533 | − if (!list_empty(&dep->req_queued)) | |
| 558 | + if (!list_empty(&dep->req_queued)) { | |
| 534 | 559 | dwc3_stop_active_transfer(dwc, dep->number); |
| 535 | 560 | |
| 561 | + /* | |
| 562 | + * NOTICE: We are violating what the Databook says about the | |
| 563 | + * EndTransfer command. Ideally we would _always_ wait for the | |
| 564 | + * EndTransfer Command Completion IRQ, but that's causing too | |
| 565 | + * much trouble synchronizing between us and gadget driver. | |
| 566 | + * | |
| 567 | + * We have discussed this with the IP Provider and it was | |
| 568 | + * suggested to giveback all requests here, but give HW some | |
| 569 | + * extra time to synchronize with the interconnect. We're using | |
| 570 | + * an arbitraty 100us delay for that. | |
| 571 | + * | |
| 572 | + * Note also that a similar handling was tested by Synopsys | |
| 573 | + * (thanks a lot Paul) and nothing bad has come out of it. | |
| 574 | + * In short, what we're doing is: | |
| 575 | + * | |
| 576 | + * - Issue EndTransfer WITH CMDIOC bit set | |
| 577 | + * - Wait 100us | |
| 578 | + * - giveback all requests to gadget driver | |
| 579 | + */ | |
| 580 | + udelay(100); | |
| 581 | + | |
| 582 | + while (!list_empty(&dep->req_queued)) { | |
| 583 | + req = next_request(&dep->req_queued); | |
| 584 | + | |
| 585 | + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); | |
| 586 | + } | |
| 587 | + } | |
| 588 | + | |
| 536 | 589 | while (!list_empty(&dep->request_list)) { |
| 537 | 590 | req = next_request(&dep->request_list); |
| 538 | 591 | |
| @@ -741,8 +794,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, · 202 unmodified lines | ||
| 741 | 794 | case USB_ENDPOINT_XFER_ISOC: |
| 742 | 795 | trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; |
| 743 | 796 | |
| 744 | − /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | |
| 745 | − if (!(cur_slot % (DWC3_TRB_NUM / 4))) | |
| 797 | + if (!req->request.no_interrupt) | |
| 746 | 798 | trb->ctrl |= DWC3_TRB_CTRL_IOC; |
| 747 | 799 | break; |
| 748 | 800 | |
| @@ -958,14 +1010,42 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, · 209 unmodified lines | ||
| 958 | 1010 | dep->flags |= DWC3_EP_BUSY; |
| 959 | 1011 | |
| 960 | 1012 | if (start_new) { |
| 961 | − dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 1013 | + dep->resource_index = dwc3_gadget_ep_get_transfer_index(dwc, | |
| 962 | 1014 | dep->number); |
| 963 | − WARN_ON_ONCE(!dep->res_trans_idx); | |
| 1015 | + WARN_ON_ONCE(!dep->resource_index); | |
| 964 | 1016 | } |
| 965 | 1017 | |
| 966 | 1018 | return 0; |
| 967 | 1019 | } |
| 968 | 1020 | |
| 1021 | +static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, | |
| 1022 | + struct dwc3_ep *dep, u32 cur_uf) | |
| 1023 | +{ | |
| 1024 | + u32 uf; | |
| 1025 | + | |
| 1026 | + if (list_empty(&dep->request_list)) { | |
| 1027 | + dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", | |
| 1028 | + dep->name); | |
| 1029 | + return; | |
| 1030 | + } | |
| 1031 | + | |
| 1032 | + /* 4 micro frames in the future */ | |
| 1033 | + uf = cur_uf + dep->interval * 4; | |
| 1034 | + | |
| 1035 | + __dwc3_gadget_kick_transfer(dep, uf, 1); | |
| 1036 | +} | |
| 1037 | + | |
| 1038 | +static void dwc3_gadget_start_isoc(struct dwc3 *dwc, | |
| 1039 | + struct dwc3_ep *dep, const struct dwc3_event_depevt *event) | |
| 1040 | +{ | |
| 1041 | + u32 cur_uf, mask; | |
| 1042 | + | |
| 1043 | + mask = ~(dep->interval - 1); | |
| 1044 | + cur_uf = event->parameters & mask; | |
| 1045 | + | |
| 1046 | + __dwc3_gadget_start_isoc(dwc, dep, cur_uf); | |
| 1047 | +} | |
| 1048 | + | |
| 969 | 1049 | static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) |
| 970 | 1050 | { |
| 971 | 1051 | struct dwc3 *dwc = dep->dwc; |
| @@ -995,11 +1075,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) · 23 unmodified lines | ||
| 995 | 1075 | |
| 996 | 1076 | list_add_tail(&req->list, &dep->request_list); |
| 997 | 1077 | |
| 998 | − if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY)) | |
| 999 | − dep->flags |= DWC3_EP_PENDING_REQUEST; | |
| 1000 | − | |
| 1001 | 1078 | /* |
| 1002 | − * There are two special cases: | |
| 1079 | + * There are a few special cases: | |
| 1003 | 1080 | * |
| 1004 | 1081 | * 1. XferNotReady with empty list of requests. We need to kick the |
| 1005 | 1082 | * transfer here in that situation, otherwise we will be NAKing |
| @@ -1008,31 +1085,46 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) · 2 unmodified lines | ||
| 1008 | 1085 | * able to receive the data until the next request is queued. |
| 1009 | 1086 | * The following code is handling exactly that. |
| 1010 | 1087 | * |
| 1011 | − * 2. XferInProgress on Isoc EP with an active transfer. We need to | |
| 1012 | − * kick the transfer here after queuing a request, otherwise the | |
| 1013 | − * core may not see the modified TRB(s). | |
| 1014 | 1088 | */ |
| 1015 | 1089 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { |
| 1016 | 1090 | int ret; |
| 1017 | − int start_trans = 1; | |
| 1018 | − u8 trans_idx = dep->res_trans_idx; | |
| 1019 | 1091 | |
| 1020 | − if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | |
| 1021 | − (dep->flags & DWC3_EP_BUSY)) { | |
| 1022 | − start_trans = 0; | |
| 1023 | − WARN_ON_ONCE(!trans_idx); | |
| 1024 | − } else { | |
| 1025 | − trans_idx = 0; | |
| 1092 | + ret = __dwc3_gadget_kick_transfer(dep, 0, true); | |
| 1093 | + if (ret && ret != -EBUSY) { | |
| 1094 | + struct dwc3 *dwc = dep->dwc; | |
| 1095 | + | |
| 1096 | + dev_dbg(dwc->dev, "%s: failed to kick transfers\n", | |
| 1097 | + dep->name); | |
| 1026 | 1098 | } |
| 1099 | + } | |
| 1027 | 1100 | |
| 1028 | − ret = __dwc3_gadget_kick_transfer(dep, trans_idx, start_trans); | |
| 1101 | + /* | |
| 1102 | + * 2. XferInProgress on Isoc EP with an active transfer. We need to | |
| 1103 | + * kick the transfer here after queuing a request, otherwise the | |
| 1104 | + * core may not see the modified TRB(s). | |
| 1105 | + */ | |
| 1106 | + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | |
| 1107 | + (dep->flags & DWC3_EP_BUSY)) { | |
| 1108 | + WARN_ON_ONCE(!dep->resource_index); | |
| 1109 | + ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, | |
| 1110 | + false); | |
| 1029 | 1111 | if (ret && ret != -EBUSY) { |
| 1030 | 1112 | struct dwc3 *dwc = dep->dwc; |
| 1031 | 1113 | |
| 1032 | 1114 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", |
| 1033 | 1115 | dep->name); |
| 1034 | 1116 | } |
| 1035 | − }; | |
| 1117 | + } | |
| 1118 | + | |
| 1119 | + /* | |
| 1120 | + * 3. Missed ISOC Handling. We need to start isoc transfer on the saved | |
| 1121 | + * uframe number. | |
| 1122 | + */ | |
| 1123 | + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | |
| 1124 | + (dep->flags & DWC3_EP_MISSED_ISOC)) { | |
| 1125 | + __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf); | |
| 1126 | + dep->flags &= ~DWC3_EP_MISSED_ISOC; | |
| 1127 | + } | |
| 1036 | 1128 | |
| 1037 | 1129 | return 0; |
| 1038 | 1130 | } |
| @@ -1118,15 +1210,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) · 79 unmodified lines | ||
| 1118 | 1210 | memset(¶ms, 0x00, sizeof(params)); |
| 1119 | 1211 | |
| 1120 | 1212 | if (value) { |
| 1121 | − if (dep->number == 0 || dep->number == 1) { | |
| 1122 | − /* | |
| 1123 | − * Whenever EP0 is stalled, we will restart | |
| 1124 | − * the state machine, thus moving back to | |
| 1125 | − * Setup Phase | |
| 1126 | − */ | |
| 1127 | − dwc->ep0state = EP0_SETUP_PHASE; | |
| 1128 | − } | |
| 1129 | − | |
| 1130 | 1213 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, |
| 1131 | 1214 | DWC3_DEPCMD_SETSTALL, ¶ms); |
| 1132 | 1215 | if (ret) |
| @@ -1186,7 +1269,10 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) · 53 unmodified lines | ||
| 1186 | 1269 | dep->flags |= DWC3_EP_WEDGE; |
| 1187 | 1270 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 1188 | 1271 | |
| 1189 | − return dwc3_gadget_ep_set_halt(ep, 1); | |
| 1272 | + if (dep->number == 0 || dep->number == 1) | |
| 1273 | + return dwc3_gadget_ep0_set_halt(ep, 1); | |
| 1274 | + else | |
| 1275 | + return dwc3_gadget_ep_set_halt(ep, 1); | |
| 1190 | 1276 | } |
| 1191 | 1277 | |
| 1192 | 1278 | /* -------------------------------------------------------------------------- */ |
| @@ -1204,7 +1290,7 @@ static const struct usb_ep_ops dwc3_gadget_ep0_ops = { · 11 unmodified lines | ||
| 1204 | 1290 | .free_request = dwc3_gadget_ep_free_request, |
| 1205 | 1291 | .queue = dwc3_gadget_ep0_queue, |
| 1206 | 1292 | .dequeue = dwc3_gadget_ep_dequeue, |
| 1207 | − .set_halt = dwc3_gadget_ep_set_halt, | |
| 1293 | + .set_halt = dwc3_gadget_ep0_set_halt, | |
| 1208 | 1294 | .set_wedge = dwc3_gadget_ep_set_wedge, |
| 1209 | 1295 | }; |
| 1210 | 1296 | |
| @@ -1280,9 +1366,13 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) · 69 unmodified lines | ||
| 1280 | 1366 | goto out; |
| 1281 | 1367 | } |
| 1282 | 1368 | |
| 1283 | − /* write zeroes to Link Change Request */ | |
| 1284 | − reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; | |
| 1285 | − dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1369 | + /* Recent versions do this automatically */ | |
| 1370 | + if (dwc->revision < DWC3_REVISION_194A) { | |
| 1371 | + /* write zeroes to Link Change Request */ | |
| 1372 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 1373 | + reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; | |
| 1374 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 1375 | + } | |
| 1286 | 1376 | |
| 1287 | 1377 | /* poll until Link State changes to ON */ |
| 1288 | 1378 | timeout = jiffies + msecs_to_jiffies(100); |
| @@ -1319,16 +1409,21 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, · 30 unmodified lines | ||
| 1319 | 1409 | return 0; |
| 1320 | 1410 | } |
| 1321 | 1411 | |
| 1322 | −static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) | |
| 1412 | +static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) | |
| 1323 | 1413 | { |
| 1324 | 1414 | u32 reg; |
| 1325 | 1415 | u32 timeout = 500; |
| 1326 | 1416 | |
| 1327 | 1417 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 1328 | 1418 | if (is_on) { |
| 1329 | − reg &= ~DWC3_DCTL_TRGTULST_MASK; | |
| 1330 | − reg |= (DWC3_DCTL_RUN_STOP | |
| 1331 | − | DWC3_DCTL_TRGTULST_RX_DET); | |
| 1419 | + if (dwc->revision <= DWC3_REVISION_187A) { | |
| 1420 | + reg &= ~DWC3_DCTL_TRGTULST_MASK; | |
| 1421 | + reg |= DWC3_DCTL_TRGTULST_RX_DET; | |
| 1422 | + } | |
| 1423 | + | |
| 1424 | + if (dwc->revision >= DWC3_REVISION_194A) | |
| 1425 | + reg &= ~DWC3_DCTL_KEEP_CONNECT; | |
| 1426 | + reg |= DWC3_DCTL_RUN_STOP; | |
| 1332 | 1427 | } else { |
| 1333 | 1428 | reg &= ~DWC3_DCTL_RUN_STOP; |
| 1334 | 1429 | } |
| @@ -1346,7 +1441,7 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) · 11 unmodified lines | ||
| 1346 | 1441 | } |
| 1347 | 1442 | timeout--; |
| 1348 | 1443 | if (!timeout) |
| 1349 | − break; | |
| 1444 | + return -ETIMEDOUT; | |
| 1350 | 1445 | udelay(1); |
| 1351 | 1446 | } while (1); |
| 1352 | 1447 | |
| @@ -1354,20 +1449,23 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) · 1 unmodified line | ||
| 1354 | 1449 | dwc->gadget_driver |
| 1355 | 1450 | ? dwc->gadget_driver->function : "no-function", |
| 1356 | 1451 | is_on ? "connect" : "disconnect"); |
| 1452 | + | |
| 1453 | + return 0; | |
| 1357 | 1454 | } |
| 1358 | 1455 | |
| 1359 | 1456 | static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) |
| 1360 | 1457 | { |
| 1361 | 1458 | struct dwc3 *dwc = gadget_to_dwc(g); |
| 1362 | 1459 | unsigned long flags; |
| 1460 | + int ret; | |
| 1363 | 1461 | |
| 1364 | 1462 | is_on = !!is_on; |
| 1365 | 1463 | |
| 1366 | 1464 | spin_lock_irqsave(&dwc->lock, flags); |
| 1367 | − dwc3_gadget_run_stop(dwc, is_on); | |
| 1465 | + ret = dwc3_gadget_run_stop(dwc, is_on); | |
| 1368 | 1466 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 1369 | 1467 | |
| 1370 | − return 0; | |
| 1468 | + return ret; | |
| 1371 | 1469 | } |
| 1372 | 1470 | |
| 1373 | 1471 | static int dwc3_gadget_start(struct usb_gadget *g, |
| @@ -1468,6 +1566,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g, · 94 unmodified lines | ||
| 1468 | 1566 | |
| 1469 | 1567 | return 0; |
| 1470 | 1568 | } |
| 1569 | + | |
| 1471 | 1570 | static const struct usb_gadget_ops dwc3_gadget_ops = { |
| 1472 | 1571 | .get_frame = dwc3_gadget_get_frame, |
| 1473 | 1572 | .wakeup = dwc3_gadget_wakeup, |
| @@ -1558,6 +1657,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, · 84 unmodified lines | ||
| 1558 | 1657 | struct dwc3_trb *trb; |
| 1559 | 1658 | unsigned int count; |
| 1560 | 1659 | unsigned int s_pkt = 0; |
| 1660 | + unsigned int trb_status; | |
| 1561 | 1661 | |
| 1562 | 1662 | do { |
| 1563 | 1663 | req = next_request(&dep->req_queued); |
| @@ -1583,9 +1683,18 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, · 19 unmodified lines | ||
| 1583 | 1683 | |
| 1584 | 1684 | if (dep->direction) { |
| 1585 | 1685 | if (count) { |
| 1586 | − dev_err(dwc->dev, "incomplete IN transfer %s\n", | |
| 1587 | − dep->name); | |
| 1588 | − status = -ECONNRESET; | |
| 1686 | + trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size); | |
| 1687 | + if (trb_status == DWC3_TRBSTS_MISSED_ISOC) { | |
| 1688 | + dev_dbg(dwc->dev, "incomplete IN transfer %s\n", | |
| 1689 | + dep->name); | |
| 1690 | + dep->current_uf = event->parameters & | |
| 1691 | + ~(dep->interval - 1); | |
| 1692 | + dep->flags |= DWC3_EP_MISSED_ISOC; | |
| 1693 | + } else { | |
| 1694 | + dev_err(dwc->dev, "incomplete IN transfer %s\n", | |
| 1695 | + dep->name); | |
| 1696 | + status = -ECONNRESET; | |
| 1697 | + } | |
| 1589 | 1698 | } |
| 1590 | 1699 | } else { |
| 1591 | 1700 | if (count && (event->status & DEPEVT_STATUS_SHORT)) |
| @@ -1604,7 +1713,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, · 12 unmodified lines | ||
| 1604 | 1713 | if (s_pkt) |
| 1605 | 1714 | break; |
| 1606 | 1715 | if ((event->status & DEPEVT_STATUS_LST) && |
| 1607 | − (trb->ctrl & DWC3_TRB_CTRL_LST)) | |
| 1716 | + (trb->ctrl & (DWC3_TRB_CTRL_LST | | |
| 1717 | + DWC3_TRB_CTRL_HWO))) | |
| 1608 | 1718 | break; |
| 1609 | 1719 | if ((event->status & DEPEVT_STATUS_IOC) && |
| 1610 | 1720 | (trb->ctrl & DWC3_TRB_CTRL_IOC)) |
| @@ -1657,65 +1767,6 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, · 46 unmodified lines | ||
| 1657 | 1767 | } |
| 1658 | 1768 | } |
| 1659 | 1769 | |
| 1660 | −static void dwc3_gadget_start_isoc(struct dwc3 *dwc, | |
| 1661 | − struct dwc3_ep *dep, const struct dwc3_event_depevt *event) | |
| 1662 | −{ | |
| 1663 | − u32 uf, mask; | |
| 1664 | − | |
| 1665 | − if (list_empty(&dep->request_list)) { | |
| 1666 | − dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", | |
| 1667 | − dep->name); | |
| 1668 | − return; | |
| 1669 | − } | |
| 1670 | − | |
| 1671 | − mask = ~(dep->interval - 1); | |
| 1672 | − uf = event->parameters & mask; | |
| 1673 | − /* 4 micro frames in the future */ | |
| 1674 | − uf += dep->interval * 4; | |
| 1675 | − | |
| 1676 | − __dwc3_gadget_kick_transfer(dep, uf, 1); | |
| 1677 | −} | |
| 1678 | − | |
| 1679 | −static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, | |
| 1680 | − const struct dwc3_event_depevt *event) | |
| 1681 | −{ | |
| 1682 | − struct dwc3 *dwc = dep->dwc; | |
| 1683 | − struct dwc3_event_depevt mod_ev = *event; | |
| 1684 | − | |
| 1685 | − /* | |
| 1686 | − * We were asked to remove one request. It is possible that this | |
| 1687 | − * request and a few others were started together and have the same | |
| 1688 | − * transfer index. Since we stopped the complete endpoint we don't | |
| 1689 | − * know how many requests were already completed (and not yet) | |
| 1690 | − * reported and how could be done (later). We purge them all until | |
| 1691 | − * the end of the list. | |
| 1692 | − */ | |
| 1693 | − mod_ev.status = DEPEVT_STATUS_LST; | |
| 1694 | − dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); | |
| 1695 | − dep->flags &= ~DWC3_EP_BUSY; | |
| 1696 | − /* pending requests are ignored and are queued on XferNotReady */ | |
| 1697 | −} | |
| 1698 | − | |
| 1699 | −static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, | |
| 1700 | − const struct dwc3_event_depevt *event) | |
| 1701 | −{ | |
| 1702 | − u32 param = event->parameters; | |
| 1703 | − u32 cmd_type = (param >> 8) & ((1 << 5) - 1); | |
| 1704 | − | |
| 1705 | − switch (cmd_type) { | |
| 1706 | − case DWC3_DEPCMD_ENDTRANSFER: | |
| 1707 | − dwc3_process_ep_cmd_complete(dep, event); | |
| 1708 | − break; | |
| 1709 | − case DWC3_DEPCMD_STARTTRANSFER: | |
| 1710 | − dep->res_trans_idx = param & 0x7f; | |
| 1711 | − break; | |
| 1712 | − default: | |
| 1713 | − printk(KERN_ERR "%s() unknown /unexpected type: %d\n", | |
| 1714 | − __func__, cmd_type); | |
| 1715 | − break; | |
| 1716 | − }; | |
| 1717 | −} | |
| 1718 | − | |
| 1719 | 1770 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, |
| 1720 | 1771 | const struct dwc3_event_depevt *event) |
| 1721 | 1772 | { |
| @@ -1724,6 +1775,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, · 2 unmodified lines | ||
| 1724 | 1775 | |
| 1725 | 1776 | dep = dwc->eps[epnum]; |
| 1726 | 1777 | |
| 1778 | + if (!(dep->flags & DWC3_EP_ENABLED)) | |
| 1779 | + return; | |
| 1780 | + | |
| 1727 | 1781 | dev_vdbg(dwc->dev, "%s: %s\n", dep->name, |
| 1728 | 1782 | dwc3_ep_event_string(event->endpoint_event)); |
| 1729 | 1783 | |
| @@ -1734,7 +1788,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, · 4 unmodified lines | ||
| 1734 | 1788 | |
| 1735 | 1789 | switch (event->endpoint_event) { |
| 1736 | 1790 | case DWC3_DEPEVT_XFERCOMPLETE: |
| 1737 | − dep->res_trans_idx = 0; | |
| 1791 | + dep->resource_index = 0; | |
| 1738 | 1792 | |
| 1739 | 1793 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { |
| 1740 | 1794 | dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", |
| @@ -1797,7 +1851,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, · 56 unmodified lines | ||
| 1797 | 1851 | dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); |
| 1798 | 1852 | break; |
| 1799 | 1853 | case DWC3_DEPEVT_EPCMDCMPLT: |
| 1800 | − dwc3_ep_cmd_compl(dep, event); | |
| 1854 | + dev_vdbg(dwc->dev, "Endpoint Command Complete\n"); | |
| 1801 | 1855 | break; |
| 1802 | 1856 | } |
| 1803 | 1857 | } |
| @@ -1820,16 +1874,16 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) · 16 unmodified lines | ||
| 1820 | 1874 | |
| 1821 | 1875 | dep = dwc->eps[epnum]; |
| 1822 | 1876 | |
| 1823 | − WARN_ON(!dep->res_trans_idx); | |
| 1824 | − if (dep->res_trans_idx) { | |
| 1825 | − cmd = DWC3_DEPCMD_ENDTRANSFER; | |
| 1826 | − cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; | |
| 1827 | − cmd |= DWC3_DEPCMD_PARAM(dep->res_trans_idx); | |
| 1828 | − memset(¶ms, 0, sizeof(params)); | |
| 1829 | − ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | |
| 1830 | − WARN_ON_ONCE(ret); | |
| 1831 | − dep->res_trans_idx = 0; | |
| 1832 | − } | |
| 1877 | + if (!dep->resource_index) | |
| 1878 | + return; | |
| 1879 | + | |
| 1880 | + cmd = DWC3_DEPCMD_ENDTRANSFER; | |
| 1881 | + cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; | |
| 1882 | + cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); | |
| 1883 | + memset(¶ms, 0, sizeof(params)); | |
| 1884 | + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | |
| 1885 | + WARN_ON_ONCE(ret); | |
| 1886 | + dep->resource_index = 0; | |
| 1833 | 1887 | } |
| 1834 | 1888 | |
| 1835 | 1889 | static void dwc3_stop_active_transfers(struct dwc3 *dwc) |
| @@ -1872,11 +1926,9 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) · 36 unmodified lines | ||
| 1872 | 1926 | |
| 1873 | 1927 | static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) |
| 1874 | 1928 | { |
| 1929 | + int reg; | |
| 1930 | + | |
| 1875 | 1931 | dev_vdbg(dwc->dev, "%s\n", __func__); |
| 1876 | −#if 0 | |
| 1877 | − XXX | |
| 1878 | − U1/U2 is powersave optimization. Skip it for now. Anyway we need to | |
| 1879 | − enable it before we can disable it. | |
| 1880 | 1932 | |
| 1881 | 1933 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 1882 | 1934 | reg &= ~DWC3_DCTL_INITU1ENA; |
| @@ -1884,9 +1936,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) · 1 unmodified line | ||
| 1884 | 1936 | |
| 1885 | 1937 | reg &= ~DWC3_DCTL_INITU2ENA; |
| 1886 | 1938 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
| 1887 | −#endif | |
| 1888 | 1939 | |
| 1889 | − dwc3_stop_active_transfers(dwc); | |
| 1890 | 1940 | dwc3_disconnect_gadget(dwc); |
| 1891 | 1941 | dwc->start_config_issued = false; |
| 1892 | 1942 | |
| @@ -1894,30 +1944,30 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) · 1 unmodified line | ||
| 1894 | 1944 | dwc->setup_packet_pending = false; |
| 1895 | 1945 | } |
| 1896 | 1946 | |
| 1897 | −static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on) | |
| 1947 | +static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) | |
| 1898 | 1948 | { |
| 1899 | 1949 | u32 reg; |
| 1900 | 1950 | |
| 1901 | 1951 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); |
| 1902 | 1952 | |
| 1903 | − if (on) | |
| 1904 | − reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; | |
| 1905 | − else | |
| 1953 | + if (suspend) | |
| 1906 | 1954 | reg |= DWC3_GUSB3PIPECTL_SUSPHY; |
| 1955 | + else | |
| 1956 | + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; | |
| 1907 | 1957 | |
| 1908 | 1958 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); |
| 1909 | 1959 | } |
| 1910 | 1960 | |
| 1911 | −static void dwc3_gadget_usb2_phy_power(struct dwc3 *dwc, int on) | |
| 1961 | +static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend) | |
| 1912 | 1962 | { |
| 1913 | 1963 | u32 reg; |
| 1914 | 1964 | |
| 1915 | 1965 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); |
| 1916 | 1966 | |
| 1917 | − if (on) | |
| 1918 | − reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | |
| 1919 | − else | |
| 1967 | + if (suspend) | |
| 1920 | 1968 | reg |= DWC3_GUSB2PHYCFG_SUSPHY; |
| 1969 | + else | |
| 1970 | + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | |
| 1921 | 1971 | |
| 1922 | 1972 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); |
| 1923 | 1973 | } |
| @@ -1962,16 +2012,18 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) · 38 unmodified lines | ||
| 1962 | 2012 | /* after reset -> Default State */ |
| 1963 | 2013 | dwc->dev_state = DWC3_DEFAULT_STATE; |
| 1964 | 2014 | |
| 1965 | − /* Enable PHYs */ | |
| 1966 | − dwc3_gadget_usb2_phy_power(dwc, true); | |
| 1967 | − dwc3_gadget_usb3_phy_power(dwc, true); | |
| 2015 | + /* Recent versions support automatic phy suspend and don't need this */ | |
| 2016 | + if (dwc->revision < DWC3_REVISION_194A) { | |
| 2017 | + /* Resume PHYs */ | |
| 2018 | + dwc3_gadget_usb2_phy_suspend(dwc, false); | |
| 2019 | + dwc3_gadget_usb3_phy_suspend(dwc, false); | |
| 2020 | + } | |
| 1968 | 2021 | |
| 1969 | 2022 | if (dwc->gadget.speed != USB_SPEED_UNKNOWN) |
| 1970 | 2023 | dwc3_disconnect_gadget(dwc); |
| 1971 | 2024 | |
| 1972 | 2025 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 1973 | 2026 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; |
| 1974 | − reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA); | |
| 1975 | 2027 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
| 1976 | 2028 | dwc->test_mode = false; |
| 1977 | 2029 | |
| @@ -2010,16 +2062,16 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) · 32 unmodified lines | ||
| 2010 | 2062 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); |
| 2011 | 2063 | } |
| 2012 | 2064 | |
| 2013 | −static void dwc3_gadget_disable_phy(struct dwc3 *dwc, u8 speed) | |
| 2065 | +static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed) | |
| 2014 | 2066 | { |
| 2015 | 2067 | switch (speed) { |
| 2016 | 2068 | case USB_SPEED_SUPER: |
| 2017 | − dwc3_gadget_usb2_phy_power(dwc, false); | |
| 2069 | + dwc3_gadget_usb2_phy_suspend(dwc, true); | |
| 2018 | 2070 | break; |
| 2019 | 2071 | case USB_SPEED_HIGH: |
| 2020 | 2072 | case USB_SPEED_FULL: |
| 2021 | 2073 | case USB_SPEED_LOW: |
| 2022 | − dwc3_gadget_usb3_phy_power(dwc, false); | |
| 2074 | + dwc3_gadget_usb3_phy_suspend(dwc, true); | |
| 2023 | 2075 | break; |
| 2024 | 2076 | } |
| 2025 | 2077 | } |
| @@ -2082,8 +2134,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) · 56 unmodified lines | ||
| 2082 | 2134 | break; |
| 2083 | 2135 | } |
| 2084 | 2136 | |
| 2085 | − /* Disable unneded PHY */ | |
| 2086 | − dwc3_gadget_disable_phy(dwc, dwc->gadget.speed); | |
| 2137 | + /* Recent versions support automatic phy suspend and don't need this */ | |
| 2138 | + if (dwc->revision < DWC3_REVISION_194A) { | |
| 2139 | + /* Suspend unneeded PHY */ | |
| 2140 | + dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed); | |
| 2141 | + } | |
| 2087 | 2142 | |
| 2088 | 2143 | dep = dwc->eps[0]; |
| 2089 | 2144 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); |
| @@ -2373,10 +2428,6 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) · 283 unmodified lines | ||
| 2373 | 2428 | reg |= DWC3_DCFG_LPM_CAP; |
| 2374 | 2429 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); |
| 2375 | 2430 | |
| 2376 | − reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 2377 | − reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA; | |
| 2378 | − dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 2379 | − | |
| 2380 | 2431 | /* Enable all but Start and End of Frame IRQs */ |
| 2381 | 2432 | reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | |
| 2382 | 2433 | DWC3_DEVTEN_EVNTOVERFLOWEN | |
| @@ -2389,6 +2440,24 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) · 6 unmodified lines | ||
| 2389 | 2440 | DWC3_DEVTEN_DISCONNEVTEN); |
| 2390 | 2441 | dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); |
| 2391 | 2442 | |
| 2443 | + /* Enable USB2 LPM and automatic phy suspend only on recent versions */ | |
| 2444 | + if (dwc->revision >= DWC3_REVISION_194A) { | |
| 2445 | + reg = dwc3_readl(dwc->regs, DWC3_DCFG); | |
| 2446 | + reg |= DWC3_DCFG_LPM_CAP; | |
| 2447 | + dwc3_writel(dwc->regs, DWC3_DCFG, reg); | |
| 2448 | + | |
| 2449 | + reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
| 2450 | + reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); | |
| 2451 | + | |
| 2452 | + /* TODO: This should be configurable */ | |
| 2453 | + reg |= DWC3_DCTL_HIRD_THRES(28); | |
| 2454 | + | |
| 2455 | + dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 2456 | + | |
| 2457 | + dwc3_gadget_usb2_phy_suspend(dwc, false); | |
| 2458 | + dwc3_gadget_usb3_phy_suspend(dwc, false); | |
| 2459 | + } | |
| 2460 | + | |
| 2392 | 2461 | ret = device_register(&dwc->gadget.dev); |
| 2393 | 2462 | if (ret) { |
| 2394 | 2463 | dev_err(dwc->dev, "failed to register gadget device\n"); |
| @@ -66,7 +66,12 @@ struct dwc3; · 65 unmodified lines | ||
| 66 | 66 | #define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) |
| 67 | 67 | #define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) |
| 68 | 68 | #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) |
| 69 | +/* This applies for core versions earlier than 1.94a */ | |
| 69 | 70 | #define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) |
| 71 | +/* These apply for core versions 1.94a and later */ | |
| 72 | +#define DWC3_DEPCFG_ACTION_INIT (0 << 30) | |
| 73 | +#define DWC3_DEPCFG_ACTION_RESTORE (1 << 30) | |
| 74 | +#define DWC3_DEPCFG_ACTION_MODIFY (2 << 30) | |
| 70 | 75 | |
| 71 | 76 | /* DEPXFERCFG parameter 0 */ |
| 72 | 77 | #define DWC3_DEPXFERCFG_NUM_XFER_RES(n) ((n) & 0xffff) |
| @@ -106,6 +111,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); · 33 unmodified lines | ||
| 106 | 111 | void dwc3_ep0_interrupt(struct dwc3 *dwc, |
| 107 | 112 | const struct dwc3_event_depevt *event); |
| 108 | 113 | void dwc3_ep0_out_start(struct dwc3 *dwc); |
| 114 | +int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); | |
| 109 | 115 | int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, |
| 110 | 116 | gfp_t gfp_flags); |
| 111 | 117 | int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); |
| @@ -334,7 +334,7 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, · 333 unmodified lines | ||
| 334 | 334 | int ret; |
| 335 | 335 | |
| 336 | 336 | read = (requesttype & USB_DIR_IN) != 0; |
| 337 | − if (size > (read ? DBGP_MAX_PACKET:0)) | |
| 337 | + if (size > (read ? DBGP_MAX_PACKET : 0)) | |
| 338 | 338 | return -1; |
| 339 | 339 | |
| 340 | 340 | /* Compute the control message */ |
| @@ -321,6 +321,15 @@ config USB_MV_UDC · 320 unmodified lines | ||
| 321 | 321 | USB2.0 OTG controller, which can be configured as high speed or |
| 322 | 322 | full speed USB peripheral. |
| 323 | 323 | |
| 324 | +config USB_MV_U3D | |
| 325 | + tristate "MARVELL PXA2128 USB 3.0 controller" | |
| 326 | + depends on CPU_MMP3 | |
| 327 | + select USB_GADGET_DUALSPEED | |
| 328 | + select USB_GADGET_SUPERSPEED | |
| 329 | + help | |
| 330 | + MARVELL PXA2128 Processor series include a super speed USB3.0 device | |
| 331 | + controller, which support super speed USB peripheral. | |
| 332 | + | |
| 324 | 333 | # |
| 325 | 334 | # Controllers available in both integrated and discrete versions |
| 326 | 335 | # |
| @@ -29,6 +29,7 @@ obj-$(CONFIG_USB_EG20T) += pch_udc.o · 28 unmodified lines | ||
| 29 | 29 | obj-$(CONFIG_USB_MV_UDC) += mv_udc.o |
| 30 | 30 | mv_udc-y := mv_udc_core.o |
| 31 | 31 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o |
| 32 | +obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o | |
| 32 | 33 | |
| 33 | 34 | # |
| 34 | 35 | # USB gadget drivers |
| @@ -235,6 +235,7 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) · 234 unmodified lines | ||
| 235 | 235 | static struct usb_composite_driver acm_ms_driver = { |
| 236 | 236 | .name = "g_acm_ms", |
| 237 | 237 | .dev = &device_desc, |
| 238 | + .max_speed = USB_SPEED_SUPER, | |
| 238 | 239 | .strings = dev_strings, |
| 239 | 240 | .unbind = __exit_p(acm_ms_unbind), |
| 240 | 241 | }; |
| @@ -1634,6 +1634,7 @@ static int at91_start(struct usb_gadget *gadget, · 1633 unmodified lines | ||
| 1634 | 1634 | udc = container_of(gadget, struct at91_udc, gadget); |
| 1635 | 1635 | udc->driver = driver; |
| 1636 | 1636 | udc->gadget.dev.driver = &driver->driver; |
| 1637 | + udc->gadget.dev.of_node = udc->pdev->dev.of_node; | |
| 1637 | 1638 | dev_set_drvdata(&udc->gadget.dev, &driver->driver); |
| 1638 | 1639 | udc->enabled = 1; |
| 1639 | 1640 | udc->selfpowered = 1; |
| @@ -117,6 +117,7 @@ int config_ep_by_speed(struct usb_gadget *g, · 116 unmodified lines | ||
| 117 | 117 | struct usb_function *f, |
| 118 | 118 | struct usb_ep *_ep) |
| 119 | 119 | { |
| 120 | + struct usb_composite_dev *cdev = get_gadget_data(g); | |
| 120 | 121 | struct usb_endpoint_descriptor *chosen_desc = NULL; |
| 121 | 122 | struct usb_descriptor_header **speed_desc = NULL; |
| 122 | 123 | |
| @@ -180,10 +181,12 @@ ep_found: · 57 unmodified lines | ||
| 180 | 181 | _ep->mult = comp_desc->bmAttributes & 0x3; |
| 181 | 182 | case USB_ENDPOINT_XFER_BULK: |
| 182 | 183 | case USB_ENDPOINT_XFER_INT: |
| 183 | − _ep->maxburst = comp_desc->bMaxBurst; | |
| 184 | + _ep->maxburst = comp_desc->bMaxBurst + 1; | |
| 184 | 185 | break; |
| 185 | 186 | default: |
| 186 | − /* Do nothing for control endpoints */ | |
| 187 | + if (comp_desc->bMaxBurst != 0) | |
| 188 | + ERROR(cdev, "ep0 bMaxBurst must be 0\n"); | |
| 189 | + _ep->maxburst = 1; | |
| 187 | 190 | break; |
| 188 | 191 | } |
| 189 | 192 | } |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/blkdev.h> |
| 22 | 22 | #include <linux/pagemap.h> |
| 23 | 23 | #include <linux/export.h> |
| 24 | +#include <linux/hid.h> | |
| 24 | 25 | #include <asm/unaligned.h> |
| 25 | 26 | |
| 26 | 27 | #include <linux/usb/composite.h> |
| @@ -1671,6 +1672,12 @@ static int __must_check ffs_do_desc(char *data, unsigned len, · 1644 unmodified lines | ||
| 1671 | 1672 | } |
| 1672 | 1673 | break; |
| 1673 | 1674 | |
| 1675 | + case HID_DT_HID: | |
| 1676 | + pr_vdebug("hid descriptor\n"); | |
| 1677 | + if (length != sizeof(struct hid_descriptor)) | |
| 1678 | + goto inv_length; | |
| 1679 | + break; | |
| 1680 | + | |
| 1674 | 1681 | case USB_DT_OTG: |
| 1675 | 1682 | if (length != sizeof(struct usb_otg_descriptor)) |
| 1676 | 1683 | goto inv_length; |
| @@ -26,6 +26,12 @@ static struct class *hidg_class; · 25 unmodified lines | ||
| 26 | 26 | /*-------------------------------------------------------------------------*/ |
| 27 | 27 | /* HID gadget struct */ |
| 28 | 28 | |
| 29 | +struct f_hidg_req_list { | |
| 30 | + struct usb_request *req; | |
| 31 | + unsigned int pos; | |
| 32 | + struct list_head list; | |
| 33 | +}; | |
| 34 | + | |
| 29 | 35 | struct f_hidg { |
| 30 | 36 | /* configuration */ |
| 31 | 37 | unsigned char bInterfaceSubClass; |
| @@ -35,10 +41,10 @@ struct f_hidg { · 3 unmodified lines | ||
| 35 | 41 | unsigned short report_length; |
| 36 | 42 | |
| 37 | 43 | /* recv report */ |
| 38 | − char *set_report_buff; | |
| 39 | − unsigned short set_report_length; | |
| 44 | + struct list_head completed_out_req; | |
| 40 | 45 | spinlock_t spinlock; |
| 41 | 46 | wait_queue_head_t read_queue; |
| 47 | + unsigned int qlen; | |
| 42 | 48 | |
| 43 | 49 | /* send report */ |
| 44 | 50 | struct mutex lock; |
| @@ -49,7 +55,9 @@ struct f_hidg { · 4 unmodified lines | ||
| 49 | 55 | int minor; |
| 50 | 56 | struct cdev cdev; |
| 51 | 57 | struct usb_function func; |
| 58 | + | |
| 52 | 59 | struct usb_ep *in_ep; |
| 60 | + struct usb_ep *out_ep; | |
| 53 | 61 | }; |
| 54 | 62 | |
| 55 | 63 | static inline struct f_hidg *func_to_hidg(struct usb_function *f) |
| @@ -65,7 +73,7 @@ static struct usb_interface_descriptor hidg_interface_desc = { · 9 unmodified lines | ||
| 65 | 73 | .bDescriptorType = USB_DT_INTERFACE, |
| 66 | 74 | /* .bInterfaceNumber = DYNAMIC */ |
| 67 | 75 | .bAlternateSetting = 0, |
| 68 | − .bNumEndpoints = 1, | |
| 76 | + .bNumEndpoints = 2, | |
| 69 | 77 | .bInterfaceClass = USB_CLASS_HID, |
| 70 | 78 | /* .bInterfaceSubClass = DYNAMIC */ |
| 71 | 79 | /* .bInterfaceProtocol = DYNAMIC */ |
| @@ -96,10 +104,23 @@ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { · 24 unmodified lines | ||
| 96 | 104 | */ |
| 97 | 105 | }; |
| 98 | 106 | |
| 107 | +static struct usb_endpoint_descriptor hidg_hs_out_ep_desc = { | |
| 108 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 109 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 110 | + .bEndpointAddress = USB_DIR_OUT, | |
| 111 | + .bmAttributes = USB_ENDPOINT_XFER_INT, | |
| 112 | + /*.wMaxPacketSize = DYNAMIC */ | |
| 113 | + .bInterval = 4, /* FIXME: Add this field in the | |
| 114 | + * HID gadget configuration? | |
| 115 | + * (struct hidg_func_descriptor) | |
| 116 | + */ | |
| 117 | +}; | |
| 118 | + | |
| 99 | 119 | static struct usb_descriptor_header *hidg_hs_descriptors[] = { |
| 100 | 120 | (struct usb_descriptor_header *)&hidg_interface_desc, |
| 101 | 121 | (struct usb_descriptor_header *)&hidg_desc, |
| 102 | 122 | (struct usb_descriptor_header *)&hidg_hs_in_ep_desc, |
| 123 | + (struct usb_descriptor_header *)&hidg_hs_out_ep_desc, | |
| 103 | 124 | NULL, |
| 104 | 125 | }; |
| 105 | 126 | |
| @@ -117,10 +138,23 @@ static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = { · 11 unmodified lines | ||
| 117 | 138 | */ |
| 118 | 139 | }; |
| 119 | 140 | |
| 141 | +static struct usb_endpoint_descriptor hidg_fs_out_ep_desc = { | |
| 142 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 143 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 144 | + .bEndpointAddress = USB_DIR_OUT, | |
| 145 | + .bmAttributes = USB_ENDPOINT_XFER_INT, | |
| 146 | + /*.wMaxPacketSize = DYNAMIC */ | |
| 147 | + .bInterval = 10, /* FIXME: Add this field in the | |
| 148 | + * HID gadget configuration? | |
| 149 | + * (struct hidg_func_descriptor) | |
| 150 | + */ | |
| 151 | +}; | |
| 152 | + | |
| 120 | 153 | static struct usb_descriptor_header *hidg_fs_descriptors[] = { |
| 121 | 154 | (struct usb_descriptor_header *)&hidg_interface_desc, |
| 122 | 155 | (struct usb_descriptor_header *)&hidg_desc, |
| 123 | 156 | (struct usb_descriptor_header *)&hidg_fs_in_ep_desc, |
| 157 | + (struct usb_descriptor_header *)&hidg_fs_out_ep_desc, | |
| 124 | 158 | NULL, |
| 125 | 159 | }; |
| 126 | 160 | |
| @@ -130,9 +164,11 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = { · 3 unmodified lines | ||
| 130 | 164 | static ssize_t f_hidg_read(struct file *file, char __user *buffer, |
| 131 | 165 | size_t count, loff_t *ptr) |
| 132 | 166 | { |
| 133 | − struct f_hidg *hidg = file->private_data; | |
| 134 | − char *tmp_buff = NULL; | |
| 135 | − unsigned long flags; | |
| 167 | + struct f_hidg *hidg = file->private_data; | |
| 168 | + struct f_hidg_req_list *list; | |
| 169 | + struct usb_request *req; | |
| 170 | + unsigned long flags; | |
| 171 | + int ret; | |
| 136 | 172 | |
| 137 | 173 | if (!count) |
| 138 | 174 | return 0; |
| @@ -142,8 +178,9 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, · 3 unmodified lines | ||
| 142 | 178 | |
| 143 | 179 | spin_lock_irqsave(&hidg->spinlock, flags); |
| 144 | 180 | |
| 145 | −#define READ_COND (hidg->set_report_buff != NULL) | |
| 181 | +#define READ_COND (!list_empty(&hidg->completed_out_req)) | |
| 146 | 182 | |
| 183 | + /* wait for at least one buffer to complete */ | |
| 147 | 184 | while (!READ_COND) { |
| 148 | 185 | spin_unlock_irqrestore(&hidg->spinlock, flags); |
| 149 | 186 | if (file->f_flags & O_NONBLOCK) |
| @@ -155,19 +192,34 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, · 5 unmodified lines | ||
| 155 | 192 | spin_lock_irqsave(&hidg->spinlock, flags); |
| 156 | 193 | } |
| 157 | 194 | |
| 158 | − | |
| 159 | − count = min_t(unsigned, count, hidg->set_report_length); | |
| 160 | − tmp_buff = hidg->set_report_buff; | |
| 161 | − hidg->set_report_buff = NULL; | |
| 162 | − | |
| 195 | + /* pick the first one */ | |
| 196 | + list = list_first_entry(&hidg->completed_out_req, | |
| 197 | + struct f_hidg_req_list, list); | |
| 198 | + req = list->req; | |
| 199 | + count = min_t(unsigned int, count, req->actual - list->pos); | |
| 163 | 200 | spin_unlock_irqrestore(&hidg->spinlock, flags); |
| 164 | 201 | |
| 165 | − if (tmp_buff != NULL) { | |
| 166 | − /* copy to user outside spinlock */ | |
| 167 | − count -= copy_to_user(buffer, tmp_buff, count); | |
| 168 | − kfree(tmp_buff); | |
| 169 | − } else | |
| 170 | − count = -ENOMEM; | |
| 202 | + /* copy to user outside spinlock */ | |
| 203 | + count -= copy_to_user(buffer, req->buf + list->pos, count); | |
| 204 | + list->pos += count; | |
| 205 | + | |
| 206 | + /* | |
| 207 | + * if this request is completely handled and transfered to | |
| 208 | + * userspace, remove its entry from the list and requeue it | |
| 209 | + * again. Otherwise, we will revisit it again upon the next | |
| 210 | + * call, taking into account its current read position. | |
| 211 | + */ | |
| 212 | + if (list->pos == req->actual) { | |
| 213 | + spin_lock_irqsave(&hidg->spinlock, flags); | |
| 214 | + list_del(&list->list); | |
| 215 | + kfree(list); | |
| 216 | + spin_unlock_irqrestore(&hidg->spinlock, flags); | |
| 217 | + | |
| 218 | + req->length = hidg->report_length; | |
| 219 | + ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); | |
| 220 | + if (ret < 0) | |
| 221 | + return ret; | |
| 222 | + } | |
| 171 | 223 | |
| 172 | 224 | return count; |
| 173 | 225 | } |
| @@ -282,28 +334,37 @@ static int f_hidg_open(struct inode *inode, struct file *fd) · 108 unmodified lines | ||
| 282 | 334 | /*-------------------------------------------------------------------------*/ |
| 283 | 335 | /* usb_function */ |
| 284 | 336 | |
| 285 | −static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) | |
| 337 | +static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length) | |
| 286 | 338 | { |
| 287 | − struct f_hidg *hidg = (struct f_hidg *)req->context; | |
| 288 | − | |
| 289 | − if (req->status != 0 || req->buf == NULL || req->actual == 0) { | |
| 290 | − ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__); | |
| 291 | − return; | |
| 339 | + struct usb_request *req; | |
| 340 | + | |
| 341 | + req = usb_ep_alloc_request(ep, GFP_ATOMIC); | |
| 342 | + if (req) { | |
| 343 | + req->length = length; | |
| 344 | + req->buf = kmalloc(length, GFP_ATOMIC); | |
| 345 | + if (!req->buf) { | |
| 346 | + usb_ep_free_request(ep, req); | |
| 347 | + req = NULL; | |
| 348 | + } | |
| 292 | 349 | } |
| 350 | + return req; | |
| 351 | +} | |
| 293 | 352 | |
| 294 | − spin_lock(&hidg->spinlock); | |
| 295 | − | |
| 296 | − hidg->set_report_buff = krealloc(hidg->set_report_buff, | |
| 297 | − req->actual, GFP_ATOMIC); | |
| 353 | +static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) | |
| 354 | +{ | |
| 355 | + struct f_hidg *hidg = (struct f_hidg *) req->context; | |
| 356 | + struct f_hidg_req_list *req_list; | |
| 357 | + unsigned long flags; | |
| 298 | 358 | |
| 299 | − if (hidg->set_report_buff == NULL) { | |
| 300 | − spin_unlock(&hidg->spinlock); | |
| 359 | + req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); | |
| 360 | + if (!req_list) | |
| 301 | 361 | return; |
| 302 | − } | |
| 303 | − hidg->set_report_length = req->actual; | |
| 304 | − memcpy(hidg->set_report_buff, req->buf, req->actual); | |
| 305 | 362 | |
| 306 | − spin_unlock(&hidg->spinlock); | |
| 363 | + req_list->req = req; | |
| 364 | + | |
| 365 | + spin_lock_irqsave(&hidg->spinlock, flags); | |
| 366 | + list_add_tail(&req_list->list, &hidg->completed_out_req); | |
| 367 | + spin_unlock_irqrestore(&hidg->spinlock, flags); | |
| 307 | 368 | |
| 308 | 369 | wake_up(&hidg->read_queue); |
| 309 | 370 | } |
| @@ -344,9 +405,7 @@ static int hidg_setup(struct usb_function *f, · 34 unmodified lines | ||
| 344 | 405 | case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 |
| 345 | 406 | | HID_REQ_SET_REPORT): |
| 346 | 407 | VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength); |
| 347 | − req->context = hidg; | |
| 348 | − req->complete = hidg_set_report_complete; | |
| 349 | − goto respond; | |
| 408 | + goto stall; | |
| 350 | 409 | break; |
| 351 | 410 | |
| 352 | 411 | case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 |
| @@ -403,16 +462,25 @@ respond: · 50 unmodified lines | ||
| 403 | 462 | static void hidg_disable(struct usb_function *f) |
| 404 | 463 | { |
| 405 | 464 | struct f_hidg *hidg = func_to_hidg(f); |
| 465 | + struct f_hidg_req_list *list, *next; | |
| 406 | 466 | |
| 407 | 467 | usb_ep_disable(hidg->in_ep); |
| 408 | 468 | hidg->in_ep->driver_data = NULL; |
| 469 | + | |
| 470 | + usb_ep_disable(hidg->out_ep); | |
| 471 | + hidg->out_ep->driver_data = NULL; | |
| 472 | + | |
| 473 | + list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { | |
| 474 | + list_del(&list->list); | |
| 475 | + kfree(list); | |
| 476 | + } | |
| 409 | 477 | } |
| 410 | 478 | |
| 411 | 479 | static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) |
| 412 | 480 | { |
| 413 | 481 | struct usb_composite_dev *cdev = f->config->cdev; |
| 414 | 482 | struct f_hidg *hidg = func_to_hidg(f); |
| 415 | − int status = 0; | |
| 483 | + int i, status = 0; | |
| 416 | 484 | |
| 417 | 485 | VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); |
| 418 | 486 | |
| @@ -429,11 +497,55 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) · 10 unmodified lines | ||
| 429 | 497 | } |
| 430 | 498 | status = usb_ep_enable(hidg->in_ep); |
| 431 | 499 | if (status < 0) { |
| 432 | − ERROR(cdev, "Enable endpoint FAILED!\n"); | |
| 500 | + ERROR(cdev, "Enable IN endpoint FAILED!\n"); | |
| 433 | 501 | goto fail; |
| 434 | 502 | } |
| 435 | 503 | hidg->in_ep->driver_data = hidg; |
| 436 | 504 | } |
| 505 | + | |
| 506 | + | |
| 507 | + if (hidg->out_ep != NULL) { | |
| 508 | + /* restart endpoint */ | |
| 509 | + if (hidg->out_ep->driver_data != NULL) | |
| 510 | + usb_ep_disable(hidg->out_ep); | |
| 511 | + | |
| 512 | + status = config_ep_by_speed(f->config->cdev->gadget, f, | |
| 513 | + hidg->out_ep); | |
| 514 | + if (status) { | |
| 515 | + ERROR(cdev, "config_ep_by_speed FAILED!\n"); | |
| 516 | + goto fail; | |
| 517 | + } | |
| 518 | + status = usb_ep_enable(hidg->out_ep); | |
| 519 | + if (status < 0) { | |
| 520 | + ERROR(cdev, "Enable IN endpoint FAILED!\n"); | |
| 521 | + goto fail; | |
| 522 | + } | |
| 523 | + hidg->out_ep->driver_data = hidg; | |
| 524 | + | |
| 525 | + /* | |
| 526 | + * allocate a bunch of read buffers and queue them all at once. | |
| 527 | + */ | |
| 528 | + for (i = 0; i < hidg->qlen && status == 0; i++) { | |
| 529 | + struct usb_request *req = | |
| 530 | + hidg_alloc_ep_req(hidg->out_ep, | |
| 531 | + hidg->report_length); | |
| 532 | + if (req) { | |
| 533 | + req->complete = hidg_set_report_complete; | |
| 534 | + req->context = hidg; | |
| 535 | + status = usb_ep_queue(hidg->out_ep, req, | |
| 536 | + GFP_ATOMIC); | |
| 537 | + if (status) | |
| 538 | + ERROR(cdev, "%s queue req --> %d\n", | |
| 539 | + hidg->out_ep->name, status); | |
| 540 | + } else { | |
| 541 | + usb_ep_disable(hidg->out_ep); | |
| 542 | + hidg->out_ep->driver_data = NULL; | |
| 543 | + status = -ENOMEM; | |
| 544 | + goto fail; | |
| 545 | + } | |
| 546 | + } | |
| 547 | + } | |
| 548 | + | |
| 437 | 549 | fail: |
| 438 | 550 | return status; |
| 439 | 551 | } |
| @@ -470,13 +582,18 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) · 30 unmodified lines | ||
| 470 | 582 | ep->driver_data = c->cdev; /* claim */ |
| 471 | 583 | hidg->in_ep = ep; |
| 472 | 584 | |
| 585 | + ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc); | |
| 586 | + if (!ep) | |
| 587 | + goto fail; | |
| 588 | + ep->driver_data = c->cdev; /* claim */ | |
| 589 | + hidg->out_ep = ep; | |
| 590 | + | |
| 473 | 591 | /* preallocate request and buffer */ |
| 474 | 592 | status = -ENOMEM; |
| 475 | 593 | hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL); |
| 476 | 594 | if (!hidg->req) |
| 477 | 595 | goto fail; |
| 478 | 596 | |
| 479 | − | |
| 480 | 597 | hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL); |
| 481 | 598 | if (!hidg->req->buf) |
| 482 | 599 | goto fail; |
| @@ -486,12 +603,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) · 3 unmodified lines | ||
| 486 | 603 | hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; |
| 487 | 604 | hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); |
| 488 | 605 | hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); |
| 606 | + hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); | |
| 607 | + hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); | |
| 489 | 608 | hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; |
| 490 | 609 | hidg_desc.desc[0].wDescriptorLength = |
| 491 | 610 | cpu_to_le16(hidg->report_desc_length); |
| 492 | 611 | |
| 493 | − hidg->set_report_buff = NULL; | |
| 494 | − | |
| 495 | 612 | /* copy descriptors */ |
| 496 | 613 | f->descriptors = usb_copy_descriptors(hidg_fs_descriptors); |
| 497 | 614 | if (!f->descriptors) |
| @@ -500,6 +617,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) · 2 unmodified lines | ||
| 500 | 617 | if (gadget_is_dualspeed(c->cdev->gadget)) { |
| 501 | 618 | hidg_hs_in_ep_desc.bEndpointAddress = |
| 502 | 619 | hidg_fs_in_ep_desc.bEndpointAddress; |
| 620 | + hidg_hs_out_ep_desc.bEndpointAddress = | |
| 621 | + hidg_fs_out_ep_desc.bEndpointAddress; | |
| 503 | 622 | f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors); |
| 504 | 623 | if (!f->hs_descriptors) |
| 505 | 624 | goto fail; |
| @@ -509,6 +628,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) · 3 unmodified lines | ||
| 509 | 628 | spin_lock_init(&hidg->spinlock); |
| 510 | 629 | init_waitqueue_head(&hidg->write_queue); |
| 511 | 630 | init_waitqueue_head(&hidg->read_queue); |
| 631 | + INIT_LIST_HEAD(&hidg->completed_out_req); | |
| 512 | 632 | |
| 513 | 633 | /* create char device */ |
| 514 | 634 | cdev_init(&hidg->cdev, &f_hidg_fops); |
| @@ -553,7 +673,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) · 38 unmodified lines | ||
| 553 | 673 | usb_free_descriptors(f->descriptors); |
| 554 | 674 | |
| 555 | 675 | kfree(hidg->report_desc); |
| 556 | − kfree(hidg->set_report_buff); | |
| 557 | 676 | kfree(hidg); |
| 558 | 677 | } |
| 559 | 678 | |
| @@ -624,6 +743,9 @@ int __init hidg_bind_config(struct usb_configuration *c, · 64 unmodified lines | ||
| 624 | 743 | hidg->func.disable = hidg_disable; |
| 625 | 744 | hidg->func.setup = hidg_setup; |
| 626 | 745 | |
| 746 | + /* this could me made configurable at some point */ | |
| 747 | + hidg->qlen = 4; | |
| 748 | + | |
| 627 | 749 | status = usb_add_function(c, &hidg->func); |
| 628 | 750 | if (status) |
| 629 | 751 | kfree(hidg); |
| @@ -44,12 +44,12 @@ · 43 unmodified lines | ||
| 44 | 44 | * function for a USB device, it also illustrates a technique of |
| 45 | 45 | * double-buffering for increased throughput. |
| 46 | 46 | * |
| 47 | − * Function supports multiple logical units (LUNs). Backing storage | |
| 48 | − * for each LUN is provided by a regular file or a block device. | |
| 49 | − * Access for each LUN can be limited to read-only. Moreover, the | |
| 50 | − * function can indicate that LUN is removable and/or CD-ROM. (The | |
| 51 | − * later implies read-only access.) | |
| 52 | − * | |
| 47 | + * For more information about MSF and in particular its module | |
| 48 | + * parameters and sysfs interface read the | |
| 49 | + * <Documentation/usb/mass-storage.txt> file. | |
| 50 | + */ | |
| 51 | + | |
| 52 | +/* | |
| 53 | 53 | * MSF is configured by specifying a fsg_config structure. It has the |
| 54 | 54 | * following fields: |
| 55 | 55 | * |
| @@ -75,25 +75,6 @@ · 19 unmodified lines | ||
| 75 | 75 | * ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12) |
| 76 | 76 | * commands for this LUN shall be ignored. |
| 77 | 77 | * |
| 78 | − * lun_name_format A printf-like format for names of the LUN | |
| 79 | − * devices. This determines how the | |
| 80 | − * directory in sysfs will be named. | |
| 81 | − * Unless you are using several MSFs in | |
| 82 | − * a single gadget (as opposed to single | |
| 83 | − * MSF in many configurations) you may | |
| 84 | − * leave it as NULL (in which case | |
| 85 | − * "lun%d" will be used). In the format | |
| 86 | − * you can use "%d" to index LUNs for | |
| 87 | − * MSF's with more than one LUN. (Beware | |
| 88 | − * that there is only one integer given | |
| 89 | − * as an argument for the format and | |
| 90 | − * specifying invalid format may cause | |
| 91 | − * unspecified behaviour.) | |
| 92 | − * thread_name Name of the kernel thread process used by the | |
| 93 | − * MSF. You can safely set it to NULL | |
| 94 | − * (in which case default "file-storage" | |
| 95 | − * will be used). | |
| 96 | − * | |
| 97 | 78 | * vendor_name |
| 98 | 79 | * product_name |
| 99 | 80 | * release Information used as a reply to INQUIRY |
| @@ -114,62 +95,6 @@ · 14 unmodified lines | ||
| 114 | 95 | * data track and no audio tracks; hence there need be only one |
| 115 | 96 | * backing file per LUN. |
| 116 | 97 | * |
| 117 | − * | |
| 118 | − * MSF includes support for module parameters. If gadget using it | |
| 119 | − * decides to use it, the following module parameters will be | |
| 120 | − * available: | |
| 121 | − * | |
| 122 | − * file=filename[,filename...] | |
| 123 | − * Names of the files or block devices used for | |
| 124 | − * backing storage. | |
| 125 | − * ro=b[,b...] Default false, boolean for read-only access. | |
| 126 | − * removable=b[,b...] | |
| 127 | − * Default true, boolean for removable media. | |
| 128 | − * cdrom=b[,b...] Default false, boolean for whether to emulate | |
| 129 | − * a CD-ROM drive. | |
| 130 | − * nofua=b[,b...] Default false, booleans for ignore FUA flag | |
| 131 | − * in SCSI WRITE(10,12) commands | |
| 132 | − * luns=N Default N = number of filenames, number of | |
| 133 | − * LUNs to support. | |
| 134 | − * stall Default determined according to the type of | |
| 135 | − * USB device controller (usually true), | |
| 136 | − * boolean to permit the driver to halt | |
| 137 | − * bulk endpoints. | |
| 138 | − * | |
| 139 | − * The module parameters may be prefixed with some string. You need | |
| 140 | − * to consult gadget's documentation or source to verify whether it is | |
| 141 | − * using those module parameters and if it does what are the prefixes | |
| 142 | − * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is | |
| 143 | − * the prefix). | |
| 144 | − * | |
| 145 | − * | |
| 146 | − * Requirements are modest; only a bulk-in and a bulk-out endpoint are | |
| 147 | − * needed. The memory requirement amounts to two 16K buffers, size | |
| 148 | − * configurable by a parameter. Support is included for both | |
| 149 | − * full-speed and high-speed operation. | |
| 150 | − * | |
| 151 | − * Note that the driver is slightly non-portable in that it assumes a | |
| 152 | − * single memory/DMA buffer will be useable for bulk-in, bulk-out, and | |
| 153 | − * interrupt-in endpoints. With most device controllers this isn't an | |
| 154 | − * issue, but there may be some with hardware restrictions that prevent | |
| 155 | − * a buffer from being used by more than one endpoint. | |
| 156 | − * | |
| 157 | − * | |
| 158 | − * The pathnames of the backing files and the ro settings are | |
| 159 | − * available in the attribute files "file" and "ro" in the lun<n> (or | |
| 160 | − * to be more precise in a directory which name comes from | |
| 161 | − * "lun_name_format" option!) subdirectory of the gadget's sysfs | |
| 162 | − * directory. If the "removable" option is set, writing to these | |
| 163 | − * files will simulate ejecting/loading the medium (writing an empty | |
| 164 | − * line means eject) and adjusting a write-enable tab. Changes to the | |
| 165 | − * ro setting are not allowed when the medium is loaded or if CD-ROM | |
| 166 | − * emulation is being used. | |
| 167 | − * | |
| 168 | − * When a LUN receive an "eject" SCSI request (Start/Stop Unit), | |
| 169 | − * if the LUN is removable, the backing file is released to simulate | |
| 170 | − * ejection. | |
| 171 | − * | |
| 172 | − * | |
| 173 | 98 | * This function is heavily based on "File-backed Storage Gadget" by |
| 174 | 99 | * Alan Stern which in turn is heavily based on "Gadget Zero" by David |
| 175 | 100 | * Brownell. The driver's SCSI command interface was based on the |
| @@ -211,7 +136,7 @@ · 35 unmodified lines | ||
| 211 | 136 | * In normal operation the main thread is started during the gadget's |
| 212 | 137 | * fsg_bind() callback and stopped during fsg_unbind(). But it can |
| 213 | 138 | * also exit when it receives a signal, and there's no point leaving |
| 214 | − * the gadget running when the thread is dead. At of this moment, MSF | |
| 139 | + * the gadget running when the thread is dead. As of this moment, MSF | |
| 215 | 140 | * provides no way to deregister the gadget when thread dies -- maybe |
| 216 | 141 | * a callback functions is needed. |
| 217 | 142 | * |
| @@ -417,9 +342,6 @@ struct fsg_config { · 199 unmodified lines | ||
| 417 | 342 | char nofua; |
| 418 | 343 | } luns[FSG_MAX_LUNS]; |
| 419 | 344 | |
| 420 | − const char *lun_name_format; | |
| 421 | − const char *thread_name; | |
| 422 | − | |
| 423 | 345 | /* Callback functions. */ |
| 424 | 346 | const struct fsg_operations *ops; |
| 425 | 347 | /* Gadget's private data. */ |
| @@ -2687,11 +2609,15 @@ static int fsg_main_thread(void *common_) · 2261 unmodified lines | ||
| 2687 | 2609 | |
| 2688 | 2610 | /*************************** DEVICE ATTRIBUTES ***************************/ |
| 2689 | 2611 | |
| 2690 | −/* Write permission is checked per LUN in store_*() functions. */ | |
| 2691 | 2612 | static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro); |
| 2692 | 2613 | static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua); |
| 2693 | 2614 | static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file); |
| 2694 | 2615 | |
| 2616 | +static struct device_attribute dev_attr_ro_cdrom = | |
| 2617 | + __ATTR(ro, 0444, fsg_show_ro, NULL); | |
| 2618 | +static struct device_attribute dev_attr_file_nonremovable = | |
| 2619 | + __ATTR(file, 0444, fsg_show_file, NULL); | |
| 2620 | + | |
| 2695 | 2621 | |
| 2696 | 2622 | /****************************** FSG COMMON ******************************/ |
| 2697 | 2623 | |
| @@ -2792,11 +2718,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, · 94 unmodified lines | ||
| 2792 | 2718 | curlun->dev.parent = &gadget->dev; |
| 2793 | 2719 | /* curlun->dev.driver = &fsg_driver.driver; XXX */ |
| 2794 | 2720 | dev_set_drvdata(&curlun->dev, &common->filesem); |
| 2795 | − dev_set_name(&curlun->dev, | |
| 2796 | − cfg->lun_name_format | |
| 2797 | − ? cfg->lun_name_format | |
| 2798 | − : "lun%d", | |
| 2799 | − i); | |
| 2721 | + dev_set_name(&curlun->dev, "lun%d", i); | |
| 2800 | 2722 | |
| 2801 | 2723 | rc = device_register(&curlun->dev); |
| 2802 | 2724 | if (rc) { |
| @@ -2806,10 +2728,16 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, · 3 unmodified lines | ||
| 2806 | 2728 | goto error_release; |
| 2807 | 2729 | } |
| 2808 | 2730 | |
| 2809 | − rc = device_create_file(&curlun->dev, &dev_attr_ro); | |
| 2731 | + rc = device_create_file(&curlun->dev, | |
| 2732 | + curlun->cdrom | |
| 2733 | + ? &dev_attr_ro_cdrom | |
| 2734 | + : &dev_attr_ro); | |
| 2810 | 2735 | if (rc) |
| 2811 | 2736 | goto error_luns; |
| 2812 | − rc = device_create_file(&curlun->dev, &dev_attr_file); | |
| 2737 | + rc = device_create_file(&curlun->dev, | |
| 2738 | + curlun->removable | |
| 2739 | + ? &dev_attr_file | |
| 2740 | + : &dev_attr_file_nonremovable); | |
| 2813 | 2741 | if (rc) |
| 2814 | 2742 | goto error_luns; |
| 2815 | 2743 | rc = device_create_file(&curlun->dev, &dev_attr_nofua); |
| @@ -2878,8 +2806,7 @@ buffhds_first_it: · 62 unmodified lines | ||
| 2878 | 2806 | |
| 2879 | 2807 | /* Tell the thread to start working */ |
| 2880 | 2808 | common->thread_task = |
| 2881 | − kthread_create(fsg_main_thread, common, | |
| 2882 | − cfg->thread_name ?: "file-storage"); | |
| 2809 | + kthread_create(fsg_main_thread, common, "file-storage"); | |
| 2883 | 2810 | if (IS_ERR(common->thread_task)) { |
| 2884 | 2811 | rc = PTR_ERR(common->thread_task); |
| 2885 | 2812 | goto error_release; |
| @@ -2945,8 +2872,14 @@ static void fsg_common_release(struct kref *ref) · 59 unmodified lines | ||
| 2945 | 2872 | /* In error recovery common->nluns may be zero. */ |
| 2946 | 2873 | for (; i; --i, ++lun) { |
| 2947 | 2874 | device_remove_file(&lun->dev, &dev_attr_nofua); |
| 2948 | − device_remove_file(&lun->dev, &dev_attr_ro); | |
| 2949 | − device_remove_file(&lun->dev, &dev_attr_file); | |
| 2875 | + device_remove_file(&lun->dev, | |
| 2876 | + lun->cdrom | |
| 2877 | + ? &dev_attr_ro_cdrom | |
| 2878 | + : &dev_attr_ro); | |
| 2879 | + device_remove_file(&lun->dev, | |
| 2880 | + lun->removable | |
| 2881 | + ? &dev_attr_file | |
| 2882 | + : &dev_attr_file_nonremovable); | |
| 2950 | 2883 | fsg_lun_close(lun); |
| 2951 | 2884 | device_unregister(&lun->dev); |
| 2952 | 2885 | } |
| @@ -3167,8 +3100,7 @@ fsg_config_from_params(struct fsg_config *cfg, · 214 unmodified lines | ||
| 3167 | 3100 | for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) { |
| 3168 | 3101 | lun->ro = !!params->ro[i]; |
| 3169 | 3102 | lun->cdrom = !!params->cdrom[i]; |
| 3170 | − lun->removable = /* Removable by default */ | |
| 3171 | − params->removable_count <= i || params->removable[i]; | |
| 3103 | + lun->removable = !!params->removable[i]; | |
| 3172 | 3104 | lun->filename = |
| 3173 | 3105 | params->file_count > i && params->file[i][0] |
| 3174 | 3106 | ? params->file[i] |
| @@ -3176,8 +3108,6 @@ fsg_config_from_params(struct fsg_config *cfg, · 1 unmodified line | ||
| 3176 | 3108 | } |
| 3177 | 3109 | |
| 3178 | 3110 | /* Let MSF use defaults */ |
| 3179 | − cfg->lun_name_format = 0; | |
| 3180 | − cfg->thread_name = 0; | |
| 3181 | 3111 | cfg->vendor_name = 0; |
| 3182 | 3112 | cfg->product_name = 0; |
| 3183 | 3113 | cfg->release = 0xffff; |
| @@ -3203,4 +3133,3 @@ fsg_common_from_params(struct fsg_common *common, · 19 unmodified lines | ||
| 3203 | 3133 | fsg_config_from_params(&cfg, params); |
| 3204 | 3134 | return fsg_common_init(common, cdev, &cfg); |
| 3205 | 3135 | } |
| 3206 | − | |
| @@ -29,6 +29,25 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | unsigned int uvc_gadget_trace_param; |
| 31 | 31 | |
| 32 | +/*-------------------------------------------------------------------------*/ | |
| 33 | + | |
| 34 | +/* module parameters specific to the Video streaming endpoint */ | |
| 35 | +static unsigned streaming_interval = 1; | |
| 36 | +module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); | |
| 37 | +MODULE_PARM_DESC(streaming_interval, "1 - 16"); | |
| 38 | + | |
| 39 | +static unsigned streaming_maxpacket = 1024; | |
| 40 | +module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); | |
| 41 | +MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); | |
| 42 | + | |
| 43 | +static unsigned streaming_mult; | |
| 44 | +module_param(streaming_mult, uint, S_IRUGO|S_IWUSR); | |
| 45 | +MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)"); | |
| 46 | + | |
| 47 | +static unsigned streaming_maxburst; | |
| 48 | +module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); | |
| 49 | +MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); | |
| 50 | + | |
| 32 | 51 | /* -------------------------------------------------------------------------- |
| 33 | 52 | * Function descriptors |
| 34 | 53 | */ |
| @@ -59,6 +78,8 @@ static struct usb_gadget_strings *uvc_function_strings[] = { · 24 unmodified lines | ||
| 59 | 78 | #define UVC_INTF_VIDEO_CONTROL 0 |
| 60 | 79 | #define UVC_INTF_VIDEO_STREAMING 1 |
| 61 | 80 | |
| 81 | +#define STATUS_BYTECOUNT 16 /* 16 bytes status */ | |
| 82 | + | |
| 62 | 83 | static struct usb_interface_assoc_descriptor uvc_iad __initdata = { |
| 63 | 84 | .bLength = sizeof(uvc_iad), |
| 64 | 85 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
| @@ -82,12 +103,12 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { · 17 unmodified lines | ||
| 82 | 103 | .iInterface = 0, |
| 83 | 104 | }; |
| 84 | 105 | |
| 85 | −static struct usb_endpoint_descriptor uvc_control_ep __initdata = { | |
| 106 | +static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { | |
| 86 | 107 | .bLength = USB_DT_ENDPOINT_SIZE, |
| 87 | 108 | .bDescriptorType = USB_DT_ENDPOINT, |
| 88 | 109 | .bEndpointAddress = USB_DIR_IN, |
| 89 | 110 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
| 90 | − .wMaxPacketSize = cpu_to_le16(16), | |
| 111 | + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), | |
| 91 | 112 | .bInterval = 8, |
| 92 | 113 | }; |
| 93 | 114 | |
| @@ -95,7 +116,7 @@ static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { · 1 unmodified line | ||
| 95 | 116 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, |
| 96 | 117 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
| 97 | 118 | .bDescriptorSubType = UVC_EP_INTERRUPT, |
| 98 | − .wMaxTransferSize = cpu_to_le16(16), | |
| 119 | + .wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT), | |
| 99 | 120 | }; |
| 100 | 121 | |
| 101 | 122 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { |
| @@ -122,7 +143,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { · 20 unmodified lines | ||
| 122 | 143 | .iInterface = 0, |
| 123 | 144 | }; |
| 124 | 145 | |
| 125 | −static struct usb_endpoint_descriptor uvc_streaming_ep = { | |
| 146 | +static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { | |
| 126 | 147 | .bLength = USB_DT_ENDPOINT_SIZE, |
| 127 | 148 | .bDescriptorType = USB_DT_ENDPOINT, |
| 128 | 149 | .bEndpointAddress = USB_DIR_IN, |
| @@ -131,15 +152,72 @@ static struct usb_endpoint_descriptor uvc_streaming_ep = { · 2 unmodified lines | ||
| 131 | 152 | .bInterval = 1, |
| 132 | 153 | }; |
| 133 | 154 | |
| 155 | +static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { | |
| 156 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 157 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 158 | + .bEndpointAddress = USB_DIR_IN, | |
| 159 | + .bmAttributes = USB_ENDPOINT_XFER_ISOC, | |
| 160 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 161 | + .bInterval = 1, | |
| 162 | +}; | |
| 163 | + | |
| 164 | +/* super speed support */ | |
| 165 | +static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { | |
| 166 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 167 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 168 | + | |
| 169 | + .bEndpointAddress = USB_DIR_IN, | |
| 170 | + .bmAttributes = USB_ENDPOINT_XFER_INT, | |
| 171 | + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), | |
| 172 | + .bInterval = 8, | |
| 173 | +}; | |
| 174 | + | |
| 175 | +static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { | |
| 176 | + .bLength = sizeof uvc_ss_control_comp, | |
| 177 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 178 | + | |
| 179 | + /* the following 3 values can be tweaked if necessary */ | |
| 180 | + /* .bMaxBurst = 0, */ | |
| 181 | + /* .bmAttributes = 0, */ | |
| 182 | + .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), | |
| 183 | +}; | |
| 184 | + | |
| 185 | +static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | |
| 186 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 187 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 188 | + | |
| 189 | + .bEndpointAddress = USB_DIR_IN, | |
| 190 | + .bmAttributes = USB_ENDPOINT_XFER_ISOC, | |
| 191 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 192 | + .bInterval = 4, | |
| 193 | +}; | |
| 194 | + | |
| 195 | +static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { | |
| 196 | + .bLength = sizeof uvc_ss_streaming_comp, | |
| 197 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 198 | + | |
| 199 | + /* the following 3 values can be tweaked if necessary */ | |
| 200 | + .bMaxBurst = 0, | |
| 201 | + .bmAttributes = 0, | |
| 202 | + .wBytesPerInterval = cpu_to_le16(1024), | |
| 203 | +}; | |
| 204 | + | |
| 134 | 205 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { |
| 135 | 206 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, |
| 136 | − (struct usb_descriptor_header *) &uvc_streaming_ep, | |
| 207 | + (struct usb_descriptor_header *) &uvc_fs_streaming_ep, | |
| 137 | 208 | NULL, |
| 138 | 209 | }; |
| 139 | 210 | |
| 140 | 211 | static const struct usb_descriptor_header * const uvc_hs_streaming[] = { |
| 141 | 212 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, |
| 142 | − (struct usb_descriptor_header *) &uvc_streaming_ep, | |
| 213 | + (struct usb_descriptor_header *) &uvc_hs_streaming_ep, | |
| 214 | + NULL, | |
| 215 | +}; | |
| 216 | + | |
| 217 | +static const struct usb_descriptor_header * const uvc_ss_streaming[] = { | |
| 218 | + (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, | |
| 219 | + (struct usb_descriptor_header *) &uvc_ss_streaming_ep, | |
| 220 | + (struct usb_descriptor_header *) &uvc_ss_streaming_comp, | |
| 143 | 221 | NULL, |
| 144 | 222 | }; |
| 145 | 223 | |
| @@ -215,6 +293,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) · 69 unmodified lines | ||
| 215 | 293 | struct uvc_device *uvc = to_uvc(f); |
| 216 | 294 | struct v4l2_event v4l2_event; |
| 217 | 295 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
| 296 | + int ret; | |
| 218 | 297 | |
| 219 | 298 | INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); |
| 220 | 299 | |
| @@ -262,7 +341,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) · 41 unmodified lines | ||
| 262 | 341 | return 0; |
| 263 | 342 | |
| 264 | 343 | if (uvc->video.ep) { |
| 265 | − uvc->video.ep->desc = &uvc_streaming_ep; | |
| 344 | + ret = config_ep_by_speed(f->config->cdev->gadget, | |
| 345 | + &(uvc->func), uvc->video.ep); | |
| 346 | + if (ret) | |
| 347 | + return ret; | |
| 266 | 348 | usb_ep_enable(uvc->video.ep); |
| 267 | 349 | } |
| 268 | 350 | |
| @@ -368,9 +450,11 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) · 99 unmodified lines | ||
| 368 | 450 | { |
| 369 | 451 | struct uvc_input_header_descriptor *uvc_streaming_header; |
| 370 | 452 | struct uvc_header_descriptor *uvc_control_header; |
| 453 | + const struct uvc_descriptor_header * const *uvc_control_desc; | |
| 371 | 454 | const struct uvc_descriptor_header * const *uvc_streaming_cls; |
| 372 | 455 | const struct usb_descriptor_header * const *uvc_streaming_std; |
| 373 | 456 | const struct usb_descriptor_header * const *src; |
| 457 | + static struct usb_endpoint_descriptor *uvc_control_ep; | |
| 374 | 458 | struct usb_descriptor_header **dst; |
| 375 | 459 | struct usb_descriptor_header **hdr; |
| 376 | 460 | unsigned int control_size; |
| @@ -379,10 +463,29 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) · 2 unmodified lines | ||
| 379 | 463 | unsigned int bytes; |
| 380 | 464 | void *mem; |
| 381 | 465 | |
| 382 | − uvc_streaming_cls = (speed == USB_SPEED_FULL) | |
| 383 | − ? uvc->desc.fs_streaming : uvc->desc.hs_streaming; | |
| 384 | − uvc_streaming_std = (speed == USB_SPEED_FULL) | |
| 385 | − ? uvc_fs_streaming : uvc_hs_streaming; | |
| 466 | + switch (speed) { | |
| 467 | + case USB_SPEED_SUPER: | |
| 468 | + uvc_control_desc = uvc->desc.ss_control; | |
| 469 | + uvc_streaming_cls = uvc->desc.ss_streaming; | |
| 470 | + uvc_streaming_std = uvc_ss_streaming; | |
| 471 | + uvc_control_ep = &uvc_ss_control_ep; | |
| 472 | + break; | |
| 473 | + | |
| 474 | + case USB_SPEED_HIGH: | |
| 475 | + uvc_control_desc = uvc->desc.fs_control; | |
| 476 | + uvc_streaming_cls = uvc->desc.hs_streaming; | |
| 477 | + uvc_streaming_std = uvc_hs_streaming; | |
| 478 | + uvc_control_ep = &uvc_fs_control_ep; | |
| 479 | + break; | |
| 480 | + | |
| 481 | + case USB_SPEED_FULL: | |
| 482 | + default: | |
| 483 | + uvc_control_desc = uvc->desc.fs_control; | |
| 484 | + uvc_streaming_cls = uvc->desc.fs_streaming; | |
| 485 | + uvc_streaming_std = uvc_fs_streaming; | |
| 486 | + uvc_control_ep = &uvc_fs_control_ep; | |
| 487 | + break; | |
| 488 | + } | |
| 386 | 489 | |
| 387 | 490 | /* Descriptors layout |
| 388 | 491 | * |
| @@ -400,16 +503,24 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) · 11 unmodified lines | ||
| 400 | 503 | control_size = 0; |
| 401 | 504 | streaming_size = 0; |
| 402 | 505 | bytes = uvc_iad.bLength + uvc_control_intf.bLength |
| 403 | − + uvc_control_ep.bLength + uvc_control_cs_ep.bLength | |
| 506 | + + uvc_control_ep->bLength + uvc_control_cs_ep.bLength | |
| 404 | 507 | + uvc_streaming_intf_alt0.bLength; |
| 405 | − n_desc = 5; | |
| 406 | 508 | |
| 407 | − for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) { | |
| 509 | + if (speed == USB_SPEED_SUPER) { | |
| 510 | + bytes += uvc_ss_control_comp.bLength; | |
| 511 | + n_desc = 6; | |
| 512 | + } else { | |
| 513 | + n_desc = 5; | |
| 514 | + } | |
| 515 | + | |
| 516 | + for (src = (const struct usb_descriptor_header **)uvc_control_desc; | |
| 517 | + *src; ++src) { | |
| 408 | 518 | control_size += (*src)->bLength; |
| 409 | 519 | bytes += (*src)->bLength; |
| 410 | 520 | n_desc++; |
| 411 | 521 | } |
| 412 | − for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) { | |
| 522 | + for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; | |
| 523 | + *src; ++src) { | |
| 413 | 524 | streaming_size += (*src)->bLength; |
| 414 | 525 | bytes += (*src)->bLength; |
| 415 | 526 | n_desc++; |
| @@ -433,12 +544,15 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) · 17 unmodified lines | ||
| 433 | 544 | |
| 434 | 545 | uvc_control_header = mem; |
| 435 | 546 | UVC_COPY_DESCRIPTORS(mem, dst, |
| 436 | − (const struct usb_descriptor_header**)uvc->desc.control); | |
| 547 | + (const struct usb_descriptor_header **)uvc_control_desc); | |
| 437 | 548 | uvc_control_header->wTotalLength = cpu_to_le16(control_size); |
| 438 | 549 | uvc_control_header->bInCollection = 1; |
| 439 | 550 | uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; |
| 440 | 551 | |
| 441 | − UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); | |
| 552 | + UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep); | |
| 553 | + if (speed == USB_SPEED_SUPER) | |
| 554 | + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); | |
| 555 | + | |
| 442 | 556 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep); |
| 443 | 557 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0); |
| 444 | 558 | |
| @@ -446,7 +560,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) · 1 unmodified line | ||
| 446 | 560 | UVC_COPY_DESCRIPTORS(mem, dst, |
| 447 | 561 | (const struct usb_descriptor_header**)uvc_streaming_cls); |
| 448 | 562 | uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); |
| 449 | − uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress; | |
| 563 | + uvc_streaming_header->bEndpointAddress = | |
| 564 | + uvc_fs_streaming_ep.bEndpointAddress; | |
| 450 | 565 | |
| 451 | 566 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); |
| 452 | 567 | |
| @@ -482,6 +597,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) · 29 unmodified lines | ||
| 482 | 597 | |
| 483 | 598 | kfree(f->descriptors); |
| 484 | 599 | kfree(f->hs_descriptors); |
| 600 | + kfree(f->ss_descriptors); | |
| 485 | 601 | |
| 486 | 602 | kfree(uvc); |
| 487 | 603 | } |
| @@ -496,8 +612,26 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) · 8 unmodified lines | ||
| 496 | 612 | |
| 497 | 613 | INFO(cdev, "uvc_function_bind\n"); |
| 498 | 614 | |
| 615 | + /* sanity check the streaming endpoint module parameters */ | |
| 616 | + if (streaming_interval < 1) | |
| 617 | + streaming_interval = 1; | |
| 618 | + if (streaming_interval > 16) | |
| 619 | + streaming_interval = 16; | |
| 620 | + if (streaming_mult > 2) | |
| 621 | + streaming_mult = 2; | |
| 622 | + if (streaming_maxburst > 15) | |
| 623 | + streaming_maxburst = 15; | |
| 624 | + | |
| 625 | + /* | |
| 626 | + * fill in the FS video streaming specific descriptors from the | |
| 627 | + * module parameters | |
| 628 | + */ | |
| 629 | + uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? | |
| 630 | + 1023 : streaming_maxpacket; | |
| 631 | + uvc_fs_streaming_ep.bInterval = streaming_interval; | |
| 632 | + | |
| 499 | 633 | /* Allocate endpoints. */ |
| 500 | − ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); | |
| 634 | + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); | |
| 501 | 635 | if (!ep) { |
| 502 | 636 | INFO(cdev, "Unable to allocate control EP\n"); |
| 503 | 637 | goto error; |
| @@ -505,7 +639,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) · 1 unmodified line | ||
| 505 | 639 | uvc->control_ep = ep; |
| 506 | 640 | ep->driver_data = uvc; |
| 507 | 641 | |
| 508 | − ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep); | |
| 642 | + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); | |
| 509 | 643 | if (!ep) { |
| 510 | 644 | INFO(cdev, "Unable to allocate streaming EP\n"); |
| 511 | 645 | goto error; |
| @@ -526,9 +660,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) · 14 unmodified lines | ||
| 526 | 660 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; |
| 527 | 661 | uvc->streaming_intf = ret; |
| 528 | 662 | |
| 529 | − /* Copy descriptors. */ | |
| 663 | + /* sanity check the streaming endpoint module parameters */ | |
| 664 | + if (streaming_maxpacket > 1024) | |
| 665 | + streaming_maxpacket = 1024; | |
| 666 | + | |
| 667 | + /* Copy descriptors for FS. */ | |
| 530 | 668 | f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); |
| 531 | − f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); | |
| 669 | + | |
| 670 | + /* support high speed hardware */ | |
| 671 | + if (gadget_is_dualspeed(cdev->gadget)) { | |
| 672 | + /* | |
| 673 | + * Fill in the HS descriptors from the module parameters for the | |
| 674 | + * Video Streaming endpoint. | |
| 675 | + * NOTE: We assume that the user knows what they are doing and | |
| 676 | + * won't give parameters that their UDC doesn't support. | |
| 677 | + */ | |
| 678 | + uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; | |
| 679 | + uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; | |
| 680 | + uvc_hs_streaming_ep.bInterval = streaming_interval; | |
| 681 | + uvc_hs_streaming_ep.bEndpointAddress = | |
| 682 | + uvc_fs_streaming_ep.bEndpointAddress; | |
| 683 | + | |
| 684 | + /* Copy descriptors. */ | |
| 685 | + f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); | |
| 686 | + } | |
| 687 | + | |
| 688 | + /* support super speed hardware */ | |
| 689 | + if (gadget_is_superspeed(c->cdev->gadget)) { | |
| 690 | + /* | |
| 691 | + * Fill in the SS descriptors from the module parameters for the | |
| 692 | + * Video Streaming endpoint. | |
| 693 | + * NOTE: We assume that the user knows what they are doing and | |
| 694 | + * won't give parameters that their UDC doesn't support. | |
| 695 | + */ | |
| 696 | + uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; | |
| 697 | + uvc_ss_streaming_ep.bInterval = streaming_interval; | |
| 698 | + uvc_ss_streaming_comp.bmAttributes = streaming_mult; | |
| 699 | + uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; | |
| 700 | + uvc_ss_streaming_comp.wBytesPerInterval = | |
| 701 | + streaming_maxpacket * (streaming_mult + 1) * | |
| 702 | + (streaming_maxburst + 1); | |
| 703 | + uvc_ss_streaming_ep.bEndpointAddress = | |
| 704 | + uvc_fs_streaming_ep.bEndpointAddress; | |
| 705 | + | |
| 706 | + /* Copy descriptors. */ | |
| 707 | + f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); | |
| 708 | + } | |
| 532 | 709 | |
| 533 | 710 | /* Preallocate control endpoint request. */ |
| 534 | 711 | uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); |
| @@ -583,9 +760,11 @@ error: · 48 unmodified lines | ||
| 583 | 760 | */ |
| 584 | 761 | int __init |
| 585 | 762 | uvc_bind_config(struct usb_configuration *c, |
| 586 | − const struct uvc_descriptor_header * const *control, | |
| 763 | + const struct uvc_descriptor_header * const *fs_control, | |
| 764 | + const struct uvc_descriptor_header * const *ss_control, | |
| 587 | 765 | const struct uvc_descriptor_header * const *fs_streaming, |
| 588 | − const struct uvc_descriptor_header * const *hs_streaming) | |
| 766 | + const struct uvc_descriptor_header * const *hs_streaming, | |
| 767 | + const struct uvc_descriptor_header * const *ss_streaming) | |
| 589 | 768 | { |
| 590 | 769 | struct uvc_device *uvc; |
| 591 | 770 | int ret = 0; |
| @@ -603,38 +782,54 @@ uvc_bind_config(struct usb_configuration *c, · 11 unmodified lines | ||
| 603 | 782 | uvc->state = UVC_STATE_DISCONNECTED; |
| 604 | 783 | |
| 605 | 784 | /* Validate the descriptors. */ |
| 606 | − if (control == NULL || control[0] == NULL || | |
| 607 | − control[0]->bDescriptorSubType != UVC_VC_HEADER) | |
| 785 | + if (fs_control == NULL || fs_control[0] == NULL || | |
| 786 | + fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) | |
| 608 | 787 | goto error; |
| 609 | 788 | |
| 610 | − if (fs_streaming == NULL || fs_streaming[0] == NULL || | |
| 611 | − fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | |
| 789 | + if (ss_control == NULL || ss_control[0] == NULL || | |
| 790 | + ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) | |
| 612 | 791 | goto error; |
| 613 | 792 | |
| 614 | − if (hs_streaming == NULL || hs_streaming[0] == NULL || | |
| 615 | − hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | |
| 793 | + if (fs_streaming == NULL || fs_streaming[0] == NULL || | |
| 794 | + fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | |
| 616 | 795 | goto error; |
| 617 | 796 | |
| 618 | − uvc->desc.control = control; | |
| 619 | − uvc->desc.fs_streaming = fs_streaming; | |
| 620 | − uvc->desc.hs_streaming = hs_streaming; | |
| 621 | − | |
| 622 | − /* Allocate string descriptor numbers. */ | |
| 623 | − if ((ret = usb_string_id(c->cdev)) < 0) | |
| 797 | + if (hs_streaming == NULL || hs_streaming[0] == NULL || | |
| 798 | + hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | |
| 624 | 799 | goto error; |
| 625 | − uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; | |
| 626 | − uvc_iad.iFunction = ret; | |
| 627 | 800 | |
| 628 | − if ((ret = usb_string_id(c->cdev)) < 0) | |
| 801 | + if (ss_streaming == NULL || ss_streaming[0] == NULL || | |
| 802 | + ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | |
| 629 | 803 | goto error; |
| 630 | − uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; | |
| 631 | − uvc_control_intf.iInterface = ret; | |
| 632 | 804 | |
| 633 | − if ((ret = usb_string_id(c->cdev)) < 0) | |
| 634 | − goto error; | |
| 635 | − uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; | |
| 636 | − uvc_streaming_intf_alt0.iInterface = ret; | |
| 637 | − uvc_streaming_intf_alt1.iInterface = ret; | |
| 805 | + uvc->desc.fs_control = fs_control; | |
| 806 | + uvc->desc.ss_control = ss_control; | |
| 807 | + uvc->desc.fs_streaming = fs_streaming; | |
| 808 | + uvc->desc.hs_streaming = hs_streaming; | |
| 809 | + uvc->desc.ss_streaming = ss_streaming; | |
| 810 | + | |
| 811 | + /* maybe allocate device-global string IDs, and patch descriptors */ | |
| 812 | + if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { | |
| 813 | + /* Allocate string descriptor numbers. */ | |
| 814 | + ret = usb_string_id(c->cdev); | |
| 815 | + if (ret < 0) | |
| 816 | + goto error; | |
| 817 | + uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; | |
| 818 | + uvc_iad.iFunction = ret; | |
| 819 | + | |
| 820 | + ret = usb_string_id(c->cdev); | |
| 821 | + if (ret < 0) | |
| 822 | + goto error; | |
| 823 | + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; | |
| 824 | + uvc_control_intf.iInterface = ret; | |
| 825 | + | |
| 826 | + ret = usb_string_id(c->cdev); | |
| 827 | + if (ret < 0) | |
| 828 | + goto error; | |
| 829 | + uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; | |
| 830 | + uvc_streaming_intf_alt0.iInterface = ret; | |
| 831 | + uvc_streaming_intf_alt1.iInterface = ret; | |
| 832 | + } | |
| 638 | 833 | |
| 639 | 834 | /* Register the function. */ |
| 640 | 835 | uvc->func.name = "uvc"; |
| @@ -17,9 +17,11 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/usb/video.h> |
| 18 | 18 | |
| 19 | 19 | extern int uvc_bind_config(struct usb_configuration *c, |
| 20 | − const struct uvc_descriptor_header * const *control, | |
| 21 | − const struct uvc_descriptor_header * const *fs_streaming, | |
| 22 | − const struct uvc_descriptor_header * const *hs_streaming); | |
| 20 | + const struct uvc_descriptor_header * const *fs_control, | |
| 21 | + const struct uvc_descriptor_header * const *hs_control, | |
| 22 | + const struct uvc_descriptor_header * const *fs_streaming, | |
| 23 | + const struct uvc_descriptor_header * const *hs_streaming, | |
| 24 | + const struct uvc_descriptor_header * const *ss_streaming); | |
| 23 | 25 | |
| 24 | 26 | #endif /* _F_UVC_H_ */ |
| 25 | 27 | |
| @@ -21,7 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <mach/hardware.h> |
| 22 | 22 | |
| 23 | 23 | static struct clk *mxc_ahb_clk; |
| 24 | −static struct clk *mxc_usb_clk; | |
| 24 | +static struct clk *mxc_per_clk; | |
| 25 | +static struct clk *mxc_ipg_clk; | |
| 25 | 26 | |
| 26 | 27 | /* workaround ENGcm09152 for i.MX35 */ |
| 27 | 28 | #define USBPHYCTRL_OTGBASE_OFFSET 0x608 |
| @@ -35,28 +36,31 @@ int fsl_udc_clk_init(struct platform_device *pdev) · 7 unmodified lines | ||
| 35 | 36 | |
| 36 | 37 | pdata = pdev->dev.platform_data; |
| 37 | 38 | |
| 38 | − if (!cpu_is_mx35() && !cpu_is_mx25()) { | |
| 39 | − mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb"); | |
| 40 | − if (IS_ERR(mxc_ahb_clk)) | |
| 41 | − return PTR_ERR(mxc_ahb_clk); | |
| 39 | + mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg"); | |
| 40 | + if (IS_ERR(mxc_ipg_clk)) { | |
| 41 | + dev_err(&pdev->dev, "clk_get(\"ipg\") failed\n"); | |
| 42 | + return PTR_ERR(mxc_ipg_clk); | |
| 43 | + } | |
| 42 | 44 | |
| 43 | − ret = clk_enable(mxc_ahb_clk); | |
| 44 | − if (ret < 0) { | |
| 45 | − dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n"); | |
| 46 | − goto eenahb; | |
| 47 | − } | |
| 45 | + mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb"); | |
| 46 | + if (IS_ERR(mxc_ahb_clk)) { | |
| 47 | + dev_err(&pdev->dev, "clk_get(\"ahb\") failed\n"); | |
| 48 | + return PTR_ERR(mxc_ahb_clk); | |
| 48 | 49 | } |
| 49 | 50 | |
| 50 | − /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ | |
| 51 | − mxc_usb_clk = clk_get(&pdev->dev, "usb"); | |
| 52 | − if (IS_ERR(mxc_usb_clk)) { | |
| 53 | − dev_err(&pdev->dev, "clk_get(\"usb\") failed\n"); | |
| 54 | − ret = PTR_ERR(mxc_usb_clk); | |
| 55 | − goto egusb; | |
| 51 | + mxc_per_clk = devm_clk_get(&pdev->dev, "per"); | |
| 52 | + if (IS_ERR(mxc_per_clk)) { | |
| 53 | + dev_err(&pdev->dev, "clk_get(\"per\") failed\n"); | |
| 54 | + return PTR_ERR(mxc_per_clk); | |
| 56 | 55 | } |
| 57 | 56 | |
| 57 | + clk_prepare_enable(mxc_ipg_clk); | |
| 58 | + clk_prepare_enable(mxc_ahb_clk); | |
| 59 | + clk_prepare_enable(mxc_per_clk); | |
| 60 | + | |
| 61 | + /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ | |
| 58 | 62 | if (!cpu_is_mx51()) { |
| 59 | − freq = clk_get_rate(mxc_usb_clk); | |
| 63 | + freq = clk_get_rate(mxc_per_clk); | |
| 60 | 64 | if (pdata->phy_mode != FSL_USB2_PHY_ULPI && |
| 61 | 65 | (freq < 59999000 || freq > 60001000)) { |
| 62 | 66 | dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq); |
| @@ -65,24 +69,13 @@ int fsl_udc_clk_init(struct platform_device *pdev) · 2 unmodified lines | ||
| 65 | 69 | } |
| 66 | 70 | } |
| 67 | 71 | |
| 68 | − ret = clk_enable(mxc_usb_clk); | |
| 69 | − if (ret < 0) { | |
| 70 | − dev_err(&pdev->dev, "clk_enable(\"usb_clk\") failed\n"); | |
| 71 | − goto eenusb; | |
| 72 | − } | |
| 73 | − | |
| 74 | 72 | return 0; |
| 75 | 73 | |
| 76 | −eenusb: | |
| 77 | 74 | eclkrate: |
| 78 | − clk_put(mxc_usb_clk); | |
| 79 | − mxc_usb_clk = NULL; | |
| 80 | −egusb: | |
| 81 | − if (!cpu_is_mx35()) | |
| 82 | − clk_disable(mxc_ahb_clk); | |
| 83 | −eenahb: | |
| 84 | − if (!cpu_is_mx35()) | |
| 85 | − clk_put(mxc_ahb_clk); | |
| 75 | + clk_disable_unprepare(mxc_ipg_clk); | |
| 76 | + clk_disable_unprepare(mxc_ahb_clk); | |
| 77 | + clk_disable_unprepare(mxc_per_clk); | |
| 78 | + mxc_per_clk = NULL; | |
| 86 | 79 | return ret; |
| 87 | 80 | } |
| 88 | 81 | |
| @@ -104,20 +97,15 @@ void fsl_udc_clk_finalize(struct platform_device *pdev) · 15 unmodified lines | ||
| 104 | 97 | |
| 105 | 98 | /* ULPI transceivers don't need usbpll */ |
| 106 | 99 | if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { |
| 107 | − clk_disable(mxc_usb_clk); | |
| 108 | − clk_put(mxc_usb_clk); | |
| 109 | − mxc_usb_clk = NULL; | |
| 100 | + clk_disable_unprepare(mxc_per_clk); | |
| 101 | + mxc_per_clk = NULL; | |
| 110 | 102 | } |
| 111 | 103 | } |
| 112 | 104 | |
| 113 | 105 | void fsl_udc_clk_release(void) |
| 114 | 106 | { |
| 115 | − if (mxc_usb_clk) { | |
| 116 | − clk_disable(mxc_usb_clk); | |
| 117 | − clk_put(mxc_usb_clk); | |
| 118 | − } | |
| 119 | − if (!cpu_is_mx35()) { | |
| 120 | − clk_disable(mxc_ahb_clk); | |
| 121 | − clk_put(mxc_ahb_clk); | |
| 122 | − } | |
| 107 | + if (mxc_per_clk) | |
| 108 | + clk_disable_unprepare(mxc_per_clk); | |
| 109 | + clk_disable_unprepare(mxc_ahb_clk); | |
| 110 | + clk_disable_unprepare(mxc_ipg_clk); | |
| 123 | 111 | } |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/ioport.h> |
| 25 | 25 | #include <linux/types.h> |
| 26 | 26 | #include <linux/errno.h> |
| 27 | +#include <linux/err.h> | |
| 27 | 28 | #include <linux/slab.h> |
| 28 | 29 | #include <linux/init.h> |
| 29 | 30 | #include <linux/list.h> |
| @@ -1229,7 +1230,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) · 1199 unmodified lines | ||
| 1229 | 1230 | struct fsl_udc *udc; |
| 1230 | 1231 | |
| 1231 | 1232 | udc = container_of(gadget, struct fsl_udc, gadget); |
| 1232 | − if (udc->transceiver) | |
| 1233 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1233 | 1234 | return usb_phy_set_power(udc->transceiver, mA); |
| 1234 | 1235 | return -ENOTSUPP; |
| 1235 | 1236 | } |
| @@ -1983,13 +1984,13 @@ static int fsl_start(struct usb_gadget_driver *driver, · 747 unmodified lines | ||
| 1983 | 1984 | goto out; |
| 1984 | 1985 | } |
| 1985 | 1986 | |
| 1986 | − if (udc_controller->transceiver) { | |
| 1987 | + if (!IS_ERR_OR_NULL(udc_controller->transceiver)) { | |
| 1987 | 1988 | /* Suspend the controller until OTG enable it */ |
| 1988 | 1989 | udc_controller->stopped = 1; |
| 1989 | 1990 | printk(KERN_INFO "Suspend udc for OTG auto detect\n"); |
| 1990 | 1991 | |
| 1991 | 1992 | /* connect to bus through transceiver */ |
| 1992 | − if (udc_controller->transceiver) { | |
| 1993 | + if (!IS_ERR_OR_NULL(udc_controller->transceiver)) { | |
| 1993 | 1994 | retval = otg_set_peripheral( |
| 1994 | 1995 | udc_controller->transceiver->otg, |
| 1995 | 1996 | &udc_controller->gadget); |
| @@ -2030,7 +2031,7 @@ static int fsl_stop(struct usb_gadget_driver *driver) · 34 unmodified lines | ||
| 2030 | 2031 | if (!driver || driver != udc_controller->driver || !driver->unbind) |
| 2031 | 2032 | return -EINVAL; |
| 2032 | 2033 | |
| 2033 | − if (udc_controller->transceiver) | |
| 2034 | + if (!IS_ERR_OR_NULL(udc_controller->transceiver)) | |
| 2034 | 2035 | otg_set_peripheral(udc_controller->transceiver->otg, NULL); |
| 2035 | 2036 | |
| 2036 | 2037 | /* stop DR, disable intr */ |
| @@ -2455,8 +2456,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev) · 418 unmodified lines | ||
| 2455 | 2456 | |
| 2456 | 2457 | #ifdef CONFIG_USB_OTG |
| 2457 | 2458 | if (pdata->operating_mode == FSL_USB2_DR_OTG) { |
| 2458 | − udc_controller->transceiver = usb_get_transceiver(); | |
| 2459 | − if (!udc_controller->transceiver) { | |
| 2459 | + udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2460 | + if (IS_ERR_OR_NULL(udc_controller->transceiver)) { | |
| 2460 | 2461 | ERR("Can't find OTG driver!\n"); |
| 2461 | 2462 | ret = -ENODEV; |
| 2462 | 2463 | goto err_kfree; |
| @@ -2540,7 +2541,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) · 77 unmodified lines | ||
| 2540 | 2541 | goto err_free_irq; |
| 2541 | 2542 | } |
| 2542 | 2543 | |
| 2543 | − if (!udc_controller->transceiver) { | |
| 2544 | + if (IS_ERR_OR_NULL(udc_controller->transceiver)) { | |
| 2544 | 2545 | /* initialize usb hw reg except for regs for EP, |
| 2545 | 2546 | * leave usbintr reg untouched */ |
| 2546 | 2547 | dr_controller_setup(udc_controller); |
| @@ -2560,11 +2561,12 @@ static int __init fsl_udc_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 2560 | 2561 | dev_set_name(&udc_controller->gadget.dev, "gadget"); |
| 2561 | 2562 | udc_controller->gadget.dev.release = fsl_udc_release; |
| 2562 | 2563 | udc_controller->gadget.dev.parent = &pdev->dev; |
| 2564 | + udc_controller->gadget.dev.of_node = pdev->dev.of_node; | |
| 2563 | 2565 | ret = device_register(&udc_controller->gadget.dev); |
| 2564 | 2566 | if (ret < 0) |
| 2565 | 2567 | goto err_free_irq; |
| 2566 | 2568 | |
| 2567 | − if (udc_controller->transceiver) | |
| 2569 | + if (!IS_ERR_OR_NULL(udc_controller->transceiver)) | |
| 2568 | 2570 | udc_controller->gadget.is_otg = 1; |
| 2569 | 2571 | |
| 2570 | 2572 | /* setup QH and epctrl for ep0 */ |
| @@ -1432,7 +1432,7 @@ static int __init imx_udc_probe(struct platform_device *pdev) · 1431 unmodified lines | ||
| 1432 | 1432 | dev_err(&pdev->dev, "can't get USB clock\n"); |
| 1433 | 1433 | goto fail2; |
| 1434 | 1434 | } |
| 1435 | − clk_enable(clk); | |
| 1435 | + clk_prepare_enable(clk); | |
| 1436 | 1436 | |
| 1437 | 1437 | if (clk_get_rate(clk) != 48000000) { |
| 1438 | 1438 | D_INI(&pdev->dev, |
| @@ -1496,7 +1496,7 @@ fail4: · 57 unmodified lines | ||
| 1496 | 1496 | free_irq(imx_usb->usbd_int[i], imx_usb); |
| 1497 | 1497 | fail3: |
| 1498 | 1498 | clk_put(clk); |
| 1499 | − clk_disable(clk); | |
| 1499 | + clk_disable_unprepare(clk); | |
| 1500 | 1500 | fail2: |
| 1501 | 1501 | iounmap(base); |
| 1502 | 1502 | fail1: |
| @@ -1521,7 +1521,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) · 18 unmodified lines | ||
| 1521 | 1521 | free_irq(imx_usb->usbd_int[i], imx_usb); |
| 1522 | 1522 | |
| 1523 | 1523 | clk_put(imx_usb->clk); |
| 1524 | − clk_disable(imx_usb->clk); | |
| 1524 | + clk_disable_unprepare(imx_usb->clk); | |
| 1525 | 1525 | iounmap(imx_usb->base); |
| 1526 | 1526 | |
| 1527 | 1527 | release_mem_region(imx_usb->res->start, resource_size(imx_usb->res)); |
| @@ -165,6 +165,7 @@ struct lpc32xx_udc { · 164 unmodified lines | ||
| 165 | 165 | int udp_irq[4]; |
| 166 | 166 | struct clk *usb_pll_clk; |
| 167 | 167 | struct clk *usb_slv_clk; |
| 168 | + struct clk *usb_otg_clk; | |
| 168 | 169 | |
| 169 | 170 | /* DMA support */ |
| 170 | 171 | u32 *udca_v_base; |
| @@ -227,33 +228,15 @@ static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g) · 56 unmodified lines | ||
| 227 | 228 | #define UDCA_BUFF_SIZE (128) |
| 228 | 229 | |
| 229 | 230 | /* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will |
| 230 | − * be replaced with an inremap()ed pointer, see USB_OTG_CLK_CTRL() | |
| 231 | + * be replaced with an inremap()ed pointer | |
| 231 | 232 | * */ |
| 232 | 233 | #define USB_CTRL IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64) |
| 233 | −#define USB_CLOCK_MASK (AHB_M_CLOCK_ON | OTG_CLOCK_ON | \ | |
| 234 | − DEV_CLOCK_ON | I2C_CLOCK_ON) | |
| 235 | 234 | |
| 236 | 235 | /* USB_CTRL bit defines */ |
| 237 | 236 | #define USB_SLAVE_HCLK_EN (1 << 24) |
| 238 | 237 | #define USB_HOST_NEED_CLK_EN (1 << 21) |
| 239 | 238 | #define USB_DEV_NEED_CLK_EN (1 << 22) |
| 240 | 239 | |
| 241 | −#define USB_OTG_CLK_CTRL(udc) ((udc)->udp_baseaddr + 0xFF4) | |
| 242 | −#define USB_OTG_CLK_STAT(udc) ((udc)->udp_baseaddr + 0xFF8) | |
| 243 | − | |
| 244 | −/* USB_OTG_CLK_CTRL bit defines */ | |
| 245 | −#define AHB_M_CLOCK_ON (1 << 4) | |
| 246 | −#define OTG_CLOCK_ON (1 << 3) | |
| 247 | −#define I2C_CLOCK_ON (1 << 2) | |
| 248 | −#define DEV_CLOCK_ON (1 << 1) | |
| 249 | −#define HOST_CLOCK_ON (1 << 0) | |
| 250 | − | |
| 251 | −#define USB_OTG_STAT_CONTROL(udc) (udc->udp_baseaddr + 0x110) | |
| 252 | − | |
| 253 | −/* USB_OTG_STAT_CONTROL bit defines */ | |
| 254 | −#define TRANSPARENT_I2C_EN (1 << 7) | |
| 255 | −#define HOST_EN (1 << 0) | |
| 256 | − | |
| 257 | 240 | /********************************************************************** |
| 258 | 241 | * USB device controller register offsets |
| 259 | 242 | **********************************************************************/ |
| @@ -677,7 +660,7 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) · 417 unmodified lines | ||
| 677 | 660 | ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD); |
| 678 | 661 | |
| 679 | 662 | /* Enable usb_need_clk clock after transceiver is initialized */ |
| 680 | − writel((readl(USB_CTRL) | (1 << 22)), USB_CTRL); | |
| 663 | + writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL); | |
| 681 | 664 | |
| 682 | 665 | dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n", |
| 683 | 666 | i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00)); |
| @@ -1010,11 +993,8 @@ static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd) · 326 unmodified lines | ||
| 1010 | 993 | /* Enables or disables most of the USB system clocks when low power mode is |
| 1011 | 994 | * needed. Clocks are typically started on a connection event, and disabled |
| 1012 | 995 | * when a cable is disconnected */ |
| 1013 | −#define OTGOFF_CLK_MASK (AHB_M_CLOCK_ON | I2C_CLOCK_ON) | |
| 1014 | 996 | static void udc_clk_set(struct lpc32xx_udc *udc, int enable) |
| 1015 | 997 | { |
| 1016 | − int to = 1000; | |
| 1017 | − | |
| 1018 | 998 | if (enable != 0) { |
| 1019 | 999 | if (udc->clocked) |
| 1020 | 1000 | return; |
| @@ -1028,14 +1008,7 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) · 7 unmodified lines | ||
| 1028 | 1008 | writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, |
| 1029 | 1009 | USB_CTRL); |
| 1030 | 1010 | |
| 1031 | − /* Set to enable all needed USB OTG clocks */ | |
| 1032 | − writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc)); | |
| 1033 | − | |
| 1034 | − while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) != | |
| 1035 | − USB_CLOCK_MASK) && (to > 0)) | |
| 1036 | − to--; | |
| 1037 | − if (!to) | |
| 1038 | − dev_dbg(udc->dev, "Cannot enable USB OTG clocking\n"); | |
| 1011 | + clk_enable(udc->usb_otg_clk); | |
| 1039 | 1012 | } else { |
| 1040 | 1013 | if (!udc->clocked) |
| 1041 | 1014 | return; |
| @@ -1047,19 +1020,11 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) · 5 unmodified lines | ||
| 1047 | 1020 | /* 48MHz PLL dpwn */ |
| 1048 | 1021 | clk_disable(udc->usb_pll_clk); |
| 1049 | 1022 | |
| 1050 | − /* Enable the USB device clock */ | |
| 1023 | + /* Disable the USB device clock */ | |
| 1051 | 1024 | writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN, |
| 1052 | 1025 | USB_CTRL); |
| 1053 | 1026 | |
| 1054 | − /* Set to enable all needed USB OTG clocks */ | |
| 1055 | − writel(OTGOFF_CLK_MASK, USB_OTG_CLK_CTRL(udc)); | |
| 1056 | − | |
| 1057 | − while (((readl(USB_OTG_CLK_STAT(udc)) & | |
| 1058 | − OTGOFF_CLK_MASK) != | |
| 1059 | − OTGOFF_CLK_MASK) && (to > 0)) | |
| 1060 | − to--; | |
| 1061 | − if (!to) | |
| 1062 | − dev_dbg(udc->dev, "Cannot disable USB OTG clocking\n"); | |
| 1027 | + clk_disable(udc->usb_otg_clk); | |
| 1063 | 1028 | } |
| 1064 | 1029 | } |
| 1065 | 1030 | |
| @@ -3041,6 +3006,7 @@ static int lpc32xx_start(struct usb_gadget_driver *driver, · 1975 unmodified lines | ||
| 3041 | 3006 | |
| 3042 | 3007 | udc->driver = driver; |
| 3043 | 3008 | udc->gadget.dev.driver = &driver->driver; |
| 3009 | + udc->gadget.dev.of_node = udc->dev->of_node; | |
| 3044 | 3010 | udc->enabled = 1; |
| 3045 | 3011 | udc->selfpowered = 1; |
| 3046 | 3012 | udc->vbus = 0; |
| @@ -3239,6 +3205,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) · 192 unmodified lines | ||
| 3239 | 3205 | retval = PTR_ERR(udc->usb_slv_clk); |
| 3240 | 3206 | goto usb_clk_get_fail; |
| 3241 | 3207 | } |
| 3208 | + udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); | |
| 3209 | + if (IS_ERR(udc->usb_otg_clk)) { | |
| 3210 | + dev_err(udc->dev, "failed to acquire USB otg clock\n"); | |
| 3211 | + retval = PTR_ERR(udc->usb_slv_clk); | |
| 3212 | + goto usb_otg_clk_get_fail; | |
| 3213 | + } | |
| 3242 | 3214 | |
| 3243 | 3215 | /* Setup PLL clock to 48MHz */ |
| 3244 | 3216 | retval = clk_enable(udc->usb_pll_clk); |
| @@ -3262,15 +3234,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 3262 | 3234 | goto usb_clk_enable_fail; |
| 3263 | 3235 | } |
| 3264 | 3236 | |
| 3265 | − /* Set to enable all needed USB OTG clocks */ | |
| 3266 | − writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc)); | |
| 3267 | − | |
| 3268 | − i = 1000; | |
| 3269 | − while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) != | |
| 3270 | − USB_CLOCK_MASK) && (i > 0)) | |
| 3271 | − i--; | |
| 3272 | − if (!i) | |
| 3273 | − dev_dbg(udc->dev, "USB OTG clocks not correctly enabled\n"); | |
| 3237 | + /* Enable USB OTG clock */ | |
| 3238 | + retval = clk_enable(udc->usb_otg_clk); | |
| 3239 | + if (retval < 0) { | |
| 3240 | + dev_err(udc->dev, "failed to start USB otg clock\n"); | |
| 3241 | + goto usb_otg_clk_enable_fail; | |
| 3242 | + } | |
| 3274 | 3243 | |
| 3275 | 3244 | /* Setup deferred workqueue data */ |
| 3276 | 3245 | udc->poweron = udc->pullup = 0; |
| @@ -3390,12 +3359,16 @@ dma_alloc_fail: · 113 unmodified lines | ||
| 3390 | 3359 | dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, |
| 3391 | 3360 | udc->udca_v_base, udc->udca_p_base); |
| 3392 | 3361 | i2c_fail: |
| 3362 | + clk_disable(udc->usb_otg_clk); | |
| 3363 | +usb_otg_clk_enable_fail: | |
| 3393 | 3364 | clk_disable(udc->usb_slv_clk); |
| 3394 | 3365 | usb_clk_enable_fail: |
| 3395 | 3366 | pll_set_fail: |
| 3396 | 3367 | clk_disable(udc->usb_pll_clk); |
| 3397 | 3368 | pll_enable_fail: |
| 3398 | 3369 | clk_put(udc->usb_slv_clk); |
| 3370 | +usb_otg_clk_get_fail: | |
| 3371 | + clk_put(udc->usb_otg_clk); | |
| 3399 | 3372 | usb_clk_get_fail: |
| 3400 | 3373 | clk_put(udc->usb_pll_clk); |
| 3401 | 3374 | pll_get_fail: |
| @@ -3433,6 +3406,8 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev) · 31 unmodified lines | ||
| 3433 | 3406 | |
| 3434 | 3407 | device_unregister(&udc->gadget.dev); |
| 3435 | 3408 | |
| 3409 | + clk_disable(udc->usb_otg_clk); | |
| 3410 | + clk_put(udc->usb_otg_clk); | |
| 3436 | 3411 | clk_disable(udc->usb_slv_clk); |
| 3437 | 3412 | clk_put(udc->usb_slv_clk); |
| 3438 | 3413 | clk_disable(udc->usb_pll_clk); |
| @@ -3446,7 +3421,6 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev) · 7 unmodified lines | ||
| 3446 | 3421 | #ifdef CONFIG_PM |
| 3447 | 3422 | static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg) |
| 3448 | 3423 | { |
| 3449 | − int to = 1000; | |
| 3450 | 3424 | struct lpc32xx_udc *udc = platform_get_drvdata(pdev); |
| 3451 | 3425 | |
| 3452 | 3426 | if (udc->clocked) { |
| @@ -3461,15 +3435,6 @@ static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg) · 8 unmodified lines | ||
| 3461 | 3435 | on resume */ |
| 3462 | 3436 | udc->clocked = 1; |
| 3463 | 3437 | |
| 3464 | − /* Kill OTG and I2C clocks */ | |
| 3465 | − writel(0, USB_OTG_CLK_CTRL(udc)); | |
| 3466 | − while (((readl(USB_OTG_CLK_STAT(udc)) & OTGOFF_CLK_MASK) != | |
| 3467 | − OTGOFF_CLK_MASK) && (to > 0)) | |
| 3468 | − to--; | |
| 3469 | − if (!to) | |
| 3470 | − dev_dbg(udc->dev, | |
| 3471 | − "USB OTG clocks not correctly enabled\n"); | |
| 3472 | − | |
| 3473 | 3438 | /* Kill global USB clock */ |
| 3474 | 3439 | clk_disable(udc->usb_slv_clk); |
| 3475 | 3440 | } |
| @@ -0,0 +1,320 @@ | ||
| 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 and conditions of the GNU General Public License, | |
| 6 | + * version 2, as published by the Free Software Foundation. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef __MV_U3D_H | |
| 10 | +#define __MV_U3D_H | |
| 11 | + | |
| 12 | +#define MV_U3D_EP_CONTEXT_ALIGNMENT 32 | |
| 13 | +#define MV_U3D_TRB_ALIGNMENT 16 | |
| 14 | +#define MV_U3D_DMA_BOUNDARY 4096 | |
| 15 | +#define MV_U3D_EP0_MAX_PKT_SIZE 512 | |
| 16 | + | |
| 17 | +/* ep0 transfer state */ | |
| 18 | +#define MV_U3D_WAIT_FOR_SETUP 0 | |
| 19 | +#define MV_U3D_DATA_STATE_XMIT 1 | |
| 20 | +#define MV_U3D_DATA_STATE_NEED_ZLP 2 | |
| 21 | +#define MV_U3D_WAIT_FOR_OUT_STATUS 3 | |
| 22 | +#define MV_U3D_DATA_STATE_RECV 4 | |
| 23 | +#define MV_U3D_STATUS_STAGE 5 | |
| 24 | + | |
| 25 | +#define MV_U3D_EP_MAX_LENGTH_TRANSFER 0x10000 | |
| 26 | + | |
| 27 | +/* USB3 Interrupt Status */ | |
| 28 | +#define MV_U3D_USBINT_SETUP 0x00000001 | |
| 29 | +#define MV_U3D_USBINT_RX_COMPLETE 0x00000002 | |
| 30 | +#define MV_U3D_USBINT_TX_COMPLETE 0x00000004 | |
| 31 | +#define MV_U3D_USBINT_UNDER_RUN 0x00000008 | |
| 32 | +#define MV_U3D_USBINT_RXDESC_ERR 0x00000010 | |
| 33 | +#define MV_U3D_USBINT_TXDESC_ERR 0x00000020 | |
| 34 | +#define MV_U3D_USBINT_RX_TRB_COMPLETE 0x00000040 | |
| 35 | +#define MV_U3D_USBINT_TX_TRB_COMPLETE 0x00000080 | |
| 36 | +#define MV_U3D_USBINT_VBUS_VALID 0x00010000 | |
| 37 | +#define MV_U3D_USBINT_STORAGE_CMD_FULL 0x00020000 | |
| 38 | +#define MV_U3D_USBINT_LINK_CHG 0x01000000 | |
| 39 | + | |
| 40 | +/* USB3 Interrupt Enable */ | |
| 41 | +#define MV_U3D_INTR_ENABLE_SETUP 0x00000001 | |
| 42 | +#define MV_U3D_INTR_ENABLE_RX_COMPLETE 0x00000002 | |
| 43 | +#define MV_U3D_INTR_ENABLE_TX_COMPLETE 0x00000004 | |
| 44 | +#define MV_U3D_INTR_ENABLE_UNDER_RUN 0x00000008 | |
| 45 | +#define MV_U3D_INTR_ENABLE_RXDESC_ERR 0x00000010 | |
| 46 | +#define MV_U3D_INTR_ENABLE_TXDESC_ERR 0x00000020 | |
| 47 | +#define MV_U3D_INTR_ENABLE_RX_TRB_COMPLETE 0x00000040 | |
| 48 | +#define MV_U3D_INTR_ENABLE_TX_TRB_COMPLETE 0x00000080 | |
| 49 | +#define MV_U3D_INTR_ENABLE_RX_BUFFER_ERR 0x00000100 | |
| 50 | +#define MV_U3D_INTR_ENABLE_VBUS_VALID 0x00010000 | |
| 51 | +#define MV_U3D_INTR_ENABLE_STORAGE_CMD_FULL 0x00020000 | |
| 52 | +#define MV_U3D_INTR_ENABLE_LINK_CHG 0x01000000 | |
| 53 | +#define MV_U3D_INTR_ENABLE_PRIME_STATUS 0x02000000 | |
| 54 | + | |
| 55 | +/* USB3 Link Change */ | |
| 56 | +#define MV_U3D_LINK_CHANGE_LINK_UP 0x00000001 | |
| 57 | +#define MV_U3D_LINK_CHANGE_SUSPEND 0x00000002 | |
| 58 | +#define MV_U3D_LINK_CHANGE_RESUME 0x00000004 | |
| 59 | +#define MV_U3D_LINK_CHANGE_WRESET 0x00000008 | |
| 60 | +#define MV_U3D_LINK_CHANGE_HRESET 0x00000010 | |
| 61 | +#define MV_U3D_LINK_CHANGE_VBUS_INVALID 0x00000020 | |
| 62 | +#define MV_U3D_LINK_CHANGE_INACT 0x00000040 | |
| 63 | +#define MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0 0x00000080 | |
| 64 | +#define MV_U3D_LINK_CHANGE_U1 0x00000100 | |
| 65 | +#define MV_U3D_LINK_CHANGE_U2 0x00000200 | |
| 66 | +#define MV_U3D_LINK_CHANGE_U3 0x00000400 | |
| 67 | + | |
| 68 | +/* bridge setting */ | |
| 69 | +#define MV_U3D_BRIDGE_SETTING_VBUS_VALID (1 << 16) | |
| 70 | + | |
| 71 | +/* Command Register Bit Masks */ | |
| 72 | +#define MV_U3D_CMD_RUN_STOP 0x00000001 | |
| 73 | +#define MV_U3D_CMD_CTRL_RESET 0x00000002 | |
| 74 | + | |
| 75 | +/* ep control register */ | |
| 76 | +#define MV_U3D_EPXCR_EP_TYPE_CONTROL 0 | |
| 77 | +#define MV_U3D_EPXCR_EP_TYPE_ISOC 1 | |
| 78 | +#define MV_U3D_EPXCR_EP_TYPE_BULK 2 | |
| 79 | +#define MV_U3D_EPXCR_EP_TYPE_INT 3 | |
| 80 | +#define MV_U3D_EPXCR_EP_ENABLE_SHIFT 4 | |
| 81 | +#define MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT 12 | |
| 82 | +#define MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT 16 | |
| 83 | +#define MV_U3D_USB_BULK_BURST_OUT 6 | |
| 84 | +#define MV_U3D_USB_BULK_BURST_IN 14 | |
| 85 | + | |
| 86 | +#define MV_U3D_EPXCR_EP_FLUSH (1 << 7) | |
| 87 | +#define MV_U3D_EPXCR_EP_HALT (1 << 1) | |
| 88 | +#define MV_U3D_EPXCR_EP_INIT (1) | |
| 89 | + | |
| 90 | +/* TX/RX Status Register */ | |
| 91 | +#define MV_U3D_XFERSTATUS_COMPLETE_SHIFT 24 | |
| 92 | +#define MV_U3D_COMPLETE_INVALID 0 | |
| 93 | +#define MV_U3D_COMPLETE_SUCCESS 1 | |
| 94 | +#define MV_U3D_COMPLETE_BUFF_ERR 2 | |
| 95 | +#define MV_U3D_COMPLETE_SHORT_PACKET 3 | |
| 96 | +#define MV_U3D_COMPLETE_TRB_ERR 5 | |
| 97 | +#define MV_U3D_XFERSTATUS_TRB_LENGTH_MASK (0xFFFFFF) | |
| 98 | + | |
| 99 | +#define MV_U3D_USB_LINK_BYPASS_VBUS 0x8 | |
| 100 | + | |
| 101 | +#define MV_U3D_LTSSM_PHY_INIT_DONE 0x80000000 | |
| 102 | +#define MV_U3D_LTSSM_NEVER_GO_COMPLIANCE 0x40000000 | |
| 103 | + | |
| 104 | +#define MV_U3D_USB3_OP_REGS_OFFSET 0x100 | |
| 105 | +#define MV_U3D_USB3_PHY_OFFSET 0xB800 | |
| 106 | + | |
| 107 | +#define DCS_ENABLE 0x1 | |
| 108 | + | |
| 109 | +/* timeout */ | |
| 110 | +#define MV_U3D_RESET_TIMEOUT 10000 | |
| 111 | +#define MV_U3D_FLUSH_TIMEOUT 100000 | |
| 112 | +#define MV_U3D_OWN_TIMEOUT 10000 | |
| 113 | +#define LOOPS_USEC_SHIFT 4 | |
| 114 | +#define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) | |
| 115 | +#define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT) | |
| 116 | + | |
| 117 | +/* ep direction */ | |
| 118 | +#define MV_U3D_EP_DIR_IN 1 | |
| 119 | +#define MV_U3D_EP_DIR_OUT 0 | |
| 120 | +#define mv_u3d_ep_dir(ep) (((ep)->ep_num == 0) ? \ | |
| 121 | + ((ep)->u3d->ep0_dir) : ((ep)->direction)) | |
| 122 | + | |
| 123 | +/* usb capability registers */ | |
| 124 | +struct mv_u3d_cap_regs { | |
| 125 | + u32 rsvd[5]; | |
| 126 | + u32 dboff; /* doorbell register offset */ | |
| 127 | + u32 rtsoff; /* runtime register offset */ | |
| 128 | + u32 vuoff; /* vendor unique register offset */ | |
| 129 | +}; | |
| 130 | + | |
| 131 | +/* operation registers */ | |
| 132 | +struct mv_u3d_op_regs { | |
| 133 | + u32 usbcmd; /* Command register */ | |
| 134 | + u32 rsvd1[11]; | |
| 135 | + u32 dcbaapl; /* Device Context Base Address low register */ | |
| 136 | + u32 dcbaaph; /* Device Context Base Address high register */ | |
| 137 | + u32 rsvd2[243]; | |
| 138 | + u32 portsc; /* port status and control register*/ | |
| 139 | + u32 portlinkinfo; /* port link info register*/ | |
| 140 | + u32 rsvd3[9917]; | |
| 141 | + u32 doorbell; /* doorbell register */ | |
| 142 | +}; | |
| 143 | + | |
| 144 | +/* control enpoint enable registers */ | |
| 145 | +struct epxcr { | |
| 146 | + u32 epxoutcr0; /* ep out control 0 register */ | |
| 147 | + u32 epxoutcr1; /* ep out control 1 register */ | |
| 148 | + u32 epxincr0; /* ep in control 0 register */ | |
| 149 | + u32 epxincr1; /* ep in control 1 register */ | |
| 150 | +}; | |
| 151 | + | |
| 152 | +/* transfer status registers */ | |
| 153 | +struct xferstatus { | |
| 154 | + u32 curdeqlo; /* current TRB pointer low */ | |
| 155 | + u32 curdeqhi; /* current TRB pointer high */ | |
| 156 | + u32 statuslo; /* transfer status low */ | |
| 157 | + u32 statushi; /* transfer status high */ | |
| 158 | +}; | |
| 159 | + | |
| 160 | +/* vendor unique control registers */ | |
| 161 | +struct mv_u3d_vuc_regs { | |
| 162 | + u32 ctrlepenable; /* control endpoint enable register */ | |
| 163 | + u32 setuplock; /* setup lock register */ | |
| 164 | + u32 endcomplete; /* endpoint transfer complete register */ | |
| 165 | + u32 intrcause; /* interrupt cause register */ | |
| 166 | + u32 intrenable; /* interrupt enable register */ | |
| 167 | + u32 trbcomplete; /* TRB complete register */ | |
| 168 | + u32 linkchange; /* link change register */ | |
| 169 | + u32 rsvd1[5]; | |
| 170 | + u32 trbunderrun; /* TRB underrun register */ | |
| 171 | + u32 rsvd2[43]; | |
| 172 | + u32 bridgesetting; /* bridge setting register */ | |
| 173 | + u32 rsvd3[7]; | |
| 174 | + struct xferstatus txst[16]; /* TX status register */ | |
| 175 | + struct xferstatus rxst[16]; /* RX status register */ | |
| 176 | + u32 ltssm; /* LTSSM control register */ | |
| 177 | + u32 pipe; /* PIPE control register */ | |
| 178 | + u32 linkcr0; /* link control 0 register */ | |
| 179 | + u32 linkcr1; /* link control 1 register */ | |
| 180 | + u32 rsvd6[60]; | |
| 181 | + u32 mib0; /* MIB0 counter register */ | |
| 182 | + u32 usblink; /* usb link control register */ | |
| 183 | + u32 ltssmstate; /* LTSSM state register */ | |
| 184 | + u32 linkerrorcause; /* link error cause register */ | |
| 185 | + u32 rsvd7[60]; | |
| 186 | + u32 devaddrtiebrkr; /* device address and tie breaker */ | |
| 187 | + u32 itpinfo0; /* ITP info 0 register */ | |
| 188 | + u32 itpinfo1; /* ITP info 1 register */ | |
| 189 | + u32 rsvd8[61]; | |
| 190 | + struct epxcr epcr[16]; /* ep control register */ | |
| 191 | + u32 rsvd9[64]; | |
| 192 | + u32 phyaddr; /* PHY address register */ | |
| 193 | + u32 phydata; /* PHY data register */ | |
| 194 | +}; | |
| 195 | + | |
| 196 | +/* Endpoint context structure */ | |
| 197 | +struct mv_u3d_ep_context { | |
| 198 | + u32 rsvd0; | |
| 199 | + u32 rsvd1; | |
| 200 | + u32 trb_addr_lo; /* TRB address low 32 bit */ | |
| 201 | + u32 trb_addr_hi; /* TRB address high 32 bit */ | |
| 202 | + u32 rsvd2; | |
| 203 | + u32 rsvd3; | |
| 204 | + struct usb_ctrlrequest setup_buffer; /* setup data buffer */ | |
| 205 | +}; | |
| 206 | + | |
| 207 | +/* TRB control data structure */ | |
| 208 | +struct mv_u3d_trb_ctrl { | |
| 209 | + u32 own:1; /* owner of TRB */ | |
| 210 | + u32 rsvd1:3; | |
| 211 | + u32 chain:1; /* associate this TRB with the | |
| 212 | + next TRB on the Ring */ | |
| 213 | + u32 ioc:1; /* interrupt on complete */ | |
| 214 | + u32 rsvd2:4; | |
| 215 | + u32 type:6; /* TRB type */ | |
| 216 | +#define TYPE_NORMAL 1 | |
| 217 | +#define TYPE_DATA 3 | |
| 218 | +#define TYPE_LINK 6 | |
| 219 | + u32 dir:1; /* Working at data stage of control endpoint | |
| 220 | + operation. 0 is OUT and 1 is IN. */ | |
| 221 | + u32 rsvd3:15; | |
| 222 | +}; | |
| 223 | + | |
| 224 | +/* TRB data structure | |
| 225 | + * For multiple TRB, all the TRBs' physical address should be continuous. | |
| 226 | + */ | |
| 227 | +struct mv_u3d_trb_hw { | |
| 228 | + u32 buf_addr_lo; /* data buffer address low 32 bit */ | |
| 229 | + u32 buf_addr_hi; /* data buffer address high 32 bit */ | |
| 230 | + u32 trb_len; /* transfer length */ | |
| 231 | + struct mv_u3d_trb_ctrl ctrl; /* TRB control data */ | |
| 232 | +}; | |
| 233 | + | |
| 234 | +/* TRB structure */ | |
| 235 | +struct mv_u3d_trb { | |
| 236 | + struct mv_u3d_trb_hw *trb_hw; /* point to the trb_hw structure */ | |
| 237 | + dma_addr_t trb_dma; /* dma address for this trb_hw */ | |
| 238 | + struct list_head trb_list; /* trb list */ | |
| 239 | +}; | |
| 240 | + | |
| 241 | +/* device data structure */ | |
| 242 | +struct mv_u3d { | |
| 243 | + struct usb_gadget gadget; | |
| 244 | + struct usb_gadget_driver *driver; | |
| 245 | + spinlock_t lock; /* device lock */ | |
| 246 | + struct completion *done; | |
| 247 | + struct device *dev; | |
| 248 | + int irq; | |
| 249 | + | |
| 250 | + /* usb controller registers */ | |
| 251 | + struct mv_u3d_cap_regs __iomem *cap_regs; | |
| 252 | + struct mv_u3d_op_regs __iomem *op_regs; | |
| 253 | + struct mv_u3d_vuc_regs __iomem *vuc_regs; | |
| 254 | + void __iomem *phy_regs; | |
| 255 | + | |
| 256 | + unsigned int max_eps; | |
| 257 | + struct mv_u3d_ep_context *ep_context; | |
| 258 | + size_t ep_context_size; | |
| 259 | + dma_addr_t ep_context_dma; | |
| 260 | + | |
| 261 | + struct dma_pool *trb_pool; /* for TRB data structure */ | |
| 262 | + struct mv_u3d_ep *eps; | |
| 263 | + | |
| 264 | + struct mv_u3d_req *status_req; /* ep0 status request */ | |
| 265 | + struct usb_ctrlrequest local_setup_buff; /* store setup data*/ | |
| 266 | + | |
| 267 | + unsigned int resume_state; /* USB state to resume */ | |
| 268 | + unsigned int usb_state; /* USB current state */ | |
| 269 | + unsigned int ep0_state; /* Endpoint zero state */ | |
| 270 | + unsigned int ep0_dir; | |
| 271 | + | |
| 272 | + unsigned int dev_addr; /* device address */ | |
| 273 | + | |
| 274 | + unsigned int errors; | |
| 275 | + | |
| 276 | + unsigned softconnect:1; | |
| 277 | + unsigned vbus_active:1; /* vbus is active or not */ | |
| 278 | + unsigned remote_wakeup:1; /* support remote wakeup */ | |
| 279 | + unsigned clock_gating:1; /* clock gating or not */ | |
| 280 | + unsigned active:1; /* udc is active or not */ | |
| 281 | + unsigned vbus_valid_detect:1; /* udc vbus detection */ | |
| 282 | + | |
| 283 | + struct mv_usb_addon_irq *vbus; | |
| 284 | + unsigned int power; | |
| 285 | + | |
| 286 | + struct clk *clk; | |
| 287 | +}; | |
| 288 | + | |
| 289 | +/* endpoint data structure */ | |
| 290 | +struct mv_u3d_ep { | |
| 291 | + struct usb_ep ep; | |
| 292 | + struct mv_u3d *u3d; | |
| 293 | + struct list_head queue; /* ep request queued hardware */ | |
| 294 | + struct list_head req_list; /* list of ep request */ | |
| 295 | + struct mv_u3d_ep_context *ep_context; /* ep context */ | |
| 296 | + u32 direction; | |
| 297 | + char name[14]; | |
| 298 | + u32 processing; /* there is ep request | |
| 299 | + queued on haredware */ | |
| 300 | + spinlock_t req_lock; /* ep lock */ | |
| 301 | + unsigned wedge:1; | |
| 302 | + unsigned enabled:1; | |
| 303 | + unsigned ep_type:2; | |
| 304 | + unsigned ep_num:8; | |
| 305 | +}; | |
| 306 | + | |
| 307 | +/* request data structure */ | |
| 308 | +struct mv_u3d_req { | |
| 309 | + struct usb_request req; | |
| 310 | + struct mv_u3d_ep *ep; | |
| 311 | + struct list_head queue; /* ep requst queued on hardware */ | |
| 312 | + struct list_head list; /* ep request list */ | |
| 313 | + struct list_head trb_list; /* trb list of a request */ | |
| 314 | + | |
| 315 | + struct mv_u3d_trb *trb_head; /* point to first trb of a request */ | |
| 316 | + unsigned trb_count; /* TRB number in the chain */ | |
| 317 | + unsigned chain; /* TRB chain or not */ | |
| 318 | +}; | |
| 319 | + | |
| 320 | +#endif | |
| @@ -0,0 +1,2098 @@ | ||
| 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 and conditions of the GNU General Public License, | |
| 6 | + * version 2, as published by the Free Software Foundation. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/module.h> | |
| 10 | +#include <linux/dma-mapping.h> | |
| 11 | +#include <linux/dmapool.h> | |
| 12 | +#include <linux/kernel.h> | |
| 13 | +#include <linux/delay.h> | |
| 14 | +#include <linux/ioport.h> | |
| 15 | +#include <linux/sched.h> | |
| 16 | +#include <linux/slab.h> | |
| 17 | +#include <linux/errno.h> | |
| 18 | +#include <linux/init.h> | |
| 19 | +#include <linux/timer.h> | |
| 20 | +#include <linux/list.h> | |
| 21 | +#include <linux/notifier.h> | |
| 22 | +#include <linux/interrupt.h> | |
| 23 | +#include <linux/moduleparam.h> | |
| 24 | +#include <linux/device.h> | |
| 25 | +#include <linux/usb/ch9.h> | |
| 26 | +#include <linux/usb/gadget.h> | |
| 27 | +#include <linux/pm.h> | |
| 28 | +#include <linux/io.h> | |
| 29 | +#include <linux/irq.h> | |
| 30 | +#include <linux/platform_device.h> | |
| 31 | +#include <linux/platform_data/mv_usb.h> | |
| 32 | +#include <linux/clk.h> | |
| 33 | +#include <asm/system.h> | |
| 34 | +#include <asm/unaligned.h> | |
| 35 | +#include <asm/byteorder.h> | |
| 36 | + | |
| 37 | +#include "mv_u3d.h" | |
| 38 | + | |
| 39 | +#define DRIVER_DESC "Marvell PXA USB3.0 Device Controller driver" | |
| 40 | + | |
| 41 | +static const char driver_name[] = "mv_u3d"; | |
| 42 | +static const char driver_desc[] = DRIVER_DESC; | |
| 43 | + | |
| 44 | +static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status); | |
| 45 | +static void mv_u3d_stop_activity(struct mv_u3d *u3d, | |
| 46 | + struct usb_gadget_driver *driver); | |
| 47 | + | |
| 48 | +/* for endpoint 0 operations */ | |
| 49 | +static const struct usb_endpoint_descriptor mv_u3d_ep0_desc = { | |
| 50 | + .bLength = USB_DT_ENDPOINT_SIZE, | |
| 51 | + .bDescriptorType = USB_DT_ENDPOINT, | |
| 52 | + .bEndpointAddress = 0, | |
| 53 | + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | |
| 54 | + .wMaxPacketSize = MV_U3D_EP0_MAX_PKT_SIZE, | |
| 55 | +}; | |
| 56 | + | |
| 57 | +static void mv_u3d_ep0_reset(struct mv_u3d *u3d) | |
| 58 | +{ | |
| 59 | + struct mv_u3d_ep *ep; | |
| 60 | + u32 epxcr; | |
| 61 | + int i; | |
| 62 | + | |
| 63 | + for (i = 0; i < 2; i++) { | |
| 64 | + ep = &u3d->eps[i]; | |
| 65 | + ep->u3d = u3d; | |
| 66 | + | |
| 67 | + /* ep0 ep context, ep0 in and out share the same ep context */ | |
| 68 | + ep->ep_context = &u3d->ep_context[1]; | |
| 69 | + } | |
| 70 | + | |
| 71 | + /* reset ep state machine */ | |
| 72 | + /* reset ep0 out */ | |
| 73 | + epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 74 | + epxcr |= MV_U3D_EPXCR_EP_INIT; | |
| 75 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 76 | + udelay(5); | |
| 77 | + epxcr &= ~MV_U3D_EPXCR_EP_INIT; | |
| 78 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 79 | + | |
| 80 | + epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE | |
| 81 | + << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT) | |
| 82 | + | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT) | |
| 83 | + | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 84 | + | MV_U3D_EPXCR_EP_TYPE_CONTROL); | |
| 85 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr1); | |
| 86 | + | |
| 87 | + /* reset ep0 in */ | |
| 88 | + epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxincr0); | |
| 89 | + epxcr |= MV_U3D_EPXCR_EP_INIT; | |
| 90 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0); | |
| 91 | + udelay(5); | |
| 92 | + epxcr &= ~MV_U3D_EPXCR_EP_INIT; | |
| 93 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0); | |
| 94 | + | |
| 95 | + epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE | |
| 96 | + << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT) | |
| 97 | + | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT) | |
| 98 | + | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 99 | + | MV_U3D_EPXCR_EP_TYPE_CONTROL); | |
| 100 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr1); | |
| 101 | +} | |
| 102 | + | |
| 103 | +static void mv_u3d_ep0_stall(struct mv_u3d *u3d) | |
| 104 | +{ | |
| 105 | + u32 tmp; | |
| 106 | + dev_dbg(u3d->dev, "%s\n", __func__); | |
| 107 | + | |
| 108 | + /* set TX and RX to stall */ | |
| 109 | + tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 110 | + tmp |= MV_U3D_EPXCR_EP_HALT; | |
| 111 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 112 | + | |
| 113 | + tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0); | |
| 114 | + tmp |= MV_U3D_EPXCR_EP_HALT; | |
| 115 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0); | |
| 116 | + | |
| 117 | + /* update ep0 state */ | |
| 118 | + u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP; | |
| 119 | + u3d->ep0_dir = MV_U3D_EP_DIR_OUT; | |
| 120 | +} | |
| 121 | + | |
| 122 | +static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index, | |
| 123 | + struct mv_u3d_req *curr_req) | |
| 124 | +{ | |
| 125 | + struct mv_u3d_trb *curr_trb; | |
| 126 | + dma_addr_t cur_deq_lo; | |
| 127 | + struct mv_u3d_ep_context *curr_ep_context; | |
| 128 | + int trb_complete, actual, remaining_length; | |
| 129 | + int direction, ep_num; | |
| 130 | + int retval = 0; | |
| 131 | + u32 tmp, status, length; | |
| 132 | + | |
| 133 | + curr_ep_context = &u3d->ep_context[index]; | |
| 134 | + direction = index % 2; | |
| 135 | + ep_num = index / 2; | |
| 136 | + | |
| 137 | + trb_complete = 0; | |
| 138 | + actual = curr_req->req.length; | |
| 139 | + | |
| 140 | + while (!list_empty(&curr_req->trb_list)) { | |
| 141 | + curr_trb = list_entry(curr_req->trb_list.next, | |
| 142 | + struct mv_u3d_trb, trb_list); | |
| 143 | + if (!curr_trb->trb_hw->ctrl.own) { | |
| 144 | + dev_err(u3d->dev, "%s, TRB own error!\n", | |
| 145 | + u3d->eps[index].name); | |
| 146 | + return 1; | |
| 147 | + } | |
| 148 | + | |
| 149 | + curr_trb->trb_hw->ctrl.own = 0; | |
| 150 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 151 | + tmp = ioread32(&u3d->vuc_regs->rxst[ep_num].statuslo); | |
| 152 | + cur_deq_lo = | |
| 153 | + ioread32(&u3d->vuc_regs->rxst[ep_num].curdeqlo); | |
| 154 | + } else { | |
| 155 | + tmp = ioread32(&u3d->vuc_regs->txst[ep_num].statuslo); | |
| 156 | + cur_deq_lo = | |
| 157 | + ioread32(&u3d->vuc_regs->txst[ep_num].curdeqlo); | |
| 158 | + } | |
| 159 | + | |
| 160 | + status = tmp >> MV_U3D_XFERSTATUS_COMPLETE_SHIFT; | |
| 161 | + length = tmp & MV_U3D_XFERSTATUS_TRB_LENGTH_MASK; | |
| 162 | + | |
| 163 | + if (status == MV_U3D_COMPLETE_SUCCESS || | |
| 164 | + (status == MV_U3D_COMPLETE_SHORT_PACKET && | |
| 165 | + direction == MV_U3D_EP_DIR_OUT)) { | |
| 166 | + remaining_length += length; | |
| 167 | + actual -= remaining_length; | |
| 168 | + } else { | |
| 169 | + dev_err(u3d->dev, | |
| 170 | + "complete_tr error: ep=%d %s: error = 0x%x\n", | |
| 171 | + index >> 1, direction ? "SEND" : "RECV", | |
| 172 | + status); | |
| 173 | + retval = -EPROTO; | |
| 174 | + } | |
| 175 | + | |
| 176 | + list_del_init(&curr_trb->trb_list); | |
| 177 | + } | |
| 178 | + if (retval) | |
| 179 | + return retval; | |
| 180 | + | |
| 181 | + curr_req->req.actual = actual; | |
| 182 | + return 0; | |
| 183 | +} | |
| 184 | + | |
| 185 | +/* | |
| 186 | + * mv_u3d_done() - retire a request; caller blocked irqs | |
| 187 | + * @status : request status to be set, only works when | |
| 188 | + * request is still in progress. | |
| 189 | + */ | |
| 190 | +static | |
| 191 | +void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status) | |
| 192 | +{ | |
| 193 | + struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d; | |
| 194 | + | |
| 195 | + dev_dbg(u3d->dev, "mv_u3d_done: remove req->queue\n"); | |
| 196 | + /* Removed the req from ep queue */ | |
| 197 | + list_del_init(&req->queue); | |
| 198 | + | |
| 199 | + /* req.status should be set as -EINPROGRESS in ep_queue() */ | |
| 200 | + if (req->req.status == -EINPROGRESS) | |
| 201 | + req->req.status = status; | |
| 202 | + else | |
| 203 | + status = req->req.status; | |
| 204 | + | |
| 205 | + /* Free trb for the request */ | |
| 206 | + if (!req->chain) | |
| 207 | + dma_pool_free(u3d->trb_pool, | |
| 208 | + req->trb_head->trb_hw, req->trb_head->trb_dma); | |
| 209 | + else { | |
| 210 | + dma_unmap_single(ep->u3d->gadget.dev.parent, | |
| 211 | + (dma_addr_t)req->trb_head->trb_dma, | |
| 212 | + req->trb_count * sizeof(struct mv_u3d_trb_hw), | |
| 213 | + DMA_BIDIRECTIONAL); | |
| 214 | + kfree(req->trb_head->trb_hw); | |
| 215 | + } | |
| 216 | + kfree(req->trb_head); | |
| 217 | + | |
| 218 | + usb_gadget_unmap_request(&u3d->gadget, &req->req, mv_u3d_ep_dir(ep)); | |
| 219 | + | |
| 220 | + if (status && (status != -ESHUTDOWN)) { | |
| 221 | + dev_dbg(u3d->dev, "complete %s req %p stat %d len %u/%u", | |
| 222 | + ep->ep.name, &req->req, status, | |
| 223 | + req->req.actual, req->req.length); | |
| 224 | + } | |
| 225 | + | |
| 226 | + spin_unlock(&ep->u3d->lock); | |
| 227 | + /* | |
| 228 | + * complete() is from gadget layer, | |
| 229 | + * eg fsg->bulk_in_complete() | |
| 230 | + */ | |
| 231 | + if (req->req.complete) | |
| 232 | + req->req.complete(&ep->ep, &req->req); | |
| 233 | + | |
| 234 | + spin_lock(&ep->u3d->lock); | |
| 235 | +} | |
| 236 | + | |
| 237 | +static int mv_u3d_queue_trb(struct mv_u3d_ep *ep, struct mv_u3d_req *req) | |
| 238 | +{ | |
| 239 | + u32 tmp, direction; | |
| 240 | + struct mv_u3d *u3d; | |
| 241 | + struct mv_u3d_ep_context *ep_context; | |
| 242 | + int retval = 0; | |
| 243 | + | |
| 244 | + u3d = ep->u3d; | |
| 245 | + direction = mv_u3d_ep_dir(ep); | |
| 246 | + | |
| 247 | + /* ep0 in and out share the same ep context slot 1*/ | |
| 248 | + if (ep->ep_num == 0) | |
| 249 | + ep_context = &(u3d->ep_context[1]); | |
| 250 | + else | |
| 251 | + ep_context = &(u3d->ep_context[ep->ep_num * 2 + direction]); | |
| 252 | + | |
| 253 | + /* check if the pipe is empty or not */ | |
| 254 | + if (!list_empty(&ep->queue)) { | |
| 255 | + dev_err(u3d->dev, "add trb to non-empty queue!\n"); | |
| 256 | + retval = -ENOMEM; | |
| 257 | + WARN_ON(1); | |
| 258 | + } else { | |
| 259 | + ep_context->rsvd0 = cpu_to_le32(1); | |
| 260 | + ep_context->rsvd1 = 0; | |
| 261 | + | |
| 262 | + /* Configure the trb address and set the DCS bit. | |
| 263 | + * Both DCS bit and own bit in trb should be set. | |
| 264 | + */ | |
| 265 | + ep_context->trb_addr_lo = | |
| 266 | + cpu_to_le32(req->trb_head->trb_dma | DCS_ENABLE); | |
| 267 | + ep_context->trb_addr_hi = 0; | |
| 268 | + | |
| 269 | + /* Ensure that updates to the EP Context will | |
| 270 | + * occure before Ring Bell. | |
| 271 | + */ | |
| 272 | + wmb(); | |
| 273 | + | |
| 274 | + /* ring bell the ep */ | |
| 275 | + if (ep->ep_num == 0) | |
| 276 | + tmp = 0x1; | |
| 277 | + else | |
| 278 | + tmp = ep->ep_num * 2 | |
| 279 | + + ((direction == MV_U3D_EP_DIR_OUT) ? 0 : 1); | |
| 280 | + | |
| 281 | + iowrite32(tmp, &u3d->op_regs->doorbell); | |
| 282 | + } | |
| 283 | + return retval; | |
| 284 | +} | |
| 285 | + | |
| 286 | +static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req, | |
| 287 | + unsigned *length, dma_addr_t *dma) | |
| 288 | +{ | |
| 289 | + u32 temp; | |
| 290 | + unsigned int direction; | |
| 291 | + struct mv_u3d_trb *trb; | |
| 292 | + struct mv_u3d_trb_hw *trb_hw; | |
| 293 | + struct mv_u3d *u3d; | |
| 294 | + | |
| 295 | + /* how big will this transfer be? */ | |
| 296 | + *length = req->req.length - req->req.actual; | |
| 297 | + BUG_ON(*length > (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER); | |
| 298 | + | |
| 299 | + u3d = req->ep->u3d; | |
| 300 | + | |
| 301 | + trb = kzalloc(sizeof(*trb), GFP_ATOMIC); | |
| 302 | + if (!trb) { | |
| 303 | + dev_err(u3d->dev, "%s, trb alloc fail\n", __func__); | |
| 304 | + return NULL; | |
| 305 | + } | |
| 306 | + | |
| 307 | + /* | |
| 308 | + * Be careful that no _GFP_HIGHMEM is set, | |
| 309 | + * or we can not use dma_to_virt | |
| 310 | + * cannot use GFP_KERNEL in spin lock | |
| 311 | + */ | |
| 312 | + trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma); | |
| 313 | + if (!trb_hw) { | |
| 314 | + dev_err(u3d->dev, | |
| 315 | + "%s, dma_pool_alloc fail\n", __func__); | |
| 316 | + return NULL; | |
| 317 | + } | |
| 318 | + trb->trb_dma = *dma; | |
| 319 | + trb->trb_hw = trb_hw; | |
| 320 | + | |
| 321 | + /* initialize buffer page pointers */ | |
| 322 | + temp = (u32)(req->req.dma + req->req.actual); | |
| 323 | + | |
| 324 | + trb_hw->buf_addr_lo = cpu_to_le32(temp); | |
| 325 | + trb_hw->buf_addr_hi = 0; | |
| 326 | + trb_hw->trb_len = cpu_to_le32(*length); | |
| 327 | + trb_hw->ctrl.own = 1; | |
| 328 | + | |
| 329 | + if (req->ep->ep_num == 0) | |
| 330 | + trb_hw->ctrl.type = TYPE_DATA; | |
| 331 | + else | |
| 332 | + trb_hw->ctrl.type = TYPE_NORMAL; | |
| 333 | + | |
| 334 | + req->req.actual += *length; | |
| 335 | + | |
| 336 | + direction = mv_u3d_ep_dir(req->ep); | |
| 337 | + if (direction == MV_U3D_EP_DIR_IN) | |
| 338 | + trb_hw->ctrl.dir = 1; | |
| 339 | + else | |
| 340 | + trb_hw->ctrl.dir = 0; | |
| 341 | + | |
| 342 | + /* Enable interrupt for the last trb of a request */ | |
| 343 | + if (!req->req.no_interrupt) | |
| 344 | + trb_hw->ctrl.ioc = 1; | |
| 345 | + | |
| 346 | + trb_hw->ctrl.chain = 0; | |
| 347 | + | |
| 348 | + wmb(); | |
| 349 | + return trb; | |
| 350 | +} | |
| 351 | + | |
| 352 | +static int mv_u3d_build_trb_chain(struct mv_u3d_req *req, unsigned *length, | |
| 353 | + struct mv_u3d_trb *trb, int *is_last) | |
| 354 | +{ | |
| 355 | + u32 temp; | |
| 356 | + unsigned int direction; | |
| 357 | + struct mv_u3d *u3d; | |
| 358 | + | |
| 359 | + /* how big will this transfer be? */ | |
| 360 | + *length = min(req->req.length - req->req.actual, | |
| 361 | + (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER); | |
| 362 | + | |
| 363 | + u3d = req->ep->u3d; | |
| 364 | + | |
| 365 | + trb->trb_dma = 0; | |
| 366 | + | |
| 367 | + /* initialize buffer page pointers */ | |
| 368 | + temp = (u32)(req->req.dma + req->req.actual); | |
| 369 | + | |
| 370 | + trb->trb_hw->buf_addr_lo = cpu_to_le32(temp); | |
| 371 | + trb->trb_hw->buf_addr_hi = 0; | |
| 372 | + trb->trb_hw->trb_len = cpu_to_le32(*length); | |
| 373 | + trb->trb_hw->ctrl.own = 1; | |
| 374 | + | |
| 375 | + if (req->ep->ep_num == 0) | |
| 376 | + trb->trb_hw->ctrl.type = TYPE_DATA; | |
| 377 | + else | |
| 378 | + trb->trb_hw->ctrl.type = TYPE_NORMAL; | |
| 379 | + | |
| 380 | + req->req.actual += *length; | |
| 381 | + | |
| 382 | + direction = mv_u3d_ep_dir(req->ep); | |
| 383 | + if (direction == MV_U3D_EP_DIR_IN) | |
| 384 | + trb->trb_hw->ctrl.dir = 1; | |
| 385 | + else | |
| 386 | + trb->trb_hw->ctrl.dir = 0; | |
| 387 | + | |
| 388 | + /* zlp is needed if req->req.zero is set */ | |
| 389 | + if (req->req.zero) { | |
| 390 | + if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0) | |
| 391 | + *is_last = 1; | |
| 392 | + else | |
| 393 | + *is_last = 0; | |
| 394 | + } else if (req->req.length == req->req.actual) | |
| 395 | + *is_last = 1; | |
| 396 | + else | |
| 397 | + *is_last = 0; | |
| 398 | + | |
| 399 | + /* Enable interrupt for the last trb of a request */ | |
| 400 | + if (*is_last && !req->req.no_interrupt) | |
| 401 | + trb->trb_hw->ctrl.ioc = 1; | |
| 402 | + | |
| 403 | + if (*is_last) | |
| 404 | + trb->trb_hw->ctrl.chain = 0; | |
| 405 | + else { | |
| 406 | + trb->trb_hw->ctrl.chain = 1; | |
| 407 | + dev_dbg(u3d->dev, "chain trb\n"); | |
| 408 | + } | |
| 409 | + | |
| 410 | + wmb(); | |
| 411 | + | |
| 412 | + return 0; | |
| 413 | +} | |
| 414 | + | |
| 415 | +/* generate TRB linked list for a request | |
| 416 | + * usb controller only supports continous trb chain, | |
| 417 | + * that trb structure physical address should be continous. | |
| 418 | + */ | |
| 419 | +static int mv_u3d_req_to_trb(struct mv_u3d_req *req) | |
| 420 | +{ | |
| 421 | + unsigned count; | |
| 422 | + int is_last; | |
| 423 | + struct mv_u3d_trb *trb; | |
| 424 | + struct mv_u3d_trb_hw *trb_hw; | |
| 425 | + struct mv_u3d *u3d; | |
| 426 | + dma_addr_t dma; | |
| 427 | + unsigned length; | |
| 428 | + unsigned trb_num; | |
| 429 | + | |
| 430 | + u3d = req->ep->u3d; | |
| 431 | + | |
| 432 | + INIT_LIST_HEAD(&req->trb_list); | |
| 433 | + | |
| 434 | + length = req->req.length - req->req.actual; | |
| 435 | + /* normally the request transfer length is less than 16KB. | |
| 436 | + * we use buil_trb_one() to optimize it. | |
| 437 | + */ | |
| 438 | + if (length <= (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER) { | |
| 439 | + trb = mv_u3d_build_trb_one(req, &count, &dma); | |
| 440 | + list_add_tail(&trb->trb_list, &req->trb_list); | |
| 441 | + req->trb_head = trb; | |
| 442 | + req->trb_count = 1; | |
| 443 | + req->chain = 0; | |
| 444 | + } else { | |
| 445 | + trb_num = length / MV_U3D_EP_MAX_LENGTH_TRANSFER; | |
| 446 | + if (length % MV_U3D_EP_MAX_LENGTH_TRANSFER) | |
| 447 | + trb_num++; | |
| 448 | + | |
| 449 | + trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC); | |
| 450 | + if (!trb) { | |
| 451 | + dev_err(u3d->dev, | |
| 452 | + "%s, trb alloc fail\n", __func__); | |
| 453 | + return -ENOMEM; | |
| 454 | + } | |
| 455 | + | |
| 456 | + trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC); | |
| 457 | + if (!trb_hw) { | |
| 458 | + dev_err(u3d->dev, | |
| 459 | + "%s, trb_hw alloc fail\n", __func__); | |
| 460 | + return -ENOMEM; | |
| 461 | + } | |
| 462 | + | |
| 463 | + do { | |
| 464 | + trb->trb_hw = trb_hw; | |
| 465 | + if (mv_u3d_build_trb_chain(req, &count, | |
| 466 | + trb, &is_last)) { | |
| 467 | + dev_err(u3d->dev, | |
| 468 | + "%s, mv_u3d_build_trb_chain fail\n", | |
| 469 | + __func__); | |
| 470 | + return -EIO; | |
| 471 | + } | |
| 472 | + | |
| 473 | + list_add_tail(&trb->trb_list, &req->trb_list); | |
| 474 | + req->trb_count++; | |
| 475 | + trb++; | |
| 476 | + trb_hw++; | |
| 477 | + } while (!is_last); | |
| 478 | + | |
| 479 | + req->trb_head = list_entry(req->trb_list.next, | |
| 480 | + struct mv_u3d_trb, trb_list); | |
| 481 | + req->trb_head->trb_dma = dma_map_single(u3d->gadget.dev.parent, | |
| 482 | + req->trb_head->trb_hw, | |
| 483 | + trb_num * sizeof(*trb_hw), | |
| 484 | + DMA_BIDIRECTIONAL); | |
| 485 | + | |
| 486 | + req->chain = 1; | |
| 487 | + } | |
| 488 | + | |
| 489 | + return 0; | |
| 490 | +} | |
| 491 | + | |
| 492 | +static int | |
| 493 | +mv_u3d_start_queue(struct mv_u3d_ep *ep) | |
| 494 | +{ | |
| 495 | + struct mv_u3d *u3d = ep->u3d; | |
| 496 | + struct mv_u3d_req *req; | |
| 497 | + int ret; | |
| 498 | + | |
| 499 | + if (!list_empty(&ep->req_list) && !ep->processing) | |
| 500 | + req = list_entry(ep->req_list.next, struct mv_u3d_req, list); | |
| 501 | + else | |
| 502 | + return 0; | |
| 503 | + | |
| 504 | + ep->processing = 1; | |
| 505 | + | |
| 506 | + /* set up dma mapping */ | |
| 507 | + ret = usb_gadget_map_request(&u3d->gadget, &req->req, | |
| 508 | + mv_u3d_ep_dir(ep)); | |
| 509 | + if (ret) | |
| 510 | + return ret; | |
| 511 | + | |
| 512 | + req->req.status = -EINPROGRESS; | |
| 513 | + req->req.actual = 0; | |
| 514 | + req->trb_count = 0; | |
| 515 | + | |
| 516 | + /* build trbs and push them to device queue */ | |
| 517 | + if (!mv_u3d_req_to_trb(req)) { | |
| 518 | + ret = mv_u3d_queue_trb(ep, req); | |
| 519 | + if (ret) { | |
| 520 | + ep->processing = 0; | |
| 521 | + return ret; | |
| 522 | + } | |
| 523 | + } else { | |
| 524 | + ep->processing = 0; | |
| 525 | + dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__); | |
| 526 | + return -ENOMEM; | |
| 527 | + } | |
| 528 | + | |
| 529 | + /* irq handler advances the queue */ | |
| 530 | + if (req) | |
| 531 | + list_add_tail(&req->queue, &ep->queue); | |
| 532 | + | |
| 533 | + return 0; | |
| 534 | +} | |
| 535 | + | |
| 536 | +static int mv_u3d_ep_enable(struct usb_ep *_ep, | |
| 537 | + const struct usb_endpoint_descriptor *desc) | |
| 538 | +{ | |
| 539 | + struct mv_u3d *u3d; | |
| 540 | + struct mv_u3d_ep *ep; | |
| 541 | + struct mv_u3d_ep_context *ep_context; | |
| 542 | + u16 max = 0; | |
| 543 | + unsigned maxburst = 0; | |
| 544 | + u32 epxcr, direction; | |
| 545 | + | |
| 546 | + if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) | |
| 547 | + return -EINVAL; | |
| 548 | + | |
| 549 | + ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 550 | + u3d = ep->u3d; | |
| 551 | + | |
| 552 | + if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN) | |
| 553 | + return -ESHUTDOWN; | |
| 554 | + | |
| 555 | + direction = mv_u3d_ep_dir(ep); | |
| 556 | + max = le16_to_cpu(desc->wMaxPacketSize); | |
| 557 | + | |
| 558 | + if (!_ep->maxburst) | |
| 559 | + _ep->maxburst = 1; | |
| 560 | + maxburst = _ep->maxburst; | |
| 561 | + | |
| 562 | + /* Get the endpoint context address */ | |
| 563 | + ep_context = (struct mv_u3d_ep_context *)ep->ep_context; | |
| 564 | + | |
| 565 | + /* Set the max burst size */ | |
| 566 | + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | |
| 567 | + case USB_ENDPOINT_XFER_BULK: | |
| 568 | + if (maxburst > 16) { | |
| 569 | + dev_dbg(u3d->dev, | |
| 570 | + "max burst should not be greater " | |
| 571 | + "than 16 on bulk ep\n"); | |
| 572 | + maxburst = 1; | |
| 573 | + _ep->maxburst = maxburst; | |
| 574 | + } | |
| 575 | + dev_dbg(u3d->dev, | |
| 576 | + "maxburst: %d on bulk %s\n", maxburst, ep->name); | |
| 577 | + break; | |
| 578 | + case USB_ENDPOINT_XFER_CONTROL: | |
| 579 | + /* control transfer only supports maxburst as one */ | |
| 580 | + maxburst = 1; | |
| 581 | + _ep->maxburst = maxburst; | |
| 582 | + break; | |
| 583 | + case USB_ENDPOINT_XFER_INT: | |
| 584 | + if (maxburst != 1) { | |
| 585 | + dev_dbg(u3d->dev, | |
| 586 | + "max burst should be 1 on int ep " | |
| 587 | + "if transfer size is not 1024\n"); | |
| 588 | + maxburst = 1; | |
| 589 | + _ep->maxburst = maxburst; | |
| 590 | + } | |
| 591 | + break; | |
| 592 | + case USB_ENDPOINT_XFER_ISOC: | |
| 593 | + if (maxburst != 1) { | |
| 594 | + dev_dbg(u3d->dev, | |
| 595 | + "max burst should be 1 on isoc ep " | |
| 596 | + "if transfer size is not 1024\n"); | |
| 597 | + maxburst = 1; | |
| 598 | + _ep->maxburst = maxburst; | |
| 599 | + } | |
| 600 | + break; | |
| 601 | + default: | |
| 602 | + goto en_done; | |
| 603 | + } | |
| 604 | + | |
| 605 | + ep->ep.maxpacket = max; | |
| 606 | + ep->ep.desc = desc; | |
| 607 | + ep->enabled = 1; | |
| 608 | + | |
| 609 | + /* Enable the endpoint for Rx or Tx and set the endpoint type */ | |
| 610 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 611 | + epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 612 | + epxcr |= MV_U3D_EPXCR_EP_INIT; | |
| 613 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 614 | + udelay(5); | |
| 615 | + epxcr &= ~MV_U3D_EPXCR_EP_INIT; | |
| 616 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 617 | + | |
| 618 | + epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT) | |
| 619 | + | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT) | |
| 620 | + | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 621 | + | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)); | |
| 622 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1); | |
| 623 | + } else { | |
| 624 | + epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 625 | + epxcr |= MV_U3D_EPXCR_EP_INIT; | |
| 626 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 627 | + udelay(5); | |
| 628 | + epxcr &= ~MV_U3D_EPXCR_EP_INIT; | |
| 629 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 630 | + | |
| 631 | + epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT) | |
| 632 | + | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT) | |
| 633 | + | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 634 | + | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)); | |
| 635 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1); | |
| 636 | + } | |
| 637 | + | |
| 638 | + return 0; | |
| 639 | +en_done: | |
| 640 | + return -EINVAL; | |
| 641 | +} | |
| 642 | + | |
| 643 | +static int mv_u3d_ep_disable(struct usb_ep *_ep) | |
| 644 | +{ | |
| 645 | + struct mv_u3d *u3d; | |
| 646 | + struct mv_u3d_ep *ep; | |
| 647 | + struct mv_u3d_ep_context *ep_context; | |
| 648 | + u32 epxcr, direction; | |
| 649 | + | |
| 650 | + if (!_ep) | |
| 651 | + return -EINVAL; | |
| 652 | + | |
| 653 | + ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 654 | + if (!ep->ep.desc) | |
| 655 | + return -EINVAL; | |
| 656 | + | |
| 657 | + u3d = ep->u3d; | |
| 658 | + | |
| 659 | + /* Get the endpoint context address */ | |
| 660 | + ep_context = ep->ep_context; | |
| 661 | + | |
| 662 | + direction = mv_u3d_ep_dir(ep); | |
| 663 | + | |
| 664 | + /* nuke all pending requests (does flush) */ | |
| 665 | + mv_u3d_nuke(ep, -ESHUTDOWN); | |
| 666 | + | |
| 667 | + /* Disable the endpoint for Rx or Tx and reset the endpoint type */ | |
| 668 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 669 | + epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1); | |
| 670 | + epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 671 | + | USB_ENDPOINT_XFERTYPE_MASK); | |
| 672 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1); | |
| 673 | + } else { | |
| 674 | + epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr1); | |
| 675 | + epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT) | |
| 676 | + | USB_ENDPOINT_XFERTYPE_MASK); | |
| 677 | + iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1); | |
| 678 | + } | |
| 679 | + | |
| 680 | + ep->enabled = 0; | |
| 681 | + | |
| 682 | + ep->ep.desc = NULL; | |
| 683 | + return 0; | |
| 684 | +} | |
| 685 | + | |
| 686 | +static struct usb_request * | |
| 687 | +mv_u3d_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) | |
| 688 | +{ | |
| 689 | + struct mv_u3d_req *req = NULL; | |
| 690 | + | |
| 691 | + req = kzalloc(sizeof *req, gfp_flags); | |
| 692 | + if (!req) | |
| 693 | + return NULL; | |
| 694 | + | |
| 695 | + INIT_LIST_HEAD(&req->queue); | |
| 696 | + | |
| 697 | + return &req->req; | |
| 698 | +} | |
| 699 | + | |
| 700 | +static void mv_u3d_free_request(struct usb_ep *_ep, struct usb_request *_req) | |
| 701 | +{ | |
| 702 | + struct mv_u3d_req *req = container_of(_req, struct mv_u3d_req, req); | |
| 703 | + | |
| 704 | + kfree(req); | |
| 705 | +} | |
| 706 | + | |
| 707 | +static void mv_u3d_ep_fifo_flush(struct usb_ep *_ep) | |
| 708 | +{ | |
| 709 | + struct mv_u3d *u3d; | |
| 710 | + u32 direction; | |
| 711 | + struct mv_u3d_ep *ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 712 | + unsigned int loops; | |
| 713 | + u32 tmp; | |
| 714 | + | |
| 715 | + /* if endpoint is not enabled, cannot flush endpoint */ | |
| 716 | + if (!ep->enabled) | |
| 717 | + return; | |
| 718 | + | |
| 719 | + u3d = ep->u3d; | |
| 720 | + direction = mv_u3d_ep_dir(ep); | |
| 721 | + | |
| 722 | + /* ep0 need clear bit after flushing fifo. */ | |
| 723 | + if (!ep->ep_num) { | |
| 724 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 725 | + tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 726 | + tmp |= MV_U3D_EPXCR_EP_FLUSH; | |
| 727 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 728 | + udelay(10); | |
| 729 | + tmp &= ~MV_U3D_EPXCR_EP_FLUSH; | |
| 730 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0); | |
| 731 | + } else { | |
| 732 | + tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0); | |
| 733 | + tmp |= MV_U3D_EPXCR_EP_FLUSH; | |
| 734 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0); | |
| 735 | + udelay(10); | |
| 736 | + tmp &= ~MV_U3D_EPXCR_EP_FLUSH; | |
| 737 | + iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0); | |
| 738 | + } | |
| 739 | + return; | |
| 740 | + } | |
| 741 | + | |
| 742 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 743 | + tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 744 | + tmp |= MV_U3D_EPXCR_EP_FLUSH; | |
| 745 | + iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 746 | + | |
| 747 | + /* Wait until flushing completed */ | |
| 748 | + loops = LOOPS(MV_U3D_FLUSH_TIMEOUT); | |
| 749 | + while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0) & | |
| 750 | + MV_U3D_EPXCR_EP_FLUSH) { | |
| 751 | + /* | |
| 752 | + * EP_FLUSH bit should be cleared to indicate this | |
| 753 | + * operation is complete | |
| 754 | + */ | |
| 755 | + if (loops == 0) { | |
| 756 | + dev_dbg(u3d->dev, | |
| 757 | + "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num, | |
| 758 | + direction ? "in" : "out"); | |
| 759 | + return; | |
| 760 | + } | |
| 761 | + loops--; | |
| 762 | + udelay(LOOPS_USEC); | |
| 763 | + } | |
| 764 | + } else { /* EP_DIR_IN */ | |
| 765 | + tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 766 | + tmp |= MV_U3D_EPXCR_EP_FLUSH; | |
| 767 | + iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 768 | + | |
| 769 | + /* Wait until flushing completed */ | |
| 770 | + loops = LOOPS(MV_U3D_FLUSH_TIMEOUT); | |
| 771 | + while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0) & | |
| 772 | + MV_U3D_EPXCR_EP_FLUSH) { | |
| 773 | + /* | |
| 774 | + * EP_FLUSH bit should be cleared to indicate this | |
| 775 | + * operation is complete | |
| 776 | + */ | |
| 777 | + if (loops == 0) { | |
| 778 | + dev_dbg(u3d->dev, | |
| 779 | + "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num, | |
| 780 | + direction ? "in" : "out"); | |
| 781 | + return; | |
| 782 | + } | |
| 783 | + loops--; | |
| 784 | + udelay(LOOPS_USEC); | |
| 785 | + } | |
| 786 | + } | |
| 787 | +} | |
| 788 | + | |
| 789 | +/* queues (submits) an I/O request to an endpoint */ | |
| 790 | +static int | |
| 791 | +mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |
| 792 | +{ | |
| 793 | + struct mv_u3d_ep *ep; | |
| 794 | + struct mv_u3d_req *req; | |
| 795 | + struct mv_u3d *u3d; | |
| 796 | + unsigned long flags; | |
| 797 | + int is_first_req = 0; | |
| 798 | + | |
| 799 | + if (unlikely(!_ep || !_req)) | |
| 800 | + return -EINVAL; | |
| 801 | + | |
| 802 | + ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 803 | + u3d = ep->u3d; | |
| 804 | + | |
| 805 | + req = container_of(_req, struct mv_u3d_req, req); | |
| 806 | + | |
| 807 | + if (!ep->ep_num | |
| 808 | + && u3d->ep0_state == MV_U3D_STATUS_STAGE | |
| 809 | + && !_req->length) { | |
| 810 | + dev_dbg(u3d->dev, "ep0 status stage\n"); | |
| 811 | + u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP; | |
| 812 | + return 0; | |
| 813 | + } | |
| 814 | + | |
| 815 | + dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n", | |
| 816 | + __func__, _ep->name, (u32)req); | |
| 817 | + | |
| 818 | + /* catch various bogus parameters */ | |
| 819 | + if (!req->req.complete || !req->req.buf | |
| 820 | + || !list_empty(&req->queue)) { | |
| 821 | + dev_err(u3d->dev, | |
| 822 | + "%s, bad params, _req: 0x%x," | |
| 823 | + "req->req.complete: 0x%x, req->req.buf: 0x%x," | |
| 824 | + "list_empty: 0x%x\n", | |
| 825 | + __func__, (u32)_req, | |
| 826 | + (u32)req->req.complete, (u32)req->req.buf, | |
| 827 | + (u32)list_empty(&req->queue)); | |
| 828 | + return -EINVAL; | |
| 829 | + } | |
| 830 | + if (unlikely(!ep->ep.desc)) { | |
| 831 | + dev_err(u3d->dev, "%s, bad ep\n", __func__); | |
| 832 | + return -EINVAL; | |
| 833 | + } | |
| 834 | + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { | |
| 835 | + if (req->req.length > ep->ep.maxpacket) | |
| 836 | + return -EMSGSIZE; | |
| 837 | + } | |
| 838 | + | |
| 839 | + if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN) { | |
| 840 | + dev_err(u3d->dev, | |
| 841 | + "bad params of driver/speed\n"); | |
| 842 | + return -ESHUTDOWN; | |
| 843 | + } | |
| 844 | + | |
| 845 | + req->ep = ep; | |
| 846 | + | |
| 847 | + /* Software list handles usb request. */ | |
| 848 | + spin_lock_irqsave(&ep->req_lock, flags); | |
| 849 | + is_first_req = list_empty(&ep->req_list); | |
| 850 | + list_add_tail(&req->list, &ep->req_list); | |
| 851 | + spin_unlock_irqrestore(&ep->req_lock, flags); | |
| 852 | + if (!is_first_req) { | |
| 853 | + dev_dbg(u3d->dev, "list is not empty\n"); | |
| 854 | + return 0; | |
| 855 | + } | |
| 856 | + | |
| 857 | + dev_dbg(u3d->dev, "call mv_u3d_start_queue from usb_ep_queue\n"); | |
| 858 | + spin_lock_irqsave(&u3d->lock, flags); | |
| 859 | + mv_u3d_start_queue(ep); | |
| 860 | + spin_unlock_irqrestore(&u3d->lock, flags); | |
| 861 | + return 0; | |
| 862 | +} | |
| 863 | + | |
| 864 | +/* dequeues (cancels, unlinks) an I/O request from an endpoint */ | |
| 865 | +static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | |
| 866 | +{ | |
| 867 | + struct mv_u3d_ep *ep; | |
| 868 | + struct mv_u3d_req *req; | |
| 869 | + struct mv_u3d *u3d; | |
| 870 | + struct mv_u3d_ep_context *ep_context; | |
| 871 | + struct mv_u3d_req *next_req; | |
| 872 | + | |
| 873 | + unsigned long flags; | |
| 874 | + int ret = 0; | |
| 875 | + | |
| 876 | + if (!_ep || !_req) | |
| 877 | + return -EINVAL; | |
| 878 | + | |
| 879 | + ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 880 | + u3d = ep->u3d; | |
| 881 | + | |
| 882 | + spin_lock_irqsave(&ep->u3d->lock, flags); | |
| 883 | + | |
| 884 | + /* make sure it's actually queued on this endpoint */ | |
| 885 | + list_for_each_entry(req, &ep->queue, queue) { | |
| 886 | + if (&req->req == _req) | |
| 887 | + break; | |
| 888 | + } | |
| 889 | + if (&req->req != _req) { | |
| 890 | + ret = -EINVAL; | |
| 891 | + goto out; | |
| 892 | + } | |
| 893 | + | |
| 894 | + /* The request is in progress, or completed but not dequeued */ | |
| 895 | + if (ep->queue.next == &req->queue) { | |
| 896 | + _req->status = -ECONNRESET; | |
| 897 | + mv_u3d_ep_fifo_flush(_ep); | |
| 898 | + | |
| 899 | + /* The request isn't the last request in this ep queue */ | |
| 900 | + if (req->queue.next != &ep->queue) { | |
| 901 | + dev_dbg(u3d->dev, | |
| 902 | + "it is the last request in this ep queue\n"); | |
| 903 | + ep_context = ep->ep_context; | |
| 904 | + next_req = list_entry(req->queue.next, | |
| 905 | + struct mv_u3d_req, queue); | |
| 906 | + | |
| 907 | + /* Point first TRB of next request to the EP context. */ | |
| 908 | + iowrite32((u32) next_req->trb_head, | |
| 909 | + &ep_context->trb_addr_lo); | |
| 910 | + } else { | |
| 911 | + struct mv_u3d_ep_context *ep_context; | |
| 912 | + ep_context = ep->ep_context; | |
| 913 | + ep_context->trb_addr_lo = 0; | |
| 914 | + ep_context->trb_addr_hi = 0; | |
| 915 | + } | |
| 916 | + | |
| 917 | + } else | |
| 918 | + WARN_ON(1); | |
| 919 | + | |
| 920 | + mv_u3d_done(ep, req, -ECONNRESET); | |
| 921 | + | |
| 922 | + /* remove the req from the ep req list */ | |
| 923 | + if (!list_empty(&ep->req_list)) { | |
| 924 | + struct mv_u3d_req *curr_req; | |
| 925 | + curr_req = list_entry(ep->req_list.next, | |
| 926 | + struct mv_u3d_req, list); | |
| 927 | + if (curr_req == req) { | |
| 928 | + list_del_init(&req->list); | |
| 929 | + ep->processing = 0; | |
| 930 | + } | |
| 931 | + } | |
| 932 | + | |
| 933 | +out: | |
| 934 | + spin_unlock_irqrestore(&ep->u3d->lock, flags); | |
| 935 | + return ret; | |
| 936 | +} | |
| 937 | + | |
| 938 | +static void | |
| 939 | +mv_u3d_ep_set_stall(struct mv_u3d *u3d, u8 ep_num, u8 direction, int stall) | |
| 940 | +{ | |
| 941 | + u32 tmp; | |
| 942 | + struct mv_u3d_ep *ep = u3d->eps; | |
| 943 | + | |
| 944 | + dev_dbg(u3d->dev, "%s\n", __func__); | |
| 945 | + if (direction == MV_U3D_EP_DIR_OUT) { | |
| 946 | + tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 947 | + if (stall) | |
| 948 | + tmp |= MV_U3D_EPXCR_EP_HALT; | |
| 949 | + else | |
| 950 | + tmp &= ~MV_U3D_EPXCR_EP_HALT; | |
| 951 | + iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0); | |
| 952 | + } else { | |
| 953 | + tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 954 | + if (stall) | |
| 955 | + tmp |= MV_U3D_EPXCR_EP_HALT; | |
| 956 | + else | |
| 957 | + tmp &= ~MV_U3D_EPXCR_EP_HALT; | |
| 958 | + iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0); | |
| 959 | + } | |
| 960 | +} | |
| 961 | + | |
| 962 | +static int mv_u3d_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) | |
| 963 | +{ | |
| 964 | + struct mv_u3d_ep *ep; | |
| 965 | + unsigned long flags = 0; | |
| 966 | + int status = 0; | |
| 967 | + struct mv_u3d *u3d; | |
| 968 | + | |
| 969 | + ep = container_of(_ep, struct mv_u3d_ep, ep); | |
| 970 | + u3d = ep->u3d; | |
| 971 | + if (!ep->ep.desc) { | |
| 972 | + status = -EINVAL; | |
| 973 | + goto out; | |
| 974 | + } | |
| 975 | + | |
| 976 | + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { | |
| 977 | + status = -EOPNOTSUPP; | |
| 978 | + goto out; | |
| 979 | + } | |
| 980 | + | |
| 981 | + /* | |
| 982 | + * Attempt to halt IN ep will fail if any transfer requests | |
| 983 | + * are still queue | |
| 984 | + */ | |
| 985 | + if (halt && (mv_u3d_ep_dir(ep) == MV_U3D_EP_DIR_IN) | |
| 986 | + && !list_empty(&ep->queue)) { | |
| 987 | + status = -EAGAIN; | |
| 988 | + goto out; | |
| 989 | + } | |
| 990 | + | |
| 991 | + spin_lock_irqsave(&ep->u3d->lock, flags); | |
| 992 | + mv_u3d_ep_set_stall(u3d, ep->ep_num, mv_u3d_ep_dir(ep), halt); | |
| 993 | + if (halt && wedge) | |
| 994 | + ep->wedge = 1; | |
| 995 | + else if (!halt) | |
| 996 | + ep->wedge = 0; | |
| 997 | + spin_unlock_irqrestore(&ep->u3d->lock, flags); | |
| 998 | + | |
| 999 | + if (ep->ep_num == 0) | |
| 1000 | + u3d->ep0_dir = MV_U3D_EP_DIR_OUT; | |
| 1001 | +out: | |
| 1002 | + return status; | |
| 1003 | +} | |
| 1004 | + | |
| 1005 | +static int mv_u3d_ep_set_halt(struct usb_ep *_ep, int halt) | |
| 1006 | +{ | |
| 1007 | + return mv_u3d_ep_set_halt_wedge(_ep, halt, 0); | |
| 1008 | +} | |
| 1009 | + | |
| 1010 | +static int mv_u3d_ep_set_wedge(struct usb_ep *_ep) | |
| 1011 | +{ | |
| 1012 | + return mv_u3d_ep_set_halt_wedge(_ep, 1, 1); | |
| 1013 | +} | |
| 1014 | + | |
| 1015 | +static struct usb_ep_ops mv_u3d_ep_ops = { | |
| 1016 | + .enable = mv_u3d_ep_enable, | |
| 1017 | + .disable = mv_u3d_ep_disable, | |
| 1018 | + | |
| 1019 | + .alloc_request = mv_u3d_alloc_request, | |
| 1020 | + .free_request = mv_u3d_free_request, | |
| 1021 | + | |
| 1022 | + .queue = mv_u3d_ep_queue, | |
| 1023 | + .dequeue = mv_u3d_ep_dequeue, | |
| 1024 | + | |
| 1025 | + .set_wedge = mv_u3d_ep_set_wedge, | |
| 1026 | + .set_halt = mv_u3d_ep_set_halt, | |
| 1027 | + .fifo_flush = mv_u3d_ep_fifo_flush, | |
| 1028 | +}; | |
| 1029 | + | |
| 1030 | +static void mv_u3d_controller_stop(struct mv_u3d *u3d) | |
| 1031 | +{ | |
| 1032 | + u32 tmp; | |
| 1033 | + | |
| 1034 | + if (!u3d->clock_gating && u3d->vbus_valid_detect) | |
| 1035 | + iowrite32(MV_U3D_INTR_ENABLE_VBUS_VALID, | |
| 1036 | + &u3d->vuc_regs->intrenable); | |
| 1037 | + else | |
| 1038 | + iowrite32(0, &u3d->vuc_regs->intrenable); | |
| 1039 | + iowrite32(~0x0, &u3d->vuc_regs->endcomplete); | |
| 1040 | + iowrite32(~0x0, &u3d->vuc_regs->trbunderrun); | |
| 1041 | + iowrite32(~0x0, &u3d->vuc_regs->trbcomplete); | |
| 1042 | + iowrite32(~0x0, &u3d->vuc_regs->linkchange); | |
| 1043 | + iowrite32(0x1, &u3d->vuc_regs->setuplock); | |
| 1044 | + | |
| 1045 | + /* Reset the RUN bit in the command register to stop USB */ | |
| 1046 | + tmp = ioread32(&u3d->op_regs->usbcmd); | |
| 1047 | + tmp &= ~MV_U3D_CMD_RUN_STOP; | |
| 1048 | + iowrite32(tmp, &u3d->op_regs->usbcmd); | |
| 1049 | + dev_dbg(u3d->dev, "after u3d_stop, USBCMD 0x%x\n", | |
| 1050 | + ioread32(&u3d->op_regs->usbcmd)); | |
| 1051 | +} | |
| 1052 | + | |
| 1053 | +static void mv_u3d_controller_start(struct mv_u3d *u3d) | |
| 1054 | +{ | |
| 1055 | + u32 usbintr; | |
| 1056 | + u32 temp; | |
| 1057 | + | |
| 1058 | + /* enable link LTSSM state machine */ | |
| 1059 | + temp = ioread32(&u3d->vuc_regs->ltssm); | |
| 1060 | + temp |= MV_U3D_LTSSM_PHY_INIT_DONE; | |
| 1061 | + iowrite32(temp, &u3d->vuc_regs->ltssm); | |
| 1062 | + | |
| 1063 | + /* Enable interrupts */ | |
| 1064 | + usbintr = MV_U3D_INTR_ENABLE_LINK_CHG | MV_U3D_INTR_ENABLE_TXDESC_ERR | | |
| 1065 | + MV_U3D_INTR_ENABLE_RXDESC_ERR | MV_U3D_INTR_ENABLE_TX_COMPLETE | | |
| 1066 | + MV_U3D_INTR_ENABLE_RX_COMPLETE | MV_U3D_INTR_ENABLE_SETUP | | |
| 1067 | + (u3d->vbus_valid_detect ? MV_U3D_INTR_ENABLE_VBUS_VALID : 0); | |
| 1068 | + iowrite32(usbintr, &u3d->vuc_regs->intrenable); | |
| 1069 | + | |
| 1070 | + /* Enable ctrl ep */ | |
| 1071 | + iowrite32(0x1, &u3d->vuc_regs->ctrlepenable); | |
| 1072 | + | |
| 1073 | + /* Set the Run bit in the command register */ | |
| 1074 | + iowrite32(MV_U3D_CMD_RUN_STOP, &u3d->op_regs->usbcmd); | |
| 1075 | + dev_dbg(u3d->dev, "after u3d_start, USBCMD 0x%x\n", | |
| 1076 | + ioread32(&u3d->op_regs->usbcmd)); | |
| 1077 | +} | |
| 1078 | + | |
| 1079 | +static int mv_u3d_controller_reset(struct mv_u3d *u3d) | |
| 1080 | +{ | |
| 1081 | + unsigned int loops; | |
| 1082 | + u32 tmp; | |
| 1083 | + | |
| 1084 | + /* Stop the controller */ | |
| 1085 | + tmp = ioread32(&u3d->op_regs->usbcmd); | |
| 1086 | + tmp &= ~MV_U3D_CMD_RUN_STOP; | |
| 1087 | + iowrite32(tmp, &u3d->op_regs->usbcmd); | |
| 1088 | + | |
| 1089 | + /* Reset the controller to get default values */ | |
| 1090 | + iowrite32(MV_U3D_CMD_CTRL_RESET, &u3d->op_regs->usbcmd); | |
| 1091 | + | |
| 1092 | + /* wait for reset to complete */ | |
| 1093 | + loops = LOOPS(MV_U3D_RESET_TIMEOUT); | |
| 1094 | + while (ioread32(&u3d->op_regs->usbcmd) & MV_U3D_CMD_CTRL_RESET) { | |
| 1095 | + if (loops == 0) { | |
| 1096 | + dev_err(u3d->dev, | |
| 1097 | + "Wait for RESET completed TIMEOUT\n"); | |
| 1098 | + return -ETIMEDOUT; | |
| 1099 | + } | |
| 1100 | + loops--; | |
| 1101 | + udelay(LOOPS_USEC); | |
| 1102 | + } | |
| 1103 | + | |
| 1104 | + /* Configure the Endpoint Context Address */ | |
| 1105 | + iowrite32(u3d->ep_context_dma, &u3d->op_regs->dcbaapl); | |
| 1106 | + iowrite32(0, &u3d->op_regs->dcbaaph); | |
| 1107 | + | |
| 1108 | + return 0; | |
| 1109 | +} | |
| 1110 | + | |
| 1111 | +static int mv_u3d_enable(struct mv_u3d *u3d) | |
| 1112 | +{ | |
| 1113 | + struct mv_usb_platform_data *pdata = u3d->dev->platform_data; | |
| 1114 | + int retval; | |
| 1115 | + | |
| 1116 | + if (u3d->active) | |
| 1117 | + return 0; | |
| 1118 | + | |
| 1119 | + if (!u3d->clock_gating) { | |
| 1120 | + u3d->active = 1; | |
| 1121 | + return 0; | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + dev_dbg(u3d->dev, "enable u3d\n"); | |
| 1125 | + clk_enable(u3d->clk); | |
| 1126 | + if (pdata->phy_init) { | |
| 1127 | + retval = pdata->phy_init(u3d->phy_regs); | |
| 1128 | + if (retval) { | |
| 1129 | + dev_err(u3d->dev, | |
| 1130 | + "init phy error %d\n", retval); | |
| 1131 | + clk_disable(u3d->clk); | |
| 1132 | + return retval; | |
| 1133 | + } | |
| 1134 | + } | |
| 1135 | + u3d->active = 1; | |
| 1136 | + | |
| 1137 | + return 0; | |
| 1138 | +} | |
| 1139 | + | |
| 1140 | +static void mv_u3d_disable(struct mv_u3d *u3d) | |
| 1141 | +{ | |
| 1142 | + struct mv_usb_platform_data *pdata = u3d->dev->platform_data; | |
| 1143 | + if (u3d->clock_gating && u3d->active) { | |
| 1144 | + dev_dbg(u3d->dev, "disable u3d\n"); | |
| 1145 | + if (pdata->phy_deinit) | |
| 1146 | + pdata->phy_deinit(u3d->phy_regs); | |
| 1147 | + clk_disable(u3d->clk); | |
| 1148 | + u3d->active = 0; | |
| 1149 | + } | |
| 1150 | +} | |
| 1151 | + | |
| 1152 | +static int mv_u3d_vbus_session(struct usb_gadget *gadget, int is_active) | |
| 1153 | +{ | |
| 1154 | + struct mv_u3d *u3d; | |
| 1155 | + unsigned long flags; | |
| 1156 | + int retval = 0; | |
| 1157 | + | |
| 1158 | + u3d = container_of(gadget, struct mv_u3d, gadget); | |
| 1159 | + | |
| 1160 | + spin_lock_irqsave(&u3d->lock, flags); | |
| 1161 | + | |
| 1162 | + u3d->vbus_active = (is_active != 0); | |
| 1163 | + dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n", | |
| 1164 | + __func__, u3d->softconnect, u3d->vbus_active); | |
| 1165 | + /* | |
| 1166 | + * 1. external VBUS detect: we can disable/enable clock on demand. | |
| 1167 | + * 2. UDC VBUS detect: we have to enable clock all the time. | |
| 1168 | + * 3. No VBUS detect: we have to enable clock all the time. | |
| 1169 | + */ | |
| 1170 | + if (u3d->driver && u3d->softconnect && u3d->vbus_active) { | |
| 1171 | + retval = mv_u3d_enable(u3d); | |
| 1172 | + if (retval == 0) { | |
| 1173 | + /* | |
| 1174 | + * after clock is disabled, we lost all the register | |
| 1175 | + * context. We have to re-init registers | |
| 1176 | + */ | |
| 1177 | + mv_u3d_controller_reset(u3d); | |
| 1178 | + mv_u3d_ep0_reset(u3d); | |
| 1179 | + mv_u3d_controller_start(u3d); | |
| 1180 | + } | |
| 1181 | + } else if (u3d->driver && u3d->softconnect) { | |
| 1182 | + if (!u3d->active) | |
| 1183 | + goto out; | |
| 1184 | + | |
| 1185 | + /* stop all the transfer in queue*/ | |
| 1186 | + mv_u3d_stop_activity(u3d, u3d->driver); | |
| 1187 | + mv_u3d_controller_stop(u3d); | |
| 1188 | + mv_u3d_disable(u3d); | |
| 1189 | + } | |
| 1190 | + | |
| 1191 | +out: | |
| 1192 | + spin_unlock_irqrestore(&u3d->lock, flags); | |
| 1193 | + return retval; | |
| 1194 | +} | |
| 1195 | + | |
| 1196 | +/* constrain controller's VBUS power usage | |
| 1197 | + * This call is used by gadget drivers during SET_CONFIGURATION calls, | |
| 1198 | + * reporting how much power the device may consume. For example, this | |
| 1199 | + * could affect how quickly batteries are recharged. | |
| 1200 | + * | |
| 1201 | + * Returns zero on success, else negative errno. | |
| 1202 | + */ | |
| 1203 | +static int mv_u3d_vbus_draw(struct usb_gadget *gadget, unsigned mA) | |
| 1204 | +{ | |
| 1205 | + struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget); | |
| 1206 | + | |
| 1207 | + u3d->power = mA; | |
| 1208 | + | |
| 1209 | + return 0; | |
| 1210 | +} | |
| 1211 | + | |
| 1212 | +static int mv_u3d_pullup(struct usb_gadget *gadget, int is_on) | |
| 1213 | +{ | |
| 1214 | + struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget); | |
| 1215 | + unsigned long flags; | |
| 1216 | + int retval = 0; | |
| 1217 | + | |
| 1218 | + spin_lock_irqsave(&u3d->lock, flags); | |
| 1219 | + | |
| 1220 | + dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n", | |
| 1221 | + __func__, u3d->softconnect, u3d->vbus_active); | |
| 1222 | + u3d->softconnect = (is_on != 0); | |
| 1223 | + if (u3d->driver && u3d->softconnect && u3d->vbus_active) { | |
| 1224 | + retval = mv_u3d_enable(u3d); | |
| 1225 | + if (retval == 0) { | |
| 1226 | + /* | |
| 1227 | + * after clock is disabled, we lost all the register | |
| 1228 | + * context. We have to re-init registers | |
| 1229 | + */ | |
| 1230 | + mv_u3d_controller_reset(u3d); | |
| 1231 | + mv_u3d_ep0_reset(u3d); | |
| 1232 | + mv_u3d_controller_start(u3d); | |
| 1233 | + } | |
| 1234 | + } else if (u3d->driver && u3d->vbus_active) { | |
| 1235 | + /* stop all the transfer in queue*/ | |
| 1236 | + mv_u3d_stop_activity(u3d, u3d->driver); | |
| 1237 | + mv_u3d_controller_stop(u3d); | |
| 1238 | + mv_u3d_disable(u3d); | |
| 1239 | + } | |
| 1240 | + | |
| 1241 | + spin_unlock_irqrestore(&u3d->lock, flags); | |
| 1242 | + | |
| 1243 | + return retval; | |
| 1244 | +} | |
| 1245 | + | |
| 1246 | +static int mv_u3d_start(struct usb_gadget *g, | |
| 1247 | + struct usb_gadget_driver *driver) | |
| 1248 | +{ | |
| 1249 | + struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget); | |
| 1250 | + struct mv_usb_platform_data *pdata = u3d->dev->platform_data; | |
| 1251 | + unsigned long flags; | |
| 1252 | + | |
| 1253 | + if (u3d->driver) | |
| 1254 | + return -EBUSY; | |
| 1255 | + | |
| 1256 | + spin_lock_irqsave(&u3d->lock, flags); | |
| 1257 | + | |
| 1258 | + if (!u3d->clock_gating) { | |
| 1259 | + clk_enable(u3d->clk); | |
| 1260 | + if (pdata->phy_init) | |
| 1261 | + pdata->phy_init(u3d->phy_regs); | |
| 1262 | + } | |
| 1263 | + | |
| 1264 | + /* hook up the driver ... */ | |
| 1265 | + driver->driver.bus = NULL; | |
| 1266 | + u3d->driver = driver; | |
| 1267 | + u3d->gadget.dev.driver = &driver->driver; | |
| 1268 | + | |
| 1269 | + u3d->ep0_dir = USB_DIR_OUT; | |
| 1270 | + | |
| 1271 | + spin_unlock_irqrestore(&u3d->lock, flags); | |
| 1272 | + | |
| 1273 | + u3d->vbus_valid_detect = 1; | |
| 1274 | + | |
| 1275 | + return 0; | |
| 1276 | +} | |
| 1277 | + | |
| 1278 | +static int mv_u3d_stop(struct usb_gadget *g, | |
| 1279 | + struct usb_gadget_driver *driver) | |
| 1280 | +{ | |
| 1281 | + struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget); | |
| 1282 | + struct mv_usb_platform_data *pdata = u3d->dev->platform_data; | |
| 1283 | + unsigned long flags; | |
| 1284 | + | |
| 1285 | + u3d->vbus_valid_detect = 0; | |
| 1286 | + spin_lock_irqsave(&u3d->lock, flags); | |
| 1287 | + | |
| 1288 | + /* enable clock to access controller register */ | |
| 1289 | + clk_enable(u3d->clk); | |
| 1290 | + if (pdata->phy_init) | |
| 1291 | + pdata->phy_init(u3d->phy_regs); | |
| 1292 | + | |
| 1293 | + mv_u3d_controller_stop(u3d); | |
| 1294 | + /* stop all usb activities */ | |
| 1295 | + u3d->gadget.speed = USB_SPEED_UNKNOWN; | |
| 1296 | + mv_u3d_stop_activity(u3d, driver); | |
| 1297 | + mv_u3d_disable(u3d); | |
| 1298 | + | |
| 1299 | + if (pdata->phy_deinit) | |
| 1300 | + pdata->phy_deinit(u3d->phy_regs); | |
| 1301 | + clk_disable(u3d->clk); | |
| 1302 | + | |
| 1303 | + spin_unlock_irqrestore(&u3d->lock, flags); | |
| 1304 | + | |
| 1305 | + u3d->gadget.dev.driver = NULL; | |
| 1306 | + u3d->driver = NULL; | |
| 1307 | + | |
| 1308 | + return 0; | |
| 1309 | +} | |
| 1310 | + | |
| 1311 | +/* device controller usb_gadget_ops structure */ | |
| 1312 | +static const struct usb_gadget_ops mv_u3d_ops = { | |
| 1313 | + /* notify controller that VBUS is powered or not */ | |
| 1314 | + .vbus_session = mv_u3d_vbus_session, | |
| 1315 | + | |
| 1316 | + /* constrain controller's VBUS power usage */ | |
| 1317 | + .vbus_draw = mv_u3d_vbus_draw, | |
| 1318 | + | |
| 1319 | + .pullup = mv_u3d_pullup, | |
| 1320 | + .udc_start = mv_u3d_start, | |
| 1321 | + .udc_stop = mv_u3d_stop, | |
| 1322 | +}; | |
| 1323 | + | |
| 1324 | +static int mv_u3d_eps_init(struct mv_u3d *u3d) | |
| 1325 | +{ | |
| 1326 | + struct mv_u3d_ep *ep; | |
| 1327 | + char name[14]; | |
| 1328 | + int i; | |
| 1329 | + | |
| 1330 | + /* initialize ep0, ep0 in/out use eps[1] */ | |
| 1331 | + ep = &u3d->eps[1]; | |
| 1332 | + ep->u3d = u3d; | |
| 1333 | + strncpy(ep->name, "ep0", sizeof(ep->name)); | |
| 1334 | + ep->ep.name = ep->name; | |
| 1335 | + ep->ep.ops = &mv_u3d_ep_ops; | |
| 1336 | + ep->wedge = 0; | |
| 1337 | + ep->ep.maxpacket = MV_U3D_EP0_MAX_PKT_SIZE; | |
| 1338 | + ep->ep_num = 0; | |
| 1339 | + ep->ep.desc = &mv_u3d_ep0_desc; | |
| 1340 | + INIT_LIST_HEAD(&ep->queue); | |
| 1341 | + INIT_LIST_HEAD(&ep->req_list); | |
| 1342 | + ep->ep_type = USB_ENDPOINT_XFER_CONTROL; | |
| 1343 | + | |
| 1344 | + /* add ep0 ep_context */ | |
| 1345 | + ep->ep_context = &u3d->ep_context[1]; | |
| 1346 | + | |
| 1347 | + /* initialize other endpoints */ | |
| 1348 | + for (i = 2; i < u3d->max_eps * 2; i++) { | |
| 1349 | + ep = &u3d->eps[i]; | |
| 1350 | + if (i & 1) { | |
| 1351 | + snprintf(name, sizeof(name), "ep%din", i >> 1); | |
| 1352 | + ep->direction = MV_U3D_EP_DIR_IN; | |
| 1353 | + } else { | |
| 1354 | + snprintf(name, sizeof(name), "ep%dout", i >> 1); | |
| 1355 | + ep->direction = MV_U3D_EP_DIR_OUT; | |
| 1356 | + } | |
| 1357 | + ep->u3d = u3d; | |
| 1358 | + strncpy(ep->name, name, sizeof(ep->name)); | |
| 1359 | + ep->ep.name = ep->name; | |
| 1360 | + | |
| 1361 | + ep->ep.ops = &mv_u3d_ep_ops; | |
| 1362 | + ep->ep.maxpacket = (unsigned short) ~0; | |
| 1363 | + ep->ep_num = i / 2; | |
| 1364 | + | |
| 1365 | + INIT_LIST_HEAD(&ep->queue); | |
| 1366 | + list_add_tail(&ep->ep.ep_list, &u3d->gadget.ep_list); | |
| 1367 | + | |
| 1368 | + INIT_LIST_HEAD(&ep->req_list); | |
| 1369 | + spin_lock_init(&ep->req_lock); | |
| 1370 | + ep->ep_context = &u3d->ep_context[i]; | |
| 1371 | + } | |
| 1372 | + | |
| 1373 | + return 0; | |
| 1374 | +} | |
| 1375 | + | |
| 1376 | +/* delete all endpoint requests, called with spinlock held */ | |
| 1377 | +static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status) | |
| 1378 | +{ | |
| 1379 | + /* endpoint fifo flush */ | |
| 1380 | + mv_u3d_ep_fifo_flush(&ep->ep); | |
| 1381 | + | |
| 1382 | + while (!list_empty(&ep->queue)) { | |
| 1383 | + struct mv_u3d_req *req = NULL; | |
| 1384 | + req = list_entry(ep->queue.next, struct mv_u3d_req, queue); | |
| 1385 | + mv_u3d_done(ep, req, status); | |
| 1386 | + } | |
| 1387 | +} | |
| 1388 | + | |
| 1389 | +/* stop all USB activities */ | |
| 1390 | +static | |
| 1391 | +void mv_u3d_stop_activity(struct mv_u3d *u3d, struct usb_gadget_driver *driver) | |
| 1392 | +{ | |
| 1393 | + struct mv_u3d_ep *ep; | |
| 1394 | + | |
| 1395 | + mv_u3d_nuke(&u3d->eps[1], -ESHUTDOWN); | |
| 1396 | + | |
| 1397 | + list_for_each_entry(ep, &u3d->gadget.ep_list, ep.ep_list) { | |
| 1398 | + mv_u3d_nuke(ep, -ESHUTDOWN); | |
| 1399 | + } | |
| 1400 | + | |
| 1401 | + /* report disconnect; the driver is already quiesced */ | |
| 1402 | + if (driver) { | |
| 1403 | + spin_unlock(&u3d->lock); | |
| 1404 | + driver->disconnect(&u3d->gadget); | |
| 1405 | + spin_lock(&u3d->lock); | |
| 1406 | + } | |
| 1407 | +} | |
| 1408 | + | |
| 1409 | +static void mv_u3d_irq_process_error(struct mv_u3d *u3d) | |
| 1410 | +{ | |
| 1411 | + /* Increment the error count */ | |
| 1412 | + u3d->errors++; | |
| 1413 | + dev_err(u3d->dev, "%s\n", __func__); | |
| 1414 | +} | |
| 1415 | + | |
| 1416 | +static void mv_u3d_irq_process_link_change(struct mv_u3d *u3d) | |
| 1417 | +{ | |
| 1418 | + u32 linkchange; | |
| 1419 | + | |
| 1420 | + linkchange = ioread32(&u3d->vuc_regs->linkchange); | |
| 1421 | + iowrite32(linkchange, &u3d->vuc_regs->linkchange); | |
| 1422 | + | |
| 1423 | + dev_dbg(u3d->dev, "linkchange: 0x%x\n", linkchange); | |
| 1424 | + | |
| 1425 | + if (linkchange & MV_U3D_LINK_CHANGE_LINK_UP) { | |
| 1426 | + dev_dbg(u3d->dev, "link up: ltssm state: 0x%x\n", | |
| 1427 | + ioread32(&u3d->vuc_regs->ltssmstate)); | |
| 1428 | + | |
| 1429 | + u3d->usb_state = USB_STATE_DEFAULT; | |
| 1430 | + u3d->ep0_dir = MV_U3D_EP_DIR_OUT; | |
| 1431 | + u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP; | |
| 1432 | + | |
| 1433 | + /* set speed */ | |
| 1434 | + u3d->gadget.speed = USB_SPEED_SUPER; | |
| 1435 | + } | |
| 1436 | + | |
| 1437 | + if (linkchange & MV_U3D_LINK_CHANGE_SUSPEND) { | |
| 1438 | + dev_dbg(u3d->dev, "link suspend\n"); | |
| 1439 | + u3d->resume_state = u3d->usb_state; | |
| 1440 | + u3d->usb_state = USB_STATE_SUSPENDED; | |
| 1441 | + } | |
| 1442 | + | |
| 1443 | + if (linkchange & MV_U3D_LINK_CHANGE_RESUME) { | |
| 1444 | + dev_dbg(u3d->dev, "link resume\n"); | |
| 1445 | + u3d->usb_state = u3d->resume_state; | |
| 1446 | + u3d->resume_state = 0; | |
| 1447 | + } | |
| 1448 | + | |
| 1449 | + if (linkchange & MV_U3D_LINK_CHANGE_WRESET) { | |
| 1450 | + dev_dbg(u3d->dev, "warm reset\n"); | |
| 1451 | + u3d->usb_state = USB_STATE_POWERED; | |
| 1452 | + } | |
| 1453 | + | |
| 1454 | + if (linkchange & MV_U3D_LINK_CHANGE_HRESET) { | |
| 1455 | + dev_dbg(u3d->dev, "hot reset\n"); | |
| 1456 | + u3d->usb_state = USB_STATE_DEFAULT; | |
| 1457 | + } | |
| 1458 | + | |
| 1459 | + if (linkchange & MV_U3D_LINK_CHANGE_INACT) | |
| 1460 | + dev_dbg(u3d->dev, "inactive\n"); | |
| 1461 | + | |
| 1462 | + if (linkchange & MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0) | |
| 1463 | + dev_dbg(u3d->dev, "ss.disabled\n"); | |
| 1464 | + | |
| 1465 | + if (linkchange & MV_U3D_LINK_CHANGE_VBUS_INVALID) { | |
| 1466 | + dev_dbg(u3d->dev, "vbus invalid\n"); | |
| 1467 | + u3d->usb_state = USB_STATE_ATTACHED; | |
| 1468 | + u3d->vbus_valid_detect = 1; | |
| 1469 | + /* if external vbus detect is not supported, | |
| 1470 | + * we handle it here. | |
| 1471 | + */ | |
| 1472 | + if (!u3d->vbus) { | |
| 1473 | + spin_unlock(&u3d->lock); | |
| 1474 | + mv_u3d_vbus_session(&u3d->gadget, 0); | |
| 1475 | + spin_lock(&u3d->lock); | |
| 1476 | + } | |
| 1477 | + } | |
| 1478 | +} | |
| 1479 | + | |
| 1480 | +static void mv_u3d_ch9setaddress(struct mv_u3d *u3d, | |
| 1481 | + struct usb_ctrlrequest *setup) | |
| 1482 | +{ | |
| 1483 | + u32 tmp; | |
| 1484 | + | |
| 1485 | + if (u3d->usb_state != USB_STATE_DEFAULT) { | |
| 1486 | + dev_err(u3d->dev, | |
| 1487 | + "%s, cannot setaddr in this state (%d)\n", | |
| 1488 | + __func__, u3d->usb_state); | |
| 1489 | + goto err; | |
| 1490 | + } | |
| 1491 | + | |
| 1492 | + u3d->dev_addr = (u8)setup->wValue; | |
| 1493 | + | |
| 1494 | + dev_dbg(u3d->dev, "%s: 0x%x\n", __func__, u3d->dev_addr); | |
| 1495 | + | |
| 1496 | + if (u3d->dev_addr > 127) { | |
| 1497 | + dev_err(u3d->dev, | |
| 1498 | + "%s, u3d address is wrong (out of range)\n", __func__); | |
| 1499 | + u3d->dev_addr = 0; | |
| 1500 | + goto err; | |
| 1501 | + } | |
| 1502 | + | |
| 1503 | + /* update usb state */ | |
| 1504 | + u3d->usb_state = USB_STATE_ADDRESS; | |
| 1505 | + | |
| 1506 | + /* set the new address */ | |
| 1507 | + tmp = ioread32(&u3d->vuc_regs->devaddrtiebrkr); | |
| 1508 | + tmp &= ~0x7F; | |
| 1509 | + tmp |= (u32)u3d->dev_addr; | |
| 1510 | + iowrite32(tmp, &u3d->vuc_regs->devaddrtiebrkr); | |
| 1511 | + | |
| 1512 | + return; | |
| 1513 | +err: | |
| 1514 | + mv_u3d_ep0_stall(u3d); | |
| 1515 | +} | |
| 1516 | + | |
| 1517 | +static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup) | |
| 1518 | +{ | |
| 1519 | + if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | |
| 1520 | + if (setup->bRequest == USB_REQ_SET_CONFIGURATION) | |
| 1521 | + return 1; | |
| 1522 | + | |
| 1523 | + return 0; | |
| 1524 | +} | |
| 1525 | + | |
| 1526 | +static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num, | |
| 1527 | + struct usb_ctrlrequest *setup) | |
| 1528 | +{ | |
| 1529 | + bool delegate = false; | |
| 1530 | + | |
| 1531 | + mv_u3d_nuke(&u3d->eps[ep_num * 2 + MV_U3D_EP_DIR_IN], -ESHUTDOWN); | |
| 1532 | + | |
| 1533 | + dev_dbg(u3d->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", | |
| 1534 | + setup->bRequestType, setup->bRequest, | |
| 1535 | + setup->wValue, setup->wIndex, setup->wLength); | |
| 1536 | + | |
| 1537 | + /* We process some stardard setup requests here */ | |
| 1538 | + if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | |
| 1539 | + switch (setup->bRequest) { | |
| 1540 | + case USB_REQ_GET_STATUS: | |
| 1541 | + delegate = true; | |
| 1542 | + break; | |
| 1543 | + | |
| 1544 | + case USB_REQ_SET_ADDRESS: | |
| 1545 | + mv_u3d_ch9setaddress(u3d, setup); | |
| 1546 | + break; | |
| 1547 | + | |
| 1548 | + case USB_REQ_CLEAR_FEATURE: | |
| 1549 | + delegate = true; | |
| 1550 | + break; | |
| 1551 | + | |
| 1552 | + case USB_REQ_SET_FEATURE: | |
| 1553 | + delegate = true; | |
| 1554 | + break; | |
| 1555 | + | |
| 1556 | + default: | |
| 1557 | + delegate = true; | |
| 1558 | + } | |
| 1559 | + } else | |
| 1560 | + delegate = true; | |
| 1561 | + | |
| 1562 | + /* delegate USB standard requests to the gadget driver */ | |
| 1563 | + if (delegate == true) { | |
| 1564 | + /* USB requests handled by gadget */ | |
| 1565 | + if (setup->wLength) { | |
| 1566 | + /* DATA phase from gadget, STATUS phase from u3d */ | |
| 1567 | + u3d->ep0_dir = (setup->bRequestType & USB_DIR_IN) | |
| 1568 | + ? MV_U3D_EP_DIR_IN : MV_U3D_EP_DIR_OUT; | |
| 1569 | + spin_unlock(&u3d->lock); | |
| 1570 | + if (u3d->driver->setup(&u3d->gadget, | |
| 1571 | + &u3d->local_setup_buff) < 0) { | |
| 1572 | + dev_err(u3d->dev, "setup error!\n"); | |
| 1573 | + mv_u3d_ep0_stall(u3d); | |
| 1574 | + } | |
| 1575 | + spin_lock(&u3d->lock); | |
| 1576 | + } else { | |
| 1577 | + /* no DATA phase, STATUS phase from gadget */ | |
| 1578 | + u3d->ep0_dir = MV_U3D_EP_DIR_IN; | |
| 1579 | + u3d->ep0_state = MV_U3D_STATUS_STAGE; | |
| 1580 | + spin_unlock(&u3d->lock); | |
| 1581 | + if (u3d->driver->setup(&u3d->gadget, | |
| 1582 | + &u3d->local_setup_buff) < 0) | |
| 1583 | + mv_u3d_ep0_stall(u3d); | |
| 1584 | + spin_lock(&u3d->lock); | |
| 1585 | + } | |
| 1586 | + | |
| 1587 | + if (mv_u3d_is_set_configuration(setup)) { | |
| 1588 | + dev_dbg(u3d->dev, "u3d configured\n"); | |
| 1589 | + u3d->usb_state = USB_STATE_CONFIGURED; | |
| 1590 | + } | |
| 1591 | + } | |
| 1592 | +} | |
| 1593 | + | |
| 1594 | +static void mv_u3d_get_setup_data(struct mv_u3d *u3d, u8 ep_num, u8 *buffer_ptr) | |
| 1595 | +{ | |
| 1596 | + struct mv_u3d_ep_context *epcontext; | |
| 1597 | + | |
| 1598 | + epcontext = &u3d->ep_context[ep_num * 2 + MV_U3D_EP_DIR_IN]; | |
| 1599 | + | |
| 1600 | + /* Copy the setup packet to local buffer */ | |
| 1601 | + memcpy(buffer_ptr, (u8 *) &epcontext->setup_buffer, 8); | |
| 1602 | +} | |
| 1603 | + | |
| 1604 | +static void mv_u3d_irq_process_setup(struct mv_u3d *u3d) | |
| 1605 | +{ | |
| 1606 | + u32 tmp, i; | |
| 1607 | + /* Process all Setup packet received interrupts */ | |
| 1608 | + tmp = ioread32(&u3d->vuc_regs->setuplock); | |
| 1609 | + if (tmp) { | |
| 1610 | + for (i = 0; i < u3d->max_eps; i++) { | |
| 1611 | + if (tmp & (1 << i)) { | |
| 1612 | + mv_u3d_get_setup_data(u3d, i, | |
| 1613 | + (u8 *)(&u3d->local_setup_buff)); | |
| 1614 | + mv_u3d_handle_setup_packet(u3d, i, | |
| 1615 | + &u3d->local_setup_buff); | |
| 1616 | + } | |
| 1617 | + } | |
| 1618 | + } | |
| 1619 | + | |
| 1620 | + iowrite32(tmp, &u3d->vuc_regs->setuplock); | |
| 1621 | +} | |
| 1622 | + | |
| 1623 | +static void mv_u3d_irq_process_tr_complete(struct mv_u3d *u3d) | |
| 1624 | +{ | |
| 1625 | + u32 tmp, bit_pos; | |
| 1626 | + int i, ep_num = 0, direction = 0; | |
| 1627 | + struct mv_u3d_ep *curr_ep; | |
| 1628 | + struct mv_u3d_req *curr_req, *temp_req; | |
| 1629 | + int status; | |
| 1630 | + | |
| 1631 | + tmp = ioread32(&u3d->vuc_regs->endcomplete); | |
| 1632 | + | |
| 1633 | + dev_dbg(u3d->dev, "tr_complete: ep: 0x%x\n", tmp); | |
| 1634 | + if (!tmp) | |
| 1635 | + return; | |
| 1636 | + iowrite32(tmp, &u3d->vuc_regs->endcomplete); | |
| 1637 | + | |
| 1638 | + for (i = 0; i < u3d->max_eps * 2; i++) { | |
| 1639 | + ep_num = i >> 1; | |
| 1640 | + direction = i % 2; | |
| 1641 | + | |
| 1642 | + bit_pos = 1 << (ep_num + 16 * direction); | |
| 1643 | + | |
| 1644 | + if (!(bit_pos & tmp)) | |
| 1645 | + continue; | |
| 1646 | + | |
| 1647 | + if (i == 0) | |
| 1648 | + curr_ep = &u3d->eps[1]; | |
| 1649 | + else | |
| 1650 | + curr_ep = &u3d->eps[i]; | |
| 1651 | + | |
| 1652 | + /* remove req out of ep request list after completion */ | |
| 1653 | + dev_dbg(u3d->dev, "tr comp: check req_list\n"); | |
| 1654 | + spin_lock(&curr_ep->req_lock); | |
| 1655 | + if (!list_empty(&curr_ep->req_list)) { | |
| 1656 | + struct mv_u3d_req *req; | |
| 1657 | + req = list_entry(curr_ep->req_list.next, | |
| 1658 | + struct mv_u3d_req, list); | |
| 1659 | + list_del_init(&req->list); | |
| 1660 | + curr_ep->processing = 0; | |
| 1661 | + } | |
| 1662 | + spin_unlock(&curr_ep->req_lock); | |
| 1663 | + | |
| 1664 | + /* process the req queue until an uncomplete request */ | |
| 1665 | + list_for_each_entry_safe(curr_req, temp_req, | |
| 1666 | + &curr_ep->queue, queue) { | |
| 1667 | + status = mv_u3d_process_ep_req(u3d, i, curr_req); | |
| 1668 | + if (status) | |
| 1669 | + break; | |
| 1670 | + /* write back status to req */ | |
| 1671 | + curr_req->req.status = status; | |
| 1672 | + | |
| 1673 | + /* ep0 request completion */ | |
| 1674 | + if (ep_num == 0) { | |
| 1675 | + mv_u3d_done(curr_ep, curr_req, 0); | |
| 1676 | + break; | |
| 1677 | + } else { | |
| 1678 | + mv_u3d_done(curr_ep, curr_req, status); | |
| 1679 | + } | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + dev_dbg(u3d->dev, "call mv_u3d_start_queue from ep complete\n"); | |
| 1683 | + mv_u3d_start_queue(curr_ep); | |
| 1684 | + } | |
| 1685 | +} | |
| 1686 | + | |
| 1687 | +static irqreturn_t mv_u3d_irq(int irq, void *dev) | |
| 1688 | +{ | |
| 1689 | + struct mv_u3d *u3d = (struct mv_u3d *)dev; | |
| 1690 | + u32 status, intr; | |
| 1691 | + u32 bridgesetting; | |
| 1692 | + u32 trbunderrun; | |
| 1693 | + | |
| 1694 | + spin_lock(&u3d->lock); | |
| 1695 | + | |
| 1696 | + status = ioread32(&u3d->vuc_regs->intrcause); | |
| 1697 | + intr = ioread32(&u3d->vuc_regs->intrenable); | |
| 1698 | + status &= intr; | |
| 1699 | + | |
| 1700 | + if (status == 0) { | |
| 1701 | + spin_unlock(&u3d->lock); | |
| 1702 | + dev_err(u3d->dev, "irq error!\n"); | |
| 1703 | + return IRQ_NONE; | |
| 1704 | + } | |
| 1705 | + | |
| 1706 | + if (status & MV_U3D_USBINT_VBUS_VALID) { | |
| 1707 | + bridgesetting = ioread32(&u3d->vuc_regs->bridgesetting); | |
| 1708 | + if (bridgesetting & MV_U3D_BRIDGE_SETTING_VBUS_VALID) { | |
| 1709 | + /* write vbus valid bit of bridge setting to clear */ | |
| 1710 | + bridgesetting = MV_U3D_BRIDGE_SETTING_VBUS_VALID; | |
| 1711 | + iowrite32(bridgesetting, &u3d->vuc_regs->bridgesetting); | |
| 1712 | + dev_dbg(u3d->dev, "vbus valid\n"); | |
| 1713 | + | |
| 1714 | + u3d->usb_state = USB_STATE_POWERED; | |
| 1715 | + u3d->vbus_valid_detect = 0; | |
| 1716 | + /* if external vbus detect is not supported, | |
| 1717 | + * we handle it here. | |
| 1718 | + */ | |
| 1719 | + if (!u3d->vbus) { | |
| 1720 | + spin_unlock(&u3d->lock); | |
| 1721 | + mv_u3d_vbus_session(&u3d->gadget, 1); | |
| 1722 | + spin_lock(&u3d->lock); | |
| 1723 | + } | |
| 1724 | + } else | |
| 1725 | + dev_err(u3d->dev, "vbus bit is not set\n"); | |
| 1726 | + } | |
| 1727 | + | |
| 1728 | + /* RX data is already in the 16KB FIFO.*/ | |
| 1729 | + if (status & MV_U3D_USBINT_UNDER_RUN) { | |
| 1730 | + trbunderrun = ioread32(&u3d->vuc_regs->trbunderrun); | |
| 1731 | + dev_err(u3d->dev, "under run, ep%d\n", trbunderrun); | |
| 1732 | + iowrite32(trbunderrun, &u3d->vuc_regs->trbunderrun); | |
| 1733 | + mv_u3d_irq_process_error(u3d); | |
| 1734 | + } | |
| 1735 | + | |
| 1736 | + if (status & (MV_U3D_USBINT_RXDESC_ERR | MV_U3D_USBINT_TXDESC_ERR)) { | |
| 1737 | + /* write one to clear */ | |
| 1738 | + iowrite32(status & (MV_U3D_USBINT_RXDESC_ERR | |
| 1739 | + | MV_U3D_USBINT_TXDESC_ERR), | |
| 1740 | + &u3d->vuc_regs->intrcause); | |
| 1741 | + dev_err(u3d->dev, "desc err 0x%x\n", status); | |
| 1742 | + mv_u3d_irq_process_error(u3d); | |
| 1743 | + } | |
| 1744 | + | |
| 1745 | + if (status & MV_U3D_USBINT_LINK_CHG) | |
| 1746 | + mv_u3d_irq_process_link_change(u3d); | |
| 1747 | + | |
| 1748 | + if (status & MV_U3D_USBINT_TX_COMPLETE) | |
| 1749 | + mv_u3d_irq_process_tr_complete(u3d); | |
| 1750 | + | |
| 1751 | + if (status & MV_U3D_USBINT_RX_COMPLETE) | |
| 1752 | + mv_u3d_irq_process_tr_complete(u3d); | |
| 1753 | + | |
| 1754 | + if (status & MV_U3D_USBINT_SETUP) | |
| 1755 | + mv_u3d_irq_process_setup(u3d); | |
| 1756 | + | |
| 1757 | + spin_unlock(&u3d->lock); | |
| 1758 | + return IRQ_HANDLED; | |
| 1759 | +} | |
| 1760 | + | |
| 1761 | +static void mv_u3d_gadget_release(struct device *dev) | |
| 1762 | +{ | |
| 1763 | + dev_dbg(dev, "%s\n", __func__); | |
| 1764 | +} | |
| 1765 | + | |
| 1766 | +static __devexit int mv_u3d_remove(struct platform_device *dev) | |
| 1767 | +{ | |
| 1768 | + struct mv_u3d *u3d = platform_get_drvdata(dev); | |
| 1769 | + | |
| 1770 | + BUG_ON(u3d == NULL); | |
| 1771 | + | |
| 1772 | + usb_del_gadget_udc(&u3d->gadget); | |
| 1773 | + | |
| 1774 | + /* free memory allocated in probe */ | |
| 1775 | + if (u3d->trb_pool) | |
| 1776 | + dma_pool_destroy(u3d->trb_pool); | |
| 1777 | + | |
| 1778 | + if (u3d->ep_context) | |
| 1779 | + dma_free_coherent(&dev->dev, u3d->ep_context_size, | |
| 1780 | + u3d->ep_context, u3d->ep_context_dma); | |
| 1781 | + | |
| 1782 | + kfree(u3d->eps); | |
| 1783 | + | |
| 1784 | + if (u3d->irq) | |
| 1785 | + free_irq(u3d->irq, &dev->dev); | |
| 1786 | + | |
| 1787 | + if (u3d->cap_regs) | |
| 1788 | + iounmap(u3d->cap_regs); | |
| 1789 | + u3d->cap_regs = NULL; | |
| 1790 | + | |
| 1791 | + kfree(u3d->status_req); | |
| 1792 | + | |
| 1793 | + clk_put(u3d->clk); | |
| 1794 | + | |
| 1795 | + device_unregister(&u3d->gadget.dev); | |
| 1796 | + | |
| 1797 | + platform_set_drvdata(dev, NULL); | |
| 1798 | + | |
| 1799 | + kfree(u3d); | |
| 1800 | + | |
| 1801 | + return 0; | |
| 1802 | +} | |
| 1803 | + | |
| 1804 | +static int mv_u3d_probe(struct platform_device *dev) | |
| 1805 | +{ | |
| 1806 | + struct mv_u3d *u3d = NULL; | |
| 1807 | + struct mv_usb_platform_data *pdata = dev->dev.platform_data; | |
| 1808 | + int retval = 0; | |
| 1809 | + struct resource *r; | |
| 1810 | + size_t size; | |
| 1811 | + | |
| 1812 | + if (!dev->dev.platform_data) { | |
| 1813 | + dev_err(&dev->dev, "missing platform_data\n"); | |
| 1814 | + retval = -ENODEV; | |
| 1815 | + goto err_pdata; | |
| 1816 | + } | |
| 1817 | + | |
| 1818 | + u3d = kzalloc(sizeof(*u3d), GFP_KERNEL); | |
| 1819 | + if (!u3d) { | |
| 1820 | + dev_err(&dev->dev, "failed to allocate memory for u3d\n"); | |
| 1821 | + retval = -ENOMEM; | |
| 1822 | + goto err_alloc_private; | |
| 1823 | + } | |
| 1824 | + | |
| 1825 | + spin_lock_init(&u3d->lock); | |
| 1826 | + | |
| 1827 | + platform_set_drvdata(dev, u3d); | |
| 1828 | + | |
| 1829 | + u3d->dev = &dev->dev; | |
| 1830 | + u3d->vbus = pdata->vbus; | |
| 1831 | + | |
| 1832 | + u3d->clk = clk_get(&dev->dev, pdata->clkname[0]); | |
| 1833 | + if (IS_ERR(u3d->clk)) { | |
| 1834 | + retval = PTR_ERR(u3d->clk); | |
| 1835 | + goto err_get_clk; | |
| 1836 | + } | |
| 1837 | + | |
| 1838 | + r = platform_get_resource_byname(dev, IORESOURCE_MEM, "capregs"); | |
| 1839 | + if (!r) { | |
| 1840 | + dev_err(&dev->dev, "no I/O memory resource defined\n"); | |
| 1841 | + retval = -ENODEV; | |
| 1842 | + goto err_get_cap_regs; | |
| 1843 | + } | |
| 1844 | + | |
| 1845 | + u3d->cap_regs = (struct mv_u3d_cap_regs __iomem *) | |
| 1846 | + ioremap(r->start, resource_size(r)); | |
| 1847 | + if (!u3d->cap_regs) { | |
| 1848 | + dev_err(&dev->dev, "failed to map I/O memory\n"); | |
| 1849 | + retval = -EBUSY; | |
| 1850 | + goto err_map_cap_regs; | |
| 1851 | + } else { | |
| 1852 | + dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n", | |
| 1853 | + (unsigned int)r->start, (unsigned int)u3d->cap_regs); | |
| 1854 | + } | |
| 1855 | + | |
| 1856 | + /* we will access controller register, so enable the u3d controller */ | |
| 1857 | + clk_enable(u3d->clk); | |
| 1858 | + | |
| 1859 | + if (pdata->phy_init) { | |
| 1860 | + retval = pdata->phy_init(u3d->phy_regs); | |
| 1861 | + if (retval) { | |
| 1862 | + dev_err(&dev->dev, "init phy error %d\n", retval); | |
| 1863 | + goto err_u3d_enable; | |
| 1864 | + } | |
| 1865 | + } | |
| 1866 | + | |
| 1867 | + u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs | |
| 1868 | + + MV_U3D_USB3_OP_REGS_OFFSET); | |
| 1869 | + | |
| 1870 | + u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs | |
| 1871 | + + ioread32(&u3d->cap_regs->vuoff)); | |
| 1872 | + | |
| 1873 | + u3d->max_eps = 16; | |
| 1874 | + | |
| 1875 | + /* | |
| 1876 | + * some platform will use usb to download image, it may not disconnect | |
| 1877 | + * usb gadget before loading kernel. So first stop u3d here. | |
| 1878 | + */ | |
| 1879 | + mv_u3d_controller_stop(u3d); | |
| 1880 | + iowrite32(0xFFFFFFFF, &u3d->vuc_regs->intrcause); | |
| 1881 | + | |
| 1882 | + if (pdata->phy_deinit) | |
| 1883 | + pdata->phy_deinit(u3d->phy_regs); | |
| 1884 | + clk_disable(u3d->clk); | |
| 1885 | + | |
| 1886 | + size = u3d->max_eps * sizeof(struct mv_u3d_ep_context) * 2; | |
| 1887 | + size = (size + MV_U3D_EP_CONTEXT_ALIGNMENT - 1) | |
| 1888 | + & ~(MV_U3D_EP_CONTEXT_ALIGNMENT - 1); | |
| 1889 | + u3d->ep_context = dma_alloc_coherent(&dev->dev, size, | |
| 1890 | + &u3d->ep_context_dma, GFP_KERNEL); | |
| 1891 | + if (!u3d->ep_context) { | |
| 1892 | + dev_err(&dev->dev, "allocate ep context memory failed\n"); | |
| 1893 | + retval = -ENOMEM; | |
| 1894 | + goto err_alloc_ep_context; | |
| 1895 | + } | |
| 1896 | + u3d->ep_context_size = size; | |
| 1897 | + | |
| 1898 | + /* create TRB dma_pool resource */ | |
| 1899 | + u3d->trb_pool = dma_pool_create("u3d_trb", | |
| 1900 | + &dev->dev, | |
| 1901 | + sizeof(struct mv_u3d_trb_hw), | |
| 1902 | + MV_U3D_TRB_ALIGNMENT, | |
| 1903 | + MV_U3D_DMA_BOUNDARY); | |
| 1904 | + | |
| 1905 | + if (!u3d->trb_pool) { | |
| 1906 | + retval = -ENOMEM; | |
| 1907 | + goto err_alloc_trb_pool; | |
| 1908 | + } | |
| 1909 | + | |
| 1910 | + size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2; | |
| 1911 | + u3d->eps = kzalloc(size, GFP_KERNEL); | |
| 1912 | + if (!u3d->eps) { | |
| 1913 | + dev_err(&dev->dev, "allocate ep memory failed\n"); | |
| 1914 | + retval = -ENOMEM; | |
| 1915 | + goto err_alloc_eps; | |
| 1916 | + } | |
| 1917 | + | |
| 1918 | + /* initialize ep0 status request structure */ | |
| 1919 | + u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL); | |
| 1920 | + if (!u3d->status_req) { | |
| 1921 | + dev_err(&dev->dev, "allocate status_req memory failed\n"); | |
| 1922 | + retval = -ENOMEM; | |
| 1923 | + goto err_alloc_status_req; | |
| 1924 | + } | |
| 1925 | + INIT_LIST_HEAD(&u3d->status_req->queue); | |
| 1926 | + | |
| 1927 | + /* allocate a small amount of memory to get valid address */ | |
| 1928 | + u3d->status_req->req.buf = (char *)u3d->status_req | |
| 1929 | + + sizeof(struct mv_u3d_req); | |
| 1930 | + u3d->status_req->req.dma = virt_to_phys(u3d->status_req->req.buf); | |
| 1931 | + | |
| 1932 | + u3d->resume_state = USB_STATE_NOTATTACHED; | |
| 1933 | + u3d->usb_state = USB_STATE_ATTACHED; | |
| 1934 | + u3d->ep0_dir = MV_U3D_EP_DIR_OUT; | |
| 1935 | + u3d->remote_wakeup = 0; | |
| 1936 | + | |
| 1937 | + r = platform_get_resource(dev, IORESOURCE_IRQ, 0); | |
| 1938 | + if (!r) { | |
| 1939 | + dev_err(&dev->dev, "no IRQ resource defined\n"); | |
| 1940 | + retval = -ENODEV; | |
| 1941 | + goto err_get_irq; | |
| 1942 | + } | |
| 1943 | + u3d->irq = r->start; | |
| 1944 | + if (request_irq(u3d->irq, mv_u3d_irq, | |
| 1945 | + IRQF_DISABLED | IRQF_SHARED, driver_name, u3d)) { | |
| 1946 | + u3d->irq = 0; | |
| 1947 | + dev_err(&dev->dev, "Request irq %d for u3d failed\n", | |
| 1948 | + u3d->irq); | |
| 1949 | + retval = -ENODEV; | |
| 1950 | + goto err_request_irq; | |
| 1951 | + } | |
| 1952 | + | |
| 1953 | + /* initialize gadget structure */ | |
| 1954 | + u3d->gadget.ops = &mv_u3d_ops; /* usb_gadget_ops */ | |
| 1955 | + u3d->gadget.ep0 = &u3d->eps[1].ep; /* gadget ep0 */ | |
| 1956 | + INIT_LIST_HEAD(&u3d->gadget.ep_list); /* ep_list */ | |
| 1957 | + u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ | |
| 1958 | + | |
| 1959 | + /* the "gadget" abstracts/virtualizes the controller */ | |
| 1960 | + dev_set_name(&u3d->gadget.dev, "gadget"); | |
| 1961 | + u3d->gadget.dev.parent = &dev->dev; | |
| 1962 | + u3d->gadget.dev.dma_mask = dev->dev.dma_mask; | |
| 1963 | + u3d->gadget.dev.release = mv_u3d_gadget_release; | |
| 1964 | + u3d->gadget.name = driver_name; /* gadget name */ | |
| 1965 | + | |
| 1966 | + retval = device_register(&u3d->gadget.dev); | |
| 1967 | + if (retval) | |
| 1968 | + goto err_register_gadget_device; | |
| 1969 | + | |
| 1970 | + mv_u3d_eps_init(u3d); | |
| 1971 | + | |
| 1972 | + /* external vbus detection */ | |
| 1973 | + if (u3d->vbus) { | |
| 1974 | + u3d->clock_gating = 1; | |
| 1975 | + dev_err(&dev->dev, "external vbus detection\n"); | |
| 1976 | + } | |
| 1977 | + | |
| 1978 | + if (!u3d->clock_gating) | |
| 1979 | + u3d->vbus_active = 1; | |
| 1980 | + | |
| 1981 | + /* enable usb3 controller vbus detection */ | |
| 1982 | + u3d->vbus_valid_detect = 1; | |
| 1983 | + | |
| 1984 | + retval = usb_add_gadget_udc(&dev->dev, &u3d->gadget); | |
| 1985 | + if (retval) | |
| 1986 | + goto err_unregister; | |
| 1987 | + | |
| 1988 | + dev_dbg(&dev->dev, "successful probe usb3 device %s clock gating.\n", | |
| 1989 | + u3d->clock_gating ? "with" : "without"); | |
| 1990 | + | |
| 1991 | + return 0; | |
| 1992 | + | |
| 1993 | +err_unregister: | |
| 1994 | + device_unregister(&u3d->gadget.dev); | |
| 1995 | +err_register_gadget_device: | |
| 1996 | + free_irq(u3d->irq, &dev->dev); | |
| 1997 | +err_request_irq: | |
| 1998 | +err_get_irq: | |
| 1999 | + kfree(u3d->status_req); | |
| 2000 | +err_alloc_status_req: | |
| 2001 | + kfree(u3d->eps); | |
| 2002 | +err_alloc_eps: | |
| 2003 | + dma_pool_destroy(u3d->trb_pool); | |
| 2004 | +err_alloc_trb_pool: | |
| 2005 | + dma_free_coherent(&dev->dev, u3d->ep_context_size, | |
| 2006 | + u3d->ep_context, u3d->ep_context_dma); | |
| 2007 | +err_alloc_ep_context: | |
| 2008 | + if (pdata->phy_deinit) | |
| 2009 | + pdata->phy_deinit(u3d->phy_regs); | |
| 2010 | + clk_disable(u3d->clk); | |
| 2011 | +err_u3d_enable: | |
| 2012 | + iounmap(u3d->cap_regs); | |
| 2013 | +err_map_cap_regs: | |
| 2014 | +err_get_cap_regs: | |
| 2015 | +err_get_clk: | |
| 2016 | + clk_put(u3d->clk); | |
| 2017 | + platform_set_drvdata(dev, NULL); | |
| 2018 | + kfree(u3d); | |
| 2019 | +err_alloc_private: | |
| 2020 | +err_pdata: | |
| 2021 | + return retval; | |
| 2022 | +} | |
| 2023 | + | |
| 2024 | +#ifdef CONFIG_PM | |
| 2025 | +static int mv_u3d_suspend(struct device *dev) | |
| 2026 | +{ | |
| 2027 | + struct mv_u3d *u3d = dev_get_drvdata(dev); | |
| 2028 | + | |
| 2029 | + /* | |
| 2030 | + * only cable is unplugged, usb can suspend. | |
| 2031 | + * So do not care about clock_gating == 1, it is handled by | |
| 2032 | + * vbus session. | |
| 2033 | + */ | |
| 2034 | + if (!u3d->clock_gating) { | |
| 2035 | + mv_u3d_controller_stop(u3d); | |
| 2036 | + | |
| 2037 | + spin_lock_irq(&u3d->lock); | |
| 2038 | + /* stop all usb activities */ | |
| 2039 | + mv_u3d_stop_activity(u3d, u3d->driver); | |
| 2040 | + spin_unlock_irq(&u3d->lock); | |
| 2041 | + | |
| 2042 | + mv_u3d_disable(u3d); | |
| 2043 | + } | |
| 2044 | + | |
| 2045 | + return 0; | |
| 2046 | +} | |
| 2047 | + | |
| 2048 | +static int mv_u3d_resume(struct device *dev) | |
| 2049 | +{ | |
| 2050 | + struct mv_u3d *u3d = dev_get_drvdata(dev); | |
| 2051 | + int retval; | |
| 2052 | + | |
| 2053 | + if (!u3d->clock_gating) { | |
| 2054 | + retval = mv_u3d_enable(u3d); | |
| 2055 | + if (retval) | |
| 2056 | + return retval; | |
| 2057 | + | |
| 2058 | + if (u3d->driver && u3d->softconnect) { | |
| 2059 | + mv_u3d_controller_reset(u3d); | |
| 2060 | + mv_u3d_ep0_reset(u3d); | |
| 2061 | + mv_u3d_controller_start(u3d); | |
| 2062 | + } | |
| 2063 | + } | |
| 2064 | + | |
| 2065 | + return 0; | |
| 2066 | +} | |
| 2067 | + | |
| 2068 | +SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); | |
| 2069 | +#endif | |
| 2070 | + | |
| 2071 | +static void mv_u3d_shutdown(struct platform_device *dev) | |
| 2072 | +{ | |
| 2073 | + struct mv_u3d *u3d = dev_get_drvdata(&dev->dev); | |
| 2074 | + u32 tmp; | |
| 2075 | + | |
| 2076 | + tmp = ioread32(&u3d->op_regs->usbcmd); | |
| 2077 | + tmp &= ~MV_U3D_CMD_RUN_STOP; | |
| 2078 | + iowrite32(tmp, &u3d->op_regs->usbcmd); | |
| 2079 | +} | |
| 2080 | + | |
| 2081 | +static struct platform_driver mv_u3d_driver = { | |
| 2082 | + .probe = mv_u3d_probe, | |
| 2083 | + .remove = __exit_p(mv_u3d_remove), | |
| 2084 | + .shutdown = mv_u3d_shutdown, | |
| 2085 | + .driver = { | |
| 2086 | + .owner = THIS_MODULE, | |
| 2087 | + .name = "mv-u3d", | |
| 2088 | +#ifdef CONFIG_PM | |
| 2089 | + .pm = &mv_u3d_pm_ops, | |
| 2090 | +#endif | |
| 2091 | + }, | |
| 2092 | +}; | |
| 2093 | + | |
| 2094 | +module_platform_driver(mv_u3d_driver); | |
| 2095 | +MODULE_ALIAS("platform:mv-u3d"); | |
| 2096 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
| 2097 | +MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>"); | |
| 2098 | +MODULE_LICENSE("GPL"); | |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/sched.h> |
| 20 | 20 | #include <linux/slab.h> |
| 21 | 21 | #include <linux/errno.h> |
| 22 | +#include <linux/err.h> | |
| 22 | 23 | #include <linux/init.h> |
| 23 | 24 | #include <linux/timer.h> |
| 24 | 25 | #include <linux/list.h> |
| @@ -1381,7 +1382,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver, · 1356 unmodified lines | ||
| 1381 | 1382 | return retval; |
| 1382 | 1383 | } |
| 1383 | 1384 | |
| 1384 | − if (udc->transceiver) { | |
| 1385 | + if (!IS_ERR_OR_NULL(udc->transceiver)) { | |
| 1385 | 1386 | retval = otg_set_peripheral(udc->transceiver->otg, |
| 1386 | 1387 | &udc->gadget); |
| 1387 | 1388 | if (retval) { |
| @@ -2107,7 +2108,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev) · 719 unmodified lines | ||
| 2107 | 2108 | * then vbus irq will not be requested in udc driver. |
| 2108 | 2109 | */ |
| 2109 | 2110 | if (udc->pdata && udc->pdata->vbus |
| 2110 | − && udc->clock_gating && udc->transceiver == NULL) | |
| 2111 | + && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver)) | |
| 2111 | 2112 | free_irq(udc->pdata->vbus->irq, &dev->dev); |
| 2112 | 2113 | |
| 2113 | 2114 | /* free memory allocated in probe */ |
| @@ -2180,7 +2181,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev) · 66 unmodified lines | ||
| 2180 | 2181 | |
| 2181 | 2182 | #ifdef CONFIG_USB_OTG_UTILS |
| 2182 | 2183 | if (pdata->mode == MV_USB_MODE_OTG) |
| 2183 | − udc->transceiver = usb_get_transceiver(); | |
| 2184 | + udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2184 | 2185 | #endif |
| 2185 | 2186 | |
| 2186 | 2187 | udc->clknum = pdata->clknum; |
| @@ -2325,7 +2326,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev) · 138 unmodified lines | ||
| 2325 | 2326 | eps_init(udc); |
| 2326 | 2327 | |
| 2327 | 2328 | /* VBUS detect: we can disable/enable clock on demand.*/ |
| 2328 | − if (udc->transceiver) | |
| 2329 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 2329 | 2330 | udc->clock_gating = 1; |
| 2330 | 2331 | else if (pdata->vbus) { |
| 2331 | 2332 | udc->clock_gating = 1; |
| @@ -2369,7 +2370,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev) · 37 unmodified lines | ||
| 2369 | 2370 | |
| 2370 | 2371 | err_unregister: |
| 2371 | 2372 | if (udc->pdata && udc->pdata->vbus |
| 2372 | − && udc->clock_gating && udc->transceiver == NULL) | |
| 2373 | + && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver)) | |
| 2373 | 2374 | free_irq(pdata->vbus->irq, &dev->dev); |
| 2374 | 2375 | device_unregister(&udc->gadget.dev); |
| 2375 | 2376 | err_free_irq: |
| @@ -2404,7 +2405,7 @@ static int mv_udc_suspend(struct device *_dev) · 28 unmodified lines | ||
| 2404 | 2405 | struct mv_udc *udc = the_controller; |
| 2405 | 2406 | |
| 2406 | 2407 | /* if OTG is enabled, the following will be done in OTG driver*/ |
| 2407 | − if (udc->transceiver) | |
| 2408 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 2408 | 2409 | return 0; |
| 2409 | 2410 | |
| 2410 | 2411 | if (udc->pdata->vbus && udc->pdata->vbus->poll) |
| @@ -2437,7 +2438,7 @@ static int mv_udc_resume(struct device *_dev) · 26 unmodified lines | ||
| 2437 | 2438 | int retval; |
| 2438 | 2439 | |
| 2439 | 2440 | /* if OTG is enabled, the following will be done in OTG driver*/ |
| 2440 | − if (udc->transceiver) | |
| 2441 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 2441 | 2442 | return 0; |
| 2442 | 2443 | |
| 2443 | 2444 | if (!udc->clock_gating) { |
| @@ -35,10 +35,11 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <linux/usb/otg.h> |
| 36 | 36 | #include <linux/dma-mapping.h> |
| 37 | 37 | #include <linux/clk.h> |
| 38 | +#include <linux/err.h> | |
| 38 | 39 | #include <linux/prefetch.h> |
| 40 | +#include <linux/io.h> | |
| 39 | 41 | |
| 40 | 42 | #include <asm/byteorder.h> |
| 41 | −#include <asm/io.h> | |
| 42 | 43 | #include <asm/irq.h> |
| 43 | 44 | #include <asm/unaligned.h> |
| 44 | 45 | #include <asm/mach-types.h> |
| @@ -60,11 +61,6 @@ · 15 unmodified lines | ||
| 60 | 61 | #define DRIVER_DESC "OMAP UDC driver" |
| 61 | 62 | #define DRIVER_VERSION "4 October 2004" |
| 62 | 63 | |
| 63 | −#define DMA_ADDR_INVALID (~(dma_addr_t)0) | |
| 64 | − | |
| 65 | −#define OMAP2_DMA_CH(ch) (((ch) - 1) << 1) | |
| 66 | −#define OMAP24XX_DMA(name, ch) (OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch)) | |
| 67 | − | |
| 68 | 64 | /* |
| 69 | 65 | * The OMAP UDC needs _very_ early endpoint setup: before enabling the |
| 70 | 66 | * D+ pullup to allow enumeration. That's too early for the gadget |
| @@ -88,14 +84,14 @@ · 17 unmodified lines | ||
| 88 | 84 | #ifdef USE_ISO |
| 89 | 85 | static unsigned fifo_mode = 3; |
| 90 | 86 | #else |
| 91 | −static unsigned fifo_mode = 0; | |
| 87 | +static unsigned fifo_mode; | |
| 92 | 88 | #endif |
| 93 | 89 | |
| 94 | 90 | /* "modprobe omap_udc fifo_mode=42", or else as a kernel |
| 95 | 91 | * boot parameter "omap_udc:fifo_mode=42" |
| 96 | 92 | */ |
| 97 | −module_param (fifo_mode, uint, 0); | |
| 98 | −MODULE_PARM_DESC (fifo_mode, "endpoint configuration"); | |
| 93 | +module_param(fifo_mode, uint, 0); | |
| 94 | +MODULE_PARM_DESC(fifo_mode, "endpoint configuration"); | |
| 99 | 95 | |
| 100 | 96 | #ifdef USE_DMA |
| 101 | 97 | static bool use_dma = 1; |
| @@ -103,8 +99,8 @@ static bool use_dma = 1; · 1 unmodified line | ||
| 103 | 99 | /* "modprobe omap_udc use_dma=y", or else as a kernel |
| 104 | 100 | * boot parameter "omap_udc:use_dma=y" |
| 105 | 101 | */ |
| 106 | −module_param (use_dma, bool, 0); | |
| 107 | −MODULE_PARM_DESC (use_dma, "enable/disable DMA"); | |
| 102 | +module_param(use_dma, bool, 0); | |
| 103 | +MODULE_PARM_DESC(use_dma, "enable/disable DMA"); | |
| 108 | 104 | #else /* !USE_DMA */ |
| 109 | 105 | |
| 110 | 106 | /* save a bit of code */ |
| @@ -112,8 +108,8 @@ MODULE_PARM_DESC (use_dma, "enable/disable DMA"); · 1 unmodified line | ||
| 112 | 108 | #endif /* !USE_DMA */ |
| 113 | 109 | |
| 114 | 110 | |
| 115 | −static const char driver_name [] = "omap_udc"; | |
| 116 | −static const char driver_desc [] = DRIVER_DESC; | |
| 111 | +static const char driver_name[] = "omap_udc"; | |
| 112 | +static const char driver_desc[] = DRIVER_DESC; | |
| 117 | 113 | |
| 118 | 114 | /*-------------------------------------------------------------------------*/ |
| 119 | 115 | |
| @@ -251,7 +247,7 @@ static int omap_ep_disable(struct usb_ep *_ep) · 131 unmodified lines | ||
| 251 | 247 | |
| 252 | 248 | spin_lock_irqsave(&ep->udc->lock, flags); |
| 253 | 249 | ep->ep.desc = NULL; |
| 254 | − nuke (ep, -ESHUTDOWN); | |
| 250 | + nuke(ep, -ESHUTDOWN); | |
| 255 | 251 | ep->ep.maxpacket = ep->maxpacket; |
| 256 | 252 | ep->has_dma = 0; |
| 257 | 253 | omap_writew(UDC_SET_HALT, UDC_CTRL); |
| @@ -272,10 +268,11 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) · 14 unmodified lines | ||
| 272 | 268 | struct omap_req *req; |
| 273 | 269 | |
| 274 | 270 | req = kzalloc(sizeof(*req), gfp_flags); |
| 275 | − if (req) { | |
| 276 | − req->req.dma = DMA_ADDR_INVALID; | |
| 277 | − INIT_LIST_HEAD (&req->queue); | |
| 278 | − } | |
| 271 | + if (!req) | |
| 272 | + return NULL; | |
| 273 | + | |
| 274 | + INIT_LIST_HEAD(&req->queue); | |
| 275 | + | |
| 279 | 276 | return &req->req; |
| 280 | 277 | } |
| 281 | 278 | |
| @@ -284,8 +281,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) · 2 unmodified lines | ||
| 284 | 281 | { |
| 285 | 282 | struct omap_req *req = container_of(_req, struct omap_req, req); |
| 286 | 283 | |
| 287 | − if (_req) | |
| 288 | − kfree (req); | |
| 284 | + kfree(req); | |
| 289 | 285 | } |
| 290 | 286 | |
| 291 | 287 | /*-------------------------------------------------------------------------*/ |
| @@ -293,6 +289,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) · 1 unmodified line | ||
| 293 | 289 | static void |
| 294 | 290 | done(struct omap_ep *ep, struct omap_req *req, int status) |
| 295 | 291 | { |
| 292 | + struct omap_udc *udc = ep->udc; | |
| 296 | 293 | unsigned stopped = ep->stopped; |
| 297 | 294 | |
| 298 | 295 | list_del_init(&req->queue); |
| @@ -302,22 +299,9 @@ done(struct omap_ep *ep, struct omap_req *req, int status) · 3 unmodified lines | ||
| 302 | 299 | else |
| 303 | 300 | status = req->req.status; |
| 304 | 301 | |
| 305 | − if (use_dma && ep->has_dma) { | |
| 306 | − if (req->mapped) { | |
| 307 | − dma_unmap_single(ep->udc->gadget.dev.parent, | |
| 308 | − req->req.dma, req->req.length, | |
| 309 | − (ep->bEndpointAddress & USB_DIR_IN) | |
| 310 | − ? DMA_TO_DEVICE | |
| 311 | − : DMA_FROM_DEVICE); | |
| 312 | − req->req.dma = DMA_ADDR_INVALID; | |
| 313 | − req->mapped = 0; | |
| 314 | − } else | |
| 315 | − dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, | |
| 316 | − req->req.dma, req->req.length, | |
| 317 | − (ep->bEndpointAddress & USB_DIR_IN) | |
| 318 | − ? DMA_TO_DEVICE | |
| 319 | − : DMA_FROM_DEVICE); | |
| 320 | − } | |
| 302 | + if (use_dma && ep->has_dma) | |
| 303 | + usb_gadget_unmap_request(&udc->gadget, &req->req, | |
| 304 | + (ep->bEndpointAddress & USB_DIR_IN)); | |
| 321 | 305 | |
| 322 | 306 | #ifndef USB_TRACE |
| 323 | 307 | if (status && status != -ESHUTDOWN) |
| @@ -365,10 +349,10 @@ write_packet(u8 *buf, struct omap_req *req, unsigned max) · 41 unmodified lines | ||
| 365 | 349 | return len; |
| 366 | 350 | } |
| 367 | 351 | |
| 368 | −// FIXME change r/w fifo calling convention | |
| 352 | +/* FIXME change r/w fifo calling convention */ | |
| 369 | 353 | |
| 370 | 354 | |
| 371 | −// return: 0 = still running, 1 = completed, negative = errno | |
| 355 | +/* return: 0 = still running, 1 = completed, negative = errno */ | |
| 372 | 356 | static int write_fifo(struct omap_ep *ep, struct omap_req *req) |
| 373 | 357 | { |
| 374 | 358 | u8 *buf; |
| @@ -430,7 +414,7 @@ read_packet(u8 *buf, struct omap_req *req, unsigned avail) · 55 unmodified lines | ||
| 430 | 414 | return len; |
| 431 | 415 | } |
| 432 | 416 | |
| 433 | −// return: 0 = still running, 1 = queue empty, negative = errno | |
| 417 | +/* return: 0 = still running, 1 = queue empty, negative = errno */ | |
| 434 | 418 | static int read_fifo(struct omap_ep *ep, struct omap_req *req) |
| 435 | 419 | { |
| 436 | 420 | u8 *buf; |
| @@ -537,12 +521,8 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) · 100 unmodified lines | ||
| 537 | 521 | : OMAP_DMA_SYNC_ELEMENT; |
| 538 | 522 | int dma_trigger = 0; |
| 539 | 523 | |
| 540 | − if (cpu_is_omap24xx()) | |
| 541 | − dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel); | |
| 542 | − | |
| 543 | 524 | /* measure length in either bytes or packets */ |
| 544 | 525 | if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC) |
| 545 | − || (cpu_is_omap24xx() && length < ep->maxpacket) | |
| 546 | 526 | || (cpu_is_omap15xx() && length < ep->maxpacket)) { |
| 547 | 527 | txdma_ctrl = UDC_TXN_EOT | length; |
| 548 | 528 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, |
| @@ -601,28 +581,14 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) · 52 unmodified lines | ||
| 601 | 581 | int dma_trigger = 0; |
| 602 | 582 | u16 w; |
| 603 | 583 | |
| 604 | − if (cpu_is_omap24xx()) | |
| 605 | − dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel); | |
| 606 | − | |
| 607 | − /* NOTE: we filtered out "short reads" before, so we know | |
| 608 | − * the buffer has only whole numbers of packets. | |
| 609 | − * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode | |
| 610 | − */ | |
| 611 | − if (cpu_is_omap24xx() && packets < ep->maxpacket) { | |
| 612 | − omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | |
| 613 | − packets, 1, OMAP_DMA_SYNC_ELEMENT, | |
| 614 | − dma_trigger, 0); | |
| 615 | − req->dma_bytes = packets; | |
| 616 | − } else { | |
| 617 | − /* set up this DMA transfer, enable the fifo, start */ | |
| 618 | − packets /= ep->ep.maxpacket; | |
| 619 | − packets = min(packets, (unsigned)UDC_RXN_TC + 1); | |
| 620 | − req->dma_bytes = packets * ep->ep.maxpacket; | |
| 621 | − omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, | |
| 622 | − ep->ep.maxpacket >> 1, packets, | |
| 623 | − OMAP_DMA_SYNC_ELEMENT, | |
| 624 | − dma_trigger, 0); | |
| 625 | − } | |
| 584 | + /* set up this DMA transfer, enable the fifo, start */ | |
| 585 | + packets /= ep->ep.maxpacket; | |
| 586 | + packets = min(packets, (unsigned)UDC_RXN_TC + 1); | |
| 587 | + req->dma_bytes = packets * ep->ep.maxpacket; | |
| 588 | + omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, | |
| 589 | + ep->ep.maxpacket >> 1, packets, | |
| 590 | + OMAP_DMA_SYNC_ELEMENT, | |
| 591 | + dma_trigger, 0); | |
| 626 | 592 | omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, |
| 627 | 593 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, |
| 628 | 594 | 0, 0); |
| @@ -684,7 +650,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) · 55 unmodified lines | ||
| 684 | 650 | } |
| 685 | 651 | omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC); |
| 686 | 652 | |
| 687 | − if (!list_empty (&ep->queue)) { | |
| 653 | + if (!list_empty(&ep->queue)) { | |
| 688 | 654 | req = container_of(ep->queue.next, |
| 689 | 655 | struct omap_req, queue); |
| 690 | 656 | next_in_dma(ep, req); |
| @@ -703,7 +669,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) · 12 unmodified lines | ||
| 703 | 669 | } |
| 704 | 670 | omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC); |
| 705 | 671 | |
| 706 | − if (!list_empty (&ep->queue)) { | |
| 672 | + if (!list_empty(&ep->queue)) { | |
| 707 | 673 | req = container_of(ep->queue.next, |
| 708 | 674 | struct omap_req, queue); |
| 709 | 675 | next_out_dma(ep, req); |
| @@ -761,10 +727,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) · 51 unmodified lines | ||
| 761 | 727 | ep->dma_channel = channel; |
| 762 | 728 | |
| 763 | 729 | if (is_in) { |
| 764 | − if (cpu_is_omap24xx()) | |
| 765 | − dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel); | |
| 766 | − else | |
| 767 | − dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel; | |
| 730 | + dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel; | |
| 768 | 731 | status = omap_request_dma(dma_channel, |
| 769 | 732 | ep->ep.name, dma_error, ep, &ep->lch); |
| 770 | 733 | if (status == 0) { |
| @@ -781,11 +744,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) · 10 unmodified lines | ||
| 781 | 744 | 0, 0); |
| 782 | 745 | } |
| 783 | 746 | } else { |
| 784 | − if (cpu_is_omap24xx()) | |
| 785 | − dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel); | |
| 786 | − else | |
| 787 | − dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel; | |
| 788 | − | |
| 747 | + dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel; | |
| 789 | 748 | status = omap_request_dma(dma_channel, |
| 790 | 749 | ep->ep.name, dma_error, ep, &ep->lch); |
| 791 | 750 | if (status == 0) { |
| @@ -809,7 +768,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) · 17 unmodified lines | ||
| 809 | 768 | omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ); |
| 810 | 769 | |
| 811 | 770 | /* channel type P: hw synch (fifo) */ |
| 812 | − if (cpu_class_is_omap1() && !cpu_is_omap15xx()) | |
| 771 | + if (!cpu_is_omap15xx()) | |
| 813 | 772 | omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P); |
| 814 | 773 | } |
| 815 | 774 | |
| @@ -929,13 +888,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 113 unmodified lines | ||
| 929 | 888 | |
| 930 | 889 | /* this isn't bogus, but OMAP DMA isn't the only hardware to |
| 931 | 890 | * have a hard time with partial packet reads... reject it. |
| 932 | − * Except OMAP2 can handle the small packets. | |
| 933 | 891 | */ |
| 934 | 892 | if (use_dma |
| 935 | 893 | && ep->has_dma |
| 936 | 894 | && ep->bEndpointAddress != 0 |
| 937 | 895 | && (ep->bEndpointAddress & USB_DIR_IN) == 0 |
| 938 | − && !cpu_class_is_omap2() | |
| 939 | 896 | && (req->req.length % ep->ep.maxpacket) != 0) { |
| 940 | 897 | DBG("%s, no partial packet OUT reads\n", __func__); |
| 941 | 898 | return -EMSGSIZE; |
| @@ -945,26 +902,9 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 3 unmodified lines | ||
| 945 | 902 | if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) |
| 946 | 903 | return -ESHUTDOWN; |
| 947 | 904 | |
| 948 | − if (use_dma && ep->has_dma) { | |
| 949 | − if (req->req.dma == DMA_ADDR_INVALID) { | |
| 950 | − req->req.dma = dma_map_single( | |
| 951 | − ep->udc->gadget.dev.parent, | |
| 952 | − req->req.buf, | |
| 953 | − req->req.length, | |
| 954 | − (ep->bEndpointAddress & USB_DIR_IN) | |
| 955 | − ? DMA_TO_DEVICE | |
| 956 | − : DMA_FROM_DEVICE); | |
| 957 | − req->mapped = 1; | |
| 958 | − } else { | |
| 959 | − dma_sync_single_for_device( | |
| 960 | − ep->udc->gadget.dev.parent, | |
| 961 | − req->req.dma, req->req.length, | |
| 962 | − (ep->bEndpointAddress & USB_DIR_IN) | |
| 963 | − ? DMA_TO_DEVICE | |
| 964 | − : DMA_FROM_DEVICE); | |
| 965 | − req->mapped = 0; | |
| 966 | − } | |
| 967 | − } | |
| 905 | + if (use_dma && ep->has_dma) | |
| 906 | + usb_gadget_map_request(&udc->gadget, &req->req, | |
| 907 | + (ep->bEndpointAddress & USB_DIR_IN)); | |
| 968 | 908 | |
| 969 | 909 | VDBG("%s queue req %p, len %d buf %p\n", |
| 970 | 910 | ep->ep.name, _req, _req->length, _req->buf); |
| @@ -985,7 +925,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 14 unmodified lines | ||
| 985 | 925 | int is_in; |
| 986 | 926 | |
| 987 | 927 | if (ep->bEndpointAddress == 0) { |
| 988 | − if (!udc->ep0_pending || !list_empty (&ep->queue)) { | |
| 928 | + if (!udc->ep0_pending || !list_empty(&ep->queue)) { | |
| 989 | 929 | spin_unlock_irqrestore(&udc->lock, flags); |
| 990 | 930 | return -EL2HLT; |
| 991 | 931 | } |
| @@ -1012,7 +952,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 20 unmodified lines | ||
| 1012 | 952 | * always an IN ... even for IN transfers, |
| 1013 | 953 | * a weird case which seem to stall OMAP. |
| 1014 | 954 | */ |
| 1015 | − omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); | |
| 955 | + omap_writew(UDC_EP_SEL | UDC_EP_DIR, | |
| 956 | + UDC_EP_NUM); | |
| 1016 | 957 | omap_writew(UDC_CLR_EP, UDC_CTRL); |
| 1017 | 958 | omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); |
| 1018 | 959 | omap_writew(UDC_EP_DIR, UDC_EP_NUM); |
| @@ -1024,7 +965,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) · 5 unmodified lines | ||
| 1024 | 965 | |
| 1025 | 966 | /* non-empty DATA stage */ |
| 1026 | 967 | } else if (is_in) { |
| 1027 | − omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); | |
| 968 | + omap_writew(UDC_EP_SEL | UDC_EP_DIR, | |
| 969 | + UDC_EP_NUM); | |
| 1028 | 970 | } else { |
| 1029 | 971 | if (udc->ep0_setup) |
| 1030 | 972 | goto irq_wait; |
| @@ -1072,7 +1014,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) · 41 unmodified lines | ||
| 1072 | 1014 | spin_lock_irqsave(&ep->udc->lock, flags); |
| 1073 | 1015 | |
| 1074 | 1016 | /* make sure it's actually queued on this endpoint */ |
| 1075 | − list_for_each_entry (req, &ep->queue, queue) { | |
| 1017 | + list_for_each_entry(req, &ep->queue, queue) { | |
| 1076 | 1018 | if (&req->req == _req) |
| 1077 | 1019 | break; |
| 1078 | 1020 | } |
| @@ -1179,8 +1121,8 @@ static struct usb_ep_ops omap_ep_ops = { · 100 unmodified lines | ||
| 1179 | 1121 | .dequeue = omap_ep_dequeue, |
| 1180 | 1122 | |
| 1181 | 1123 | .set_halt = omap_ep_set_halt, |
| 1182 | − // fifo_status ... report bytes in fifo | |
| 1183 | − // fifo_flush ... flush fifo | |
| 1124 | + /* fifo_status ... report bytes in fifo */ | |
| 1125 | + /* fifo_flush ... flush fifo */ | |
| 1184 | 1126 | }; |
| 1185 | 1127 | |
| 1186 | 1128 | /*-------------------------------------------------------------------------*/ |
| @@ -1212,7 +1154,7 @@ static int omap_wakeup(struct usb_gadget *gadget) · 25 unmodified lines | ||
| 1212 | 1154 | |
| 1213 | 1155 | /* NOTE: non-OTG systems may use SRP TOO... */ |
| 1214 | 1156 | } else if (!(udc->devstat & UDC_ATT)) { |
| 1215 | − if (udc->transceiver) | |
| 1157 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1216 | 1158 | retval = otg_start_srp(udc->transceiver->otg); |
| 1217 | 1159 | } |
| 1218 | 1160 | spin_unlock_irqrestore(&udc->lock, flags); |
| @@ -1344,7 +1286,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA) · 125 unmodified lines | ||
| 1344 | 1286 | struct omap_udc *udc; |
| 1345 | 1287 | |
| 1346 | 1288 | udc = container_of(gadget, struct omap_udc, gadget); |
| 1347 | − if (udc->transceiver) | |
| 1289 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1348 | 1290 | return usb_phy_set_power(udc->transceiver, mA); |
| 1349 | 1291 | return -EOPNOTSUPP; |
| 1350 | 1292 | } |
| @@ -1410,7 +1352,7 @@ static void udc_quiesce(struct omap_udc *udc) · 59 unmodified lines | ||
| 1410 | 1352 | |
| 1411 | 1353 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
| 1412 | 1354 | nuke(&udc->ep[0], -ESHUTDOWN); |
| 1413 | − list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) | |
| 1355 | + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) | |
| 1414 | 1356 | nuke(ep, -ESHUTDOWN); |
| 1415 | 1357 | } |
| 1416 | 1358 | |
| @@ -1526,7 +1468,8 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) · 109 unmodified lines | ||
| 1526 | 1468 | /* read next OUT packet of request, maybe |
| 1527 | 1469 | * reactiviting the fifo; stall on errors. |
| 1528 | 1470 | */ |
| 1529 | − if (!req || (stat = read_fifo(ep0, req)) < 0) { | |
| 1471 | + stat = read_fifo(ep0, req); | |
| 1472 | + if (!req || stat < 0) { | |
| 1530 | 1473 | omap_writew(UDC_STALL_CMD, UDC_SYSCON2); |
| 1531 | 1474 | udc->ep0_pending = 0; |
| 1532 | 1475 | stat = 0; |
| @@ -1659,7 +1602,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) · 126 unmodified lines | ||
| 1659 | 1602 | /* this has rude side-effects (aborts) and |
| 1660 | 1603 | * can't really work if DMA-IN is active |
| 1661 | 1604 | */ |
| 1662 | − DBG("%s host set_halt, NYET \n", ep->name); | |
| 1605 | + DBG("%s host set_halt, NYET\n", ep->name); | |
| 1663 | 1606 | goto do_stall; |
| 1664 | 1607 | } |
| 1665 | 1608 | use_ep(ep, 0); |
| @@ -1750,7 +1693,7 @@ delegate: · 84 unmodified lines | ||
| 1750 | 1693 | */ |
| 1751 | 1694 | udc->ep0_setup = 1; |
| 1752 | 1695 | spin_unlock(&udc->lock); |
| 1753 | − status = udc->driver->setup (&udc->gadget, &u.r); | |
| 1696 | + status = udc->driver->setup(&udc->gadget, &u.r); | |
| 1754 | 1697 | spin_lock(&udc->lock); |
| 1755 | 1698 | udc->ep0_setup = 0; |
| 1756 | 1699 | } |
| @@ -1793,12 +1736,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) · 36 unmodified lines | ||
| 1793 | 1736 | if (devstat & UDC_ATT) { |
| 1794 | 1737 | udc->gadget.speed = USB_SPEED_FULL; |
| 1795 | 1738 | VDBG("connect\n"); |
| 1796 | − if (!udc->transceiver) | |
| 1739 | + if (IS_ERR_OR_NULL(udc->transceiver)) | |
| 1797 | 1740 | pullup_enable(udc); |
| 1798 | − // if (driver->connect) call it | |
| 1741 | + /* if (driver->connect) call it */ | |
| 1799 | 1742 | } else if (udc->gadget.speed != USB_SPEED_UNKNOWN) { |
| 1800 | 1743 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
| 1801 | − if (!udc->transceiver) | |
| 1744 | + if (IS_ERR_OR_NULL(udc->transceiver)) | |
| 1802 | 1745 | pullup_disable(udc); |
| 1803 | 1746 | DBG("disconnect, gadget %s\n", |
| 1804 | 1747 | udc->driver->driver.name); |
| @@ -1827,7 +1770,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) · 22 unmodified lines | ||
| 1827 | 1770 | } |
| 1828 | 1771 | if (change & UDC_SUS) { |
| 1829 | 1772 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) { |
| 1830 | − // FIXME tell isp1301 to suspend/resume (?) | |
| 1773 | + /* FIXME tell isp1301 to suspend/resume (?) */ | |
| 1831 | 1774 | if (devstat & UDC_SUS) { |
| 1832 | 1775 | VDBG("suspend\n"); |
| 1833 | 1776 | update_otg(udc); |
| @@ -1838,12 +1781,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) · 4 unmodified lines | ||
| 1838 | 1781 | udc->driver->suspend(&udc->gadget); |
| 1839 | 1782 | spin_lock(&udc->lock); |
| 1840 | 1783 | } |
| 1841 | − if (udc->transceiver) | |
| 1784 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1842 | 1785 | usb_phy_set_suspend( |
| 1843 | 1786 | udc->transceiver, 1); |
| 1844 | 1787 | } else { |
| 1845 | 1788 | VDBG("resume\n"); |
| 1846 | − if (udc->transceiver) | |
| 1789 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1847 | 1790 | usb_phy_set_suspend( |
| 1848 | 1791 | udc->transceiver, 0); |
| 1849 | 1792 | if (udc->gadget.speed == USB_SPEED_FULL |
| @@ -2030,7 +1973,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) · 180 unmodified lines | ||
| 2030 | 1973 | spin_lock_irqsave(&udc->lock, flags); |
| 2031 | 1974 | |
| 2032 | 1975 | /* handle all non-DMA ISO transfers */ |
| 2033 | − list_for_each_entry (ep, &udc->iso, iso) { | |
| 1976 | + list_for_each_entry(ep, &udc->iso, iso) { | |
| 2034 | 1977 | u16 stat; |
| 2035 | 1978 | struct omap_req *req; |
| 2036 | 1979 | |
| @@ -2089,15 +2032,11 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) · 52 unmodified lines | ||
| 2089 | 2032 | |
| 2090 | 2033 | static inline int machine_without_vbus_sense(void) |
| 2091 | 2034 | { |
| 2092 | − return (machine_is_omap_innovator() | |
| 2035 | + return machine_is_omap_innovator() | |
| 2093 | 2036 | || machine_is_omap_osk() |
| 2094 | − || machine_is_omap_apollon() | |
| 2095 | −#ifndef CONFIG_MACH_OMAP_H4_OTG | |
| 2096 | − || machine_is_omap_h4() | |
| 2097 | −#endif | |
| 2098 | 2037 | || machine_is_sx1() |
| 2099 | − || cpu_is_omap7xx() /* No known omap7xx boards with vbus sense */ | |
| 2100 | − ); | |
| 2038 | + /* No known omap7xx boards with vbus sense */ | |
| 2039 | + || cpu_is_omap7xx(); | |
| 2101 | 2040 | } |
| 2102 | 2041 | |
| 2103 | 2042 | static int omap_udc_start(struct usb_gadget_driver *driver, |
| @@ -2111,7 +2050,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, · 7 unmodified lines | ||
| 2111 | 2050 | if (!udc) |
| 2112 | 2051 | return -ENODEV; |
| 2113 | 2052 | if (!driver |
| 2114 | − // FIXME if otg, check: driver->is_otg | |
| 2053 | + /* FIXME if otg, check: driver->is_otg */ | |
| 2115 | 2054 | || driver->max_speed < USB_SPEED_FULL |
| 2116 | 2055 | || !bind || !driver->setup) |
| 2117 | 2056 | return -EINVAL; |
| @@ -2123,7 +2062,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, · 5 unmodified lines | ||
| 2123 | 2062 | } |
| 2124 | 2063 | |
| 2125 | 2064 | /* reset state */ |
| 2126 | − list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { | |
| 2065 | + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { | |
| 2127 | 2066 | ep->irqs = 0; |
| 2128 | 2067 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) |
| 2129 | 2068 | continue; |
| @@ -2155,13 +2094,13 @@ static int omap_udc_start(struct usb_gadget_driver *driver, · 25 unmodified lines | ||
| 2155 | 2094 | omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC); |
| 2156 | 2095 | |
| 2157 | 2096 | /* connect to bus through transceiver */ |
| 2158 | − if (udc->transceiver) { | |
| 2097 | + if (!IS_ERR_OR_NULL(udc->transceiver)) { | |
| 2159 | 2098 | status = otg_set_peripheral(udc->transceiver->otg, |
| 2160 | 2099 | &udc->gadget); |
| 2161 | 2100 | if (status < 0) { |
| 2162 | 2101 | ERR("can't bind to transceiver\n"); |
| 2163 | 2102 | if (driver->unbind) { |
| 2164 | − driver->unbind (&udc->gadget); | |
| 2103 | + driver->unbind(&udc->gadget); | |
| 2165 | 2104 | udc->gadget.dev.driver = NULL; |
| 2166 | 2105 | udc->driver = NULL; |
| 2167 | 2106 | } |
| @@ -2169,9 +2108,9 @@ static int omap_udc_start(struct usb_gadget_driver *driver, · 1 unmodified line | ||
| 2169 | 2108 | } |
| 2170 | 2109 | } else { |
| 2171 | 2110 | if (can_pullup(udc)) |
| 2172 | − pullup_enable (udc); | |
| 2111 | + pullup_enable(udc); | |
| 2173 | 2112 | else |
| 2174 | − pullup_disable (udc); | |
| 2113 | + pullup_disable(udc); | |
| 2175 | 2114 | } |
| 2176 | 2115 | |
| 2177 | 2116 | /* boards that don't have VBUS sensing can't autogate 48MHz; |
| @@ -2202,7 +2141,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver) · 24 unmodified lines | ||
| 2202 | 2141 | if (machine_without_vbus_sense()) |
| 2203 | 2142 | omap_vbus_session(&udc->gadget, 0); |
| 2204 | 2143 | |
| 2205 | − if (udc->transceiver) | |
| 2144 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 2206 | 2145 | (void) otg_set_peripheral(udc->transceiver->otg, NULL); |
| 2207 | 2146 | else |
| 2208 | 2147 | pullup_disable(udc); |
| @@ -2230,7 +2169,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver) · 21 unmodified lines | ||
| 2230 | 2169 | static const char proc_filename[] = "driver/udc"; |
| 2231 | 2170 | |
| 2232 | 2171 | #define FOURBITS "%s%s%s%s" |
| 2233 | −#define EIGHTBITS FOURBITS FOURBITS | |
| 2172 | +#define EIGHTBITS "%s%s%s%s%s%s%s%s" | |
| 2234 | 2173 | |
| 2235 | 2174 | static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) |
| 2236 | 2175 | { |
| @@ -2252,12 +2191,21 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) · 15 unmodified lines | ||
| 2252 | 2191 | "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n", |
| 2253 | 2192 | ep->name, buf, |
| 2254 | 2193 | ep->double_buf ? "dbuf " : "", |
| 2255 | − ({char *s; switch(ep->ackwait){ | |
| 2256 | − case 0: s = ""; break; | |
| 2257 | − case 1: s = "(ackw) "; break; | |
| 2258 | − case 2: s = "(ackw2) "; break; | |
| 2259 | − default: s = "(?) "; break; | |
| 2260 | − } s;}), | |
| 2194 | + ({ char *s; | |
| 2195 | + switch (ep->ackwait) { | |
| 2196 | + case 0: | |
| 2197 | + s = ""; | |
| 2198 | + break; | |
| 2199 | + case 1: | |
| 2200 | + s = "(ackw) "; | |
| 2201 | + break; | |
| 2202 | + case 2: | |
| 2203 | + s = "(ackw2) "; | |
| 2204 | + break; | |
| 2205 | + default: | |
| 2206 | + s = "(?) "; | |
| 2207 | + break; | |
| 2208 | + } s; }), | |
| 2261 | 2209 | ep->irqs, stat_flg, |
| 2262 | 2210 | (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "", |
| 2263 | 2211 | (stat_flg & UDC_MISS_IN) ? "miss_in " : "", |
| @@ -2273,10 +2221,10 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) · 9 unmodified lines | ||
| 2273 | 2221 | (stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "", |
| 2274 | 2222 | (stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : ""); |
| 2275 | 2223 | |
| 2276 | − if (list_empty (&ep->queue)) | |
| 2224 | + if (list_empty(&ep->queue)) | |
| 2277 | 2225 | seq_printf(s, "\t(queue empty)\n"); |
| 2278 | 2226 | else |
| 2279 | − list_for_each_entry (req, &ep->queue, queue) { | |
| 2227 | + list_for_each_entry(req, &ep->queue, queue) { | |
| 2280 | 2228 | unsigned length = req->req.actual; |
| 2281 | 2229 | |
| 2282 | 2230 | if (use_dma && buf[0]) { |
| @@ -2294,11 +2242,16 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) · 11 unmodified lines | ||
| 2294 | 2242 | static char *trx_mode(unsigned m, int enabled) |
| 2295 | 2243 | { |
| 2296 | 2244 | switch (m) { |
| 2297 | − case 0: return enabled ? "*6wire" : "unused"; | |
| 2298 | − case 1: return "4wire"; | |
| 2299 | − case 2: return "3wire"; | |
| 2300 | − case 3: return "6wire"; | |
| 2301 | − default: return "unknown"; | |
| 2245 | + case 0: | |
| 2246 | + return enabled ? "*6wire" : "unused"; | |
| 2247 | + case 1: | |
| 2248 | + return "4wire"; | |
| 2249 | + case 2: | |
| 2250 | + return "3wire"; | |
| 2251 | + case 3: | |
| 2252 | + return "6wire"; | |
| 2253 | + default: | |
| 2254 | + return "unknown"; | |
| 2302 | 2255 | } |
| 2303 | 2256 | } |
| 2304 | 2257 | |
| @@ -2308,12 +2261,9 @@ static int proc_otg_show(struct seq_file *s) · 3 unmodified lines | ||
| 2308 | 2261 | u32 trans = 0; |
| 2309 | 2262 | char *ctrl_name = "(UNKNOWN)"; |
| 2310 | 2263 | |
| 2311 | − /* XXX This needs major revision for OMAP2+ */ | |
| 2312 | 2264 | tmp = omap_readl(OTG_REV); |
| 2313 | − if (cpu_class_is_omap1()) { | |
| 2314 | − ctrl_name = "tranceiver_ctrl"; | |
| 2315 | − trans = omap_readw(USB_TRANSCEIVER_CTRL); | |
| 2316 | − } | |
| 2265 | + ctrl_name = "tranceiver_ctrl"; | |
| 2266 | + trans = omap_readw(USB_TRANSCEIVER_CTRL); | |
| 2317 | 2267 | seq_printf(s, "\nOTG rev %d.%d, %s %05x\n", |
| 2318 | 2268 | tmp >> 4, tmp & 0xf, ctrl_name, trans); |
| 2319 | 2269 | tmp = omap_readw(OTG_SYSCON_1); |
| @@ -2333,7 +2283,7 @@ static int proc_otg_show(struct seq_file *s) · 13 unmodified lines | ||
| 2333 | 2283 | " b_ase_brst=%d hmc=%d\n", tmp, |
| 2334 | 2284 | (tmp & OTG_EN) ? " otg_en" : "", |
| 2335 | 2285 | (tmp & USBX_SYNCHRO) ? " synchro" : "", |
| 2336 | − // much more SRP stuff | |
| 2286 | + /* much more SRP stuff */ | |
| 2337 | 2287 | (tmp & SRP_DATA) ? " srp_data" : "", |
| 2338 | 2288 | (tmp & SRP_VBUS) ? " srp_vbus" : "", |
| 2339 | 2289 | (tmp & OTG_PADEN) ? " otg_paden" : "", |
| @@ -2400,14 +2350,12 @@ static int proc_udc_show(struct seq_file *s, void *_) · 60 unmodified lines | ||
| 2400 | 2350 | HMC, |
| 2401 | 2351 | udc->transceiver |
| 2402 | 2352 | ? udc->transceiver->label |
| 2403 | − : ((cpu_is_omap1710() || cpu_is_omap24xx()) | |
| 2353 | + : (cpu_is_omap1710() | |
| 2404 | 2354 | ? "external" : "(none)")); |
| 2405 | − if (cpu_class_is_omap1()) { | |
| 2406 | − seq_printf(s, "ULPD control %04x req %04x status %04x\n", | |
| 2407 | − omap_readw(ULPD_CLOCK_CTRL), | |
| 2408 | − omap_readw(ULPD_SOFT_REQ), | |
| 2409 | − omap_readw(ULPD_STATUS_REQ)); | |
| 2410 | − } | |
| 2355 | + seq_printf(s, "ULPD control %04x req %04x status %04x\n", | |
| 2356 | + omap_readw(ULPD_CLOCK_CTRL), | |
| 2357 | + omap_readw(ULPD_SOFT_REQ), | |
| 2358 | + omap_readw(ULPD_STATUS_REQ)); | |
| 2411 | 2359 | |
| 2412 | 2360 | /* OTG controller registers */ |
| 2413 | 2361 | if (!cpu_is_omap15xx()) |
| @@ -2423,7 +2371,7 @@ static int proc_udc_show(struct seq_file *s, void *_) · 9 unmodified lines | ||
| 2423 | 2371 | (tmp & UDC_SELF_PWR) ? " self_pwr" : "", |
| 2424 | 2372 | (tmp & UDC_SOFF_DIS) ? " soff_dis" : "", |
| 2425 | 2373 | (tmp & UDC_PULLUP_EN) ? " PULLUP" : ""); |
| 2426 | − // syscon2 is write-only | |
| 2374 | + /* syscon2 is write-only */ | |
| 2427 | 2375 | |
| 2428 | 2376 | /* UDC controller registers */ |
| 2429 | 2377 | if (!(tmp & UDC_PULLUP_EN)) { |
| @@ -2507,7 +2455,7 @@ static int proc_udc_show(struct seq_file *s, void *_) · 77 unmodified lines | ||
| 2507 | 2455 | if (tmp & UDC_ATT) { |
| 2508 | 2456 | proc_ep_show(s, &udc->ep[0]); |
| 2509 | 2457 | if (tmp & UDC_ADD) { |
| 2510 | − list_for_each_entry (ep, &udc->gadget.ep_list, | |
| 2458 | + list_for_each_entry(ep, &udc->gadget.ep_list, | |
| 2511 | 2459 | ep.ep_list) { |
| 2512 | 2460 | if (ep->ep.desc) |
| 2513 | 2461 | proc_ep_show(s, ep); |
| @@ -2558,7 +2506,7 @@ static inline void remove_proc_file(void) {} · 44 unmodified lines | ||
| 2558 | 2506 | * UDC_SYSCON_1.CFG_LOCK is set can now work. We won't use that |
| 2559 | 2507 | * capability yet though. |
| 2560 | 2508 | */ |
| 2561 | −static unsigned __init | |
| 2509 | +static unsigned __devinit | |
| 2562 | 2510 | omap_ep_setup(char *name, u8 addr, u8 type, |
| 2563 | 2511 | unsigned buf, unsigned maxp, int dbuf) |
| 2564 | 2512 | { |
| @@ -2576,14 +2524,29 @@ omap_ep_setup(char *name, u8 addr, u8 type, · 11 unmodified lines | ||
| 2576 | 2524 | /* chip setup ... bit values are same for IN, OUT */ |
| 2577 | 2525 | if (type == USB_ENDPOINT_XFER_ISOC) { |
| 2578 | 2526 | switch (maxp) { |
| 2579 | − case 8: epn_rxtx = 0 << 12; break; | |
| 2580 | − case 16: epn_rxtx = 1 << 12; break; | |
| 2581 | − case 32: epn_rxtx = 2 << 12; break; | |
| 2582 | − case 64: epn_rxtx = 3 << 12; break; | |
| 2583 | − case 128: epn_rxtx = 4 << 12; break; | |
| 2584 | − case 256: epn_rxtx = 5 << 12; break; | |
| 2585 | − case 512: epn_rxtx = 6 << 12; break; | |
| 2586 | − default: BUG(); | |
| 2527 | + case 8: | |
| 2528 | + epn_rxtx = 0 << 12; | |
| 2529 | + break; | |
| 2530 | + case 16: | |
| 2531 | + epn_rxtx = 1 << 12; | |
| 2532 | + break; | |
| 2533 | + case 32: | |
| 2534 | + epn_rxtx = 2 << 12; | |
| 2535 | + break; | |
| 2536 | + case 64: | |
| 2537 | + epn_rxtx = 3 << 12; | |
| 2538 | + break; | |
| 2539 | + case 128: | |
| 2540 | + epn_rxtx = 4 << 12; | |
| 2541 | + break; | |
| 2542 | + case 256: | |
| 2543 | + epn_rxtx = 5 << 12; | |
| 2544 | + break; | |
| 2545 | + case 512: | |
| 2546 | + epn_rxtx = 6 << 12; | |
| 2547 | + break; | |
| 2548 | + default: | |
| 2549 | + BUG(); | |
| 2587 | 2550 | } |
| 2588 | 2551 | epn_rxtx |= UDC_EPN_RX_ISO; |
| 2589 | 2552 | dbuf = 1; |
| @@ -2592,15 +2555,24 @@ omap_ep_setup(char *name, u8 addr, u8 type, · 2 unmodified lines | ||
| 2592 | 2555 | * and ignored for PIO-IN on newer chips |
| 2593 | 2556 | * (for more reliable behavior) |
| 2594 | 2557 | */ |
| 2595 | − if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx()) | |
| 2558 | + if (!use_dma || cpu_is_omap15xx()) | |
| 2596 | 2559 | dbuf = 0; |
| 2597 | 2560 | |
| 2598 | 2561 | switch (maxp) { |
| 2599 | − case 8: epn_rxtx = 0 << 12; break; | |
| 2600 | − case 16: epn_rxtx = 1 << 12; break; | |
| 2601 | − case 32: epn_rxtx = 2 << 12; break; | |
| 2602 | − case 64: epn_rxtx = 3 << 12; break; | |
| 2603 | − default: BUG(); | |
| 2562 | + case 8: | |
| 2563 | + epn_rxtx = 0 << 12; | |
| 2564 | + break; | |
| 2565 | + case 16: | |
| 2566 | + epn_rxtx = 1 << 12; | |
| 2567 | + break; | |
| 2568 | + case 32: | |
| 2569 | + epn_rxtx = 2 << 12; | |
| 2570 | + break; | |
| 2571 | + case 64: | |
| 2572 | + epn_rxtx = 3 << 12; | |
| 2573 | + break; | |
| 2574 | + default: | |
| 2575 | + BUG(); | |
| 2604 | 2576 | } |
| 2605 | 2577 | if (dbuf && addr) |
| 2606 | 2578 | epn_rxtx |= UDC_EPN_RX_DB; |
| @@ -2640,7 +2612,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, · 33 unmodified lines | ||
| 2640 | 2612 | ep->ep.name = ep->name; |
| 2641 | 2613 | ep->ep.ops = &omap_ep_ops; |
| 2642 | 2614 | ep->ep.maxpacket = ep->maxpacket = maxp; |
| 2643 | − list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list); | |
| 2615 | + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); | |
| 2644 | 2616 | |
| 2645 | 2617 | return buf; |
| 2646 | 2618 | } |
| @@ -2648,11 +2620,11 @@ omap_ep_setup(char *name, u8 addr, u8 type, · 1 unmodified line | ||
| 2648 | 2620 | static void omap_udc_release(struct device *dev) |
| 2649 | 2621 | { |
| 2650 | 2622 | complete(udc->done); |
| 2651 | − kfree (udc); | |
| 2623 | + kfree(udc); | |
| 2652 | 2624 | udc = NULL; |
| 2653 | 2625 | } |
| 2654 | 2626 | |
| 2655 | −static int __init | |
| 2627 | +static int __devinit | |
| 2656 | 2628 | omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) |
| 2657 | 2629 | { |
| 2658 | 2630 | unsigned tmp, buf; |
| @@ -2666,13 +2638,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) · 7 unmodified lines | ||
| 2666 | 2638 | omap_writew(0, UDC_TXDMA_CFG); |
| 2667 | 2639 | |
| 2668 | 2640 | /* UDC_PULLUP_EN gates the chip clock */ |
| 2669 | − // OTG_SYSCON_1 |= DEV_IDLE_EN; | |
| 2641 | + /* OTG_SYSCON_1 |= DEV_IDLE_EN; */ | |
| 2670 | 2642 | |
| 2671 | 2643 | udc = kzalloc(sizeof(*udc), GFP_KERNEL); |
| 2672 | 2644 | if (!udc) |
| 2673 | 2645 | return -ENOMEM; |
| 2674 | 2646 | |
| 2675 | − spin_lock_init (&udc->lock); | |
| 2647 | + spin_lock_init(&udc->lock); | |
| 2676 | 2648 | |
| 2677 | 2649 | udc->gadget.ops = &omap_gadget_ops; |
| 2678 | 2650 | udc->gadget.ep0 = &udc->ep[0].ep; |
| @@ -2702,13 +2674,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) · 23 unmodified lines | ||
| 2702 | 2674 | omap_writew(0, UDC_EP_TX(tmp)); |
| 2703 | 2675 | } |
| 2704 | 2676 | |
| 2705 | −#define OMAP_BULK_EP(name,addr) \ | |
| 2677 | +#define OMAP_BULK_EP(name, addr) \ | |
| 2706 | 2678 | buf = omap_ep_setup(name "-bulk", addr, \ |
| 2707 | 2679 | USB_ENDPOINT_XFER_BULK, buf, 64, 1); |
| 2708 | −#define OMAP_INT_EP(name,addr, maxp) \ | |
| 2680 | +#define OMAP_INT_EP(name, addr, maxp) \ | |
| 2709 | 2681 | buf = omap_ep_setup(name "-int", addr, \ |
| 2710 | 2682 | USB_ENDPOINT_XFER_INT, buf, maxp, 0); |
| 2711 | −#define OMAP_ISO_EP(name,addr, maxp) \ | |
| 2683 | +#define OMAP_ISO_EP(name, addr, maxp) \ | |
| 2712 | 2684 | buf = omap_ep_setup(name "-iso", addr, \ |
| 2713 | 2685 | USB_ENDPOINT_XFER_ISOC, buf, maxp, 1); |
| 2714 | 2686 | |
| @@ -2789,15 +2761,18 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) · 74 unmodified lines | ||
| 2789 | 2761 | return 0; |
| 2790 | 2762 | } |
| 2791 | 2763 | |
| 2792 | −static int __init omap_udc_probe(struct platform_device *pdev) | |
| 2764 | +static int __devinit omap_udc_probe(struct platform_device *pdev) | |
| 2793 | 2765 | { |
| 2794 | 2766 | int status = -ENODEV; |
| 2795 | 2767 | int hmc; |
| 2796 | 2768 | struct usb_phy *xceiv = NULL; |
| 2797 | 2769 | const char *type = NULL; |
| 2798 | 2770 | struct omap_usb_config *config = pdev->dev.platform_data; |
| 2799 | − struct clk *dc_clk; | |
| 2800 | − struct clk *hhc_clk; | |
| 2771 | + struct clk *dc_clk = NULL; | |
| 2772 | + struct clk *hhc_clk = NULL; | |
| 2773 | + | |
| 2774 | + if (cpu_is_omap7xx()) | |
| 2775 | + use_dma = 0; | |
| 2801 | 2776 | |
| 2802 | 2777 | /* NOTE: "knows" the order of the resources! */ |
| 2803 | 2778 | if (!request_mem_region(pdev->resource[0].start, |
| @@ -2817,16 +2792,6 @@ static int __init omap_udc_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 2817 | 2792 | udelay(100); |
| 2818 | 2793 | } |
| 2819 | 2794 | |
| 2820 | − if (cpu_is_omap24xx()) { | |
| 2821 | − dc_clk = clk_get(&pdev->dev, "usb_fck"); | |
| 2822 | − hhc_clk = clk_get(&pdev->dev, "usb_l4_ick"); | |
| 2823 | − BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); | |
| 2824 | − /* can't use omap_udc_enable_clock yet */ | |
| 2825 | − clk_enable(dc_clk); | |
| 2826 | − clk_enable(hhc_clk); | |
| 2827 | − udelay(100); | |
| 2828 | − } | |
| 2829 | − | |
| 2830 | 2795 | if (cpu_is_omap7xx()) { |
| 2831 | 2796 | dc_clk = clk_get(&pdev->dev, "usb_dc_ck"); |
| 2832 | 2797 | hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck"); |
| @@ -2866,8 +2831,8 @@ static int __init omap_udc_probe(struct platform_device *pdev) · 33 unmodified lines | ||
| 2866 | 2831 | * use it. Except for OTG, we don't _need_ to talk to one; |
| 2867 | 2832 | * but not having one probably means no VBUS detection. |
| 2868 | 2833 | */ |
| 2869 | − xceiv = usb_get_transceiver(); | |
| 2870 | − if (xceiv) | |
| 2834 | + xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2835 | + if (!IS_ERR_OR_NULL(xceiv)) | |
| 2871 | 2836 | type = xceiv->label; |
| 2872 | 2837 | else if (config->otg) { |
| 2873 | 2838 | DBG("OTG requires external transceiver!\n"); |
| @@ -2876,14 +2841,6 @@ static int __init omap_udc_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 2876 | 2841 | |
| 2877 | 2842 | hmc = HMC_1610; |
| 2878 | 2843 | |
| 2879 | − if (cpu_is_omap24xx()) { | |
| 2880 | − /* this could be transceiverless in one of the | |
| 2881 | − * "we don't need to know" modes. | |
| 2882 | − */ | |
| 2883 | − type = "external"; | |
| 2884 | − goto known; | |
| 2885 | − } | |
| 2886 | − | |
| 2887 | 2844 | switch (hmc) { |
| 2888 | 2845 | case 0: /* POWERUP DEFAULT == 0 */ |
| 2889 | 2846 | case 4: |
| @@ -2899,7 +2856,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 2899 | 2856 | case 16: |
| 2900 | 2857 | case 19: |
| 2901 | 2858 | case 25: |
| 2902 | − if (!xceiv) { | |
| 2859 | + if (IS_ERR_OR_NULL(xceiv)) { | |
| 2903 | 2860 | DBG("external transceiver not registered!\n"); |
| 2904 | 2861 | type = "unknown"; |
| 2905 | 2862 | } |
| @@ -2922,16 +2879,16 @@ bad_on_1710: · 16 unmodified lines | ||
| 2922 | 2879 | goto cleanup0; |
| 2923 | 2880 | } |
| 2924 | 2881 | } |
| 2925 | −known: | |
| 2882 | + | |
| 2926 | 2883 | INFO("hmc mode %d, %s transceiver\n", hmc, type); |
| 2927 | 2884 | |
| 2928 | 2885 | /* a "gadget" abstracts/virtualizes the controller */ |
| 2929 | 2886 | status = omap_udc_setup(pdev, xceiv); |
| 2930 | − if (status) { | |
| 2887 | + if (status) | |
| 2931 | 2888 | goto cleanup0; |
| 2932 | − } | |
| 2889 | + | |
| 2933 | 2890 | xceiv = NULL; |
| 2934 | − // "udc" is now valid | |
| 2891 | + /* "udc" is now valid */ | |
| 2935 | 2892 | pullup_disable(udc); |
| 2936 | 2893 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 2937 | 2894 | udc->gadget.is_otg = (config->otg != 0); |
| @@ -2945,7 +2902,7 @@ known: · 7 unmodified lines | ||
| 2945 | 2902 | |
| 2946 | 2903 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ |
| 2947 | 2904 | status = request_irq(pdev->resource[1].start, omap_udc_irq, |
| 2948 | − IRQF_SAMPLE_RANDOM, driver_name, udc); | |
| 2905 | + 0, driver_name, udc); | |
| 2949 | 2906 | if (status != 0) { |
| 2950 | 2907 | ERR("can't get irq %d, err %d\n", |
| 2951 | 2908 | (int) pdev->resource[1].start, status); |
| @@ -2954,7 +2911,7 @@ known: · 2 unmodified lines | ||
| 2954 | 2911 | |
| 2955 | 2912 | /* USB "non-iso" IRQ (PIO for all but ep0) */ |
| 2956 | 2913 | status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, |
| 2957 | − IRQF_SAMPLE_RANDOM, "omap_udc pio", udc); | |
| 2914 | + 0, "omap_udc pio", udc); | |
| 2958 | 2915 | if (status != 0) { |
| 2959 | 2916 | ERR("can't get irq %d, err %d\n", |
| 2960 | 2917 | (int) pdev->resource[2].start, status); |
| @@ -2976,16 +2933,6 @@ known: · 15 unmodified lines | ||
| 2976 | 2933 | clk_disable(dc_clk); |
| 2977 | 2934 | } |
| 2978 | 2935 | |
| 2979 | − if (cpu_is_omap24xx()) { | |
| 2980 | − udc->dc_clk = dc_clk; | |
| 2981 | − udc->hhc_clk = hhc_clk; | |
| 2982 | − /* FIXME OMAP2 don't release hhc & dc clock */ | |
| 2983 | −#if 0 | |
| 2984 | − clk_disable(hhc_clk); | |
| 2985 | − clk_disable(dc_clk); | |
| 2986 | −#endif | |
| 2987 | − } | |
| 2988 | − | |
| 2989 | 2936 | create_proc_file(); |
| 2990 | 2937 | status = device_add(&udc->gadget.dev); |
| 2991 | 2938 | if (status) |
| @@ -3007,14 +2954,14 @@ cleanup2: · 15 unmodified lines | ||
| 3007 | 2954 | free_irq(pdev->resource[1].start, udc); |
| 3008 | 2955 | |
| 3009 | 2956 | cleanup1: |
| 3010 | − kfree (udc); | |
| 2957 | + kfree(udc); | |
| 3011 | 2958 | udc = NULL; |
| 3012 | 2959 | |
| 3013 | 2960 | cleanup0: |
| 3014 | − if (xceiv) | |
| 3015 | − usb_put_transceiver(xceiv); | |
| 2961 | + if (!IS_ERR_OR_NULL(xceiv)) | |
| 2962 | + usb_put_phy(xceiv); | |
| 3016 | 2963 | |
| 3017 | − if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) { | |
| 2964 | + if (cpu_is_omap16xx() || cpu_is_omap7xx()) { | |
| 3018 | 2965 | clk_disable(hhc_clk); |
| 3019 | 2966 | clk_disable(dc_clk); |
| 3020 | 2967 | clk_put(hhc_clk); |
| @@ -3027,7 +2974,7 @@ cleanup0: · 6 unmodified lines | ||
| 3027 | 2974 | return status; |
| 3028 | 2975 | } |
| 3029 | 2976 | |
| 3030 | −static int __exit omap_udc_remove(struct platform_device *pdev) | |
| 2977 | +static int __devexit omap_udc_remove(struct platform_device *pdev) | |
| 3031 | 2978 | { |
| 3032 | 2979 | DECLARE_COMPLETION_ONSTACK(done); |
| 3033 | 2980 | |
| @@ -3041,8 +2988,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev) · 7 unmodified lines | ||
| 3041 | 2988 | udc->done = &done; |
| 3042 | 2989 | |
| 3043 | 2990 | pullup_disable(udc); |
| 3044 | − if (udc->transceiver) { | |
| 3045 | − usb_put_transceiver(udc->transceiver); | |
| 2991 | + if (!IS_ERR_OR_NULL(udc->transceiver)) { | |
| 2992 | + usb_put_phy(udc->transceiver); | |
| 3046 | 2993 | udc->transceiver = NULL; |
| 3047 | 2994 | } |
| 3048 | 2995 | omap_writew(0, UDC_SYSCON1); |
| @@ -3112,7 +3059,8 @@ static int omap_udc_resume(struct platform_device *dev) · 63 unmodified lines | ||
| 3112 | 3059 | /*-------------------------------------------------------------------------*/ |
| 3113 | 3060 | |
| 3114 | 3061 | static struct platform_driver udc_driver = { |
| 3115 | − .remove = __exit_p(omap_udc_remove), | |
| 3062 | + .probe = omap_udc_probe, | |
| 3063 | + .remove = __devexit_p(omap_udc_remove), | |
| 3116 | 3064 | .suspend = omap_udc_suspend, |
| 3117 | 3065 | .resume = omap_udc_resume, |
| 3118 | 3066 | .driver = { |
| @@ -3121,27 +3069,7 @@ static struct platform_driver udc_driver = { · 2 unmodified lines | ||
| 3121 | 3069 | }, |
| 3122 | 3070 | }; |
| 3123 | 3071 | |
| 3124 | −static int __init udc_init(void) | |
| 3125 | −{ | |
| 3126 | − /* Disable DMA for omap7xx -- it doesn't work right. */ | |
| 3127 | − if (cpu_is_omap7xx()) | |
| 3128 | − use_dma = 0; | |
| 3129 | − | |
| 3130 | − INFO("%s, version: " DRIVER_VERSION | |
| 3131 | −#ifdef USE_ISO | |
| 3132 | − " (iso)" | |
| 3133 | −#endif | |
| 3134 | − "%s\n", driver_desc, | |
| 3135 | − use_dma ? " (dma)" : ""); | |
| 3136 | − return platform_driver_probe(&udc_driver, omap_udc_probe); | |
| 3137 | −} | |
| 3138 | −module_init(udc_init); | |
| 3139 | − | |
| 3140 | −static void __exit udc_exit(void) | |
| 3141 | −{ | |
| 3142 | − platform_driver_unregister(&udc_driver); | |
| 3143 | −} | |
| 3144 | −module_exit(udc_exit); | |
| 3072 | +module_platform_driver(udc_driver); | |
| 3145 | 3073 | |
| 3146 | 3074 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 3147 | 3075 | MODULE_LICENSE("GPL"); |
| @@ -2208,7 +2208,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep) · 2207 unmodified lines | ||
| 2208 | 2208 | return; |
| 2209 | 2209 | } |
| 2210 | 2210 | if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE) |
| 2211 | − if (td->status | PCH_UDC_DMA_LAST) { | |
| 2211 | + if (td->status & PCH_UDC_DMA_LAST) { | |
| 2212 | 2212 | count = td->status & PCH_UDC_RXTX_BYTES; |
| 2213 | 2213 | break; |
| 2214 | 2214 | } |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/ioport.h> |
| 22 | 22 | #include <linux/types.h> |
| 23 | 23 | #include <linux/errno.h> |
| 24 | +#include <linux/err.h> | |
| 24 | 25 | #include <linux/delay.h> |
| 25 | 26 | #include <linux/slab.h> |
| 26 | 27 | #include <linux/init.h> |
| @@ -993,7 +994,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) · 966 unmodified lines | ||
| 993 | 994 | |
| 994 | 995 | udc = container_of(_gadget, struct pxa25x_udc, gadget); |
| 995 | 996 | |
| 996 | − if (udc->transceiver) | |
| 997 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 997 | 998 | return usb_phy_set_power(udc->transceiver, mA); |
| 998 | 999 | return -EOPNOTSUPP; |
| 999 | 1000 | } |
| @@ -1299,7 +1300,7 @@ fail: · 299 unmodified lines | ||
| 1299 | 1300 | DMSG("registered gadget driver '%s'\n", driver->driver.name); |
| 1300 | 1301 | |
| 1301 | 1302 | /* connect to bus through transceiver */ |
| 1302 | − if (dev->transceiver) { | |
| 1303 | + if (!IS_ERR_OR_NULL(dev->transceiver)) { | |
| 1303 | 1304 | retval = otg_set_peripheral(dev->transceiver->otg, |
| 1304 | 1305 | &dev->gadget); |
| 1305 | 1306 | if (retval) { |
| @@ -1359,7 +1360,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver) · 53 unmodified lines | ||
| 1359 | 1360 | stop_activity(dev, driver); |
| 1360 | 1361 | local_irq_enable(); |
| 1361 | 1362 | |
| 1362 | − if (dev->transceiver) | |
| 1363 | + if (!IS_ERR_OR_NULL(dev->transceiver)) | |
| 1363 | 1364 | (void) otg_set_peripheral(dev->transceiver->otg, NULL); |
| 1364 | 1365 | |
| 1365 | 1366 | driver->unbind(&dev->gadget); |
| @@ -2159,7 +2160,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) · 793 unmodified lines | ||
| 2159 | 2160 | dev->dev = &pdev->dev; |
| 2160 | 2161 | dev->mach = pdev->dev.platform_data; |
| 2161 | 2162 | |
| 2162 | − dev->transceiver = usb_get_transceiver(); | |
| 2163 | + dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2163 | 2164 | |
| 2164 | 2165 | if (gpio_is_valid(dev->mach->gpio_pullup)) { |
| 2165 | 2166 | if ((retval = gpio_request(dev->mach->gpio_pullup, |
| @@ -2237,8 +2238,8 @@ lubbock_fail0: · 71 unmodified lines | ||
| 2237 | 2238 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
| 2238 | 2239 | gpio_free(dev->mach->gpio_pullup); |
| 2239 | 2240 | err_gpio_pullup: |
| 2240 | − if (dev->transceiver) { | |
| 2241 | − usb_put_transceiver(dev->transceiver); | |
| 2241 | + if (!IS_ERR_OR_NULL(dev->transceiver)) { | |
| 2242 | + usb_put_phy(dev->transceiver); | |
| 2242 | 2243 | dev->transceiver = NULL; |
| 2243 | 2244 | } |
| 2244 | 2245 | clk_put(dev->clk); |
| @@ -2279,8 +2280,8 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) · 34 unmodified lines | ||
| 2279 | 2280 | |
| 2280 | 2281 | clk_put(dev->clk); |
| 2281 | 2282 | |
| 2282 | − if (dev->transceiver) { | |
| 2283 | − usb_put_transceiver(dev->transceiver); | |
| 2283 | + if (!IS_ERR_OR_NULL(dev->transceiver)) { | |
| 2284 | + usb_put_phy(dev->transceiver); | |
| 2284 | 2285 | dev->transceiver = NULL; |
| 2285 | 2286 | } |
| 2286 | 2287 | |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/kernel.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | 15 | #include <linux/errno.h> |
| 16 | +#include <linux/err.h> | |
| 16 | 17 | #include <linux/platform_device.h> |
| 17 | 18 | #include <linux/delay.h> |
| 18 | 19 | #include <linux/list.h> |
| @@ -1573,7 +1574,7 @@ static int should_enable_udc(struct pxa_udc *udc) · 1554 unmodified lines | ||
| 1573 | 1574 | int put_on; |
| 1574 | 1575 | |
| 1575 | 1576 | put_on = ((udc->pullup_on) && (udc->driver)); |
| 1576 | − put_on &= ((udc->vbus_sensed) || (!udc->transceiver)); | |
| 1577 | + put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver))); | |
| 1577 | 1578 | return put_on; |
| 1578 | 1579 | } |
| 1579 | 1580 | |
| @@ -1594,7 +1595,7 @@ static int should_disable_udc(struct pxa_udc *udc) · 14 unmodified lines | ||
| 1594 | 1595 | int put_off; |
| 1595 | 1596 | |
| 1596 | 1597 | put_off = ((!udc->pullup_on) || (!udc->driver)); |
| 1597 | − put_off |= ((!udc->vbus_sensed) && (udc->transceiver)); | |
| 1598 | + put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver))); | |
| 1598 | 1599 | return put_off; |
| 1599 | 1600 | } |
| 1600 | 1601 | |
| @@ -1665,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) · 64 unmodified lines | ||
| 1665 | 1666 | struct pxa_udc *udc; |
| 1666 | 1667 | |
| 1667 | 1668 | udc = to_gadget_udc(_gadget); |
| 1668 | − if (udc->transceiver) | |
| 1669 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1669 | 1670 | return usb_phy_set_power(udc->transceiver, mA); |
| 1670 | 1671 | return -EOPNOTSUPP; |
| 1671 | 1672 | } |
| @@ -1834,7 +1835,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver, · 162 unmodified lines | ||
| 1834 | 1835 | dev_dbg(udc->dev, "registered gadget driver '%s'\n", |
| 1835 | 1836 | driver->driver.name); |
| 1836 | 1837 | |
| 1837 | − if (udc->transceiver) { | |
| 1838 | + if (!IS_ERR_OR_NULL(udc->transceiver)) { | |
| 1838 | 1839 | retval = otg_set_peripheral(udc->transceiver->otg, |
| 1839 | 1840 | &udc->gadget); |
| 1840 | 1841 | if (retval) { |
| @@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver) · 67 unmodified lines | ||
| 1908 | 1909 | dev_info(udc->dev, "unregistered gadget driver '%s'\n", |
| 1909 | 1910 | driver->driver.name); |
| 1910 | 1911 | |
| 1911 | − if (udc->transceiver) | |
| 1912 | + if (!IS_ERR_OR_NULL(udc->transceiver)) | |
| 1912 | 1913 | return otg_set_peripheral(udc->transceiver->otg, NULL); |
| 1913 | 1914 | return 0; |
| 1914 | 1915 | } |
| @@ -2464,7 +2465,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) · 549 unmodified lines | ||
| 2464 | 2465 | |
| 2465 | 2466 | udc->dev = &pdev->dev; |
| 2466 | 2467 | udc->mach = pdev->dev.platform_data; |
| 2467 | − udc->transceiver = usb_get_transceiver(); | |
| 2468 | + udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 2468 | 2469 | |
| 2469 | 2470 | gpio = udc->mach->gpio_pullup; |
| 2470 | 2471 | if (gpio_is_valid(gpio)) { |
| @@ -2543,7 +2544,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) · 72 unmodified lines | ||
| 2543 | 2544 | if (gpio_is_valid(gpio)) |
| 2544 | 2545 | gpio_free(gpio); |
| 2545 | 2546 | |
| 2546 | − usb_put_transceiver(udc->transceiver); | |
| 2547 | + usb_put_phy(udc->transceiver); | |
| 2547 | 2548 | |
| 2548 | 2549 | udc->transceiver = NULL; |
| 2549 | 2550 | platform_set_drvdata(_dev, NULL); |
| @@ -112,7 +112,6 @@ struct s3c_hsotg_ep { · 111 unmodified lines | ||
| 112 | 112 | struct s3c_hsotg_req *req; |
| 113 | 113 | struct dentry *debugfs; |
| 114 | 114 | |
| 115 | − spinlock_t lock; | |
| 116 | 115 | |
| 117 | 116 | unsigned long total_data; |
| 118 | 117 | unsigned int size_loaded; |
| @@ -136,7 +135,6 @@ struct s3c_hsotg_ep { · 17 unmodified lines | ||
| 136 | 135 | * @driver: USB gadget driver |
| 137 | 136 | * @plat: The platform specific configuration data. |
| 138 | 137 | * @regs: The memory area mapped for accessing registers. |
| 139 | − * @regs_res: The resource that was allocated when claiming register space. | |
| 140 | 138 | * @irq: The IRQ number we are using |
| 141 | 139 | * @supplies: Definition of USB power supplies |
| 142 | 140 | * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. |
| @@ -157,8 +155,9 @@ struct s3c_hsotg { · 14 unmodified lines | ||
| 157 | 155 | struct usb_gadget_driver *driver; |
| 158 | 156 | struct s3c_hsotg_plat *plat; |
| 159 | 157 | |
| 158 | + spinlock_t lock; | |
| 159 | + | |
| 160 | 160 | void __iomem *regs; |
| 161 | − struct resource *regs_res; | |
| 162 | 161 | int irq; |
| 163 | 162 | struct clk *clk; |
| 164 | 163 | |
| @@ -896,7 +895,6 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, · 731 unmodified lines | ||
| 896 | 895 | struct s3c_hsotg_req *hs_req = our_req(req); |
| 897 | 896 | struct s3c_hsotg_ep *hs_ep = our_ep(ep); |
| 898 | 897 | struct s3c_hsotg *hs = hs_ep->parent; |
| 899 | − unsigned long irqflags; | |
| 900 | 898 | bool first; |
| 901 | 899 | |
| 902 | 900 | dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", |
| @@ -915,19 +913,30 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, · 12 unmodified lines | ||
| 915 | 913 | return ret; |
| 916 | 914 | } |
| 917 | 915 | |
| 918 | − spin_lock_irqsave(&hs_ep->lock, irqflags); | |
| 919 | − | |
| 920 | 916 | first = list_empty(&hs_ep->queue); |
| 921 | 917 | list_add_tail(&hs_req->queue, &hs_ep->queue); |
| 922 | 918 | |
| 923 | 919 | if (first) |
| 924 | 920 | s3c_hsotg_start_req(hs, hs_ep, hs_req, false); |
| 925 | 921 | |
| 926 | − spin_unlock_irqrestore(&hs_ep->lock, irqflags); | |
| 927 | − | |
| 928 | 922 | return 0; |
| 929 | 923 | } |
| 930 | 924 | |
| 925 | +static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, | |
| 926 | + gfp_t gfp_flags) | |
| 927 | +{ | |
| 928 | + struct s3c_hsotg_ep *hs_ep = our_ep(ep); | |
| 929 | + struct s3c_hsotg *hs = hs_ep->parent; | |
| 930 | + unsigned long flags = 0; | |
| 931 | + int ret = 0; | |
| 932 | + | |
| 933 | + spin_lock_irqsave(&hs->lock, flags); | |
| 934 | + ret = s3c_hsotg_ep_queue(ep, req, gfp_flags); | |
| 935 | + spin_unlock_irqrestore(&hs->lock, flags); | |
| 936 | + | |
| 937 | + return ret; | |
| 938 | +} | |
| 939 | + | |
| 931 | 940 | static void s3c_hsotg_ep_free_request(struct usb_ep *ep, |
| 932 | 941 | struct usb_request *req) |
| 933 | 942 | { |
| @@ -1383,9 +1392,9 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, · 449 unmodified lines | ||
| 1383 | 1392 | */ |
| 1384 | 1393 | |
| 1385 | 1394 | if (hs_req->req.complete) { |
| 1386 | − spin_unlock(&hs_ep->lock); | |
| 1395 | + spin_unlock(&hsotg->lock); | |
| 1387 | 1396 | hs_req->req.complete(&hs_ep->ep, &hs_req->req); |
| 1388 | − spin_lock(&hs_ep->lock); | |
| 1397 | + spin_lock(&hsotg->lock); | |
| 1389 | 1398 | } |
| 1390 | 1399 | |
| 1391 | 1400 | /* |
| @@ -1403,28 +1412,6 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, · 11 unmodified lines | ||
| 1403 | 1412 | } |
| 1404 | 1413 | } |
| 1405 | 1414 | |
| 1406 | −/** | |
| 1407 | − * s3c_hsotg_complete_request_lock - complete a request given to us (locked) | |
| 1408 | − * @hsotg: The device state. | |
| 1409 | − * @hs_ep: The endpoint the request was on. | |
| 1410 | − * @hs_req: The request to complete. | |
| 1411 | − * @result: The result code (0 => Ok, otherwise errno) | |
| 1412 | − * | |
| 1413 | − * See s3c_hsotg_complete_request(), but called with the endpoint's | |
| 1414 | − * lock held. | |
| 1415 | − */ | |
| 1416 | −static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, | |
| 1417 | − struct s3c_hsotg_ep *hs_ep, | |
| 1418 | − struct s3c_hsotg_req *hs_req, | |
| 1419 | − int result) | |
| 1420 | −{ | |
| 1421 | − unsigned long flags; | |
| 1422 | − | |
| 1423 | − spin_lock_irqsave(&hs_ep->lock, flags); | |
| 1424 | − s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); | |
| 1425 | − spin_unlock_irqrestore(&hs_ep->lock, flags); | |
| 1426 | −} | |
| 1427 | − | |
| 1428 | 1415 | /** |
| 1429 | 1416 | * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint |
| 1430 | 1417 | * @hsotg: The device state. |
| @@ -1444,6 +1431,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) · 13 unmodified lines | ||
| 1444 | 1431 | int max_req; |
| 1445 | 1432 | int read_ptr; |
| 1446 | 1433 | |
| 1434 | + | |
| 1447 | 1435 | if (!hs_req) { |
| 1448 | 1436 | u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); |
| 1449 | 1437 | int ptr; |
| @@ -1459,8 +1447,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) · 9 unmodified lines | ||
| 1459 | 1447 | return; |
| 1460 | 1448 | } |
| 1461 | 1449 | |
| 1462 | − spin_lock(&hs_ep->lock); | |
| 1463 | − | |
| 1464 | 1450 | to_read = size; |
| 1465 | 1451 | read_ptr = hs_req->req.actual; |
| 1466 | 1452 | max_req = hs_req->req.length - read_ptr; |
| @@ -1487,8 +1473,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) · 20 unmodified lines | ||
| 1487 | 1473 | * alignment of the data. |
| 1488 | 1474 | */ |
| 1489 | 1475 | readsl(fifo, hs_req->req.buf + read_ptr, to_read); |
| 1490 | − | |
| 1491 | − spin_unlock(&hs_ep->lock); | |
| 1492 | 1476 | } |
| 1493 | 1477 | |
| 1494 | 1478 | /** |
| @@ -1609,7 +1593,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, · 114 unmodified lines | ||
| 1609 | 1593 | s3c_hsotg_send_zlp(hsotg, hs_req); |
| 1610 | 1594 | } |
| 1611 | 1595 | |
| 1612 | − s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); | |
| 1596 | + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); | |
| 1613 | 1597 | } |
| 1614 | 1598 | |
| 1615 | 1599 | /** |
| @@ -1864,7 +1848,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, · 248 unmodified lines | ||
| 1864 | 1848 | /* Finish ZLP handling for IN EP0 transactions */ |
| 1865 | 1849 | if (hsotg->eps[0].sent_zlp) { |
| 1866 | 1850 | dev_dbg(hsotg->dev, "zlp packet received\n"); |
| 1867 | − s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); | |
| 1851 | + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); | |
| 1868 | 1852 | return; |
| 1869 | 1853 | } |
| 1870 | 1854 | |
| @@ -1915,7 +1899,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, · 44 unmodified lines | ||
| 1915 | 1899 | dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); |
| 1916 | 1900 | s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); |
| 1917 | 1901 | } else |
| 1918 | − s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); | |
| 1902 | + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); | |
| 1919 | 1903 | } |
| 1920 | 1904 | |
| 1921 | 1905 | /** |
| @@ -2123,9 +2107,6 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, · 201 unmodified lines | ||
| 2123 | 2107 | int result, bool force) |
| 2124 | 2108 | { |
| 2125 | 2109 | struct s3c_hsotg_req *req, *treq; |
| 2126 | − unsigned long flags; | |
| 2127 | − | |
| 2128 | − spin_lock_irqsave(&ep->lock, flags); | |
| 2129 | 2110 | |
| 2130 | 2111 | list_for_each_entry_safe(req, treq, &ep->queue, queue) { |
| 2131 | 2112 | /* |
| @@ -2139,14 +2120,15 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, · 7 unmodified lines | ||
| 2139 | 2120 | s3c_hsotg_complete_request(hsotg, ep, req, |
| 2140 | 2121 | result); |
| 2141 | 2122 | } |
| 2142 | − | |
| 2143 | − spin_unlock_irqrestore(&ep->lock, flags); | |
| 2144 | 2123 | } |
| 2145 | 2124 | |
| 2146 | 2125 | #define call_gadget(_hs, _entry) \ |
| 2147 | 2126 | if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ |
| 2148 | − (_hs)->driver && (_hs)->driver->_entry) \ | |
| 2149 | − (_hs)->driver->_entry(&(_hs)->gadget); | |
| 2127 | + (_hs)->driver && (_hs)->driver->_entry) { \ | |
| 2128 | + spin_unlock(&_hs->lock); \ | |
| 2129 | + (_hs)->driver->_entry(&(_hs)->gadget); \ | |
| 2130 | + spin_lock(&_hs->lock); \ | |
| 2131 | + } | |
| 2150 | 2132 | |
| 2151 | 2133 | /** |
| 2152 | 2134 | * s3c_hsotg_disconnect - disconnect service |
| @@ -2388,6 +2370,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) · 235 unmodified lines | ||
| 2388 | 2370 | u32 gintsts; |
| 2389 | 2371 | u32 gintmsk; |
| 2390 | 2372 | |
| 2373 | + spin_lock(&hsotg->lock); | |
| 2391 | 2374 | irq_retry: |
| 2392 | 2375 | gintsts = readl(hsotg->regs + GINTSTS); |
| 2393 | 2376 | gintmsk = readl(hsotg->regs + GINTMSK); |
| @@ -2557,6 +2540,8 @@ irq_retry: · 163 unmodified lines | ||
| 2557 | 2540 | if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) |
| 2558 | 2541 | goto irq_retry; |
| 2559 | 2542 | |
| 2543 | + spin_unlock(&hsotg->lock); | |
| 2544 | + | |
| 2560 | 2545 | return IRQ_HANDLED; |
| 2561 | 2546 | } |
| 2562 | 2547 | |
| @@ -2604,7 +2589,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, · 41 unmodified lines | ||
| 2604 | 2589 | dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", |
| 2605 | 2590 | __func__, epctrl, epctrl_reg); |
| 2606 | 2591 | |
| 2607 | − spin_lock_irqsave(&hs_ep->lock, flags); | |
| 2592 | + spin_lock_irqsave(&hsotg->lock, flags); | |
| 2608 | 2593 | |
| 2609 | 2594 | epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK); |
| 2610 | 2595 | epctrl |= DxEPCTL_MPS(mps); |
| @@ -2683,7 +2668,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, · 72 unmodified lines | ||
| 2683 | 2668 | s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); |
| 2684 | 2669 | |
| 2685 | 2670 | out: |
| 2686 | − spin_unlock_irqrestore(&hs_ep->lock, flags); | |
| 2671 | + spin_unlock_irqrestore(&hsotg->lock, flags); | |
| 2687 | 2672 | return ret; |
| 2688 | 2673 | } |
| 2689 | 2674 | |
| @@ -2710,10 +2695,10 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) · 20 unmodified lines | ||
| 2710 | 2695 | |
| 2711 | 2696 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); |
| 2712 | 2697 | |
| 2698 | + spin_lock_irqsave(&hsotg->lock, flags); | |
| 2713 | 2699 | /* terminate all requests with shutdown */ |
| 2714 | 2700 | kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); |
| 2715 | 2701 | |
| 2716 | − spin_lock_irqsave(&hs_ep->lock, flags); | |
| 2717 | 2702 | |
| 2718 | 2703 | ctrl = readl(hsotg->regs + epctrl_reg); |
| 2719 | 2704 | ctrl &= ~DxEPCTL_EPEna; |
| @@ -2726,7 +2711,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) · 6 unmodified lines | ||
| 2726 | 2711 | /* disable endpoint interrupts */ |
| 2727 | 2712 | s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); |
| 2728 | 2713 | |
| 2729 | − spin_unlock_irqrestore(&hs_ep->lock, flags); | |
| 2714 | + spin_unlock_irqrestore(&hsotg->lock, flags); | |
| 2730 | 2715 | return 0; |
| 2731 | 2716 | } |
| 2732 | 2717 | |
| @@ -2761,15 +2746,15 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) · 28 unmodified lines | ||
| 2761 | 2746 | |
| 2762 | 2747 | dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); |
| 2763 | 2748 | |
| 2764 | − spin_lock_irqsave(&hs_ep->lock, flags); | |
| 2749 | + spin_lock_irqsave(&hs->lock, flags); | |
| 2765 | 2750 | |
| 2766 | 2751 | if (!on_list(hs_ep, hs_req)) { |
| 2767 | − spin_unlock_irqrestore(&hs_ep->lock, flags); | |
| 2752 | + spin_unlock_irqrestore(&hs->lock, flags); | |
| 2768 | 2753 | return -EINVAL; |
| 2769 | 2754 | } |
| 2770 | 2755 | |
| 2771 | 2756 | s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); |
| 2772 | − spin_unlock_irqrestore(&hs_ep->lock, flags); | |
| 2757 | + spin_unlock_irqrestore(&hs->lock, flags); | |
| 2773 | 2758 | |
| 2774 | 2759 | return 0; |
| 2775 | 2760 | } |
| @@ -2784,15 +2769,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) · 8 unmodified lines | ||
| 2784 | 2769 | struct s3c_hsotg_ep *hs_ep = our_ep(ep); |
| 2785 | 2770 | struct s3c_hsotg *hs = hs_ep->parent; |
| 2786 | 2771 | int index = hs_ep->index; |
| 2787 | − unsigned long irqflags; | |
| 2788 | 2772 | u32 epreg; |
| 2789 | 2773 | u32 epctl; |
| 2790 | 2774 | u32 xfertype; |
| 2791 | 2775 | |
| 2792 | 2776 | dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); |
| 2793 | 2777 | |
| 2794 | − spin_lock_irqsave(&hs_ep->lock, irqflags); | |
| 2795 | − | |
| 2796 | 2778 | /* write both IN and OUT control registers */ |
| 2797 | 2779 | |
| 2798 | 2780 | epreg = DIEPCTL(index); |
| @@ -2827,19 +2809,36 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) · 28 unmodified lines | ||
| 2827 | 2809 | |
| 2828 | 2810 | writel(epctl, hs->regs + epreg); |
| 2829 | 2811 | |
| 2830 | − spin_unlock_irqrestore(&hs_ep->lock, irqflags); | |
| 2831 | − | |
| 2832 | 2812 | return 0; |
| 2833 | 2813 | } |
| 2834 | 2814 | |
| 2815 | +/** | |
| 2816 | + * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held | |
| 2817 | + * @ep: The endpoint to set halt. | |
| 2818 | + * @value: Set or unset the halt. | |
| 2819 | + */ | |
| 2820 | +static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) | |
| 2821 | +{ | |
| 2822 | + struct s3c_hsotg_ep *hs_ep = our_ep(ep); | |
| 2823 | + struct s3c_hsotg *hs = hs_ep->parent; | |
| 2824 | + unsigned long flags = 0; | |
| 2825 | + int ret = 0; | |
| 2826 | + | |
| 2827 | + spin_lock_irqsave(&hs->lock, flags); | |
| 2828 | + ret = s3c_hsotg_ep_sethalt(ep, value); | |
| 2829 | + spin_unlock_irqrestore(&hs->lock, flags); | |
| 2830 | + | |
| 2831 | + return ret; | |
| 2832 | +} | |
| 2833 | + | |
| 2835 | 2834 | static struct usb_ep_ops s3c_hsotg_ep_ops = { |
| 2836 | 2835 | .enable = s3c_hsotg_ep_enable, |
| 2837 | 2836 | .disable = s3c_hsotg_ep_disable, |
| 2838 | 2837 | .alloc_request = s3c_hsotg_ep_alloc_request, |
| 2839 | 2838 | .free_request = s3c_hsotg_ep_free_request, |
| 2840 | − .queue = s3c_hsotg_ep_queue, | |
| 2839 | + .queue = s3c_hsotg_ep_queue_lock, | |
| 2841 | 2840 | .dequeue = s3c_hsotg_ep_dequeue, |
| 2842 | − .set_halt = s3c_hsotg_ep_sethalt, | |
| 2841 | + .set_halt = s3c_hsotg_ep_sethalt_lock, | |
| 2843 | 2842 | /* note, don't believe we have any call for the fifo routines */ |
| 2844 | 2843 | }; |
| 2845 | 2844 | |
| @@ -2954,6 +2953,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, · 108 unmodified lines | ||
| 2954 | 2953 | driver->driver.bus = NULL; |
| 2955 | 2954 | hsotg->driver = driver; |
| 2956 | 2955 | hsotg->gadget.dev.driver = &driver->driver; |
| 2956 | + hsotg->gadget.dev.of_node = hsotg->dev->of_node; | |
| 2957 | 2957 | hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; |
| 2958 | 2958 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; |
| 2959 | 2959 | |
| @@ -2964,9 +2964,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, · 4 unmodified lines | ||
| 2964 | 2964 | goto err; |
| 2965 | 2965 | } |
| 2966 | 2966 | |
| 2967 | − s3c_hsotg_phy_enable(hsotg); | |
| 2968 | − | |
| 2969 | − s3c_hsotg_core_init(hsotg); | |
| 2970 | 2967 | hsotg->last_rst = jiffies; |
| 2971 | 2968 | dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); |
| 2972 | 2969 | return 0; |
| @@ -2988,6 +2985,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, · 15 unmodified lines | ||
| 2988 | 2985 | struct usb_gadget_driver *driver) |
| 2989 | 2986 | { |
| 2990 | 2987 | struct s3c_hsotg *hsotg = to_hsotg(gadget); |
| 2988 | + unsigned long flags = 0; | |
| 2991 | 2989 | int ep; |
| 2992 | 2990 | |
| 2993 | 2991 | if (!hsotg) |
| @@ -3000,6 +2998,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, · 6 unmodified lines | ||
| 3000 | 2998 | for (ep = 0; ep < hsotg->num_of_eps; ep++) |
| 3001 | 2999 | s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); |
| 3002 | 3000 | |
| 3001 | + spin_lock_irqsave(&hsotg->lock, flags); | |
| 3002 | + | |
| 3003 | 3003 | s3c_hsotg_phy_disable(hsotg); |
| 3004 | 3004 | regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); |
| 3005 | 3005 | |
| @@ -3007,6 +3007,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, · 1 unmodified line | ||
| 3007 | 3007 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; |
| 3008 | 3008 | hsotg->gadget.dev.driver = NULL; |
| 3009 | 3009 | |
| 3010 | + spin_unlock_irqrestore(&hsotg->lock, flags); | |
| 3011 | + | |
| 3010 | 3012 | dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", |
| 3011 | 3013 | driver->driver.name); |
| 3012 | 3014 | |
| @@ -3024,10 +3026,40 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) · 11 unmodified lines | ||
| 3024 | 3026 | return s3c_hsotg_read_frameno(to_hsotg(gadget)); |
| 3025 | 3027 | } |
| 3026 | 3028 | |
| 3029 | +/** | |
| 3030 | + * s3c_hsotg_pullup - connect/disconnect the USB PHY | |
| 3031 | + * @gadget: The usb gadget state | |
| 3032 | + * @is_on: Current state of the USB PHY | |
| 3033 | + * | |
| 3034 | + * Connect/Disconnect the USB PHY pullup | |
| 3035 | + */ | |
| 3036 | +static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) | |
| 3037 | +{ | |
| 3038 | + struct s3c_hsotg *hsotg = to_hsotg(gadget); | |
| 3039 | + unsigned long flags = 0; | |
| 3040 | + | |
| 3041 | + dev_dbg(hsotg->dev, "%s: is_in: %d\n", __func__, is_on); | |
| 3042 | + | |
| 3043 | + spin_lock_irqsave(&hsotg->lock, flags); | |
| 3044 | + if (is_on) { | |
| 3045 | + s3c_hsotg_phy_enable(hsotg); | |
| 3046 | + s3c_hsotg_core_init(hsotg); | |
| 3047 | + } else { | |
| 3048 | + s3c_hsotg_disconnect(hsotg); | |
| 3049 | + s3c_hsotg_phy_disable(hsotg); | |
| 3050 | + } | |
| 3051 | + | |
| 3052 | + hsotg->gadget.speed = USB_SPEED_UNKNOWN; | |
| 3053 | + spin_unlock_irqrestore(&hsotg->lock, flags); | |
| 3054 | + | |
| 3055 | + return 0; | |
| 3056 | +} | |
| 3057 | + | |
| 3027 | 3058 | static struct usb_gadget_ops s3c_hsotg_gadget_ops = { |
| 3028 | 3059 | .get_frame = s3c_hsotg_gadget_getframe, |
| 3029 | 3060 | .udc_start = s3c_hsotg_udc_start, |
| 3030 | 3061 | .udc_stop = s3c_hsotg_udc_stop, |
| 3062 | + .pullup = s3c_hsotg_pullup, | |
| 3031 | 3063 | }; |
| 3032 | 3064 | |
| 3033 | 3065 | /** |
| @@ -3063,8 +3095,6 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, · 29 unmodified lines | ||
| 3063 | 3095 | INIT_LIST_HEAD(&hs_ep->queue); |
| 3064 | 3096 | INIT_LIST_HEAD(&hs_ep->ep.ep_list); |
| 3065 | 3097 | |
| 3066 | − spin_lock_init(&hs_ep->lock); | |
| 3067 | − | |
| 3068 | 3098 | /* add to the list of endpoints known by the gadget driver */ |
| 3069 | 3099 | if (epnum) |
| 3070 | 3100 | list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); |
| @@ -3342,7 +3372,7 @@ static int ep_show(struct seq_file *seq, void *v) · 271 unmodified lines | ||
| 3342 | 3372 | seq_printf(seq, "request list (%p,%p):\n", |
| 3343 | 3373 | ep->queue.next, ep->queue.prev); |
| 3344 | 3374 | |
| 3345 | − spin_lock_irqsave(&ep->lock, flags); | |
| 3375 | + spin_lock_irqsave(&hsotg->lock, flags); | |
| 3346 | 3376 | |
| 3347 | 3377 | list_for_each_entry(req, &ep->queue, queue) { |
| 3348 | 3378 | if (--show_limit < 0) { |
| @@ -3357,7 +3387,7 @@ static int ep_show(struct seq_file *seq, void *v) · 8 unmodified lines | ||
| 3357 | 3387 | req->req.actual, req->req.status); |
| 3358 | 3388 | } |
| 3359 | 3389 | |
| 3360 | − spin_unlock_irqrestore(&ep->lock, flags); | |
| 3390 | + spin_unlock_irqrestore(&hsotg->lock, flags); | |
| 3361 | 3391 | |
| 3362 | 3392 | return 0; |
| 3363 | 3393 | } |
| @@ -3477,7 +3507,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) · 113 unmodified lines | ||
| 3477 | 3507 | return -EINVAL; |
| 3478 | 3508 | } |
| 3479 | 3509 | |
| 3480 | − hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL); | |
| 3510 | + hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL); | |
| 3481 | 3511 | if (!hsotg) { |
| 3482 | 3512 | dev_err(dev, "cannot get memory\n"); |
| 3483 | 3513 | return -ENOMEM; |
| @@ -3489,46 +3519,35 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 3489 | 3519 | hsotg->clk = clk_get(&pdev->dev, "otg"); |
| 3490 | 3520 | if (IS_ERR(hsotg->clk)) { |
| 3491 | 3521 | dev_err(dev, "cannot get otg clock\n"); |
| 3492 | − ret = PTR_ERR(hsotg->clk); | |
| 3493 | − goto err_mem; | |
| 3522 | + return PTR_ERR(hsotg->clk); | |
| 3494 | 3523 | } |
| 3495 | 3524 | |
| 3496 | 3525 | platform_set_drvdata(pdev, hsotg); |
| 3497 | 3526 | |
| 3498 | 3527 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 3499 | − if (!res) { | |
| 3500 | − dev_err(dev, "cannot find register resource 0\n"); | |
| 3501 | − ret = -EINVAL; | |
| 3502 | − goto err_clk; | |
| 3503 | − } | |
| 3504 | − | |
| 3505 | − hsotg->regs_res = request_mem_region(res->start, resource_size(res), | |
| 3506 | − dev_name(dev)); | |
| 3507 | − if (!hsotg->regs_res) { | |
| 3508 | − dev_err(dev, "cannot reserve registers\n"); | |
| 3509 | − ret = -ENOENT; | |
| 3510 | − goto err_clk; | |
| 3511 | − } | |
| 3512 | 3528 | |
| 3513 | − hsotg->regs = ioremap(res->start, resource_size(res)); | |
| 3529 | + hsotg->regs = devm_request_and_ioremap(&pdev->dev, res); | |
| 3514 | 3530 | if (!hsotg->regs) { |
| 3515 | 3531 | dev_err(dev, "cannot map registers\n"); |
| 3516 | 3532 | ret = -ENXIO; |
| 3517 | − goto err_regs_res; | |
| 3533 | + goto err_clk; | |
| 3518 | 3534 | } |
| 3519 | 3535 | |
| 3520 | 3536 | ret = platform_get_irq(pdev, 0); |
| 3521 | 3537 | if (ret < 0) { |
| 3522 | 3538 | dev_err(dev, "cannot find IRQ\n"); |
| 3523 | − goto err_regs; | |
| 3539 | + goto err_clk; | |
| 3524 | 3540 | } |
| 3525 | 3541 | |
| 3542 | + spin_lock_init(&hsotg->lock); | |
| 3543 | + | |
| 3526 | 3544 | hsotg->irq = ret; |
| 3527 | 3545 | |
| 3528 | − ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg); | |
| 3546 | + ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, | |
| 3547 | + dev_name(dev), hsotg); | |
| 3529 | 3548 | if (ret < 0) { |
| 3530 | 3549 | dev_err(dev, "cannot claim IRQ\n"); |
| 3531 | − goto err_regs; | |
| 3550 | + goto err_clk; | |
| 3532 | 3551 | } |
| 3533 | 3552 | |
| 3534 | 3553 | dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); |
| @@ -3558,7 +3577,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) · 23 unmodified lines | ||
| 3558 | 3577 | hsotg->supplies); |
| 3559 | 3578 | if (ret) { |
| 3560 | 3579 | dev_err(dev, "failed to request supplies: %d\n", ret); |
| 3561 | − goto err_irq; | |
| 3580 | + goto err_clk; | |
| 3562 | 3581 | } |
| 3563 | 3582 | |
| 3564 | 3583 | ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), |
| @@ -3642,19 +3661,11 @@ err_ep_mem: · 77 unmodified lines | ||
| 3642 | 3661 | err_supplies: |
| 3643 | 3662 | s3c_hsotg_phy_disable(hsotg); |
| 3644 | 3663 | regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); |
| 3645 | −err_irq: | |
| 3646 | − free_irq(hsotg->irq, hsotg); | |
| 3647 | −err_regs: | |
| 3648 | − iounmap(hsotg->regs); | |
| 3649 | − | |
| 3650 | −err_regs_res: | |
| 3651 | − release_resource(hsotg->regs_res); | |
| 3652 | − kfree(hsotg->regs_res); | |
| 3664 | + | |
| 3653 | 3665 | err_clk: |
| 3654 | 3666 | clk_disable_unprepare(hsotg->clk); |
| 3655 | 3667 | clk_put(hsotg->clk); |
| 3656 | −err_mem: | |
| 3657 | − kfree(hsotg); | |
| 3668 | + | |
| 3658 | 3669 | return ret; |
| 3659 | 3670 | } |
| 3660 | 3671 | |
| @@ -3675,12 +3686,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) · 14 unmodified lines | ||
| 3675 | 3686 | usb_gadget_unregister_driver(hsotg->driver); |
| 3676 | 3687 | } |
| 3677 | 3688 | |
| 3678 | − free_irq(hsotg->irq, hsotg); | |
| 3679 | − iounmap(hsotg->regs); | |
| 3680 | − | |
| 3681 | − release_resource(hsotg->regs_res); | |
| 3682 | − kfree(hsotg->regs_res); | |
| 3683 | − | |
| 3684 | 3689 | s3c_hsotg_phy_disable(hsotg); |
| 3685 | 3690 | regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); |
| 3686 | 3691 | |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/io.h> |
| 25 | 25 | #include <linux/slab.h> |
| 26 | 26 | #include <linux/clk.h> |
| 27 | +#include <linux/err.h> | |
| 27 | 28 | #include <linux/usb/ch9.h> |
| 28 | 29 | #include <linux/usb/gadget.h> |
| 29 | 30 | #include <linux/usb/otg.h> |
| @@ -1165,7 +1166,7 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, · 1135 unmodified lines | ||
| 1165 | 1166 | } |
| 1166 | 1167 | |
| 1167 | 1168 | /* connect to bus through transceiver */ |
| 1168 | − if (hsudc->transceiver) { | |
| 1169 | + if (!IS_ERR_OR_NULL(hsudc->transceiver)) { | |
| 1169 | 1170 | ret = otg_set_peripheral(hsudc->transceiver->otg, |
| 1170 | 1171 | &hsudc->gadget); |
| 1171 | 1172 | if (ret) { |
| @@ -1220,7 +1221,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, · 48 unmodified lines | ||
| 1220 | 1221 | s3c_hsudc_stop_activity(hsudc); |
| 1221 | 1222 | spin_unlock_irqrestore(&hsudc->lock, flags); |
| 1222 | 1223 | |
| 1223 | − if (hsudc->transceiver) | |
| 1224 | + if (!IS_ERR_OR_NULL(hsudc->transceiver)) | |
| 1224 | 1225 | (void) otg_set_peripheral(hsudc->transceiver->otg, NULL); |
| 1225 | 1226 | |
| 1226 | 1227 | disable_irq(hsudc->irq); |
| @@ -1249,7 +1250,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) · 22 unmodified lines | ||
| 1249 | 1250 | if (!hsudc) |
| 1250 | 1251 | return -ENODEV; |
| 1251 | 1252 | |
| 1252 | − if (hsudc->transceiver) | |
| 1253 | + if (!IS_ERR_OR_NULL(hsudc->transceiver)) | |
| 1253 | 1254 | return usb_phy_set_power(hsudc->transceiver, mA); |
| 1254 | 1255 | |
| 1255 | 1256 | return -EOPNOTSUPP; |
| @@ -1282,7 +1283,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) · 26 unmodified lines | ||
| 1282 | 1283 | hsudc->dev = dev; |
| 1283 | 1284 | hsudc->pd = pdev->dev.platform_data; |
| 1284 | 1285 | |
| 1285 | − hsudc->transceiver = usb_get_transceiver(); | |
| 1286 | + hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 1286 | 1287 | |
| 1287 | 1288 | for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++) |
| 1288 | 1289 | hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; |
| @@ -1385,8 +1386,8 @@ err_irq: · 96 unmodified lines | ||
| 1385 | 1386 | err_remap: |
| 1386 | 1387 | release_mem_region(res->start, resource_size(res)); |
| 1387 | 1388 | err_res: |
| 1388 | − if (hsudc->transceiver) | |
| 1389 | − usb_put_transceiver(hsudc->transceiver); | |
| 1389 | + if (!IS_ERR_OR_NULL(hsudc->transceiver)) | |
| 1390 | + usb_put_phy(hsudc->transceiver); | |
| 1390 | 1391 | |
| 1391 | 1392 | regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); |
| 1392 | 1393 | err_supplies: |
| @@ -37,12 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. |
| 38 | 38 | */ |
| 39 | 39 | |
| 40 | −/* | |
| 41 | − * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included | |
| 42 | − * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN | |
| 43 | − * characters rather then a pointer to void. | |
| 44 | − */ | |
| 45 | − | |
| 46 | 40 | /* |
| 47 | 41 | * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers |
| 48 | 42 | * sets the number of pipeline buffers (length of the fsg_buffhd array). |
| @@ -260,11 +254,7 @@ enum fsg_buffer_state { · 211 unmodified lines | ||
| 260 | 254 | }; |
| 261 | 255 | |
| 262 | 256 | struct fsg_buffhd { |
| 263 | −#ifdef FSG_BUFFHD_STATIC_BUFFER | |
| 264 | − char buf[FSG_BUFLEN]; | |
| 265 | −#else | |
| 266 | 257 | void *buf; |
| 267 | −#endif | |
| 268 | 258 | enum fsg_buffer_state state; |
| 269 | 259 | struct fsg_buffhd *next; |
| 270 | 260 | |
| @@ -627,6 +617,16 @@ static struct usb_gadget_strings fsg_stringtab = { · 356 unmodified lines | ||
| 627 | 617 | * the caller must own fsg->filesem for writing. |
| 628 | 618 | */ |
| 629 | 619 | |
| 620 | +static void fsg_lun_close(struct fsg_lun *curlun) | |
| 621 | +{ | |
| 622 | + if (curlun->filp) { | |
| 623 | + LDBG(curlun, "close backing file\n"); | |
| 624 | + fput(curlun->filp); | |
| 625 | + curlun->filp = NULL; | |
| 626 | + } | |
| 627 | +} | |
| 628 | + | |
| 629 | + | |
| 630 | 630 | static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) |
| 631 | 631 | { |
| 632 | 632 | int ro; |
| @@ -636,6 +636,8 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) · 3 unmodified lines | ||
| 636 | 636 | loff_t size; |
| 637 | 637 | loff_t num_sectors; |
| 638 | 638 | loff_t min_sectors; |
| 639 | + unsigned int blkbits; | |
| 640 | + unsigned int blksize; | |
| 639 | 641 | |
| 640 | 642 | /* R/W if we can, R/O if we must */ |
| 641 | 643 | ro = curlun->initially_ro; |
| @@ -680,17 +682,17 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) · 38 unmodified lines | ||
| 680 | 682 | } |
| 681 | 683 | |
| 682 | 684 | if (curlun->cdrom) { |
| 683 | − curlun->blksize = 2048; | |
| 684 | − curlun->blkbits = 11; | |
| 685 | + blksize = 2048; | |
| 686 | + blkbits = 11; | |
| 685 | 687 | } else if (inode->i_bdev) { |
| 686 | − curlun->blksize = bdev_logical_block_size(inode->i_bdev); | |
| 687 | − curlun->blkbits = blksize_bits(curlun->blksize); | |
| 688 | + blksize = bdev_logical_block_size(inode->i_bdev); | |
| 689 | + blkbits = blksize_bits(blksize); | |
| 688 | 690 | } else { |
| 689 | − curlun->blksize = 512; | |
| 690 | − curlun->blkbits = 9; | |
| 691 | + blksize = 512; | |
| 692 | + blkbits = 9; | |
| 691 | 693 | } |
| 692 | 694 | |
| 693 | − num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */ | |
| 695 | + num_sectors = size >> blkbits; /* File size in logic-block-size blocks */ | |
| 694 | 696 | min_sectors = 1; |
| 695 | 697 | if (curlun->cdrom) { |
| 696 | 698 | min_sectors = 300; /* Smallest track is 300 frames */ |
| @@ -707,7 +709,12 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) · 10 unmodified lines | ||
| 707 | 709 | goto out; |
| 708 | 710 | } |
| 709 | 711 | |
| 712 | + if (fsg_lun_is_open(curlun)) | |
| 713 | + fsg_lun_close(curlun); | |
| 714 | + | |
| 710 | 715 | get_file(filp); |
| 716 | + curlun->blksize = blksize; | |
| 717 | + curlun->blkbits = blkbits; | |
| 711 | 718 | curlun->ro = ro; |
| 712 | 719 | curlun->filp = filp; |
| 713 | 720 | curlun->file_length = size; |
| @@ -721,16 +728,6 @@ out: · 7 unmodified lines | ||
| 721 | 728 | } |
| 722 | 729 | |
| 723 | 730 | |
| 724 | −static void fsg_lun_close(struct fsg_lun *curlun) | |
| 725 | −{ | |
| 726 | − if (curlun->filp) { | |
| 727 | − LDBG(curlun, "close backing file\n"); | |
| 728 | − fput(curlun->filp); | |
| 729 | − curlun->filp = NULL; | |
| 730 | − } | |
| 731 | −} | |
| 732 | − | |
| 733 | − | |
| 734 | 731 | /*-------------------------------------------------------------------------*/ |
| 735 | 732 | |
| 736 | 733 | /* |
| @@ -881,19 +878,17 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, · 144 unmodified lines | ||
| 881 | 878 | if (count > 0 && buf[count-1] == '\n') |
| 882 | 879 | ((char *) buf)[count-1] = 0; /* Ugh! */ |
| 883 | 880 | |
| 884 | − /* Eject current medium */ | |
| 885 | − down_write(filesem); | |
| 886 | − if (fsg_lun_is_open(curlun)) { | |
| 887 | − fsg_lun_close(curlun); | |
| 888 | − curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; | |
| 889 | − } | |
| 890 | − | |
| 891 | 881 | /* Load new medium */ |
| 882 | + down_write(filesem); | |
| 892 | 883 | if (count > 0 && buf[0]) { |
| 884 | + /* fsg_lun_open() will close existing file if any. */ | |
| 893 | 885 | rc = fsg_lun_open(curlun, buf); |
| 894 | 886 | if (rc == 0) |
| 895 | 887 | curlun->unit_attention_data = |
| 896 | 888 | SS_NOT_READY_TO_READY_TRANSITION; |
| 889 | + } else if (fsg_lun_is_open(curlun)) { | |
| 890 | + fsg_lun_close(curlun); | |
| 891 | + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; | |
| 897 | 892 | } |
| 898 | 893 | up_write(filesem); |
| 899 | 894 | return (rc < 0 ? rc : count); |
| @@ -798,12 +798,6 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], · 797 unmodified lines | ||
| 798 | 798 | |
| 799 | 799 | SET_ETHTOOL_OPS(net, &ops); |
| 800 | 800 | |
| 801 | − /* two kinds of host-initiated state changes: | |
| 802 | − * - iff DATA transfer is active, carrier is "on" | |
| 803 | − * - tx queueing enabled if open *and* carrier is "on" | |
| 804 | − */ | |
| 805 | − netif_carrier_off(net); | |
| 806 | − | |
| 807 | 801 | dev->gadget = g; |
| 808 | 802 | SET_NETDEV_DEV(net, &g->dev); |
| 809 | 803 | SET_NETDEV_DEVTYPE(net, &gadget_type); |
| @@ -817,6 +811,12 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], · 7 unmodified lines | ||
| 817 | 811 | INFO(dev, "HOST MAC %pM\n", dev->host_mac); |
| 818 | 812 | |
| 819 | 813 | the_dev = dev; |
| 814 | + | |
| 815 | + /* two kinds of host-initiated state changes: | |
| 816 | + * - iff DATA transfer is active, carrier is "on" | |
| 817 | + * - tx queueing enabled if open *and* carrier is "on" | |
| 818 | + */ | |
| 819 | + netif_carrier_off(net); | |
| 820 | 820 | } |
| 821 | 821 | |
| 822 | 822 | return status; |
| @@ -153,9 +153,11 @@ struct uvc_device · 152 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | /* Descriptors */ |
| 155 | 155 | struct { |
| 156 | − const struct uvc_descriptor_header * const *control; | |
| 156 | + const struct uvc_descriptor_header * const *fs_control; | |
| 157 | + const struct uvc_descriptor_header * const *ss_control; | |
| 157 | 158 | const struct uvc_descriptor_header * const *fs_streaming; |
| 158 | 159 | const struct uvc_descriptor_header * const *hs_streaming; |
| 160 | + const struct uvc_descriptor_header * const *ss_streaming; | |
| 159 | 161 | } desc; |
| 160 | 162 | |
| 161 | 163 | unsigned int control_intf; |
| @@ -272,7 +272,15 @@ static const struct uvc_color_matching_descriptor uvc_color_matching = { · 271 unmodified lines | ||
| 272 | 272 | .bMatrixCoefficients = 4, |
| 273 | 273 | }; |
| 274 | 274 | |
| 275 | −static const struct uvc_descriptor_header * const uvc_control_cls[] = { | |
| 275 | +static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = { | |
| 276 | + (const struct uvc_descriptor_header *) &uvc_control_header, | |
| 277 | + (const struct uvc_descriptor_header *) &uvc_camera_terminal, | |
| 278 | + (const struct uvc_descriptor_header *) &uvc_processing, | |
| 279 | + (const struct uvc_descriptor_header *) &uvc_output_terminal, | |
| 280 | + NULL, | |
| 281 | +}; | |
| 282 | + | |
| 283 | +static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { | |
| 276 | 284 | (const struct uvc_descriptor_header *) &uvc_control_header, |
| 277 | 285 | (const struct uvc_descriptor_header *) &uvc_camera_terminal, |
| 278 | 286 | (const struct uvc_descriptor_header *) &uvc_processing, |
| @@ -304,6 +312,18 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { · 25 unmodified lines | ||
| 304 | 312 | NULL, |
| 305 | 313 | }; |
| 306 | 314 | |
| 315 | +static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { | |
| 316 | + (const struct uvc_descriptor_header *) &uvc_input_header, | |
| 317 | + (const struct uvc_descriptor_header *) &uvc_format_yuv, | |
| 318 | + (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, | |
| 319 | + (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, | |
| 320 | + (const struct uvc_descriptor_header *) &uvc_format_mjpg, | |
| 321 | + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, | |
| 322 | + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, | |
| 323 | + (const struct uvc_descriptor_header *) &uvc_color_matching, | |
| 324 | + NULL, | |
| 325 | +}; | |
| 326 | + | |
| 307 | 327 | /* -------------------------------------------------------------------------- |
| 308 | 328 | * USB configuration |
| 309 | 329 | */ |
| @@ -311,8 +331,9 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { · 1 unmodified line | ||
| 311 | 331 | static int __init |
| 312 | 332 | webcam_config_bind(struct usb_configuration *c) |
| 313 | 333 | { |
| 314 | − return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, | |
| 315 | − uvc_hs_streaming_cls); | |
| 334 | + return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls, | |
| 335 | + uvc_fs_streaming_cls, uvc_hs_streaming_cls, | |
| 336 | + uvc_ss_streaming_cls); | |
| 316 | 337 | } |
| 317 | 338 | |
| 318 | 339 | static struct usb_configuration webcam_config_driver = { |
| @@ -373,7 +394,7 @@ static struct usb_composite_driver webcam_driver = { · 54 unmodified lines | ||
| 373 | 394 | .name = "g_webcam", |
| 374 | 395 | .dev = &webcam_device_descriptor, |
| 375 | 396 | .strings = webcam_device_strings, |
| 376 | − .max_speed = USB_SPEED_HIGH, | |
| 397 | + .max_speed = USB_SPEED_SUPER, | |
| 377 | 398 | .unbind = webcam_unbind, |
| 378 | 399 | }; |
| 379 | 400 | |
| @@ -652,7 +652,7 @@ config USB_HCD_BCMA · 651 unmodified lines | ||
| 652 | 652 | select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD |
| 653 | 653 | select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD |
| 654 | 654 | help |
| 655 | − Enbale support for the EHCI and OCHI host controller on an bcma bus. | |
| 655 | + Enable support for the EHCI and OCHI host controller on an bcma bus. | |
| 656 | 656 | It converts the bcma driver into two platform device drivers |
| 657 | 657 | for ehci and ohci. |
| 658 | 658 | |
| @@ -664,7 +664,7 @@ config USB_HCD_SSB · 5 unmodified lines | ||
| 664 | 664 | select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD |
| 665 | 665 | select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD |
| 666 | 666 | help |
| 667 | − Enbale support for the EHCI and OCHI host controller on an bcma bus. | |
| 667 | + Enable support for the EHCI and OCHI host controller on an bcma bus. | |
| 668 | 668 | It converts the bcma driver into two platform device drivers |
| 669 | 669 | for ehci and ohci. |
| 670 | 670 | |
| @@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev) · 52 unmodified lines | ||
| 53 | 53 | static int ehci_atmel_setup(struct usb_hcd *hcd) |
| 54 | 54 | { |
| 55 | 55 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 56 | − int retval = 0; | |
| 56 | + int retval; | |
| 57 | 57 | |
| 58 | 58 | /* registers start at offset 0x0 */ |
| 59 | 59 | ehci->caps = hcd->regs; |
| 60 | − ehci->regs = hcd->regs + | |
| 61 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 62 | − dbg_hcs_params(ehci, "reset"); | |
| 63 | − dbg_hcc_params(ehci, "reset"); | |
| 64 | − | |
| 65 | − /* cache this readonly data; minimize chip reads */ | |
| 66 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 67 | − | |
| 68 | − retval = ehci_halt(ehci); | |
| 69 | − if (retval) | |
| 70 | − return retval; | |
| 71 | 60 | |
| 72 | − /* data structure init */ | |
| 73 | − retval = ehci_init(hcd); | |
| 61 | + retval = ehci_setup(hcd); | |
| 74 | 62 | if (retval) |
| 75 | 63 | return retval; |
| 76 | 64 | |
| 77 | − ehci->sbrn = 0x20; | |
| 78 | − | |
| 79 | − ehci_reset(ehci); | |
| 80 | 65 | ehci_port_power(ehci, 0); |
| 81 | 66 | |
| 82 | 67 | return retval; |
| @@ -20,10 +20,12 @@ extern int usb_disabled(void); · 19 unmodified lines | ||
| 20 | 20 | static int au1xxx_ehci_setup(struct usb_hcd *hcd) |
| 21 | 21 | { |
| 22 | 22 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 23 | − int ret = ehci_init(hcd); | |
| 23 | + int ret; | |
| 24 | + | |
| 25 | + ehci->caps = hcd->regs; | |
| 26 | + ret = ehci_setup(hcd); | |
| 24 | 27 | |
| 25 | 28 | ehci->need_io_watchdog = 0; |
| 26 | − ehci_reset(ehci); | |
| 27 | 29 | return ret; |
| 28 | 30 | } |
| 29 | 31 | |
| @@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { · 48 unmodified lines | ||
| 78 | 80 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) |
| 79 | 81 | { |
| 80 | 82 | struct usb_hcd *hcd; |
| 81 | − struct ehci_hcd *ehci; | |
| 82 | 83 | struct resource *res; |
| 83 | 84 | int ret; |
| 84 | 85 | |
| @@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) · 31 unmodified lines | ||
| 116 | 117 | goto err3; |
| 117 | 118 | } |
| 118 | 119 | |
| 119 | − ehci = hcd_to_ehci(hcd); | |
| 120 | − ehci->caps = hcd->regs; | |
| 121 | − ehci->regs = hcd->regs + | |
| 122 | − HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); | |
| 123 | − /* cache this readonly data; minimize chip reads */ | |
| 124 | − ehci->hcs_params = readl(&ehci->caps->hcs_params); | |
| 125 | − | |
| 126 | 120 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
| 127 | 121 | IRQF_SHARED); |
| 128 | 122 | if (ret == 0) { |
| @@ -158,28 +152,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) · 29 unmodified lines | ||
| 158 | 152 | static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) |
| 159 | 153 | { |
| 160 | 154 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 161 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 162 | − unsigned long flags; | |
| 163 | − int rc = 0; | |
| 164 | − | |
| 165 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 166 | − msleep(10); | |
| 167 | − | |
| 168 | − /* Root hub was already suspended. Disable irq emission and | |
| 169 | − * mark HW unaccessible. The PM and USB cores make sure that | |
| 170 | − * the root hub is either suspended or stopped. | |
| 171 | − */ | |
| 172 | − ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); | |
| 173 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 174 | − ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 175 | − (void)ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 176 | − | |
| 177 | − clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 178 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 179 | − | |
| 180 | − // could save FLADJ in case of Vaux power loss | |
| 181 | − // ... we'd only use it to handle clock skew | |
| 155 | + bool do_wakeup = device_may_wakeup(dev); | |
| 156 | + int rc; | |
| 182 | 157 | |
| 158 | + rc = ehci_suspend(hcd, do_wakeup); | |
| 183 | 159 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); |
| 184 | 160 | |
| 185 | 161 | return rc; |
| @@ -188,56 +164,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) · 2 unmodified lines | ||
| 188 | 164 | static int ehci_hcd_au1xxx_drv_resume(struct device *dev) |
| 189 | 165 | { |
| 190 | 166 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 191 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 192 | 167 | |
| 193 | 168 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); |
| 194 | − | |
| 195 | − // maybe restore FLADJ | |
| 196 | − | |
| 197 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 198 | − msleep(100); | |
| 199 | − | |
| 200 | − /* Mark hardware accessible again as we are out of D3 state by now */ | |
| 201 | − set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 202 | − | |
| 203 | − /* If CF is still set, we maintained PCI Vaux power. | |
| 204 | − * Just undo the effect of ehci_pci_suspend(). | |
| 205 | − */ | |
| 206 | − if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | |
| 207 | − int mask = INTR_MASK; | |
| 208 | − | |
| 209 | − ehci_prepare_ports_for_controller_resume(ehci); | |
| 210 | − if (!hcd->self.root_hub->do_remote_wakeup) | |
| 211 | − mask &= ~STS_PCD; | |
| 212 | − ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 213 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 214 | − return 0; | |
| 215 | − } | |
| 216 | − | |
| 217 | − ehci_dbg(ehci, "lost power, restarting\n"); | |
| 218 | − usb_root_hub_lost_power(hcd->self.root_hub); | |
| 219 | − | |
| 220 | − /* Else reset, to cope with power loss or flush-to-storage | |
| 221 | − * style "resume" having let BIOS kick in during reboot. | |
| 222 | − */ | |
| 223 | − (void) ehci_halt(ehci); | |
| 224 | − (void) ehci_reset(ehci); | |
| 225 | − | |
| 226 | − /* emptying the schedule aborts any urbs */ | |
| 227 | − spin_lock_irq(&ehci->lock); | |
| 228 | − if (ehci->reclaim) | |
| 229 | − end_unlink_async(ehci); | |
| 230 | − ehci_work(ehci); | |
| 231 | − spin_unlock_irq(&ehci->lock); | |
| 232 | − | |
| 233 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 234 | − ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 235 | − ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 236 | − | |
| 237 | − /* here we "know" root ports should always stay powered */ | |
| 238 | − ehci_port_power(ehci, 1); | |
| 239 | − | |
| 240 | − ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 169 | + ehci_resume(hcd, false); | |
| 241 | 170 | |
| 242 | 171 | return 0; |
| 243 | 172 | } |
| @@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd) · 32 unmodified lines | ||
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | ehci->caps = hcd->regs; |
| 36 | − ehci->regs = hcd->regs | |
| 37 | − + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 38 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 39 | 36 | |
| 40 | 37 | hcd->has_tt = 0; |
| 41 | − ehci_reset(ehci); | |
| 42 | 38 | |
| 43 | − retval = ehci_init(hcd); | |
| 39 | + retval = ehci_setup(hcd); | |
| 44 | 40 | if (retval) |
| 45 | 41 | return retval; |
| 46 | 42 | |
| @@ -404,9 +404,9 @@ struct debug_buffer { · 403 unmodified lines | ||
| 404 | 404 | |
| 405 | 405 | #define speed_char(info1) ({ char tmp; \ |
| 406 | 406 | switch (info1 & (3 << 12)) { \ |
| 407 | − case 0 << 12: tmp = 'f'; break; \ | |
| 408 | − case 1 << 12: tmp = 'l'; break; \ | |
| 409 | − case 2 << 12: tmp = 'h'; break; \ | |
| 407 | + case QH_FULL_SPEED: tmp = 'f'; break; \ | |
| 408 | + case QH_LOW_SPEED: tmp = 'l'; break; \ | |
| 409 | + case QH_HIGH_SPEED: tmp = 'h'; break; \ | |
| 410 | 410 | default: tmp = '?'; break; \ |
| 411 | 411 | }; tmp; }) |
| 412 | 412 | |
| @@ -538,12 +538,13 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) · 125 unmodified lines | ||
| 538 | 538 | spin_lock_irqsave (&ehci->lock, flags); |
| 539 | 539 | for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) |
| 540 | 540 | qh_lines (ehci, qh, &next, &size); |
| 541 | − if (ehci->reclaim && size > 0) { | |
| 542 | − temp = scnprintf (next, size, "\nreclaim =\n"); | |
| 541 | + if (ehci->async_unlink && size > 0) { | |
| 542 | + temp = scnprintf(next, size, "\nunlink =\n"); | |
| 543 | 543 | size -= temp; |
| 544 | 544 | next += temp; |
| 545 | 545 | |
| 546 | − for (qh = ehci->reclaim; size > 0 && qh; qh = qh->reclaim) | |
| 546 | + for (qh = ehci->async_unlink; size > 0 && qh; | |
| 547 | + qh = qh->unlink_next) | |
| 547 | 548 | qh_lines (ehci, qh, &next, &size); |
| 548 | 549 | } |
| 549 | 550 | spin_unlock_irqrestore (&ehci->lock, flags); |
| @@ -705,6 +706,8 @@ static const char *rh_state_string(struct ehci_hcd *ehci) · 155 unmodified lines | ||
| 705 | 706 | return "suspended"; |
| 706 | 707 | case EHCI_RH_RUNNING: |
| 707 | 708 | return "running"; |
| 709 | + case EHCI_RH_STOPPING: | |
| 710 | + return "stopping"; | |
| 708 | 711 | } |
| 709 | 712 | return "?"; |
| 710 | 713 | } |
| @@ -841,16 +844,17 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) · 130 unmodified lines | ||
| 841 | 844 | } |
| 842 | 845 | } |
| 843 | 846 | |
| 844 | − if (ehci->reclaim) { | |
| 845 | − temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim); | |
| 847 | + if (ehci->async_unlink) { | |
| 848 | + temp = scnprintf(next, size, "async unlink qh %p\n", | |
| 849 | + ehci->async_unlink); | |
| 846 | 850 | size -= temp; |
| 847 | 851 | next += temp; |
| 848 | 852 | } |
| 849 | 853 | |
| 850 | 854 | #ifdef EHCI_STATS |
| 851 | 855 | temp = scnprintf (next, size, |
| 852 | − "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | |
| 853 | − ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | |
| 856 | + "irq normal %ld err %ld iaa %ld (lost %ld)\n", | |
| 857 | + ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, | |
| 854 | 858 | ehci->stats.lost_iaa); |
| 855 | 859 | size -= temp; |
| 856 | 860 | next += temp; |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/types.h> |
| 28 | 28 | #include <linux/delay.h> |
| 29 | 29 | #include <linux/pm.h> |
| 30 | +#include <linux/err.h> | |
| 30 | 31 | #include <linux/platform_device.h> |
| 31 | 32 | #include <linux/fsl_devices.h> |
| 32 | 33 | |
| @@ -142,19 +143,19 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, · 109 unmodified lines | ||
| 142 | 143 | if (pdata->operating_mode == FSL_USB2_DR_OTG) { |
| 143 | 144 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 144 | 145 | |
| 145 | − ehci->transceiver = usb_get_transceiver(); | |
| 146 | − dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n", | |
| 147 | − hcd, ehci, ehci->transceiver); | |
| 146 | + hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 147 | + dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n", | |
| 148 | + hcd, ehci, hcd->phy); | |
| 148 | 149 | |
| 149 | − if (ehci->transceiver) { | |
| 150 | − retval = otg_set_host(ehci->transceiver->otg, | |
| 150 | + if (!IS_ERR_OR_NULL(hcd->phy)) { | |
| 151 | + retval = otg_set_host(hcd->phy->otg, | |
| 151 | 152 | &ehci_to_hcd(ehci)->self); |
| 152 | 153 | if (retval) { |
| 153 | − usb_put_transceiver(ehci->transceiver); | |
| 154 | + usb_put_phy(hcd->phy); | |
| 154 | 155 | goto err4; |
| 155 | 156 | } |
| 156 | 157 | } else { |
| 157 | − dev_err(&pdev->dev, "can't find transceiver\n"); | |
| 158 | + dev_err(&pdev->dev, "can't find phy\n"); | |
| 158 | 159 | retval = -ENODEV; |
| 159 | 160 | goto err4; |
| 160 | 161 | } |
| @@ -190,11 +191,10 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, · 29 unmodified lines | ||
| 190 | 191 | struct platform_device *pdev) |
| 191 | 192 | { |
| 192 | 193 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 193 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 194 | 194 | |
| 195 | − if (ehci->transceiver) { | |
| 196 | − otg_set_host(ehci->transceiver->otg, NULL); | |
| 197 | − usb_put_transceiver(ehci->transceiver); | |
| 195 | + if (!IS_ERR_OR_NULL(hcd->phy)) { | |
| 196 | + otg_set_host(hcd->phy->otg, NULL); | |
| 197 | + usb_put_phy(hcd->phy); | |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | usb_remove_hcd(hcd); |
| @@ -313,7 +313,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) · 112 unmodified lines | ||
| 313 | 313 | } |
| 314 | 314 | |
| 315 | 315 | if (pdata->have_sysif_regs) { |
| 316 | −#ifdef CONFIG_PPC_85xx | |
| 316 | +#ifdef CONFIG_FSL_SOC_BOOKE | |
| 317 | 317 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); |
| 318 | 318 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); |
| 319 | 319 | #else |
| @@ -348,29 +348,13 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) · 28 unmodified lines | ||
| 348 | 348 | |
| 349 | 349 | /* EHCI registers start at offset 0x100 */ |
| 350 | 350 | ehci->caps = hcd->regs + 0x100; |
| 351 | − ehci->regs = hcd->regs + 0x100 + | |
| 352 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 353 | − dbg_hcs_params(ehci, "reset"); | |
| 354 | − dbg_hcc_params(ehci, "reset"); | |
| 355 | − | |
| 356 | − /* cache this readonly data; minimize chip reads */ | |
| 357 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 358 | 351 | |
| 359 | 352 | hcd->has_tt = 1; |
| 360 | 353 | |
| 361 | − retval = ehci_halt(ehci); | |
| 362 | − if (retval) | |
| 363 | − return retval; | |
| 364 | − | |
| 365 | − /* data structure init */ | |
| 366 | − retval = ehci_init(hcd); | |
| 354 | + retval = ehci_setup(hcd); | |
| 367 | 355 | if (retval) |
| 368 | 356 | return retval; |
| 369 | 357 | |
| 370 | − ehci->sbrn = 0x20; | |
| 371 | − | |
| 372 | − ehci_reset(ehci); | |
| 373 | − | |
| 374 | 358 | if (of_device_is_compatible(dev->parent->of_node, |
| 375 | 359 | "fsl,mpc5121-usb2-dr")) { |
| 376 | 360 | /* |
| @@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd) · 39 unmodified lines | ||
| 40 | 40 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 41 | 41 | int retval; |
| 42 | 42 | |
| 43 | − retval = ehci_halt(ehci); | |
| 43 | + retval = ehci_setup(hcd); | |
| 44 | 44 | if (retval) |
| 45 | 45 | return retval; |
| 46 | 46 | |
| 47 | − retval = ehci_init(hcd); | |
| 48 | − if (retval) | |
| 49 | − return retval; | |
| 50 | − | |
| 51 | − ehci->sbrn = 0x20; | |
| 52 | 47 | ehci_port_power(ehci, 1); |
| 53 | 48 | |
| 54 | − return ehci_reset(ehci); | |
| 49 | + return retval; | |
| 55 | 50 | } |
| 56 | 51 | |
| 57 | 52 | |
| @@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) · 106 unmodified lines | ||
| 164 | 159 | ehci->big_endian_capbase = 1; |
| 165 | 160 | } |
| 166 | 161 | |
| 167 | − ehci->regs = hcd->regs + | |
| 168 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 169 | − | |
| 170 | − /* cache this readonly data; minimize chip reads */ | |
| 171 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 172 | − | |
| 173 | 162 | rv = usb_add_hcd(hcd, irq, 0); |
| 174 | 163 | if (rv) |
| 175 | 164 | goto err_ehci; |
| @@ -30,8 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/vmalloc.h> |
| 31 | 31 | #include <linux/errno.h> |
| 32 | 32 | #include <linux/init.h> |
| 33 | −#include <linux/timer.h> | |
| 34 | −#include <linux/ktime.h> | |
| 33 | +#include <linux/hrtimer.h> | |
| 35 | 34 | #include <linux/list.h> |
| 36 | 35 | #include <linux/interrupt.h> |
| 37 | 36 | #include <linux/usb.h> |
| @@ -94,12 +93,6 @@ static const char hcd_name [] = "ehci_hcd"; · 56 unmodified lines | ||
| 94 | 93 | */ |
| 95 | 94 | #define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */ |
| 96 | 95 | |
| 97 | −#define EHCI_IAA_MSECS 10 /* arbitrary */ | |
| 98 | −#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | |
| 99 | −#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | |
| 100 | −#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1) | |
| 101 | − /* 5-ms async qh unlink delay */ | |
| 102 | − | |
| 103 | 96 | /* Initial IRQ latency: faster than hw default */ |
| 104 | 97 | static int log2_irq_thresh = 0; // 0 to 6 |
| 105 | 98 | module_param (log2_irq_thresh, int, S_IRUGO); |
| @@ -130,41 +123,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); · 24 unmodified lines | ||
| 130 | 123 | |
| 131 | 124 | /*-------------------------------------------------------------------------*/ |
| 132 | 125 | |
| 133 | −static void | |
| 134 | −timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) | |
| 135 | −{ | |
| 136 | − /* Don't override timeouts which shrink or (later) disable | |
| 137 | − * the async ring; just the I/O watchdog. Note that if a | |
| 138 | − * SHRINK were pending, OFF would never be requested. | |
| 139 | − */ | |
| 140 | − if (timer_pending(&ehci->watchdog) | |
| 141 | − && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) | |
| 142 | − & ehci->actions)) | |
| 143 | − return; | |
| 144 | − | |
| 145 | − if (!test_and_set_bit(action, &ehci->actions)) { | |
| 146 | − unsigned long t; | |
| 147 | − | |
| 148 | − switch (action) { | |
| 149 | − case TIMER_IO_WATCHDOG: | |
| 150 | − if (!ehci->need_io_watchdog) | |
| 151 | − return; | |
| 152 | − t = EHCI_IO_JIFFIES; | |
| 153 | − break; | |
| 154 | − case TIMER_ASYNC_OFF: | |
| 155 | − t = EHCI_ASYNC_JIFFIES; | |
| 156 | − break; | |
| 157 | − /* case TIMER_ASYNC_SHRINK: */ | |
| 158 | − default: | |
| 159 | − t = EHCI_SHRINK_JIFFIES; | |
| 160 | − break; | |
| 161 | − } | |
| 162 | − mod_timer(&ehci->watchdog, t + jiffies); | |
| 163 | − } | |
| 164 | −} | |
| 165 | − | |
| 166 | −/*-------------------------------------------------------------------------*/ | |
| 167 | − | |
| 168 | 126 | /* |
| 169 | 127 | * handshake - spin reading hc until handshake completes or fails |
| 170 | 128 | * @ptr: address of hc register to be read |
| @@ -203,29 +161,30 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, · 32 unmodified lines | ||
| 203 | 161 | /* check TDI/ARC silicon is in host mode */ |
| 204 | 162 | static int tdi_in_host_mode (struct ehci_hcd *ehci) |
| 205 | 163 | { |
| 206 | − u32 __iomem *reg_ptr; | |
| 207 | 164 | u32 tmp; |
| 208 | 165 | |
| 209 | − reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); | |
| 210 | − tmp = ehci_readl(ehci, reg_ptr); | |
| 166 | + tmp = ehci_readl(ehci, &ehci->regs->usbmode); | |
| 211 | 167 | return (tmp & 3) == USBMODE_CM_HC; |
| 212 | 168 | } |
| 213 | 169 | |
| 214 | −/* force HC to halt state from unknown (EHCI spec section 2.3) */ | |
| 170 | +/* | |
| 171 | + * Force HC to halt state from unknown (EHCI spec section 2.3). | |
| 172 | + * Must be called with interrupts enabled and the lock not held. | |
| 173 | + */ | |
| 215 | 174 | static int ehci_halt (struct ehci_hcd *ehci) |
| 216 | 175 | { |
| 217 | − u32 temp = ehci_readl(ehci, &ehci->regs->status); | |
| 176 | + u32 temp; | |
| 177 | + | |
| 178 | + spin_lock_irq(&ehci->lock); | |
| 218 | 179 | |
| 219 | 180 | /* disable any irqs left enabled by previous code */ |
| 220 | 181 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
| 221 | 182 | |
| 222 | − if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) { | |
| 183 | + if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) { | |
| 184 | + spin_unlock_irq(&ehci->lock); | |
| 223 | 185 | return 0; |
| 224 | 186 | } |
| 225 | 187 | |
| 226 | − if ((temp & STS_HALT) != 0) | |
| 227 | − return 0; | |
| 228 | − | |
| 229 | 188 | /* |
| 230 | 189 | * This routine gets called during probe before ehci->command |
| 231 | 190 | * has been initialized, so we can't rely on its value. |
| @@ -234,80 +193,20 @@ static int ehci_halt (struct ehci_hcd *ehci) · 2 unmodified lines | ||
| 234 | 193 | temp = ehci_readl(ehci, &ehci->regs->command); |
| 235 | 194 | temp &= ~(CMD_RUN | CMD_IAAD); |
| 236 | 195 | ehci_writel(ehci, temp, &ehci->regs->command); |
| 237 | − return handshake (ehci, &ehci->regs->status, | |
| 238 | − STS_HALT, STS_HALT, 16 * 125); | |
| 239 | −} | |
| 240 | − | |
| 241 | −#if defined(CONFIG_USB_SUSPEND) && defined(CONFIG_PPC_PS3) | |
| 242 | − | |
| 243 | −/* | |
| 244 | − * The EHCI controller of the Cell Super Companion Chip used in the | |
| 245 | − * PS3 will stop the root hub after all root hub ports are suspended. | |
| 246 | − * When in this condition handshake will return -ETIMEDOUT. The | |
| 247 | − * STS_HLT bit will not be set, so inspection of the frame index is | |
| 248 | − * used here to test for the condition. If the condition is found | |
| 249 | − * return success to allow the USB suspend to complete. | |
| 250 | − */ | |
| 251 | − | |
| 252 | −static int handshake_for_broken_root_hub(struct ehci_hcd *ehci, | |
| 253 | − void __iomem *ptr, u32 mask, u32 done, | |
| 254 | − int usec) | |
| 255 | −{ | |
| 256 | − unsigned int old_index; | |
| 257 | − int error; | |
| 258 | − | |
| 259 | − if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | |
| 260 | − return -ETIMEDOUT; | |
| 261 | − | |
| 262 | − old_index = ehci_read_frame_index(ehci); | |
| 263 | − | |
| 264 | − error = handshake(ehci, ptr, mask, done, usec); | |
| 265 | − | |
| 266 | − if (error == -ETIMEDOUT && ehci_read_frame_index(ehci) == old_index) | |
| 267 | − return 0; | |
| 268 | − | |
| 269 | − return error; | |
| 270 | −} | |
| 271 | − | |
| 272 | −#else | |
| 273 | − | |
| 274 | −static int handshake_for_broken_root_hub(struct ehci_hcd *ehci, | |
| 275 | − void __iomem *ptr, u32 mask, u32 done, | |
| 276 | − int usec) | |
| 277 | −{ | |
| 278 | − return -ETIMEDOUT; | |
| 279 | −} | |
| 280 | − | |
| 281 | −#endif | |
| 282 | 196 | |
| 283 | −static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, | |
| 284 | − u32 mask, u32 done, int usec) | |
| 285 | −{ | |
| 286 | − int error; | |
| 287 | − | |
| 288 | − error = handshake(ehci, ptr, mask, done, usec); | |
| 289 | − if (error == -ETIMEDOUT) | |
| 290 | − error = handshake_for_broken_root_hub(ehci, ptr, mask, done, | |
| 291 | − usec); | |
| 292 | − | |
| 293 | − if (error) { | |
| 294 | − ehci_halt(ehci); | |
| 295 | − ehci->rh_state = EHCI_RH_HALTED; | |
| 296 | − ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n", | |
| 297 | − ptr, mask, done, error); | |
| 298 | − } | |
| 197 | + spin_unlock_irq(&ehci->lock); | |
| 198 | + synchronize_irq(ehci_to_hcd(ehci)->irq); | |
| 299 | 199 | |
| 300 | − return error; | |
| 200 | + return handshake(ehci, &ehci->regs->status, | |
| 201 | + STS_HALT, STS_HALT, 16 * 125); | |
| 301 | 202 | } |
| 302 | 203 | |
| 303 | 204 | /* put TDI/ARC silicon into EHCI mode */ |
| 304 | 205 | static void tdi_reset (struct ehci_hcd *ehci) |
| 305 | 206 | { |
| 306 | − u32 __iomem *reg_ptr; | |
| 307 | 207 | u32 tmp; |
| 308 | 208 | |
| 309 | − reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); | |
| 310 | − tmp = ehci_readl(ehci, reg_ptr); | |
| 209 | + tmp = ehci_readl(ehci, &ehci->regs->usbmode); | |
| 311 | 210 | tmp |= USBMODE_CM_HC; |
| 312 | 211 | /* The default byte access to MMR space is LE after |
| 313 | 212 | * controller reset. Set the required endian mode |
| @@ -315,10 +214,13 @@ static void tdi_reset (struct ehci_hcd *ehci) · 1 unmodified line | ||
| 315 | 214 | */ |
| 316 | 215 | if (ehci_big_endian_mmio(ehci)) |
| 317 | 216 | tmp |= USBMODE_BE; |
| 318 | − ehci_writel(ehci, tmp, reg_ptr); | |
| 217 | + ehci_writel(ehci, tmp, &ehci->regs->usbmode); | |
| 319 | 218 | } |
| 320 | 219 | |
| 321 | −/* reset a non-running (STS_HALT == 1) controller */ | |
| 220 | +/* | |
| 221 | + * Reset a non-running (STS_HALT == 1) controller. | |
| 222 | + * Must be called with interrupts enabled and the lock not held. | |
| 223 | + */ | |
| 322 | 224 | static int ehci_reset (struct ehci_hcd *ehci) |
| 323 | 225 | { |
| 324 | 226 | int retval; |
| @@ -339,9 +241,8 @@ static int ehci_reset (struct ehci_hcd *ehci) · 14 unmodified lines | ||
| 339 | 241 | |
| 340 | 242 | if (ehci->has_hostpc) { |
| 341 | 243 | ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, |
| 342 | − (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX)); | |
| 343 | − ehci_writel(ehci, TXFIFO_DEFAULT, | |
| 344 | − (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING)); | |
| 244 | + &ehci->regs->usbmode_ex); | |
| 245 | + ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning); | |
| 345 | 246 | } |
| 346 | 247 | if (retval) |
| 347 | 248 | return retval; |
| @@ -357,36 +258,40 @@ static int ehci_reset (struct ehci_hcd *ehci) · 9 unmodified lines | ||
| 357 | 258 | return retval; |
| 358 | 259 | } |
| 359 | 260 | |
| 360 | −/* idle the controller (from running) */ | |
| 261 | +/* | |
| 262 | + * Idle the controller (turn off the schedules). | |
| 263 | + * Must be called with interrupts enabled and the lock not held. | |
| 264 | + */ | |
| 361 | 265 | static void ehci_quiesce (struct ehci_hcd *ehci) |
| 362 | 266 | { |
| 363 | 267 | u32 temp; |
| 364 | 268 | |
| 365 | −#ifdef DEBUG | |
| 366 | 269 | if (ehci->rh_state != EHCI_RH_RUNNING) |
| 367 | − BUG (); | |
| 368 | −#endif | |
| 270 | + return; | |
| 369 | 271 | |
| 370 | 272 | /* wait for any schedule enables/disables to take effect */ |
| 371 | 273 | temp = (ehci->command << 10) & (STS_ASS | STS_PSS); |
| 372 | − if (handshake_on_error_set_halt(ehci, &ehci->regs->status, | |
| 373 | − STS_ASS | STS_PSS, temp, 16 * 125)) | |
| 374 | − return; | |
| 274 | + handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); | |
| 375 | 275 | |
| 376 | 276 | /* then disable anything that's still active */ |
| 277 | + spin_lock_irq(&ehci->lock); | |
| 377 | 278 | ehci->command &= ~(CMD_ASE | CMD_PSE); |
| 378 | 279 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
| 280 | + spin_unlock_irq(&ehci->lock); | |
| 379 | 281 | |
| 380 | 282 | /* hardware can take 16 microframes to turn off ... */ |
| 381 | − handshake_on_error_set_halt(ehci, &ehci->regs->status, | |
| 382 | − STS_ASS | STS_PSS, 0, 16 * 125); | |
| 283 | + handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); | |
| 383 | 284 | } |
| 384 | 285 | |
| 385 | 286 | /*-------------------------------------------------------------------------*/ |
| 386 | 287 | |
| 387 | 288 | static void end_unlink_async(struct ehci_hcd *ehci); |
| 289 | +static void unlink_empty_async(struct ehci_hcd *ehci); | |
| 388 | 290 | static void ehci_work(struct ehci_hcd *ehci); |
| 291 | +static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); | |
| 292 | +static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); | |
| 389 | 293 | |
| 294 | +#include "ehci-timer.c" | |
| 390 | 295 | #include "ehci-hub.c" |
| 391 | 296 | #include "ehci-lpm.c" |
| 392 | 297 | #include "ehci-mem.c" |
| @@ -396,68 +301,6 @@ static void ehci_work(struct ehci_hcd *ehci); · 3 unmodified lines | ||
| 396 | 301 | |
| 397 | 302 | /*-------------------------------------------------------------------------*/ |
| 398 | 303 | |
| 399 | −static void ehci_iaa_watchdog(unsigned long param) | |
| 400 | −{ | |
| 401 | − struct ehci_hcd *ehci = (struct ehci_hcd *) param; | |
| 402 | − unsigned long flags; | |
| 403 | − | |
| 404 | − spin_lock_irqsave (&ehci->lock, flags); | |
| 405 | − | |
| 406 | − /* Lost IAA irqs wedge things badly; seen first with a vt8235. | |
| 407 | − * So we need this watchdog, but must protect it against both | |
| 408 | − * (a) SMP races against real IAA firing and retriggering, and | |
| 409 | − * (b) clean HC shutdown, when IAA watchdog was pending. | |
| 410 | − */ | |
| 411 | − if (ehci->reclaim | |
| 412 | − && !timer_pending(&ehci->iaa_watchdog) | |
| 413 | − && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 414 | − u32 cmd, status; | |
| 415 | − | |
| 416 | − /* If we get here, IAA is *REALLY* late. It's barely | |
| 417 | − * conceivable that the system is so busy that CMD_IAAD | |
| 418 | − * is still legitimately set, so let's be sure it's | |
| 419 | − * clear before we read STS_IAA. (The HC should clear | |
| 420 | − * CMD_IAAD when it sets STS_IAA.) | |
| 421 | − */ | |
| 422 | − cmd = ehci_readl(ehci, &ehci->regs->command); | |
| 423 | − | |
| 424 | − /* If IAA is set here it either legitimately triggered | |
| 425 | − * before we cleared IAAD above (but _way_ late, so we'll | |
| 426 | − * still count it as lost) ... or a silicon erratum: | |
| 427 | − * - VIA seems to set IAA without triggering the IRQ; | |
| 428 | − * - IAAD potentially cleared without setting IAA. | |
| 429 | − */ | |
| 430 | − status = ehci_readl(ehci, &ehci->regs->status); | |
| 431 | − if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { | |
| 432 | − COUNT (ehci->stats.lost_iaa); | |
| 433 | − ehci_writel(ehci, STS_IAA, &ehci->regs->status); | |
| 434 | − } | |
| 435 | − | |
| 436 | − ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", | |
| 437 | − status, cmd); | |
| 438 | − end_unlink_async(ehci); | |
| 439 | − } | |
| 440 | − | |
| 441 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 442 | −} | |
| 443 | − | |
| 444 | −static void ehci_watchdog(unsigned long param) | |
| 445 | −{ | |
| 446 | − struct ehci_hcd *ehci = (struct ehci_hcd *) param; | |
| 447 | − unsigned long flags; | |
| 448 | − | |
| 449 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 450 | − | |
| 451 | − /* stop async processing after it's idled a bit */ | |
| 452 | − if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) | |
| 453 | − start_unlink_async (ehci, ehci->async); | |
| 454 | − | |
| 455 | − /* ehci could run by timer, without IRQs ... */ | |
| 456 | − ehci_work (ehci); | |
| 457 | − | |
| 458 | − spin_unlock_irqrestore (&ehci->lock, flags); | |
| 459 | −} | |
| 460 | − | |
| 461 | 304 | /* On some systems, leaving remote wakeup enabled prevents system shutdown. |
| 462 | 305 | * The firmware seems to think that powering off is a wakeup event! |
| 463 | 306 | * This routine turns off remote wakeup and everything else, on all ports. |
| @@ -473,11 +316,14 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) · 9 unmodified lines | ||
| 473 | 316 | |
| 474 | 317 | /* |
| 475 | 318 | * Halt HC, turn off all ports, and let the BIOS use the companion controllers. |
| 476 | − * Should be called with ehci->lock held. | |
| 319 | + * Must be called with interrupts enabled and the lock not held. | |
| 477 | 320 | */ |
| 478 | 321 | static void ehci_silence_controller(struct ehci_hcd *ehci) |
| 479 | 322 | { |
| 480 | 323 | ehci_halt(ehci); |
| 324 | + | |
| 325 | + spin_lock_irq(&ehci->lock); | |
| 326 | + ehci->rh_state = EHCI_RH_HALTED; | |
| 481 | 327 | ehci_turn_off_all_ports(ehci); |
| 482 | 328 | |
| 483 | 329 | /* make BIOS/etc use companion controller during reboot */ |
| @@ -485,6 +331,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci) · 1 unmodified line | ||
| 485 | 331 | |
| 486 | 332 | /* unblock posted writes */ |
| 487 | 333 | ehci_readl(ehci, &ehci->regs->configured_flag); |
| 334 | + spin_unlock_irq(&ehci->lock); | |
| 488 | 335 | } |
| 489 | 336 | |
| 490 | 337 | /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). |
| @@ -495,12 +342,15 @@ static void ehci_shutdown(struct usb_hcd *hcd) · 4 unmodified lines | ||
| 495 | 342 | { |
| 496 | 343 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 497 | 344 | |
| 498 | − del_timer_sync(&ehci->watchdog); | |
| 499 | − del_timer_sync(&ehci->iaa_watchdog); | |
| 500 | − | |
| 501 | 345 | spin_lock_irq(&ehci->lock); |
| 502 | − ehci_silence_controller(ehci); | |
| 346 | + ehci->shutdown = true; | |
| 347 | + ehci->rh_state = EHCI_RH_STOPPING; | |
| 348 | + ehci->enabled_hrtimer_events = 0; | |
| 503 | 349 | spin_unlock_irq(&ehci->lock); |
| 350 | + | |
| 351 | + ehci_silence_controller(ehci); | |
| 352 | + | |
| 353 | + hrtimer_cancel(&ehci->hrtimer); | |
| 504 | 354 | } |
| 505 | 355 | |
| 506 | 356 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) |
| @@ -529,28 +379,33 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) · 22 unmodified lines | ||
| 529 | 379 | */ |
| 530 | 380 | static void ehci_work (struct ehci_hcd *ehci) |
| 531 | 381 | { |
| 532 | − timer_action_done (ehci, TIMER_IO_WATCHDOG); | |
| 533 | − | |
| 534 | 382 | /* another CPU may drop ehci->lock during a schedule scan while |
| 535 | 383 | * it reports urb completions. this flag guards against bogus |
| 536 | 384 | * attempts at re-entrant schedule scanning. |
| 537 | 385 | */ |
| 538 | − if (ehci->scanning) | |
| 386 | + if (ehci->scanning) { | |
| 387 | + ehci->need_rescan = true; | |
| 539 | 388 | return; |
| 540 | − ehci->scanning = 1; | |
| 541 | − scan_async (ehci); | |
| 542 | − if (ehci->next_uframe != -1) | |
| 543 | − scan_periodic (ehci); | |
| 544 | − ehci->scanning = 0; | |
| 389 | + } | |
| 390 | + ehci->scanning = true; | |
| 391 | + | |
| 392 | + rescan: | |
| 393 | + ehci->need_rescan = false; | |
| 394 | + if (ehci->async_count) | |
| 395 | + scan_async(ehci); | |
| 396 | + if (ehci->intr_count > 0) | |
| 397 | + scan_intr(ehci); | |
| 398 | + if (ehci->isoc_count > 0) | |
| 399 | + scan_isoc(ehci); | |
| 400 | + if (ehci->need_rescan) | |
| 401 | + goto rescan; | |
| 402 | + ehci->scanning = false; | |
| 545 | 403 | |
| 546 | 404 | /* the IO watchdog guards against hardware or driver bugs that |
| 547 | 405 | * misplace IRQs, and should let us run completely without IRQs. |
| 548 | 406 | * such lossage has been observed on both VT6202 and VT8235. |
| 549 | 407 | */ |
| 550 | − if (ehci->rh_state == EHCI_RH_RUNNING && | |
| 551 | − (ehci->async->qh_next.ptr != NULL || | |
| 552 | − ehci->periodic_sched != 0)) | |
| 553 | − timer_action (ehci, TIMER_IO_WATCHDOG); | |
| 408 | + turn_on_io_watchdog(ehci); | |
| 554 | 409 | } |
| 555 | 410 | |
| 556 | 411 | /* |
| @@ -563,24 +418,22 @@ static void ehci_stop (struct usb_hcd *hcd) · 6 unmodified lines | ||
| 563 | 418 | ehci_dbg (ehci, "stop\n"); |
| 564 | 419 | |
| 565 | 420 | /* no more interrupts ... */ |
| 566 | − del_timer_sync (&ehci->watchdog); | |
| 567 | − del_timer_sync(&ehci->iaa_watchdog); | |
| 568 | 421 | |
| 569 | 422 | spin_lock_irq(&ehci->lock); |
| 570 | − if (ehci->rh_state == EHCI_RH_RUNNING) | |
| 571 | − ehci_quiesce (ehci); | |
| 423 | + ehci->enabled_hrtimer_events = 0; | |
| 424 | + spin_unlock_irq(&ehci->lock); | |
| 572 | 425 | |
| 426 | + ehci_quiesce(ehci); | |
| 573 | 427 | ehci_silence_controller(ehci); |
| 574 | 428 | ehci_reset (ehci); |
| 575 | − spin_unlock_irq(&ehci->lock); | |
| 576 | 429 | |
| 430 | + hrtimer_cancel(&ehci->hrtimer); | |
| 577 | 431 | remove_sysfs_files(ehci); |
| 578 | 432 | remove_debug_files (ehci); |
| 579 | 433 | |
| 580 | 434 | /* root hub is shut down separately (first, when possible) */ |
| 581 | 435 | spin_lock_irq (&ehci->lock); |
| 582 | − if (ehci->async) | |
| 583 | − ehci_work (ehci); | |
| 436 | + end_free_itds(ehci); | |
| 584 | 437 | spin_unlock_irq (&ehci->lock); |
| 585 | 438 | ehci_mem_cleanup (ehci); |
| 586 | 439 | |
| @@ -588,8 +441,8 @@ static void ehci_stop (struct usb_hcd *hcd) · 1 unmodified line | ||
| 588 | 441 | usb_amd_dev_put(); |
| 589 | 442 | |
| 590 | 443 | #ifdef EHCI_STATS |
| 591 | − ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | |
| 592 | − ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | |
| 444 | + ehci_dbg(ehci, "irq normal %ld err %ld iaa %ld (lost %ld)\n", | |
| 445 | + ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, | |
| 593 | 446 | ehci->stats.lost_iaa); |
| 594 | 447 | ehci_dbg (ehci, "complete %ld unlink %ld\n", |
| 595 | 448 | ehci->stats.complete, ehci->stats.unlink); |
| @@ -614,13 +467,10 @@ static int ehci_init(struct usb_hcd *hcd) · 18 unmodified lines | ||
| 614 | 467 | * keep io watchdog by default, those good HCDs could turn off it later |
| 615 | 468 | */ |
| 616 | 469 | ehci->need_io_watchdog = 1; |
| 617 | − init_timer(&ehci->watchdog); | |
| 618 | − ehci->watchdog.function = ehci_watchdog; | |
| 619 | − ehci->watchdog.data = (unsigned long) ehci; | |
| 620 | 470 | |
| 621 | − init_timer(&ehci->iaa_watchdog); | |
| 622 | − ehci->iaa_watchdog.function = ehci_iaa_watchdog; | |
| 623 | − ehci->iaa_watchdog.data = (unsigned long) ehci; | |
| 471 | + hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | |
| 472 | + ehci->hrtimer.function = ehci_hrtimer_func; | |
| 473 | + ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; | |
| 624 | 474 | |
| 625 | 475 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
| 626 | 476 | |
| @@ -635,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd) · 8 unmodified lines | ||
| 635 | 485 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
| 636 | 486 | */ |
| 637 | 487 | ehci->periodic_size = DEFAULT_I_TDPS; |
| 488 | + INIT_LIST_HEAD(&ehci->intr_qh_list); | |
| 638 | 489 | INIT_LIST_HEAD(&ehci->cached_itd_list); |
| 639 | 490 | INIT_LIST_HEAD(&ehci->cached_sitd_list); |
| 640 | 491 | |
| @@ -656,10 +507,6 @@ static int ehci_init(struct usb_hcd *hcd) · 15 unmodified lines | ||
| 656 | 507 | else // N microframes cached |
| 657 | 508 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
| 658 | 509 | |
| 659 | − ehci->reclaim = NULL; | |
| 660 | − ehci->next_uframe = -1; | |
| 661 | − ehci->clock_frame = -1; | |
| 662 | − | |
| 663 | 510 | /* |
| 664 | 511 | * dedicate a qh for the async ring head, since we couldn't unlink |
| 665 | 512 | * a 'real' qh without stopping the async schedule [4.8]. use it |
| @@ -672,7 +519,7 @@ static int ehci_init(struct usb_hcd *hcd) · 6 unmodified lines | ||
| 672 | 519 | hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); |
| 673 | 520 | hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); |
| 674 | 521 | #if defined(CONFIG_PPC_PS3) |
| 675 | − hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7)); /* I = 1 */ | |
| 522 | + hw->hw_info1 |= cpu_to_hc32(ehci, QH_INACTIVATE); | |
| 676 | 523 | #endif |
| 677 | 524 | hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); |
| 678 | 525 | hw->hw_qtd_next = EHCI_LIST_END(ehci); |
| @@ -813,7 +660,7 @@ static int ehci_run (struct usb_hcd *hcd) · 134 unmodified lines | ||
| 813 | 660 | return 0; |
| 814 | 661 | } |
| 815 | 662 | |
| 816 | −static int __maybe_unused ehci_setup (struct usb_hcd *hcd) | |
| 663 | +static int ehci_setup(struct usb_hcd *hcd) | |
| 817 | 664 | { |
| 818 | 665 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 819 | 666 | int retval; |
| @@ -828,15 +675,18 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd) · 8 unmodified lines | ||
| 828 | 675 | |
| 829 | 676 | ehci->sbrn = HCD_USB2; |
| 830 | 677 | |
| 831 | − retval = ehci_halt(ehci); | |
| 678 | + /* data structure init */ | |
| 679 | + retval = ehci_init(hcd); | |
| 832 | 680 | if (retval) |
| 833 | 681 | return retval; |
| 834 | 682 | |
| 835 | − /* data structure init */ | |
| 836 | − retval = ehci_init(hcd); | |
| 683 | + retval = ehci_halt(ehci); | |
| 837 | 684 | if (retval) |
| 838 | 685 | return retval; |
| 839 | 686 | |
| 687 | + if (ehci_is_TDI(ehci)) | |
| 688 | + tdi_reset(ehci); | |
| 689 | + | |
| 840 | 690 | ehci_reset(ehci); |
| 841 | 691 | |
| 842 | 692 | return 0; |
| @@ -895,14 +745,28 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) · 52 unmodified lines | ||
| 895 | 745 | |
| 896 | 746 | /* complete the unlinking of some qh [4.15.2.3] */ |
| 897 | 747 | if (status & STS_IAA) { |
| 748 | + | |
| 749 | + /* Turn off the IAA watchdog */ | |
| 750 | + ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_IAA_WATCHDOG); | |
| 751 | + | |
| 752 | + /* | |
| 753 | + * Mild optimization: Allow another IAAD to reset the | |
| 754 | + * hrtimer, if one occurs before the next expiration. | |
| 755 | + * In theory we could always cancel the hrtimer, but | |
| 756 | + * tests show that about half the time it will be reset | |
| 757 | + * for some other event anyway. | |
| 758 | + */ | |
| 759 | + if (ehci->next_hrtimer_event == EHCI_HRTIMER_IAA_WATCHDOG) | |
| 760 | + ++ehci->next_hrtimer_event; | |
| 761 | + | |
| 898 | 762 | /* guard against (alleged) silicon errata */ |
| 899 | 763 | if (cmd & CMD_IAAD) |
| 900 | 764 | ehci_dbg(ehci, "IAA with IAAD still set?\n"); |
| 901 | − if (ehci->reclaim) { | |
| 902 | − COUNT(ehci->stats.reclaim); | |
| 765 | + if (ehci->async_iaa) { | |
| 766 | + COUNT(ehci->stats.iaa); | |
| 903 | 767 | end_unlink_async(ehci); |
| 904 | 768 | } else |
| 905 | − ehci_dbg(ehci, "IAA with nothing to reclaim?\n"); | |
| 769 | + ehci_dbg(ehci, "IAA with nothing unlinked?\n"); | |
| 906 | 770 | } |
| 907 | 771 | |
| 908 | 772 | /* remote wakeup [4.3.1] */ |
| @@ -956,15 +820,19 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) · 47 unmodified lines | ||
| 956 | 820 | ehci_err(ehci, "fatal error\n"); |
| 957 | 821 | dbg_cmd(ehci, "fatal", cmd); |
| 958 | 822 | dbg_status(ehci, "fatal", status); |
| 959 | − ehci_halt(ehci); | |
| 960 | 823 | dead: |
| 961 | − ehci_reset(ehci); | |
| 962 | − ehci_writel(ehci, 0, &ehci->regs->configured_flag); | |
| 963 | 824 | usb_hc_died(hcd); |
| 964 | − /* generic layer kills/unlinks all urbs, then | |
| 965 | − * uses ehci_stop to clean up the rest | |
| 966 | − */ | |
| 967 | − bh = 1; | |
| 825 | + | |
| 826 | + /* Don't let the controller do anything more */ | |
| 827 | + ehci->shutdown = true; | |
| 828 | + ehci->rh_state = EHCI_RH_STOPPING; | |
| 829 | + ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); | |
| 830 | + ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 831 | + ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 832 | + ehci_handle_controller_death(ehci); | |
| 833 | + | |
| 834 | + /* Handle completions when the controller stops */ | |
| 835 | + bh = 0; | |
| 968 | 836 | } |
| 969 | 837 | |
| 970 | 838 | if (bh) |
| @@ -1026,38 +894,6 @@ static int ehci_urb_enqueue ( · 55 unmodified lines | ||
| 1026 | 894 | } |
| 1027 | 895 | } |
| 1028 | 896 | |
| 1029 | −static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 1030 | −{ | |
| 1031 | − /* failfast */ | |
| 1032 | − if (ehci->rh_state != EHCI_RH_RUNNING && ehci->reclaim) | |
| 1033 | − end_unlink_async(ehci); | |
| 1034 | − | |
| 1035 | − /* If the QH isn't linked then there's nothing we can do | |
| 1036 | − * unless we were called during a giveback, in which case | |
| 1037 | − * qh_completions() has to deal with it. | |
| 1038 | − */ | |
| 1039 | − if (qh->qh_state != QH_STATE_LINKED) { | |
| 1040 | − if (qh->qh_state == QH_STATE_COMPLETING) | |
| 1041 | − qh->needs_rescan = 1; | |
| 1042 | − return; | |
| 1043 | − } | |
| 1044 | − | |
| 1045 | − /* defer till later if busy */ | |
| 1046 | − if (ehci->reclaim) { | |
| 1047 | − struct ehci_qh *last; | |
| 1048 | − | |
| 1049 | − for (last = ehci->reclaim; | |
| 1050 | − last->reclaim; | |
| 1051 | − last = last->reclaim) | |
| 1052 | − continue; | |
| 1053 | − qh->qh_state = QH_STATE_UNLINK_WAIT; | |
| 1054 | − last->reclaim = qh; | |
| 1055 | − | |
| 1056 | − /* start IAA cycle */ | |
| 1057 | − } else | |
| 1058 | − start_unlink_async (ehci, qh); | |
| 1059 | −} | |
| 1060 | − | |
| 1061 | 897 | /* remove from hardware lists |
| 1062 | 898 | * completions normally happen asynchronously |
| 1063 | 899 | */ |
| @@ -1084,7 +920,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) · 20 unmodified lines | ||
| 1084 | 920 | switch (qh->qh_state) { |
| 1085 | 921 | case QH_STATE_LINKED: |
| 1086 | 922 | case QH_STATE_COMPLETING: |
| 1087 | − unlink_async(ehci, qh); | |
| 923 | + start_unlink_async(ehci, qh); | |
| 1088 | 924 | break; |
| 1089 | 925 | case QH_STATE_UNLINK: |
| 1090 | 926 | case QH_STATE_UNLINK_WAIT: |
| @@ -1104,7 +940,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) · 13 unmodified lines | ||
| 1104 | 940 | switch (qh->qh_state) { |
| 1105 | 941 | case QH_STATE_LINKED: |
| 1106 | 942 | case QH_STATE_COMPLETING: |
| 1107 | − intr_deschedule (ehci, qh); | |
| 943 | + start_unlink_intr(ehci, qh); | |
| 1108 | 944 | break; |
| 1109 | 945 | case QH_STATE_IDLE: |
| 1110 | 946 | qh_completions (ehci, qh); |
| @@ -1152,11 +988,17 @@ rescan: · 41 unmodified lines | ||
| 1152 | 988 | * accelerate iso completions ... so spin a while. |
| 1153 | 989 | */ |
| 1154 | 990 | if (qh->hw == NULL) { |
| 1155 | − ehci_vdbg (ehci, "iso delay\n"); | |
| 1156 | − goto idle_timeout; | |
| 991 | + struct ehci_iso_stream *stream = ep->hcpriv; | |
| 992 | + | |
| 993 | + if (!list_empty(&stream->td_list)) | |
| 994 | + goto idle_timeout; | |
| 995 | + | |
| 996 | + /* BUG_ON(!list_empty(&stream->free_list)); */ | |
| 997 | + kfree(stream); | |
| 998 | + goto done; | |
| 1157 | 999 | } |
| 1158 | 1000 | |
| 1159 | − if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 1001 | + if (ehci->rh_state < EHCI_RH_RUNNING) | |
| 1160 | 1002 | qh->qh_state = QH_STATE_IDLE; |
| 1161 | 1003 | switch (qh->qh_state) { |
| 1162 | 1004 | case QH_STATE_LINKED: |
| @@ -1169,7 +1011,7 @@ rescan: · 6 unmodified lines | ||
| 1169 | 1011 | * may already be unlinked. |
| 1170 | 1012 | */ |
| 1171 | 1013 | if (tmp) |
| 1172 | − unlink_async(ehci, qh); | |
| 1014 | + start_unlink_async(ehci, qh); | |
| 1173 | 1015 | /* FALL THROUGH */ |
| 1174 | 1016 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
| 1175 | 1017 | case QH_STATE_UNLINK_WAIT: |
| @@ -1181,7 +1023,7 @@ idle_timeout: · 5 unmodified lines | ||
| 1181 | 1023 | if (qh->clearing_tt) |
| 1182 | 1024 | goto idle_timeout; |
| 1183 | 1025 | if (list_empty (&qh->qtd_list)) { |
| 1184 | − qh_put (qh); | |
| 1026 | + qh_destroy(ehci, qh); | |
| 1185 | 1027 | break; |
| 1186 | 1028 | } |
| 1187 | 1029 | /* else FALL THROUGH */ |
| @@ -1194,8 +1036,8 @@ idle_timeout: · 6 unmodified lines | ||
| 1194 | 1036 | list_empty (&qh->qtd_list) ? "" : "(has tds)"); |
| 1195 | 1037 | break; |
| 1196 | 1038 | } |
| 1039 | + done: | |
| 1197 | 1040 | ep->hcpriv = NULL; |
| 1198 | −done: | |
| 1199 | 1041 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1200 | 1042 | } |
| 1201 | 1043 | |
| @@ -1232,9 +1074,9 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) · 30 unmodified lines | ||
| 1232 | 1074 | * re-linking will call qh_refresh(). |
| 1233 | 1075 | */ |
| 1234 | 1076 | if (eptype == USB_ENDPOINT_XFER_BULK) |
| 1235 | − unlink_async(ehci, qh); | |
| 1077 | + start_unlink_async(ehci, qh); | |
| 1236 | 1078 | else |
| 1237 | − intr_deschedule(ehci, qh); | |
| 1079 | + start_unlink_intr(ehci, qh); | |
| 1238 | 1080 | } |
| 1239 | 1081 | } |
| 1240 | 1082 | spin_unlock_irqrestore(&ehci->lock, flags); |
| @@ -1247,6 +1089,104 @@ static int ehci_get_frame (struct usb_hcd *hcd) · 6 unmodified lines | ||
| 1247 | 1089 | } |
| 1248 | 1090 | |
| 1249 | 1091 | /*-------------------------------------------------------------------------*/ |
| 1092 | + | |
| 1093 | +#ifdef CONFIG_PM | |
| 1094 | + | |
| 1095 | +/* suspend/resume, section 4.3 */ | |
| 1096 | + | |
| 1097 | +/* These routines handle the generic parts of controller suspend/resume */ | |
| 1098 | + | |
| 1099 | +static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) | |
| 1100 | +{ | |
| 1101 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 1102 | + | |
| 1103 | + if (time_before(jiffies, ehci->next_statechange)) | |
| 1104 | + msleep(10); | |
| 1105 | + | |
| 1106 | + /* | |
| 1107 | + * Root hub was already suspended. Disable IRQ emission and | |
| 1108 | + * mark HW unaccessible. The PM and USB cores make sure that | |
| 1109 | + * the root hub is either suspended or stopped. | |
| 1110 | + */ | |
| 1111 | + ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); | |
| 1112 | + | |
| 1113 | + spin_lock_irq(&ehci->lock); | |
| 1114 | + ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 1115 | + (void) ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 1116 | + | |
| 1117 | + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 1118 | + spin_unlock_irq(&ehci->lock); | |
| 1119 | + | |
| 1120 | + return 0; | |
| 1121 | +} | |
| 1122 | + | |
| 1123 | +/* Returns 0 if power was preserved, 1 if power was lost */ | |
| 1124 | +static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) | |
| 1125 | +{ | |
| 1126 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 1127 | + | |
| 1128 | + if (time_before(jiffies, ehci->next_statechange)) | |
| 1129 | + msleep(100); | |
| 1130 | + | |
| 1131 | + /* Mark hardware accessible again as we are back to full power by now */ | |
| 1132 | + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 1133 | + | |
| 1134 | + if (ehci->shutdown) | |
| 1135 | + return 0; /* Controller is dead */ | |
| 1136 | + | |
| 1137 | + /* | |
| 1138 | + * If CF is still set and we aren't resuming from hibernation | |
| 1139 | + * then we maintained suspend power. | |
| 1140 | + * Just undo the effect of ehci_suspend(). | |
| 1141 | + */ | |
| 1142 | + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && | |
| 1143 | + !hibernated) { | |
| 1144 | + int mask = INTR_MASK; | |
| 1145 | + | |
| 1146 | + ehci_prepare_ports_for_controller_resume(ehci); | |
| 1147 | + | |
| 1148 | + spin_lock_irq(&ehci->lock); | |
| 1149 | + if (ehci->shutdown) | |
| 1150 | + goto skip; | |
| 1151 | + | |
| 1152 | + if (!hcd->self.root_hub->do_remote_wakeup) | |
| 1153 | + mask &= ~STS_PCD; | |
| 1154 | + ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 1155 | + ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 1156 | + skip: | |
| 1157 | + spin_unlock_irq(&ehci->lock); | |
| 1158 | + return 0; | |
| 1159 | + } | |
| 1160 | + | |
| 1161 | + /* | |
| 1162 | + * Else reset, to cope with power loss or resume from hibernation | |
| 1163 | + * having let the firmware kick in during reboot. | |
| 1164 | + */ | |
| 1165 | + usb_root_hub_lost_power(hcd->self.root_hub); | |
| 1166 | + (void) ehci_halt(ehci); | |
| 1167 | + (void) ehci_reset(ehci); | |
| 1168 | + | |
| 1169 | + spin_lock_irq(&ehci->lock); | |
| 1170 | + if (ehci->shutdown) | |
| 1171 | + goto skip; | |
| 1172 | + | |
| 1173 | + ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 1174 | + ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 1175 | + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 1176 | + | |
| 1177 | + ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 1178 | + spin_unlock_irq(&ehci->lock); | |
| 1179 | + | |
| 1180 | + /* here we "know" root ports should always stay powered */ | |
| 1181 | + ehci_port_power(ehci, 1); | |
| 1182 | + | |
| 1183 | + return 1; | |
| 1184 | +} | |
| 1185 | + | |
| 1186 | +#endif | |
| 1187 | + | |
| 1188 | +/*-------------------------------------------------------------------------*/ | |
| 1189 | + | |
| 1250 | 1190 | /* |
| 1251 | 1191 | * The EHCI in ChipIdea HDRC cannot be a separate module or device, |
| 1252 | 1192 | * because its registers (and irq) are shared between host/gadget/otg |
| @@ -59,6 +59,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) · 58 unmodified lines | ||
| 59 | 59 | /* Give the connections some time to appear */ |
| 60 | 60 | msleep(20); |
| 61 | 61 | |
| 62 | + spin_lock_irq(&ehci->lock); | |
| 62 | 63 | port = HCS_N_PORTS(ehci->hcs_params); |
| 63 | 64 | while (port--) { |
| 64 | 65 | if (test_bit(port, &ehci->owned_ports)) { |
| @@ -70,23 +71,30 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) · 5 unmodified lines | ||
| 70 | 71 | clear_bit(port, &ehci->owned_ports); |
| 71 | 72 | else if (test_bit(port, &ehci->companion_ports)) |
| 72 | 73 | ehci_writel(ehci, status & ~PORT_PE, reg); |
| 73 | − else | |
| 74 | + else { | |
| 75 | + spin_unlock_irq(&ehci->lock); | |
| 74 | 76 | ehci_hub_control(hcd, SetPortFeature, |
| 75 | 77 | USB_PORT_FEAT_RESET, port + 1, |
| 76 | 78 | NULL, 0); |
| 79 | + spin_lock_irq(&ehci->lock); | |
| 80 | + } | |
| 77 | 81 | } |
| 78 | 82 | } |
| 83 | + spin_unlock_irq(&ehci->lock); | |
| 79 | 84 | |
| 80 | 85 | if (!ehci->owned_ports) |
| 81 | 86 | return; |
| 82 | 87 | msleep(90); /* Wait for resets to complete */ |
| 83 | 88 | |
| 89 | + spin_lock_irq(&ehci->lock); | |
| 84 | 90 | port = HCS_N_PORTS(ehci->hcs_params); |
| 85 | 91 | while (port--) { |
| 86 | 92 | if (test_bit(port, &ehci->owned_ports)) { |
| 93 | + spin_unlock_irq(&ehci->lock); | |
| 87 | 94 | ehci_hub_control(hcd, GetPortStatus, |
| 88 | 95 | 0, port + 1, |
| 89 | 96 | (char *) &buf, sizeof(buf)); |
| 97 | + spin_lock_irq(&ehci->lock); | |
| 90 | 98 | |
| 91 | 99 | /* The companion should now own the port, |
| 92 | 100 | * but if something went wrong the port must not |
| @@ -105,9 +113,10 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) · 12 unmodified lines | ||
| 105 | 113 | } |
| 106 | 114 | |
| 107 | 115 | ehci->owned_ports = 0; |
| 116 | + spin_unlock_irq(&ehci->lock); | |
| 108 | 117 | } |
| 109 | 118 | |
| 110 | −static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) | |
| 119 | +static int ehci_port_change(struct ehci_hcd *ehci) | |
| 111 | 120 | { |
| 112 | 121 | int i = HCS_N_PORTS(ehci->hcs_params); |
| 113 | 122 | |
| @@ -128,12 +137,11 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) · 14 unmodified lines | ||
| 128 | 137 | return 0; |
| 129 | 138 | } |
| 130 | 139 | |
| 131 | −static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |
| 140 | +static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |
| 132 | 141 | bool suspending, bool do_wakeup) |
| 133 | 142 | { |
| 134 | 143 | int port; |
| 135 | 144 | u32 temp; |
| 136 | − unsigned long flags; | |
| 137 | 145 | |
| 138 | 146 | /* If remote wakeup is enabled for the root hub but disabled |
| 139 | 147 | * for the controller, we must adjust all the port wakeup flags |
| @@ -143,22 +151,20 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, · 3 unmodified lines | ||
| 143 | 151 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) |
| 144 | 152 | return; |
| 145 | 153 | |
| 146 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 154 | + spin_lock_irq(&ehci->lock); | |
| 147 | 155 | |
| 148 | 156 | /* clear phy low-power mode before changing wakeup flags */ |
| 149 | 157 | if (ehci->has_hostpc) { |
| 150 | 158 | port = HCS_N_PORTS(ehci->hcs_params); |
| 151 | 159 | while (port--) { |
| 152 | − u32 __iomem *hostpc_reg; | |
| 160 | + u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; | |
| 153 | 161 | |
| 154 | − hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs | |
| 155 | − + HOSTPC0 + 4 * port); | |
| 156 | 162 | temp = ehci_readl(ehci, hostpc_reg); |
| 157 | 163 | ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); |
| 158 | 164 | } |
| 159 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 165 | + spin_unlock_irq(&ehci->lock); | |
| 160 | 166 | msleep(5); |
| 161 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 167 | + spin_lock_irq(&ehci->lock); | |
| 162 | 168 | } |
| 163 | 169 | |
| 164 | 170 | port = HCS_N_PORTS(ehci->hcs_params); |
| @@ -185,10 +191,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, · 20 unmodified lines | ||
| 185 | 191 | if (ehci->has_hostpc) { |
| 186 | 192 | port = HCS_N_PORTS(ehci->hcs_params); |
| 187 | 193 | while (port--) { |
| 188 | − u32 __iomem *hostpc_reg; | |
| 194 | + u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; | |
| 189 | 195 | |
| 190 | − hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs | |
| 191 | − + HOSTPC0 + 4 * port); | |
| 192 | 196 | temp = ehci_readl(ehci, hostpc_reg); |
| 193 | 197 | ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); |
| 194 | 198 | } |
| @@ -198,7 +202,7 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, · 3 unmodified lines | ||
| 198 | 202 | if (!suspending && ehci_port_change(ehci)) |
| 199 | 203 | usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); |
| 200 | 204 | |
| 201 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 205 | + spin_unlock_irq(&ehci->lock); | |
| 202 | 206 | } |
| 203 | 207 | |
| 204 | 208 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
| @@ -212,10 +216,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 7 unmodified lines | ||
| 212 | 216 | |
| 213 | 217 | if (time_before (jiffies, ehci->next_statechange)) |
| 214 | 218 | msleep(5); |
| 215 | − del_timer_sync(&ehci->watchdog); | |
| 216 | − del_timer_sync(&ehci->iaa_watchdog); | |
| 219 | + | |
| 220 | + /* stop the schedules */ | |
| 221 | + ehci_quiesce(ehci); | |
| 217 | 222 | |
| 218 | 223 | spin_lock_irq (&ehci->lock); |
| 224 | + if (ehci->rh_state < EHCI_RH_RUNNING) | |
| 225 | + goto done; | |
| 219 | 226 | |
| 220 | 227 | /* Once the controller is stopped, port resumes that are already |
| 221 | 228 | * in progress won't complete. Hence if remote wakeup is enabled |
| @@ -230,11 +237,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 8 unmodified lines | ||
| 230 | 237 | } |
| 231 | 238 | } |
| 232 | 239 | |
| 233 | − /* stop schedules, clean any completed work */ | |
| 234 | − if (ehci->rh_state == EHCI_RH_RUNNING) | |
| 235 | − ehci_quiesce (ehci); | |
| 236 | − ehci_work(ehci); | |
| 237 | − | |
| 238 | 240 | /* Unlike other USB host controller types, EHCI doesn't have |
| 239 | 241 | * any notion of "global" or bus-wide suspend. The driver has |
| 240 | 242 | * to manually suspend all the active unsuspended ports, and |
| @@ -285,11 +287,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 44 unmodified lines | ||
| 285 | 287 | |
| 286 | 288 | port = HCS_N_PORTS(ehci->hcs_params); |
| 287 | 289 | while (port--) { |
| 288 | − u32 __iomem *hostpc_reg; | |
| 290 | + u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; | |
| 289 | 291 | u32 t3; |
| 290 | 292 | |
| 291 | − hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs | |
| 292 | − + HOSTPC0 + 4 * port); | |
| 293 | 293 | t3 = ehci_readl(ehci, hostpc_reg); |
| 294 | 294 | ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); |
| 295 | 295 | t3 = ehci_readl(ehci, hostpc_reg); |
| @@ -298,6 +298,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 2 unmodified lines | ||
| 298 | 298 | "succeeded" : "failed"); |
| 299 | 299 | } |
| 300 | 300 | } |
| 301 | + spin_unlock_irq(&ehci->lock); | |
| 301 | 302 | |
| 302 | 303 | /* Apparently some devices need a >= 1-uframe delay here */ |
| 303 | 304 | if (ehci->bus_suspended) |
| @@ -305,10 +306,18 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 1 unmodified line | ||
| 305 | 306 | |
| 306 | 307 | /* turn off now-idle HC */ |
| 307 | 308 | ehci_halt (ehci); |
| 309 | + | |
| 310 | + spin_lock_irq(&ehci->lock); | |
| 311 | + if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD)) | |
| 312 | + ehci_handle_controller_death(ehci); | |
| 313 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 314 | + goto done; | |
| 308 | 315 | ehci->rh_state = EHCI_RH_SUSPENDED; |
| 309 | 316 | |
| 310 | − if (ehci->reclaim) | |
| 311 | − end_unlink_async(ehci); | |
| 317 | + end_unlink_async(ehci); | |
| 318 | + unlink_empty_async(ehci); | |
| 319 | + ehci_handle_intr_unlinks(ehci); | |
| 320 | + end_free_itds(ehci); | |
| 312 | 321 | |
| 313 | 322 | /* allow remote wakeup */ |
| 314 | 323 | mask = INTR_MASK; |
| @@ -317,13 +326,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) · 2 unmodified lines | ||
| 317 | 326 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
| 318 | 327 | ehci_readl(ehci, &ehci->regs->intr_enable); |
| 319 | 328 | |
| 329 | + done: | |
| 320 | 330 | ehci->next_statechange = jiffies + msecs_to_jiffies(10); |
| 331 | + ehci->enabled_hrtimer_events = 0; | |
| 332 | + ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; | |
| 321 | 333 | spin_unlock_irq (&ehci->lock); |
| 322 | 334 | |
| 323 | − /* ehci_work() may have re-enabled the watchdog timer, which we do not | |
| 324 | − * want, and so we must delete any pending watchdog timer events. | |
| 325 | − */ | |
| 326 | − del_timer_sync(&ehci->watchdog); | |
| 335 | + hrtimer_cancel(&ehci->hrtimer); | |
| 327 | 336 | return 0; |
| 328 | 337 | } |
| 329 | 338 | |
| @@ -340,10 +349,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 10 unmodified lines | ||
| 340 | 349 | if (time_before (jiffies, ehci->next_statechange)) |
| 341 | 350 | msleep(5); |
| 342 | 351 | spin_lock_irq (&ehci->lock); |
| 343 | − if (!HCD_HW_ACCESSIBLE(hcd)) { | |
| 344 | − spin_unlock_irq(&ehci->lock); | |
| 345 | − return -ESHUTDOWN; | |
| 346 | − } | |
| 352 | + if (!HCD_HW_ACCESSIBLE(hcd) || ehci->shutdown) | |
| 353 | + goto shutdown; | |
| 347 | 354 | |
| 348 | 355 | if (unlikely(ehci->debug)) { |
| 349 | 356 | if (!dbgp_reset_prep()) |
| @@ -382,16 +389,17 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 32 unmodified lines | ||
| 382 | 389 | spin_unlock_irq(&ehci->lock); |
| 383 | 390 | msleep(8); |
| 384 | 391 | spin_lock_irq(&ehci->lock); |
| 392 | + if (ehci->shutdown) | |
| 393 | + goto shutdown; | |
| 385 | 394 | |
| 386 | 395 | /* clear phy low-power mode before resume */ |
| 387 | 396 | if (ehci->bus_suspended && ehci->has_hostpc) { |
| 388 | 397 | i = HCS_N_PORTS(ehci->hcs_params); |
| 389 | 398 | while (i--) { |
| 390 | 399 | if (test_bit(i, &ehci->bus_suspended)) { |
| 391 | − u32 __iomem *hostpc_reg; | |
| 400 | + u32 __iomem *hostpc_reg = | |
| 401 | + &ehci->regs->hostpc[i]; | |
| 392 | 402 | |
| 393 | − hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs | |
| 394 | − + HOSTPC0 + 4 * i); | |
| 395 | 403 | temp = ehci_readl(ehci, hostpc_reg); |
| 396 | 404 | ehci_writel(ehci, temp & ~HOSTPC_PHCD, |
| 397 | 405 | hostpc_reg); |
| @@ -400,6 +408,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 2 unmodified lines | ||
| 400 | 408 | spin_unlock_irq(&ehci->lock); |
| 401 | 409 | msleep(5); |
| 402 | 410 | spin_lock_irq(&ehci->lock); |
| 411 | + if (ehci->shutdown) | |
| 412 | + goto shutdown; | |
| 403 | 413 | } |
| 404 | 414 | |
| 405 | 415 | /* manually resume the ports we suspended during bus_suspend() */ |
| @@ -420,6 +430,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 14 unmodified lines | ||
| 420 | 430 | spin_unlock_irq(&ehci->lock); |
| 421 | 431 | msleep(20); |
| 422 | 432 | spin_lock_irq(&ehci->lock); |
| 433 | + if (ehci->shutdown) | |
| 434 | + goto shutdown; | |
| 423 | 435 | } |
| 424 | 436 | |
| 425 | 437 | i = HCS_N_PORTS (ehci->hcs_params); |
| @@ -431,27 +443,25 @@ static int ehci_bus_resume (struct usb_hcd *hcd) · 5 unmodified lines | ||
| 431 | 443 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); |
| 432 | 444 | } |
| 433 | 445 | } |
| 434 | − (void) ehci_readl(ehci, &ehci->regs->command); | |
| 435 | − | |
| 436 | − /* maybe re-activate the schedule(s) */ | |
| 437 | − temp = 0; | |
| 438 | − if (ehci->async->qh_next.qh) | |
| 439 | − temp |= CMD_ASE; | |
| 440 | − if (ehci->periodic_sched) | |
| 441 | − temp |= CMD_PSE; | |
| 442 | − if (temp) { | |
| 443 | − ehci->command |= temp; | |
| 444 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 445 | − } | |
| 446 | 446 | |
| 447 | 447 | ehci->next_statechange = jiffies + msecs_to_jiffies(5); |
| 448 | + spin_unlock_irq(&ehci->lock); | |
| 449 | + | |
| 450 | + ehci_handover_companion_ports(ehci); | |
| 448 | 451 | |
| 449 | 452 | /* Now we can safely re-enable irqs */ |
| 453 | + spin_lock_irq(&ehci->lock); | |
| 454 | + if (ehci->shutdown) | |
| 455 | + goto shutdown; | |
| 450 | 456 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); |
| 457 | + (void) ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 458 | + spin_unlock_irq(&ehci->lock); | |
| 451 | 459 | |
| 452 | − spin_unlock_irq (&ehci->lock); | |
| 453 | − ehci_handover_companion_ports(ehci); | |
| 454 | 460 | return 0; |
| 461 | + | |
| 462 | + shutdown: | |
| 463 | + spin_unlock_irq(&ehci->lock); | |
| 464 | + return -ESHUTDOWN; | |
| 455 | 465 | } |
| 456 | 466 | |
| 457 | 467 | #else |
| @@ -667,7 +677,7 @@ static int ehci_hub_control ( · 209 unmodified lines | ||
| 667 | 677 | int ports = HCS_N_PORTS (ehci->hcs_params); |
| 668 | 678 | u32 __iomem *status_reg = &ehci->regs->port_status[ |
| 669 | 679 | (wIndex & 0xff) - 1]; |
| 670 | − u32 __iomem *hostpc_reg = NULL; | |
| 680 | + u32 __iomem *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1]; | |
| 671 | 681 | u32 temp, temp1, status; |
| 672 | 682 | unsigned long flags; |
| 673 | 683 | int retval = 0; |
| @@ -680,9 +690,6 @@ static int ehci_hub_control ( · 6 unmodified lines | ||
| 680 | 690 | * power, "this is the one", etc. EHCI spec supports this. |
| 681 | 691 | */ |
| 682 | 692 | |
| 683 | − if (ehci->has_hostpc) | |
| 684 | − hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs | |
| 685 | − + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); | |
| 686 | 693 | spin_lock_irqsave (&ehci->lock, flags); |
| 687 | 694 | switch (typeReq) { |
| 688 | 695 | case ClearHubFeature: |
| @@ -724,7 +731,7 @@ static int ehci_hub_control ( · 35 unmodified lines | ||
| 724 | 731 | #ifdef CONFIG_USB_OTG |
| 725 | 732 | if ((hcd->self.otg_port == (wIndex + 1)) |
| 726 | 733 | && hcd->self.b_hnp_enable) { |
| 727 | − otg_start_hnp(ehci->transceiver->otg); | |
| 734 | + otg_start_hnp(hcd->phy->otg); | |
| 728 | 735 | break; |
| 729 | 736 | } |
| 730 | 737 | #endif |
| @@ -734,7 +741,7 @@ static int ehci_hub_control ( · 3 unmodified lines | ||
| 734 | 741 | goto error; |
| 735 | 742 | |
| 736 | 743 | /* clear phy low-power mode before resume */ |
| 737 | − if (hostpc_reg) { | |
| 744 | + if (ehci->has_hostpc) { | |
| 738 | 745 | temp1 = ehci_readl(ehci, hostpc_reg); |
| 739 | 746 | ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, |
| 740 | 747 | hostpc_reg); |
| @@ -984,7 +991,7 @@ static int ehci_hub_control ( · 243 unmodified lines | ||
| 984 | 991 | temp &= ~PORT_WKCONN_E; |
| 985 | 992 | temp |= PORT_WKDISC_E | PORT_WKOC_E; |
| 986 | 993 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); |
| 987 | − if (hostpc_reg) { | |
| 994 | + if (ehci->has_hostpc) { | |
| 988 | 995 | spin_unlock_irqrestore(&ehci->lock, flags); |
| 989 | 996 | msleep(5);/* 5ms for HCD enter low pwr mode */ |
| 990 | 997 | spin_lock_irqsave(&ehci->lock, flags); |
| @@ -1041,7 +1048,9 @@ static int ehci_hub_control ( · 50 unmodified lines | ||
| 1041 | 1048 | case USB_PORT_FEAT_TEST: |
| 1042 | 1049 | if (!selector || selector > 5) |
| 1043 | 1050 | goto error; |
| 1051 | + spin_unlock_irqrestore(&ehci->lock, flags); | |
| 1044 | 1052 | ehci_quiesce(ehci); |
| 1053 | + spin_lock_irqsave(&ehci->lock, flags); | |
| 1045 | 1054 | |
| 1046 | 1055 | /* Put all enabled ports into suspend */ |
| 1047 | 1056 | while (ports--) { |
| @@ -1053,7 +1062,11 @@ static int ehci_hub_control ( · 5 unmodified lines | ||
| 1053 | 1062 | ehci_writel(ehci, temp | PORT_SUSPEND, |
| 1054 | 1063 | sreg); |
| 1055 | 1064 | } |
| 1065 | + | |
| 1066 | + spin_unlock_irqrestore(&ehci->lock, flags); | |
| 1056 | 1067 | ehci_halt(ehci); |
| 1068 | + spin_lock_irqsave(&ehci->lock, flags); | |
| 1069 | + | |
| 1057 | 1070 | temp = ehci_readl(ehci, status_reg); |
| 1058 | 1071 | temp |= selector << 16; |
| 1059 | 1072 | ehci_writel(ehci, temp, status_reg); |
| @@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd) · 21 unmodified lines | ||
| 22 | 22 | ehci->big_endian_mmio = 1; |
| 23 | 23 | |
| 24 | 24 | ehci->caps = hcd->regs + 0x100; |
| 25 | − ehci->regs = hcd->regs + 0x100 | |
| 26 | − + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 27 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 28 | 25 | |
| 29 | 26 | hcd->has_tt = 1; |
| 30 | − ehci_reset(ehci); | |
| 31 | 27 | |
| 32 | − retval = ehci_init(hcd); | |
| 28 | + retval = ehci_setup(hcd); | |
| 33 | 29 | if (retval) |
| 34 | 30 | return retval; |
| 35 | 31 | |
| @@ -64,10 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) · 63 unmodified lines | ||
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | |
| 67 | −static void qh_destroy(struct ehci_qh *qh) | |
| 67 | +static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 68 | 68 | { |
| 69 | − struct ehci_hcd *ehci = qh->ehci; | |
| 70 | − | |
| 71 | 69 | /* clean qtds first, and know this is not linked */ |
| 72 | 70 | if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { |
| 73 | 71 | ehci_dbg (ehci, "unused qh not empty!\n"); |
| @@ -92,8 +90,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) · 18 unmodified lines | ||
| 92 | 90 | if (!qh->hw) |
| 93 | 91 | goto fail; |
| 94 | 92 | memset(qh->hw, 0, sizeof *qh->hw); |
| 95 | − qh->refcount = 1; | |
| 96 | − qh->ehci = ehci; | |
| 97 | 93 | qh->qh_dma = dma; |
| 98 | 94 | // INIT_LIST_HEAD (&qh->qh_list); |
| 99 | 95 | INIT_LIST_HEAD (&qh->qtd_list); |
| @@ -113,20 +109,6 @@ fail: · 13 unmodified lines | ||
| 113 | 109 | return NULL; |
| 114 | 110 | } |
| 115 | 111 | |
| 116 | −/* to share a qh (cpu threads, or hc) */ | |
| 117 | −static inline struct ehci_qh *qh_get (struct ehci_qh *qh) | |
| 118 | −{ | |
| 119 | − WARN_ON(!qh->refcount); | |
| 120 | − qh->refcount++; | |
| 121 | − return qh; | |
| 122 | −} | |
| 123 | − | |
| 124 | −static inline void qh_put (struct ehci_qh *qh) | |
| 125 | −{ | |
| 126 | − if (!--qh->refcount) | |
| 127 | − qh_destroy(qh); | |
| 128 | −} | |
| 129 | − | |
| 130 | 112 | /*-------------------------------------------------------------------------*/ |
| 131 | 113 | |
| 132 | 114 | /* The queue heads and transfer descriptors are managed from pools tied |
| @@ -136,13 +118,12 @@ static inline void qh_put (struct ehci_qh *qh) · 3 unmodified lines | ||
| 136 | 118 | |
| 137 | 119 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) |
| 138 | 120 | { |
| 139 | − free_cached_lists(ehci); | |
| 140 | 121 | if (ehci->async) |
| 141 | − qh_put (ehci->async); | |
| 122 | + qh_destroy(ehci, ehci->async); | |
| 142 | 123 | ehci->async = NULL; |
| 143 | 124 | |
| 144 | 125 | if (ehci->dummy) |
| 145 | − qh_put(ehci->dummy); | |
| 126 | + qh_destroy(ehci, ehci->dummy); | |
| 146 | 127 | ehci->dummy = NULL; |
| 147 | 128 | |
| 148 | 129 | /* DMA consistent memory and pools */ |
| @@ -145,8 +145,8 @@ static int ehci_msm_probe(struct platform_device *pdev) · 144 unmodified lines | ||
| 145 | 145 | * powering up VBUS, mapping of registers address space and power |
| 146 | 146 | * management. |
| 147 | 147 | */ |
| 148 | − phy = usb_get_transceiver(); | |
| 149 | − if (!phy) { | |
| 148 | + phy = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 149 | + if (IS_ERR_OR_NULL(phy)) { | |
| 150 | 150 | dev_err(&pdev->dev, "unable to find transceiver\n"); |
| 151 | 151 | ret = -ENODEV; |
| 152 | 152 | goto unmap; |
| @@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 169 | 169 | return 0; |
| 170 | 170 | |
| 171 | 171 | put_transceiver: |
| 172 | − usb_put_transceiver(phy); | |
| 172 | + usb_put_phy(phy); | |
| 173 | 173 | unmap: |
| 174 | 174 | iounmap(hcd->regs); |
| 175 | 175 | put_hcd: |
| @@ -187,7 +187,7 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) · 11 unmodified lines | ||
| 187 | 187 | pm_runtime_set_suspended(&pdev->dev); |
| 188 | 188 | |
| 189 | 189 | otg_set_host(phy->otg, NULL); |
| 190 | − usb_put_transceiver(phy); | |
| 190 | + usb_put_phy(phy); | |
| 191 | 191 | |
| 192 | 192 | usb_put_hcd(hcd); |
| 193 | 193 | |
| @@ -198,24 +198,11 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) · 4 unmodified lines | ||
| 198 | 198 | static int ehci_msm_pm_suspend(struct device *dev) |
| 199 | 199 | { |
| 200 | 200 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 201 | − bool wakeup = device_may_wakeup(dev); | |
| 201 | + bool do_wakeup = device_may_wakeup(dev); | |
| 202 | 202 | |
| 203 | 203 | dev_dbg(dev, "ehci-msm PM suspend\n"); |
| 204 | 204 | |
| 205 | − /* | |
| 206 | − * EHCI helper function has also the same check before manipulating | |
| 207 | − * port wakeup flags. We do check here the same condition before | |
| 208 | − * calling the same helper function to avoid bringing hardware | |
| 209 | − * from Low power mode when there is no need for adjusting port | |
| 210 | − * wakeup flags. | |
| 211 | − */ | |
| 212 | − if (hcd->self.root_hub->do_remote_wakeup && !wakeup) { | |
| 213 | − pm_runtime_resume(dev); | |
| 214 | − ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), | |
| 215 | − wakeup); | |
| 216 | − } | |
| 217 | − | |
| 218 | − return 0; | |
| 205 | + return ehci_suspend(hcd, do_wakeup); | |
| 219 | 206 | } |
| 220 | 207 | |
| 221 | 208 | static int ehci_msm_pm_resume(struct device *dev) |
| @@ -223,7 +210,7 @@ static int ehci_msm_pm_resume(struct device *dev) · 1 unmodified line | ||
| 223 | 210 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 224 | 211 | |
| 225 | 212 | dev_dbg(dev, "ehci-msm PM resume\n"); |
| 226 | − ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); | |
| 213 | + ehci_resume(hcd, false); | |
| 227 | 214 | |
| 228 | 215 | return 0; |
| 229 | 216 | } |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/module.h> |
| 14 | 14 | #include <linux/platform_device.h> |
| 15 | 15 | #include <linux/clk.h> |
| 16 | +#include <linux/err.h> | |
| 16 | 17 | #include <linux/usb/otg.h> |
| 17 | 18 | #include <linux/platform_data/mv_usb.h> |
| 18 | 19 | |
| @@ -76,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) · 57 unmodified lines | ||
| 76 | 77 | |
| 77 | 78 | static int mv_ehci_reset(struct usb_hcd *hcd) |
| 78 | 79 | { |
| 79 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 80 | 80 | struct device *dev = hcd->self.controller; |
| 81 | 81 | struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev); |
| 82 | 82 | int retval; |
| @@ -86,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd) · 3 unmodified lines | ||
| 86 | 86 | return -ENODEV; |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | − /* | |
| 90 | − * data structure init | |
| 91 | − */ | |
| 92 | − retval = ehci_init(hcd); | |
| 93 | − if (retval) { | |
| 94 | − dev_err(dev, "ehci_init failed %d\n", retval); | |
| 95 | − return retval; | |
| 96 | − } | |
| 97 | − | |
| 98 | 89 | hcd->has_tt = 1; |
| 99 | − ehci->sbrn = 0x20; | |
| 100 | 90 | |
| 101 | − retval = ehci_reset(ehci); | |
| 102 | − if (retval) { | |
| 103 | − dev_err(dev, "ehci_reset failed %d\n", retval); | |
| 104 | − return retval; | |
| 105 | − } | |
| 91 | + retval = ehci_setup(hcd); | |
| 92 | + if (retval) | |
| 93 | + dev_err(dev, "ehci_setup failed %d\n", retval); | |
| 106 | 94 | |
| 107 | − return 0; | |
| 95 | + return retval; | |
| 108 | 96 | } |
| 109 | 97 | |
| 110 | 98 | static const struct hc_driver mv_ehci_hc_driver = { |
| @@ -247,14 +235,12 @@ static int mv_ehci_probe(struct platform_device *pdev) · 136 unmodified lines | ||
| 247 | 235 | |
| 248 | 236 | ehci = hcd_to_ehci(hcd); |
| 249 | 237 | ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; |
| 250 | − ehci->regs = (struct ehci_regs *) ehci_mv->op_regs; | |
| 251 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 252 | 238 | |
| 253 | 239 | ehci_mv->mode = pdata->mode; |
| 254 | 240 | if (ehci_mv->mode == MV_USB_MODE_OTG) { |
| 255 | 241 | #ifdef CONFIG_USB_OTG_UTILS |
| 256 | − ehci_mv->otg = usb_get_transceiver(); | |
| 257 | − if (!ehci_mv->otg) { | |
| 242 | + ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 243 | + if (IS_ERR_OR_NULL(ehci_mv->otg)) { | |
| 258 | 244 | dev_err(&pdev->dev, |
| 259 | 245 | "unable to find transceiver\n"); |
| 260 | 246 | retval = -ENODEV; |
| @@ -302,8 +288,8 @@ err_set_vbus: · 41 unmodified lines | ||
| 302 | 288 | pdata->set_vbus(0); |
| 303 | 289 | #ifdef CONFIG_USB_OTG_UTILS |
| 304 | 290 | err_put_transceiver: |
| 305 | − if (ehci_mv->otg) | |
| 306 | − usb_put_transceiver(ehci_mv->otg); | |
| 291 | + if (!IS_ERR_OR_NULL(ehci_mv->otg)) | |
| 292 | + usb_put_phy(ehci_mv->otg); | |
| 307 | 293 | #endif |
| 308 | 294 | err_disable_clk: |
| 309 | 295 | mv_ehci_disable(ehci_mv); |
| @@ -331,9 +317,9 @@ static int mv_ehci_remove(struct platform_device *pdev) · 21 unmodified lines | ||
| 331 | 317 | if (hcd->rh_registered) |
| 332 | 318 | usb_remove_hcd(hcd); |
| 333 | 319 | |
| 334 | − if (ehci_mv->otg) { | |
| 320 | + if (!IS_ERR_OR_NULL(ehci_mv->otg)) { | |
| 335 | 321 | otg_set_host(ehci_mv->otg->otg, NULL); |
| 336 | − usb_put_transceiver(ehci_mv->otg); | |
| 322 | + usb_put_phy(ehci_mv->otg); | |
| 337 | 323 | } |
| 338 | 324 | |
| 339 | 325 | if (ehci_mv->mode == MV_USB_MODE_HOST) { |
| @@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) · 41 unmodified lines | ||
| 42 | 42 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 43 | 43 | int retval; |
| 44 | 44 | |
| 45 | − dbg_hcs_params(ehci, "reset"); | |
| 46 | − dbg_hcc_params(ehci, "reset"); | |
| 47 | − | |
| 48 | − /* cache this readonly data; minimize chip reads */ | |
| 49 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 50 | − | |
| 51 | 45 | hcd->has_tt = 1; |
| 52 | 46 | |
| 53 | − retval = ehci_halt(ehci); | |
| 47 | + retval = ehci_setup(hcd); | |
| 54 | 48 | if (retval) |
| 55 | 49 | return retval; |
| 56 | 50 | |
| 57 | − /* data structure init */ | |
| 58 | − retval = ehci_init(hcd); | |
| 59 | − if (retval) | |
| 60 | − return retval; | |
| 61 | − | |
| 62 | − ehci->sbrn = 0x20; | |
| 63 | − | |
| 64 | − ehci_reset(ehci); | |
| 65 | − | |
| 66 | 51 | ehci_port_power(ehci, 0); |
| 67 | 52 | return 0; |
| 68 | 53 | } |
| @@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = { · 55 unmodified lines | ||
| 56 | 56 | /* |
| 57 | 57 | * basic lifecycle operations |
| 58 | 58 | */ |
| 59 | − .reset = ehci_init, | |
| 59 | + .reset = ehci_setup, | |
| 60 | 60 | .start = ehci_run, |
| 61 | 61 | .stop = ehci_stop, |
| 62 | 62 | .shutdown = ehci_shutdown, |
| @@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) · 87 unmodified lines | ||
| 150 | 150 | #endif |
| 151 | 151 | |
| 152 | 152 | ehci->caps = hcd->regs; |
| 153 | − ehci->regs = hcd->regs + | |
| 154 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 155 | − /* cache this readonly data; minimize chip reads */ | |
| 156 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 157 | − | |
| 158 | − ehci_reset(ehci); | |
| 159 | 153 | |
| 160 | 154 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 161 | 155 | if (ret) { |
| @@ -115,9 +115,8 @@ static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) · 114 unmodified lines | ||
| 115 | 115 | clk_disable(usbhost_p2_fck); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | −static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) | |
| 118 | +static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) | |
| 119 | 119 | { |
| 120 | − struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); | |
| 121 | 120 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
| 122 | 121 | unsigned reg = 0; |
| 123 | 122 | |
| @@ -139,12 +138,63 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) · 15 unmodified lines | ||
| 139 | 138 | cpu_relax(); |
| 140 | 139 | |
| 141 | 140 | if (time_after(jiffies, timeout)) { |
| 142 | − dev_dbg(&pdev->dev, "phy reset operation timed out\n"); | |
| 141 | + dev_dbg(hcd->self.controller, | |
| 142 | + "phy reset operation timed out\n"); | |
| 143 | 143 | break; |
| 144 | 144 | } |
| 145 | 145 | } |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | +static int omap_ehci_init(struct usb_hcd *hcd) | |
| 149 | +{ | |
| 150 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 151 | + int rc; | |
| 152 | + struct ehci_hcd_omap_platform_data *pdata; | |
| 153 | + | |
| 154 | + pdata = hcd->self.controller->platform_data; | |
| 155 | + if (pdata->phy_reset) { | |
| 156 | + if (gpio_is_valid(pdata->reset_gpio_port[0])) | |
| 157 | + gpio_request_one(pdata->reset_gpio_port[0], | |
| 158 | + GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); | |
| 159 | + | |
| 160 | + if (gpio_is_valid(pdata->reset_gpio_port[1])) | |
| 161 | + gpio_request_one(pdata->reset_gpio_port[1], | |
| 162 | + GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); | |
| 163 | + | |
| 164 | + /* Hold the PHY in RESET for enough time till DIR is high */ | |
| 165 | + udelay(10); | |
| 166 | + } | |
| 167 | + | |
| 168 | + /* Soft reset the PHY using PHY reset command over ULPI */ | |
| 169 | + if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) | |
| 170 | + omap_ehci_soft_phy_reset(hcd, 0); | |
| 171 | + if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) | |
| 172 | + omap_ehci_soft_phy_reset(hcd, 1); | |
| 173 | + | |
| 174 | + /* we know this is the memory we want, no need to ioremap again */ | |
| 175 | + ehci->caps = hcd->regs; | |
| 176 | + | |
| 177 | + rc = ehci_setup(hcd); | |
| 178 | + | |
| 179 | + if (pdata->phy_reset) { | |
| 180 | + /* Hold the PHY in RESET for enough time till | |
| 181 | + * PHY is settled and ready | |
| 182 | + */ | |
| 183 | + udelay(10); | |
| 184 | + | |
| 185 | + if (gpio_is_valid(pdata->reset_gpio_port[0])) | |
| 186 | + gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); | |
| 187 | + | |
| 188 | + if (gpio_is_valid(pdata->reset_gpio_port[1])) | |
| 189 | + gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); | |
| 190 | + } | |
| 191 | + | |
| 192 | + /* root ports should always stay powered */ | |
| 193 | + ehci_port_power(ehci, 1); | |
| 194 | + | |
| 195 | + return rc; | |
| 196 | +} | |
| 197 | + | |
| 148 | 198 | static int omap_ehci_hub_control( |
| 149 | 199 | struct usb_hcd *hcd, |
| 150 | 200 | u16 typeReq, |
| @@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) · 68 unmodified lines | ||
| 219 | 269 | struct resource *res; |
| 220 | 270 | struct usb_hcd *hcd; |
| 221 | 271 | void __iomem *regs; |
| 222 | − struct ehci_hcd *omap_ehci; | |
| 223 | 272 | int ret = -ENODEV; |
| 224 | 273 | int irq; |
| 225 | 274 | int i; |
| @@ -281,18 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) · 55 unmodified lines | ||
| 281 | 330 | } |
| 282 | 331 | } |
| 283 | 332 | |
| 284 | − /* Hold PHYs in reset while initializing EHCI controller */ | |
| 285 | − if (pdata->phy_reset) { | |
| 286 | − if (gpio_is_valid(pdata->reset_gpio_port[0])) | |
| 287 | − gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); | |
| 288 | − | |
| 289 | − if (gpio_is_valid(pdata->reset_gpio_port[1])) | |
| 290 | − gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); | |
| 291 | − | |
| 292 | − /* Hold the PHY in RESET for enough time till DIR is high */ | |
| 293 | − udelay(10); | |
| 294 | − } | |
| 295 | − | |
| 296 | 333 | pm_runtime_enable(dev); |
| 297 | 334 | pm_runtime_get_sync(dev); |
| 298 | 335 | |
| @@ -308,49 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 308 | 345 | ehci_write(regs, EHCI_INSNREG04, |
| 309 | 346 | EHCI_INSNREG04_DISABLE_UNSUSPEND); |
| 310 | 347 | |
| 311 | − /* Soft reset the PHY using PHY reset command over ULPI */ | |
| 312 | − if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) | |
| 313 | − omap_ehci_soft_phy_reset(pdev, 0); | |
| 314 | − if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) | |
| 315 | − omap_ehci_soft_phy_reset(pdev, 1); | |
| 316 | − | |
| 317 | − omap_ehci = hcd_to_ehci(hcd); | |
| 318 | − omap_ehci->sbrn = 0x20; | |
| 319 | − | |
| 320 | − /* we know this is the memory we want, no need to ioremap again */ | |
| 321 | − omap_ehci->caps = hcd->regs; | |
| 322 | − omap_ehci->regs = hcd->regs | |
| 323 | − + HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase)); | |
| 324 | − | |
| 325 | − dbg_hcs_params(omap_ehci, "reset"); | |
| 326 | − dbg_hcc_params(omap_ehci, "reset"); | |
| 327 | − | |
| 328 | − /* cache this readonly data; minimize chip reads */ | |
| 329 | − omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); | |
| 330 | − | |
| 331 | − ehci_reset(omap_ehci); | |
| 332 | 348 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 333 | 349 | if (ret) { |
| 334 | 350 | dev_err(dev, "failed to add hcd with err %d\n", ret); |
| 335 | − goto err_add_hcd; | |
| 351 | + goto err_pm_runtime; | |
| 336 | 352 | } |
| 337 | 353 | |
| 338 | − if (pdata->phy_reset) { | |
| 339 | − /* Hold the PHY in RESET for enough time till | |
| 340 | − * PHY is settled and ready | |
| 341 | − */ | |
| 342 | − udelay(10); | |
| 343 | − | |
| 344 | − if (gpio_is_valid(pdata->reset_gpio_port[0])) | |
| 345 | − gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); | |
| 346 | − | |
| 347 | − if (gpio_is_valid(pdata->reset_gpio_port[1])) | |
| 348 | − gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); | |
| 349 | − } | |
| 350 | − | |
| 351 | − /* root ports should always stay powered */ | |
| 352 | − ehci_port_power(omap_ehci, 1); | |
| 353 | − | |
| 354 | 354 | /* get clocks */ |
| 355 | 355 | utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); |
| 356 | 356 | if (IS_ERR(utmi_p1_fck)) { |
| @@ -422,8 +422,12 @@ err_utmi_p1_fck: · 65 unmodified lines | ||
| 422 | 422 | clk_put(utmi_p1_fck); |
| 423 | 423 | |
| 424 | 424 | err_add_hcd: |
| 425 | + usb_remove_hcd(hcd); | |
| 426 | + | |
| 427 | +err_pm_runtime: | |
| 425 | 428 | disable_put_regulator(pdata); |
| 426 | 429 | pm_runtime_put_sync(dev); |
| 430 | + usb_put_hcd(hcd); | |
| 427 | 431 | |
| 428 | 432 | err_io: |
| 429 | 433 | iounmap(regs); |
| @@ -506,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = { · 76 unmodified lines | ||
| 506 | 510 | /* |
| 507 | 511 | * basic lifecycle operations |
| 508 | 512 | */ |
| 509 | − .reset = ehci_init, | |
| 513 | + .reset = omap_ehci_init, | |
| 510 | 514 | .start = ehci_run, |
| 511 | 515 | .stop = ehci_stop, |
| 512 | 516 | .shutdown = ehci_shutdown, |
| @@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd) · 105 unmodified lines | ||
| 106 | 106 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 107 | 107 | int retval; |
| 108 | 108 | |
| 109 | − hcd->has_tt = 1; | |
| 110 | − | |
| 111 | − retval = ehci_halt(ehci); | |
| 112 | − if (retval) | |
| 113 | − return retval; | |
| 114 | − | |
| 115 | − /* | |
| 116 | − * data structure init | |
| 117 | − */ | |
| 118 | − retval = ehci_init(hcd); | |
| 109 | + retval = ehci_setup(hcd); | |
| 119 | 110 | if (retval) |
| 120 | 111 | return retval; |
| 121 | 112 | |
| 122 | − ehci_reset(ehci); | |
| 123 | − | |
| 124 | 113 | ehci_port_power(ehci, 0); |
| 125 | 114 | |
| 126 | 115 | return retval; |
| @@ -261,11 +250,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) · 134 unmodified lines | ||
| 261 | 250 | |
| 262 | 251 | ehci = hcd_to_ehci(hcd); |
| 263 | 252 | ehci->caps = hcd->regs + 0x100; |
| 264 | − ehci->regs = hcd->regs + 0x100 + | |
| 265 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 266 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 267 | 253 | hcd->has_tt = 1; |
| 268 | − ehci->sbrn = 0x20; | |
| 269 | 254 | |
| 270 | 255 | /* |
| 271 | 256 | * (Re-)program MBUS remapping windows if we are asked to. |
| @@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 53 unmodified lines | ||
| 54 | 54 | u32 temp; |
| 55 | 55 | int retval; |
| 56 | 56 | |
| 57 | + ehci->caps = hcd->regs; | |
| 58 | + | |
| 59 | + /* | |
| 60 | + * ehci_init() causes memory for DMA transfers to be | |
| 61 | + * allocated. Thus, any vendor-specific workarounds based on | |
| 62 | + * limiting the type of memory used for DMA transfers must | |
| 63 | + * happen before ehci_setup() is called. | |
| 64 | + * | |
| 65 | + * Most other workarounds can be done either before or after | |
| 66 | + * init and reset; they are located here too. | |
| 67 | + */ | |
| 57 | 68 | switch (pdev->vendor) { |
| 58 | 69 | case PCI_VENDOR_ID_TOSHIBA_2: |
| 59 | 70 | /* celleb's companion chip */ |
| @@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 6 unmodified lines | ||
| 66 | 77 | #endif |
| 67 | 78 | } |
| 68 | 79 | break; |
| 69 | − } | |
| 70 | − | |
| 71 | − ehci->caps = hcd->regs; | |
| 72 | − ehci->regs = hcd->regs + | |
| 73 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 74 | − | |
| 75 | − dbg_hcs_params(ehci, "reset"); | |
| 76 | − dbg_hcc_params(ehci, "reset"); | |
| 77 | − | |
| 78 | − /* ehci_init() causes memory for DMA transfers to be | |
| 79 | − * allocated. Thus, any vendor-specific workarounds based on | |
| 80 | − * limiting the type of memory used for DMA transfers must | |
| 81 | − * happen before ehci_init() is called. */ | |
| 82 | − switch (pdev->vendor) { | |
| 83 | 80 | case PCI_VENDOR_ID_NVIDIA: |
| 84 | 81 | /* NVidia reports that certain chips don't handle |
| 85 | 82 | * QH, ITD, or SITD addresses above 2GB. (But TD, |
| @@ -95,61 +92,24 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 9 unmodified lines | ||
| 95 | 92 | ehci_warn(ehci, "can't enable NVidia " |
| 96 | 93 | "workaround for >2GB RAM\n"); |
| 97 | 94 | break; |
| 98 | − } | |
| 99 | − break; | |
| 100 | − } | |
| 101 | − | |
| 102 | − /* cache this readonly data; minimize chip reads */ | |
| 103 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 104 | − | |
| 105 | − retval = ehci_halt(ehci); | |
| 106 | − if (retval) | |
| 107 | − return retval; | |
| 108 | 95 | |
| 109 | − if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) || | |
| 110 | − (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) { | |
| 111 | − /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may | |
| 112 | − * read/write memory space which does not belong to it when | |
| 113 | − * there is NULL pointer with T-bit set to 1 in the frame list | |
| 114 | − * table. To avoid the issue, the frame list link pointer | |
| 115 | − * should always contain a valid pointer to a inactive qh. | |
| 96 | + /* Some NForce2 chips have problems with selective suspend; | |
| 97 | + * fixed in newer silicon. | |
| 116 | 98 | */ |
| 117 | − ehci->use_dummy_qh = 1; | |
| 118 | − ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI " | |
| 119 | − "dummy qh workaround\n"); | |
| 120 | − } | |
| 121 | − | |
| 122 | − /* data structure init */ | |
| 123 | − retval = ehci_init(hcd); | |
| 124 | − if (retval) | |
| 125 | − return retval; | |
| 126 | − | |
| 127 | − switch (pdev->vendor) { | |
| 128 | − case PCI_VENDOR_ID_NEC: | |
| 129 | − ehci->need_io_watchdog = 0; | |
| 99 | + case 0x0068: | |
| 100 | + if (pdev->revision < 0xa4) | |
| 101 | + ehci->no_selective_suspend = 1; | |
| 102 | + break; | |
| 103 | + } | |
| 130 | 104 | break; |
| 131 | 105 | case PCI_VENDOR_ID_INTEL: |
| 132 | − ehci->need_io_watchdog = 0; | |
| 133 | 106 | ehci->fs_i_thresh = 1; |
| 134 | − if (pdev->device == 0x27cc) { | |
| 135 | − ehci->broken_periodic = 1; | |
| 136 | − ehci_info(ehci, "using broken periodic workaround\n"); | |
| 137 | − } | |
| 138 | − if (pdev->device == 0x0806 || pdev->device == 0x0811 | |
| 139 | − || pdev->device == 0x0829) { | |
| 140 | − ehci_info(ehci, "disable lpm for langwell/penwell\n"); | |
| 141 | − ehci->has_lpm = 0; | |
| 142 | − } | |
| 143 | − if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) { | |
| 107 | + if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) | |
| 144 | 108 | hcd->has_tt = 1; |
| 145 | − tdi_reset(ehci); | |
| 146 | − } | |
| 147 | 109 | break; |
| 148 | 110 | case PCI_VENDOR_ID_TDI: |
| 149 | − if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | |
| 111 | + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) | |
| 150 | 112 | hcd->has_tt = 1; |
| 151 | − tdi_reset(ehci); | |
| 152 | − } | |
| 153 | 113 | break; |
| 154 | 114 | case PCI_VENDOR_ID_AMD: |
| 155 | 115 | /* AMD PLL quirk */ |
| @@ -161,28 +121,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 5 unmodified lines | ||
| 161 | 121 | retval = -EIO; |
| 162 | 122 | goto done; |
| 163 | 123 | } |
| 164 | − break; | |
| 165 | − case PCI_VENDOR_ID_NVIDIA: | |
| 166 | − switch (pdev->device) { | |
| 167 | − /* Some NForce2 chips have problems with selective suspend; | |
| 168 | − * fixed in newer silicon. | |
| 169 | − */ | |
| 170 | − case 0x0068: | |
| 171 | − if (pdev->revision < 0xa4) | |
| 172 | − ehci->no_selective_suspend = 1; | |
| 173 | − break; | |
| 174 | 124 | |
| 175 | − /* MCP89 chips on the MacBookAir3,1 give EPROTO when | |
| 176 | − * fetching device descriptors unless LPM is disabled. | |
| 177 | − * There are also intermittent problems enumerating | |
| 178 | − * devices with PPCD enabled. | |
| 125 | + /* | |
| 126 | + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may | |
| 127 | + * read/write memory space which does not belong to it when | |
| 128 | + * there is NULL pointer with T-bit set to 1 in the frame list | |
| 129 | + * table. To avoid the issue, the frame list link pointer | |
| 130 | + * should always contain a valid pointer to a inactive qh. | |
| 179 | 131 | */ |
| 180 | − case 0x0d9d: | |
| 181 | − ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); | |
| 182 | − ehci->has_lpm = 0; | |
| 183 | − ehci->has_ppcd = 0; | |
| 184 | − ehci->command &= ~CMD_PPCEE; | |
| 185 | − break; | |
| 132 | + if (pdev->device == 0x7808) { | |
| 133 | + ehci->use_dummy_qh = 1; | |
| 134 | + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); | |
| 186 | 135 | } |
| 187 | 136 | break; |
| 188 | 137 | case PCI_VENDOR_ID_VIA: |
| @@ -203,6 +152,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 14 unmodified lines | ||
| 203 | 152 | /* AMD PLL quirk */ |
| 204 | 153 | if (usb_amd_find_chipset_info()) |
| 205 | 154 | ehci->amd_pll_fix = 1; |
| 155 | + | |
| 156 | + /* | |
| 157 | + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may | |
| 158 | + * read/write memory space which does not belong to it when | |
| 159 | + * there is NULL pointer with T-bit set to 1 in the frame list | |
| 160 | + * table. To avoid the issue, the frame list link pointer | |
| 161 | + * should always contain a valid pointer to a inactive qh. | |
| 162 | + */ | |
| 163 | + if (pdev->device == 0x4396) { | |
| 164 | + ehci->use_dummy_qh = 1; | |
| 165 | + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); | |
| 166 | + } | |
| 206 | 167 | /* SB600 and old version of SB700 have a bug in EHCI controller, |
| 207 | 168 | * which causes usb devices lose response in some cases. |
| 208 | 169 | */ |
| @@ -231,6 +192,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 22 unmodified lines | ||
| 231 | 192 | break; |
| 232 | 193 | } |
| 233 | 194 | |
| 195 | + retval = ehci_setup(hcd); | |
| 196 | + if (retval) | |
| 197 | + return retval; | |
| 198 | + | |
| 199 | + /* These workarounds need to be applied after ehci_setup() */ | |
| 200 | + switch (pdev->vendor) { | |
| 201 | + case PCI_VENDOR_ID_NEC: | |
| 202 | + ehci->need_io_watchdog = 0; | |
| 203 | + break; | |
| 204 | + case PCI_VENDOR_ID_INTEL: | |
| 205 | + ehci->need_io_watchdog = 0; | |
| 206 | + if (pdev->device == 0x0806 || pdev->device == 0x0811 | |
| 207 | + || pdev->device == 0x0829) { | |
| 208 | + ehci_info(ehci, "disable lpm for langwell/penwell\n"); | |
| 209 | + ehci->has_lpm = 0; | |
| 210 | + } | |
| 211 | + break; | |
| 212 | + case PCI_VENDOR_ID_NVIDIA: | |
| 213 | + switch (pdev->device) { | |
| 214 | + /* MCP89 chips on the MacBookAir3,1 give EPROTO when | |
| 215 | + * fetching device descriptors unless LPM is disabled. | |
| 216 | + * There are also intermittent problems enumerating | |
| 217 | + * devices with PPCD enabled. | |
| 218 | + */ | |
| 219 | + case 0x0d9d: | |
| 220 | + ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); | |
| 221 | + ehci->has_lpm = 0; | |
| 222 | + ehci->has_ppcd = 0; | |
| 223 | + ehci->command &= ~CMD_PPCEE; | |
| 224 | + break; | |
| 225 | + } | |
| 226 | + break; | |
| 227 | + } | |
| 228 | + | |
| 234 | 229 | /* optional debug port, normally in the first BAR */ |
| 235 | 230 | temp = pci_find_capability(pdev, 0x0a); |
| 236 | 231 | if (temp) { |
| @@ -238,7 +233,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 1 unmodified line | ||
| 238 | 233 | temp >>= 16; |
| 239 | 234 | if ((temp & (3 << 13)) == (1 << 13)) { |
| 240 | 235 | temp &= 0x1fff; |
| 241 | − ehci->debug = ehci_to_hcd(ehci)->regs + temp; | |
| 236 | + ehci->debug = hcd->regs + temp; | |
| 242 | 237 | temp = ehci_readl(ehci, &ehci->debug->control); |
| 243 | 238 | ehci_info(ehci, "debug port %d%s\n", |
| 244 | 239 | HCS_DEBUG_PORT(ehci->hcs_params), |
| @@ -250,8 +245,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 5 unmodified lines | ||
| 250 | 245 | } |
| 251 | 246 | } |
| 252 | 247 | |
| 253 | − ehci_reset(ehci); | |
| 254 | − | |
| 255 | 248 | /* at least the Genesys GL880S needs fixup here */ |
| 256 | 249 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); |
| 257 | 250 | temp &= 0x0f; |
| @@ -275,10 +268,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 17 unmodified lines | ||
| 275 | 268 | } |
| 276 | 269 | |
| 277 | 270 | /* Serial Bus Release Number is at PCI 0x60 offset */ |
| 278 | − pci_read_config_byte(pdev, 0x60, &ehci->sbrn); | |
| 279 | 271 | if (pdev->vendor == PCI_VENDOR_ID_STMICRO |
| 280 | 272 | && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) |
| 281 | − ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ | |
| 273 | + ; /* ConneXT has no sbrn register */ | |
| 274 | + else | |
| 275 | + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); | |
| 282 | 276 | |
| 283 | 277 | /* Keep this around for a while just in case some EHCI |
| 284 | 278 | * implementation uses legacy PCI PM support. This test |
| @@ -331,29 +325,7 @@ done: · 46 unmodified lines | ||
| 331 | 325 | |
| 332 | 326 | static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
| 333 | 327 | { |
| 334 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 335 | − unsigned long flags; | |
| 336 | − int rc = 0; | |
| 337 | − | |
| 338 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 339 | − msleep(10); | |
| 340 | − | |
| 341 | − /* Root hub was already suspended. Disable irq emission and | |
| 342 | − * mark HW unaccessible. The PM and USB cores make sure that | |
| 343 | − * the root hub is either suspended or stopped. | |
| 344 | − */ | |
| 345 | − ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); | |
| 346 | − spin_lock_irqsave (&ehci->lock, flags); | |
| 347 | − ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 348 | − (void)ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 349 | − | |
| 350 | − clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 351 | − spin_unlock_irqrestore (&ehci->lock, flags); | |
| 352 | − | |
| 353 | − // could save FLADJ in case of Vaux power loss | |
| 354 | − // ... we'd only use it to handle clock skew | |
| 355 | − | |
| 356 | − return rc; | |
| 328 | + return ehci_suspend(hcd, do_wakeup); | |
| 357 | 329 | } |
| 358 | 330 | |
| 359 | 331 | static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) |
| @@ -402,54 +374,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) · 42 unmodified lines | ||
| 402 | 374 | if (usb_is_intel_switchable_ehci(pdev)) |
| 403 | 375 | ehci_enable_xhci_companion(); |
| 404 | 376 | |
| 405 | − // maybe restore FLADJ | |
| 406 | − | |
| 407 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 408 | − msleep(100); | |
| 409 | − | |
| 410 | − /* Mark hardware accessible again as we are out of D3 state by now */ | |
| 411 | − set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 412 | − | |
| 413 | − /* If CF is still set and we aren't resuming from hibernation | |
| 414 | − * then we maintained PCI Vaux power. | |
| 415 | − * Just undo the effect of ehci_pci_suspend(). | |
| 416 | − */ | |
| 417 | − if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && | |
| 418 | − !hibernated) { | |
| 419 | − int mask = INTR_MASK; | |
| 420 | − | |
| 421 | − ehci_prepare_ports_for_controller_resume(ehci); | |
| 422 | − if (!hcd->self.root_hub->do_remote_wakeup) | |
| 423 | − mask &= ~STS_PCD; | |
| 424 | − ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 425 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 426 | − return 0; | |
| 427 | − } | |
| 428 | − | |
| 429 | − usb_root_hub_lost_power(hcd->self.root_hub); | |
| 430 | − | |
| 431 | − /* Else reset, to cope with power loss or flush-to-storage | |
| 432 | − * style "resume" having let BIOS kick in during reboot. | |
| 433 | − */ | |
| 434 | − (void) ehci_halt(ehci); | |
| 435 | − (void) ehci_reset(ehci); | |
| 436 | − (void) ehci_pci_reinit(ehci, pdev); | |
| 437 | − | |
| 438 | − /* emptying the schedule aborts any urbs */ | |
| 439 | − spin_lock_irq(&ehci->lock); | |
| 440 | − if (ehci->reclaim) | |
| 441 | − end_unlink_async(ehci); | |
| 442 | − ehci_work(ehci); | |
| 443 | − spin_unlock_irq(&ehci->lock); | |
| 444 | − | |
| 445 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 446 | − ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 447 | − ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 448 | − | |
| 449 | − /* here we "know" root ports should always stay powered */ | |
| 450 | − ehci_port_power(ehci, 1); | |
| 451 | − | |
| 452 | − ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 377 | + if (ehci_resume(hcd, hibernated) != 0) | |
| 378 | + (void) ehci_pci_reinit(ehci, pdev); | |
| 453 | 379 | return 0; |
| 454 | 380 | } |
| 455 | 381 | #endif |
| @@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) · 152 unmodified lines | ||
| 153 | 153 | static int ehci_platform_suspend(struct device *dev) |
| 154 | 154 | { |
| 155 | 155 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 156 | − bool wakeup = device_may_wakeup(dev); | |
| 156 | + bool do_wakeup = device_may_wakeup(dev); | |
| 157 | 157 | |
| 158 | − ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup); | |
| 159 | − return 0; | |
| 158 | + return ehci_suspend(hcd, do_wakeup); | |
| 160 | 159 | } |
| 161 | 160 | |
| 162 | 161 | static int ehci_platform_resume(struct device *dev) |
| 163 | 162 | { |
| 164 | 163 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 165 | 164 | |
| 166 | − ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); | |
| 165 | + ehci_resume(hcd, false); | |
| 167 | 166 | return 0; |
| 168 | 167 | } |
| 169 | 168 | |
| @@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd) · 77 unmodified lines | ||
| 78 | 78 | { |
| 79 | 79 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 80 | 80 | int retval; |
| 81 | + | |
| 81 | 82 | ehci->big_endian_mmio = 1; |
| 82 | 83 | ehci->big_endian_desc = 1; |
| 83 | 84 | |
| 84 | 85 | ehci->caps = hcd->regs; |
| 85 | − ehci->regs = hcd->regs + | |
| 86 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 87 | − dbg_hcs_params(ehci, "reset"); | |
| 88 | − dbg_hcc_params(ehci, "reset"); | |
| 89 | − | |
| 90 | − /* cache this readonly data; minimize chip reads */ | |
| 91 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 92 | 86 | hcd->has_tt = 1; |
| 93 | 87 | |
| 94 | − retval = ehci_halt(ehci); | |
| 95 | − if (retval) | |
| 96 | − return retval; | |
| 97 | − | |
| 98 | − ehci_reset(ehci); | |
| 99 | − | |
| 100 | − /* data structure init */ | |
| 101 | − retval = ehci_init(hcd); | |
| 88 | + retval = ehci_setup(hcd); | |
| 102 | 89 | if (retval) |
| 103 | 90 | return retval; |
| 104 | 91 | |
| @@ -17,24 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/of.h> |
| 18 | 18 | #include <linux/of_platform.h> |
| 19 | 19 | |
| 20 | −/* called during probe() after chip reset completes */ | |
| 21 | −static int ehci_ppc_of_setup(struct usb_hcd *hcd) | |
| 22 | −{ | |
| 23 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 24 | − int retval; | |
| 25 | − | |
| 26 | − retval = ehci_halt(ehci); | |
| 27 | − if (retval) | |
| 28 | − return retval; | |
| 29 | − | |
| 30 | − retval = ehci_init(hcd); | |
| 31 | − if (retval) | |
| 32 | − return retval; | |
| 33 | − | |
| 34 | − ehci->sbrn = 0x20; | |
| 35 | − return ehci_reset(ehci); | |
| 36 | −} | |
| 37 | − | |
| 38 | 20 | |
| 39 | 21 | static const struct hc_driver ehci_ppc_of_hc_driver = { |
| 40 | 22 | .description = hcd_name, |
| @@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { · 9 unmodified lines | ||
| 50 | 32 | /* |
| 51 | 33 | * basic lifecycle operations |
| 52 | 34 | */ |
| 53 | − .reset = ehci_ppc_of_setup, | |
| 35 | + .reset = ehci_setup, | |
| 54 | 36 | .start = ehci_run, |
| 55 | 37 | .stop = ehci_stop, |
| 56 | 38 | .shutdown = ehci_shutdown, |
| @@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) · 121 unmodified lines | ||
| 178 | 160 | ehci->big_endian_desc = 1; |
| 179 | 161 | |
| 180 | 162 | ehci->caps = hcd->regs; |
| 181 | − ehci->regs = hcd->regs + | |
| 182 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 183 | − | |
| 184 | − /* cache this readonly data; minimize chip reads */ | |
| 185 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 186 | 163 | |
| 187 | 164 | if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) { |
| 188 | 165 | rv = ppc44x_enable_bmt(dn); |
| @@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd) · 54 unmodified lines | ||
| 55 | 55 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 56 | 56 | |
| 57 | 57 | ehci->big_endian_mmio = 1; |
| 58 | − | |
| 59 | 58 | ehci->caps = hcd->regs; |
| 60 | − ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, | |
| 61 | − &ehci->caps->hc_capbase)); | |
| 62 | − | |
| 63 | − dbg_hcs_params(ehci, "reset"); | |
| 64 | − dbg_hcc_params(ehci, "reset"); | |
| 65 | − | |
| 66 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 67 | − | |
| 68 | − result = ehci_halt(ehci); | |
| 69 | 59 | |
| 60 | + result = ehci_setup(hcd); | |
| 70 | 61 | if (result) |
| 71 | 62 | return result; |
| 72 | 63 | |
| 73 | − result = ehci_init(hcd); | |
| 74 | − | |
| 75 | − if (result) | |
| 76 | − return result; | |
| 77 | − | |
| 78 | − ehci_reset(ehci); | |
| 79 | − | |
| 80 | 64 | ps3_ehci_setup_insnreg(ehci); |
| 81 | 65 | |
| 82 | 66 | return result; |
| @@ -100,7 +100,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) · 99 unmodified lines | ||
| 100 | 100 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will |
| 101 | 101 | * ever clear it. |
| 102 | 102 | */ |
| 103 | − if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { | |
| 103 | + if (!(hw->hw_info1 & cpu_to_hc32(ehci, QH_TOGGLE_CTL))) { | |
| 104 | 104 | unsigned is_out, epnum; |
| 105 | 105 | |
| 106 | 106 | is_out = qh->is_out; |
| @@ -265,7 +265,6 @@ __acquires(ehci->lock) · 158 unmodified lines | ||
| 265 | 265 | /* ... update hc-wide periodic stats (for usbfs) */ |
| 266 | 266 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; |
| 267 | 267 | } |
| 268 | − qh_put (qh); | |
| 269 | 268 | } |
| 270 | 269 | |
| 271 | 270 | if (unlikely(urb->unlinked)) { |
| @@ -294,9 +293,6 @@ __acquires(ehci->lock) · 22 unmodified lines | ||
| 294 | 293 | spin_lock (&ehci->lock); |
| 295 | 294 | } |
| 296 | 295 | |
| 297 | −static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); | |
| 298 | −static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); | |
| 299 | − | |
| 300 | 296 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); |
| 301 | 297 | |
| 302 | 298 | /* |
| @@ -326,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) · 23 unmodified lines | ||
| 326 | 322 | * |
| 327 | 323 | * It's a bug for qh->qh_state to be anything other than |
| 328 | 324 | * QH_STATE_IDLE, unless our caller is scan_async() or |
| 329 | − * scan_periodic(). | |
| 325 | + * scan_intr(). | |
| 330 | 326 | */ |
| 331 | 327 | state = qh->qh_state; |
| 332 | 328 | qh->qh_state = QH_STATE_COMPLETING; |
| @@ -434,7 +430,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) · 101 unmodified lines | ||
| 434 | 430 | |
| 435 | 431 | /* stop scanning when we reach qtds the hc is using */ |
| 436 | 432 | } else if (likely (!stopped |
| 437 | − && ehci->rh_state == EHCI_RH_RUNNING)) { | |
| 433 | + && ehci->rh_state >= EHCI_RH_RUNNING)) { | |
| 438 | 434 | break; |
| 439 | 435 | |
| 440 | 436 | /* scan the whole queue for unlinks whenever it stops */ |
| @@ -442,7 +438,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) · 1 unmodified line | ||
| 442 | 438 | stopped = 1; |
| 443 | 439 | |
| 444 | 440 | /* cancel everything if we halt, suspend, etc */ |
| 445 | − if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 441 | + if (ehci->rh_state < EHCI_RH_RUNNING) | |
| 446 | 442 | last_status = -ESHUTDOWN; |
| 447 | 443 | |
| 448 | 444 | /* this qtd is active; skip it unless a previous qtd |
| @@ -836,7 +832,6 @@ qh_make ( · 387 unmodified lines | ||
| 836 | 832 | is_input, 0, |
| 837 | 833 | hb_mult(maxp) * max_packet(maxp))); |
| 838 | 834 | qh->start = NO_FRAME; |
| 839 | − qh->stamp = ehci->periodic_stamp; | |
| 840 | 835 | |
| 841 | 836 | if (urb->dev->speed == USB_SPEED_HIGH) { |
| 842 | 837 | qh->c_usecs = 0; |
| @@ -887,7 +882,7 @@ qh_make ( · 44 unmodified lines | ||
| 887 | 882 | /* using TT? */ |
| 888 | 883 | switch (urb->dev->speed) { |
| 889 | 884 | case USB_SPEED_LOW: |
| 890 | − info1 |= (1 << 12); /* EPS "low" */ | |
| 885 | + info1 |= QH_LOW_SPEED; | |
| 891 | 886 | /* FALL THROUGH */ |
| 892 | 887 | |
| 893 | 888 | case USB_SPEED_FULL: |
| @@ -895,8 +890,8 @@ qh_make ( · 1 unmodified line | ||
| 895 | 890 | if (type != PIPE_INTERRUPT) |
| 896 | 891 | info1 |= (EHCI_TUNE_RL_TT << 28); |
| 897 | 892 | if (type == PIPE_CONTROL) { |
| 898 | − info1 |= (1 << 27); /* for TT */ | |
| 899 | − info1 |= 1 << 14; /* toggle from qtd */ | |
| 893 | + info1 |= QH_CONTROL_EP; /* for TT */ | |
| 894 | + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ | |
| 900 | 895 | } |
| 901 | 896 | info1 |= maxp << 16; |
| 902 | 897 | |
| @@ -921,11 +916,11 @@ qh_make ( · 18 unmodified lines | ||
| 921 | 916 | break; |
| 922 | 917 | |
| 923 | 918 | case USB_SPEED_HIGH: /* no TT involved */ |
| 924 | − info1 |= (2 << 12); /* EPS "high" */ | |
| 919 | + info1 |= QH_HIGH_SPEED; | |
| 925 | 920 | if (type == PIPE_CONTROL) { |
| 926 | 921 | info1 |= (EHCI_TUNE_RL_HS << 28); |
| 927 | 922 | info1 |= 64 << 16; /* usb2 fixed maxpacket */ |
| 928 | − info1 |= 1 << 14; /* toggle from qtd */ | |
| 923 | + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ | |
| 929 | 924 | info2 |= (EHCI_TUNE_MULT_HS << 30); |
| 930 | 925 | } else if (type == PIPE_BULK) { |
| 931 | 926 | info1 |= (EHCI_TUNE_RL_HS << 28); |
| @@ -946,7 +941,7 @@ qh_make ( · 14 unmodified lines | ||
| 946 | 941 | ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev, |
| 947 | 942 | urb->dev->speed); |
| 948 | 943 | done: |
| 949 | − qh_put (qh); | |
| 944 | + qh_destroy(ehci, qh); | |
| 950 | 945 | return NULL; |
| 951 | 946 | } |
| 952 | 947 | |
| @@ -965,6 +960,31 @@ done: · 12 unmodified lines | ||
| 965 | 960 | |
| 966 | 961 | /*-------------------------------------------------------------------------*/ |
| 967 | 962 | |
| 963 | +static void enable_async(struct ehci_hcd *ehci) | |
| 964 | +{ | |
| 965 | + if (ehci->async_count++) | |
| 966 | + return; | |
| 967 | + | |
| 968 | + /* Stop waiting to turn off the async schedule */ | |
| 969 | + ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_ASYNC); | |
| 970 | + | |
| 971 | + /* Don't start the schedule until ASS is 0 */ | |
| 972 | + ehci_poll_ASS(ehci); | |
| 973 | + turn_on_io_watchdog(ehci); | |
| 974 | +} | |
| 975 | + | |
| 976 | +static void disable_async(struct ehci_hcd *ehci) | |
| 977 | +{ | |
| 978 | + if (--ehci->async_count) | |
| 979 | + return; | |
| 980 | + | |
| 981 | + /* The async schedule and async_unlink list are supposed to be empty */ | |
| 982 | + WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink); | |
| 983 | + | |
| 984 | + /* Don't turn off the schedule until ASS is 1 */ | |
| 985 | + ehci_poll_ASS(ehci); | |
| 986 | +} | |
| 987 | + | |
| 968 | 988 | /* move qh (and its qtds) onto async queue; maybe enable queue. */ |
| 969 | 989 | |
| 970 | 990 | static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
| @@ -978,24 +998,11 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) · 7 unmodified lines | ||
| 978 | 998 | |
| 979 | 999 | WARN_ON(qh->qh_state != QH_STATE_IDLE); |
| 980 | 1000 | |
| 981 | − /* (re)start the async schedule? */ | |
| 982 | − head = ehci->async; | |
| 983 | − timer_action_done (ehci, TIMER_ASYNC_OFF); | |
| 984 | − if (!head->qh_next.qh) { | |
| 985 | − if (!(ehci->command & CMD_ASE)) { | |
| 986 | − /* in case a clear of CMD_ASE didn't take yet */ | |
| 987 | − (void)handshake(ehci, &ehci->regs->status, | |
| 988 | − STS_ASS, 0, 150); | |
| 989 | − ehci->command |= CMD_ASE; | |
| 990 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 991 | − /* posted write need not be known to HC yet ... */ | |
| 992 | − } | |
| 993 | − } | |
| 994 | − | |
| 995 | 1001 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ |
| 996 | 1002 | qh_refresh(ehci, qh); |
| 997 | 1003 | |
| 998 | 1004 | /* splice right after start */ |
| 1005 | + head = ehci->async; | |
| 999 | 1006 | qh->qh_next = head->qh_next; |
| 1000 | 1007 | qh->hw->hw_next = head->hw->hw_next; |
| 1001 | 1008 | wmb (); |
| @@ -1003,10 +1010,11 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) · 1 unmodified line | ||
| 1003 | 1010 | head->qh_next.qh = qh; |
| 1004 | 1011 | head->hw->hw_next = dma; |
| 1005 | 1012 | |
| 1006 | − qh_get(qh); | |
| 1007 | 1013 | qh->xacterrs = 0; |
| 1008 | 1014 | qh->qh_state = QH_STATE_LINKED; |
| 1009 | 1015 | /* qtd completions reported later by interrupt */ |
| 1016 | + | |
| 1017 | + enable_async(ehci); | |
| 1010 | 1018 | } |
| 1011 | 1019 | |
| 1012 | 1020 | /*-------------------------------------------------------------------------*/ |
| @@ -1090,7 +1098,7 @@ static struct ehci_qh *qh_append_tds ( · 77 unmodified lines | ||
| 1090 | 1098 | wmb (); |
| 1091 | 1099 | dummy->hw_token = token; |
| 1092 | 1100 | |
| 1093 | − urb->hcpriv = qh_get (qh); | |
| 1101 | + urb->hcpriv = qh; | |
| 1094 | 1102 | } |
| 1095 | 1103 | } |
| 1096 | 1104 | return qh; |
| @@ -1155,117 +1163,155 @@ submit_async ( · 58 unmodified lines | ||
| 1155 | 1163 | |
| 1156 | 1164 | /*-------------------------------------------------------------------------*/ |
| 1157 | 1165 | |
| 1158 | −/* the async qh for the qtds being reclaimed are now unlinked from the HC */ | |
| 1159 | − | |
| 1160 | −static void end_unlink_async (struct ehci_hcd *ehci) | |
| 1166 | +static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 1161 | 1167 | { |
| 1162 | − struct ehci_qh *qh = ehci->reclaim; | |
| 1163 | − struct ehci_qh *next; | |
| 1168 | + struct ehci_qh *prev; | |
| 1164 | 1169 | |
| 1165 | − iaa_watchdog_done(ehci); | |
| 1170 | + /* Add to the end of the list of QHs waiting for the next IAAD */ | |
| 1171 | + qh->qh_state = QH_STATE_UNLINK; | |
| 1172 | + if (ehci->async_unlink) | |
| 1173 | + ehci->async_unlink_last->unlink_next = qh; | |
| 1174 | + else | |
| 1175 | + ehci->async_unlink = qh; | |
| 1176 | + ehci->async_unlink_last = qh; | |
| 1166 | 1177 | |
| 1167 | − // qh->hw_next = cpu_to_hc32(qh->qh_dma); | |
| 1168 | − qh->qh_state = QH_STATE_IDLE; | |
| 1169 | − qh->qh_next.qh = NULL; | |
| 1170 | − qh_put (qh); // refcount from reclaim | |
| 1178 | + /* Unlink it from the schedule */ | |
| 1179 | + prev = ehci->async; | |
| 1180 | + while (prev->qh_next.qh != qh) | |
| 1181 | + prev = prev->qh_next.qh; | |
| 1171 | 1182 | |
| 1172 | − /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ | |
| 1173 | − next = qh->reclaim; | |
| 1174 | − ehci->reclaim = next; | |
| 1175 | − qh->reclaim = NULL; | |
| 1183 | + prev->hw->hw_next = qh->hw->hw_next; | |
| 1184 | + prev->qh_next = qh->qh_next; | |
| 1185 | + if (ehci->qh_scan_next == qh) | |
| 1186 | + ehci->qh_scan_next = qh->qh_next.qh; | |
| 1187 | +} | |
| 1176 | 1188 | |
| 1177 | − qh_completions (ehci, qh); | |
| 1189 | +static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) | |
| 1190 | +{ | |
| 1191 | + /* | |
| 1192 | + * Do nothing if an IAA cycle is already running or | |
| 1193 | + * if one will be started shortly. | |
| 1194 | + */ | |
| 1195 | + if (ehci->async_iaa || ehci->async_unlinking) | |
| 1196 | + return; | |
| 1178 | 1197 | |
| 1179 | − if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 1180 | − qh_link_async (ehci, qh); | |
| 1181 | − } else { | |
| 1182 | − /* it's not free to turn the async schedule on/off; leave it | |
| 1183 | − * active but idle for a while once it empties. | |
| 1184 | − */ | |
| 1185 | − if (ehci->rh_state == EHCI_RH_RUNNING | |
| 1186 | − && ehci->async->qh_next.qh == NULL) | |
| 1187 | − timer_action (ehci, TIMER_ASYNC_OFF); | |
| 1188 | − } | |
| 1189 | − qh_put(qh); /* refcount from async list */ | |
| 1198 | + /* Do all the waiting QHs at once */ | |
| 1199 | + ehci->async_iaa = ehci->async_unlink; | |
| 1200 | + ehci->async_unlink = NULL; | |
| 1190 | 1201 | |
| 1191 | − if (next) { | |
| 1192 | − ehci->reclaim = NULL; | |
| 1193 | − start_unlink_async (ehci, next); | |
| 1202 | + /* If the controller isn't running, we don't have to wait for it */ | |
| 1203 | + if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { | |
| 1204 | + if (!nested) /* Avoid recursion */ | |
| 1205 | + end_unlink_async(ehci); | |
| 1206 | + | |
| 1207 | + /* Otherwise start a new IAA cycle */ | |
| 1208 | + } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { | |
| 1209 | + /* Make sure the unlinks are all visible to the hardware */ | |
| 1210 | + wmb(); | |
| 1211 | + | |
| 1212 | + ehci_writel(ehci, ehci->command | CMD_IAAD, | |
| 1213 | + &ehci->regs->command); | |
| 1214 | + ehci_readl(ehci, &ehci->regs->command); | |
| 1215 | + ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true); | |
| 1194 | 1216 | } |
| 1217 | +} | |
| 1218 | + | |
| 1219 | +/* the async qh for the qtds being unlinked are now gone from the HC */ | |
| 1220 | + | |
| 1221 | +static void end_unlink_async(struct ehci_hcd *ehci) | |
| 1222 | +{ | |
| 1223 | + struct ehci_qh *qh; | |
| 1195 | 1224 | |
| 1196 | 1225 | if (ehci->has_synopsys_hc_bug) |
| 1197 | 1226 | ehci_writel(ehci, (u32) ehci->async->qh_dma, |
| 1198 | 1227 | &ehci->regs->async_next); |
| 1199 | −} | |
| 1200 | − | |
| 1201 | −/* makes sure the async qh will become idle */ | |
| 1202 | −/* caller must own ehci->lock */ | |
| 1203 | 1228 | |
| 1204 | −static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 1205 | −{ | |
| 1206 | − struct ehci_qh *prev; | |
| 1229 | + /* Process the idle QHs */ | |
| 1230 | + restart: | |
| 1231 | + ehci->async_unlinking = true; | |
| 1232 | + while (ehci->async_iaa) { | |
| 1233 | + qh = ehci->async_iaa; | |
| 1234 | + ehci->async_iaa = qh->unlink_next; | |
| 1235 | + qh->unlink_next = NULL; | |
| 1236 | + | |
| 1237 | + qh->qh_state = QH_STATE_IDLE; | |
| 1238 | + qh->qh_next.qh = NULL; | |
| 1239 | + | |
| 1240 | + qh_completions(ehci, qh); | |
| 1241 | + if (!list_empty(&qh->qtd_list) && | |
| 1242 | + ehci->rh_state == EHCI_RH_RUNNING) | |
| 1243 | + qh_link_async(ehci, qh); | |
| 1244 | + disable_async(ehci); | |
| 1245 | + } | |
| 1246 | + ehci->async_unlinking = false; | |
| 1207 | 1247 | |
| 1208 | −#ifdef DEBUG | |
| 1209 | − assert_spin_locked(&ehci->lock); | |
| 1210 | − if (ehci->reclaim | |
| 1211 | − || (qh->qh_state != QH_STATE_LINKED | |
| 1212 | − && qh->qh_state != QH_STATE_UNLINK_WAIT) | |
| 1213 | − ) | |
| 1214 | − BUG (); | |
| 1215 | −#endif | |
| 1248 | + /* Start a new IAA cycle if any QHs are waiting for it */ | |
| 1249 | + if (ehci->async_unlink) { | |
| 1250 | + start_iaa_cycle(ehci, true); | |
| 1251 | + if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) | |
| 1252 | + goto restart; | |
| 1253 | + } | |
| 1254 | +} | |
| 1216 | 1255 | |
| 1217 | − /* stop async schedule right now? */ | |
| 1218 | − if (unlikely (qh == ehci->async)) { | |
| 1219 | − /* can't get here without STS_ASS set */ | |
| 1220 | − if (ehci->rh_state != EHCI_RH_HALTED | |
| 1221 | − && !ehci->reclaim) { | |
| 1222 | − /* ... and CMD_IAAD clear */ | |
| 1223 | − ehci->command &= ~CMD_ASE; | |
| 1224 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 1225 | − wmb (); | |
| 1226 | − // handshake later, if we need to | |
| 1227 | − timer_action_done (ehci, TIMER_ASYNC_OFF); | |
| 1256 | +static void unlink_empty_async(struct ehci_hcd *ehci) | |
| 1257 | +{ | |
| 1258 | + struct ehci_qh *qh, *next; | |
| 1259 | + bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); | |
| 1260 | + bool check_unlinks_later = false; | |
| 1261 | + | |
| 1262 | + /* Unlink all the async QHs that have been empty for a timer cycle */ | |
| 1263 | + next = ehci->async->qh_next.qh; | |
| 1264 | + while (next) { | |
| 1265 | + qh = next; | |
| 1266 | + next = qh->qh_next.qh; | |
| 1267 | + | |
| 1268 | + if (list_empty(&qh->qtd_list) && | |
| 1269 | + qh->qh_state == QH_STATE_LINKED) { | |
| 1270 | + if (!stopped && qh->unlink_cycle == | |
| 1271 | + ehci->async_unlink_cycle) | |
| 1272 | + check_unlinks_later = true; | |
| 1273 | + else | |
| 1274 | + single_unlink_async(ehci, qh); | |
| 1228 | 1275 | } |
| 1229 | − return; | |
| 1230 | 1276 | } |
| 1231 | 1277 | |
| 1232 | − qh->qh_state = QH_STATE_UNLINK; | |
| 1233 | − ehci->reclaim = qh = qh_get (qh); | |
| 1278 | + /* Start a new IAA cycle if any QHs are waiting for it */ | |
| 1279 | + if (ehci->async_unlink) | |
| 1280 | + start_iaa_cycle(ehci, false); | |
| 1234 | 1281 | |
| 1235 | − prev = ehci->async; | |
| 1236 | − while (prev->qh_next.qh != qh) | |
| 1237 | − prev = prev->qh_next.qh; | |
| 1282 | + /* QHs that haven't been empty for long enough will be handled later */ | |
| 1283 | + if (check_unlinks_later) { | |
| 1284 | + ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); | |
| 1285 | + ++ehci->async_unlink_cycle; | |
| 1286 | + } | |
| 1287 | +} | |
| 1238 | 1288 | |
| 1239 | − prev->hw->hw_next = qh->hw->hw_next; | |
| 1240 | − prev->qh_next = qh->qh_next; | |
| 1241 | − if (ehci->qh_scan_next == qh) | |
| 1242 | − ehci->qh_scan_next = qh->qh_next.qh; | |
| 1243 | − wmb (); | |
| 1289 | +/* makes sure the async qh will become idle */ | |
| 1290 | +/* caller must own ehci->lock */ | |
| 1244 | 1291 | |
| 1245 | − /* If the controller isn't running, we don't have to wait for it */ | |
| 1246 | − if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) { | |
| 1247 | − /* if (unlikely (qh->reclaim != 0)) | |
| 1248 | − * this will recurse, probably not much | |
| 1249 | − */ | |
| 1250 | − end_unlink_async (ehci); | |
| 1292 | +static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 1293 | +{ | |
| 1294 | + /* | |
| 1295 | + * If the QH isn't linked then there's nothing we can do | |
| 1296 | + * unless we were called during a giveback, in which case | |
| 1297 | + * qh_completions() has to deal with it. | |
| 1298 | + */ | |
| 1299 | + if (qh->qh_state != QH_STATE_LINKED) { | |
| 1300 | + if (qh->qh_state == QH_STATE_COMPLETING) | |
| 1301 | + qh->needs_rescan = 1; | |
| 1251 | 1302 | return; |
| 1252 | 1303 | } |
| 1253 | 1304 | |
| 1254 | − ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command); | |
| 1255 | − (void)ehci_readl(ehci, &ehci->regs->command); | |
| 1256 | − iaa_watchdog_start(ehci); | |
| 1305 | + single_unlink_async(ehci, qh); | |
| 1306 | + start_iaa_cycle(ehci, false); | |
| 1257 | 1307 | } |
| 1258 | 1308 | |
| 1259 | 1309 | /*-------------------------------------------------------------------------*/ |
| 1260 | 1310 | |
| 1261 | 1311 | static void scan_async (struct ehci_hcd *ehci) |
| 1262 | 1312 | { |
| 1263 | − bool stopped; | |
| 1264 | 1313 | struct ehci_qh *qh; |
| 1265 | − enum ehci_timer_action action = TIMER_IO_WATCHDOG; | |
| 1266 | − | |
| 1267 | − timer_action_done (ehci, TIMER_ASYNC_SHRINK); | |
| 1268 | − stopped = (ehci->rh_state != EHCI_RH_RUNNING); | |
| 1314 | + bool check_unlinks_later = false; | |
| 1269 | 1315 | |
| 1270 | 1316 | ehci->qh_scan_next = ehci->async->qh_next.qh; |
| 1271 | 1317 | while (ehci->qh_scan_next) { |
| @@ -1281,33 +1327,30 @@ static void scan_async (struct ehci_hcd *ehci) · 9 unmodified lines | ||
| 1281 | 1327 | * drops the lock. That's why ehci->qh_scan_next |
| 1282 | 1328 | * always holds the next qh to scan; if the next qh |
| 1283 | 1329 | * gets unlinked then ehci->qh_scan_next is adjusted |
| 1284 | − * in start_unlink_async(). | |
| 1330 | + * in single_unlink_async(). | |
| 1285 | 1331 | */ |
| 1286 | − qh = qh_get(qh); | |
| 1287 | 1332 | temp = qh_completions(ehci, qh); |
| 1288 | − if (qh->needs_rescan) | |
| 1289 | − unlink_async(ehci, qh); | |
| 1290 | − qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES; | |
| 1291 | − qh_put(qh); | |
| 1292 | − if (temp != 0) | |
| 1333 | + if (qh->needs_rescan) { | |
| 1334 | + start_unlink_async(ehci, qh); | |
| 1335 | + } else if (list_empty(&qh->qtd_list) | |
| 1336 | + && qh->qh_state == QH_STATE_LINKED) { | |
| 1337 | + qh->unlink_cycle = ehci->async_unlink_cycle; | |
| 1338 | + check_unlinks_later = true; | |
| 1339 | + } else if (temp != 0) | |
| 1293 | 1340 | goto rescan; |
| 1294 | 1341 | } |
| 1342 | + } | |
| 1295 | 1343 | |
| 1296 | − /* unlink idle entries, reducing DMA usage as well | |
| 1297 | − * as HCD schedule-scanning costs. delay for any qh | |
| 1298 | − * we just scanned, there's a not-unusual case that it | |
| 1299 | − * doesn't stay idle for long. | |
| 1300 | − * (plus, avoids some kind of re-activation race.) | |
| 1301 | − */ | |
| 1302 | − if (list_empty(&qh->qtd_list) | |
| 1303 | − && qh->qh_state == QH_STATE_LINKED) { | |
| 1304 | − if (!ehci->reclaim && (stopped || | |
| 1305 | − time_after_eq(jiffies, qh->unlink_time))) | |
| 1306 | − start_unlink_async(ehci, qh); | |
| 1307 | − else | |
| 1308 | − action = TIMER_ASYNC_SHRINK; | |
| 1309 | − } | |
| 1344 | + /* | |
| 1345 | + * Unlink empty entries, reducing DMA usage as well | |
| 1346 | + * as HCD schedule-scanning costs. Delay for any qh | |
| 1347 | + * we just scanned, there's a not-unusual case that it | |
| 1348 | + * doesn't stay idle for long. | |
| 1349 | + */ | |
| 1350 | + if (check_unlinks_later && ehci->rh_state == EHCI_RH_RUNNING && | |
| 1351 | + !(ehci->enabled_hrtimer_events & | |
| 1352 | + BIT(EHCI_HRTIMER_ASYNC_UNLINKS))) { | |
| 1353 | + ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); | |
| 1354 | + ++ehci->async_unlink_cycle; | |
| 1310 | 1355 | } |
| 1311 | − if (action == TIMER_ASYNC_SHRINK) | |
| 1312 | − timer_action (ehci, TIMER_ASYNC_SHRINK); | |
| 1313 | 1356 | } |
| @@ -13,7 +13,9 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #include <linux/clk.h> |
| 16 | +#include <linux/of.h> | |
| 16 | 17 | #include <linux/platform_device.h> |
| 18 | +#include <linux/of_gpio.h> | |
| 17 | 19 | #include <plat/ehci.h> |
| 18 | 20 | #include <plat/usb-phy.h> |
| 19 | 21 | |
| @@ -40,7 +42,7 @@ static const struct hc_driver s5p_ehci_hc_driver = { · 20 unmodified lines | ||
| 40 | 42 | .irq = ehci_irq, |
| 41 | 43 | .flags = HCD_MEMORY | HCD_USB2, |
| 42 | 44 | |
| 43 | − .reset = ehci_init, | |
| 45 | + .reset = ehci_setup, | |
| 44 | 46 | .start = ehci_run, |
| 45 | 47 | .stop = ehci_stop, |
| 46 | 48 | .shutdown = ehci_shutdown, |
| @@ -63,6 +65,26 @@ static const struct hc_driver s5p_ehci_hc_driver = { · 16 unmodified lines | ||
| 63 | 65 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, |
| 64 | 66 | }; |
| 65 | 67 | |
| 68 | +static void s5p_setup_vbus_gpio(struct platform_device *pdev) | |
| 69 | +{ | |
| 70 | + int err; | |
| 71 | + int gpio; | |
| 72 | + | |
| 73 | + if (!pdev->dev.of_node) | |
| 74 | + return; | |
| 75 | + | |
| 76 | + gpio = of_get_named_gpio(pdev->dev.of_node, | |
| 77 | + "samsung,vbus-gpio", 0); | |
| 78 | + if (!gpio_is_valid(gpio)) | |
| 79 | + return; | |
| 80 | + | |
| 81 | + err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio"); | |
| 82 | + if (err) | |
| 83 | + dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio); | |
| 84 | +} | |
| 85 | + | |
| 86 | +static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); | |
| 87 | + | |
| 66 | 88 | static int __devinit s5p_ehci_probe(struct platform_device *pdev) |
| 67 | 89 | { |
| 68 | 90 | struct s5p_ehci_platdata *pdata; |
| @@ -79,7 +101,20 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 79 | 101 | return -EINVAL; |
| 80 | 102 | } |
| 81 | 103 | |
| 82 | − s5p_ehci = kzalloc(sizeof(struct s5p_ehci_hcd), GFP_KERNEL); | |
| 104 | + /* | |
| 105 | + * Right now device-tree probed devices don't get dma_mask set. | |
| 106 | + * Since shared usb code relies on it, set it here for now. | |
| 107 | + * Once we move to full device tree support this will vanish off. | |
| 108 | + */ | |
| 109 | + if (!pdev->dev.dma_mask) | |
| 110 | + pdev->dev.dma_mask = &ehci_s5p_dma_mask; | |
| 111 | + if (!pdev->dev.coherent_dma_mask) | |
| 112 | + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | |
| 113 | + | |
| 114 | + s5p_setup_vbus_gpio(pdev); | |
| 115 | + | |
| 116 | + s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd), | |
| 117 | + GFP_KERNEL); | |
| 83 | 118 | if (!s5p_ehci) |
| 84 | 119 | return -ENOMEM; |
| 85 | 120 | |
| @@ -89,8 +124,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 89 | 124 | dev_name(&pdev->dev)); |
| 90 | 125 | if (!hcd) { |
| 91 | 126 | dev_err(&pdev->dev, "Unable to create HCD\n"); |
| 92 | − err = -ENOMEM; | |
| 93 | − goto fail_hcd; | |
| 127 | + return -ENOMEM; | |
| 94 | 128 | } |
| 95 | 129 | |
| 96 | 130 | s5p_ehci->hcd = hcd; |
| @@ -115,7 +149,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 18 unmodified lines | ||
| 115 | 149 | |
| 116 | 150 | hcd->rsrc_start = res->start; |
| 117 | 151 | hcd->rsrc_len = resource_size(res); |
| 118 | − hcd->regs = ioremap(res->start, resource_size(res)); | |
| 152 | + hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); | |
| 119 | 153 | if (!hcd->regs) { |
| 120 | 154 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); |
| 121 | 155 | err = -ENOMEM; |
| @@ -126,7 +160,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 126 | 160 | if (!irq) { |
| 127 | 161 | dev_err(&pdev->dev, "Failed to get IRQ\n"); |
| 128 | 162 | err = -ENODEV; |
| 129 | − goto fail; | |
| 163 | + goto fail_io; | |
| 130 | 164 | } |
| 131 | 165 | |
| 132 | 166 | if (pdata->phy_init) |
| @@ -134,40 +168,26 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 134 | 168 | |
| 135 | 169 | ehci = hcd_to_ehci(hcd); |
| 136 | 170 | ehci->caps = hcd->regs; |
| 137 | − ehci->regs = hcd->regs + | |
| 138 | − HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); | |
| 139 | 171 | |
| 140 | 172 | /* DMA burst Enable */ |
| 141 | 173 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); |
| 142 | 174 | |
| 143 | − dbg_hcs_params(ehci, "reset"); | |
| 144 | − dbg_hcc_params(ehci, "reset"); | |
| 145 | − | |
| 146 | − /* cache this readonly data; minimize chip reads */ | |
| 147 | − ehci->hcs_params = readl(&ehci->caps->hcs_params); | |
| 148 | − | |
| 149 | − ehci_reset(ehci); | |
| 150 | − | |
| 151 | 175 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 152 | 176 | if (err) { |
| 153 | 177 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
| 154 | − goto fail; | |
| 178 | + goto fail_io; | |
| 155 | 179 | } |
| 156 | 180 | |
| 157 | 181 | platform_set_drvdata(pdev, s5p_ehci); |
| 158 | 182 | |
| 159 | 183 | return 0; |
| 160 | 184 | |
| 161 | −fail: | |
| 162 | − iounmap(hcd->regs); | |
| 163 | 185 | fail_io: |
| 164 | 186 | clk_disable(s5p_ehci->clk); |
| 165 | 187 | fail_clken: |
| 166 | 188 | clk_put(s5p_ehci->clk); |
| 167 | 189 | fail_clk: |
| 168 | 190 | usb_put_hcd(hcd); |
| 169 | −fail_hcd: | |
| 170 | − kfree(s5p_ehci); | |
| 171 | 191 | return err; |
| 172 | 192 | } |
| 173 | 193 | |
| @@ -182,13 +202,10 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 182 | 202 | if (pdata && pdata->phy_exit) |
| 183 | 203 | pdata->phy_exit(pdev, S5P_USB_PHY_HOST); |
| 184 | 204 | |
| 185 | − iounmap(hcd->regs); | |
| 186 | − | |
| 187 | 205 | clk_disable(s5p_ehci->clk); |
| 188 | 206 | clk_put(s5p_ehci->clk); |
| 189 | 207 | |
| 190 | 208 | usb_put_hcd(hcd); |
| 191 | − kfree(s5p_ehci); | |
| 192 | 209 | |
| 193 | 210 | return 0; |
| 194 | 211 | } |
| @@ -207,27 +224,12 @@ static int s5p_ehci_suspend(struct device *dev) · 12 unmodified lines | ||
| 207 | 224 | { |
| 208 | 225 | struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); |
| 209 | 226 | struct usb_hcd *hcd = s5p_ehci->hcd; |
| 210 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 227 | + bool do_wakeup = device_may_wakeup(dev); | |
| 211 | 228 | struct platform_device *pdev = to_platform_device(dev); |
| 212 | 229 | struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; |
| 213 | − unsigned long flags; | |
| 214 | − int rc = 0; | |
| 215 | − | |
| 216 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 217 | − msleep(20); | |
| 218 | − | |
| 219 | − /* | |
| 220 | − * Root hub was already suspended. Disable irq emission and | |
| 221 | − * mark HW unaccessible. The PM and USB cores make sure that | |
| 222 | − * the root hub is either suspended or stopped. | |
| 223 | − */ | |
| 224 | − ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); | |
| 225 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 226 | − ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 227 | − (void)ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 230 | + int rc; | |
| 228 | 231 | |
| 229 | − clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 230 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 232 | + rc = ehci_suspend(hcd, do_wakeup); | |
| 231 | 233 | |
| 232 | 234 | if (pdata && pdata->phy_exit) |
| 233 | 235 | pdata->phy_exit(pdev, S5P_USB_PHY_HOST); |
| @@ -241,7 +243,6 @@ static int s5p_ehci_resume(struct device *dev) · 7 unmodified lines | ||
| 241 | 243 | { |
| 242 | 244 | struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); |
| 243 | 245 | struct usb_hcd *hcd = s5p_ehci->hcd; |
| 244 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 245 | 246 | struct platform_device *pdev = to_platform_device(dev); |
| 246 | 247 | struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; |
| 247 | 248 | |
| @@ -253,44 +254,7 @@ static int s5p_ehci_resume(struct device *dev) · 5 unmodified lines | ||
| 253 | 254 | /* DMA burst Enable */ |
| 254 | 255 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); |
| 255 | 256 | |
| 256 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 257 | − msleep(100); | |
| 258 | − | |
| 259 | − /* Mark hardware accessible again as we are out of D3 state by now */ | |
| 260 | − set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 261 | − | |
| 262 | − if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | |
| 263 | − int mask = INTR_MASK; | |
| 264 | − | |
| 265 | − ehci_prepare_ports_for_controller_resume(ehci); | |
| 266 | − if (!hcd->self.root_hub->do_remote_wakeup) | |
| 267 | − mask &= ~STS_PCD; | |
| 268 | − ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 269 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 270 | − return 0; | |
| 271 | − } | |
| 272 | − | |
| 273 | − usb_root_hub_lost_power(hcd->self.root_hub); | |
| 274 | − | |
| 275 | − (void) ehci_halt(ehci); | |
| 276 | − (void) ehci_reset(ehci); | |
| 277 | − | |
| 278 | − /* emptying the schedule aborts any urbs */ | |
| 279 | − spin_lock_irq(&ehci->lock); | |
| 280 | − if (ehci->reclaim) | |
| 281 | − end_unlink_async(ehci); | |
| 282 | − ehci_work(ehci); | |
| 283 | − spin_unlock_irq(&ehci->lock); | |
| 284 | − | |
| 285 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 286 | − ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 287 | − ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 288 | − | |
| 289 | − /* here we "know" root ports should always stay powered */ | |
| 290 | − ehci_port_power(ehci, 1); | |
| 291 | − | |
| 292 | − ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 293 | − | |
| 257 | + ehci_resume(hcd, false); | |
| 294 | 258 | return 0; |
| 295 | 259 | } |
| 296 | 260 | #else |
| @@ -303,6 +267,14 @@ static const struct dev_pm_ops s5p_ehci_pm_ops = { · 6 unmodified lines | ||
| 303 | 267 | .resume = s5p_ehci_resume, |
| 304 | 268 | }; |
| 305 | 269 | |
| 270 | +#ifdef CONFIG_OF | |
| 271 | +static const struct of_device_id exynos_ehci_match[] = { | |
| 272 | + { .compatible = "samsung,exynos-ehci" }, | |
| 273 | + {}, | |
| 274 | +}; | |
| 275 | +MODULE_DEVICE_TABLE(of, exynos_ehci_match); | |
| 276 | +#endif | |
| 277 | + | |
| 306 | 278 | static struct platform_driver s5p_ehci_driver = { |
| 307 | 279 | .probe = s5p_ehci_probe, |
| 308 | 280 | .remove = __devexit_p(s5p_ehci_remove), |
| @@ -311,6 +283,7 @@ static struct platform_driver s5p_ehci_driver = { · 2 unmodified lines | ||
| 311 | 283 | .name = "s5p-ehci", |
| 312 | 284 | .owner = THIS_MODULE, |
| 313 | 285 | .pm = &s5p_ehci_pm_ops, |
| 286 | + .of_match_table = of_match_ptr(exynos_ehci_match), | |
| 314 | 287 | } |
| 315 | 288 | }; |
| 316 | 289 | |
| @@ -479,70 +479,26 @@ static int tt_no_collision ( · 478 unmodified lines | ||
| 479 | 479 | |
| 480 | 480 | /*-------------------------------------------------------------------------*/ |
| 481 | 481 | |
| 482 | −static int enable_periodic (struct ehci_hcd *ehci) | |
| 482 | +static void enable_periodic(struct ehci_hcd *ehci) | |
| 483 | 483 | { |
| 484 | − int status; | |
| 485 | − | |
| 486 | − if (ehci->periodic_sched++) | |
| 487 | − return 0; | |
| 488 | − | |
| 489 | − /* did clearing PSE did take effect yet? | |
| 490 | − * takes effect only at frame boundaries... | |
| 491 | − */ | |
| 492 | − status = handshake_on_error_set_halt(ehci, &ehci->regs->status, | |
| 493 | − STS_PSS, 0, 9 * 125); | |
| 494 | − if (status) { | |
| 495 | − usb_hc_died(ehci_to_hcd(ehci)); | |
| 496 | − return status; | |
| 497 | − } | |
| 484 | + if (ehci->periodic_count++) | |
| 485 | + return; | |
| 498 | 486 | |
| 499 | − ehci->command |= CMD_PSE; | |
| 500 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 501 | − /* posted write ... PSS happens later */ | |
| 487 | + /* Stop waiting to turn off the periodic schedule */ | |
| 488 | + ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_PERIODIC); | |
| 502 | 489 | |
| 503 | − /* make sure ehci_work scans these */ | |
| 504 | − ehci->next_uframe = ehci_read_frame_index(ehci) | |
| 505 | − % (ehci->periodic_size << 3); | |
| 506 | − if (unlikely(ehci->broken_periodic)) | |
| 507 | − ehci->last_periodic_enable = ktime_get_real(); | |
| 508 | − return 0; | |
| 490 | + /* Don't start the schedule until PSS is 0 */ | |
| 491 | + ehci_poll_PSS(ehci); | |
| 492 | + turn_on_io_watchdog(ehci); | |
| 509 | 493 | } |
| 510 | 494 | |
| 511 | −static int disable_periodic (struct ehci_hcd *ehci) | |
| 495 | +static void disable_periodic(struct ehci_hcd *ehci) | |
| 512 | 496 | { |
| 513 | − int status; | |
| 514 | − | |
| 515 | − if (--ehci->periodic_sched) | |
| 516 | − return 0; | |
| 517 | − | |
| 518 | − if (unlikely(ehci->broken_periodic)) { | |
| 519 | − /* delay experimentally determined */ | |
| 520 | − ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000); | |
| 521 | − ktime_t now = ktime_get_real(); | |
| 522 | − s64 delay = ktime_us_delta(safe, now); | |
| 523 | − | |
| 524 | − if (unlikely(delay > 0)) | |
| 525 | − udelay(delay); | |
| 526 | − } | |
| 527 | − | |
| 528 | − /* did setting PSE not take effect yet? | |
| 529 | − * takes effect only at frame boundaries... | |
| 530 | − */ | |
| 531 | − status = handshake_on_error_set_halt(ehci, &ehci->regs->status, | |
| 532 | − STS_PSS, STS_PSS, 9 * 125); | |
| 533 | − if (status) { | |
| 534 | − usb_hc_died(ehci_to_hcd(ehci)); | |
| 535 | − return status; | |
| 536 | − } | |
| 537 | − | |
| 538 | − ehci->command &= ~CMD_PSE; | |
| 539 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 540 | − /* posted write ... */ | |
| 541 | − | |
| 542 | − free_cached_lists(ehci); | |
| 497 | + if (--ehci->periodic_count) | |
| 498 | + return; | |
| 543 | 499 | |
| 544 | − ehci->next_uframe = -1; | |
| 545 | − return 0; | |
| 500 | + /* Don't turn off the schedule until PSS is 1 */ | |
| 501 | + ehci_poll_PSS(ehci); | |
| 546 | 502 | } |
| 547 | 503 | |
| 548 | 504 | /*-------------------------------------------------------------------------*/ |
| @@ -553,7 +509,7 @@ static int disable_periodic (struct ehci_hcd *ehci) · 4 unmodified lines | ||
| 553 | 509 | * this just links in a qh; caller guarantees uframe masks are set right. |
| 554 | 510 | * no FSTN support (yet; ehci 0.96+) |
| 555 | 511 | */ |
| 556 | −static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 512 | +static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 557 | 513 | { |
| 558 | 514 | unsigned i; |
| 559 | 515 | unsigned period = qh->period; |
| @@ -606,28 +562,38 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) · 46 unmodified lines | ||
| 606 | 562 | } |
| 607 | 563 | qh->qh_state = QH_STATE_LINKED; |
| 608 | 564 | qh->xacterrs = 0; |
| 609 | − qh_get (qh); | |
| 610 | 565 | |
| 611 | 566 | /* update per-qh bandwidth for usbfs */ |
| 612 | 567 | ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period |
| 613 | 568 | ? ((qh->usecs + qh->c_usecs) / qh->period) |
| 614 | 569 | : (qh->usecs * 8); |
| 615 | 570 | |
| 571 | + list_add(&qh->intr_node, &ehci->intr_qh_list); | |
| 572 | + | |
| 616 | 573 | /* maybe enable periodic schedule processing */ |
| 617 | − return enable_periodic(ehci); | |
| 574 | + ++ehci->intr_count; | |
| 575 | + enable_periodic(ehci); | |
| 618 | 576 | } |
| 619 | 577 | |
| 620 | −static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 578 | +static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 621 | 579 | { |
| 622 | 580 | unsigned i; |
| 623 | 581 | unsigned period; |
| 624 | 582 | |
| 625 | − // FIXME: | |
| 626 | − // IF this isn't high speed | |
| 627 | − // and this qh is active in the current uframe | |
| 628 | − // (and overlay token SplitXstate is false?) | |
| 629 | − // THEN | |
| 630 | − // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); | |
| 583 | + /* | |
| 584 | + * If qh is for a low/full-speed device, simply unlinking it | |
| 585 | + * could interfere with an ongoing split transaction. To unlink | |
| 586 | + * it safely would require setting the QH_INACTIVATE bit and | |
| 587 | + * waiting at least one frame, as described in EHCI 4.12.2.5. | |
| 588 | + * | |
| 589 | + * We won't bother with any of this. Instead, we assume that the | |
| 590 | + * only reason for unlinking an interrupt QH while the current URB | |
| 591 | + * is still active is to dequeue all the URBs (flush the whole | |
| 592 | + * endpoint queue). | |
| 593 | + * | |
| 594 | + * If rebalancing the periodic schedule is ever implemented, this | |
| 595 | + * approach will no longer be valid. | |
| 596 | + */ | |
| 631 | 597 | |
| 632 | 598 | /* high bandwidth, or otherwise part of every microframe */ |
| 633 | 599 | if ((period = qh->period) == 0) |
| @@ -650,18 +616,15 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) · 16 unmodified lines | ||
| 650 | 616 | /* qh->qh_next still "live" to HC */ |
| 651 | 617 | qh->qh_state = QH_STATE_UNLINK; |
| 652 | 618 | qh->qh_next.ptr = NULL; |
| 653 | − qh_put (qh); | |
| 654 | 619 | |
| 655 | − /* maybe turn off periodic schedule */ | |
| 656 | − return disable_periodic(ehci); | |
| 620 | + if (ehci->qh_scan_next == qh) | |
| 621 | + ehci->qh_scan_next = list_entry(qh->intr_node.next, | |
| 622 | + struct ehci_qh, intr_node); | |
| 623 | + list_del(&qh->intr_node); | |
| 657 | 624 | } |
| 658 | 625 | |
| 659 | −static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 626 | +static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 660 | 627 | { |
| 661 | − unsigned wait; | |
| 662 | − struct ehci_qh_hw *hw = qh->hw; | |
| 663 | − int rc; | |
| 664 | − | |
| 665 | 628 | /* If the QH isn't linked then there's nothing we can do |
| 666 | 629 | * unless we were called during a giveback, in which case |
| 667 | 630 | * qh_completions() has to deal with it. |
| @@ -674,28 +637,45 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) · 6 unmodified lines | ||
| 674 | 637 | |
| 675 | 638 | qh_unlink_periodic (ehci, qh); |
| 676 | 639 | |
| 677 | − /* simple/paranoid: always delay, expecting the HC needs to read | |
| 678 | − * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and | |
| 679 | − * expect khubd to clean up after any CSPLITs we won't issue. | |
| 680 | − * active high speed queues may need bigger delays... | |
| 640 | + /* Make sure the unlinks are visible before starting the timer */ | |
| 641 | + wmb(); | |
| 642 | + | |
| 643 | + /* | |
| 644 | + * The EHCI spec doesn't say how long it takes the controller to | |
| 645 | + * stop accessing an unlinked interrupt QH. The timer delay is | |
| 646 | + * 9 uframes; presumably that will be long enough. | |
| 681 | 647 | */ |
| 682 | − if (list_empty (&qh->qtd_list) | |
| 683 | − || (cpu_to_hc32(ehci, QH_CMASK) | |
| 684 | − & hw->hw_info2) != 0) | |
| 685 | − wait = 2; | |
| 648 | + qh->unlink_cycle = ehci->intr_unlink_cycle; | |
| 649 | + | |
| 650 | + /* New entries go at the end of the intr_unlink list */ | |
| 651 | + if (ehci->intr_unlink) | |
| 652 | + ehci->intr_unlink_last->unlink_next = qh; | |
| 686 | 653 | else |
| 687 | − wait = 55; /* worst case: 3 * 1024 */ | |
| 654 | + ehci->intr_unlink = qh; | |
| 655 | + ehci->intr_unlink_last = qh; | |
| 656 | + | |
| 657 | + if (ehci->intr_unlinking) | |
| 658 | + ; /* Avoid recursive calls */ | |
| 659 | + else if (ehci->rh_state < EHCI_RH_RUNNING) | |
| 660 | + ehci_handle_intr_unlinks(ehci); | |
| 661 | + else if (ehci->intr_unlink == qh) { | |
| 662 | + ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); | |
| 663 | + ++ehci->intr_unlink_cycle; | |
| 664 | + } | |
| 665 | +} | |
| 666 | + | |
| 667 | +static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) | |
| 668 | +{ | |
| 669 | + struct ehci_qh_hw *hw = qh->hw; | |
| 670 | + int rc; | |
| 688 | 671 | |
| 689 | − udelay (wait); | |
| 690 | 672 | qh->qh_state = QH_STATE_IDLE; |
| 691 | 673 | hw->hw_next = EHCI_LIST_END(ehci); |
| 692 | − wmb (); | |
| 693 | 674 | |
| 694 | 675 | qh_completions(ehci, qh); |
| 695 | 676 | |
| 696 | 677 | /* reschedule QH iff another request is queued */ |
| 697 | − if (!list_empty(&qh->qtd_list) && | |
| 698 | − ehci->rh_state == EHCI_RH_RUNNING) { | |
| 678 | + if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 699 | 679 | rc = qh_schedule(ehci, qh); |
| 700 | 680 | |
| 701 | 681 | /* An error here likely indicates handshake failure |
| @@ -708,6 +688,10 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) · 6 unmodified lines | ||
| 708 | 688 | ehci_err(ehci, "can't reschedule qh %p, err %d\n", |
| 709 | 689 | qh, rc); |
| 710 | 690 | } |
| 691 | + | |
| 692 | + /* maybe turn off periodic schedule */ | |
| 693 | + --ehci->intr_count; | |
| 694 | + disable_periodic(ehci); | |
| 711 | 695 | } |
| 712 | 696 | |
| 713 | 697 | /*-------------------------------------------------------------------------*/ |
| @@ -884,7 +868,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) · 170 unmodified lines | ||
| 884 | 868 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); |
| 885 | 869 | |
| 886 | 870 | /* stuff into the periodic schedule */ |
| 887 | − status = qh_link_periodic (ehci, qh); | |
| 871 | + qh_link_periodic(ehci, qh); | |
| 888 | 872 | done: |
| 889 | 873 | return status; |
| 890 | 874 | } |
| @@ -944,6 +928,35 @@ done_not_linked: · 53 unmodified lines | ||
| 944 | 928 | return status; |
| 945 | 929 | } |
| 946 | 930 | |
| 931 | +static void scan_intr(struct ehci_hcd *ehci) | |
| 932 | +{ | |
| 933 | + struct ehci_qh *qh; | |
| 934 | + | |
| 935 | + list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list, | |
| 936 | + intr_node) { | |
| 937 | + rescan: | |
| 938 | + /* clean any finished work for this qh */ | |
| 939 | + if (!list_empty(&qh->qtd_list)) { | |
| 940 | + int temp; | |
| 941 | + | |
| 942 | + /* | |
| 943 | + * Unlinks could happen here; completion reporting | |
| 944 | + * drops the lock. That's why ehci->qh_scan_next | |
| 945 | + * always holds the next qh to scan; if the next qh | |
| 946 | + * gets unlinked then ehci->qh_scan_next is adjusted | |
| 947 | + * in qh_unlink_periodic(). | |
| 948 | + */ | |
| 949 | + temp = qh_completions(ehci, qh); | |
| 950 | + if (unlikely(qh->needs_rescan || | |
| 951 | + (list_empty(&qh->qtd_list) && | |
| 952 | + qh->qh_state == QH_STATE_LINKED))) | |
| 953 | + start_unlink_intr(ehci, qh); | |
| 954 | + else if (temp != 0) | |
| 955 | + goto rescan; | |
| 956 | + } | |
| 957 | + } | |
| 958 | +} | |
| 959 | + | |
| 947 | 960 | /*-------------------------------------------------------------------------*/ |
| 948 | 961 | |
| 949 | 962 | /* ehci_iso_stream ops work with both ITD and SITD */ |
| @@ -958,7 +971,6 @@ iso_stream_alloc (gfp_t mem_flags) · 8 unmodified lines | ||
| 958 | 971 | INIT_LIST_HEAD(&stream->td_list); |
| 959 | 972 | INIT_LIST_HEAD(&stream->free_list); |
| 960 | 973 | stream->next_uframe = -1; |
| 961 | − stream->refcount = 1; | |
| 962 | 974 | } |
| 963 | 975 | return stream; |
| 964 | 976 | } |
| @@ -1058,57 +1070,6 @@ iso_stream_init ( · 93 unmodified lines | ||
| 1058 | 1070 | stream->maxp = maxp; |
| 1059 | 1071 | } |
| 1060 | 1072 | |
| 1061 | −static void | |
| 1062 | −iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) | |
| 1063 | −{ | |
| 1064 | − stream->refcount--; | |
| 1065 | − | |
| 1066 | − /* free whenever just a dev->ep reference remains. | |
| 1067 | − * not like a QH -- no persistent state (toggle, halt) | |
| 1068 | − */ | |
| 1069 | − if (stream->refcount == 1) { | |
| 1070 | − // BUG_ON (!list_empty(&stream->td_list)); | |
| 1071 | − | |
| 1072 | − while (!list_empty (&stream->free_list)) { | |
| 1073 | − struct list_head *entry; | |
| 1074 | − | |
| 1075 | − entry = stream->free_list.next; | |
| 1076 | − list_del (entry); | |
| 1077 | − | |
| 1078 | − /* knows about ITD vs SITD */ | |
| 1079 | − if (stream->highspeed) { | |
| 1080 | − struct ehci_itd *itd; | |
| 1081 | − | |
| 1082 | − itd = list_entry (entry, struct ehci_itd, | |
| 1083 | − itd_list); | |
| 1084 | − dma_pool_free (ehci->itd_pool, itd, | |
| 1085 | − itd->itd_dma); | |
| 1086 | − } else { | |
| 1087 | − struct ehci_sitd *sitd; | |
| 1088 | − | |
| 1089 | − sitd = list_entry (entry, struct ehci_sitd, | |
| 1090 | − sitd_list); | |
| 1091 | − dma_pool_free (ehci->sitd_pool, sitd, | |
| 1092 | − sitd->sitd_dma); | |
| 1093 | − } | |
| 1094 | − } | |
| 1095 | − | |
| 1096 | − stream->bEndpointAddress &= 0x0f; | |
| 1097 | − if (stream->ep) | |
| 1098 | − stream->ep->hcpriv = NULL; | |
| 1099 | − | |
| 1100 | − kfree(stream); | |
| 1101 | − } | |
| 1102 | −} | |
| 1103 | − | |
| 1104 | −static inline struct ehci_iso_stream * | |
| 1105 | −iso_stream_get (struct ehci_iso_stream *stream) | |
| 1106 | −{ | |
| 1107 | − if (likely (stream != NULL)) | |
| 1108 | − stream->refcount++; | |
| 1109 | − return stream; | |
| 1110 | −} | |
| 1111 | − | |
| 1112 | 1073 | static struct ehci_iso_stream * |
| 1113 | 1074 | iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) |
| 1114 | 1075 | { |
| @@ -1129,7 +1090,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) · 14 unmodified lines | ||
| 1129 | 1090 | if (unlikely (stream == NULL)) { |
| 1130 | 1091 | stream = iso_stream_alloc(GFP_ATOMIC); |
| 1131 | 1092 | if (likely (stream != NULL)) { |
| 1132 | − /* dev->ep owns the initial refcount */ | |
| 1133 | 1093 | ep->hcpriv = stream; |
| 1134 | 1094 | stream->ep = ep; |
| 1135 | 1095 | iso_stream_init(ehci, stream, urb->dev, urb->pipe, |
| @@ -1144,9 +1104,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) · 8 unmodified lines | ||
| 1144 | 1104 | stream = NULL; |
| 1145 | 1105 | } |
| 1146 | 1106 | |
| 1147 | − /* caller guarantees an eventual matching iso_stream_put */ | |
| 1148 | − stream = iso_stream_get (stream); | |
| 1149 | − | |
| 1150 | 1107 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1151 | 1108 | return stream; |
| 1152 | 1109 | } |
| @@ -1254,17 +1211,19 @@ itd_urb_transaction ( · 101 unmodified lines | ||
| 1254 | 1211 | spin_lock_irqsave (&ehci->lock, flags); |
| 1255 | 1212 | for (i = 0; i < num_itds; i++) { |
| 1256 | 1213 | |
| 1257 | − /* free_list.next might be cache-hot ... but maybe | |
| 1258 | − * the HC caches it too. avoid that issue for now. | |
| 1214 | + /* | |
| 1215 | + * Use iTDs from the free list, but not iTDs that may | |
| 1216 | + * still be in use by the hardware. | |
| 1259 | 1217 | */ |
| 1260 | − | |
| 1261 | − /* prefer previously-allocated itds */ | |
| 1262 | − if (likely (!list_empty(&stream->free_list))) { | |
| 1263 | − itd = list_entry (stream->free_list.prev, | |
| 1218 | + if (likely(!list_empty(&stream->free_list))) { | |
| 1219 | + itd = list_first_entry(&stream->free_list, | |
| 1264 | 1220 | struct ehci_itd, itd_list); |
| 1221 | + if (itd->frame == ehci->now_frame) | |
| 1222 | + goto alloc_itd; | |
| 1265 | 1223 | list_del (&itd->itd_list); |
| 1266 | 1224 | itd_dma = itd->itd_dma; |
| 1267 | 1225 | } else { |
| 1226 | + alloc_itd: | |
| 1268 | 1227 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1269 | 1228 | itd = dma_pool_alloc (ehci->itd_pool, mem_flags, |
| 1270 | 1229 | &itd_dma); |
| @@ -1528,6 +1487,10 @@ iso_stream_schedule ( · 257 unmodified lines | ||
| 1528 | 1487 | urb->start_frame = stream->next_uframe; |
| 1529 | 1488 | if (!stream->highspeed) |
| 1530 | 1489 | urb->start_frame >>= 3; |
| 1490 | + | |
| 1491 | + /* Make sure scan_isoc() sees these */ | |
| 1492 | + if (ehci->isoc_count == 0) | |
| 1493 | + ehci->next_frame = now >> 3; | |
| 1531 | 1494 | return 0; |
| 1532 | 1495 | |
| 1533 | 1496 | fail: |
| @@ -1615,8 +1578,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) · 81 unmodified lines | ||
| 1615 | 1578 | } |
| 1616 | 1579 | |
| 1617 | 1580 | /* fit urb's itds into the selected schedule slot; activate as needed */ |
| 1618 | −static int | |
| 1619 | −itd_link_urb ( | |
| 1581 | +static void itd_link_urb( | |
| 1620 | 1582 | struct ehci_hcd *ehci, |
| 1621 | 1583 | struct urb *urb, |
| 1622 | 1584 | unsigned mod, |
| @@ -1659,7 +1621,7 @@ itd_link_urb ( · 36 unmodified lines | ||
| 1659 | 1621 | itd = list_entry (iso_sched->td_list.next, |
| 1660 | 1622 | struct ehci_itd, itd_list); |
| 1661 | 1623 | list_move_tail (&itd->itd_list, &stream->td_list); |
| 1662 | − itd->stream = iso_stream_get (stream); | |
| 1624 | + itd->stream = stream; | |
| 1663 | 1625 | itd->urb = urb; |
| 1664 | 1626 | itd_init (ehci, stream, itd); |
| 1665 | 1627 | } |
| @@ -1686,8 +1648,8 @@ itd_link_urb ( · 20 unmodified lines | ||
| 1686 | 1648 | iso_sched_free (stream, iso_sched); |
| 1687 | 1649 | urb->hcpriv = NULL; |
| 1688 | 1650 | |
| 1689 | − timer_action (ehci, TIMER_IO_WATCHDOG); | |
| 1690 | − return enable_periodic(ehci); | |
| 1651 | + ++ehci->isoc_count; | |
| 1652 | + enable_periodic(ehci); | |
| 1691 | 1653 | } |
| 1692 | 1654 | |
| 1693 | 1655 | #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) |
| @@ -1702,11 +1664,8 @@ itd_link_urb ( · 8 unmodified lines | ||
| 1702 | 1664 | * (b) only this endpoint's completions submit URBs. It seems some silicon |
| 1703 | 1665 | * corrupts things if you reuse completed descriptors very quickly... |
| 1704 | 1666 | */ |
| 1705 | −static unsigned | |
| 1706 | −itd_complete ( | |
| 1707 | − struct ehci_hcd *ehci, | |
| 1708 | − struct ehci_itd *itd | |
| 1709 | −) { | |
| 1667 | +static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) | |
| 1668 | +{ | |
| 1710 | 1669 | struct urb *urb = itd->urb; |
| 1711 | 1670 | struct usb_iso_packet_descriptor *desc; |
| 1712 | 1671 | u32 t; |
| @@ -1714,7 +1673,7 @@ itd_complete ( · 1 unmodified line | ||
| 1714 | 1673 | int urb_index = -1; |
| 1715 | 1674 | struct ehci_iso_stream *stream = itd->stream; |
| 1716 | 1675 | struct usb_device *dev; |
| 1717 | − unsigned retval = false; | |
| 1676 | + bool retval = false; | |
| 1718 | 1677 | |
| 1719 | 1678 | /* for each uframe with a packet */ |
| 1720 | 1679 | for (uframe = 0; uframe < 8; uframe++) { |
| @@ -1767,9 +1726,11 @@ itd_complete ( · 46 unmodified lines | ||
| 1767 | 1726 | ehci_urb_done(ehci, urb, 0); |
| 1768 | 1727 | retval = true; |
| 1769 | 1728 | urb = NULL; |
| 1770 | − (void) disable_periodic(ehci); | |
| 1771 | − ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | |
| 1772 | 1729 | |
| 1730 | + --ehci->isoc_count; | |
| 1731 | + disable_periodic(ehci); | |
| 1732 | + | |
| 1733 | + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | |
| 1773 | 1734 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { |
| 1774 | 1735 | if (ehci->amd_pll_fix == 1) |
| 1775 | 1736 | usb_amd_quirk_pll_enable(); |
| @@ -1783,28 +1744,20 @@ itd_complete ( · 7 unmodified lines | ||
| 1783 | 1744 | dev->devpath, stream->bEndpointAddress & 0x0f, |
| 1784 | 1745 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
| 1785 | 1746 | } |
| 1786 | − iso_stream_put (ehci, stream); | |
| 1787 | 1747 | |
| 1788 | 1748 | done: |
| 1789 | 1749 | itd->urb = NULL; |
| 1790 | − if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { | |
| 1791 | − /* OK to recycle this ITD now. */ | |
| 1792 | − itd->stream = NULL; | |
| 1793 | − list_move(&itd->itd_list, &stream->free_list); | |
| 1794 | − iso_stream_put(ehci, stream); | |
| 1795 | − } else { | |
| 1796 | − /* HW might remember this ITD, so we can't recycle it yet. | |
| 1797 | − * Move it to a safe place until a new frame starts. | |
| 1798 | − */ | |
| 1799 | − list_move(&itd->itd_list, &ehci->cached_itd_list); | |
| 1800 | − if (stream->refcount == 2) { | |
| 1801 | − /* If iso_stream_put() were called here, stream | |
| 1802 | − * would be freed. Instead, just prevent reuse. | |
| 1803 | − */ | |
| 1804 | − stream->ep->hcpriv = NULL; | |
| 1805 | − stream->ep = NULL; | |
| 1806 | − } | |
| 1750 | + | |
| 1751 | + /* Add to the end of the free list for later reuse */ | |
| 1752 | + list_move_tail(&itd->itd_list, &stream->free_list); | |
| 1753 | + | |
| 1754 | + /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ | |
| 1755 | + if (list_empty(&stream->td_list)) { | |
| 1756 | + list_splice_tail_init(&stream->free_list, | |
| 1757 | + &ehci->cached_itd_list); | |
| 1758 | + start_free_itds(ehci); | |
| 1807 | 1759 | } |
| 1760 | + | |
| 1808 | 1761 | return retval; |
| 1809 | 1762 | } |
| 1810 | 1763 | |
| @@ -1861,12 +1814,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, · 50 unmodified lines | ||
| 1861 | 1814 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
| 1862 | 1815 | else |
| 1863 | 1816 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
| 1864 | −done_not_linked: | |
| 1817 | + done_not_linked: | |
| 1865 | 1818 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1866 | − | |
| 1867 | −done: | |
| 1868 | − if (unlikely (status < 0)) | |
| 1869 | − iso_stream_put (ehci, stream); | |
| 1819 | + done: | |
| 1870 | 1820 | return status; |
| 1871 | 1821 | } |
| 1872 | 1822 | |
| @@ -1955,17 +1905,19 @@ sitd_urb_transaction ( · 82 unmodified lines | ||
| 1955 | 1905 | * means we never need two sitds for full speed packets. |
| 1956 | 1906 | */ |
| 1957 | 1907 | |
| 1958 | − /* free_list.next might be cache-hot ... but maybe | |
| 1959 | − * the HC caches it too. avoid that issue for now. | |
| 1908 | + /* | |
| 1909 | + * Use siTDs from the free list, but not siTDs that may | |
| 1910 | + * still be in use by the hardware. | |
| 1960 | 1911 | */ |
| 1961 | − | |
| 1962 | − /* prefer previously-allocated sitds */ | |
| 1963 | − if (!list_empty(&stream->free_list)) { | |
| 1964 | − sitd = list_entry (stream->free_list.prev, | |
| 1912 | + if (likely(!list_empty(&stream->free_list))) { | |
| 1913 | + sitd = list_first_entry(&stream->free_list, | |
| 1965 | 1914 | struct ehci_sitd, sitd_list); |
| 1915 | + if (sitd->frame == ehci->now_frame) | |
| 1916 | + goto alloc_sitd; | |
| 1966 | 1917 | list_del (&sitd->sitd_list); |
| 1967 | 1918 | sitd_dma = sitd->sitd_dma; |
| 1968 | 1919 | } else { |
| 1920 | + alloc_sitd: | |
| 1969 | 1921 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1970 | 1922 | sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, |
| 1971 | 1923 | &sitd_dma); |
| @@ -2034,8 +1986,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) · 62 unmodified lines | ||
| 2034 | 1986 | } |
| 2035 | 1987 | |
| 2036 | 1988 | /* fit urb's sitds into the selected schedule slot; activate as needed */ |
| 2037 | −static int | |
| 2038 | −sitd_link_urb ( | |
| 1989 | +static void sitd_link_urb( | |
| 2039 | 1990 | struct ehci_hcd *ehci, |
| 2040 | 1991 | struct urb *urb, |
| 2041 | 1992 | unsigned mod, |
| @@ -2081,7 +2032,7 @@ sitd_link_urb ( · 39 unmodified lines | ||
| 2081 | 2032 | sitd = list_entry (sched->td_list.next, |
| 2082 | 2033 | struct ehci_sitd, sitd_list); |
| 2083 | 2034 | list_move_tail (&sitd->sitd_list, &stream->td_list); |
| 2084 | − sitd->stream = iso_stream_get (stream); | |
| 2035 | + sitd->stream = stream; | |
| 2085 | 2036 | sitd->urb = urb; |
| 2086 | 2037 | |
| 2087 | 2038 | sitd_patch(ehci, stream, sitd, sched, packet); |
| @@ -2096,8 +2047,8 @@ sitd_link_urb ( · 8 unmodified lines | ||
| 2096 | 2047 | iso_sched_free (stream, sched); |
| 2097 | 2048 | urb->hcpriv = NULL; |
| 2098 | 2049 | |
| 2099 | − timer_action (ehci, TIMER_IO_WATCHDOG); | |
| 2100 | − return enable_periodic(ehci); | |
| 2050 | + ++ehci->isoc_count; | |
| 2051 | + enable_periodic(ehci); | |
| 2101 | 2052 | } |
| 2102 | 2053 | |
| 2103 | 2054 | /*-------------------------------------------------------------------------*/ |
| @@ -2115,18 +2066,15 @@ sitd_link_urb ( · 11 unmodified lines | ||
| 2115 | 2066 | * (b) only this endpoint's completions submit URBs. It seems some silicon |
| 2116 | 2067 | * corrupts things if you reuse completed descriptors very quickly... |
| 2117 | 2068 | */ |
| 2118 | −static unsigned | |
| 2119 | −sitd_complete ( | |
| 2120 | − struct ehci_hcd *ehci, | |
| 2121 | − struct ehci_sitd *sitd | |
| 2122 | −) { | |
| 2069 | +static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) | |
| 2070 | +{ | |
| 2123 | 2071 | struct urb *urb = sitd->urb; |
| 2124 | 2072 | struct usb_iso_packet_descriptor *desc; |
| 2125 | 2073 | u32 t; |
| 2126 | 2074 | int urb_index = -1; |
| 2127 | 2075 | struct ehci_iso_stream *stream = sitd->stream; |
| 2128 | 2076 | struct usb_device *dev; |
| 2129 | − unsigned retval = false; | |
| 2077 | + bool retval = false; | |
| 2130 | 2078 | |
| 2131 | 2079 | urb_index = sitd->index; |
| 2132 | 2080 | desc = &urb->iso_frame_desc [urb_index]; |
| @@ -2163,9 +2111,11 @@ sitd_complete ( · 30 unmodified lines | ||
| 2163 | 2111 | ehci_urb_done(ehci, urb, 0); |
| 2164 | 2112 | retval = true; |
| 2165 | 2113 | urb = NULL; |
| 2166 | − (void) disable_periodic(ehci); | |
| 2167 | − ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | |
| 2168 | 2114 | |
| 2115 | + --ehci->isoc_count; | |
| 2116 | + disable_periodic(ehci); | |
| 2117 | + | |
| 2118 | + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | |
| 2169 | 2119 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { |
| 2170 | 2120 | if (ehci->amd_pll_fix == 1) |
| 2171 | 2121 | usb_amd_quirk_pll_enable(); |
| @@ -2179,28 +2129,20 @@ sitd_complete ( · 7 unmodified lines | ||
| 2179 | 2129 | dev->devpath, stream->bEndpointAddress & 0x0f, |
| 2180 | 2130 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
| 2181 | 2131 | } |
| 2182 | − iso_stream_put (ehci, stream); | |
| 2183 | 2132 | |
| 2184 | 2133 | done: |
| 2185 | 2134 | sitd->urb = NULL; |
| 2186 | − if (ehci->clock_frame != sitd->frame) { | |
| 2187 | − /* OK to recycle this SITD now. */ | |
| 2188 | − sitd->stream = NULL; | |
| 2189 | − list_move(&sitd->sitd_list, &stream->free_list); | |
| 2190 | − iso_stream_put(ehci, stream); | |
| 2191 | − } else { | |
| 2192 | − /* HW might remember this SITD, so we can't recycle it yet. | |
| 2193 | − * Move it to a safe place until a new frame starts. | |
| 2194 | − */ | |
| 2195 | − list_move(&sitd->sitd_list, &ehci->cached_sitd_list); | |
| 2196 | − if (stream->refcount == 2) { | |
| 2197 | − /* If iso_stream_put() were called here, stream | |
| 2198 | − * would be freed. Instead, just prevent reuse. | |
| 2199 | − */ | |
| 2200 | − stream->ep->hcpriv = NULL; | |
| 2201 | − stream->ep = NULL; | |
| 2202 | − } | |
| 2135 | + | |
| 2136 | + /* Add to the end of the free list for later reuse */ | |
| 2137 | + list_move_tail(&sitd->sitd_list, &stream->free_list); | |
| 2138 | + | |
| 2139 | + /* Recycle the siTDs when the pipeline is empty (ep no longer in use) */ | |
| 2140 | + if (list_empty(&stream->td_list)) { | |
| 2141 | + list_splice_tail_init(&stream->free_list, | |
| 2142 | + &ehci->cached_sitd_list); | |
| 2143 | + start_free_itds(ehci); | |
| 2203 | 2144 | } |
| 2145 | + | |
| 2204 | 2146 | return retval; |
| 2205 | 2147 | } |
| 2206 | 2148 | |
| @@ -2254,74 +2196,39 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, · 47 unmodified lines | ||
| 2254 | 2196 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
| 2255 | 2197 | else |
| 2256 | 2198 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
| 2257 | −done_not_linked: | |
| 2199 | + done_not_linked: | |
| 2258 | 2200 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 2259 | − | |
| 2260 | −done: | |
| 2261 | − if (status < 0) | |
| 2262 | − iso_stream_put (ehci, stream); | |
| 2201 | + done: | |
| 2263 | 2202 | return status; |
| 2264 | 2203 | } |
| 2265 | 2204 | |
| 2266 | 2205 | /*-------------------------------------------------------------------------*/ |
| 2267 | 2206 | |
| 2268 | −static void free_cached_lists(struct ehci_hcd *ehci) | |
| 2207 | +static void scan_isoc(struct ehci_hcd *ehci) | |
| 2269 | 2208 | { |
| 2270 | − struct ehci_itd *itd, *n; | |
| 2271 | − struct ehci_sitd *sitd, *sn; | |
| 2272 | − | |
| 2273 | − list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { | |
| 2274 | − struct ehci_iso_stream *stream = itd->stream; | |
| 2275 | − itd->stream = NULL; | |
| 2276 | − list_move(&itd->itd_list, &stream->free_list); | |
| 2277 | − iso_stream_put(ehci, stream); | |
| 2278 | − } | |
| 2279 | − | |
| 2280 | − list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { | |
| 2281 | − struct ehci_iso_stream *stream = sitd->stream; | |
| 2282 | − sitd->stream = NULL; | |
| 2283 | − list_move(&sitd->sitd_list, &stream->free_list); | |
| 2284 | − iso_stream_put(ehci, stream); | |
| 2285 | − } | |
| 2286 | −} | |
| 2287 | − | |
| 2288 | −/*-------------------------------------------------------------------------*/ | |
| 2289 | − | |
| 2290 | −static void | |
| 2291 | −scan_periodic (struct ehci_hcd *ehci) | |
| 2292 | −{ | |
| 2293 | − unsigned now_uframe, frame, clock, clock_frame, mod; | |
| 2294 | − unsigned modified; | |
| 2295 | − | |
| 2296 | − mod = ehci->periodic_size << 3; | |
| 2209 | + unsigned uf, now_frame, frame; | |
| 2210 | + unsigned fmask = ehci->periodic_size - 1; | |
| 2211 | + bool modified, live; | |
| 2297 | 2212 | |
| 2298 | 2213 | /* |
| 2299 | 2214 | * When running, scan from last scan point up to "now" |
| 2300 | 2215 | * else clean up by scanning everything that's left. |
| 2301 | 2216 | * Touches as few pages as possible: cache-friendly. |
| 2302 | 2217 | */ |
| 2303 | − now_uframe = ehci->next_uframe; | |
| 2304 | − if (ehci->rh_state == EHCI_RH_RUNNING) { | |
| 2305 | − clock = ehci_read_frame_index(ehci); | |
| 2306 | − clock_frame = (clock >> 3) & (ehci->periodic_size - 1); | |
| 2218 | + if (ehci->rh_state >= EHCI_RH_RUNNING) { | |
| 2219 | + uf = ehci_read_frame_index(ehci); | |
| 2220 | + now_frame = (uf >> 3) & fmask; | |
| 2221 | + live = true; | |
| 2307 | 2222 | } else { |
| 2308 | − clock = now_uframe + mod - 1; | |
| 2309 | − clock_frame = -1; | |
| 2223 | + now_frame = (ehci->next_frame - 1) & fmask; | |
| 2224 | + live = false; | |
| 2310 | 2225 | } |
| 2311 | − if (ehci->clock_frame != clock_frame) { | |
| 2312 | − free_cached_lists(ehci); | |
| 2313 | − ehci->clock_frame = clock_frame; | |
| 2314 | − } | |
| 2315 | − clock &= mod - 1; | |
| 2316 | − clock_frame = clock >> 3; | |
| 2317 | − ++ehci->periodic_stamp; | |
| 2226 | + ehci->now_frame = now_frame; | |
| 2318 | 2227 | |
| 2228 | + frame = ehci->next_frame; | |
| 2319 | 2229 | for (;;) { |
| 2320 | 2230 | union ehci_shadow q, *q_p; |
| 2321 | 2231 | __hc32 type, *hw_p; |
| 2322 | − unsigned incomplete = false; | |
| 2323 | − | |
| 2324 | − frame = now_uframe >> 3; | |
| 2325 | 2232 | |
| 2326 | 2233 | restart: |
| 2327 | 2234 | /* scan each element in frame's queue for completions */ |
| @@ -2329,48 +2236,17 @@ restart: · 1 unmodified line | ||
| 2329 | 2236 | hw_p = &ehci->periodic [frame]; |
| 2330 | 2237 | q.ptr = q_p->ptr; |
| 2331 | 2238 | type = Q_NEXT_TYPE(ehci, *hw_p); |
| 2332 | − modified = 0; | |
| 2239 | + modified = false; | |
| 2333 | 2240 | |
| 2334 | 2241 | while (q.ptr != NULL) { |
| 2335 | − unsigned uf; | |
| 2336 | − union ehci_shadow temp; | |
| 2337 | − int live; | |
| 2338 | − | |
| 2339 | − live = (ehci->rh_state == EHCI_RH_RUNNING); | |
| 2340 | 2242 | switch (hc32_to_cpu(ehci, type)) { |
| 2341 | − case Q_TYPE_QH: | |
| 2342 | − /* handle any completions */ | |
| 2343 | − temp.qh = qh_get (q.qh); | |
| 2344 | − type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); | |
| 2345 | − q = q.qh->qh_next; | |
| 2346 | − if (temp.qh->stamp != ehci->periodic_stamp) { | |
| 2347 | − modified = qh_completions(ehci, temp.qh); | |
| 2348 | − if (!modified) | |
| 2349 | − temp.qh->stamp = ehci->periodic_stamp; | |
| 2350 | − if (unlikely(list_empty(&temp.qh->qtd_list) || | |
| 2351 | − temp.qh->needs_rescan)) | |
| 2352 | − intr_deschedule(ehci, temp.qh); | |
| 2353 | − } | |
| 2354 | − qh_put (temp.qh); | |
| 2355 | − break; | |
| 2356 | − case Q_TYPE_FSTN: | |
| 2357 | − /* for "save place" FSTNs, look at QH entries | |
| 2358 | − * in the previous frame for completions. | |
| 2359 | − */ | |
| 2360 | − if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) { | |
| 2361 | − ehci_dbg(ehci, | |
| 2362 | − "ignoring completions from FSTNs\n"); | |
| 2363 | − } | |
| 2364 | − type = Q_NEXT_TYPE(ehci, q.fstn->hw_next); | |
| 2365 | − q = q.fstn->fstn_next; | |
| 2366 | − break; | |
| 2367 | 2243 | case Q_TYPE_ITD: |
| 2368 | 2244 | /* If this ITD is still active, leave it for |
| 2369 | 2245 | * later processing ... check the next entry. |
| 2370 | 2246 | * No need to check for activity unless the |
| 2371 | 2247 | * frame is current. |
| 2372 | 2248 | */ |
| 2373 | − if (frame == clock_frame && live) { | |
| 2249 | + if (frame == now_frame && live) { | |
| 2374 | 2250 | rmb(); |
| 2375 | 2251 | for (uf = 0; uf < 8; uf++) { |
| 2376 | 2252 | if (q.itd->hw_transaction[uf] & |
| @@ -2378,7 +2254,6 @@ restart: · 1 unmodified line | ||
| 2378 | 2254 | break; |
| 2379 | 2255 | } |
| 2380 | 2256 | if (uf < 8) { |
| 2381 | − incomplete = true; | |
| 2382 | 2257 | q_p = &q.itd->itd_next; |
| 2383 | 2258 | hw_p = &q.itd->hw_next; |
| 2384 | 2259 | type = Q_NEXT_TYPE(ehci, |
| @@ -2410,14 +2285,12 @@ restart: · 25 unmodified lines | ||
| 2410 | 2285 | * No need to check for activity unless the |
| 2411 | 2286 | * frame is current. |
| 2412 | 2287 | */ |
| 2413 | − if (((frame == clock_frame) || | |
| 2414 | − (((frame + 1) & (ehci->periodic_size - 1)) | |
| 2415 | − == clock_frame)) | |
| 2288 | + if (((frame == now_frame) || | |
| 2289 | + (((frame + 1) & fmask) == now_frame)) | |
| 2416 | 2290 | && live |
| 2417 | 2291 | && (q.sitd->hw_results & |
| 2418 | 2292 | SITD_ACTIVE(ehci))) { |
| 2419 | 2293 | |
| 2420 | − incomplete = true; | |
| 2421 | 2294 | q_p = &q.sitd->sitd_next; |
| 2422 | 2295 | hw_p = &q.sitd->hw_next; |
| 2423 | 2296 | type = Q_NEXT_TYPE(ehci, |
| @@ -2445,58 +2318,23 @@ restart: · 21 unmodified lines | ||
| 2445 | 2318 | ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", |
| 2446 | 2319 | type, frame, q.ptr); |
| 2447 | 2320 | // BUG (); |
| 2321 | + /* FALL THROUGH */ | |
| 2322 | + case Q_TYPE_QH: | |
| 2323 | + case Q_TYPE_FSTN: | |
| 2324 | + /* End of the iTDs and siTDs */ | |
| 2448 | 2325 | q.ptr = NULL; |
| 2326 | + break; | |
| 2449 | 2327 | } |
| 2450 | 2328 | |
| 2451 | 2329 | /* assume completion callbacks modify the queue */ |
| 2452 | − if (unlikely (modified)) { | |
| 2453 | − if (likely(ehci->periodic_sched > 0)) | |
| 2454 | − goto restart; | |
| 2455 | − /* short-circuit this scan */ | |
| 2456 | − now_uframe = clock; | |
| 2457 | − break; | |
| 2458 | − } | |
| 2330 | + if (unlikely(modified && ehci->isoc_count > 0)) | |
| 2331 | + goto restart; | |
| 2459 | 2332 | } |
| 2460 | 2333 | |
| 2461 | − /* If we can tell we caught up to the hardware, stop now. | |
| 2462 | − * We can't advance our scan without collecting the ISO | |
| 2463 | − * transfers that are still pending in this frame. | |
| 2464 | − */ | |
| 2465 | − if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) { | |
| 2466 | − ehci->next_uframe = now_uframe; | |
| 2334 | + /* Stop when we have reached the current frame */ | |
| 2335 | + if (frame == now_frame) | |
| 2467 | 2336 | break; |
| 2468 | − } | |
| 2469 | − | |
| 2470 | − // FIXME: this assumes we won't get lapped when | |
| 2471 | − // latencies climb; that should be rare, but... | |
| 2472 | − // detect it, and just go all the way around. | |
| 2473 | − // FLR might help detect this case, so long as latencies | |
| 2474 | − // don't exceed periodic_size msec (default 1.024 sec). | |
| 2475 | − | |
| 2476 | − // FIXME: likewise assumes HC doesn't halt mid-scan | |
| 2477 | − | |
| 2478 | − if (now_uframe == clock) { | |
| 2479 | − unsigned now; | |
| 2480 | − | |
| 2481 | − if (ehci->rh_state != EHCI_RH_RUNNING | |
| 2482 | − || ehci->periodic_sched == 0) | |
| 2483 | − break; | |
| 2484 | − ehci->next_uframe = now_uframe; | |
| 2485 | − now = ehci_read_frame_index(ehci) & (mod - 1); | |
| 2486 | − if (now_uframe == now) | |
| 2487 | − break; | |
| 2488 | − | |
| 2489 | − /* rescan the rest of this frame, then ... */ | |
| 2490 | − clock = now; | |
| 2491 | − clock_frame = clock >> 3; | |
| 2492 | − if (ehci->clock_frame != clock_frame) { | |
| 2493 | − free_cached_lists(ehci); | |
| 2494 | − ehci->clock_frame = clock_frame; | |
| 2495 | − ++ehci->periodic_stamp; | |
| 2496 | − } | |
| 2497 | − } else { | |
| 2498 | − now_uframe++; | |
| 2499 | − now_uframe &= mod - 1; | |
| 2500 | − } | |
| 2337 | + frame = (frame + 1) & fmask; | |
| 2501 | 2338 | } |
| 2339 | + ehci->next_frame = now_frame; | |
| 2502 | 2340 | } |
| @@ -160,84 +160,16 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev) · 159 unmodified lines | ||
| 160 | 160 | static int ehci_hcd_sead3_drv_suspend(struct device *dev) |
| 161 | 161 | { |
| 162 | 162 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 163 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 164 | − unsigned long flags; | |
| 165 | − int rc = 0; | |
| 166 | − | |
| 167 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 168 | − msleep(20); | |
| 169 | − | |
| 170 | − /* Root hub was already suspended. Disable irq emission and | |
| 171 | − * mark HW unaccessible. The PM and USB cores make sure that | |
| 172 | − * the root hub is either suspended or stopped. | |
| 173 | − */ | |
| 174 | − ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); | |
| 175 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 176 | − ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 177 | − (void)ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 178 | − | |
| 179 | − clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 180 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 163 | + bool do_wakeup = device_may_wakeup(dev); | |
| 181 | 164 | |
| 182 | − /* could save FLADJ in case of Vaux power loss | |
| 183 | − * ... we'd only use it to handle clock skew | |
| 184 | − */ | |
| 185 | − | |
| 186 | − return rc; | |
| 165 | + return ehci_suspend(hcd, do_wakeup); | |
| 187 | 166 | } |
| 188 | 167 | |
| 189 | 168 | static int ehci_hcd_sead3_drv_resume(struct device *dev) |
| 190 | 169 | { |
| 191 | 170 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 192 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 193 | − | |
| 194 | − /* maybe restore FLADJ. */ | |
| 195 | − | |
| 196 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 197 | − msleep(100); | |
| 198 | − | |
| 199 | − /* Mark hardware accessible again as we are out of D3 state by now */ | |
| 200 | − set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | |
| 201 | − | |
| 202 | − /* If CF is still set, we maintained PCI Vaux power. | |
| 203 | − * Just undo the effect of ehci_pci_suspend(). | |
| 204 | − */ | |
| 205 | − if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | |
| 206 | − int mask = INTR_MASK; | |
| 207 | − | |
| 208 | − ehci_prepare_ports_for_controller_resume(ehci); | |
| 209 | − if (!hcd->self.root_hub->do_remote_wakeup) | |
| 210 | − mask &= ~STS_PCD; | |
| 211 | − ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 212 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 213 | − return 0; | |
| 214 | − } | |
| 215 | − | |
| 216 | − ehci_dbg(ehci, "lost power, restarting\n"); | |
| 217 | − usb_root_hub_lost_power(hcd->self.root_hub); | |
| 218 | − | |
| 219 | − /* Else reset, to cope with power loss or flush-to-storage | |
| 220 | − * style "resume" having let BIOS kick in during reboot. | |
| 221 | − */ | |
| 222 | − (void) ehci_halt(ehci); | |
| 223 | − (void) ehci_reset(ehci); | |
| 224 | − | |
| 225 | − /* emptying the schedule aborts any urbs */ | |
| 226 | − spin_lock_irq(&ehci->lock); | |
| 227 | − if (ehci->reclaim) | |
| 228 | − end_unlink_async(ehci); | |
| 229 | − ehci_work(ehci); | |
| 230 | − spin_unlock_irq(&ehci->lock); | |
| 231 | − | |
| 232 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 233 | − ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 234 | − ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 235 | − | |
| 236 | − /* here we "know" root ports should always stay powered */ | |
| 237 | − ehci_port_power(ehci, 1); | |
| 238 | − | |
| 239 | − ehci->rh_state = EHCI_RH_SUSPENDED; | |
| 240 | 171 | |
| 172 | + ehci_resume(hcd, false); | |
| 241 | 173 | return 0; |
| 242 | 174 | } |
| 243 | 175 | |
| @@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd) · 23 unmodified lines | ||
| 24 | 24 | int ret; |
| 25 | 25 | |
| 26 | 26 | ehci->caps = hcd->regs; |
| 27 | − ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, | |
| 28 | − &ehci->caps->hc_capbase)); | |
| 29 | 27 | |
| 30 | − dbg_hcs_params(ehci, "reset"); | |
| 31 | − dbg_hcc_params(ehci, "reset"); | |
| 32 | − | |
| 33 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 34 | − | |
| 35 | − ret = ehci_halt(ehci); | |
| 36 | − if (unlikely(ret)) | |
| 37 | − return ret; | |
| 38 | − | |
| 39 | − ret = ehci_init(hcd); | |
| 28 | + ret = ehci_setup(hcd); | |
| 40 | 29 | if (unlikely(ret)) |
| 41 | 30 | return ret; |
| 42 | 31 | |
| 43 | − ehci->sbrn = 0x20; | |
| 44 | − | |
| 45 | − ehci_reset(ehci); | |
| 46 | 32 | ehci_port_power(ehci, 0); |
| 47 | 33 | |
| 48 | 34 | return ret; |
| @@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd) · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | /* registers start at offset 0x0 */ |
| 43 | 43 | ehci->caps = hcd->regs; |
| 44 | − ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, | |
| 45 | − &ehci->caps->hc_capbase)); | |
| 46 | − /* cache this readonly data; minimize chip reads */ | |
| 47 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 48 | − retval = ehci_halt(ehci); | |
| 49 | − if (retval) | |
| 50 | − return retval; | |
| 51 | 44 | |
| 52 | − retval = ehci_init(hcd); | |
| 45 | + retval = ehci_setup(hcd); | |
| 53 | 46 | if (retval) |
| 54 | 47 | return retval; |
| 55 | 48 | |
| 56 | − ehci_reset(ehci); | |
| 57 | 49 | ehci_port_power(ehci, 0); |
| 58 | 50 | |
| 59 | 51 | return retval; |
| @@ -97,71 +89,16 @@ static const struct hc_driver ehci_spear_hc_driver = { · 37 unmodified lines | ||
| 97 | 89 | static int ehci_spear_drv_suspend(struct device *dev) |
| 98 | 90 | { |
| 99 | 91 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 100 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 101 | − unsigned long flags; | |
| 102 | − int rc = 0; | |
| 92 | + bool do_wakeup = device_may_wakeup(dev); | |
| 103 | 93 | |
| 104 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 105 | − msleep(10); | |
| 106 | − | |
| 107 | − /* | |
| 108 | − * Root hub was already suspended. Disable irq emission and mark HW | |
| 109 | − * unaccessible. The PM and USB cores make sure that the root hub is | |
| 110 | − * either suspended or stopped. | |
| 111 | − */ | |
| 112 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 113 | − ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); | |
| 114 | − ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 115 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 116 | − spin_unlock_irqrestore(&ehci->lock, flags); | |
| 117 | − | |
| 118 | − return rc; | |
| 94 | + return ehci_suspend(hcd, do_wakeup); | |
| 119 | 95 | } |
| 120 | 96 | |
| 121 | 97 | static int ehci_spear_drv_resume(struct device *dev) |
| 122 | 98 | { |
| 123 | 99 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 124 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 125 | − | |
| 126 | − if (time_before(jiffies, ehci->next_statechange)) | |
| 127 | − msleep(100); | |
| 128 | − | |
| 129 | − if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | |
| 130 | − int mask = INTR_MASK; | |
| 131 | − | |
| 132 | − ehci_prepare_ports_for_controller_resume(ehci); | |
| 133 | − | |
| 134 | − if (!hcd->self.root_hub->do_remote_wakeup) | |
| 135 | − mask &= ~STS_PCD; | |
| 136 | − | |
| 137 | − ehci_writel(ehci, mask, &ehci->regs->intr_enable); | |
| 138 | − ehci_readl(ehci, &ehci->regs->intr_enable); | |
| 139 | − return 0; | |
| 140 | − } | |
| 141 | − | |
| 142 | − usb_root_hub_lost_power(hcd->self.root_hub); | |
| 143 | − | |
| 144 | − /* | |
| 145 | − * Else reset, to cope with power loss or flush-to-storage style | |
| 146 | − * "resume" having let BIOS kick in during reboot. | |
| 147 | − */ | |
| 148 | − ehci_halt(ehci); | |
| 149 | − ehci_reset(ehci); | |
| 150 | − | |
| 151 | − /* emptying the schedule aborts any urbs */ | |
| 152 | − spin_lock_irq(&ehci->lock); | |
| 153 | − if (ehci->reclaim) | |
| 154 | − end_unlink_async(ehci); | |
| 155 | − | |
| 156 | − ehci_work(ehci); | |
| 157 | − spin_unlock_irq(&ehci->lock); | |
| 158 | − | |
| 159 | − ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 160 | − ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | |
| 161 | − ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
| 162 | 100 | |
| 163 | − /* here we "know" root ports should always stay powered */ | |
| 164 | − ehci_port_power(ehci, 1); | |
| 101 | + ehci_resume(hcd, false); | |
| 165 | 102 | return 0; |
| 166 | 103 | } |
| 167 | 104 | #endif /* CONFIG_PM */ |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | 19 | #include <linux/clk.h> |
| 20 | +#include <linux/err.h> | |
| 20 | 21 | #include <linux/platform_device.h> |
| 21 | 22 | #include <linux/platform_data/tegra_usb.h> |
| 22 | 23 | #include <linux/irq.h> |
| @@ -280,30 +281,14 @@ static int tegra_ehci_setup(struct usb_hcd *hcd) · 257 unmodified lines | ||
| 280 | 281 | |
| 281 | 282 | /* EHCI registers start at offset 0x100 */ |
| 282 | 283 | ehci->caps = hcd->regs + 0x100; |
| 283 | − ehci->regs = hcd->regs + 0x100 + | |
| 284 | − HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); | |
| 285 | − | |
| 286 | − dbg_hcs_params(ehci, "reset"); | |
| 287 | − dbg_hcc_params(ehci, "reset"); | |
| 288 | − | |
| 289 | − /* cache this readonly data; minimize chip reads */ | |
| 290 | − ehci->hcs_params = readl(&ehci->caps->hcs_params); | |
| 291 | 284 | |
| 292 | 285 | /* switch to host mode */ |
| 293 | 286 | hcd->has_tt = 1; |
| 294 | − ehci_reset(ehci); | |
| 295 | − | |
| 296 | − retval = ehci_halt(ehci); | |
| 297 | − if (retval) | |
| 298 | − return retval; | |
| 299 | 287 | |
| 300 | − /* data structure init */ | |
| 301 | − retval = ehci_init(hcd); | |
| 288 | + retval = ehci_setup(hcd); | |
| 302 | 289 | if (retval) |
| 303 | 290 | return retval; |
| 304 | 291 | |
| 305 | − ehci->sbrn = 0x20; | |
| 306 | − | |
| 307 | 292 | ehci_port_power(ehci, 1); |
| 308 | 293 | return retval; |
| 309 | 294 | } |
| @@ -460,12 +445,11 @@ static int controller_suspend(struct device *dev) · 150 unmodified lines | ||
| 460 | 445 | if (time_before(jiffies, ehci->next_statechange)) |
| 461 | 446 | msleep(10); |
| 462 | 447 | |
| 463 | − spin_lock_irqsave(&ehci->lock, flags); | |
| 448 | + ehci_halt(ehci); | |
| 464 | 449 | |
| 450 | + spin_lock_irqsave(&ehci->lock, flags); | |
| 465 | 451 | tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; |
| 466 | − ehci_halt(ehci); | |
| 467 | 452 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
| 468 | − | |
| 469 | 453 | spin_unlock_irqrestore(&ehci->lock, flags); |
| 470 | 454 | |
| 471 | 455 | tegra_ehci_power_down(hcd); |
| @@ -749,8 +733,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) · 277 unmodified lines | ||
| 749 | 733 | |
| 750 | 734 | #ifdef CONFIG_USB_OTG_UTILS |
| 751 | 735 | if (pdata->operating_mode == TEGRA_USB_OTG) { |
| 752 | − tegra->transceiver = usb_get_transceiver(); | |
| 753 | − if (tegra->transceiver) | |
| 736 | + tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 737 | + if (!IS_ERR_OR_NULL(tegra->transceiver)) | |
| 754 | 738 | otg_set_host(tegra->transceiver->otg, &hcd->self); |
| 755 | 739 | } |
| 756 | 740 | #endif |
| @@ -773,9 +757,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 773 | 757 | |
| 774 | 758 | fail: |
| 775 | 759 | #ifdef CONFIG_USB_OTG_UTILS |
| 776 | − if (tegra->transceiver) { | |
| 760 | + if (!IS_ERR_OR_NULL(tegra->transceiver)) { | |
| 777 | 761 | otg_set_host(tegra->transceiver->otg, NULL); |
| 778 | − usb_put_transceiver(tegra->transceiver); | |
| 762 | + usb_put_phy(tegra->transceiver); | |
| 779 | 763 | } |
| 780 | 764 | #endif |
| 781 | 765 | tegra_usb_phy_close(tegra->phy); |
| @@ -808,9 +792,9 @@ static int tegra_ehci_remove(struct platform_device *pdev) · 26 unmodified lines | ||
| 808 | 792 | pm_runtime_put_noidle(&pdev->dev); |
| 809 | 793 | |
| 810 | 794 | #ifdef CONFIG_USB_OTG_UTILS |
| 811 | − if (tegra->transceiver) { | |
| 795 | + if (!IS_ERR_OR_NULL(tegra->transceiver)) { | |
| 812 | 796 | otg_set_host(tegra->transceiver->otg, NULL); |
| 813 | − usb_put_transceiver(tegra->transceiver); | |
| 797 | + usb_put_phy(tegra->transceiver); | |
| 814 | 798 | } |
| 815 | 799 | #endif |
| 816 | 800 | |
| @@ -0,0 +1,401 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2012 by Alan Stern | |
| 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 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, but | |
| 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
| 11 | + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 12 | + * for more details. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +/* This file is part of ehci-hcd.c */ | |
| 16 | + | |
| 17 | +/*-------------------------------------------------------------------------*/ | |
| 18 | + | |
| 19 | +/* Set a bit in the USBCMD register */ | |
| 20 | +static void ehci_set_command_bit(struct ehci_hcd *ehci, u32 bit) | |
| 21 | +{ | |
| 22 | + ehci->command |= bit; | |
| 23 | + ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 24 | + | |
| 25 | + /* unblock posted write */ | |
| 26 | + ehci_readl(ehci, &ehci->regs->command); | |
| 27 | +} | |
| 28 | + | |
| 29 | +/* Clear a bit in the USBCMD register */ | |
| 30 | +static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit) | |
| 31 | +{ | |
| 32 | + ehci->command &= ~bit; | |
| 33 | + ehci_writel(ehci, ehci->command, &ehci->regs->command); | |
| 34 | + | |
| 35 | + /* unblock posted write */ | |
| 36 | + ehci_readl(ehci, &ehci->regs->command); | |
| 37 | +} | |
| 38 | + | |
| 39 | +/*-------------------------------------------------------------------------*/ | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * EHCI timer support... Now using hrtimers. | |
| 43 | + * | |
| 44 | + * Lots of different events are triggered from ehci->hrtimer. Whenever | |
| 45 | + * the timer routine runs, it checks each possible event; events that are | |
| 46 | + * currently enabled and whose expiration time has passed get handled. | |
| 47 | + * The set of enabled events is stored as a collection of bitflags in | |
| 48 | + * ehci->enabled_hrtimer_events, and they are numbered in order of | |
| 49 | + * increasing delay values (ranging between 1 ms and 100 ms). | |
| 50 | + * | |
| 51 | + * Rather than implementing a sorted list or tree of all pending events, | |
| 52 | + * we keep track only of the lowest-numbered pending event, in | |
| 53 | + * ehci->next_hrtimer_event. Whenever ehci->hrtimer gets restarted, its | |
| 54 | + * expiration time is set to the timeout value for this event. | |
| 55 | + * | |
| 56 | + * As a result, events might not get handled right away; the actual delay | |
| 57 | + * could be anywhere up to twice the requested delay. This doesn't | |
| 58 | + * matter, because none of the events are especially time-critical. The | |
| 59 | + * ones that matter most all have a delay of 1 ms, so they will be | |
| 60 | + * handled after 2 ms at most, which is okay. In addition to this, we | |
| 61 | + * allow for an expiration range of 1 ms. | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * Delay lengths for the hrtimer event types. | |
| 66 | + * Keep this list sorted by delay length, in the same order as | |
| 67 | + * the event types indexed by enum ehci_hrtimer_event in ehci.h. | |
| 68 | + */ | |
| 69 | +static unsigned event_delays_ns[] = { | |
| 70 | + 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_ASS */ | |
| 71 | + 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_PSS */ | |
| 72 | + 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_DEAD */ | |
| 73 | + 1125 * NSEC_PER_USEC, /* EHCI_HRTIMER_UNLINK_INTR */ | |
| 74 | + 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_FREE_ITDS */ | |
| 75 | + 6 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ASYNC_UNLINKS */ | |
| 76 | + 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IAA_WATCHDOG */ | |
| 77 | + 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_PERIODIC */ | |
| 78 | + 15 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_ASYNC */ | |
| 79 | + 100 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IO_WATCHDOG */ | |
| 80 | +}; | |
| 81 | + | |
| 82 | +/* Enable a pending hrtimer event */ | |
| 83 | +static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event, | |
| 84 | + bool resched) | |
| 85 | +{ | |
| 86 | + ktime_t *timeout = &ehci->hr_timeouts[event]; | |
| 87 | + | |
| 88 | + if (resched) | |
| 89 | + *timeout = ktime_add(ktime_get(), | |
| 90 | + ktime_set(0, event_delays_ns[event])); | |
| 91 | + ehci->enabled_hrtimer_events |= (1 << event); | |
| 92 | + | |
| 93 | + /* Track only the lowest-numbered pending event */ | |
| 94 | + if (event < ehci->next_hrtimer_event) { | |
| 95 | + ehci->next_hrtimer_event = event; | |
| 96 | + hrtimer_start_range_ns(&ehci->hrtimer, *timeout, | |
| 97 | + NSEC_PER_MSEC, HRTIMER_MODE_ABS); | |
| 98 | + } | |
| 99 | +} | |
| 100 | + | |
| 101 | + | |
| 102 | +/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ | |
| 103 | +static void ehci_poll_ASS(struct ehci_hcd *ehci) | |
| 104 | +{ | |
| 105 | + unsigned actual, want; | |
| 106 | + | |
| 107 | + /* Don't enable anything if the controller isn't running (e.g., died) */ | |
| 108 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 109 | + return; | |
| 110 | + | |
| 111 | + want = (ehci->command & CMD_ASE) ? STS_ASS : 0; | |
| 112 | + actual = ehci_readl(ehci, &ehci->regs->status) & STS_ASS; | |
| 113 | + | |
| 114 | + if (want != actual) { | |
| 115 | + | |
| 116 | + /* Poll again later, but give up after about 20 ms */ | |
| 117 | + if (ehci->ASS_poll_count++ < 20) { | |
| 118 | + ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); | |
| 119 | + return; | |
| 120 | + } | |
| 121 | + ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n"); | |
| 122 | + } | |
| 123 | + ehci->ASS_poll_count = 0; | |
| 124 | + | |
| 125 | + /* The status is up-to-date; restart or stop the schedule as needed */ | |
| 126 | + if (want == 0) { /* Stopped */ | |
| 127 | + if (ehci->async_count > 0) | |
| 128 | + ehci_set_command_bit(ehci, CMD_ASE); | |
| 129 | + | |
| 130 | + } else { /* Running */ | |
| 131 | + if (ehci->async_count == 0) { | |
| 132 | + | |
| 133 | + /* Turn off the schedule after a while */ | |
| 134 | + ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_ASYNC, | |
| 135 | + true); | |
| 136 | + } | |
| 137 | + } | |
| 138 | +} | |
| 139 | + | |
| 140 | +/* Turn off the async schedule after a brief delay */ | |
| 141 | +static void ehci_disable_ASE(struct ehci_hcd *ehci) | |
| 142 | +{ | |
| 143 | + ehci_clear_command_bit(ehci, CMD_ASE); | |
| 144 | +} | |
| 145 | + | |
| 146 | + | |
| 147 | +/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ | |
| 148 | +static void ehci_poll_PSS(struct ehci_hcd *ehci) | |
| 149 | +{ | |
| 150 | + unsigned actual, want; | |
| 151 | + | |
| 152 | + /* Don't do anything if the controller isn't running (e.g., died) */ | |
| 153 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 154 | + return; | |
| 155 | + | |
| 156 | + want = (ehci->command & CMD_PSE) ? STS_PSS : 0; | |
| 157 | + actual = ehci_readl(ehci, &ehci->regs->status) & STS_PSS; | |
| 158 | + | |
| 159 | + if (want != actual) { | |
| 160 | + | |
| 161 | + /* Poll again later, but give up after about 20 ms */ | |
| 162 | + if (ehci->PSS_poll_count++ < 20) { | |
| 163 | + ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); | |
| 164 | + return; | |
| 165 | + } | |
| 166 | + ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n"); | |
| 167 | + } | |
| 168 | + ehci->PSS_poll_count = 0; | |
| 169 | + | |
| 170 | + /* The status is up-to-date; restart or stop the schedule as needed */ | |
| 171 | + if (want == 0) { /* Stopped */ | |
| 172 | + if (ehci->periodic_count > 0) | |
| 173 | + ehci_set_command_bit(ehci, CMD_PSE); | |
| 174 | + | |
| 175 | + } else { /* Running */ | |
| 176 | + if (ehci->periodic_count == 0) { | |
| 177 | + | |
| 178 | + /* Turn off the schedule after a while */ | |
| 179 | + ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_PERIODIC, | |
| 180 | + true); | |
| 181 | + } | |
| 182 | + } | |
| 183 | +} | |
| 184 | + | |
| 185 | +/* Turn off the periodic schedule after a brief delay */ | |
| 186 | +static void ehci_disable_PSE(struct ehci_hcd *ehci) | |
| 187 | +{ | |
| 188 | + ehci_clear_command_bit(ehci, CMD_PSE); | |
| 189 | +} | |
| 190 | + | |
| 191 | + | |
| 192 | +/* Poll the STS_HALT status bit; see when a dead controller stops */ | |
| 193 | +static void ehci_handle_controller_death(struct ehci_hcd *ehci) | |
| 194 | +{ | |
| 195 | + if (!(ehci_readl(ehci, &ehci->regs->status) & STS_HALT)) { | |
| 196 | + | |
| 197 | + /* Give up after a few milliseconds */ | |
| 198 | + if (ehci->died_poll_count++ < 5) { | |
| 199 | + /* Try again later */ | |
| 200 | + ehci_enable_event(ehci, EHCI_HRTIMER_POLL_DEAD, true); | |
| 201 | + return; | |
| 202 | + } | |
| 203 | + ehci_warn(ehci, "Waited too long for the controller to stop, giving up\n"); | |
| 204 | + } | |
| 205 | + | |
| 206 | + /* Clean up the mess */ | |
| 207 | + ehci->rh_state = EHCI_RH_HALTED; | |
| 208 | + ehci_writel(ehci, 0, &ehci->regs->configured_flag); | |
| 209 | + ehci_writel(ehci, 0, &ehci->regs->intr_enable); | |
| 210 | + ehci_work(ehci); | |
| 211 | + end_unlink_async(ehci); | |
| 212 | + | |
| 213 | + /* Not in process context, so don't try to reset the controller */ | |
| 214 | +} | |
| 215 | + | |
| 216 | + | |
| 217 | +/* Handle unlinked interrupt QHs once they are gone from the hardware */ | |
| 218 | +static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci) | |
| 219 | +{ | |
| 220 | + bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); | |
| 221 | + | |
| 222 | + /* | |
| 223 | + * Process all the QHs on the intr_unlink list that were added | |
| 224 | + * before the current unlink cycle began. The list is in | |
| 225 | + * temporal order, so stop when we reach the first entry in the | |
| 226 | + * current cycle. But if the root hub isn't running then | |
| 227 | + * process all the QHs on the list. | |
| 228 | + */ | |
| 229 | + ehci->intr_unlinking = true; | |
| 230 | + while (ehci->intr_unlink) { | |
| 231 | + struct ehci_qh *qh = ehci->intr_unlink; | |
| 232 | + | |
| 233 | + if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle) | |
| 234 | + break; | |
| 235 | + ehci->intr_unlink = qh->unlink_next; | |
| 236 | + qh->unlink_next = NULL; | |
| 237 | + end_unlink_intr(ehci, qh); | |
| 238 | + } | |
| 239 | + | |
| 240 | + /* Handle remaining entries later */ | |
| 241 | + if (ehci->intr_unlink) { | |
| 242 | + ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); | |
| 243 | + ++ehci->intr_unlink_cycle; | |
| 244 | + } | |
| 245 | + ehci->intr_unlinking = false; | |
| 246 | +} | |
| 247 | + | |
| 248 | + | |
| 249 | +/* Start another free-iTDs/siTDs cycle */ | |
| 250 | +static void start_free_itds(struct ehci_hcd *ehci) | |
| 251 | +{ | |
| 252 | + if (!(ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_FREE_ITDS))) { | |
| 253 | + ehci->last_itd_to_free = list_entry( | |
| 254 | + ehci->cached_itd_list.prev, | |
| 255 | + struct ehci_itd, itd_list); | |
| 256 | + ehci->last_sitd_to_free = list_entry( | |
| 257 | + ehci->cached_sitd_list.prev, | |
| 258 | + struct ehci_sitd, sitd_list); | |
| 259 | + ehci_enable_event(ehci, EHCI_HRTIMER_FREE_ITDS, true); | |
| 260 | + } | |
| 261 | +} | |
| 262 | + | |
| 263 | +/* Wait for controller to stop using old iTDs and siTDs */ | |
| 264 | +static void end_free_itds(struct ehci_hcd *ehci) | |
| 265 | +{ | |
| 266 | + struct ehci_itd *itd, *n; | |
| 267 | + struct ehci_sitd *sitd, *sn; | |
| 268 | + | |
| 269 | + if (ehci->rh_state < EHCI_RH_RUNNING) { | |
| 270 | + ehci->last_itd_to_free = NULL; | |
| 271 | + ehci->last_sitd_to_free = NULL; | |
| 272 | + } | |
| 273 | + | |
| 274 | + list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { | |
| 275 | + list_del(&itd->itd_list); | |
| 276 | + dma_pool_free(ehci->itd_pool, itd, itd->itd_dma); | |
| 277 | + if (itd == ehci->last_itd_to_free) | |
| 278 | + break; | |
| 279 | + } | |
| 280 | + list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { | |
| 281 | + list_del(&sitd->sitd_list); | |
| 282 | + dma_pool_free(ehci->sitd_pool, sitd, sitd->sitd_dma); | |
| 283 | + if (sitd == ehci->last_sitd_to_free) | |
| 284 | + break; | |
| 285 | + } | |
| 286 | + | |
| 287 | + if (!list_empty(&ehci->cached_itd_list) || | |
| 288 | + !list_empty(&ehci->cached_sitd_list)) | |
| 289 | + start_free_itds(ehci); | |
| 290 | +} | |
| 291 | + | |
| 292 | + | |
| 293 | +/* Handle lost (or very late) IAA interrupts */ | |
| 294 | +static void ehci_iaa_watchdog(struct ehci_hcd *ehci) | |
| 295 | +{ | |
| 296 | + if (ehci->rh_state != EHCI_RH_RUNNING) | |
| 297 | + return; | |
| 298 | + | |
| 299 | + /* | |
| 300 | + * Lost IAA irqs wedge things badly; seen first with a vt8235. | |
| 301 | + * So we need this watchdog, but must protect it against both | |
| 302 | + * (a) SMP races against real IAA firing and retriggering, and | |
| 303 | + * (b) clean HC shutdown, when IAA watchdog was pending. | |
| 304 | + */ | |
| 305 | + if (ehci->async_iaa) { | |
| 306 | + u32 cmd, status; | |
| 307 | + | |
| 308 | + /* If we get here, IAA is *REALLY* late. It's barely | |
| 309 | + * conceivable that the system is so busy that CMD_IAAD | |
| 310 | + * is still legitimately set, so let's be sure it's | |
| 311 | + * clear before we read STS_IAA. (The HC should clear | |
| 312 | + * CMD_IAAD when it sets STS_IAA.) | |
| 313 | + */ | |
| 314 | + cmd = ehci_readl(ehci, &ehci->regs->command); | |
| 315 | + | |
| 316 | + /* | |
| 317 | + * If IAA is set here it either legitimately triggered | |
| 318 | + * after the watchdog timer expired (_way_ late, so we'll | |
| 319 | + * still count it as lost) ... or a silicon erratum: | |
| 320 | + * - VIA seems to set IAA without triggering the IRQ; | |
| 321 | + * - IAAD potentially cleared without setting IAA. | |
| 322 | + */ | |
| 323 | + status = ehci_readl(ehci, &ehci->regs->status); | |
| 324 | + if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { | |
| 325 | + COUNT(ehci->stats.lost_iaa); | |
| 326 | + ehci_writel(ehci, STS_IAA, &ehci->regs->status); | |
| 327 | + } | |
| 328 | + | |
| 329 | + ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", | |
| 330 | + status, cmd); | |
| 331 | + end_unlink_async(ehci); | |
| 332 | + } | |
| 333 | +} | |
| 334 | + | |
| 335 | + | |
| 336 | +/* Enable the I/O watchdog, if appropriate */ | |
| 337 | +static void turn_on_io_watchdog(struct ehci_hcd *ehci) | |
| 338 | +{ | |
| 339 | + /* Not needed if the controller isn't running or it's already enabled */ | |
| 340 | + if (ehci->rh_state != EHCI_RH_RUNNING || | |
| 341 | + (ehci->enabled_hrtimer_events & | |
| 342 | + BIT(EHCI_HRTIMER_IO_WATCHDOG))) | |
| 343 | + return; | |
| 344 | + | |
| 345 | + /* | |
| 346 | + * Isochronous transfers always need the watchdog. | |
| 347 | + * For other sorts we use it only if the flag is set. | |
| 348 | + */ | |
| 349 | + if (ehci->isoc_count > 0 || (ehci->need_io_watchdog && | |
| 350 | + ehci->async_count + ehci->intr_count > 0)) | |
| 351 | + ehci_enable_event(ehci, EHCI_HRTIMER_IO_WATCHDOG, true); | |
| 352 | +} | |
| 353 | + | |
| 354 | + | |
| 355 | +/* | |
| 356 | + * Handler functions for the hrtimer event types. | |
| 357 | + * Keep this array in the same order as the event types indexed by | |
| 358 | + * enum ehci_hrtimer_event in ehci.h. | |
| 359 | + */ | |
| 360 | +static void (*event_handlers[])(struct ehci_hcd *) = { | |
| 361 | + ehci_poll_ASS, /* EHCI_HRTIMER_POLL_ASS */ | |
| 362 | + ehci_poll_PSS, /* EHCI_HRTIMER_POLL_PSS */ | |
| 363 | + ehci_handle_controller_death, /* EHCI_HRTIMER_POLL_DEAD */ | |
| 364 | + ehci_handle_intr_unlinks, /* EHCI_HRTIMER_UNLINK_INTR */ | |
| 365 | + end_free_itds, /* EHCI_HRTIMER_FREE_ITDS */ | |
| 366 | + unlink_empty_async, /* EHCI_HRTIMER_ASYNC_UNLINKS */ | |
| 367 | + ehci_iaa_watchdog, /* EHCI_HRTIMER_IAA_WATCHDOG */ | |
| 368 | + ehci_disable_PSE, /* EHCI_HRTIMER_DISABLE_PERIODIC */ | |
| 369 | + ehci_disable_ASE, /* EHCI_HRTIMER_DISABLE_ASYNC */ | |
| 370 | + ehci_work, /* EHCI_HRTIMER_IO_WATCHDOG */ | |
| 371 | +}; | |
| 372 | + | |
| 373 | +static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t) | |
| 374 | +{ | |
| 375 | + struct ehci_hcd *ehci = container_of(t, struct ehci_hcd, hrtimer); | |
| 376 | + ktime_t now; | |
| 377 | + unsigned long events; | |
| 378 | + unsigned long flags; | |
| 379 | + unsigned e; | |
| 380 | + | |
| 381 | + spin_lock_irqsave(&ehci->lock, flags); | |
| 382 | + | |
| 383 | + events = ehci->enabled_hrtimer_events; | |
| 384 | + ehci->enabled_hrtimer_events = 0; | |
| 385 | + ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; | |
| 386 | + | |
| 387 | + /* | |
| 388 | + * Check each pending event. If its time has expired, handle | |
| 389 | + * the event; otherwise re-enable it. | |
| 390 | + */ | |
| 391 | + now = ktime_get(); | |
| 392 | + for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) { | |
| 393 | + if (now.tv64 >= ehci->hr_timeouts[e].tv64) | |
| 394 | + event_handlers[e](ehci); | |
| 395 | + else | |
| 396 | + ehci_enable_event(ehci, e, false); | |
| 397 | + } | |
| 398 | + | |
| 399 | + spin_unlock_irqrestore(&ehci->lock, flags); | |
| 400 | + return HRTIMER_NORESTART; | |
| 401 | +} | |
| @@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = { · 47 unmodified lines | ||
| 48 | 48 | /* |
| 49 | 49 | * basic lifecycle operations |
| 50 | 50 | */ |
| 51 | − .reset = ehci_init, | |
| 51 | + .reset = ehci_setup, | |
| 52 | 52 | .start = ehci_run, |
| 53 | 53 | .stop = ehci_stop, |
| 54 | 54 | .shutdown = ehci_shutdown, |
| @@ -121,18 +121,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) · 66 unmodified lines | ||
| 121 | 121 | |
| 122 | 122 | ehci = hcd_to_ehci(hcd); |
| 123 | 123 | ehci->caps = hcd->regs; |
| 124 | − ehci->regs = hcd->regs + | |
| 125 | − HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); | |
| 126 | − | |
| 127 | − dbg_hcs_params(ehci, "reset"); | |
| 128 | − dbg_hcc_params(ehci, "reset"); | |
| 129 | − | |
| 130 | − /* cache this readonly data; minimize chip reads */ | |
| 131 | − ehci->hcs_params = readl(&ehci->caps->hcs_params); | |
| 132 | − | |
| 133 | − ehci_port_power(ehci, 1); | |
| 134 | − | |
| 135 | − ehci_reset(ehci); | |
| 136 | 124 | |
| 137 | 125 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
| 138 | 126 | IRQF_SHARED); |
| @@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver, · 70 unmodified lines | ||
| 71 | 71 | val |= ENPHY; |
| 72 | 72 | __raw_writel(val, ehci->regs+PHY1_CTR); |
| 73 | 73 | |
| 74 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 75 | − ehci->sbrn = 0x20; | |
| 76 | − | |
| 77 | 74 | irq = platform_get_irq(pdev, 0); |
| 78 | 75 | if (irq < 0) |
| 79 | 76 | goto err4; |
| 80 | 77 | |
| 81 | − ehci_reset(ehci); | |
| 82 | − | |
| 83 | 78 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 84 | 79 | if (retval != 0) |
| 85 | 80 | goto err4; |
| 86 | 81 | |
| 87 | − ehci_writel(ehci, 1, &ehci->regs->configured_flag); | |
| 88 | − | |
| 89 | 82 | return retval; |
| 90 | 83 | err4: |
| 91 | 84 | iounmap(hcd->regs); |
| @@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = { · 28 unmodified lines | ||
| 120 | 113 | /* |
| 121 | 114 | * basic lifecycle operations |
| 122 | 115 | */ |
| 123 | − .reset = ehci_init, | |
| 116 | + .reset = ehci_setup, | |
| 124 | 117 | .start = ehci_run, |
| 125 | 118 | |
| 126 | 119 | .stop = ehci_stop, |
| @@ -31,30 +31,6 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/of_platform.h> |
| 32 | 32 | #include <linux/of_address.h> |
| 33 | 33 | |
| 34 | −/** | |
| 35 | − * ehci_xilinx_of_setup - Initialize the device for ehci_reset() | |
| 36 | − * @hcd: Pointer to the usb_hcd device to which the host controller bound | |
| 37 | − * | |
| 38 | − * called during probe() after chip reset completes. | |
| 39 | − */ | |
| 40 | −static int ehci_xilinx_of_setup(struct usb_hcd *hcd) | |
| 41 | −{ | |
| 42 | − struct ehci_hcd *ehci = hcd_to_ehci(hcd); | |
| 43 | − int retval; | |
| 44 | − | |
| 45 | − retval = ehci_halt(ehci); | |
| 46 | − if (retval) | |
| 47 | − return retval; | |
| 48 | − | |
| 49 | − retval = ehci_init(hcd); | |
| 50 | − if (retval) | |
| 51 | − return retval; | |
| 52 | − | |
| 53 | − ehci->sbrn = 0x20; | |
| 54 | − | |
| 55 | − return ehci_reset(ehci); | |
| 56 | −} | |
| 57 | − | |
| 58 | 34 | /** |
| 59 | 35 | * ehci_xilinx_port_handed_over - hand the port out if failed to enable it |
| 60 | 36 | * @hcd: Pointer to the usb_hcd device to which the host controller bound |
| @@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { · 46 unmodified lines | ||
| 107 | 83 | /* |
| 108 | 84 | * basic lifecycle operations |
| 109 | 85 | */ |
| 110 | − .reset = ehci_xilinx_of_setup, | |
| 86 | + .reset = ehci_setup, | |
| 111 | 87 | .start = ehci_run, |
| 112 | 88 | .stop = ehci_stop, |
| 113 | 89 | .shutdown = ehci_shutdown, |
| @@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) · 105 unmodified lines | ||
| 219 | 195 | /* Debug registers are at the first 0x100 region |
| 220 | 196 | */ |
| 221 | 197 | ehci->caps = hcd->regs + 0x100; |
| 222 | − ehci->regs = hcd->regs + 0x100 + | |
| 223 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 224 | − | |
| 225 | − /* cache this readonly data; minimize chip reads */ | |
| 226 | − ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | |
| 227 | 198 | |
| 228 | 199 | rv = usb_add_hcd(hcd, irq, 0); |
| 229 | 200 | if (rv == 0) |
| @@ -14,30 +14,11 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | static int ehci_xls_setup(struct usb_hcd *hcd) |
| 16 | 16 | { |
| 17 | − int retval; | |
| 18 | 17 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 19 | 18 | |
| 20 | 19 | ehci->caps = hcd->regs; |
| 21 | − ehci->regs = hcd->regs + | |
| 22 | − HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | |
| 23 | − dbg_hcs_params(ehci, "reset"); | |
| 24 | − dbg_hcc_params(ehci, "reset"); | |
| 25 | 20 | |
| 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; | |
| 21 | + return ehci_setup(hcd); | |
| 41 | 22 | } |
| 42 | 23 | |
| 43 | 24 | int ehci_xls_probe_internal(const struct hc_driver *driver, |
| @@ -42,7 +42,7 @@ struct ehci_stats { · 41 unmodified lines | ||
| 42 | 42 | /* irq usage */ |
| 43 | 43 | unsigned long normal; |
| 44 | 44 | unsigned long error; |
| 45 | − unsigned long reclaim; | |
| 45 | + unsigned long iaa; | |
| 46 | 46 | unsigned long lost_iaa; |
| 47 | 47 | |
| 48 | 48 | /* termination of urbs from core */ |
| @@ -51,7 +51,7 @@ struct ehci_stats { · 2 unmodified lines | ||
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | 53 | /* ehci_hcd->lock guards shared data against other CPUs: |
| 54 | − * ehci_hcd: async, reclaim, periodic (and shadow), ... | |
| 54 | + * ehci_hcd: async, unlink, periodic (and shadow), ... | |
| 55 | 55 | * usb_host_endpoint: hcpriv |
| 56 | 56 | * ehci_qh: qh_next, qtd_list |
| 57 | 57 | * ehci_qtd: qtd_list |
| @@ -62,13 +62,48 @@ struct ehci_stats { · 4 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ |
| 64 | 64 | |
| 65 | +/* | |
| 66 | + * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the | |
| 67 | + * controller may be doing DMA. Lower values mean there's no DMA. | |
| 68 | + */ | |
| 65 | 69 | enum ehci_rh_state { |
| 66 | 70 | EHCI_RH_HALTED, |
| 67 | 71 | EHCI_RH_SUSPENDED, |
| 68 | − EHCI_RH_RUNNING | |
| 72 | + EHCI_RH_RUNNING, | |
| 73 | + EHCI_RH_STOPPING | |
| 69 | 74 | }; |
| 70 | 75 | |
| 76 | +/* | |
| 77 | + * Timer events, ordered by increasing delay length. | |
| 78 | + * Always update event_delays_ns[] and event_handlers[] (defined in | |
| 79 | + * ehci-timer.c) in parallel with this list. | |
| 80 | + */ | |
| 81 | +enum ehci_hrtimer_event { | |
| 82 | + EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */ | |
| 83 | + EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ | |
| 84 | + EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ | |
| 85 | + EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ | |
| 86 | + EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ | |
| 87 | + EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ | |
| 88 | + EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ | |
| 89 | + EHCI_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ | |
| 90 | + EHCI_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ | |
| 91 | + EHCI_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ | |
| 92 | + EHCI_HRTIMER_NUM_EVENTS /* Must come last */ | |
| 93 | +}; | |
| 94 | +#define EHCI_HRTIMER_NO_EVENT 99 | |
| 95 | + | |
| 71 | 96 | struct ehci_hcd { /* one per controller */ |
| 97 | + /* timing support */ | |
| 98 | + enum ehci_hrtimer_event next_hrtimer_event; | |
| 99 | + unsigned enabled_hrtimer_events; | |
| 100 | + ktime_t hr_timeouts[EHCI_HRTIMER_NUM_EVENTS]; | |
| 101 | + struct hrtimer hrtimer; | |
| 102 | + | |
| 103 | + int PSS_poll_count; | |
| 104 | + int ASS_poll_count; | |
| 105 | + int died_poll_count; | |
| 106 | + | |
| 72 | 107 | /* glue to PCI and HCD framework */ |
| 73 | 108 | struct ehci_caps __iomem *caps; |
| 74 | 109 | struct ehci_regs __iomem *regs; |
| @@ -78,30 +113,48 @@ struct ehci_hcd { /* one per controller */ · 3 unmodified lines | ||
| 78 | 113 | spinlock_t lock; |
| 79 | 114 | enum ehci_rh_state rh_state; |
| 80 | 115 | |
| 116 | + /* general schedule support */ | |
| 117 | + bool scanning:1; | |
| 118 | + bool need_rescan:1; | |
| 119 | + bool intr_unlinking:1; | |
| 120 | + bool async_unlinking:1; | |
| 121 | + bool shutdown:1; | |
| 122 | + struct ehci_qh *qh_scan_next; | |
| 123 | + | |
| 81 | 124 | /* async schedule support */ |
| 82 | 125 | struct ehci_qh *async; |
| 83 | 126 | struct ehci_qh *dummy; /* For AMD quirk use */ |
| 84 | − struct ehci_qh *reclaim; | |
| 85 | − struct ehci_qh *qh_scan_next; | |
| 86 | − unsigned scanning : 1; | |
| 127 | + struct ehci_qh *async_unlink; | |
| 128 | + struct ehci_qh *async_unlink_last; | |
| 129 | + struct ehci_qh *async_iaa; | |
| 130 | + unsigned async_unlink_cycle; | |
| 131 | + unsigned async_count; /* async activity count */ | |
| 87 | 132 | |
| 88 | 133 | /* periodic schedule support */ |
| 89 | 134 | #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ |
| 90 | 135 | unsigned periodic_size; |
| 91 | 136 | __hc32 *periodic; /* hw periodic table */ |
| 92 | 137 | dma_addr_t periodic_dma; |
| 138 | + struct list_head intr_qh_list; | |
| 93 | 139 | unsigned i_thresh; /* uframes HC might cache */ |
| 94 | 140 | |
| 95 | 141 | union ehci_shadow *pshadow; /* mirror hw periodic table */ |
| 96 | − int next_uframe; /* scan periodic, start here */ | |
| 97 | − unsigned periodic_sched; /* periodic activity count */ | |
| 142 | + struct ehci_qh *intr_unlink; | |
| 143 | + struct ehci_qh *intr_unlink_last; | |
| 144 | + unsigned intr_unlink_cycle; | |
| 145 | + unsigned now_frame; /* frame from HC hardware */ | |
| 146 | + unsigned next_frame; /* scan periodic, start here */ | |
| 147 | + unsigned intr_count; /* intr activity count */ | |
| 148 | + unsigned isoc_count; /* isoc activity count */ | |
| 149 | + unsigned periodic_count; /* periodic activity count */ | |
| 98 | 150 | unsigned uframe_periodic_max; /* max periodic time per uframe */ |
| 99 | 151 | |
| 100 | 152 | |
| 101 | − /* list of itds & sitds completed while clock_frame was still active */ | |
| 153 | + /* list of itds & sitds completed while now_frame was still active */ | |
| 102 | 154 | struct list_head cached_itd_list; |
| 155 | + struct ehci_itd *last_itd_to_free; | |
| 103 | 156 | struct list_head cached_sitd_list; |
| 104 | − unsigned clock_frame; | |
| 157 | + struct ehci_sitd *last_sitd_to_free; | |
| 105 | 158 | |
| 106 | 159 | /* per root hub port */ |
| 107 | 160 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; |
| @@ -126,10 +179,6 @@ struct ehci_hcd { /* one per controller */ · 18 unmodified lines | ||
| 126 | 179 | struct dma_pool *itd_pool; /* itd per iso urb */ |
| 127 | 180 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ |
| 128 | 181 | |
| 129 | − struct timer_list iaa_watchdog; | |
| 130 | − struct timer_list watchdog; | |
| 131 | − unsigned long actions; | |
| 132 | − unsigned periodic_stamp; | |
| 133 | 182 | unsigned random_frame; |
| 134 | 183 | unsigned long next_statechange; |
| 135 | 184 | ktime_t last_periodic_enable; |
| @@ -143,7 +192,6 @@ struct ehci_hcd { /* one per controller */ · 7 unmodified lines | ||
| 143 | 192 | unsigned big_endian_capbase:1; |
| 144 | 193 | unsigned has_amcc_usb23:1; |
| 145 | 194 | unsigned need_io_watchdog:1; |
| 146 | − unsigned broken_periodic:1; | |
| 147 | 195 | unsigned amd_pll_fix:1; |
| 148 | 196 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ |
| 149 | 197 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ |
| @@ -175,10 +223,6 @@ struct ehci_hcd { /* one per controller */ · 25 unmodified lines | ||
| 175 | 223 | #ifdef DEBUG |
| 176 | 224 | struct dentry *debug_dir; |
| 177 | 225 | #endif |
| 178 | − /* | |
| 179 | − * OTG controllers and transceivers need software interaction | |
| 180 | − */ | |
| 181 | − struct usb_phy *transceiver; | |
| 182 | 226 | }; |
| 183 | 227 | |
| 184 | 228 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
| @@ -191,34 +235,6 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) · 6 unmodified lines | ||
| 191 | 235 | return container_of ((void *) ehci, struct usb_hcd, hcd_priv); |
| 192 | 236 | } |
| 193 | 237 | |
| 194 | − | |
| 195 | −static inline void | |
| 196 | −iaa_watchdog_start(struct ehci_hcd *ehci) | |
| 197 | −{ | |
| 198 | − WARN_ON(timer_pending(&ehci->iaa_watchdog)); | |
| 199 | − mod_timer(&ehci->iaa_watchdog, | |
| 200 | − jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); | |
| 201 | −} | |
| 202 | − | |
| 203 | −static inline void iaa_watchdog_done(struct ehci_hcd *ehci) | |
| 204 | −{ | |
| 205 | − del_timer(&ehci->iaa_watchdog); | |
| 206 | −} | |
| 207 | − | |
| 208 | −enum ehci_timer_action { | |
| 209 | − TIMER_IO_WATCHDOG, | |
| 210 | − TIMER_ASYNC_SHRINK, | |
| 211 | − TIMER_ASYNC_OFF, | |
| 212 | −}; | |
| 213 | − | |
| 214 | −static inline void | |
| 215 | −timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) | |
| 216 | −{ | |
| 217 | − clear_bit (action, &ehci->actions); | |
| 218 | −} | |
| 219 | − | |
| 220 | −static void free_cached_lists(struct ehci_hcd *ehci); | |
| 221 | − | |
| 222 | 238 | /*-------------------------------------------------------------------------*/ |
| 223 | 239 | |
| 224 | 240 | #include <linux/usb/ehci_def.h> |
| @@ -328,7 +344,13 @@ union ehci_shadow { · 103 unmodified lines | ||
| 328 | 344 | struct ehci_qh_hw { |
| 329 | 345 | __hc32 hw_next; /* see EHCI 3.6.1 */ |
| 330 | 346 | __hc32 hw_info1; /* see EHCI 3.6.2 */ |
| 331 | −#define QH_HEAD 0x00008000 | |
| 347 | +#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ | |
| 348 | +#define QH_HEAD (1 << 15) /* Head of async reclamation list */ | |
| 349 | +#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ | |
| 350 | +#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ | |
| 351 | +#define QH_LOW_SPEED (1 << 12) | |
| 352 | +#define QH_FULL_SPEED (0 << 12) | |
| 353 | +#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ | |
| 332 | 354 | __hc32 hw_info2; /* see EHCI 3.6.2 */ |
| 333 | 355 | #define QH_SMASK 0x000000ff |
| 334 | 356 | #define QH_CMASK 0x0000ff00 |
| @@ -346,32 +368,23 @@ struct ehci_qh_hw { · 11 unmodified lines | ||
| 346 | 368 | } __attribute__ ((aligned(32))); |
| 347 | 369 | |
| 348 | 370 | struct ehci_qh { |
| 349 | − struct ehci_qh_hw *hw; | |
| 371 | + struct ehci_qh_hw *hw; /* Must come first */ | |
| 350 | 372 | /* the rest is HCD-private */ |
| 351 | 373 | dma_addr_t qh_dma; /* address of qh */ |
| 352 | 374 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ |
| 353 | 375 | struct list_head qtd_list; /* sw qtd list */ |
| 376 | + struct list_head intr_node; /* list of intr QHs */ | |
| 354 | 377 | struct ehci_qtd *dummy; |
| 355 | − struct ehci_qh *reclaim; /* next to reclaim */ | |
| 356 | − | |
| 357 | − struct ehci_hcd *ehci; | |
| 358 | − unsigned long unlink_time; | |
| 378 | + struct ehci_qh *unlink_next; /* next on unlink list */ | |
| 359 | 379 | |
| 360 | − /* | |
| 361 | − * Do NOT use atomic operations for QH refcounting. On some CPUs | |
| 362 | − * (PPC7448 for example), atomic operations cannot be performed on | |
| 363 | − * memory that is cache-inhibited (i.e. being used for DMA). | |
| 364 | − * Spinlocks are used to protect all QH fields. | |
| 365 | − */ | |
| 366 | − u32 refcount; | |
| 367 | − unsigned stamp; | |
| 380 | + unsigned unlink_cycle; | |
| 368 | 381 | |
| 369 | 382 | u8 needs_rescan; /* Dequeue during giveback */ |
| 370 | 383 | u8 qh_state; |
| 371 | 384 | #define QH_STATE_LINKED 1 /* HC sees this */ |
| 372 | 385 | #define QH_STATE_UNLINK 2 /* HC may still see this */ |
| 373 | 386 | #define QH_STATE_IDLE 3 /* HC doesn't see this */ |
| 374 | −#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ | |
| 387 | +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */ | |
| 375 | 388 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ |
| 376 | 389 | |
| 377 | 390 | u8 xacterrs; /* XactErr retry counter */ |
| @@ -421,7 +434,6 @@ struct ehci_iso_stream { · 43 unmodified lines | ||
| 421 | 434 | /* first field matches ehci_hq, but is NULL */ |
| 422 | 435 | struct ehci_qh_hw *hw; |
| 423 | 436 | |
| 424 | − u32 refcount; | |
| 425 | 437 | u8 bEndpointAddress; |
| 426 | 438 | u8 highspeed; |
| 427 | 439 | struct list_head td_list; /* queued itds/sitds */ |
| @@ -41,7 +41,7 @@ void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) · 40 unmodified lines | ||
| 41 | 41 | static int fhci_dfs_regs_show(struct seq_file *s, void *v) |
| 42 | 42 | { |
| 43 | 43 | struct fhci_hcd *fhci = s->private; |
| 44 | − struct fhci_regs __iomem *regs = fhci->regs; | |
| 44 | + struct qe_usb_ctlr __iomem *regs = fhci->regs; | |
| 45 | 45 | |
| 46 | 46 | seq_printf(s, |
| 47 | 47 | "mode: 0x%x\n" "addr: 0x%x\n" |
| @@ -50,11 +50,11 @@ static int fhci_dfs_regs_show(struct seq_file *s, void *v) · 2 unmodified lines | ||
| 50 | 50 | "status: 0x%x\n" "SOF timer: %d\n" |
| 51 | 51 | "frame number: %d\n" |
| 52 | 52 | "lines status: 0x%x\n", |
| 53 | − in_8(®s->usb_mod), in_8(®s->usb_addr), | |
| 54 | − in_8(®s->usb_comm), in_be16(®s->usb_ep[0]), | |
| 55 | − in_be16(®s->usb_event), in_be16(®s->usb_mask), | |
| 56 | − in_8(®s->usb_status), in_be16(®s->usb_sof_tmr), | |
| 57 | − in_be16(®s->usb_frame_num), | |
| 53 | + in_8(®s->usb_usmod), in_8(®s->usb_usadr), | |
| 54 | + in_8(®s->usb_uscom), in_be16(®s->usb_usep[0]), | |
| 55 | + in_be16(®s->usb_usber), in_be16(®s->usb_usbmr), | |
| 56 | + in_8(®s->usb_usbs), in_be16(®s->usb_ussft), | |
| 57 | + in_be16(®s->usb_usfrn), | |
| 58 | 58 | fhci_ioports_check_bus_state(fhci)); |
| 59 | 59 | |
| 60 | 60 | return 0; |
| @@ -40,8 +40,8 @@ void fhci_start_sof_timer(struct fhci_hcd *fhci) · 39 unmodified lines | ||
| 40 | 40 | /* clear frame_n */ |
| 41 | 41 | out_be16(&fhci->pram->frame_num, 0); |
| 42 | 42 | |
| 43 | − out_be16(&fhci->regs->usb_sof_tmr, 0); | |
| 44 | − setbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | |
| 43 | + out_be16(&fhci->regs->usb_ussft, 0); | |
| 44 | + setbits8(&fhci->regs->usb_usmod, USB_MODE_SFTE); | |
| 45 | 45 | |
| 46 | 46 | fhci_dbg(fhci, "<- %s\n", __func__); |
| 47 | 47 | } |
| @@ -50,7 +50,7 @@ void fhci_stop_sof_timer(struct fhci_hcd *fhci) · 2 unmodified lines | ||
| 50 | 50 | { |
| 51 | 51 | fhci_dbg(fhci, "-> %s\n", __func__); |
| 52 | 52 | |
| 53 | − clrbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | |
| 53 | + clrbits8(&fhci->regs->usb_usmod, USB_MODE_SFTE); | |
| 54 | 54 | gtm_stop_timer16(fhci->timer); |
| 55 | 55 | |
| 56 | 56 | fhci_dbg(fhci, "<- %s\n", __func__); |
| @@ -58,7 +58,7 @@ void fhci_stop_sof_timer(struct fhci_hcd *fhci) · 1 unmodified line | ||
| 58 | 58 | |
| 59 | 59 | u16 fhci_get_sof_timer_count(struct fhci_usb *usb) |
| 60 | 60 | { |
| 61 | − return be16_to_cpu(in_be16(&usb->fhci->regs->usb_sof_tmr) / 12); | |
| 61 | + return be16_to_cpu(in_be16(&usb->fhci->regs->usb_ussft) / 12); | |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | /* initialize the endpoint zero */ |
| @@ -88,8 +88,8 @@ void fhci_usb_enable_interrupt(struct fhci_usb *usb) · 23 unmodified lines | ||
| 88 | 88 | enable_irq(fhci_to_hcd(fhci)->irq); |
| 89 | 89 | |
| 90 | 90 | /* initialize the event register and mask register */ |
| 91 | − out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
| 92 | − out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | |
| 91 | + out_be16(&usb->fhci->regs->usb_usber, 0xffff); | |
| 92 | + out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk); | |
| 93 | 93 | |
| 94 | 94 | /* enable the timer interrupts */ |
| 95 | 95 | enable_irq(fhci->timer->irq); |
| @@ -109,7 +109,7 @@ void fhci_usb_disable_interrupt(struct fhci_usb *usb) · 13 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | /* disable the usb interrupt */ |
| 111 | 111 | disable_irq_nosync(fhci_to_hcd(fhci)->irq); |
| 112 | − out_be16(&usb->fhci->regs->usb_mask, 0); | |
| 112 | + out_be16(&usb->fhci->regs->usb_usbmr, 0); | |
| 113 | 113 | } |
| 114 | 114 | usb->intr_nesting_cnt++; |
| 115 | 115 | } |
| @@ -119,9 +119,9 @@ static u32 fhci_usb_enable(struct fhci_hcd *fhci) · 3 unmodified lines | ||
| 119 | 119 | { |
| 120 | 120 | struct fhci_usb *usb = fhci->usb_lld; |
| 121 | 121 | |
| 122 | − out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
| 123 | − out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | |
| 124 | − setbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | |
| 122 | + out_be16(&usb->fhci->regs->usb_usber, 0xffff); | |
| 123 | + out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk); | |
| 124 | + setbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN); | |
| 125 | 125 | |
| 126 | 126 | mdelay(100); |
| 127 | 127 | |
| @@ -141,7 +141,7 @@ static u32 fhci_usb_disable(struct fhci_hcd *fhci) · 13 unmodified lines | ||
| 141 | 141 | usb->port_status == FHCI_PORT_LOW) |
| 142 | 142 | fhci_device_disconnected_interrupt(fhci); |
| 143 | 143 | |
| 144 | − clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | |
| 144 | + clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN); | |
| 145 | 145 | |
| 146 | 146 | return 0; |
| 147 | 147 | } |
| @@ -285,13 +285,13 @@ static int fhci_usb_init(struct fhci_hcd *fhci) · 137 unmodified lines | ||
| 285 | 285 | USB_E_IDLE_MASK | |
| 286 | 286 | USB_E_RESET_MASK | USB_E_SFT_MASK | USB_E_MSF_MASK); |
| 287 | 287 | |
| 288 | − out_8(&usb->fhci->regs->usb_mod, USB_MODE_HOST | USB_MODE_EN); | |
| 288 | + out_8(&usb->fhci->regs->usb_usmod, USB_MODE_HOST | USB_MODE_EN); | |
| 289 | 289 | |
| 290 | 290 | /* clearing the mask register */ |
| 291 | − out_be16(&usb->fhci->regs->usb_mask, 0); | |
| 291 | + out_be16(&usb->fhci->regs->usb_usbmr, 0); | |
| 292 | 292 | |
| 293 | 293 | /* initialing the event register */ |
| 294 | − out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
| 294 | + out_be16(&usb->fhci->regs->usb_usber, 0xffff); | |
| 295 | 295 | |
| 296 | 296 | if (endpoint_zero_init(usb, DEFAULT_DATA_MEM, DEFAULT_RING_LEN) != 0) { |
| 297 | 297 | fhci_usb_free(usb); |
| @@ -745,8 +745,8 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev) · 447 unmodified lines | ||
| 745 | 745 | } |
| 746 | 746 | |
| 747 | 747 | /* Clear and disable any pending interrupts. */ |
| 748 | − out_be16(&fhci->regs->usb_event, 0xffff); | |
| 749 | − out_be16(&fhci->regs->usb_mask, 0); | |
| 748 | + out_be16(&fhci->regs->usb_usber, 0xffff); | |
| 749 | + out_be16(&fhci->regs->usb_usbmr, 0); | |
| 750 | 750 | |
| 751 | 751 | ret = usb_add_hcd(hcd, usb_irq, 0); |
| 752 | 752 | if (ret < 0) |
| @@ -97,7 +97,7 @@ void fhci_port_disable(struct fhci_hcd *fhci) · 96 unmodified lines | ||
| 97 | 97 | |
| 98 | 98 | /* Enable IDLE since we want to know if something comes along */ |
| 99 | 99 | usb->saved_msk |= USB_E_IDLE_MASK; |
| 100 | − out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | |
| 100 | + out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk); | |
| 101 | 101 | |
| 102 | 102 | /* check if during the disconnection process attached new device */ |
| 103 | 103 | if (port_status == FHCI_PORT_WAITING) |
| @@ -158,21 +158,21 @@ void fhci_port_reset(void *lld) · 54 unmodified lines | ||
| 158 | 158 | |
| 159 | 159 | fhci_stop_sof_timer(fhci); |
| 160 | 160 | /* disable the USB controller */ |
| 161 | − mode = in_8(&fhci->regs->usb_mod); | |
| 162 | − out_8(&fhci->regs->usb_mod, mode & (~USB_MODE_EN)); | |
| 161 | + mode = in_8(&fhci->regs->usb_usmod); | |
| 162 | + out_8(&fhci->regs->usb_usmod, mode & (~USB_MODE_EN)); | |
| 163 | 163 | |
| 164 | 164 | /* disable idle interrupts */ |
| 165 | − mask = in_be16(&fhci->regs->usb_mask); | |
| 166 | − out_be16(&fhci->regs->usb_mask, mask & (~USB_E_IDLE_MASK)); | |
| 165 | + mask = in_be16(&fhci->regs->usb_usbmr); | |
| 166 | + out_be16(&fhci->regs->usb_usbmr, mask & (~USB_E_IDLE_MASK)); | |
| 167 | 167 | |
| 168 | 168 | fhci_io_port_generate_reset(fhci); |
| 169 | 169 | |
| 170 | 170 | /* enable interrupt on this endpoint */ |
| 171 | − out_be16(&fhci->regs->usb_mask, mask); | |
| 171 | + out_be16(&fhci->regs->usb_usbmr, mask); | |
| 172 | 172 | |
| 173 | 173 | /* enable the USB controller */ |
| 174 | − mode = in_8(&fhci->regs->usb_mod); | |
| 175 | − out_8(&fhci->regs->usb_mod, mode | USB_MODE_EN); | |
| 174 | + mode = in_8(&fhci->regs->usb_usmod); | |
| 175 | + out_8(&fhci->regs->usb_usmod, mode | USB_MODE_EN); | |
| 176 | 176 | fhci_start_sof_timer(fhci); |
| 177 | 177 | |
| 178 | 178 | fhci_dbg(fhci, "<- %s\n", __func__); |
| @@ -132,8 +132,8 @@ void fhci_flush_all_transmissions(struct fhci_usb *usb) · 131 unmodified lines | ||
| 132 | 132 | u8 mode; |
| 133 | 133 | struct td *td; |
| 134 | 134 | |
| 135 | − mode = in_8(&usb->fhci->regs->usb_mod); | |
| 136 | − clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | |
| 135 | + mode = in_8(&usb->fhci->regs->usb_usmod); | |
| 136 | + clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN); | |
| 137 | 137 | |
| 138 | 138 | fhci_flush_bds(usb); |
| 139 | 139 | |
| @@ -147,9 +147,9 @@ void fhci_flush_all_transmissions(struct fhci_usb *usb) · 7 unmodified lines | ||
| 147 | 147 | usb->actual_frame->frame_status = FRAME_END_TRANSMISSION; |
| 148 | 148 | |
| 149 | 149 | /* reset the event register */ |
| 150 | − out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
| 150 | + out_be16(&usb->fhci->regs->usb_usber, 0xffff); | |
| 151 | 151 | /* enable the USB controller */ |
| 152 | − out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | |
| 152 | + out_8(&usb->fhci->regs->usb_usmod, mode | USB_MODE_EN); | |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | 155 | /* |
| @@ -414,7 +414,7 @@ static void sof_interrupt(struct fhci_hcd *fhci) · 258 unmodified lines | ||
| 414 | 414 | usb->port_status = FHCI_PORT_FULL; |
| 415 | 415 | /* Disable IDLE */ |
| 416 | 416 | usb->saved_msk &= ~USB_E_IDLE_MASK; |
| 417 | − out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | |
| 417 | + out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk); | |
| 418 | 418 | } |
| 419 | 419 | |
| 420 | 420 | gtm_set_exact_timer16(fhci->timer, usb->max_frame_usage, false); |
| @@ -433,14 +433,14 @@ void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci) · 12 unmodified lines | ||
| 433 | 433 | fhci_dbg(fhci, "-> %s\n", __func__); |
| 434 | 434 | |
| 435 | 435 | fhci_usb_disable_interrupt(usb); |
| 436 | − clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | |
| 436 | + clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS); | |
| 437 | 437 | usb->port_status = FHCI_PORT_DISABLED; |
| 438 | 438 | |
| 439 | 439 | fhci_stop_sof_timer(fhci); |
| 440 | 440 | |
| 441 | 441 | /* Enable IDLE since we want to know if something comes along */ |
| 442 | 442 | usb->saved_msk |= USB_E_IDLE_MASK; |
| 443 | − out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | |
| 443 | + out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk); | |
| 444 | 444 | |
| 445 | 445 | usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_CONNECTION; |
| 446 | 446 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_CONNECTION; |
| @@ -473,7 +473,7 @@ void fhci_device_connected_interrupt(struct fhci_hcd *fhci) · 26 unmodified lines | ||
| 473 | 473 | } |
| 474 | 474 | |
| 475 | 475 | usb->port_status = FHCI_PORT_LOW; |
| 476 | − setbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | |
| 476 | + setbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS); | |
| 477 | 477 | usb->vroot_hub->port.wPortStatus |= |
| 478 | 478 | (USB_PORT_STAT_LOW_SPEED | |
| 479 | 479 | USB_PORT_STAT_CONNECTION); |
| @@ -491,7 +491,7 @@ void fhci_device_connected_interrupt(struct fhci_hcd *fhci) · 11 unmodified lines | ||
| 491 | 491 | } |
| 492 | 492 | |
| 493 | 493 | usb->port_status = FHCI_PORT_FULL; |
| 494 | − clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | |
| 494 | + clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS); | |
| 495 | 495 | usb->vroot_hub->port.wPortStatus &= |
| 496 | 496 | ~USB_PORT_STAT_LOW_SPEED; |
| 497 | 497 | usb->vroot_hub->port.wPortStatus |= |
| @@ -535,7 +535,7 @@ static void abort_transmission(struct fhci_usb *usb) · 37 unmodified lines | ||
| 535 | 535 | /* issue stop Tx command */ |
| 536 | 536 | qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0); |
| 537 | 537 | /* flush Tx FIFOs */ |
| 538 | − out_8(&usb->fhci->regs->usb_comm, USB_CMD_FLUSH_FIFO | EP_ZERO); | |
| 538 | + out_8(&usb->fhci->regs->usb_uscom, USB_CMD_FLUSH_FIFO | EP_ZERO); | |
| 539 | 539 | udelay(1000); |
| 540 | 540 | /* reset Tx BDs */ |
| 541 | 541 | fhci_flush_bds(usb); |
| @@ -555,11 +555,11 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) · 13 unmodified lines | ||
| 555 | 555 | |
| 556 | 556 | usb = fhci->usb_lld; |
| 557 | 557 | |
| 558 | − usb_er |= in_be16(&usb->fhci->regs->usb_event) & | |
| 559 | − in_be16(&usb->fhci->regs->usb_mask); | |
| 558 | + usb_er |= in_be16(&usb->fhci->regs->usb_usber) & | |
| 559 | + in_be16(&usb->fhci->regs->usb_usbmr); | |
| 560 | 560 | |
| 561 | 561 | /* clear event bits for next time */ |
| 562 | − out_be16(&usb->fhci->regs->usb_event, usb_er); | |
| 562 | + out_be16(&usb->fhci->regs->usb_usber, usb_er); | |
| 563 | 563 | |
| 564 | 564 | fhci_dbg_isr(fhci, usb_er); |
| 565 | 565 | |
| @@ -573,7 +573,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) · 7 unmodified lines | ||
| 573 | 573 | |
| 574 | 574 | /* Turn on IDLE since we want to disconnect */ |
| 575 | 575 | usb->saved_msk |= USB_E_IDLE_MASK; |
| 576 | − out_be16(&usb->fhci->regs->usb_event, | |
| 576 | + out_be16(&usb->fhci->regs->usb_usber, | |
| 577 | 577 | usb->saved_msk); |
| 578 | 578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { |
| 579 | 579 | if (fhci_ioports_check_bus_state(fhci) == 1) |
| @@ -611,7 +611,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) · 31 unmodified lines | ||
| 611 | 611 | /* XXX usb->port_status = FHCI_PORT_WAITING; */ |
| 612 | 612 | /* Disable IDLE */ |
| 613 | 613 | usb->saved_msk &= ~USB_E_IDLE_MASK; |
| 614 | − out_be16(&usb->fhci->regs->usb_mask, | |
| 614 | + out_be16(&usb->fhci->regs->usb_usbmr, | |
| 615 | 615 | usb->saved_msk); |
| 616 | 616 | } else { |
| 617 | 617 | fhci_dbg_isr(fhci, -1); |
| @@ -249,7 +249,7 @@ void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, · 248 unmodified lines | ||
| 249 | 249 | u8 rt; |
| 250 | 250 | |
| 251 | 251 | /* set the endpoint registers according to the endpoint */ |
| 252 | − out_be16(&usb->fhci->regs->usb_ep[0], | |
| 252 | + out_be16(&usb->fhci->regs->usb_usep[0], | |
| 253 | 253 | USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE); |
| 254 | 254 | out_be16(&usb->fhci->pram->ep_ptr[0], |
| 255 | 255 | cpm_muram_offset(ep->ep_pram_ptr)); |
| @@ -463,7 +463,7 @@ u32 fhci_host_transaction(struct fhci_usb *usb, · 207 unmodified lines | ||
| 463 | 463 | cq_put(&ep->conf_frame_Q, pkt); |
| 464 | 464 | |
| 465 | 465 | if (cq_howmany(&ep->conf_frame_Q) == 1) |
| 466 | − out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | |
| 466 | + out_8(&usb->fhci->regs->usb_uscom, USB_CMD_STR_FIFO); | |
| 467 | 467 | |
| 468 | 468 | return 0; |
| 469 | 469 | } |
| @@ -535,8 +535,8 @@ void fhci_flush_actual_frame(struct fhci_usb *usb) · 65 unmodified lines | ||
| 535 | 535 | struct endpoint *ep = usb->ep0; |
| 536 | 536 | |
| 537 | 537 | /* disable the USB controller */ |
| 538 | − mode = in_8(&usb->fhci->regs->usb_mod); | |
| 539 | − out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN); | |
| 538 | + mode = in_8(&usb->fhci->regs->usb_usmod); | |
| 539 | + out_8(&usb->fhci->regs->usb_usmod, mode & ~USB_MODE_EN); | |
| 540 | 540 | |
| 541 | 541 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); |
| 542 | 542 | td = cpm_muram_addr(tb_ptr); |
| @@ -571,9 +571,9 @@ void fhci_flush_actual_frame(struct fhci_usb *usb) · 28 unmodified lines | ||
| 571 | 571 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; |
| 572 | 572 | |
| 573 | 573 | /* reset the event register */ |
| 574 | − out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
| 574 | + out_be16(&usb->fhci->regs->usb_usber, 0xffff); | |
| 575 | 575 | /* enable the USB controller */ |
| 576 | − out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | |
| 576 | + out_8(&usb->fhci->regs->usb_usmod, mode | USB_MODE_EN); | |
| 577 | 577 | } |
| 578 | 578 | |
| 579 | 579 | /* handles Tx confirm and Tx error interrupt */ |
| @@ -613,7 +613,7 @@ void fhci_host_transmit_actual_frame(struct fhci_usb *usb) · 33 unmodified lines | ||
| 613 | 613 | |
| 614 | 614 | /* start transmit only if we have something in the TDs */ |
| 615 | 615 | if (in_be16(&td->status) & TD_R) |
| 616 | − out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | |
| 616 | + out_8(&usb->fhci->regs->usb_uscom, USB_CMD_STR_FIFO); | |
| 617 | 617 | |
| 618 | 618 | if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) { |
| 619 | 619 | out_be32(&old_td->buf_ptr, 0); |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/usb.h> |
| 29 | 29 | #include <linux/usb/hcd.h> |
| 30 | 30 | #include <asm/qe.h> |
| 31 | +#include <asm/immap_qe.h> | |
| 31 | 32 | |
| 32 | 33 | #define USB_CLOCK 48000000 |
| 33 | 34 | |
| @@ -173,25 +174,6 @@ · 139 unmodified lines | ||
| 173 | 174 | #define USB_E_TXB_MASK 0x0002 |
| 174 | 175 | #define USB_E_RXB_MASK 0x0001 |
| 175 | 176 | |
| 176 | −/* Freescale USB Host controller registers */ | |
| 177 | −struct fhci_regs { | |
| 178 | − u8 usb_mod; /* mode register */ | |
| 179 | − u8 usb_addr; /* address register */ | |
| 180 | − u8 usb_comm; /* command register */ | |
| 181 | − u8 reserved1[1]; | |
| 182 | − __be16 usb_ep[4]; /* endpoint register */ | |
| 183 | − u8 reserved2[4]; | |
| 184 | − __be16 usb_event; /* event register */ | |
| 185 | − u8 reserved3[2]; | |
| 186 | − __be16 usb_mask; /* mask register */ | |
| 187 | − u8 reserved4[1]; | |
| 188 | − u8 usb_status; /* status register */ | |
| 189 | − __be16 usb_sof_tmr; /* Start Of Frame timer */ | |
| 190 | − u8 reserved5[2]; | |
| 191 | − __be16 usb_frame_num; /* frame number register */ | |
| 192 | − u8 reserved6[1]; | |
| 193 | −}; | |
| 194 | − | |
| 195 | 177 | /* Freescale USB HOST */ |
| 196 | 178 | struct fhci_pram { |
| 197 | 179 | __be16 ep_ptr[4]; /* Endpoint porter reg */ |
| @@ -267,7 +249,7 @@ struct fhci_hcd { · 69 unmodified lines | ||
| 267 | 249 | int gpios[NUM_GPIOS]; |
| 268 | 250 | bool alow_gpios[NUM_GPIOS]; |
| 269 | 251 | |
| 270 | − struct fhci_regs __iomem *regs; /* I/O memory used to communicate */ | |
| 252 | + struct qe_usb_ctlr __iomem *regs; /* I/O memory used to communicate */ | |
| 271 | 253 | struct fhci_pram __iomem *pram; /* Parameter RAM */ |
| 272 | 254 | struct gtm_timer *timer; |
| 273 | 255 | |
| @@ -1811,7 +1811,7 @@ static int imx21_remove(struct platform_device *pdev) · 1810 unmodified lines | ||
| 1811 | 1811 | usb_remove_hcd(hcd); |
| 1812 | 1812 | |
| 1813 | 1813 | if (res != NULL) { |
| 1814 | − clk_disable(imx21->clk); | |
| 1814 | + clk_disable_unprepare(imx21->clk); | |
| 1815 | 1815 | clk_put(imx21->clk); |
| 1816 | 1816 | iounmap(imx21->regs); |
| 1817 | 1817 | release_mem_region(res->start, resource_size(res)); |
| @@ -1884,7 +1884,7 @@ static int imx21_probe(struct platform_device *pdev) · 66 unmodified lines | ||
| 1884 | 1884 | ret = clk_set_rate(imx21->clk, clk_round_rate(imx21->clk, 48000000)); |
| 1885 | 1885 | if (ret) |
| 1886 | 1886 | goto failed_clock_set; |
| 1887 | − ret = clk_enable(imx21->clk); | |
| 1887 | + ret = clk_prepare_enable(imx21->clk); | |
| 1888 | 1888 | if (ret) |
| 1889 | 1889 | goto failed_clock_enable; |
| 1890 | 1890 | |
| @@ -1900,7 +1900,7 @@ static int imx21_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 1900 | 1900 | return 0; |
| 1901 | 1901 | |
| 1902 | 1902 | failed_add_hcd: |
| 1903 | − clk_disable(imx21->clk); | |
| 1903 | + clk_disable_unprepare(imx21->clk); | |
| 1904 | 1904 | failed_clock_enable: |
| 1905 | 1905 | failed_clock_set: |
| 1906 | 1906 | clk_put(imx21->clk); |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | */ |
| 13 | 13 | |
| 14 | 14 | #include <linux/clk.h> |
| 15 | +#include <linux/of.h> | |
| 15 | 16 | #include <linux/platform_device.h> |
| 16 | 17 | #include <mach/ohci.h> |
| 17 | 18 | #include <plat/usb-phy.h> |
| @@ -71,6 +72,8 @@ static const struct hc_driver exynos_ohci_hc_driver = { · 53 unmodified lines | ||
| 71 | 72 | .start_port_reset = ohci_start_port_reset, |
| 72 | 73 | }; |
| 73 | 74 | |
| 75 | +static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32); | |
| 76 | + | |
| 74 | 77 | static int __devinit exynos_ohci_probe(struct platform_device *pdev) |
| 75 | 78 | { |
| 76 | 79 | struct exynos4_ohci_platdata *pdata; |
| @@ -87,7 +90,18 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 87 | 90 | return -EINVAL; |
| 88 | 91 | } |
| 89 | 92 | |
| 90 | − exynos_ohci = kzalloc(sizeof(struct exynos_ohci_hcd), GFP_KERNEL); | |
| 93 | + /* | |
| 94 | + * Right now device-tree probed devices don't get dma_mask set. | |
| 95 | + * Since shared usb code relies on it, set it here for now. | |
| 96 | + * Once we move to full device tree support this will vanish off. | |
| 97 | + */ | |
| 98 | + if (!pdev->dev.dma_mask) | |
| 99 | + pdev->dev.dma_mask = &ohci_exynos_dma_mask; | |
| 100 | + if (!pdev->dev.coherent_dma_mask) | |
| 101 | + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | |
| 102 | + | |
| 103 | + exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd), | |
| 104 | + GFP_KERNEL); | |
| 91 | 105 | if (!exynos_ohci) |
| 92 | 106 | return -ENOMEM; |
| 93 | 107 | |
| @@ -97,8 +111,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 97 | 111 | dev_name(&pdev->dev)); |
| 98 | 112 | if (!hcd) { |
| 99 | 113 | dev_err(&pdev->dev, "Unable to create HCD\n"); |
| 100 | − err = -ENOMEM; | |
| 101 | − goto fail_hcd; | |
| 114 | + return -ENOMEM; | |
| 102 | 115 | } |
| 103 | 116 | |
| 104 | 117 | exynos_ohci->hcd = hcd; |
| @@ -123,7 +136,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) · 18 unmodified lines | ||
| 123 | 136 | |
| 124 | 137 | hcd->rsrc_start = res->start; |
| 125 | 138 | hcd->rsrc_len = resource_size(res); |
| 126 | − hcd->regs = ioremap(res->start, resource_size(res)); | |
| 139 | + hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); | |
| 127 | 140 | if (!hcd->regs) { |
| 128 | 141 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); |
| 129 | 142 | err = -ENOMEM; |
| @@ -134,7 +147,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 134 | 147 | if (!irq) { |
| 135 | 148 | dev_err(&pdev->dev, "Failed to get IRQ\n"); |
| 136 | 149 | err = -ENODEV; |
| 137 | − goto fail; | |
| 150 | + goto fail_io; | |
| 138 | 151 | } |
| 139 | 152 | |
| 140 | 153 | if (pdata->phy_init) |
| @@ -146,23 +159,19 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 146 | 159 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 147 | 160 | if (err) { |
| 148 | 161 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
| 149 | − goto fail; | |
| 162 | + goto fail_io; | |
| 150 | 163 | } |
| 151 | 164 | |
| 152 | 165 | platform_set_drvdata(pdev, exynos_ohci); |
| 153 | 166 | |
| 154 | 167 | return 0; |
| 155 | 168 | |
| 156 | −fail: | |
| 157 | − iounmap(hcd->regs); | |
| 158 | 169 | fail_io: |
| 159 | 170 | clk_disable(exynos_ohci->clk); |
| 160 | 171 | fail_clken: |
| 161 | 172 | clk_put(exynos_ohci->clk); |
| 162 | 173 | fail_clk: |
| 163 | 174 | usb_put_hcd(hcd); |
| 164 | −fail_hcd: | |
| 165 | − kfree(exynos_ohci); | |
| 166 | 175 | return err; |
| 167 | 176 | } |
| 168 | 177 | |
| @@ -177,13 +186,10 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 177 | 186 | if (pdata && pdata->phy_exit) |
| 178 | 187 | pdata->phy_exit(pdev, S5P_USB_PHY_HOST); |
| 179 | 188 | |
| 180 | − iounmap(hcd->regs); | |
| 181 | − | |
| 182 | 189 | clk_disable(exynos_ohci->clk); |
| 183 | 190 | clk_put(exynos_ohci->clk); |
| 184 | 191 | |
| 185 | 192 | usb_put_hcd(hcd); |
| 186 | − kfree(exynos_ohci); | |
| 187 | 193 | |
| 188 | 194 | return 0; |
| 189 | 195 | } |
| @@ -225,6 +231,9 @@ static int exynos_ohci_suspend(struct device *dev) · 35 unmodified lines | ||
| 225 | 231 | |
| 226 | 232 | if (pdata && pdata->phy_exit) |
| 227 | 233 | pdata->phy_exit(pdev, S5P_USB_PHY_HOST); |
| 234 | + | |
| 235 | + clk_disable(exynos_ohci->clk); | |
| 236 | + | |
| 228 | 237 | fail: |
| 229 | 238 | spin_unlock_irqrestore(&ohci->lock, flags); |
| 230 | 239 | |
| @@ -238,6 +247,8 @@ static int exynos_ohci_resume(struct device *dev) · 7 unmodified lines | ||
| 238 | 247 | struct platform_device *pdev = to_platform_device(dev); |
| 239 | 248 | struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; |
| 240 | 249 | |
| 250 | + clk_enable(exynos_ohci->clk); | |
| 251 | + | |
| 241 | 252 | if (pdata && pdata->phy_init) |
| 242 | 253 | pdata->phy_init(pdev, S5P_USB_PHY_HOST); |
| 243 | 254 | |
| @@ -258,6 +269,14 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = { · 14 unmodified lines | ||
| 258 | 269 | .resume = exynos_ohci_resume, |
| 259 | 270 | }; |
| 260 | 271 | |
| 272 | +#ifdef CONFIG_OF | |
| 273 | +static const struct of_device_id exynos_ohci_match[] = { | |
| 274 | + { .compatible = "samsung,exynos-ohci" }, | |
| 275 | + {}, | |
| 276 | +}; | |
| 277 | +MODULE_DEVICE_TABLE(of, exynos_ohci_match); | |
| 278 | +#endif | |
| 279 | + | |
| 261 | 280 | static struct platform_driver exynos_ohci_driver = { |
| 262 | 281 | .probe = exynos_ohci_probe, |
| 263 | 282 | .remove = __devexit_p(exynos_ohci_remove), |
| @@ -266,6 +285,7 @@ static struct platform_driver exynos_ohci_driver = { · 2 unmodified lines | ||
| 266 | 285 | .name = "exynos-ohci", |
| 267 | 286 | .owner = THIS_MODULE, |
| 268 | 287 | .pm = &exynos_ohci_pm_ops, |
| 288 | + .of_match_table = of_match_ptr(exynos_ohci_match), | |
| 269 | 289 | } |
| 270 | 290 | }; |
| 271 | 291 | |
| @@ -43,16 +43,6 @@ · 42 unmodified lines | ||
| 43 | 43 | #define USB_HOST_NEED_CLK_EN (1 << 21) |
| 44 | 44 | #define PAD_CONTROL_LAST_DRIVEN (1 << 19) |
| 45 | 45 | |
| 46 | −#define USB_OTG_CLK_CTRL IO_ADDRESS(USB_CONFIG_BASE + 0xFF4) | |
| 47 | −#define USB_OTG_CLK_STAT IO_ADDRESS(USB_CONFIG_BASE + 0xFF8) | |
| 48 | − | |
| 49 | −/* USB_OTG_CLK_CTRL bit defines */ | |
| 50 | −#define AHB_M_CLOCK_ON (1 << 4) | |
| 51 | −#define OTG_CLOCK_ON (1 << 3) | |
| 52 | −#define I2C_CLOCK_ON (1 << 2) | |
| 53 | −#define DEV_CLOCK_ON (1 << 1) | |
| 54 | −#define HOST_CLOCK_ON (1 << 0) | |
| 55 | − | |
| 56 | 46 | #define USB_OTG_STAT_CONTROL IO_ADDRESS(USB_CONFIG_BASE + 0x110) |
| 57 | 47 | |
| 58 | 48 | /* USB_OTG_STAT_CONTROL bit defines */ |
| @@ -72,7 +62,9 @@ static struct i2c_client *isp1301_i2c_client; · 13 unmodified lines | ||
| 72 | 62 | |
| 73 | 63 | extern int usb_disabled(void); |
| 74 | 64 | |
| 75 | −static struct clk *usb_clk; | |
| 65 | +static struct clk *usb_pll_clk; | |
| 66 | +static struct clk *usb_dev_clk; | |
| 67 | +static struct clk *usb_otg_clk; | |
| 76 | 68 | |
| 77 | 69 | static void isp1301_configure_pnx4008(void) |
| 78 | 70 | { |
| @@ -249,8 +241,6 @@ static const struct hc_driver ohci_nxp_hc_driver = { · 170 unmodified lines | ||
| 249 | 241 | .start_port_reset = ohci_start_port_reset, |
| 250 | 242 | }; |
| 251 | 243 | |
| 252 | −#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON) | |
| 253 | − | |
| 254 | 244 | static void nxp_set_usb_bits(void) |
| 255 | 245 | { |
| 256 | 246 | if (machine_is_pnx4008()) { |
| @@ -327,41 +317,63 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) · 70 unmodified lines | ||
| 327 | 317 | /* Enable AHB slave USB clock, needed for further USB clock control */ |
| 328 | 318 | __raw_writel(USB_SLAVE_HCLK_EN | PAD_CONTROL_LAST_DRIVEN, USB_CTRL); |
| 329 | 319 | |
| 330 | − isp1301_configure(); | |
| 331 | − | |
| 332 | 320 | /* Enable USB PLL */ |
| 333 | − usb_clk = clk_get(&pdev->dev, "ck_pll5"); | |
| 334 | − if (IS_ERR(usb_clk)) { | |
| 321 | + usb_pll_clk = clk_get(&pdev->dev, "ck_pll5"); | |
| 322 | + if (IS_ERR(usb_pll_clk)) { | |
| 335 | 323 | dev_err(&pdev->dev, "failed to acquire USB PLL\n"); |
| 336 | − ret = PTR_ERR(usb_clk); | |
| 324 | + ret = PTR_ERR(usb_pll_clk); | |
| 337 | 325 | goto out1; |
| 338 | 326 | } |
| 339 | 327 | |
| 340 | − ret = clk_enable(usb_clk); | |
| 328 | + ret = clk_enable(usb_pll_clk); | |
| 341 | 329 | if (ret < 0) { |
| 342 | 330 | dev_err(&pdev->dev, "failed to start USB PLL\n"); |
| 343 | 331 | goto out2; |
| 344 | 332 | } |
| 345 | 333 | |
| 346 | − ret = clk_set_rate(usb_clk, 48000); | |
| 334 | + ret = clk_set_rate(usb_pll_clk, 48000); | |
| 347 | 335 | if (ret < 0) { |
| 348 | 336 | dev_err(&pdev->dev, "failed to set USB clock rate\n"); |
| 349 | 337 | goto out3; |
| 350 | 338 | } |
| 351 | 339 | |
| 340 | + /* Enable USB device clock */ | |
| 341 | + usb_dev_clk = clk_get(&pdev->dev, "ck_usbd"); | |
| 342 | + if (IS_ERR(usb_dev_clk)) { | |
| 343 | + dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n"); | |
| 344 | + ret = PTR_ERR(usb_dev_clk); | |
| 345 | + goto out4; | |
| 346 | + } | |
| 347 | + | |
| 348 | + ret = clk_enable(usb_dev_clk); | |
| 349 | + if (ret < 0) { | |
| 350 | + dev_err(&pdev->dev, "failed to start USB DEV Clock\n"); | |
| 351 | + goto out5; | |
| 352 | + } | |
| 353 | + | |
| 354 | + /* Enable USB otg clocks */ | |
| 355 | + usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); | |
| 356 | + if (IS_ERR(usb_otg_clk)) { | |
| 357 | + dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n"); | |
| 358 | + ret = PTR_ERR(usb_dev_clk); | |
| 359 | + goto out6; | |
| 360 | + } | |
| 361 | + | |
| 352 | 362 | __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL); |
| 353 | 363 | |
| 354 | − /* Set to enable all needed USB clocks */ | |
| 355 | − __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL); | |
| 364 | + ret = clk_enable(usb_otg_clk); | |
| 365 | + if (ret < 0) { | |
| 366 | + dev_err(&pdev->dev, "failed to start USB DEV Clock\n"); | |
| 367 | + goto out7; | |
| 368 | + } | |
| 356 | 369 | |
| 357 | − while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != | |
| 358 | − USB_CLOCK_MASK) ; | |
| 370 | + isp1301_configure(); | |
| 359 | 371 | |
| 360 | 372 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); |
| 361 | 373 | if (!hcd) { |
| 362 | 374 | dev_err(&pdev->dev, "Failed to allocate HC buffer\n"); |
| 363 | 375 | ret = -ENOMEM; |
| 364 | − goto out3; | |
| 376 | + goto out8; | |
| 365 | 377 | } |
| 366 | 378 | |
| 367 | 379 | /* Set all USB bits in the Start Enable register */ |
| @@ -371,14 +383,14 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 371 | 383 | if (!res) { |
| 372 | 384 | dev_err(&pdev->dev, "Failed to get MEM resource\n"); |
| 373 | 385 | ret = -ENOMEM; |
| 374 | − goto out4; | |
| 386 | + goto out8; | |
| 375 | 387 | } |
| 376 | 388 | |
| 377 | 389 | hcd->regs = devm_request_and_ioremap(&pdev->dev, res); |
| 378 | 390 | if (!hcd->regs) { |
| 379 | 391 | dev_err(&pdev->dev, "Failed to devm_request_and_ioremap\n"); |
| 380 | 392 | ret = -ENOMEM; |
| 381 | − goto out4; | |
| 393 | + goto out8; | |
| 382 | 394 | } |
| 383 | 395 | hcd->rsrc_start = res->start; |
| 384 | 396 | hcd->rsrc_len = resource_size(res); |
| @@ -386,7 +398,7 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 386 | 398 | irq = platform_get_irq(pdev, 0); |
| 387 | 399 | if (irq < 0) { |
| 388 | 400 | ret = -ENXIO; |
| 389 | − goto out4; | |
| 401 | + goto out8; | |
| 390 | 402 | } |
| 391 | 403 | |
| 392 | 404 | nxp_start_hc(); |
| @@ -400,13 +412,21 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 400 | 412 | return ret; |
| 401 | 413 | |
| 402 | 414 | nxp_stop_hc(); |
| 403 | −out4: | |
| 415 | +out8: | |
| 404 | 416 | nxp_unset_usb_bits(); |
| 405 | 417 | usb_put_hcd(hcd); |
| 418 | +out7: | |
| 419 | + clk_disable(usb_otg_clk); | |
| 420 | +out6: | |
| 421 | + clk_put(usb_otg_clk); | |
| 422 | +out5: | |
| 423 | + clk_disable(usb_dev_clk); | |
| 424 | +out4: | |
| 425 | + clk_put(usb_dev_clk); | |
| 406 | 426 | out3: |
| 407 | − clk_disable(usb_clk); | |
| 427 | + clk_disable(usb_pll_clk); | |
| 408 | 428 | out2: |
| 409 | − clk_put(usb_clk); | |
| 429 | + clk_put(usb_pll_clk); | |
| 410 | 430 | out1: |
| 411 | 431 | isp1301_i2c_client = NULL; |
| 412 | 432 | out: |
| @@ -422,8 +442,10 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) · 9 unmodified lines | ||
| 422 | 442 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 423 | 443 | usb_put_hcd(hcd); |
| 424 | 444 | nxp_unset_usb_bits(); |
| 425 | − clk_disable(usb_clk); | |
| 426 | − clk_put(usb_clk); | |
| 445 | + clk_disable(usb_pll_clk); | |
| 446 | + clk_put(usb_pll_clk); | |
| 447 | + clk_disable(usb_dev_clk); | |
| 448 | + clk_put(usb_dev_clk); | |
| 427 | 449 | i2c_unregister_device(isp1301_i2c_client); |
| 428 | 450 | isp1301_i2c_client = NULL; |
| 429 | 451 | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/jiffies.h> |
| 19 | 19 | #include <linux/platform_device.h> |
| 20 | 20 | #include <linux/clk.h> |
| 21 | +#include <linux/err.h> | |
| 21 | 22 | #include <linux/gpio.h> |
| 22 | 23 | |
| 23 | 24 | #include <asm/io.h> |
| @@ -168,14 +169,15 @@ static int omap_1510_local_bus_init(void) · 144 unmodified lines | ||
| 168 | 169 | |
| 169 | 170 | static void start_hnp(struct ohci_hcd *ohci) |
| 170 | 171 | { |
| 171 | − const unsigned port = ohci_to_hcd(ohci)->self.otg_port - 1; | |
| 172 | + struct usb_hcd *hcd = ohci_to_hcd(ohci); | |
| 173 | + const unsigned port = hcd->self.otg_port - 1; | |
| 172 | 174 | unsigned long flags; |
| 173 | 175 | u32 l; |
| 174 | 176 | |
| 175 | − otg_start_hnp(ohci->transceiver->otg); | |
| 177 | + otg_start_hnp(hcd->phy->otg); | |
| 176 | 178 | |
| 177 | 179 | local_irq_save(flags); |
| 178 | − ohci->transceiver->state = OTG_STATE_A_SUSPEND; | |
| 180 | + hcd->phy->state = OTG_STATE_A_SUSPEND; | |
| 179 | 181 | writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]); |
| 180 | 182 | l = omap_readl(OTG_CTRL); |
| 181 | 183 | l &= ~OTG_A_BUSREQ; |
| @@ -212,18 +214,18 @@ static int ohci_omap_init(struct usb_hcd *hcd) · 30 unmodified lines | ||
| 212 | 214 | |
| 213 | 215 | #ifdef CONFIG_USB_OTG |
| 214 | 216 | if (need_transceiver) { |
| 215 | − ohci->transceiver = usb_get_transceiver(); | |
| 216 | − if (ohci->transceiver) { | |
| 217 | − int status = otg_set_host(ohci->transceiver->otg, | |
| 217 | + hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 218 | + if (!IS_ERR_OR_NULL(hcd->phy)) { | |
| 219 | + int status = otg_set_host(hcd->phy->otg, | |
| 218 | 220 | &ohci_to_hcd(ohci)->self); |
| 219 | − dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n", | |
| 220 | − ohci->transceiver->label, status); | |
| 221 | + dev_dbg(hcd->self.controller, "init %s phy, status %d\n", | |
| 222 | + hcd->phy->label, status); | |
| 221 | 223 | if (status) { |
| 222 | − usb_put_transceiver(ohci->transceiver); | |
| 224 | + usb_put_phy(hcd->phy); | |
| 223 | 225 | return status; |
| 224 | 226 | } |
| 225 | 227 | } else { |
| 226 | − dev_err(hcd->self.controller, "can't find transceiver\n"); | |
| 228 | + dev_err(hcd->self.controller, "can't find phy\n"); | |
| 227 | 229 | return -ENODEV; |
| 228 | 230 | } |
| 229 | 231 | ohci->start_hnp = start_hnp; |
| @@ -404,9 +406,9 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) · 174 unmodified lines | ||
| 404 | 406 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 405 | 407 | |
| 406 | 408 | usb_remove_hcd(hcd); |
| 407 | − if (ohci->transceiver) { | |
| 408 | − (void) otg_set_host(ohci->transceiver->otg, 0); | |
| 409 | − usb_put_transceiver(ohci->transceiver); | |
| 409 | + if (!IS_ERR_OR_NULL(hcd->phy)) { | |
| 410 | + (void) otg_set_host(hcd->phy->otg, 0); | |
| 411 | + usb_put_phy(hcd->phy); | |
| 410 | 412 | } |
| 411 | 413 | if (machine_is_omap_osk()) |
| 412 | 414 | gpio_free(9); |
| @@ -372,11 +372,6 @@ struct ohci_hcd { · 371 unmodified lines | ||
| 372 | 372 | struct ed *ed_controltail; /* last in ctrl list */ |
| 373 | 373 | struct ed *periodic [NUM_INTS]; /* shadow int_table */ |
| 374 | 374 | |
| 375 | − /* | |
| 376 | − * OTG controllers and transceivers need software interaction; | |
| 377 | − * other external transceivers should be software-transparent | |
| 378 | − */ | |
| 379 | − struct usb_phy *transceiver; | |
| 380 | 375 | void (*start_hnp)(struct ohci_hcd *ohci); |
| 381 | 376 | |
| 382 | 377 | /* |
| @@ -544,12 +544,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 543 unmodified lines | ||
| 544 | 544 | if (hcd->speed != HCD_USB3) |
| 545 | 545 | goto error; |
| 546 | 546 | |
| 547 | + /* Set the U1 and U2 exit latencies. */ | |
| 547 | 548 | memcpy(buf, &usb_bos_descriptor, |
| 548 | 549 | USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); |
| 549 | 550 | temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); |
| 550 | 551 | buf[12] = HCS_U1_LATENCY(temp); |
| 551 | 552 | put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); |
| 552 | 553 | |
| 554 | + /* Indicate whether the host has LTM support. */ | |
| 555 | + temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | |
| 556 | + if (HCC_LTC(temp)) | |
| 557 | + buf[8] |= USB_LTM_SUPPORT; | |
| 558 | + | |
| 553 | 559 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 554 | 560 | return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; |
| 555 | 561 | case GetPortStatus: |
| @@ -4450,6 +4450,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) · 4449 unmodified lines | ||
| 4450 | 4450 | |
| 4451 | 4451 | /* Accept arbitrarily long scatter-gather lists */ |
| 4452 | 4452 | hcd->self.sg_tablesize = ~0; |
| 4453 | + /* XHCI controllers don't stop the ep queue on short packets :| */ | |
| 4454 | + hcd->self.no_stop_on_short = 1; | |
| 4453 | 4455 | |
| 4454 | 4456 | if (usb_hcd_is_primary_hcd(hcd)) { |
| 4455 | 4457 | xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/init.h> |
| 30 | 30 | #include <linux/module.h> |
| 31 | 31 | #include <linux/clk.h> |
| 32 | +#include <linux/err.h> | |
| 32 | 33 | #include <linux/io.h> |
| 33 | 34 | #include <linux/platform_device.h> |
| 34 | 35 | #include <linux/dma-mapping.h> |
| @@ -364,8 +365,8 @@ static int am35x_musb_init(struct musb *musb) · 329 unmodified lines | ||
| 364 | 365 | return -ENODEV; |
| 365 | 366 | |
| 366 | 367 | usb_nop_xceiv_register(); |
| 367 | − musb->xceiv = usb_get_transceiver(); | |
| 368 | − if (!musb->xceiv) | |
| 368 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 369 | + if (IS_ERR_OR_NULL(musb->xceiv)) | |
| 369 | 370 | return -ENODEV; |
| 370 | 371 | |
| 371 | 372 | if (is_host_enabled(musb)) |
| @@ -406,7 +407,7 @@ static int am35x_musb_exit(struct musb *musb) · 34 unmodified lines | ||
| 406 | 407 | if (data->set_phy_power) |
| 407 | 408 | data->set_phy_power(0); |
| 408 | 409 | |
| 409 | − usb_put_transceiver(musb->xceiv); | |
| 410 | + usb_put_phy(musb->xceiv); | |
| 410 | 411 | usb_nop_xceiv_unregister(); |
| 411 | 412 | |
| 412 | 413 | return 0; |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/list.h> |
| 16 | 16 | #include <linux/gpio.h> |
| 17 | 17 | #include <linux/io.h> |
| 18 | +#include <linux/err.h> | |
| 18 | 19 | #include <linux/platform_device.h> |
| 19 | 20 | #include <linux/dma-mapping.h> |
| 20 | 21 | #include <linux/prefetch.h> |
| @@ -415,8 +416,8 @@ static int bfin_musb_init(struct musb *musb) · 394 unmodified lines | ||
| 415 | 416 | gpio_direction_output(musb->config->gpio_vrsel, 0); |
| 416 | 417 | |
| 417 | 418 | usb_nop_xceiv_register(); |
| 418 | − musb->xceiv = usb_get_transceiver(); | |
| 419 | − if (!musb->xceiv) { | |
| 419 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 420 | + if (IS_ERR_OR_NULL(musb->xceiv)) { | |
| 420 | 421 | gpio_free(musb->config->gpio_vrsel); |
| 421 | 422 | return -ENODEV; |
| 422 | 423 | } |
| @@ -440,7 +441,7 @@ static int bfin_musb_exit(struct musb *musb) · 17 unmodified lines | ||
| 440 | 441 | { |
| 441 | 442 | gpio_free(musb->config->gpio_vrsel); |
| 442 | 443 | |
| 443 | − usb_put_transceiver(musb->xceiv); | |
| 444 | + usb_put_phy(musb->xceiv); | |
| 444 | 445 | usb_nop_xceiv_unregister(); |
| 445 | 446 | return 0; |
| 446 | 447 | } |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/init.h> |
| 30 | 30 | #include <linux/module.h> |
| 31 | 31 | #include <linux/clk.h> |
| 32 | +#include <linux/err.h> | |
| 32 | 33 | #include <linux/io.h> |
| 33 | 34 | #include <linux/platform_device.h> |
| 34 | 35 | #include <linux/dma-mapping.h> |
| @@ -425,8 +426,8 @@ static int da8xx_musb_init(struct musb *musb) · 390 unmodified lines | ||
| 425 | 426 | goto fail; |
| 426 | 427 | |
| 427 | 428 | usb_nop_xceiv_register(); |
| 428 | − musb->xceiv = usb_get_transceiver(); | |
| 429 | − if (!musb->xceiv) | |
| 429 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 430 | + if (IS_ERR_OR_NULL(musb->xceiv)) | |
| 430 | 431 | goto fail; |
| 431 | 432 | |
| 432 | 433 | if (is_host_enabled(musb)) |
| @@ -458,7 +459,7 @@ static int da8xx_musb_exit(struct musb *musb) · 25 unmodified lines | ||
| 458 | 459 | |
| 459 | 460 | phy_off(); |
| 460 | 461 | |
| 461 | − usb_put_transceiver(musb->xceiv); | |
| 462 | + usb_put_phy(musb->xceiv); | |
| 462 | 463 | usb_nop_xceiv_unregister(); |
| 463 | 464 | |
| 464 | 465 | return 0; |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/list.h> |
| 29 | 29 | #include <linux/delay.h> |
| 30 | 30 | #include <linux/clk.h> |
| 31 | +#include <linux/err.h> | |
| 31 | 32 | #include <linux/io.h> |
| 32 | 33 | #include <linux/gpio.h> |
| 33 | 34 | #include <linux/platform_device.h> |
| @@ -385,8 +386,8 @@ static int davinci_musb_init(struct musb *musb) · 351 unmodified lines | ||
| 385 | 386 | u32 revision; |
| 386 | 387 | |
| 387 | 388 | usb_nop_xceiv_register(); |
| 388 | − musb->xceiv = usb_get_transceiver(); | |
| 389 | − if (!musb->xceiv) | |
| 389 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 390 | + if (IS_ERR_OR_NULL(musb->xceiv)) | |
| 390 | 391 | goto unregister; |
| 391 | 392 | |
| 392 | 393 | musb->mregs += DAVINCI_BASE_OFFSET; |
| @@ -444,7 +445,7 @@ static int davinci_musb_init(struct musb *musb) · 51 unmodified lines | ||
| 444 | 445 | return 0; |
| 445 | 446 | |
| 446 | 447 | fail: |
| 447 | − usb_put_transceiver(musb->xceiv); | |
| 448 | + usb_put_phy(musb->xceiv); | |
| 448 | 449 | unregister: |
| 449 | 450 | usb_nop_xceiv_unregister(); |
| 450 | 451 | return -ENODEV; |
| @@ -494,7 +495,7 @@ static int davinci_musb_exit(struct musb *musb) · 43 unmodified lines | ||
| 494 | 495 | |
| 495 | 496 | phy_off(); |
| 496 | 497 | |
| 497 | − usb_put_transceiver(musb->xceiv); | |
| 498 | + usb_put_phy(musb->xceiv); | |
| 498 | 499 | usb_nop_xceiv_unregister(); |
| 499 | 500 | |
| 500 | 501 | return 0; |
| @@ -1909,7 +1909,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) · 1908 unmodified lines | ||
| 1909 | 1909 | /* The musb_platform_init() call: |
| 1910 | 1910 | * - adjusts musb->mregs and musb->isr if needed, |
| 1911 | 1911 | * - may initialize an integrated tranceiver |
| 1912 | − * - initializes musb->xceiv, usually by otg_get_transceiver() | |
| 1912 | + * - initializes musb->xceiv, usually by otg_get_phy() | |
| 1913 | 1913 | * - stops powering VBUS |
| 1914 | 1914 | * |
| 1915 | 1915 | * There are various transceiver configurations. Blackfin, |
| @@ -327,7 +327,6 @@ struct musb { · 326 unmodified lines | ||
| 327 | 327 | |
| 328 | 328 | irqreturn_t (*isr)(int, void *); |
| 329 | 329 | struct work_struct irq_work; |
| 330 | − struct work_struct otg_notifier_work; | |
| 331 | 330 | u16 hwvers; |
| 332 | 331 | |
| 333 | 332 | /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ |
| @@ -373,7 +372,6 @@ struct musb { · 39 unmodified lines | ||
| 373 | 372 | u16 int_tx; |
| 374 | 373 | |
| 375 | 374 | struct usb_phy *xceiv; |
| 376 | − u8 xceiv_event; | |
| 377 | 375 | |
| 378 | 376 | int nIrq; |
| 379 | 377 | unsigned irq_wake:1; |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #include <linux/init.h> |
| 33 | 33 | #include <linux/io.h> |
| 34 | +#include <linux/err.h> | |
| 34 | 35 | #include <linux/platform_device.h> |
| 35 | 36 | #include <linux/dma-mapping.h> |
| 36 | 37 | #include <linux/pm_runtime.h> |
| @@ -376,8 +377,8 @@ static int dsps_musb_init(struct musb *musb) · 339 unmodified lines | ||
| 376 | 377 | |
| 377 | 378 | /* NOP driver needs change if supporting dual instance */ |
| 378 | 379 | usb_nop_xceiv_register(); |
| 379 | − musb->xceiv = usb_get_transceiver(); | |
| 380 | − if (!musb->xceiv) | |
| 380 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 381 | + if (IS_ERR_OR_NULL(musb->xceiv)) | |
| 381 | 382 | return -ENODEV; |
| 382 | 383 | |
| 383 | 384 | /* Returns zero if e.g. not clocked */ |
| @@ -409,7 +410,7 @@ static int dsps_musb_init(struct musb *musb) · 25 unmodified lines | ||
| 409 | 410 | |
| 410 | 411 | return 0; |
| 411 | 412 | err0: |
| 412 | − usb_put_transceiver(musb->xceiv); | |
| 413 | + usb_put_phy(musb->xceiv); | |
| 413 | 414 | usb_nop_xceiv_unregister(); |
| 414 | 415 | return status; |
| 415 | 416 | } |
| @@ -430,7 +431,7 @@ static int dsps_musb_exit(struct musb *musb) · 14 unmodified lines | ||
| 430 | 431 | data->set_phy_power(0); |
| 431 | 432 | |
| 432 | 433 | /* NOP driver needs change if supporting dual instance */ |
| 433 | − usb_put_transceiver(musb->xceiv); | |
| 434 | + usb_put_phy(musb->xceiv); | |
| 434 | 435 | usb_nop_xceiv_unregister(); |
| 435 | 436 | |
| 436 | 437 | return 0; |
| @@ -328,6 +328,13 @@ static void txstate(struct musb *musb, struct musb_request *req) · 327 unmodified lines | ||
| 328 | 328 | |
| 329 | 329 | musb_ep = req->ep; |
| 330 | 330 | |
| 331 | + /* Check if EP is disabled */ | |
| 332 | + if (!musb_ep->desc) { | |
| 333 | + dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", | |
| 334 | + musb_ep->end_point.name); | |
| 335 | + return; | |
| 336 | + } | |
| 337 | + | |
| 331 | 338 | /* we shouldn't get here while DMA is active ... but we do ... */ |
| 332 | 339 | if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { |
| 333 | 340 | dev_dbg(musb->controller, "dma pending...\n"); |
| @@ -650,6 +657,13 @@ static void rxstate(struct musb *musb, struct musb_request *req) · 316 unmodified lines | ||
| 650 | 657 | |
| 651 | 658 | len = musb_ep->packet_sz; |
| 652 | 659 | |
| 660 | + /* Check if EP is disabled */ | |
| 661 | + if (!musb_ep->desc) { | |
| 662 | + dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", | |
| 663 | + musb_ep->end_point.name); | |
| 664 | + return; | |
| 665 | + } | |
| 666 | + | |
| 653 | 667 | /* We shouldn't get here while DMA is active, but we do... */ |
| 654 | 668 | if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { |
| 655 | 669 | dev_dbg(musb->controller, "DMA pending...\n"); |
| @@ -1746,7 +1746,11 @@ void musb_host_rx(struct musb *musb, u8 epnum) · 1745 unmodified lines | ||
| 1746 | 1746 | c->channel_release(dma); |
| 1747 | 1747 | hw_ep->rx_channel = NULL; |
| 1748 | 1748 | dma = NULL; |
| 1749 | − /* REVISIT reset CSR */ | |
| 1749 | + val = musb_readw(epio, MUSB_RXCSR); | |
| 1750 | + val &= ~(MUSB_RXCSR_DMAENAB | |
| 1751 | + | MUSB_RXCSR_H_AUTOREQ | |
| 1752 | + | MUSB_RXCSR_AUTOCLEAR); | |
| 1753 | + musb_writew(epio, MUSB_RXCSR, val); | |
| 1750 | 1754 | } |
| 1751 | 1755 | } |
| 1752 | 1756 | #endif /* Mentor DMA */ |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <linux/dma-mapping.h> |
| 35 | 35 | #include <linux/pm_runtime.h> |
| 36 | 36 | #include <linux/err.h> |
| 37 | +#include <linux/usb/musb-omap.h> | |
| 37 | 38 | |
| 38 | 39 | #include "musb_core.h" |
| 39 | 40 | #include "omap2430.h" |
| @@ -41,9 +42,13 @@ · 1 unmodified line | ||
| 41 | 42 | struct omap2430_glue { |
| 42 | 43 | struct device *dev; |
| 43 | 44 | struct platform_device *musb; |
| 45 | + enum omap_musb_vbus_id_status status; | |
| 46 | + struct work_struct omap_musb_mailbox_work; | |
| 44 | 47 | }; |
| 45 | 48 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
| 46 | 49 | |
| 50 | +struct omap2430_glue *_glue; | |
| 51 | + | |
| 47 | 52 | static struct timer_list musb_idle_timer; |
| 48 | 53 | |
| 49 | 54 | static void musb_do_idle(unsigned long _musb) |
| @@ -223,50 +228,63 @@ static inline void omap2430_low_level_init(struct musb *musb) · 173 unmodified lines | ||
| 223 | 228 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); |
| 224 | 229 | } |
| 225 | 230 | |
| 226 | −static int musb_otg_notifications(struct notifier_block *nb, | |
| 227 | − unsigned long event, void *unused) | |
| 231 | +void omap_musb_mailbox(enum omap_musb_vbus_id_status status) | |
| 228 | 232 | { |
| 229 | − struct musb *musb = container_of(nb, struct musb, nb); | |
| 233 | + struct omap2430_glue *glue = _glue; | |
| 234 | + struct musb *musb = glue_to_musb(glue); | |
| 230 | 235 | |
| 231 | − musb->xceiv_event = event; | |
| 232 | − schedule_work(&musb->otg_notifier_work); | |
| 236 | + glue->status = status; | |
| 237 | + if (!musb) { | |
| 238 | + dev_err(glue->dev, "musb core is not yet ready\n"); | |
| 239 | + return; | |
| 240 | + } | |
| 233 | 241 | |
| 234 | − return NOTIFY_OK; | |
| 242 | + schedule_work(&glue->omap_musb_mailbox_work); | |
| 235 | 243 | } |
| 244 | +EXPORT_SYMBOL_GPL(omap_musb_mailbox); | |
| 236 | 245 | |
| 237 | −static void musb_otg_notifier_work(struct work_struct *data_notifier_work) | |
| 246 | +static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |
| 238 | 247 | { |
| 239 | − struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work); | |
| 248 | + struct musb *musb = glue_to_musb(glue); | |
| 240 | 249 | struct device *dev = musb->controller; |
| 241 | 250 | struct musb_hdrc_platform_data *pdata = dev->platform_data; |
| 242 | 251 | struct omap_musb_board_data *data = pdata->board_data; |
| 252 | + struct usb_otg *otg = musb->xceiv->otg; | |
| 243 | 253 | |
| 244 | − switch (musb->xceiv_event) { | |
| 245 | − case USB_EVENT_ID: | |
| 246 | − dev_dbg(musb->controller, "ID GND\n"); | |
| 254 | + switch (glue->status) { | |
| 255 | + case OMAP_MUSB_ID_GROUND: | |
| 256 | + dev_dbg(dev, "ID GND\n"); | |
| 247 | 257 | |
| 258 | + otg->default_a = true; | |
| 259 | + musb->xceiv->state = OTG_STATE_A_IDLE; | |
| 260 | + musb->xceiv->last_event = USB_EVENT_ID; | |
| 248 | 261 | if (!is_otg_enabled(musb) || musb->gadget_driver) { |
| 249 | − pm_runtime_get_sync(musb->controller); | |
| 262 | + pm_runtime_get_sync(dev); | |
| 250 | 263 | usb_phy_init(musb->xceiv); |
| 251 | 264 | omap2430_musb_set_vbus(musb, 1); |
| 252 | 265 | } |
| 253 | 266 | break; |
| 254 | 267 | |
| 255 | − case USB_EVENT_VBUS: | |
| 256 | − dev_dbg(musb->controller, "VBUS Connect\n"); | |
| 268 | + case OMAP_MUSB_VBUS_VALID: | |
| 269 | + dev_dbg(dev, "VBUS Connect\n"); | |
| 257 | 270 | |
| 271 | + otg->default_a = false; | |
| 272 | + musb->xceiv->state = OTG_STATE_B_IDLE; | |
| 273 | + musb->xceiv->last_event = USB_EVENT_VBUS; | |
| 258 | 274 | if (musb->gadget_driver) |
| 259 | − pm_runtime_get_sync(musb->controller); | |
| 275 | + pm_runtime_get_sync(dev); | |
| 260 | 276 | usb_phy_init(musb->xceiv); |
| 261 | 277 | break; |
| 262 | 278 | |
| 263 | − case USB_EVENT_NONE: | |
| 264 | − dev_dbg(musb->controller, "VBUS Disconnect\n"); | |
| 279 | + case OMAP_MUSB_ID_FLOAT: | |
| 280 | + case OMAP_MUSB_VBUS_OFF: | |
| 281 | + dev_dbg(dev, "VBUS Disconnect\n"); | |
| 265 | 282 | |
| 283 | + musb->xceiv->last_event = USB_EVENT_NONE; | |
| 266 | 284 | if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) |
| 267 | 285 | if (musb->gadget_driver) { |
| 268 | − pm_runtime_mark_last_busy(musb->controller); | |
| 269 | − pm_runtime_put_autosuspend(musb->controller); | |
| 286 | + pm_runtime_mark_last_busy(dev); | |
| 287 | + pm_runtime_put_autosuspend(dev); | |
| 270 | 288 | } |
| 271 | 289 | |
| 272 | 290 | if (data->interface_type == MUSB_INTERFACE_UTMI) { |
| @@ -276,15 +294,24 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) · 3 unmodified lines | ||
| 276 | 294 | usb_phy_shutdown(musb->xceiv); |
| 277 | 295 | break; |
| 278 | 296 | default: |
| 279 | − dev_dbg(musb->controller, "ID float\n"); | |
| 297 | + dev_dbg(dev, "ID float\n"); | |
| 280 | 298 | } |
| 281 | 299 | } |
| 282 | 300 | |
| 301 | + | |
| 302 | +static void omap_musb_mailbox_work(struct work_struct *mailbox_work) | |
| 303 | +{ | |
| 304 | + struct omap2430_glue *glue = container_of(mailbox_work, | |
| 305 | + struct omap2430_glue, omap_musb_mailbox_work); | |
| 306 | + omap_musb_set_mailbox(glue); | |
| 307 | +} | |
| 308 | + | |
| 283 | 309 | static int omap2430_musb_init(struct musb *musb) |
| 284 | 310 | { |
| 285 | 311 | u32 l; |
| 286 | 312 | int status = 0; |
| 287 | 313 | struct device *dev = musb->controller; |
| 314 | + struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | |
| 288 | 315 | struct musb_hdrc_platform_data *plat = dev->platform_data; |
| 289 | 316 | struct omap_musb_board_data *data = plat->board_data; |
| 290 | 317 | |
| @@ -292,14 +319,12 @@ static int omap2430_musb_init(struct musb *musb) · 1 unmodified line | ||
| 292 | 319 | * up through ULPI. TWL4030-family PMICs include one, |
| 293 | 320 | * which needs a driver, drivers aren't always needed. |
| 294 | 321 | */ |
| 295 | − musb->xceiv = usb_get_transceiver(); | |
| 296 | − if (!musb->xceiv) { | |
| 322 | + musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | |
| 323 | + if (IS_ERR_OR_NULL(musb->xceiv)) { | |
| 297 | 324 | pr_err("HS USB OTG: no transceiver configured\n"); |
| 298 | 325 | return -ENODEV; |
| 299 | 326 | } |
| 300 | 327 | |
| 301 | − INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work); | |
| 302 | − | |
| 303 | 328 | status = pm_runtime_get_sync(dev); |
| 304 | 329 | if (status < 0) { |
| 305 | 330 | dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); |
| @@ -326,14 +351,11 @@ static int omap2430_musb_init(struct musb *musb) · 20 unmodified lines | ||
| 326 | 351 | musb_readl(musb->mregs, OTG_INTERFSEL), |
| 327 | 352 | musb_readl(musb->mregs, OTG_SIMENABLE)); |
| 328 | 353 | |
| 329 | − musb->nb.notifier_call = musb_otg_notifications; | |
| 330 | − status = usb_register_notifier(musb->xceiv, &musb->nb); | |
| 331 | − | |
| 332 | − if (status) | |
| 333 | − dev_dbg(musb->controller, "notification register failed\n"); | |
| 334 | − | |
| 335 | 354 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); |
| 336 | 355 | |
| 356 | + if (glue->status != OMAP_MUSB_UNKNOWN) | |
| 357 | + omap_musb_set_mailbox(glue); | |
| 358 | + | |
| 337 | 359 | pm_runtime_put_noidle(musb->controller); |
| 338 | 360 | return 0; |
| 339 | 361 | |
| @@ -346,12 +368,13 @@ static void omap2430_musb_enable(struct musb *musb) · 6 unmodified lines | ||
| 346 | 368 | u8 devctl; |
| 347 | 369 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
| 348 | 370 | struct device *dev = musb->controller; |
| 371 | + struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | |
| 349 | 372 | struct musb_hdrc_platform_data *pdata = dev->platform_data; |
| 350 | 373 | struct omap_musb_board_data *data = pdata->board_data; |
| 351 | 374 | |
| 352 | − switch (musb->xceiv->last_event) { | |
| 375 | + switch (glue->status) { | |
| 353 | 376 | |
| 354 | − case USB_EVENT_ID: | |
| 377 | + case OMAP_MUSB_ID_GROUND: | |
| 355 | 378 | usb_phy_init(musb->xceiv); |
| 356 | 379 | if (data->interface_type != MUSB_INTERFACE_UTMI) |
| 357 | 380 | break; |
| @@ -370,7 +393,7 @@ static void omap2430_musb_enable(struct musb *musb) · 12 unmodified lines | ||
| 370 | 393 | } |
| 371 | 394 | break; |
| 372 | 395 | |
| 373 | − case USB_EVENT_VBUS: | |
| 396 | + case OMAP_MUSB_VBUS_VALID: | |
| 374 | 397 | usb_phy_init(musb->xceiv); |
| 375 | 398 | break; |
| 376 | 399 | |
| @@ -381,17 +404,18 @@ static void omap2430_musb_enable(struct musb *musb) · 4 unmodified lines | ||
| 381 | 404 | |
| 382 | 405 | static void omap2430_musb_disable(struct musb *musb) |
| 383 | 406 | { |
| 384 | − if (musb->xceiv->last_event) | |
| 407 | + struct device *dev = musb->controller; | |
| 408 | + struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | |
| 409 | + | |
| 410 | + if (glue->status != OMAP_MUSB_UNKNOWN) | |
| 385 | 411 | usb_phy_shutdown(musb->xceiv); |
| 386 | 412 | } |
| 387 | 413 | |
| 388 | 414 | static int omap2430_musb_exit(struct musb *musb) |
| 389 | 415 | { |
| 390 | 416 | del_timer_sync(&musb_idle_timer); |
| 391 | − cancel_work_sync(&musb->otg_notifier_work); | |
| 392 | 417 | |
| 393 | 418 | omap2430_low_level_exit(musb); |
| 394 | − usb_put_transceiver(musb->xceiv); | |
| 395 | 419 | |
| 396 | 420 | return 0; |
| 397 | 421 | } |
| @@ -418,7 +442,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 418 | 442 | struct omap2430_glue *glue; |
| 419 | 443 | int ret = -ENOMEM; |
| 420 | 444 | |
| 421 | − glue = kzalloc(sizeof(*glue), GFP_KERNEL); | |
| 445 | + glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); | |
| 422 | 446 | if (!glue) { |
| 423 | 447 | dev_err(&pdev->dev, "failed to allocate glue context\n"); |
| 424 | 448 | goto err0; |
| @@ -427,7 +451,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 427 | 451 | musb = platform_device_alloc("musb-hdrc", -1); |
| 428 | 452 | if (!musb) { |
| 429 | 453 | dev_err(&pdev->dev, "failed to allocate musb device\n"); |
| 430 | − goto err1; | |
| 454 | + goto err0; | |
| 431 | 455 | } |
| 432 | 456 | |
| 433 | 457 | musb->dev.parent = &pdev->dev; |
| @@ -436,22 +460,31 @@ static int __devinit omap2430_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 436 | 460 | |
| 437 | 461 | glue->dev = &pdev->dev; |
| 438 | 462 | glue->musb = musb; |
| 463 | + glue->status = OMAP_MUSB_UNKNOWN; | |
| 439 | 464 | |
| 440 | 465 | pdata->platform_ops = &omap2430_ops; |
| 441 | 466 | |
| 442 | 467 | platform_set_drvdata(pdev, glue); |
| 443 | 468 | |
| 469 | + /* | |
| 470 | + * REVISIT if we ever have two instances of the wrapper, we will be | |
| 471 | + * in big trouble | |
| 472 | + */ | |
| 473 | + _glue = glue; | |
| 474 | + | |
| 475 | + INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); | |
| 476 | + | |
| 444 | 477 | ret = platform_device_add_resources(musb, pdev->resource, |
| 445 | 478 | pdev->num_resources); |
| 446 | 479 | if (ret) { |
| 447 | 480 | dev_err(&pdev->dev, "failed to add resources\n"); |
| 448 | − goto err2; | |
| 481 | + goto err1; | |
| 449 | 482 | } |
| 450 | 483 | |
| 451 | 484 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); |
| 452 | 485 | if (ret) { |
| 453 | 486 | dev_err(&pdev->dev, "failed to add platform_data\n"); |
| 454 | − goto err2; | |
| 487 | + goto err1; | |
| 455 | 488 | } |
| 456 | 489 | |
| 457 | 490 | pm_runtime_enable(&pdev->dev); |
| @@ -459,16 +492,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 459 | 492 | ret = platform_device_add(musb); |
| 460 | 493 | if (ret) { |
| 461 | 494 | dev_err(&pdev->dev, "failed to register musb device\n"); |
| 462 | − goto err2; | |
| 495 | + goto err1; | |
| 463 | 496 | } |
| 464 | 497 | |
| 465 | 498 | return 0; |
| 466 | 499 | |
| 467 | −err2: | |
| 468 | − platform_device_put(musb); | |
| 469 | − | |
| 470 | 500 | err1: |
| 471 | − kfree(glue); | |
| 501 | + platform_device_put(musb); | |
| 472 | 502 | |
| 473 | 503 | err0: |
| 474 | 504 | return ret; |
| @@ -478,9 +508,9 @@ static int __devexit omap2430_remove(struct platform_device *pdev) · 3 unmodified lines | ||
| 478 | 508 | { |
| 479 | 509 | struct omap2430_glue *glue = platform_get_drvdata(pdev); |
| 480 | 510 | |
| 511 | + cancel_work_sync(&glue->omap_musb_mailbox_work); | |
| 481 | 512 | platform_device_del(glue->musb); |
| 482 | 513 | platform_device_put(glue->musb); |
| 483 | − kfree(glue); | |
| 484 | 514 | |
| 485 | 515 | return 0; |
| 486 | 516 | } |
| @@ -546,7 +576,7 @@ static int __init omap2430_init(void) · 59 unmodified lines | ||
| 546 | 576 | { |
| 547 | 577 | return platform_driver_register(&omap2430_driver); |
| 548 | 578 | } |
| 549 | −module_init(omap2430_init); | |
| 579 | +subsys_initcall(omap2430_init); | |
| 550 | 580 | |
| 551 | 581 | static void __exit omap2430_exit(void) |
| 552 | 582 | { |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/module.h> |
| 18 | 18 | #include <linux/kernel.h> |
| 19 | 19 | #include <linux/errno.h> |
| 20 | +#include <linux/err.h> | |
| 20 | 21 | #include <linux/init.h> |
| 21 | 22 | #include <linux/prefetch.h> |
| 22 | 23 | #include <linux/usb.h> |
| @@ -1078,8 +1079,8 @@ static int tusb_musb_init(struct musb *musb) · 1055 unmodified lines | ||
| 1078 | 1079 | int ret; |
| 1079 | 1080 | |
| 1080 | 1081 | usb_nop_xceiv_register(); |
| 1081 | − musb->xceiv = usb_get_transceiver(); | |
| 1082 | − if (!musb->xceiv) | |
| 1082 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 1083 | + if (IS_ERR_OR_NULL(musb->xceiv)) | |
| 1083 | 1084 | return -ENODEV; |
| 1084 | 1085 | |
| 1085 | 1086 | pdev = to_platform_device(musb->controller); |
| @@ -1130,7 +1131,7 @@ done: · 44 unmodified lines | ||
| 1130 | 1131 | if (sync) |
| 1131 | 1132 | iounmap(sync); |
| 1132 | 1133 | |
| 1133 | − usb_put_transceiver(musb->xceiv); | |
| 1134 | + usb_put_phy(musb->xceiv); | |
| 1134 | 1135 | usb_nop_xceiv_unregister(); |
| 1135 | 1136 | } |
| 1136 | 1137 | return ret; |
| @@ -1146,7 +1147,7 @@ static int tusb_musb_exit(struct musb *musb) · 9 unmodified lines | ||
| 1146 | 1147 | |
| 1147 | 1148 | iounmap(musb->sync_va); |
| 1148 | 1149 | |
| 1149 | − usb_put_transceiver(musb->xceiv); | |
| 1150 | + usb_put_phy(musb->xceiv); | |
| 1150 | 1151 | usb_nop_xceiv_unregister(); |
| 1151 | 1152 | return 0; |
| 1152 | 1153 | } |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/kernel.h> |
| 24 | 24 | #include <linux/init.h> |
| 25 | 25 | #include <linux/clk.h> |
| 26 | +#include <linux/err.h> | |
| 26 | 27 | #include <linux/io.h> |
| 27 | 28 | #include <linux/platform_device.h> |
| 28 | 29 | |
| @@ -37,8 +38,8 @@ struct ux500_glue { · 8 unmodified lines | ||
| 37 | 38 | |
| 38 | 39 | static int ux500_musb_init(struct musb *musb) |
| 39 | 40 | { |
| 40 | − musb->xceiv = usb_get_transceiver(); | |
| 41 | − if (!musb->xceiv) { | |
| 41 | + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 42 | + if (IS_ERR_OR_NULL(musb->xceiv)) { | |
| 42 | 43 | pr_err("HS USB OTG: no transceiver configured\n"); |
| 43 | 44 | return -ENODEV; |
| 44 | 45 | } |
| @@ -48,7 +49,7 @@ static int ux500_musb_init(struct musb *musb) · 3 unmodified lines | ||
| 48 | 49 | |
| 49 | 50 | static int ux500_musb_exit(struct musb *musb) |
| 50 | 51 | { |
| 51 | − usb_put_transceiver(musb->xceiv); | |
| 52 | + usb_put_phy(musb->xceiv); | |
| 52 | 53 | |
| 53 | 54 | return 0; |
| 54 | 55 | } |
| @@ -116,6 +116,16 @@ config FSL_USB2_OTG · 115 unmodified lines | ||
| 116 | 116 | help |
| 117 | 117 | Enable this to support Freescale USB OTG transceiver. |
| 118 | 118 | |
| 119 | +config USB_MXS_PHY | |
| 120 | + tristate "Freescale MXS USB PHY support" | |
| 121 | + depends on ARCH_MXC || ARCH_MXS | |
| 122 | + select STMP_DEVICE | |
| 123 | + select USB_OTG_UTILS | |
| 124 | + help | |
| 125 | + Enable this to support the Freescale MXS USB PHY. | |
| 126 | + | |
| 127 | + MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. | |
| 128 | + | |
| 119 | 129 | config USB_MV_OTG |
| 120 | 130 | tristate "Marvell USB OTG support" |
| 121 | 131 | depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND |
| @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o · 19 unmodified lines | ||
| 20 | 20 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
| 21 | 21 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o |
| 22 | 22 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o |
| 23 | +obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o | |
| 23 | 24 | obj-$(CONFIG_USB_MV_OTG) += mv_otg.o |
| @@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) · 528 unmodified lines | ||
| 529 | 529 | if (err < 0) |
| 530 | 530 | goto fail0; |
| 531 | 531 | |
| 532 | − err = usb_set_transceiver(&ab->phy); | |
| 532 | + err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); | |
| 533 | 533 | if (err) { |
| 534 | 534 | dev_err(&pdev->dev, "Can't register transceiver\n"); |
| 535 | 535 | goto fail1; |
| @@ -556,7 +556,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) · 20 unmodified lines | ||
| 556 | 556 | |
| 557 | 557 | cancel_work_sync(&ab->phy_dis_work); |
| 558 | 558 | |
| 559 | − usb_set_transceiver(NULL); | |
| 559 | + usb_remove_phy(&ab->phy); | |
| 560 | 560 | |
| 561 | 561 | ab8500_usb_host_phy_dis(ab); |
| 562 | 562 | ab8500_usb_peri_phy_dis(ab); |
| @@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev) · 805 unmodified lines | ||
| 806 | 806 | fsl_otg_dev = fsl_otg_tc; |
| 807 | 807 | |
| 808 | 808 | /* Store the otg transceiver */ |
| 809 | − status = usb_set_transceiver(&fsl_otg_tc->phy); | |
| 809 | + status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2); | |
| 810 | 810 | if (status) { |
| 811 | 811 | pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); |
| 812 | 812 | goto err; |
| @@ -824,7 +824,7 @@ err: · 11 unmodified lines | ||
| 824 | 824 | int usb_otg_start(struct platform_device *pdev) |
| 825 | 825 | { |
| 826 | 826 | struct fsl_otg *p_otg; |
| 827 | − struct usb_phy *otg_trans = usb_get_transceiver(); | |
| 827 | + struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2); | |
| 828 | 828 | struct otg_fsm *fsm; |
| 829 | 829 | int status; |
| 830 | 830 | struct resource *res; |
| @@ -1134,7 +1134,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev) · 303 unmodified lines | ||
| 1134 | 1134 | { |
| 1135 | 1135 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 1136 | 1136 | |
| 1137 | − usb_set_transceiver(NULL); | |
| 1137 | + usb_remove_phy(&fsl_otg_dev->phy); | |
| 1138 | 1138 | free_irq(fsl_otg_dev->irq, fsl_otg_dev); |
| 1139 | 1139 | |
| 1140 | 1140 | iounmap((void *)usb_dr_regs); |
| @@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) · 319 unmodified lines | ||
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | /* only active when a gadget is registered */ |
| 323 | − err = usb_set_transceiver(&gpio_vbus->phy); | |
| 323 | + err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2); | |
| 324 | 324 | if (err) { |
| 325 | 325 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", |
| 326 | 326 | err); |
| @@ -354,7 +354,7 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev) · 27 unmodified lines | ||
| 354 | 354 | cancel_delayed_work_sync(&gpio_vbus->work); |
| 355 | 355 | regulator_put(gpio_vbus->vbus_draw); |
| 356 | 356 | |
| 357 | − usb_set_transceiver(NULL); | |
| 357 | + usb_remove_phy(&gpio_vbus->phy); | |
| 358 | 358 | |
| 359 | 359 | free_irq(gpio_vbus->irq, pdev); |
| 360 | 360 | if (gpio_is_valid(pdata->gpio_pullup)) |
| @@ -1336,9 +1336,6 @@ static int · 1335 unmodified lines | ||
| 1336 | 1336 | isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) |
| 1337 | 1337 | { |
| 1338 | 1338 | struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); |
| 1339 | −#ifndef CONFIG_USB_OTG | |
| 1340 | − u32 l; | |
| 1341 | −#endif | |
| 1342 | 1339 | |
| 1343 | 1340 | if (!otg || isp != the_transceiver) |
| 1344 | 1341 | return -ENODEV; |
| @@ -1365,10 +1362,14 @@ isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) · 20 unmodified lines | ||
| 1365 | 1362 | otg->gadget = gadget; |
| 1366 | 1363 | // FIXME update its refcount |
| 1367 | 1364 | |
| 1368 | − l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; | |
| 1369 | − l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); | |
| 1370 | − l |= OTG_ID; | |
| 1371 | − omap_writel(l, OTG_CTRL); | |
| 1365 | + { | |
| 1366 | + u32 l; | |
| 1367 | + | |
| 1368 | + l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; | |
| 1369 | + l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); | |
| 1370 | + l |= OTG_ID; | |
| 1371 | + omap_writel(l, OTG_CTRL); | |
| 1372 | + } | |
| 1372 | 1373 | |
| 1373 | 1374 | power_up(isp); |
| 1374 | 1375 | isp->phy.state = OTG_STATE_B_IDLE; |
| @@ -1610,7 +1611,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) · 235 unmodified lines | ||
| 1610 | 1611 | dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); |
| 1611 | 1612 | #endif |
| 1612 | 1613 | |
| 1613 | − status = usb_set_transceiver(&isp->phy); | |
| 1614 | + status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2); | |
| 1614 | 1615 | if (status < 0) |
| 1615 | 1616 | dev_err(&i2c->dev, "can't register transceiver, %d\n", |
| 1616 | 1617 | status); |
| @@ -1649,7 +1650,7 @@ subsys_initcall(isp_init); · 32 unmodified lines | ||
| 1649 | 1650 | static void __exit isp_exit(void) |
| 1650 | 1651 | { |
| 1651 | 1652 | if (the_transceiver) |
| 1652 | − usb_set_transceiver(NULL); | |
| 1653 | + usb_remove_phy(&the_transceiver->phy); | |
| 1653 | 1654 | i2c_del_driver(&isp1301_driver); |
| 1654 | 1655 | } |
| 1655 | 1656 | module_exit(isp_exit); |
| @@ -1555,9 +1555,9 @@ static int __init msm_otg_probe(struct platform_device *pdev) · 1554 unmodified lines | ||
| 1555 | 1555 | phy->otg->set_host = msm_otg_set_host; |
| 1556 | 1556 | phy->otg->set_peripheral = msm_otg_set_peripheral; |
| 1557 | 1557 | |
| 1558 | − ret = usb_set_transceiver(&motg->phy); | |
| 1558 | + ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2); | |
| 1559 | 1559 | if (ret) { |
| 1560 | − dev_err(&pdev->dev, "usb_set_transceiver failed\n"); | |
| 1560 | + dev_err(&pdev->dev, "usb_add_phy failed\n"); | |
| 1561 | 1561 | goto free_irq; |
| 1562 | 1562 | } |
| 1563 | 1563 | |
| @@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) · 60 unmodified lines | ||
| 1624 | 1624 | device_init_wakeup(&pdev->dev, 0); |
| 1625 | 1625 | pm_runtime_disable(&pdev->dev); |
| 1626 | 1626 | |
| 1627 | − usb_set_transceiver(NULL); | |
| 1627 | + usb_remove_phy(phy); | |
| 1628 | 1628 | free_irq(motg->irq, motg); |
| 1629 | 1629 | |
| 1630 | 1630 | /* |
| @@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev) · 689 unmodified lines | ||
| 690 | 690 | for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) |
| 691 | 691 | clk_put(mvotg->clk[clk_i]); |
| 692 | 692 | |
| 693 | − usb_set_transceiver(NULL); | |
| 693 | + usb_remove_phy(&mvotg->phy); | |
| 694 | 694 | platform_set_drvdata(pdev, NULL); |
| 695 | 695 | |
| 696 | 696 | kfree(mvotg->phy.otg); |
| @@ -853,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev) · 156 unmodified lines | ||
| 853 | 853 | goto err_disable_clk; |
| 854 | 854 | } |
| 855 | 855 | |
| 856 | − retval = usb_set_transceiver(&mvotg->phy); | |
| 856 | + retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2); | |
| 857 | 857 | if (retval < 0) { |
| 858 | 858 | dev_err(&pdev->dev, "can't register transceiver, %d\n", |
| 859 | 859 | retval); |
| @@ -880,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 880 | 880 | return 0; |
| 881 | 881 | |
| 882 | 882 | err_set_transceiver: |
| 883 | − usb_set_transceiver(NULL); | |
| 883 | + usb_remove_phy(&mvotg->phy); | |
| 884 | 884 | err_free_irq: |
| 885 | 885 | free_irq(mvotg->irq, mvotg); |
| 886 | 886 | err_disable_clk: |
| @@ -0,0 +1,186 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2012 Freescale Semiconductor, Inc. | |
| 3 | + * Copyright (C) 2012 Marek Vasut <marex@denx.de> | |
| 4 | + * on behalf of DENX Software Engineering GmbH | |
| 5 | + * | |
| 6 | + * The code contained herein is licensed under the GNU General Public | |
| 7 | + * License. You may obtain a copy of the GNU General Public License | |
| 8 | + * Version 2 or later at the following locations: | |
| 9 | + * | |
| 10 | + * http://www.opensource.org/licenses/gpl-license.html | |
| 11 | + * http://www.gnu.org/copyleft/gpl.html | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/kernel.h> | |
| 16 | +#include <linux/platform_device.h> | |
| 17 | +#include <linux/clk.h> | |
| 18 | +#include <linux/usb/otg.h> | |
| 19 | +#include <linux/stmp_device.h> | |
| 20 | +#include <linux/delay.h> | |
| 21 | +#include <linux/err.h> | |
| 22 | +#include <linux/io.h> | |
| 23 | + | |
| 24 | +#define DRIVER_NAME "mxs_phy" | |
| 25 | + | |
| 26 | +#define HW_USBPHY_PWD 0x00 | |
| 27 | +#define HW_USBPHY_CTRL 0x30 | |
| 28 | +#define HW_USBPHY_CTRL_SET 0x34 | |
| 29 | +#define HW_USBPHY_CTRL_CLR 0x38 | |
| 30 | + | |
| 31 | +#define BM_USBPHY_CTRL_SFTRST BIT(31) | |
| 32 | +#define BM_USBPHY_CTRL_CLKGATE BIT(30) | |
| 33 | +#define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15) | |
| 34 | +#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) | |
| 35 | +#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) | |
| 36 | + | |
| 37 | +struct mxs_phy { | |
| 38 | + struct usb_phy phy; | |
| 39 | + struct clk *clk; | |
| 40 | +}; | |
| 41 | + | |
| 42 | +#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) | |
| 43 | + | |
| 44 | +static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) | |
| 45 | +{ | |
| 46 | + void __iomem *base = mxs_phy->phy.io_priv; | |
| 47 | + | |
| 48 | + stmp_reset_block(base + HW_USBPHY_CTRL); | |
| 49 | + | |
| 50 | + /* Power up the PHY */ | |
| 51 | + writel_relaxed(0, base + HW_USBPHY_PWD); | |
| 52 | + | |
| 53 | + /* enable FS/LS device */ | |
| 54 | + writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 | | |
| 55 | + BM_USBPHY_CTRL_ENUTMILEVEL3, | |
| 56 | + base + HW_USBPHY_CTRL_SET); | |
| 57 | +} | |
| 58 | + | |
| 59 | +static int mxs_phy_init(struct usb_phy *phy) | |
| 60 | +{ | |
| 61 | + struct mxs_phy *mxs_phy = to_mxs_phy(phy); | |
| 62 | + | |
| 63 | + clk_prepare_enable(mxs_phy->clk); | |
| 64 | + mxs_phy_hw_init(mxs_phy); | |
| 65 | + | |
| 66 | + return 0; | |
| 67 | +} | |
| 68 | + | |
| 69 | +static void mxs_phy_shutdown(struct usb_phy *phy) | |
| 70 | +{ | |
| 71 | + struct mxs_phy *mxs_phy = to_mxs_phy(phy); | |
| 72 | + | |
| 73 | + writel_relaxed(BM_USBPHY_CTRL_CLKGATE, | |
| 74 | + phy->io_priv + HW_USBPHY_CTRL_SET); | |
| 75 | + | |
| 76 | + clk_disable_unprepare(mxs_phy->clk); | |
| 77 | +} | |
| 78 | + | |
| 79 | +static int mxs_phy_on_connect(struct usb_phy *phy, int port) | |
| 80 | +{ | |
| 81 | + dev_dbg(phy->dev, "Connect on port %d\n", port); | |
| 82 | + | |
| 83 | + mxs_phy_hw_init(to_mxs_phy(phy)); | |
| 84 | + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, | |
| 85 | + phy->io_priv + HW_USBPHY_CTRL_SET); | |
| 86 | + | |
| 87 | + return 0; | |
| 88 | +} | |
| 89 | + | |
| 90 | +static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) | |
| 91 | +{ | |
| 92 | + dev_dbg(phy->dev, "Disconnect on port %d\n", port); | |
| 93 | + | |
| 94 | + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, | |
| 95 | + phy->io_priv + HW_USBPHY_CTRL_CLR); | |
| 96 | + | |
| 97 | + return 0; | |
| 98 | +} | |
| 99 | + | |
| 100 | +static int mxs_phy_probe(struct platform_device *pdev) | |
| 101 | +{ | |
| 102 | + struct resource *res; | |
| 103 | + void __iomem *base; | |
| 104 | + struct clk *clk; | |
| 105 | + struct mxs_phy *mxs_phy; | |
| 106 | + | |
| 107 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 108 | + if (!res) { | |
| 109 | + dev_err(&pdev->dev, "can't get device resources\n"); | |
| 110 | + return -ENOENT; | |
| 111 | + } | |
| 112 | + | |
| 113 | + base = devm_request_and_ioremap(&pdev->dev, res); | |
| 114 | + if (!base) | |
| 115 | + return -EBUSY; | |
| 116 | + | |
| 117 | + clk = devm_clk_get(&pdev->dev, NULL); | |
| 118 | + if (IS_ERR(clk)) { | |
| 119 | + dev_err(&pdev->dev, | |
| 120 | + "can't get the clock, err=%ld", PTR_ERR(clk)); | |
| 121 | + return PTR_ERR(clk); | |
| 122 | + } | |
| 123 | + | |
| 124 | + mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL); | |
| 125 | + if (!mxs_phy) { | |
| 126 | + dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n"); | |
| 127 | + return -ENOMEM; | |
| 128 | + } | |
| 129 | + | |
| 130 | + mxs_phy->phy.io_priv = base; | |
| 131 | + mxs_phy->phy.dev = &pdev->dev; | |
| 132 | + mxs_phy->phy.label = DRIVER_NAME; | |
| 133 | + mxs_phy->phy.init = mxs_phy_init; | |
| 134 | + mxs_phy->phy.shutdown = mxs_phy_shutdown; | |
| 135 | + mxs_phy->phy.notify_connect = mxs_phy_on_connect; | |
| 136 | + mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect; | |
| 137 | + | |
| 138 | + ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier); | |
| 139 | + | |
| 140 | + mxs_phy->clk = clk; | |
| 141 | + | |
| 142 | + platform_set_drvdata(pdev, &mxs_phy->phy); | |
| 143 | + | |
| 144 | + return 0; | |
| 145 | +} | |
| 146 | + | |
| 147 | +static int __devexit mxs_phy_remove(struct platform_device *pdev) | |
| 148 | +{ | |
| 149 | + platform_set_drvdata(pdev, NULL); | |
| 150 | + | |
| 151 | + return 0; | |
| 152 | +} | |
| 153 | + | |
| 154 | +static const struct of_device_id mxs_phy_dt_ids[] = { | |
| 155 | + { .compatible = "fsl,imx23-usbphy", }, | |
| 156 | + { /* sentinel */ } | |
| 157 | +}; | |
| 158 | +MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); | |
| 159 | + | |
| 160 | +static struct platform_driver mxs_phy_driver = { | |
| 161 | + .probe = mxs_phy_probe, | |
| 162 | + .remove = __devexit_p(mxs_phy_remove), | |
| 163 | + .driver = { | |
| 164 | + .name = DRIVER_NAME, | |
| 165 | + .owner = THIS_MODULE, | |
| 166 | + .of_match_table = mxs_phy_dt_ids, | |
| 167 | + }, | |
| 168 | +}; | |
| 169 | + | |
| 170 | +static int __init mxs_phy_module_init(void) | |
| 171 | +{ | |
| 172 | + return platform_driver_register(&mxs_phy_driver); | |
| 173 | +} | |
| 174 | +postcore_initcall(mxs_phy_module_init); | |
| 175 | + | |
| 176 | +static void __exit mxs_phy_module_exit(void) | |
| 177 | +{ | |
| 178 | + platform_driver_unregister(&mxs_phy_driver); | |
| 179 | +} | |
| 180 | +module_exit(mxs_phy_module_exit); | |
| 181 | + | |
| 182 | +MODULE_ALIAS("platform:mxs-usb-phy"); | |
| 183 | +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
| 184 | +MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | |
| 185 | +MODULE_DESCRIPTION("Freescale MXS USB PHY driver"); | |
| 186 | +MODULE_LICENSE("GPL"); | |
| @@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) · 116 unmodified lines | ||
| 117 | 117 | nop->phy.otg->set_host = nop_set_host; |
| 118 | 118 | nop->phy.otg->set_peripheral = nop_set_peripheral; |
| 119 | 119 | |
| 120 | − err = usb_set_transceiver(&nop->phy); | |
| 120 | + err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2); | |
| 121 | 121 | if (err) { |
| 122 | 122 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", |
| 123 | 123 | err); |
| @@ -139,7 +139,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) · 15 unmodified lines | ||
| 139 | 139 | { |
| 140 | 140 | struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); |
| 141 | 141 | |
| 142 | − usb_set_transceiver(NULL); | |
| 142 | + usb_remove_phy(&nop->phy); | |
| 143 | 143 | |
| 144 | 144 | platform_set_drvdata(pdev, NULL); |
| 145 | 145 | kfree(nop->phy.otg); |
| @@ -11,60 +11,195 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include <linux/kernel.h> |
| 13 | 13 | #include <linux/export.h> |
| 14 | +#include <linux/err.h> | |
| 14 | 15 | #include <linux/device.h> |
| 16 | +#include <linux/slab.h> | |
| 15 | 17 | |
| 16 | 18 | #include <linux/usb/otg.h> |
| 17 | 19 | |
| 18 | −static struct usb_phy *phy; | |
| 20 | +static LIST_HEAD(phy_list); | |
| 21 | +static DEFINE_SPINLOCK(phy_lock); | |
| 22 | + | |
| 23 | +static struct usb_phy *__usb_find_phy(struct list_head *list, | |
| 24 | + enum usb_phy_type type) | |
| 25 | +{ | |
| 26 | + struct usb_phy *phy = NULL; | |
| 27 | + | |
| 28 | + list_for_each_entry(phy, list, head) { | |
| 29 | + if (phy->type != type) | |
| 30 | + continue; | |
| 31 | + | |
| 32 | + return phy; | |
| 33 | + } | |
| 34 | + | |
| 35 | + return ERR_PTR(-ENODEV); | |
| 36 | +} | |
| 37 | + | |
| 38 | +static void devm_usb_phy_release(struct device *dev, void *res) | |
| 39 | +{ | |
| 40 | + struct usb_phy *phy = *(struct usb_phy **)res; | |
| 41 | + | |
| 42 | + usb_put_phy(phy); | |
| 43 | +} | |
| 44 | + | |
| 45 | +static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) | |
| 46 | +{ | |
| 47 | + return res == match_data; | |
| 48 | +} | |
| 19 | 49 | |
| 20 | 50 | /** |
| 21 | − * usb_get_transceiver - find the (single) USB transceiver | |
| 51 | + * devm_usb_get_phy - find the USB PHY | |
| 52 | + * @dev - device that requests this phy | |
| 53 | + * @type - the type of the phy the controller requires | |
| 22 | 54 | * |
| 23 | − * Returns the transceiver driver, after getting a refcount to it; or | |
| 24 | − * null if there is no such transceiver. The caller is responsible for | |
| 25 | − * calling usb_put_transceiver() to release that count. | |
| 55 | + * Gets the phy using usb_get_phy(), and associates a device with it using | |
| 56 | + * devres. On driver detach, release function is invoked on the devres data, | |
| 57 | + * then, devres data is freed. | |
| 26 | 58 | * |
| 27 | 59 | * For use by USB host and peripheral drivers. |
| 28 | 60 | */ |
| 29 | −struct usb_phy *usb_get_transceiver(void) | |
| 61 | +struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) | |
| 30 | 62 | { |
| 31 | − if (phy) | |
| 32 | − get_device(phy->dev); | |
| 63 | + struct usb_phy **ptr, *phy; | |
| 64 | + | |
| 65 | + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); | |
| 66 | + if (!ptr) | |
| 67 | + return NULL; | |
| 68 | + | |
| 69 | + phy = usb_get_phy(type); | |
| 70 | + if (!IS_ERR(phy)) { | |
| 71 | + *ptr = phy; | |
| 72 | + devres_add(dev, ptr); | |
| 73 | + } else | |
| 74 | + devres_free(ptr); | |
| 75 | + | |
| 76 | + return phy; | |
| 77 | +} | |
| 78 | +EXPORT_SYMBOL(devm_usb_get_phy); | |
| 79 | + | |
| 80 | +/** | |
| 81 | + * usb_get_phy - find the USB PHY | |
| 82 | + * @type - the type of the phy the controller requires | |
| 83 | + * | |
| 84 | + * Returns the phy driver, after getting a refcount to it; or | |
| 85 | + * -ENODEV if there is no such phy. The caller is responsible for | |
| 86 | + * calling usb_put_phy() to release that count. | |
| 87 | + * | |
| 88 | + * For use by USB host and peripheral drivers. | |
| 89 | + */ | |
| 90 | +struct usb_phy *usb_get_phy(enum usb_phy_type type) | |
| 91 | +{ | |
| 92 | + struct usb_phy *phy = NULL; | |
| 93 | + unsigned long flags; | |
| 94 | + | |
| 95 | + spin_lock_irqsave(&phy_lock, flags); | |
| 96 | + | |
| 97 | + phy = __usb_find_phy(&phy_list, type); | |
| 98 | + if (IS_ERR(phy)) { | |
| 99 | + pr_err("unable to find transceiver of type %s\n", | |
| 100 | + usb_phy_type_string(type)); | |
| 101 | + goto err0; | |
| 102 | + } | |
| 103 | + | |
| 104 | + get_device(phy->dev); | |
| 105 | + | |
| 106 | +err0: | |
| 107 | + spin_unlock_irqrestore(&phy_lock, flags); | |
| 108 | + | |
| 33 | 109 | return phy; |
| 34 | 110 | } |
| 35 | −EXPORT_SYMBOL(usb_get_transceiver); | |
| 111 | +EXPORT_SYMBOL(usb_get_phy); | |
| 112 | + | |
| 113 | +/** | |
| 114 | + * devm_usb_put_phy - release the USB PHY | |
| 115 | + * @dev - device that wants to release this phy | |
| 116 | + * @phy - the phy returned by devm_usb_get_phy() | |
| 117 | + * | |
| 118 | + * destroys the devres associated with this phy and invokes usb_put_phy | |
| 119 | + * to release the phy. | |
| 120 | + * | |
| 121 | + * For use by USB host and peripheral drivers. | |
| 122 | + */ | |
| 123 | +void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) | |
| 124 | +{ | |
| 125 | + int r; | |
| 126 | + | |
| 127 | + r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); | |
| 128 | + dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); | |
| 129 | +} | |
| 130 | +EXPORT_SYMBOL(devm_usb_put_phy); | |
| 36 | 131 | |
| 37 | 132 | /** |
| 38 | − * usb_put_transceiver - release the (single) USB transceiver | |
| 39 | − * @x: the transceiver returned by usb_get_transceiver() | |
| 133 | + * usb_put_phy - release the USB PHY | |
| 134 | + * @x: the phy returned by usb_get_phy() | |
| 40 | 135 | * |
| 41 | − * Releases a refcount the caller received from usb_get_transceiver(). | |
| 136 | + * Releases a refcount the caller received from usb_get_phy(). | |
| 42 | 137 | * |
| 43 | 138 | * For use by USB host and peripheral drivers. |
| 44 | 139 | */ |
| 45 | −void usb_put_transceiver(struct usb_phy *x) | |
| 140 | +void usb_put_phy(struct usb_phy *x) | |
| 46 | 141 | { |
| 47 | 142 | if (x) |
| 48 | 143 | put_device(x->dev); |
| 49 | 144 | } |
| 50 | −EXPORT_SYMBOL(usb_put_transceiver); | |
| 145 | +EXPORT_SYMBOL(usb_put_phy); | |
| 51 | 146 | |
| 52 | 147 | /** |
| 53 | − * usb_set_transceiver - declare the (single) USB transceiver | |
| 54 | − * @x: the USB transceiver to be used; or NULL | |
| 148 | + * usb_add_phy - declare the USB PHY | |
| 149 | + * @x: the USB phy to be used; or NULL | |
| 150 | + * @type - the type of this PHY | |
| 55 | 151 | * |
| 56 | − * This call is exclusively for use by transceiver drivers, which | |
| 152 | + * This call is exclusively for use by phy drivers, which | |
| 57 | 153 | * coordinate the activities of drivers for host and peripheral |
| 58 | 154 | * controllers, and in some cases for VBUS current regulation. |
| 59 | 155 | */ |
| 60 | −int usb_set_transceiver(struct usb_phy *x) | |
| 156 | +int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) | |
| 157 | +{ | |
| 158 | + int ret = 0; | |
| 159 | + unsigned long flags; | |
| 160 | + struct usb_phy *phy; | |
| 161 | + | |
| 162 | + if (x && x->type != USB_PHY_TYPE_UNDEFINED) { | |
| 163 | + dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); | |
| 164 | + return -EINVAL; | |
| 165 | + } | |
| 166 | + | |
| 167 | + spin_lock_irqsave(&phy_lock, flags); | |
| 168 | + | |
| 169 | + list_for_each_entry(phy, &phy_list, head) { | |
| 170 | + if (phy->type == type) { | |
| 171 | + ret = -EBUSY; | |
| 172 | + dev_err(x->dev, "transceiver type %s already exists\n", | |
| 173 | + usb_phy_type_string(type)); | |
| 174 | + goto out; | |
| 175 | + } | |
| 176 | + } | |
| 177 | + | |
| 178 | + x->type = type; | |
| 179 | + list_add_tail(&x->head, &phy_list); | |
| 180 | + | |
| 181 | +out: | |
| 182 | + spin_unlock_irqrestore(&phy_lock, flags); | |
| 183 | + return ret; | |
| 184 | +} | |
| 185 | +EXPORT_SYMBOL(usb_add_phy); | |
| 186 | + | |
| 187 | +/** | |
| 188 | + * usb_remove_phy - remove the OTG PHY | |
| 189 | + * @x: the USB OTG PHY to be removed; | |
| 190 | + * | |
| 191 | + * This reverts the effects of usb_add_phy | |
| 192 | + */ | |
| 193 | +void usb_remove_phy(struct usb_phy *x) | |
| 61 | 194 | { |
| 62 | − if (phy && x) | |
| 63 | − return -EBUSY; | |
| 64 | − phy = x; | |
| 65 | − return 0; | |
| 195 | + unsigned long flags; | |
| 196 | + | |
| 197 | + spin_lock_irqsave(&phy_lock, flags); | |
| 198 | + if (x) | |
| 199 | + list_del(&x->head); | |
| 200 | + spin_unlock_irqrestore(&phy_lock, flags); | |
| 66 | 201 | } |
| 67 | −EXPORT_SYMBOL(usb_set_transceiver); | |
| 202 | +EXPORT_SYMBOL(usb_remove_phy); | |
| 68 | 203 | |
| 69 | 204 | const char *otg_state_string(enum usb_otg_state state) |
| 70 | 205 | { |
| @@ -33,11 +33,11 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/io.h> |
| 34 | 34 | #include <linux/delay.h> |
| 35 | 35 | #include <linux/usb/otg.h> |
| 36 | +#include <linux/usb/musb-omap.h> | |
| 36 | 37 | #include <linux/usb/ulpi.h> |
| 37 | 38 | #include <linux/i2c/twl.h> |
| 38 | 39 | #include <linux/regulator/consumer.h> |
| 39 | 40 | #include <linux/err.h> |
| 40 | −#include <linux/notifier.h> | |
| 41 | 41 | #include <linux/slab.h> |
| 42 | 42 | |
| 43 | 43 | /* Register defines */ |
| @@ -159,7 +159,7 @@ struct twl4030_usb { · 115 unmodified lines | ||
| 159 | 159 | enum twl4030_usb_mode usb_mode; |
| 160 | 160 | |
| 161 | 161 | int irq; |
| 162 | − u8 linkstat; | |
| 162 | + enum omap_musb_vbus_id_status linkstat; | |
| 163 | 163 | bool vbus_supplied; |
| 164 | 164 | u8 asleep; |
| 165 | 165 | bool irq_enabled; |
| @@ -246,11 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) · 80 unmodified lines | ||
| 246 | 246 | |
| 247 | 247 | /*-------------------------------------------------------------------------*/ |
| 248 | 248 | |
| 249 | −static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |
| 249 | +static enum omap_musb_vbus_id_status | |
| 250 | + twl4030_usb_linkstat(struct twl4030_usb *twl) | |
| 250 | 251 | { |
| 251 | 252 | int status; |
| 252 | − int linkstat = USB_EVENT_NONE; | |
| 253 | − struct usb_otg *otg = twl->phy.otg; | |
| 253 | + enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN; | |
| 254 | 254 | |
| 255 | 255 | twl->vbus_supplied = false; |
| 256 | 256 | |
| @@ -273,30 +273,23 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) · 16 unmodified lines | ||
| 273 | 273 | twl->vbus_supplied = true; |
| 274 | 274 | |
| 275 | 275 | if (status & BIT(2)) |
| 276 | − linkstat = USB_EVENT_ID; | |
| 276 | + linkstat = OMAP_MUSB_ID_GROUND; | |
| 277 | 277 | else |
| 278 | − linkstat = USB_EVENT_VBUS; | |
| 279 | − } else | |
| 280 | − linkstat = USB_EVENT_NONE; | |
| 278 | + linkstat = OMAP_MUSB_VBUS_VALID; | |
| 279 | + } else { | |
| 280 | + if (twl->linkstat != OMAP_MUSB_UNKNOWN) | |
| 281 | + linkstat = OMAP_MUSB_VBUS_OFF; | |
| 282 | + } | |
| 281 | 283 | |
| 282 | 284 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", |
| 283 | 285 | status, status, linkstat); |
| 284 | 286 | |
| 285 | − twl->phy.last_event = linkstat; | |
| 286 | − | |
| 287 | 287 | /* REVISIT this assumes host and peripheral controllers |
| 288 | 288 | * are registered, and that both are active... |
| 289 | 289 | */ |
| 290 | 290 | |
| 291 | 291 | spin_lock_irq(&twl->lock); |
| 292 | 292 | twl->linkstat = linkstat; |
| 293 | − if (linkstat == USB_EVENT_ID) { | |
| 294 | − otg->default_a = true; | |
| 295 | − twl->phy.state = OTG_STATE_A_IDLE; | |
| 296 | − } else { | |
| 297 | − otg->default_a = false; | |
| 298 | − twl->phy.state = OTG_STATE_B_IDLE; | |
| 299 | − } | |
| 300 | 293 | spin_unlock_irq(&twl->lock); |
| 301 | 294 | |
| 302 | 295 | return linkstat; |
| @@ -501,10 +494,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); · 198 unmodified lines | ||
| 501 | 494 | static irqreturn_t twl4030_usb_irq(int irq, void *_twl) |
| 502 | 495 | { |
| 503 | 496 | struct twl4030_usb *twl = _twl; |
| 504 | − int status; | |
| 497 | + enum omap_musb_vbus_id_status status; | |
| 505 | 498 | |
| 506 | 499 | status = twl4030_usb_linkstat(twl); |
| 507 | − if (status >= 0) { | |
| 500 | + if (status > 0) { | |
| 508 | 501 | /* FIXME add a set_power() method so that B-devices can |
| 509 | 502 | * configure the charger appropriately. It's not always |
| 510 | 503 | * correct to consume VBUS power, and how much current to |
| @@ -516,13 +509,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) · 5 unmodified lines | ||
| 516 | 509 | * USB_LINK_VBUS state. musb_hdrc won't care until it |
| 517 | 510 | * starts to handle softconnect right. |
| 518 | 511 | */ |
| 519 | − if (status == USB_EVENT_NONE) | |
| 512 | + if (status == OMAP_MUSB_VBUS_OFF || | |
| 513 | + status == OMAP_MUSB_ID_FLOAT) | |
| 520 | 514 | twl4030_phy_suspend(twl, 0); |
| 521 | 515 | else |
| 522 | 516 | twl4030_phy_resume(twl); |
| 523 | 517 | |
| 524 | − atomic_notifier_call_chain(&twl->phy.notifier, status, | |
| 525 | − twl->phy.otg->gadget); | |
| 518 | + omap_musb_mailbox(twl->linkstat); | |
| 526 | 519 | } |
| 527 | 520 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
| 528 | 521 | |
| @@ -531,11 +524,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) · 2 unmodified lines | ||
| 531 | 524 | |
| 532 | 525 | static void twl4030_usb_phy_init(struct twl4030_usb *twl) |
| 533 | 526 | { |
| 534 | − int status; | |
| 527 | + enum omap_musb_vbus_id_status status; | |
| 535 | 528 | |
| 536 | 529 | status = twl4030_usb_linkstat(twl); |
| 537 | − if (status >= 0) { | |
| 538 | − if (status == USB_EVENT_NONE) { | |
| 530 | + if (status > 0) { | |
| 531 | + if (status == OMAP_MUSB_VBUS_OFF || | |
| 532 | + status == OMAP_MUSB_ID_FLOAT) { | |
| 539 | 533 | __twl4030_phy_power(twl, 0); |
| 540 | 534 | twl->asleep = 1; |
| 541 | 535 | } else { |
| @@ -543,8 +537,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) · 1 unmodified line | ||
| 543 | 537 | twl->asleep = 0; |
| 544 | 538 | } |
| 545 | 539 | |
| 546 | − atomic_notifier_call_chain(&twl->phy.notifier, status, | |
| 547 | − twl->phy.otg->gadget); | |
| 540 | + omap_musb_mailbox(twl->linkstat); | |
| 548 | 541 | } |
| 549 | 542 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
| 550 | 543 | } |
| @@ -598,21 +591,20 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) · 47 unmodified lines | ||
| 598 | 591 | return -EINVAL; |
| 599 | 592 | } |
| 600 | 593 | |
| 601 | − twl = kzalloc(sizeof *twl, GFP_KERNEL); | |
| 594 | + twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); | |
| 602 | 595 | if (!twl) |
| 603 | 596 | return -ENOMEM; |
| 604 | 597 | |
| 605 | − otg = kzalloc(sizeof *otg, GFP_KERNEL); | |
| 606 | − if (!otg) { | |
| 607 | − kfree(twl); | |
| 598 | + otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); | |
| 599 | + if (!otg) | |
| 608 | 600 | return -ENOMEM; |
| 609 | − } | |
| 610 | 601 | |
| 611 | 602 | twl->dev = &pdev->dev; |
| 612 | 603 | twl->irq = platform_get_irq(pdev, 0); |
| 613 | 604 | twl->usb_mode = pdata->usb_mode; |
| 614 | 605 | twl->vbus_supplied = false; |
| 615 | 606 | twl->asleep = 1; |
| 607 | + twl->linkstat = OMAP_MUSB_UNKNOWN; | |
| 616 | 608 | |
| 617 | 609 | twl->phy.dev = twl->dev; |
| 618 | 610 | twl->phy.label = "twl4030"; |
| @@ -629,18 +621,14 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 629 | 621 | err = twl4030_usb_ldo_init(twl); |
| 630 | 622 | if (err) { |
| 631 | 623 | dev_err(&pdev->dev, "ldo init failed\n"); |
| 632 | − kfree(otg); | |
| 633 | − kfree(twl); | |
| 634 | 624 | return err; |
| 635 | 625 | } |
| 636 | − usb_set_transceiver(&twl->phy); | |
| 626 | + usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); | |
| 637 | 627 | |
| 638 | 628 | platform_set_drvdata(pdev, twl); |
| 639 | 629 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
| 640 | 630 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
| 641 | 631 | |
| 642 | − ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); | |
| 643 | − | |
| 644 | 632 | /* Our job is to use irqs and status from the power module |
| 645 | 633 | * to keep the transceiver disabled when nothing's connected. |
| 646 | 634 | * |
| @@ -651,13 +639,11 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 651 | 639 | */ |
| 652 | 640 | twl->irq_enabled = true; |
| 653 | 641 | status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, |
| 654 | − IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | |
| 655 | − "twl4030_usb", twl); | |
| 642 | + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | | |
| 643 | + IRQF_ONESHOT, "twl4030_usb", twl); | |
| 656 | 644 | if (status < 0) { |
| 657 | 645 | dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 658 | 646 | twl->irq, status); |
| 659 | − kfree(otg); | |
| 660 | − kfree(twl); | |
| 661 | 647 | return status; |
| 662 | 648 | } |
| 663 | 649 | |
| @@ -701,9 +687,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) · 37 unmodified lines | ||
| 701 | 687 | regulator_put(twl->usb1v8); |
| 702 | 688 | regulator_put(twl->usb3v1); |
| 703 | 689 | |
| 704 | − kfree(twl->phy.otg); | |
| 705 | − kfree(twl); | |
| 706 | − | |
| 707 | 690 | return 0; |
| 708 | 691 | } |
| 709 | 692 | |
| @@ -26,10 +26,10 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/platform_device.h> |
| 27 | 27 | #include <linux/io.h> |
| 28 | 28 | #include <linux/usb/otg.h> |
| 29 | +#include <linux/usb/musb-omap.h> | |
| 29 | 30 | #include <linux/i2c/twl.h> |
| 30 | 31 | #include <linux/regulator/consumer.h> |
| 31 | 32 | #include <linux/err.h> |
| 32 | −#include <linux/notifier.h> | |
| 33 | 33 | #include <linux/slab.h> |
| 34 | 34 | #include <linux/delay.h> |
| 35 | 35 | |
| @@ -100,7 +100,7 @@ struct twl6030_usb { · 64 unmodified lines | ||
| 100 | 100 | |
| 101 | 101 | int irq1; |
| 102 | 102 | int irq2; |
| 103 | − u8 linkstat; | |
| 103 | + enum omap_musb_vbus_id_status linkstat; | |
| 104 | 104 | u8 asleep; |
| 105 | 105 | bool irq_enabled; |
| 106 | 106 | bool vbus_enable; |
| @@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x) · 40 unmodified lines | ||
| 147 | 147 | dev = twl->dev; |
| 148 | 148 | pdata = dev->platform_data; |
| 149 | 149 | |
| 150 | − if (twl->linkstat == USB_EVENT_ID) | |
| 150 | + if (twl->linkstat == OMAP_MUSB_ID_GROUND) | |
| 151 | 151 | pdata->phy_power(twl->dev, 1, 1); |
| 152 | 152 | else |
| 153 | 153 | pdata->phy_power(twl->dev, 0, 1); |
| @@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev, · 81 unmodified lines | ||
| 235 | 235 | spin_lock_irqsave(&twl->lock, flags); |
| 236 | 236 | |
| 237 | 237 | switch (twl->linkstat) { |
| 238 | − case USB_EVENT_VBUS: | |
| 238 | + case OMAP_MUSB_VBUS_VALID: | |
| 239 | 239 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); |
| 240 | 240 | break; |
| 241 | − case USB_EVENT_ID: | |
| 241 | + case OMAP_MUSB_ID_GROUND: | |
| 242 | 242 | ret = snprintf(buf, PAGE_SIZE, "id\n"); |
| 243 | 243 | break; |
| 244 | − case USB_EVENT_NONE: | |
| 244 | + case OMAP_MUSB_VBUS_OFF: | |
| 245 | 245 | ret = snprintf(buf, PAGE_SIZE, "none\n"); |
| 246 | 246 | break; |
| 247 | 247 | default: |
| @@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); · 8 unmodified lines | ||
| 256 | 256 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) |
| 257 | 257 | { |
| 258 | 258 | struct twl6030_usb *twl = _twl; |
| 259 | − struct usb_otg *otg = twl->phy.otg; | |
| 260 | − int status; | |
| 259 | + enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; | |
| 261 | 260 | u8 vbus_state, hw_state; |
| 262 | 261 | |
| 263 | 262 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
| @@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) · 4 unmodified lines | ||
| 268 | 267 | if (vbus_state & VBUS_DET) { |
| 269 | 268 | regulator_enable(twl->usb3v3); |
| 270 | 269 | twl->asleep = 1; |
| 271 | − status = USB_EVENT_VBUS; | |
| 272 | − otg->default_a = false; | |
| 273 | − twl->phy.state = OTG_STATE_B_IDLE; | |
| 270 | + status = OMAP_MUSB_VBUS_VALID; | |
| 274 | 271 | twl->linkstat = status; |
| 275 | − twl->phy.last_event = status; | |
| 276 | − atomic_notifier_call_chain(&twl->phy.notifier, | |
| 277 | − status, otg->gadget); | |
| 272 | + omap_musb_mailbox(status); | |
| 278 | 273 | } else { |
| 279 | − status = USB_EVENT_NONE; | |
| 280 | − twl->linkstat = status; | |
| 281 | − twl->phy.last_event = status; | |
| 282 | − atomic_notifier_call_chain(&twl->phy.notifier, | |
| 283 | − status, otg->gadget); | |
| 284 | − if (twl->asleep) { | |
| 285 | − regulator_disable(twl->usb3v3); | |
| 286 | − twl->asleep = 0; | |
| 274 | + if (twl->linkstat != OMAP_MUSB_UNKNOWN) { | |
| 275 | + status = OMAP_MUSB_VBUS_OFF; | |
| 276 | + twl->linkstat = status; | |
| 277 | + omap_musb_mailbox(status); | |
| 278 | + if (twl->asleep) { | |
| 279 | + regulator_disable(twl->usb3v3); | |
| 280 | + twl->asleep = 0; | |
| 281 | + } | |
| 287 | 282 | } |
| 288 | 283 | } |
| 289 | 284 | } |
| @@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) · 5 unmodified lines | ||
| 295 | 290 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) |
| 296 | 291 | { |
| 297 | 292 | struct twl6030_usb *twl = _twl; |
| 298 | − struct usb_otg *otg = twl->phy.otg; | |
| 299 | − int status = USB_EVENT_NONE; | |
| 293 | + enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; | |
| 300 | 294 | u8 hw_state; |
| 301 | 295 | |
| 302 | 296 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
| @@ -307,13 +301,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) · 4 unmodified lines | ||
| 307 | 301 | twl->asleep = 1; |
| 308 | 302 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); |
| 309 | 303 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); |
| 310 | − status = USB_EVENT_ID; | |
| 311 | − otg->default_a = true; | |
| 312 | − twl->phy.state = OTG_STATE_A_IDLE; | |
| 304 | + status = OMAP_MUSB_ID_GROUND; | |
| 313 | 305 | twl->linkstat = status; |
| 314 | − twl->phy.last_event = status; | |
| 315 | − atomic_notifier_call_chain(&twl->phy.notifier, status, | |
| 316 | − otg->gadget); | |
| 306 | + omap_musb_mailbox(status); | |
| 317 | 307 | } else { |
| 318 | 308 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); |
| 319 | 309 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); |
| @@ -402,20 +392,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) · 82 unmodified lines | ||
| 402 | 392 | struct device *dev = &pdev->dev; |
| 403 | 393 | pdata = dev->platform_data; |
| 404 | 394 | |
| 405 | − twl = kzalloc(sizeof *twl, GFP_KERNEL); | |
| 395 | + twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); | |
| 406 | 396 | if (!twl) |
| 407 | 397 | return -ENOMEM; |
| 408 | 398 | |
| 409 | − otg = kzalloc(sizeof *otg, GFP_KERNEL); | |
| 410 | − if (!otg) { | |
| 411 | − kfree(twl); | |
| 399 | + otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); | |
| 400 | + if (!otg) | |
| 412 | 401 | return -ENOMEM; |
| 413 | − } | |
| 414 | 402 | |
| 415 | 403 | twl->dev = &pdev->dev; |
| 416 | 404 | twl->irq1 = platform_get_irq(pdev, 0); |
| 417 | 405 | twl->irq2 = platform_get_irq(pdev, 1); |
| 418 | 406 | twl->features = pdata->features; |
| 407 | + twl->linkstat = OMAP_MUSB_UNKNOWN; | |
| 419 | 408 | |
| 420 | 409 | twl->phy.dev = twl->dev; |
| 421 | 410 | twl->phy.label = "twl6030"; |
| @@ -436,18 +425,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 436 | 425 | err = twl6030_usb_ldo_init(twl); |
| 437 | 426 | if (err) { |
| 438 | 427 | dev_err(&pdev->dev, "ldo init failed\n"); |
| 439 | − kfree(otg); | |
| 440 | − kfree(twl); | |
| 441 | 428 | return err; |
| 442 | 429 | } |
| 443 | − usb_set_transceiver(&twl->phy); | |
| 430 | + usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); | |
| 444 | 431 | |
| 445 | 432 | platform_set_drvdata(pdev, twl); |
| 446 | 433 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
| 447 | 434 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
| 448 | 435 | |
| 449 | − ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); | |
| 450 | − | |
| 451 | 436 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
| 452 | 437 | |
| 453 | 438 | twl->irq_enabled = true; |
| @@ -458,8 +443,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 458 | 443 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 459 | 444 | twl->irq1, status); |
| 460 | 445 | device_remove_file(twl->dev, &dev_attr_vbus); |
| 461 | − kfree(otg); | |
| 462 | − kfree(twl); | |
| 463 | 446 | return status; |
| 464 | 447 | } |
| 465 | 448 | |
| @@ -471,8 +454,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 471 | 454 | twl->irq2, status); |
| 472 | 455 | free_irq(twl->irq1, twl); |
| 473 | 456 | device_remove_file(twl->dev, &dev_attr_vbus); |
| 474 | − kfree(otg); | |
| 475 | − kfree(twl); | |
| 476 | 457 | return status; |
| 477 | 458 | } |
| 478 | 459 | |
| @@ -503,8 +484,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) · 24 unmodified lines | ||
| 503 | 484 | pdata->phy_exit(twl->dev); |
| 504 | 485 | device_remove_file(twl->dev, &dev_attr_vbus); |
| 505 | 486 | cancel_work_sync(&twl->set_vbus_work); |
| 506 | − kfree(twl->phy.otg); | |
| 507 | − kfree(twl); | |
| 508 | 487 | |
| 509 | 488 | return 0; |
| 510 | 489 | } |
| @@ -771,22 +771,15 @@ static void xfer_work(struct work_struct *work) · 770 unmodified lines | ||
| 771 | 771 | struct usbhs_pipe *pipe = pkt->pipe; |
| 772 | 772 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); |
| 773 | 773 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
| 774 | − struct scatterlist sg; | |
| 775 | 774 | struct dma_async_tx_descriptor *desc; |
| 776 | 775 | struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); |
| 777 | 776 | struct device *dev = usbhs_priv_to_dev(priv); |
| 778 | 777 | enum dma_transfer_direction dir; |
| 779 | − dma_cookie_t cookie; | |
| 780 | 778 | |
| 781 | 779 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; |
| 782 | 780 | |
| 783 | − sg_init_table(&sg, 1); | |
| 784 | − sg_set_page(&sg, virt_to_page(pkt->dma), | |
| 785 | − pkt->length, offset_in_page(pkt->dma)); | |
| 786 | − sg_dma_address(&sg) = pkt->dma + pkt->actual; | |
| 787 | − sg_dma_len(&sg) = pkt->trans; | |
| 788 | − | |
| 789 | − desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, | |
| 781 | + desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual, | |
| 782 | + pkt->trans, dir, | |
| 790 | 783 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
| 791 | 784 | if (!desc) |
| 792 | 785 | return; |
| @@ -794,8 +787,7 @@ static void xfer_work(struct work_struct *work) · 1 unmodified line | ||
| 794 | 787 | desc->callback = usbhsf_dma_complete; |
| 795 | 788 | desc->callback_param = pipe; |
| 796 | 789 | |
| 797 | − cookie = desc->tx_submit(desc); | |
| 798 | − if (cookie < 0) { | |
| 790 | + if (dmaengine_submit(desc) < 0) { | |
| 799 | 791 | dev_err(dev, "Failed to submit dma descriptor\n"); |
| 800 | 792 | return; |
| 801 | 793 | } |
| @@ -176,7 +176,7 @@ static void keyspan_set_termios(struct tty_struct *tty, · 175 unmodified lines | ||
| 176 | 176 | tty_encode_baud_rate(tty, baud_rate, baud_rate); |
| 177 | 177 | /* set CTS/RTS handshake etc. */ |
| 178 | 178 | p_priv->cflag = cflag; |
| 179 | − p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; | |
| 179 | + p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none; | |
| 180 | 180 | |
| 181 | 181 | /* Mark/Space not supported */ |
| 182 | 182 | tty->termios->c_cflag &= ~CMSPAR; |
| @@ -474,7 +474,7 @@ static void usa28_indat_callback(struct urb *urb) · 291 unmodified lines | ||
| 474 | 474 | p_priv = usb_get_serial_port_data(port); |
| 475 | 475 | data = urb->transfer_buffer; |
| 476 | 476 | |
| 477 | − tty =tty_port_tty_get(&port->port); | |
| 477 | + tty = tty_port_tty_get(&port->port); | |
| 478 | 478 | if (tty && urb->actual_length) { |
| 479 | 479 | tty_insert_flip_string(tty, data, urb->actual_length); |
| 480 | 480 | tty_flip_buffer_push(tty); |
| @@ -557,9 +557,9 @@ static void usa28_instat_callback(struct urb *urb) · 76 unmodified lines | ||
| 557 | 557 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
| 558 | 558 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
| 559 | 559 | |
| 560 | − if( old_dcd_state != p_priv->dcd_state && old_dcd_state) { | |
| 560 | + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { | |
| 561 | 561 | tty = tty_port_tty_get(&port->port); |
| 562 | − if (tty && !C_CLOCAL(tty)) | |
| 562 | + if (tty && !C_CLOCAL(tty)) | |
| 563 | 563 | tty_hangup(tty); |
| 564 | 564 | tty_kref_put(tty); |
| 565 | 565 | } |
| @@ -1036,15 +1036,12 @@ static int keyspan_write_room(struct tty_struct *tty) · 470 unmodified lines | ||
| 1036 | 1036 | static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) |
| 1037 | 1037 | { |
| 1038 | 1038 | struct keyspan_port_private *p_priv; |
| 1039 | − struct keyspan_serial_private *s_priv; | |
| 1040 | − struct usb_serial *serial = port->serial; | |
| 1041 | 1039 | const struct keyspan_device_details *d_details; |
| 1042 | 1040 | int i, err; |
| 1043 | 1041 | int baud_rate, device_port; |
| 1044 | 1042 | struct urb *urb; |
| 1045 | 1043 | unsigned int cflag = 0; |
| 1046 | 1044 | |
| 1047 | − s_priv = usb_get_serial_data(serial); | |
| 1048 | 1045 | p_priv = usb_get_serial_port_data(port); |
| 1049 | 1046 | d_details = p_priv->device_details; |
| 1050 | 1047 | |
| @@ -1102,7 +1099,7 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) · 51 unmodified lines | ||
| 1102 | 1099 | } |
| 1103 | 1100 | /* set CTS/RTS handshake etc. */ |
| 1104 | 1101 | p_priv->cflag = cflag; |
| 1105 | − p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; | |
| 1102 | + p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none; | |
| 1106 | 1103 | |
| 1107 | 1104 | keyspan_send_setup(port, 1); |
| 1108 | 1105 | /* mdelay(100); */ |
| @@ -1130,10 +1127,8 @@ static void keyspan_close(struct usb_serial_port *port) · 21 unmodified lines | ||
| 1130 | 1127 | { |
| 1131 | 1128 | int i; |
| 1132 | 1129 | struct usb_serial *serial = port->serial; |
| 1133 | − struct keyspan_serial_private *s_priv; | |
| 1134 | 1130 | struct keyspan_port_private *p_priv; |
| 1135 | 1131 | |
| 1136 | − s_priv = usb_get_serial_data(serial); | |
| 1137 | 1132 | p_priv = usb_get_serial_port_data(port); |
| 1138 | 1133 | |
| 1139 | 1134 | p_priv->rts_state = 0; |
| @@ -1240,7 +1235,7 @@ static int keyspan_fake_startup(struct usb_serial *serial) · 100 unmodified lines | ||
| 1240 | 1235 | |
| 1241 | 1236 | if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { |
| 1242 | 1237 | dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); |
| 1243 | − return(1); | |
| 1238 | + return 1; | |
| 1244 | 1239 | } |
| 1245 | 1240 | |
| 1246 | 1241 | dbg("Uploading Keyspan %s firmware.", fw_name); |
| @@ -1709,7 +1704,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, · 462 unmodified lines | ||
| 1709 | 1704 | msg.setPrescaler = 0xff; |
| 1710 | 1705 | } |
| 1711 | 1706 | |
| 1712 | − msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | |
| 1707 | + msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1; | |
| 1713 | 1708 | switch (p_priv->cflag & CSIZE) { |
| 1714 | 1709 | case CS5: |
| 1715 | 1710 | msg.lcr |= USA_DATABITS_5; |
| @@ -1726,7 +1721,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, · 10 unmodified lines | ||
| 1726 | 1721 | } |
| 1727 | 1722 | if (p_priv->cflag & PARENB) { |
| 1728 | 1723 | /* note USA_PARITY_NONE == 0 */ |
| 1729 | − msg.lcr |= (p_priv->cflag & PARODD)? | |
| 1724 | + msg.lcr |= (p_priv->cflag & PARODD) ? | |
| 1730 | 1725 | USA_PARITY_ODD : USA_PARITY_EVEN; |
| 1731 | 1726 | } |
| 1732 | 1727 | msg.setLcr = 0xff; |
| @@ -1994,7 +1989,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, · 261 unmodified lines | ||
| 1994 | 1989 | /* msg.setPrescaler = 0xff; */ |
| 1995 | 1990 | } |
| 1996 | 1991 | |
| 1997 | − msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | |
| 1992 | + msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1; | |
| 1998 | 1993 | switch (p_priv->cflag & CSIZE) { |
| 1999 | 1994 | case CS5: |
| 2000 | 1995 | msg.lcr |= USA_DATABITS_5; |
| @@ -2011,7 +2006,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, · 10 unmodified lines | ||
| 2011 | 2006 | } |
| 2012 | 2007 | if (p_priv->cflag & PARENB) { |
| 2013 | 2008 | /* note USA_PARITY_NONE == 0 */ |
| 2014 | − msg.lcr |= (p_priv->cflag & PARODD)? | |
| 2009 | + msg.lcr |= (p_priv->cflag & PARODD) ? | |
| 2015 | 2010 | USA_PARITY_ODD : USA_PARITY_EVEN; |
| 2016 | 2011 | } |
| 2017 | 2012 | msg.setLcr = 0xff; |
| @@ -2178,7 +2173,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, · 160 unmodified lines | ||
| 2178 | 2173 | msg.txMode = TXMODE_BYHAND; |
| 2179 | 2174 | } |
| 2180 | 2175 | |
| 2181 | − msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | |
| 2176 | + msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1; | |
| 2182 | 2177 | switch (p_priv->cflag & CSIZE) { |
| 2183 | 2178 | case CS5: |
| 2184 | 2179 | msg.lcr |= USA_DATABITS_5; |
| @@ -2195,7 +2190,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, · 10 unmodified lines | ||
| 2195 | 2190 | } |
| 2196 | 2191 | if (p_priv->cflag & PARENB) { |
| 2197 | 2192 | /* note USA_PARITY_NONE == 0 */ |
| 2198 | − msg.lcr |= (p_priv->cflag & PARODD)? | |
| 2193 | + msg.lcr |= (p_priv->cflag & PARODD) ? | |
| 2199 | 2194 | USA_PARITY_ODD : USA_PARITY_EVEN; |
| 2200 | 2195 | } |
| 2201 | 2196 | if (p_priv->old_cflag != p_priv->cflag) { |
| @@ -2322,7 +2317,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, · 120 unmodified lines | ||
| 2322 | 2317 | } |
| 2323 | 2318 | if (p_priv->cflag & PARENB) { |
| 2324 | 2319 | /* note USA_PARITY_NONE == 0 */ |
| 2325 | − msg.lcr |= (p_priv->cflag & PARODD)? | |
| 2320 | + msg.lcr |= (p_priv->cflag & PARODD) ? | |
| 2326 | 2321 | USA_PARITY_ODD : USA_PARITY_EVEN; |
| 2327 | 2322 | } |
| 2328 | 2323 | msg.setLcr = 0xff; |
| @@ -936,6 +936,8 @@ static const struct usb_device_id option_ids[] = { · 935 unmodified lines | ||
| 936 | 936 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, |
| 937 | 937 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), |
| 938 | 938 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
| 939 | + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), | |
| 940 | + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | |
| 939 | 941 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), |
| 940 | 942 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
| 941 | 943 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), |
| @@ -1310,6 +1312,10 @@ static struct usb_serial_driver * const serial_drivers[] = { · 368 unmodified lines | ||
| 1310 | 1312 | |
| 1311 | 1313 | static bool debug; |
| 1312 | 1314 | |
| 1315 | +struct option_private { | |
| 1316 | + u8 bInterfaceNumber; | |
| 1317 | +}; | |
| 1318 | + | |
| 1313 | 1319 | module_usb_serial_driver(serial_drivers, option_ids); |
| 1314 | 1320 | |
| 1315 | 1321 | static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, |
| @@ -1340,51 +1346,78 @@ static int option_probe(struct usb_serial *serial, · 24 unmodified lines | ||
| 1340 | 1346 | const struct usb_device_id *id) |
| 1341 | 1347 | { |
| 1342 | 1348 | struct usb_wwan_intf_private *data; |
| 1343 | − | |
| 1344 | − /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ | |
| 1345 | − if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && | |
| 1346 | − serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && | |
| 1347 | − serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8) | |
| 1349 | + struct option_private *priv; | |
| 1350 | + struct usb_interface_descriptor *iface_desc = | |
| 1351 | + &serial->interface->cur_altsetting->desc; | |
| 1352 | + struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; | |
| 1353 | + | |
| 1354 | + /* | |
| 1355 | + * D-Link DWM 652 still exposes CD-Rom emulation interface in modem | |
| 1356 | + * mode. | |
| 1357 | + */ | |
| 1358 | + if (dev_desc->idVendor == DLINK_VENDOR_ID && | |
| 1359 | + dev_desc->idProduct == DLINK_PRODUCT_DWM_652 && | |
| 1360 | + iface_desc->bInterfaceClass == 0x08) | |
| 1348 | 1361 | return -ENODEV; |
| 1349 | 1362 | |
| 1350 | 1363 | /* Bandrich modem and AT command interface is 0xff */ |
| 1351 | − if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID || | |
| 1352 | − serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) && | |
| 1353 | − serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) | |
| 1364 | + if ((dev_desc->idVendor == BANDRICH_VENDOR_ID || | |
| 1365 | + dev_desc->idVendor == PIRELLI_VENDOR_ID) && | |
| 1366 | + iface_desc->bInterfaceClass != 0xff) | |
| 1354 | 1367 | return -ENODEV; |
| 1355 | − | |
| 1356 | − /* Don't bind reserved interfaces (like network ones) which often have | |
| 1368 | + /* | |
| 1369 | + * Don't bind reserved interfaces (like network ones) which often have | |
| 1357 | 1370 | * the same class/subclass/protocol as the serial interfaces. Look at |
| 1358 | 1371 | * the Windows driver .INF files for reserved interface numbers. |
| 1359 | 1372 | */ |
| 1360 | 1373 | if (is_blacklisted( |
| 1361 | − serial->interface->cur_altsetting->desc.bInterfaceNumber, | |
| 1374 | + iface_desc->bInterfaceNumber, | |
| 1362 | 1375 | OPTION_BLACKLIST_RESERVED_IF, |
| 1363 | 1376 | (const struct option_blacklist_info *) id->driver_info)) |
| 1364 | 1377 | return -ENODEV; |
| 1365 | − | |
| 1366 | − /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */ | |
| 1367 | − if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID && | |
| 1368 | − serial->dev->descriptor.idProduct == SAMSUNG_PRODUCT_GT_B3730 && | |
| 1369 | − serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) | |
| 1378 | + /* | |
| 1379 | + * Don't bind network interface on Samsung GT-B3730, it is handled by | |
| 1380 | + * a separate module. | |
| 1381 | + */ | |
| 1382 | + if (dev_desc->idVendor == SAMSUNG_VENDOR_ID && | |
| 1383 | + dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 && | |
| 1384 | + iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) | |
| 1370 | 1385 | return -ENODEV; |
| 1371 | 1386 | |
| 1372 | − data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); | |
| 1387 | + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); | |
| 1373 | 1388 | if (!data) |
| 1374 | 1389 | return -ENOMEM; |
| 1375 | − data->send_setup = option_send_setup; | |
| 1390 | + | |
| 1391 | + priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
| 1392 | + if (!priv) { | |
| 1393 | + kfree(data); | |
| 1394 | + return -ENOMEM; | |
| 1395 | + } | |
| 1396 | + | |
| 1397 | + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; | |
| 1398 | + data->private = priv; | |
| 1399 | + | |
| 1400 | + if (!is_blacklisted(iface_desc->bInterfaceNumber, | |
| 1401 | + OPTION_BLACKLIST_SENDSETUP, | |
| 1402 | + (struct option_blacklist_info *)id->driver_info)) { | |
| 1403 | + data->send_setup = option_send_setup; | |
| 1404 | + } | |
| 1376 | 1405 | spin_lock_init(&data->susp_lock); |
| 1377 | − data->private = (void *)id->driver_info; | |
| 1406 | + | |
| 1407 | + usb_set_serial_data(serial, data); | |
| 1408 | + | |
| 1378 | 1409 | return 0; |
| 1379 | 1410 | } |
| 1380 | 1411 | |
| 1381 | 1412 | static void option_release(struct usb_serial *serial) |
| 1382 | 1413 | { |
| 1383 | − struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); | |
| 1414 | + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); | |
| 1415 | + struct option_private *priv = intfdata->private; | |
| 1384 | 1416 | |
| 1385 | 1417 | usb_wwan_release(serial); |
| 1386 | 1418 | |
| 1387 | 1419 | kfree(priv); |
| 1420 | + kfree(intfdata); | |
| 1388 | 1421 | } |
| 1389 | 1422 | |
| 1390 | 1423 | static void option_instat_callback(struct urb *urb) |
| @@ -1451,18 +1484,11 @@ static void option_instat_callback(struct urb *urb) · 60 unmodified lines | ||
| 1451 | 1484 | static int option_send_setup(struct usb_serial_port *port) |
| 1452 | 1485 | { |
| 1453 | 1486 | struct usb_serial *serial = port->serial; |
| 1454 | − struct usb_wwan_intf_private *intfdata = | |
| 1455 | − (struct usb_wwan_intf_private *) serial->private; | |
| 1487 | + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); | |
| 1488 | + struct option_private *priv = intfdata->private; | |
| 1456 | 1489 | struct usb_wwan_port_private *portdata; |
| 1457 | − int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | |
| 1458 | 1490 | int val = 0; |
| 1459 | 1491 | |
| 1460 | − if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, | |
| 1461 | − (struct option_blacklist_info *) intfdata->private)) { | |
| 1462 | − dbg("No send_setup on blacklisted interface #%d\n", ifNum); | |
| 1463 | − return -EIO; | |
| 1464 | − } | |
| 1465 | − | |
| 1466 | 1492 | portdata = usb_get_serial_port_data(port); |
| 1467 | 1493 | |
| 1468 | 1494 | if (portdata->dtr_state) |
| @@ -1470,9 +1496,9 @@ static int option_send_setup(struct usb_serial_port *port) · 1 unmodified line | ||
| 1470 | 1496 | if (portdata->rts_state) |
| 1471 | 1497 | val |= 0x02; |
| 1472 | 1498 | |
| 1473 | − return usb_control_msg(serial->dev, | |
| 1474 | − usb_rcvctrlpipe(serial->dev, 0), | |
| 1475 | − 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); | |
| 1499 | + return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
| 1500 | + 0x22, 0x21, val, priv->bInterfaceNumber, NULL, | |
| 1501 | + 0, USB_CTRL_SET_TIMEOUT); | |
| 1476 | 1502 | } |
| 1477 | 1503 | |
| 1478 | 1504 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| @@ -105,6 +105,10 @@ static const struct usb_device_id id_table[] = { · 104 unmodified lines | ||
| 105 | 105 | {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */ |
| 106 | 106 | {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */ |
| 107 | 107 | {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ |
| 108 | + {USB_DEVICE(0x1199, 0x68a4)}, /* Sierra Wireless QDL */ | |
| 109 | + {USB_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ | |
| 110 | + {USB_DEVICE(0x1199, 0x68a8)}, /* Sierra Wireless QDL */ | |
| 111 | + {USB_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ | |
| 108 | 112 | {USB_DEVICE(0x1199, 0x9010)}, /* Sierra Wireless Gobi 3000 QDL */ |
| 109 | 113 | {USB_DEVICE(0x1199, 0x9012)}, /* Sierra Wireless Gobi 3000 QDL */ |
| 110 | 114 | {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ |
| @@ -112,8 +116,24 @@ static const struct usb_device_id id_table[] = { · 1 unmodified line | ||
| 112 | 116 | {USB_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ |
| 113 | 117 | {USB_DEVICE(0x1199, 0x9018)}, /* Sierra Wireless Gobi 3000 QDL */ |
| 114 | 118 | {USB_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ |
| 119 | + {USB_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ | |
| 115 | 120 | {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */ |
| 116 | 121 | {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */ |
| 122 | + | |
| 123 | + /* non Gobi Qualcomm serial devices */ | |
| 124 | + {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 0)}, /* Sierra Wireless MC7700 Device Management */ | |
| 125 | + {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 2)}, /* Sierra Wireless MC7700 NMEA */ | |
| 126 | + {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 3)}, /* Sierra Wireless MC7700 Modem */ | |
| 127 | + {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 0)}, /* Sierra Wireless MC7750 Device Management */ | |
| 128 | + {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 2)}, /* Sierra Wireless MC7750 NMEA */ | |
| 129 | + {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 3)}, /* Sierra Wireless MC7750 Modem */ | |
| 130 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 0)}, /* Sierra Wireless MC7710 Device Management */ | |
| 131 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 2)}, /* Sierra Wireless MC7710 NMEA */ | |
| 132 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 3)}, /* Sierra Wireless MC7710 Modem */ | |
| 133 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)}, /* Sierra Wireless EM7700 Device Management */ | |
| 134 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)}, /* Sierra Wireless EM7700 NMEA */ | |
| 135 | + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)}, /* Sierra Wireless EM7700 Modem */ | |
| 136 | + | |
| 117 | 137 | { } /* Terminating entry */ |
| 118 | 138 | }; |
| 119 | 139 | MODULE_DEVICE_TABLE(usb, id_table); |
| @@ -127,6 +147,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · 7 unmodified lines | ||
| 127 | 147 | __u8 nintf; |
| 128 | 148 | __u8 ifnum; |
| 129 | 149 | bool is_gobi1k = id->driver_info ? true : false; |
| 150 | + int altsetting = -1; | |
| 130 | 151 | |
| 131 | 152 | dev_dbg(dev, "Is Gobi 1000 = %d\n", is_gobi1k); |
| 132 | 153 | |
| @@ -142,38 +163,43 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · 9 unmodified lines | ||
| 142 | 163 | |
| 143 | 164 | spin_lock_init(&data->susp_lock); |
| 144 | 165 | |
| 145 | − switch (nintf) { | |
| 146 | − case 1: | |
| 166 | + if (nintf == 1) { | |
| 147 | 167 | /* QDL mode */ |
| 148 | 168 | /* Gobi 2000 has a single altsetting, older ones have two */ |
| 149 | 169 | if (serial->interface->num_altsetting == 2) |
| 150 | 170 | intf = &serial->interface->altsetting[1]; |
| 151 | 171 | else if (serial->interface->num_altsetting > 2) |
| 152 | − break; | |
| 172 | + goto done; | |
| 153 | 173 | |
| 154 | 174 | if (intf->desc.bNumEndpoints == 2 && |
| 155 | 175 | usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && |
| 156 | 176 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { |
| 157 | 177 | dev_dbg(dev, "QDL port found\n"); |
| 158 | 178 | |
| 159 | − if (serial->interface->num_altsetting == 1) { | |
| 179 | + if (serial->interface->num_altsetting == 1) | |
| 160 | 180 | retval = 0; /* Success */ |
| 161 | − break; | |
| 162 | − } | |
| 163 | − | |
| 164 | − retval = usb_set_interface(serial->dev, ifnum, 1); | |
| 165 | − if (retval < 0) { | |
| 166 | − dev_err(dev, | |
| 167 | − "Could not set interface, error %d\n", | |
| 168 | − retval); | |
| 169 | − retval = -ENODEV; | |
| 170 | − kfree(data); | |
| 171 | − } | |
| 181 | + else | |
| 182 | + altsetting = 1; | |
| 172 | 183 | } |
| 173 | − break; | |
| 184 | + goto done; | |
| 174 | 185 | |
| 175 | − case 3: | |
| 176 | − case 4: | |
| 186 | + } | |
| 187 | + | |
| 188 | + /* allow any number of interfaces when doing direct interface match */ | |
| 189 | + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) { | |
| 190 | + dev_dbg(dev, "Generic Qualcomm serial interface found\n"); | |
| 191 | + altsetting = 0; | |
| 192 | + goto done; | |
| 193 | + } | |
| 194 | + | |
| 195 | + if (nintf < 3 || nintf > 4) { | |
| 196 | + dev_err(dev, "unknown number of interfaces: %d\n", nintf); | |
| 197 | + goto done; | |
| 198 | + } | |
| 199 | + | |
| 200 | + /* default to enabling interface */ | |
| 201 | + altsetting = 0; | |
| 202 | + switch (ifnum) { | |
| 177 | 203 | /* Composite mode; don't bind to the QMI/net interface as that |
| 178 | 204 | * gets handled by other drivers. |
| 179 | 205 | */ |
| @@ -191,53 +217,44 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · 11 unmodified lines | ||
| 191 | 217 | * 3: NMEA |
| 192 | 218 | */ |
| 193 | 219 | |
| 194 | − if (ifnum == 1 && !is_gobi1k) { | |
| 220 | + case 1: | |
| 221 | + if (is_gobi1k) | |
| 222 | + altsetting = -1; | |
| 223 | + else | |
| 195 | 224 | dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n"); |
| 196 | − retval = usb_set_interface(serial->dev, ifnum, 0); | |
| 197 | − if (retval < 0) { | |
| 198 | − dev_err(dev, | |
| 199 | − "Could not set interface, error %d\n", | |
| 200 | − retval); | |
| 201 | − retval = -ENODEV; | |
| 202 | − kfree(data); | |
| 203 | − } | |
| 204 | − } else if (ifnum == 2) { | |
| 205 | − dev_dbg(dev, "Modem port found\n"); | |
| 206 | − retval = usb_set_interface(serial->dev, ifnum, 0); | |
| 207 | − if (retval < 0) { | |
| 208 | − dev_err(dev, | |
| 209 | − "Could not set interface, error %d\n", | |
| 210 | − retval); | |
| 211 | − retval = -ENODEV; | |
| 212 | − kfree(data); | |
| 213 | − } | |
| 214 | − } else if (ifnum==3 && !is_gobi1k) { | |
| 225 | + break; | |
| 226 | + case 2: | |
| 227 | + dev_dbg(dev, "Modem port found\n"); | |
| 228 | + break; | |
| 229 | + case 3: | |
| 230 | + if (is_gobi1k) | |
| 231 | + altsetting = -1; | |
| 232 | + else | |
| 215 | 233 | /* |
| 216 | 234 | * NMEA (serial line 9600 8N1) |
| 217 | 235 | * # echo "\$GPS_START" > /dev/ttyUSBx |
| 218 | 236 | * # echo "\$GPS_STOP" > /dev/ttyUSBx |
| 219 | 237 | */ |
| 220 | 238 | dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); |
| 221 | − retval = usb_set_interface(serial->dev, ifnum, 0); | |
| 222 | − if (retval < 0) { | |
| 223 | − dev_err(dev, | |
| 224 | − "Could not set interface, error %d\n", | |
| 225 | − retval); | |
| 226 | − retval = -ENODEV; | |
| 227 | − kfree(data); | |
| 228 | − } | |
| 229 | − } | |
| 230 | − break; | |
| 239 | + } | |
| 231 | 240 | |
| 232 | − default: | |
| 233 | − dev_err(dev, "unknown number of interfaces: %d\n", nintf); | |
| 234 | − kfree(data); | |
| 235 | − retval = -ENODEV; | |
| 241 | +done: | |
| 242 | + if (altsetting >= 0) { | |
| 243 | + retval = usb_set_interface(serial->dev, ifnum, altsetting); | |
| 244 | + if (retval < 0) { | |
| 245 | + dev_err(dev, | |
| 246 | + "Could not set interface, error %d\n", | |
| 247 | + retval); | |
| 248 | + retval = -ENODEV; | |
| 249 | + } | |
| 236 | 250 | } |
| 237 | 251 | |
| 238 | − /* Set serial->private if not returning -ENODEV */ | |
| 239 | − if (retval != -ENODEV) | |
| 252 | + /* Set serial->private if not returning error */ | |
| 253 | + if (retval == 0) | |
| 240 | 254 | usb_set_serial_data(serial, data); |
| 255 | + else | |
| 256 | + kfree(data); | |
| 257 | + | |
| 241 | 258 | return retval; |
| 242 | 259 | } |
| 243 | 260 | |
| @@ -345,7 +345,6 @@ static void qt2_set_termios(struct tty_struct *tty, · 344 unmodified lines | ||
| 345 | 345 | static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) |
| 346 | 346 | { |
| 347 | 347 | struct usb_serial *serial; |
| 348 | − struct qt2_serial_private *serial_priv; | |
| 349 | 348 | struct qt2_port_private *port_priv; |
| 350 | 349 | u8 *data; |
| 351 | 350 | u16 device_port; |
| @@ -357,7 +356,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) · 5 unmodified lines | ||
| 357 | 356 | serial = port->serial; |
| 358 | 357 | |
| 359 | 358 | port_priv = usb_get_serial_port_data(port); |
| 360 | − serial_priv = usb_get_serial_data(serial); | |
| 361 | 359 | |
| 362 | 360 | /* set the port to RS232 mode */ |
| 363 | 361 | status = qt2_control_msg(serial->dev, QT2_GET_SET_QMCR, |
| @@ -417,13 +415,11 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) · 53 unmodified lines | ||
| 417 | 415 | static void qt2_close(struct usb_serial_port *port) |
| 418 | 416 | { |
| 419 | 417 | struct usb_serial *serial; |
| 420 | − struct qt2_serial_private *serial_priv; | |
| 421 | 418 | struct qt2_port_private *port_priv; |
| 422 | 419 | unsigned long flags; |
| 423 | 420 | int i; |
| 424 | 421 | |
| 425 | 422 | serial = port->serial; |
| 426 | − serial_priv = usb_get_serial_data(serial); | |
| 427 | 423 | port_priv = usb_get_serial_port_data(port); |
| 428 | 424 | |
| 429 | 425 | port_priv->is_open = false; |
| @@ -288,9 +288,6 @@ static const struct usb_device_id id_table[] = { · 287 unmodified lines | ||
| 288 | 288 | /* Sierra Wireless HSPA Non-Composite Device */ |
| 289 | 289 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, |
| 290 | 290 | { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ |
| 291 | − { USB_DEVICE(0x1199, 0x68A2), /* Sierra Wireless MC77xx in QMI mode */ | |
| 292 | − .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | |
| 293 | − }, | |
| 294 | 291 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ |
| 295 | 292 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist |
| 296 | 293 | }, |
| @@ -66,7 +66,7 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) · 65 unmodified lines | ||
| 66 | 66 | * NOTE: This only works because a scsi_cmnd struct field contains |
| 67 | 67 | * a unsigned char cmnd[16], so we know we have storage available |
| 68 | 68 | */ |
| 69 | − for (; srb->cmd_len<12; srb->cmd_len++) | |
| 69 | + for (; srb->cmd_len < 12; srb->cmd_len++) | |
| 70 | 70 | srb->cmnd[srb->cmd_len] = 0; |
| 71 | 71 | |
| 72 | 72 | /* send the command to the transport layer */ |
| @@ -76,14 +76,14 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) · 3 unmodified lines | ||
| 76 | 76 | void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) |
| 77 | 77 | { |
| 78 | 78 | /* fix some commands -- this is a form of mode translation |
| 79 | − * UFI devices only accept 12 byte long commands | |
| 79 | + * UFI devices only accept 12 byte long commands | |
| 80 | 80 | * |
| 81 | 81 | * NOTE: This only works because a scsi_cmnd struct field contains |
| 82 | 82 | * a unsigned char cmnd[16], so we know we have storage available |
| 83 | 83 | */ |
| 84 | 84 | |
| 85 | 85 | /* Pad the ATAPI command with zeros */ |
| 86 | − for (; srb->cmd_len<12; srb->cmd_len++) | |
| 86 | + for (; srb->cmd_len < 12; srb->cmd_len++) | |
| 87 | 87 | srb->cmnd[srb->cmd_len] = 0; |
| 88 | 88 | |
| 89 | 89 | /* set command length to 12 bytes (this affects the transport layer) */ |
| @@ -41,16 +41,17 @@ struct sense_iu_old { · 40 unmodified lines | ||
| 41 | 41 | struct uas_dev_info { |
| 42 | 42 | struct usb_interface *intf; |
| 43 | 43 | struct usb_device *udev; |
| 44 | − int qdepth; | |
| 44 | + struct usb_anchor sense_urbs; | |
| 45 | + struct usb_anchor data_urbs; | |
| 46 | + int qdepth, resetting; | |
| 47 | + struct response_ui response; | |
| 45 | 48 | unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; |
| 46 | 49 | unsigned use_streams:1; |
| 47 | 50 | unsigned uas_sense_old:1; |
| 48 | 51 | struct scsi_cmnd *cmnd; |
| 49 | − struct urb *status_urb; /* used only if stream support is available */ | |
| 50 | 52 | }; |
| 51 | 53 | |
| 52 | 54 | enum { |
| 53 | − ALLOC_STATUS_URB = (1 << 0), | |
| 54 | 55 | SUBMIT_STATUS_URB = (1 << 1), |
| 55 | 56 | ALLOC_DATA_IN_URB = (1 << 2), |
| 56 | 57 | SUBMIT_DATA_IN_URB = (1 << 3), |
| @@ -58,18 +59,18 @@ enum { · 1 unmodified line | ||
| 58 | 59 | SUBMIT_DATA_OUT_URB = (1 << 5), |
| 59 | 60 | ALLOC_CMD_URB = (1 << 6), |
| 60 | 61 | SUBMIT_CMD_URB = (1 << 7), |
| 61 | − COMPLETED_DATA_IN = (1 << 8), | |
| 62 | − COMPLETED_DATA_OUT = (1 << 9), | |
| 63 | − DATA_COMPLETES_CMD = (1 << 10), | |
| 62 | + COMMAND_INFLIGHT = (1 << 8), | |
| 63 | + DATA_IN_URB_INFLIGHT = (1 << 9), | |
| 64 | + DATA_OUT_URB_INFLIGHT = (1 << 10), | |
| 65 | + COMMAND_COMPLETED = (1 << 11), | |
| 64 | 66 | }; |
| 65 | 67 | |
| 66 | 68 | /* Overrides scsi_pointer */ |
| 67 | 69 | struct uas_cmd_info { |
| 68 | 70 | unsigned int state; |
| 69 | 71 | unsigned int stream; |
| 72 | + unsigned int aborted; | |
| 70 | 73 | struct urb *cmd_urb; |
| 71 | − /* status_urb is used only if stream support isn't available */ | |
| 72 | − struct urb *status_urb; | |
| 73 | 74 | struct urb *data_in_urb; |
| 74 | 75 | struct urb *data_out_urb; |
| 75 | 76 | struct list_head list; |
| @@ -114,7 +115,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) · 38 unmodified lines | ||
| 114 | 115 | { |
| 115 | 116 | struct sense_iu *sense_iu = urb->transfer_buffer; |
| 116 | 117 | struct scsi_device *sdev = cmnd->device; |
| 117 | − struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 118 | 118 | |
| 119 | 119 | if (urb->actual_length > 16) { |
| 120 | 120 | unsigned len = be16_to_cpup(&sense_iu->len); |
| @@ -132,15 +132,12 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) · 11 unmodified lines | ||
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | cmnd->result = sense_iu->status; |
| 135 | − if (!(cmdinfo->state & DATA_COMPLETES_CMD)) | |
| 136 | − cmnd->scsi_done(cmnd); | |
| 137 | 135 | } |
| 138 | 136 | |
| 139 | 137 | static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) |
| 140 | 138 | { |
| 141 | 139 | struct sense_iu_old *sense_iu = urb->transfer_buffer; |
| 142 | 140 | struct scsi_device *sdev = cmnd->device; |
| 143 | − struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 144 | 141 | |
| 145 | 142 | if (urb->actual_length > 8) { |
| 146 | 143 | unsigned len = be16_to_cpup(&sense_iu->len) - 2; |
| @@ -158,17 +155,51 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) · 11 unmodified lines | ||
| 158 | 155 | } |
| 159 | 156 | |
| 160 | 157 | cmnd->result = sense_iu->status; |
| 161 | − if (!(cmdinfo->state & DATA_COMPLETES_CMD)) | |
| 162 | − cmnd->scsi_done(cmnd); | |
| 158 | +} | |
| 159 | + | |
| 160 | +static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) | |
| 161 | +{ | |
| 162 | + struct uas_cmd_info *ci = (void *)&cmnd->SCp; | |
| 163 | + | |
| 164 | + scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:" | |
| 165 | + "%s%s%s%s%s%s%s%s%s%s%s\n", | |
| 166 | + caller, cmnd, cmnd->request->tag, | |
| 167 | + (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", | |
| 168 | + (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", | |
| 169 | + (ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "", | |
| 170 | + (ci->state & ALLOC_DATA_OUT_URB) ? " a-out" : "", | |
| 171 | + (ci->state & SUBMIT_DATA_OUT_URB) ? " s-out" : "", | |
| 172 | + (ci->state & ALLOC_CMD_URB) ? " a-cmd" : "", | |
| 173 | + (ci->state & SUBMIT_CMD_URB) ? " s-cmd" : "", | |
| 174 | + (ci->state & COMMAND_INFLIGHT) ? " CMD" : "", | |
| 175 | + (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "", | |
| 176 | + (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "", | |
| 177 | + (ci->state & COMMAND_COMPLETED) ? " done" : ""); | |
| 178 | +} | |
| 179 | + | |
| 180 | +static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) | |
| 181 | +{ | |
| 182 | + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 183 | + | |
| 184 | + if (cmdinfo->state & (COMMAND_INFLIGHT | | |
| 185 | + DATA_IN_URB_INFLIGHT | | |
| 186 | + DATA_OUT_URB_INFLIGHT)) | |
| 187 | + return -EBUSY; | |
| 188 | + BUG_ON(cmdinfo->state & COMMAND_COMPLETED); | |
| 189 | + cmdinfo->state |= COMMAND_COMPLETED; | |
| 190 | + usb_free_urb(cmdinfo->data_in_urb); | |
| 191 | + usb_free_urb(cmdinfo->data_out_urb); | |
| 192 | + cmnd->scsi_done(cmnd); | |
| 193 | + return 0; | |
| 163 | 194 | } |
| 164 | 195 | |
| 165 | 196 | static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, |
| 166 | − unsigned direction) | |
| 197 | + unsigned direction) | |
| 167 | 198 | { |
| 168 | 199 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; |
| 169 | 200 | int err; |
| 170 | 201 | |
| 171 | − cmdinfo->state = direction; | |
| 202 | + cmdinfo->state |= direction | SUBMIT_STATUS_URB; | |
| 172 | 203 | err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); |
| 173 | 204 | if (err) { |
| 174 | 205 | spin_lock(&uas_work_lock); |
| @@ -186,12 +217,15 @@ static void uas_stat_cmplt(struct urb *urb) · 11 unmodified lines | ||
| 186 | 217 | struct scsi_cmnd *cmnd; |
| 187 | 218 | struct uas_cmd_info *cmdinfo; |
| 188 | 219 | u16 tag; |
| 189 | − int ret; | |
| 190 | 220 | |
| 191 | 221 | if (urb->status) { |
| 192 | 222 | dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); |
| 193 | − if (devinfo->use_streams) | |
| 194 | − usb_free_urb(urb); | |
| 223 | + usb_free_urb(urb); | |
| 224 | + return; | |
| 225 | + } | |
| 226 | + | |
| 227 | + if (devinfo->resetting) { | |
| 228 | + usb_free_urb(urb); | |
| 195 | 229 | return; |
| 196 | 230 | } |
| 197 | 231 | |
| @@ -201,47 +235,34 @@ static void uas_stat_cmplt(struct urb *urb) · 3 unmodified lines | ||
| 201 | 235 | else |
| 202 | 236 | cmnd = scsi_host_find_tag(shost, tag - 1); |
| 203 | 237 | if (!cmnd) { |
| 204 | − if (devinfo->use_streams) { | |
| 238 | + if (iu->iu_id != IU_ID_RESPONSE) { | |
| 205 | 239 | usb_free_urb(urb); |
| 206 | 240 | return; |
| 207 | 241 | } |
| 208 | − ret = usb_submit_urb(urb, GFP_ATOMIC); | |
| 209 | − if (ret) | |
| 210 | − dev_err(&urb->dev->dev, "failed submit status urb\n"); | |
| 211 | − return; | |
| 242 | + } else { | |
| 243 | + cmdinfo = (void *)&cmnd->SCp; | |
| 212 | 244 | } |
| 213 | − cmdinfo = (void *)&cmnd->SCp; | |
| 214 | 245 | |
| 215 | 246 | switch (iu->iu_id) { |
| 216 | 247 | case IU_ID_STATUS: |
| 217 | 248 | if (devinfo->cmnd == cmnd) |
| 218 | 249 | devinfo->cmnd = NULL; |
| 219 | 250 | |
| 220 | − if (!(cmdinfo->state & COMPLETED_DATA_IN) && | |
| 221 | − cmdinfo->data_in_urb) { | |
| 222 | − if (devinfo->use_streams) { | |
| 223 | − cmdinfo->state |= DATA_COMPLETES_CMD; | |
| 224 | − usb_unlink_urb(cmdinfo->data_in_urb); | |
| 225 | − } else { | |
| 226 | − usb_free_urb(cmdinfo->data_in_urb); | |
| 227 | − } | |
| 228 | − } | |
| 229 | − if (!(cmdinfo->state & COMPLETED_DATA_OUT) && | |
| 230 | − cmdinfo->data_out_urb) { | |
| 231 | − if (devinfo->use_streams) { | |
| 232 | − cmdinfo->state |= DATA_COMPLETES_CMD; | |
| 233 | − usb_unlink_urb(cmdinfo->data_in_urb); | |
| 234 | − } else { | |
| 235 | − usb_free_urb(cmdinfo->data_out_urb); | |
| 236 | − } | |
| 237 | − } | |
| 238 | − | |
| 239 | 251 | if (urb->actual_length < 16) |
| 240 | 252 | devinfo->uas_sense_old = 1; |
| 241 | 253 | if (devinfo->uas_sense_old) |
| 242 | 254 | uas_sense_old(urb, cmnd); |
| 243 | 255 | else |
| 244 | 256 | uas_sense(urb, cmnd); |
| 257 | + if (cmnd->result != 0) { | |
| 258 | + /* cancel data transfers on error */ | |
| 259 | + if (cmdinfo->state & DATA_IN_URB_INFLIGHT) | |
| 260 | + usb_unlink_urb(cmdinfo->data_in_urb); | |
| 261 | + if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) | |
| 262 | + usb_unlink_urb(cmdinfo->data_out_urb); | |
| 263 | + } | |
| 264 | + cmdinfo->state &= ~COMMAND_INFLIGHT; | |
| 265 | + uas_try_complete(cmnd, __func__); | |
| 245 | 266 | break; |
| 246 | 267 | case IU_ID_READ_READY: |
| 247 | 268 | uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB); |
| @@ -249,74 +270,59 @@ static void uas_stat_cmplt(struct urb *urb) · 1 unmodified line | ||
| 249 | 270 | case IU_ID_WRITE_READY: |
| 250 | 271 | uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); |
| 251 | 272 | break; |
| 273 | + case IU_ID_RESPONSE: | |
| 274 | + /* store results for uas_eh_task_mgmt() */ | |
| 275 | + memcpy(&devinfo->response, iu, sizeof(devinfo->response)); | |
| 276 | + break; | |
| 252 | 277 | default: |
| 253 | 278 | scmd_printk(KERN_ERR, cmnd, |
| 254 | 279 | "Bogus IU (%d) received on status pipe\n", iu->iu_id); |
| 255 | 280 | } |
| 256 | − | |
| 257 | − if (devinfo->use_streams) { | |
| 258 | − usb_free_urb(urb); | |
| 259 | − return; | |
| 260 | − } | |
| 261 | − | |
| 262 | − ret = usb_submit_urb(urb, GFP_ATOMIC); | |
| 263 | − if (ret) | |
| 264 | − dev_err(&urb->dev->dev, "failed submit status urb\n"); | |
| 265 | −} | |
| 266 | − | |
| 267 | −static void uas_data_out_cmplt(struct urb *urb) | |
| 268 | −{ | |
| 269 | − struct scsi_cmnd *cmnd = urb->context; | |
| 270 | − struct scsi_data_buffer *sdb = scsi_out(cmnd); | |
| 271 | − struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 272 | − | |
| 273 | − cmdinfo->state |= COMPLETED_DATA_OUT; | |
| 274 | − | |
| 275 | − sdb->resid = sdb->length - urb->actual_length; | |
| 276 | 281 | usb_free_urb(urb); |
| 277 | − | |
| 278 | − if (cmdinfo->state & DATA_COMPLETES_CMD) | |
| 279 | − cmnd->scsi_done(cmnd); | |
| 280 | 282 | } |
| 281 | 283 | |
| 282 | −static void uas_data_in_cmplt(struct urb *urb) | |
| 284 | +static void uas_data_cmplt(struct urb *urb) | |
| 283 | 285 | { |
| 284 | 286 | struct scsi_cmnd *cmnd = urb->context; |
| 285 | − struct scsi_data_buffer *sdb = scsi_in(cmnd); | |
| 286 | 287 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; |
| 288 | + struct scsi_data_buffer *sdb = NULL; | |
| 287 | 289 | |
| 288 | − cmdinfo->state |= COMPLETED_DATA_IN; | |
| 289 | − | |
| 290 | − sdb->resid = sdb->length - urb->actual_length; | |
| 291 | − usb_free_urb(urb); | |
| 292 | − | |
| 293 | − if (cmdinfo->state & DATA_COMPLETES_CMD) | |
| 294 | − cmnd->scsi_done(cmnd); | |
| 290 | + if (cmdinfo->data_in_urb == urb) { | |
| 291 | + sdb = scsi_in(cmnd); | |
| 292 | + cmdinfo->state &= ~DATA_IN_URB_INFLIGHT; | |
| 293 | + } else if (cmdinfo->data_out_urb == urb) { | |
| 294 | + sdb = scsi_out(cmnd); | |
| 295 | + cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT; | |
| 296 | + } | |
| 297 | + BUG_ON(sdb == NULL); | |
| 298 | + if (urb->status) { | |
| 299 | + /* error: no data transfered */ | |
| 300 | + sdb->resid = sdb->length; | |
| 301 | + } else { | |
| 302 | + sdb->resid = sdb->length - urb->actual_length; | |
| 303 | + } | |
| 304 | + if (cmdinfo->aborted) { | |
| 305 | + return; | |
| 306 | + } | |
| 307 | + uas_try_complete(cmnd, __func__); | |
| 295 | 308 | } |
| 296 | 309 | |
| 297 | 310 | static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, |
| 298 | − unsigned int pipe, struct scsi_cmnd *cmnd, | |
| 299 | − enum dma_data_direction dir) | |
| 311 | + unsigned int pipe, u16 stream_id, | |
| 312 | + struct scsi_cmnd *cmnd, | |
| 313 | + enum dma_data_direction dir) | |
| 300 | 314 | { |
| 301 | − struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 302 | 315 | struct usb_device *udev = devinfo->udev; |
| 303 | 316 | struct urb *urb = usb_alloc_urb(0, gfp); |
| 304 | − struct scsi_data_buffer *sdb; | |
| 305 | − usb_complete_t complete_fn; | |
| 306 | − u16 stream_id = cmdinfo->stream; | |
| 317 | + struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE) | |
| 318 | + ? scsi_in(cmnd) : scsi_out(cmnd); | |
| 307 | 319 | |
| 308 | 320 | if (!urb) |
| 309 | 321 | goto out; |
| 310 | − if (dir == DMA_FROM_DEVICE) { | |
| 311 | − sdb = scsi_in(cmnd); | |
| 312 | − complete_fn = uas_data_in_cmplt; | |
| 313 | − } else { | |
| 314 | − sdb = scsi_out(cmnd); | |
| 315 | − complete_fn = uas_data_out_cmplt; | |
| 316 | − } | |
| 317 | 322 | usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, |
| 318 | − complete_fn, cmnd); | |
| 319 | − urb->stream_id = stream_id; | |
| 323 | + uas_data_cmplt, cmnd); | |
| 324 | + if (devinfo->use_streams) | |
| 325 | + urb->stream_id = stream_id; | |
| 320 | 326 | urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; |
| 321 | 327 | urb->sg = sdb->table.sgl; |
| 322 | 328 | out: |
| @@ -324,7 +330,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, · 1 unmodified line | ||
| 324 | 330 | } |
| 325 | 331 | |
| 326 | 332 | static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, |
| 327 | − struct Scsi_Host *shost, u16 stream_id) | |
| 333 | + struct Scsi_Host *shost, u16 stream_id) | |
| 328 | 334 | { |
| 329 | 335 | struct usb_device *udev = devinfo->udev; |
| 330 | 336 | struct urb *urb = usb_alloc_urb(0, gfp); |
| @@ -388,38 +394,95 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, · 57 unmodified lines | ||
| 388 | 394 | return NULL; |
| 389 | 395 | } |
| 390 | 396 | |
| 397 | +static int uas_submit_task_urb(struct scsi_cmnd *cmnd, gfp_t gfp, | |
| 398 | + u8 function, u16 stream_id) | |
| 399 | +{ | |
| 400 | + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; | |
| 401 | + struct usb_device *udev = devinfo->udev; | |
| 402 | + struct urb *urb = usb_alloc_urb(0, gfp); | |
| 403 | + struct task_mgmt_iu *iu; | |
| 404 | + int err = -ENOMEM; | |
| 405 | + | |
| 406 | + if (!urb) | |
| 407 | + goto err; | |
| 408 | + | |
| 409 | + iu = kzalloc(sizeof(*iu), gfp); | |
| 410 | + if (!iu) | |
| 411 | + goto err; | |
| 412 | + | |
| 413 | + iu->iu_id = IU_ID_TASK_MGMT; | |
| 414 | + iu->tag = cpu_to_be16(stream_id); | |
| 415 | + int_to_scsilun(cmnd->device->lun, &iu->lun); | |
| 416 | + | |
| 417 | + iu->function = function; | |
| 418 | + switch (function) { | |
| 419 | + case TMF_ABORT_TASK: | |
| 420 | + if (blk_rq_tagged(cmnd->request)) | |
| 421 | + iu->task_tag = cpu_to_be16(cmnd->request->tag + 2); | |
| 422 | + else | |
| 423 | + iu->task_tag = cpu_to_be16(1); | |
| 424 | + break; | |
| 425 | + } | |
| 426 | + | |
| 427 | + usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu), | |
| 428 | + usb_free_urb, NULL); | |
| 429 | + urb->transfer_flags |= URB_FREE_BUFFER; | |
| 430 | + | |
| 431 | + err = usb_submit_urb(urb, gfp); | |
| 432 | + if (err) | |
| 433 | + goto err; | |
| 434 | + | |
| 435 | + return 0; | |
| 436 | + | |
| 437 | +err: | |
| 438 | + usb_free_urb(urb); | |
| 439 | + return err; | |
| 440 | +} | |
| 441 | + | |
| 391 | 442 | /* |
| 392 | 443 | * Why should I request the Status IU before sending the Command IU? Spec |
| 393 | 444 | * says to, but also says the device may receive them in any order. Seems |
| 394 | 445 | * daft to me. |
| 395 | 446 | */ |
| 396 | 447 | |
| 397 | −static int uas_submit_urbs(struct scsi_cmnd *cmnd, | |
| 398 | − struct uas_dev_info *devinfo, gfp_t gfp) | |
| 448 | +static int uas_submit_sense_urb(struct Scsi_Host *shost, | |
| 449 | + gfp_t gfp, unsigned int stream) | |
| 399 | 450 | { |
| 400 | − struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
| 451 | + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; | |
| 452 | + struct urb *urb; | |
| 401 | 453 | |
| 402 | − if (cmdinfo->state & ALLOC_STATUS_URB) { | |
| 403 | − cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, | |
| 404 | − cmnd->device->host, cmdinfo->stream); | |
| 405 | − if (!cmdinfo->status_urb) | |
| 406 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 407 | − cmdinfo->state &= ~ALLOC_STATUS_URB; | |
| 454 | + urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream); | |
| 455 | + if (!urb) | |
| 456 | + return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 457 | + if (usb_submit_urb(urb, gfp)) { | |
| 458 | + shost_printk(KERN_INFO, shost, | |
| 459 | + "sense urb submission failure\n"); | |
| 460 | + usb_free_urb(urb); | |
| 461 | + return SCSI_MLQUEUE_DEVICE_BUSY; | |
289 more lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.