Pull USB updates from Greg KH: "Here is the big set of USB patches for 5.4-rc1. Two major chunks of code are moving out of the tree and into the staging directory, uwb and wusb (wireless USB support), because there are no devices that actually use this protocol anymore, and what we have today probably doesn't work at all given that the maintainers left many many years ago. So move it to staging where it will be removed in a few releases if no one screams. Other than that, lots of little things. The usual gadget and xhci and usb serial driver updates, along with a bunch of sysfs file cleanups due to the driver core changes to support that. Nothing really major, just constant forward progress. All of these have been in linux-next for a while with no reported issues" * tag 'usb-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (159 commits) USB: usbcore: Fix slab-out-of-bounds bug during device reset usb: cdns3: Remove redundant dev_err call in cdns3_probe() USB: rio500: Fix lockdep violation USB: rio500: simplify locking usb: mtu3: register a USB Role Switch for dual role mode usb: common: add USB GPIO based connection detection driver usb: common: create Kconfig file usb: roles: get usb-role-switch from parent usb: roles: Add fwnode_usb_role_switch_get() function device connection: Add fwnode_connection_find_match() usb: roles: Introduce stubs for the exiting functions in role.h dt-bindings: usb: mtu3: add properties about USB Role Switch dt-bindings: usb: add binding for USB GPIO based connection detection driver dt-bindings: connector: add optional properties for Type-B dt-binding: usb: add usb-role-switch property usbip: Implement SG support to vhci-hcd and stub driver usb: roles: intel: Enable static DRD mode for role switch xhci-ext-caps.c: Add property to disable Intel SW switch usb: dwc3: remove generic PHY calibrate() calls usb: core: phy: add support for PHY calibration ...
Unified · Split
| @@ -17,6 +17,20 @@ Optional properties: · 16 unmodified lines | |||
| 17 | - self-powered: Set this property if the usb device that has its own power | 17 | - self-powered: Set this property if the usb device that has its own power |
| 18 | source. | 18 | source. |
| 19 | 19 | ||
| 20 | Optional properties for usb-b-connector: | ||
| 21 | - id-gpios: an input gpio for USB ID pin. | ||
| 22 | - vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of | ||
| 23 | VBUS 5V. | ||
| 24 | see gpio/gpio.txt. | ||
| 25 | - vbus-supply: a phandle to the regulator for USB VBUS if needed when host | ||
| 26 | mode or dual role mode is supported. | ||
| 27 | Particularly, if use an output GPIO to control a VBUS regulator, should | ||
| 28 | model it as a regulator. | ||
| 29 | see regulator/fixed-regulator.yaml | ||
| 30 | - pinctrl-names : a pinctrl state named "default" is optional | ||
| 31 | - pinctrl-0 : pin control group | ||
| 32 | see pinctrl/pinctrl-bindings.txt | ||
| 33 | |||
| 20 | Optional properties for usb-c-connector: | 34 | Optional properties for usb-c-connector: |
| 21 | - power-role: should be one of "source", "sink" or "dual"(DRP) if typec | 35 | - power-role: should be one of "source", "sink" or "dual"(DRP) if typec |
| 22 | connector has power support. | 36 | connector has power support. |
| @@ -0,0 +1,45 @@ | |||
| 1 | Binding for the Cadence USBSS-DRD controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - reg: Physical base address and size of the controller's register areas. | ||
| 5 | Controller has 3 different regions: | ||
| 6 | - HOST registers area | ||
| 7 | - DEVICE registers area | ||
| 8 | - OTG/DRD registers area | ||
| 9 | - reg-names - register memory area names: | ||
| 10 | "xhci" - for HOST registers space | ||
| 11 | "dev" - for DEVICE registers space | ||
| 12 | "otg" - for OTG/DRD registers space | ||
| 13 | - compatible: Should contain: "cdns,usb3" | ||
| 14 | - interrupts: Interrupts used by cdns3 controller: | ||
| 15 | "host" - interrupt used by XHCI driver. | ||
| 16 | "peripheral" - interrupt used by device driver | ||
| 17 | "otg" - interrupt used by DRD/OTG part of driver | ||
| 18 | |||
| 19 | Optional properties: | ||
| 20 | - maximum-speed : valid arguments are "super-speed", "high-speed" and | ||
| 21 | "full-speed"; refer to usb/generic.txt | ||
| 22 | - dr_mode: Should be one of "host", "peripheral" or "otg". | ||
| 23 | - phys: reference to the USB PHY | ||
| 24 | - phy-names: from the *Generic PHY* bindings; | ||
| 25 | Supported names are: | ||
| 26 | - cdns3,usb2-phy | ||
| 27 | - cdns3,usb3-phy | ||
| 28 | |||
| 29 | - cdns,on-chip-buff-size : size of memory intended as internal memory for endpoints | ||
| 30 | buffers expressed in KB | ||
| 31 | |||
| 32 | Example: | ||
| 33 | usb@f3000000 { | ||
| 34 | compatible = "cdns,usb3"; | ||
| 35 | interrupts = <GIC_USB_IRQ 7 IRQ_TYPE_LEVEL_HIGH>, | ||
| 36 | <GIC_USB_IRQ 7 IRQ_TYPE_LEVEL_HIGH>, | ||
| 37 | <GIC_USB_IRQ 8 IRQ_TYPE_LEVEL_HIGH>; | ||
| 38 | interrupt-names = "host", "peripheral", "otg"; | ||
| 39 | reg = <0xf3000000 0x10000>, /* memory area for HOST registers */ | ||
| 40 | <0xf3010000 0x10000>, /* memory area for DEVICE registers */ | ||
| 41 | <0xf3020000 0x10000>; /* memory area for OTG/DRD registers */ | ||
| 42 | reg-names = "xhci", "dev", "otg"; | ||
| 43 | phys = <&usb2_phy>, <&usb3_phy>; | ||
| 44 | phy-names = "cdns3,usb2-phy", "cnds3,usb3-phy"; | ||
| 45 | }; | ||
| @@ -10,6 +10,7 @@ Required properties: · 9 unmodified lines | |||
| 10 | "fsl,imx6sx-usb" | 10 | "fsl,imx6sx-usb" |
| 11 | "fsl,imx6ul-usb" | 11 | "fsl,imx6ul-usb" |
| 12 | "fsl,imx7d-usb" | 12 | "fsl,imx7d-usb" |
| 13 | "fsl,imx7ulp-usb" | ||
| 13 | "lsi,zevio-usb" | 14 | "lsi,zevio-usb" |
| 14 | "qcom,ci-hdrc" | 15 | "qcom,ci-hdrc" |
| 15 | "chipidea,usb2" | 16 | "chipidea,usb2" |
| @@ -12,13 +12,11 @@ Required properties: · 11 unmodified lines | |||
| 12 | - interrupts: interrupt number to the cpu. | 12 | - interrupts: interrupt number to the cpu. |
| 13 | - clocks: from common clock binding: handle to usb clock. | 13 | - clocks: from common clock binding: handle to usb clock. |
| 14 | - clock-names: from common clock binding: Shall be "usbhost". | 14 | - clock-names: from common clock binding: Shall be "usbhost". |
| 15 | - port: if in the SoC there are EHCI phys, they should be listed here. | 15 | - phys: from the *Generic PHY* bindings; array specifying phy(s) used |
| 16 | One phy per port. Each port should have following entries: | 16 | by the root port. |
| 17 | - reg: port number on EHCI controller, e.g | 17 | - phy-names: from the *Generic PHY* bindings; array of the names for |
| 18 | On Exynos5250, port 0 is USB2.0 otg phy | 18 | each phy for the root ports, must be a subset of the following: |
| 19 | port 1 is HSIC phy0 | 19 | "host", "hsic0", "hsic1". |
| 20 | port 2 is HSIC phy1 | ||
| 21 | - phys: from the *Generic PHY* bindings; specifying phy used by port. | ||
| 22 | 20 | ||
| 23 | Optional properties: | 21 | Optional properties: |
| 24 | - samsung,vbus-gpio: if present, specifies the GPIO that | 22 | - samsung,vbus-gpio: if present, specifies the GPIO that |
| @@ -35,12 +33,8 @@ Example: · 10 unmodified lines | |||
| 35 | clocks = <&clock 285>; | 33 | clocks = <&clock 285>; |
| 36 | clock-names = "usbhost"; | 34 | clock-names = "usbhost"; |
| 37 | 35 | ||
| 38 | #address-cells = <1>; | 36 | phys = <&usb2phy 1>; |
| 39 | #size-cells = <0>; | 37 | phy-names = "host"; |
| 40 | port@0 { | ||
| 41 | reg = <0>; | ||
| 42 | phys = <&usb2phy 1>; | ||
| 43 | }; | ||
| 44 | }; | 38 | }; |
| 45 | 39 | ||
| 46 | OHCI | 40 | OHCI |
| @@ -52,13 +46,11 @@ Required properties: · 5 unmodified lines | |||
| 52 | - interrupts: interrupt number to the cpu. | 46 | - interrupts: interrupt number to the cpu. |
| 53 | - clocks: from common clock binding: handle to usb clock. | 47 | - clocks: from common clock binding: handle to usb clock. |
| 54 | - clock-names: from common clock binding: Shall be "usbhost". | 48 | - clock-names: from common clock binding: Shall be "usbhost". |
| 55 | - port: if in the SoC there are OHCI phys, they should be listed here. | 49 | - phys: from the *Generic PHY* bindings; array specifying phy(s) used |
| 56 | One phy per port. Each port should have following entries: | 50 | by the root port. |
| 57 | - reg: port number on OHCI controller, e.g | 51 | - phy-names: from the *Generic PHY* bindings; array of the names for |
| 58 | On Exynos5250, port 0 is USB2.0 otg phy | 52 | each phy for the root ports, must be a subset of the following: |
| 59 | port 1 is HSIC phy0 | 53 | "host", "hsic0", "hsic1". |
| 60 | port 2 is HSIC phy1 | ||
| 61 | - phys: from the *Generic PHY* bindings, specifying phy used by port. | ||
| 62 | 54 | ||
| 63 | Example: | 55 | Example: |
| 64 | usb@12120000 { | 56 | usb@12120000 { |
| @@ -69,13 +61,8 @@ Example: · 4 unmodified lines | |||
| 69 | clocks = <&clock 285>; | 61 | clocks = <&clock 285>; |
| 70 | clock-names = "usbhost"; | 62 | clock-names = "usbhost"; |
| 71 | 63 | ||
| 72 | #address-cells = <1>; | 64 | phys = <&usb2phy 1>; |
| 73 | #size-cells = <0>; | 65 | phy-names = "host"; |
| 74 | port@0 { | ||
| 75 | reg = <0>; | ||
| 76 | phys = <&usb2phy 1>; | ||
| 77 | }; | ||
| 78 | |||
| 79 | }; | 66 | }; |
| 80 | 67 | ||
| 81 | DWC3 | 68 | DWC3 |
| @@ -11,13 +11,6 @@ Required sub-node: · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | Documentation/devicetree/bindings/connector/usb-connector.txt | 12 | Documentation/devicetree/bindings/connector/usb-connector.txt |
| 13 | 13 | ||
| 14 | Deprecated properties : | ||
| 15 | - fcs,max-sink-microvolt : Maximum sink voltage accepted by port controller | ||
| 16 | - fcs,max-sink-microamp : Maximum sink current accepted by port controller | ||
| 17 | - fcs,max-sink-microwatt : Maximum sink power accepted by port controller | ||
| 18 | - fcs,operating-sink-microwatt : Minimum amount of power accepted from a sink | ||
| 19 | when negotiating | ||
| 20 | |||
| 21 | 14 | ||
| 22 | Example: | 15 | Example: |
| 23 | 16 | ||
| @@ -30,6 +30,10 @@ Optional properties: · 29 unmodified lines | |||
| 30 | optional for OTG device. | 30 | optional for OTG device. |
| 31 | - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is | 31 | - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is |
| 32 | optional for OTG device. | 32 | optional for OTG device. |
| 33 | - usb-role-switch: boolean, indicates that the device is capable of assigning | ||
| 34 | the USB data role (USB host or USB device) for a given | ||
| 35 | USB connector, such as Type-C, Type-B(micro). | ||
| 36 | see connector/usb-connector.txt. | ||
| 33 | 37 | ||
| 34 | This is an attribute to a USB controller such as: | 38 | This is an attribute to a USB controller such as: |
| 35 | 39 | ||
| @@ -30,7 +30,8 @@ Required properties: · 29 unmodified lines | |||
| 30 | the following ones are optional: | 30 | the following ones are optional: |
| 31 | "ref_ck": reference clock used by low power mode etc, | 31 | "ref_ck": reference clock used by low power mode etc, |
| 32 | "mcu_ck": mcu_bus clock for register access, | 32 | "mcu_ck": mcu_bus clock for register access, |
| 33 | "dma_ck": dma_bus clock for data transfer by DMA | 33 | "dma_ck": dma_bus clock for data transfer by DMA, |
| 34 | "xhci_ck": controller clock | ||
| 34 | 35 | ||
| 35 | - phys : see usb-hcd.txt in the current directory | 36 | - phys : see usb-hcd.txt in the current directory |
| 36 | 37 | ||
| @@ -100,7 +101,7 @@ Required properties: · 63 unmodified lines | |||
| 100 | - clocks : a list of phandle + clock-specifier pairs, one for each | 101 | - clocks : a list of phandle + clock-specifier pairs, one for each |
| 101 | entry in clock-names | 102 | entry in clock-names |
| 102 | - clock-names : must contain "sys_ck", and the following ones are optional: | 103 | - clock-names : must contain "sys_ck", and the following ones are optional: |
| 103 | "ref_ck", "mcu_ck" and "dma_ck" | 104 | "ref_ck", "mcu_ck" and "dma_ck", "xhci_ck" |
| 104 | 105 | ||
| 105 | Optional properties: | 106 | Optional properties: |
| 106 | - vbus-supply : reference to the VBUS regulator; | 107 | - vbus-supply : reference to the VBUS regulator; |
| @@ -16,7 +16,7 @@ Required properties: · 15 unmodified lines | |||
| 16 | entry in clock-names | 16 | entry in clock-names |
| 17 | - clock-names : must contain "sys_ck" for clock of controller, | 17 | - clock-names : must contain "sys_ck" for clock of controller, |
| 18 | the following clocks are optional: | 18 | the following clocks are optional: |
| 19 | "ref_ck", "mcu_ck" and "dam_ck"; | 19 | "ref_ck", "mcu_ck" and "dma_ck"; |
| 20 | - phys : see usb-hcd.txt in the current directory | 20 | - phys : see usb-hcd.txt in the current directory |
| 21 | - dr_mode : should be one of "host", "peripheral" or "otg", | 21 | - dr_mode : should be one of "host", "peripheral" or "otg", |
| 22 | refer to usb/generic.txt | 22 | refer to usb/generic.txt |
| @@ -28,8 +28,13 @@ Optional properties: · 5 unmodified lines | |||
| 28 | parent's address space | 28 | parent's address space |
| 29 | - extcon : external connector for vbus and idpin changes detection, needed | 29 | - extcon : external connector for vbus and idpin changes detection, needed |
| 30 | when supports dual-role mode. | 30 | when supports dual-role mode. |
| 31 | it's considered valid for compatibility reasons, not allowed for | ||
| 32 | new bindings, and use "usb-role-switch" property instead. | ||
| 31 | - vbus-supply : reference to the VBUS regulator, needed when supports | 33 | - vbus-supply : reference to the VBUS regulator, needed when supports |
| 32 | dual-role mode. | 34 | dual-role mode. |
| 35 | it's considered valid for compatibility reasons, not allowed for | ||
| 36 | new bindings, and put into a usb-connector node. | ||
| 37 | see connector/usb-connector.txt. | ||
| 33 | - pinctrl-names : a pinctrl state named "default" is optional, and need be | 38 | - pinctrl-names : a pinctrl state named "default" is optional, and need be |
| 34 | defined if auto drd switch is enabled, that means the property dr_mode | 39 | defined if auto drd switch is enabled, that means the property dr_mode |
| 35 | is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" | 40 | is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" |
| @@ -39,6 +44,8 @@ Optional properties: · 3 unmodified lines | |||
| 39 | 44 | ||
| 40 | - maximum-speed : valid arguments are "super-speed", "high-speed" and | 45 | - maximum-speed : valid arguments are "super-speed", "high-speed" and |
| 41 | "full-speed"; refer to usb/generic.txt | 46 | "full-speed"; refer to usb/generic.txt |
| 47 | - usb-role-switch : use USB Role Switch to support dual-role switch, but | ||
| 48 | not extcon; see usb/generic.txt. | ||
| 42 | - enable-manual-drd : supports manual dual-role switch via debugfs; usually | 49 | - enable-manual-drd : supports manual dual-role switch via debugfs; usually |
| 43 | used when receptacle is TYPE-A and also wants to support dual-role | 50 | used when receptacle is TYPE-A and also wants to support dual-role |
| 44 | mode. | 51 | mode. |
| @@ -61,6 +68,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example · 16 unmodified lines | |||
| 61 | if host mode is enabled. The DT binding details of xhci can be found in: | 68 | if host mode is enabled. The DT binding details of xhci can be found in: |
| 62 | Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 69 | Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt |
| 63 | 70 | ||
| 71 | The port would be added as subnode if use "usb-role-switch" property. | ||
| 72 | see graph.txt | ||
| 73 | |||
| 64 | Example: | 74 | Example: |
| 65 | ssusb: usb@11271000 { | 75 | ssusb: usb@11271000 { |
| 66 | compatible = "mediatek,mt8173-mtu3"; | 76 | compatible = "mediatek,mt8173-mtu3"; |
File renamed without changes.
| @@ -0,0 +1,30 @@ | |||
| 1 | USB GPIO Based Connection Detection | ||
| 2 | |||
| 3 | This is typically used to switch dual role mode from the USB ID pin connected | ||
| 4 | to an input GPIO, and also used to enable/disable device mode from the USB | ||
| 5 | Vbus pin connected to an input GPIO. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : should include "gpio-usb-b-connector" and "usb-b-connector". | ||
| 9 | - id-gpios, vbus-gpios : input gpios, either one of them must be present, | ||
| 10 | and both can be present as well. | ||
| 11 | see connector/usb-connector.txt | ||
| 12 | |||
| 13 | Optional properties: | ||
| 14 | - vbus-supply : can be present if needed when supports dual role mode. | ||
| 15 | see connector/usb-connector.txt | ||
| 16 | |||
| 17 | - Sub-nodes: | ||
| 18 | - port : can be present. | ||
| 19 | see graph.txt | ||
| 20 | |||
| 21 | Example: | ||
| 22 | |||
| 23 | &mtu3 { | ||
| 24 | connector { | ||
| 25 | compatible = "gpio-usb-b-connector", "usb-b-connector"; | ||
| 26 | type = "micro"; | ||
| 27 | id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; | ||
| 28 | vbus-supply = <&usb_p0_vbus>; | ||
| 29 | }; | ||
| 30 | }; | ||
| @@ -7,6 +7,7 @@ Required properties: · 6 unmodified lines | |||
| 7 | "fsl,vf610-usbmisc" for Vybrid vf610 | 7 | "fsl,vf610-usbmisc" for Vybrid vf610 |
| 8 | "fsl,imx6sx-usbmisc" for imx6sx | 8 | "fsl,imx6sx-usbmisc" for imx6sx |
| 9 | "fsl,imx7d-usbmisc" for imx7d | 9 | "fsl,imx7d-usbmisc" for imx7d |
| 10 | "fsl,imx7ulp-usbmisc" for imx7ulp | ||
| 10 | - reg: Should contain registers location and length | 11 | - reg: Should contain registers location and length |
| 11 | 12 | ||
| 12 | Examples: | 13 | Examples: |
| @@ -3797,14 +3797,9 @@ F: scripts/sign-file.c · 3796 unmodified lines | |||
| 3797 | F: scripts/extract-cert.c | 3797 | F: scripts/extract-cert.c |
| 3798 | 3798 | ||
| 3799 | CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: | 3799 | CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: |
| 3800 | L: linux-usb@vger.kernel.org | 3800 | L: devel@driverdev.osuosl.org |
| 3801 | S: Orphan | 3801 | S: Obsolete |
| 3802 | F: Documentation/usb/wusb-design-overview.rst | 3802 | F: drivers/staging/wusbcore/ |
| 3803 | F: Documentation/usb/wusb-cbaf | ||
| 3804 | F: drivers/usb/host/hwa-hc.c | ||
| 3805 | F: drivers/usb/host/whci/ | ||
| 3806 | F: drivers/usb/wusbcore/ | ||
| 3807 | F: include/linux/usb/wusb* | ||
| 3808 | 3803 | ||
| 3809 | CFAG12864B LCD DRIVER | 3804 | CFAG12864B LCD DRIVER |
| 3810 | M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com> | 3805 | M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com> |
| @@ -16500,11 +16495,9 @@ F: drivers/usb/common/ulpi.c · 12689 unmodified lines | |||
| 16500 | F: include/linux/ulpi/ | 16495 | F: include/linux/ulpi/ |
| 16501 | 16496 | ||
| 16502 | ULTRA-WIDEBAND (UWB) SUBSYSTEM: | 16497 | ULTRA-WIDEBAND (UWB) SUBSYSTEM: |
| 16503 | L: linux-usb@vger.kernel.org | 16498 | L: devel@driverdev.osuosl.org |
| 16504 | S: Orphan | 16499 | S: Obsolete |
| 16505 | F: drivers/uwb/ | 16500 | F: drivers/staging/uwb/ |
| 16506 | F: include/linux/uwb.h | ||
| 16507 | F: include/linux/uwb/ | ||
| 16508 | 16501 | ||
| 16509 | UNICODE SUBSYSTEM: | 16502 | UNICODE SUBSYSTEM: |
| 16510 | M: Gabriel Krisman Bertazi <krisman@collabora.com> | 16503 | M: Gabriel Krisman Bertazi <krisman@collabora.com> |
| @@ -380,23 +380,8 @@ · 379 unmodified lines | |||
| 380 | clocks = <&clock CLK_USB_HOST>; | 380 | clocks = <&clock CLK_USB_HOST>; |
| 381 | clock-names = "usbhost"; | 381 | clock-names = "usbhost"; |
| 382 | status = "disabled"; | 382 | status = "disabled"; |
| 383 | #address-cells = <1>; | 383 | phys = <&exynos_usbphy 1>, <&exynos_usbphy 2>, <&exynos_usbphy 3>; |
| 384 | #size-cells = <0>; | 384 | phy-names = "host", "hsic0", "hsic1"; |
| 385 | port@0 { | ||
| 386 | reg = <0>; | ||
| 387 | phys = <&exynos_usbphy 1>; | ||
| 388 | status = "disabled"; | ||
| 389 | }; | ||
| 390 | port@1 { | ||
| 391 | reg = <1>; | ||
| 392 | phys = <&exynos_usbphy 2>; | ||
| 393 | status = "disabled"; | ||
| 394 | }; | ||
| 395 | port@2 { | ||
| 396 | reg = <2>; | ||
| 397 | phys = <&exynos_usbphy 3>; | ||
| 398 | status = "disabled"; | ||
| 399 | }; | ||
| 400 | }; | 385 | }; |
| 401 | 386 | ||
| 402 | ohci: ohci@12590000 { | 387 | ohci: ohci@12590000 { |
| @@ -406,13 +391,8 @@ · 3 unmodified lines | |||
| 406 | clocks = <&clock CLK_USB_HOST>; | 391 | clocks = <&clock CLK_USB_HOST>; |
| 407 | clock-names = "usbhost"; | 392 | clock-names = "usbhost"; |
| 408 | status = "disabled"; | 393 | status = "disabled"; |
| 409 | #address-cells = <1>; | 394 | phys = <&exynos_usbphy 1>; |
| 410 | #size-cells = <0>; | 395 | phy-names = "host"; |
| 411 | port@0 { | ||
| 412 | reg = <0>; | ||
| 413 | phys = <&exynos_usbphy 1>; | ||
| 414 | status = "disabled"; | ||
| 415 | }; | ||
| 416 | }; | 396 | }; |
| 417 | 397 | ||
| 418 | gpu: gpu@13000000 { | 398 | gpu: gpu@13000000 { |
| @@ -204,9 +204,8 @@ · 203 unmodified lines | |||
| 204 | 204 | ||
| 205 | &ehci { | 205 | &ehci { |
| 206 | status = "okay"; | 206 | status = "okay"; |
| 207 | port@0 { | 207 | phys = <&exynos_usbphy 1>; |
| 208 | status = "okay"; | 208 | phy-names = "host"; |
| 209 | }; | ||
| 210 | }; | 209 | }; |
| 211 | 210 | ||
| 212 | &exynos_usbphy { | 211 | &exynos_usbphy { |
| @@ -520,9 +519,6 @@ · 307 unmodified lines | |||
| 520 | 519 | ||
| 521 | &ohci { | 520 | &ohci { |
| 522 | status = "okay"; | 521 | status = "okay"; |
| 523 | port@0 { | ||
| 524 | status = "okay"; | ||
| 525 | }; | ||
| 526 | }; | 522 | }; |
| 527 | 523 | ||
| 528 | &pinctrl_1 { | 524 | &pinctrl_1 { |
| @@ -146,13 +146,8 @@ · 145 unmodified lines | |||
| 146 | /* In order to reset USB ethernet */ | 146 | /* In order to reset USB ethernet */ |
| 147 | samsung,vbus-gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>; | 147 | samsung,vbus-gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>; |
| 148 | 148 | ||
| 149 | port@0 { | 149 | phys = <&exynos_usbphy 1>, <&exynos_usbphy 3>; |
| 150 | status = "okay"; | 150 | phy-names = "host", "hsic1"; |
| 151 | }; | ||
| 152 | |||
| 153 | port@2 { | ||
| 154 | status = "okay"; | ||
| 155 | }; | ||
| 156 | }; | 151 | }; |
| 157 | 152 | ||
| 158 | &exynos_usbphy { | 153 | &exynos_usbphy { |
| @@ -105,12 +105,8 @@ · 104 unmodified lines | |||
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | &ehci { | 107 | &ehci { |
| 108 | port@1 { | 108 | phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>; |
| 109 | status = "okay"; | 109 | phy-names = "hsic0", "hsic1"; |
| 110 | }; | ||
| 111 | port@2 { | ||
| 112 | status = "okay"; | ||
| 113 | }; | ||
| 114 | }; | 110 | }; |
| 115 | 111 | ||
| 116 | &sound { | 112 | &sound { |
| @@ -72,9 +72,8 @@ · 71 unmodified lines | |||
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | &ehci { | 74 | &ehci { |
| 75 | port@1 { | 75 | phys = <&exynos_usbphy 2>; |
| 76 | status = "okay"; | 76 | phy-names = "hsic0"; |
| 77 | }; | ||
| 78 | }; | 77 | }; |
| 79 | 78 | ||
| 80 | &mshc_0 { | 79 | &mshc_0 { |
| @@ -88,13 +88,8 @@ · 87 unmodified lines | |||
| 88 | &ehci { | 88 | &ehci { |
| 89 | samsung,vbus-gpio = <&gpx3 5 1>; | 89 | samsung,vbus-gpio = <&gpx3 5 1>; |
| 90 | status = "okay"; | 90 | status = "okay"; |
| 91 | 91 | phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>; | |
| 92 | port@1 { | 92 | phy-names = "hsic0", "hsic1"; |
| 93 | status = "okay"; | ||
| 94 | }; | ||
| 95 | port@2 { | ||
| 96 | status = "okay"; | ||
| 97 | }; | ||
| 98 | }; | 93 | }; |
| 99 | 94 | ||
| 100 | &fimd { | 95 | &fimd { |
| @@ -665,12 +665,8 @@ · 664 unmodified lines | |||
| 665 | 665 | ||
| 666 | clocks = <&clock CLK_USB2>; | 666 | clocks = <&clock CLK_USB2>; |
| 667 | clock-names = "usbhost"; | 667 | clock-names = "usbhost"; |
| 668 | #address-cells = <1>; | 668 | phys = <&usb2_phy_gen 1>; |
| 669 | #size-cells = <0>; | 669 | phy-names = "host"; |
| 670 | port@0 { | ||
| 671 | reg = <0>; | ||
| 672 | phys = <&usb2_phy_gen 1>; | ||
| 673 | }; | ||
| 674 | }; | 670 | }; |
| 675 | 671 | ||
| 676 | ohci: usb@12120000 { | 672 | ohci: usb@12120000 { |
| @@ -680,12 +676,8 @@ · 3 unmodified lines | |||
| 680 | 676 | ||
| 681 | clocks = <&clock CLK_USB2>; | 677 | clocks = <&clock CLK_USB2>; |
| 682 | clock-names = "usbhost"; | 678 | clock-names = "usbhost"; |
| 683 | #address-cells = <1>; | 679 | phys = <&usb2_phy_gen 1>; |
| 684 | #size-cells = <0>; | 680 | phy-names = "host"; |
| 685 | port@0 { | ||
| 686 | reg = <0>; | ||
| 687 | phys = <&usb2_phy_gen 1>; | ||
| 688 | }; | ||
| 689 | }; | 681 | }; |
| 690 | 682 | ||
| 691 | usb2_phy_gen: phy@12130000 { | 683 | usb2_phy_gen: phy@12130000 { |
| @@ -189,26 +189,16 @@ · 188 unmodified lines | |||
| 189 | compatible = "samsung,exynos4210-ehci"; | 189 | compatible = "samsung,exynos4210-ehci"; |
| 190 | reg = <0x12110000 0x100>; | 190 | reg = <0x12110000 0x100>; |
| 191 | interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; | 191 | interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; |
| 192 | 192 | phys = <&usb2_phy 1>; | |
| 193 | #address-cells = <1>; | 193 | phy-names = "host"; |
| 194 | #size-cells = <0>; | ||
| 195 | port@0 { | ||
| 196 | reg = <0>; | ||
| 197 | phys = <&usb2_phy 1>; | ||
| 198 | }; | ||
| 199 | }; | 194 | }; |
| 200 | 195 | ||
| 201 | usbhost1: usb@12120000 { | 196 | usbhost1: usb@12120000 { |
| 202 | compatible = "samsung,exynos4210-ohci"; | 197 | compatible = "samsung,exynos4210-ohci"; |
| 203 | reg = <0x12120000 0x100>; | 198 | reg = <0x12120000 0x100>; |
| 204 | interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; | 199 | interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; |
| 205 | 200 | phys = <&usb2_phy 1>; | |
| 206 | #address-cells = <1>; | 201 | phy-names = "host"; |
| 207 | #size-cells = <0>; | ||
| 208 | port@0 { | ||
| 209 | reg = <0>; | ||
| 210 | phys = <&usb2_phy 1>; | ||
| 211 | }; | ||
| 212 | }; | 202 | }; |
| 213 | 203 | ||
| 214 | usb2_phy: phy@12130000 { | 204 | usb2_phy: phy@12130000 { |
| @@ -79,12 +79,3 @@ void arch_sync_dma_for_device(struct device *dev, phys_addr_t handle, · 78 unmodified lines | |||
| 79 | break; | 79 | break; |
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | |||
| 83 | void arch_setup_pdev_archdata(struct platform_device *pdev) | ||
| 84 | { | ||
| 85 | if (pdev->dev.coherent_dma_mask == DMA_MASK_NONE && | ||
| 86 | pdev->dev.dma_mask == NULL) { | ||
| 87 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
| 88 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | ||
| 89 | } | ||
| 90 | } | ||
| @@ -778,12 +778,6 @@ void ppc_printk_progress(char *s, unsigned short hex) · 777 unmodified lines | |||
| 778 | pr_info("%s\n", s); | 778 | pr_info("%s\n", s); |
| 779 | } | 779 | } |
| 780 | 780 | ||
| 781 | void arch_setup_pdev_archdata(struct platform_device *pdev) | ||
| 782 | { | ||
| 783 | pdev->archdata.dma_mask = DMA_BIT_MASK(32); | ||
| 784 | pdev->dev.dma_mask = &pdev->archdata.dma_mask; | ||
| 785 | } | ||
| 786 | |||
| 787 | static __init void print_system_info(void) | 781 | static __init void print_system_info(void) |
| 788 | { | 782 | { |
| 789 | pr_info("-----------------------------------------------------\n"); | 783 | pr_info("-----------------------------------------------------\n"); |
| @@ -527,7 +527,6 @@ static int __init ap325rxa_devices_setup(void) · 526 unmodified lines | |||
| 527 | 527 | ||
| 528 | /* Initialize CEU platform device separately to map memory first */ | 528 | /* Initialize CEU platform device separately to map memory first */ |
| 529 | device_initialize(&ap325rxa_ceu_device.dev); | 529 | device_initialize(&ap325rxa_ceu_device.dev); |
| 530 | arch_setup_pdev_archdata(&ap325rxa_ceu_device); | ||
| 531 | dma_declare_coherent_memory(&ap325rxa_ceu_device.dev, | 530 | dma_declare_coherent_memory(&ap325rxa_ceu_device.dev, |
| 532 | ceu_dma_membase, ceu_dma_membase, | 531 | ceu_dma_membase, ceu_dma_membase, |
| 533 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); | 532 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); |
| @@ -1440,7 +1440,6 @@ static int __init arch_setup(void) · 1439 unmodified lines | |||
| 1440 | 1440 | ||
| 1441 | /* Initialize CEU platform devices separately to map memory first */ | 1441 | /* Initialize CEU platform devices separately to map memory first */ |
| 1442 | device_initialize(&ecovec_ceu_devices[0]->dev); | 1442 | device_initialize(&ecovec_ceu_devices[0]->dev); |
| 1443 | arch_setup_pdev_archdata(ecovec_ceu_devices[0]); | ||
| 1444 | dma_declare_coherent_memory(&ecovec_ceu_devices[0]->dev, | 1443 | dma_declare_coherent_memory(&ecovec_ceu_devices[0]->dev, |
| 1445 | ceu0_dma_membase, ceu0_dma_membase, | 1444 | ceu0_dma_membase, ceu0_dma_membase, |
| 1446 | ceu0_dma_membase + | 1445 | ceu0_dma_membase + |
| @@ -1448,7 +1447,6 @@ static int __init arch_setup(void) · 1 unmodified line | |||
| 1448 | platform_device_add(ecovec_ceu_devices[0]); | 1447 | platform_device_add(ecovec_ceu_devices[0]); |
| 1449 | 1448 | ||
| 1450 | device_initialize(&ecovec_ceu_devices[1]->dev); | 1449 | device_initialize(&ecovec_ceu_devices[1]->dev); |
| 1451 | arch_setup_pdev_archdata(ecovec_ceu_devices[1]); | ||
| 1452 | dma_declare_coherent_memory(&ecovec_ceu_devices[1]->dev, | 1450 | dma_declare_coherent_memory(&ecovec_ceu_devices[1]->dev, |
| 1453 | ceu1_dma_membase, ceu1_dma_membase, | 1451 | ceu1_dma_membase, ceu1_dma_membase, |
| 1454 | ceu1_dma_membase + | 1452 | ceu1_dma_membase + |
| @@ -601,7 +601,6 @@ static int __init kfr2r09_devices_setup(void) · 600 unmodified lines | |||
| 601 | 601 | ||
| 602 | /* Initialize CEU platform device separately to map memory first */ | 602 | /* Initialize CEU platform device separately to map memory first */ |
| 603 | device_initialize(&kfr2r09_ceu_device.dev); | 603 | device_initialize(&kfr2r09_ceu_device.dev); |
| 604 | arch_setup_pdev_archdata(&kfr2r09_ceu_device); | ||
| 605 | dma_declare_coherent_memory(&kfr2r09_ceu_device.dev, | 604 | dma_declare_coherent_memory(&kfr2r09_ceu_device.dev, |
| 606 | ceu_dma_membase, ceu_dma_membase, | 605 | ceu_dma_membase, ceu_dma_membase, |
| 607 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); | 606 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); |
| @@ -602,7 +602,6 @@ static int __init migor_devices_setup(void) · 601 unmodified lines | |||
| 602 | 602 | ||
| 603 | /* Initialize CEU platform device separately to map memory first */ | 603 | /* Initialize CEU platform device separately to map memory first */ |
| 604 | device_initialize(&migor_ceu_device.dev); | 604 | device_initialize(&migor_ceu_device.dev); |
| 605 | arch_setup_pdev_archdata(&migor_ceu_device); | ||
| 606 | dma_declare_coherent_memory(&migor_ceu_device.dev, | 605 | dma_declare_coherent_memory(&migor_ceu_device.dev, |
| 607 | ceu_dma_membase, ceu_dma_membase, | 606 | ceu_dma_membase, ceu_dma_membase, |
| 608 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); | 607 | ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); |
| @@ -937,7 +937,6 @@ static int __init devices_setup(void) · 936 unmodified lines | |||
| 937 | 937 | ||
| 938 | /* Initialize CEU platform devices separately to map memory first */ | 938 | /* Initialize CEU platform devices separately to map memory first */ |
| 939 | device_initialize(&ms7724se_ceu_devices[0]->dev); | 939 | device_initialize(&ms7724se_ceu_devices[0]->dev); |
| 940 | arch_setup_pdev_archdata(ms7724se_ceu_devices[0]); | ||
| 941 | dma_declare_coherent_memory(&ms7724se_ceu_devices[0]->dev, | 940 | dma_declare_coherent_memory(&ms7724se_ceu_devices[0]->dev, |
| 942 | ceu0_dma_membase, ceu0_dma_membase, | 941 | ceu0_dma_membase, ceu0_dma_membase, |
| 943 | ceu0_dma_membase + | 942 | ceu0_dma_membase + |
| @@ -945,7 +944,6 @@ static int __init devices_setup(void) · 1 unmodified line | |||
| 945 | platform_device_add(ms7724se_ceu_devices[0]); | 944 | platform_device_add(ms7724se_ceu_devices[0]); |
| 946 | 945 | ||
| 947 | device_initialize(&ms7724se_ceu_devices[1]->dev); | 946 | device_initialize(&ms7724se_ceu_devices[1]->dev); |
| 948 | arch_setup_pdev_archdata(ms7724se_ceu_devices[1]); | ||
| 949 | dma_declare_coherent_memory(&ms7724se_ceu_devices[1]->dev, | 947 | dma_declare_coherent_memory(&ms7724se_ceu_devices[1]->dev, |
| 950 | ceu1_dma_membase, ceu1_dma_membase, | 948 | ceu1_dma_membase, ceu1_dma_membase, |
| 951 | ceu1_dma_membase + | 949 | ceu1_dma_membase + |
| @@ -106,8 +106,6 @@ source "drivers/hid/Kconfig" · 105 unmodified lines | |||
| 106 | 106 | ||
| 107 | source "drivers/usb/Kconfig" | 107 | source "drivers/usb/Kconfig" |
| 108 | 108 | ||
| 109 | source "drivers/uwb/Kconfig" | ||
| 110 | |||
| 111 | source "drivers/mmc/Kconfig" | 109 | source "drivers/mmc/Kconfig" |
| 112 | 110 | ||
| 113 | source "drivers/memstick/Kconfig" | 111 | source "drivers/memstick/Kconfig" |
| @@ -100,7 +100,6 @@ obj-$(CONFIG_ZORRO) += zorro/ · 99 unmodified lines | |||
| 100 | obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ | 100 | obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ |
| 101 | obj-$(CONFIG_PARIDE) += block/paride/ | 101 | obj-$(CONFIG_PARIDE) += block/paride/ |
| 102 | obj-$(CONFIG_TC) += tc/ | 102 | obj-$(CONFIG_TC) += tc/ |
| 103 | obj-$(CONFIG_UWB) += uwb/ | ||
| 104 | obj-$(CONFIG_USB_PHY) += usb/ | 103 | obj-$(CONFIG_USB_PHY) += usb/ |
| 105 | obj-$(CONFIG_USB) += usb/ | 104 | obj-$(CONFIG_USB) += usb/ |
| 106 | obj-$(CONFIG_USB_SUPPORT) += usb/ | 105 | obj-$(CONFIG_USB_SUPPORT) += usb/ |
| @@ -12,9 +12,6 @@ · 11 unmodified lines | |||
| 12 | static DEFINE_MUTEX(devcon_lock); | 12 | static DEFINE_MUTEX(devcon_lock); |
| 13 | static LIST_HEAD(devcon_list); | 13 | static LIST_HEAD(devcon_list); |
| 14 | 14 | ||
| 15 | typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, | ||
| 16 | void *data); | ||
| 17 | |||
| 18 | static void * | 15 | static void * |
| 19 | fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, | 16 | fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, |
| 20 | void *data, devcon_match_fn_t match) | 17 | void *data, devcon_match_fn_t match) |
| @@ -60,6 +57,34 @@ fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, · 39 unmodified lines | |||
| 60 | return NULL; | 57 | return NULL; |
| 61 | } | 58 | } |
| 62 | 59 | ||
| 60 | /** | ||
| 61 | * fwnode_connection_find_match - Find connection from a device node | ||
| 62 | * @fwnode: Device node with the connection | ||
| 63 | * @con_id: Identifier for the connection | ||
| 64 | * @data: Data for the match function | ||
| 65 | * @match: Function to check and convert the connection description | ||
| 66 | * | ||
| 67 | * Find a connection with unique identifier @con_id between @fwnode and another | ||
| 68 | * device node. @match will be used to convert the connection description to | ||
| 69 | * data the caller is expecting to be returned. | ||
| 70 | */ | ||
| 71 | void *fwnode_connection_find_match(struct fwnode_handle *fwnode, | ||
| 72 | const char *con_id, void *data, | ||
| 73 | devcon_match_fn_t match) | ||
| 74 | { | ||
| 75 | void *ret; | ||
| 76 | |||
| 77 | if (!fwnode || !match) | ||
| 78 | return NULL; | ||
| 79 | |||
| 80 | ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); | ||
| 81 | if (ret) | ||
| 82 | return ret; | ||
| 83 | |||
| 84 | return fwnode_devcon_match(fwnode, con_id, data, match); | ||
| 85 | } | ||
| 86 | EXPORT_SYMBOL_GPL(fwnode_connection_find_match); | ||
| 87 | |||
| 63 | /** | 88 | /** |
| 64 | * device_connection_find_match - Find physical connection to a device | 89 | * device_connection_find_match - Find physical connection to a device |
| 65 | * @dev: Device with the connection | 90 | * @dev: Device with the connection |
| @@ -83,15 +108,9 @@ void *device_connection_find_match(struct device *dev, const char *con_id, · 17 unmodified lines | |||
| 83 | if (!match) | 108 | if (!match) |
| 84 | return NULL; | 109 | return NULL; |
| 85 | 110 | ||
| 86 | if (fwnode) { | 111 | ret = fwnode_connection_find_match(fwnode, con_id, data, match); |
| 87 | ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); | 112 | if (ret) |
| 88 | if (ret) | 113 | return ret; |
| 89 | return ret; | ||
| 90 | |||
| 91 | ret = fwnode_devcon_match(fwnode, con_id, data, match); | ||
| 92 | if (ret) | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | 114 | ||
| 96 | mutex_lock(&devcon_lock); | 115 | mutex_lock(&devcon_lock); |
| 97 | 116 | ||
| @@ -39,25 +39,6 @@ struct device platform_bus = { · 38 unmodified lines | |||
| 39 | }; | 39 | }; |
| 40 | EXPORT_SYMBOL_GPL(platform_bus); | 40 | EXPORT_SYMBOL_GPL(platform_bus); |
| 41 | 41 | ||
| 42 | /** | ||
| 43 | * arch_setup_pdev_archdata - Allow manipulation of archdata before its used | ||
| 44 | * @pdev: platform device | ||
| 45 | * | ||
| 46 | * This is called before platform_device_add() such that any pdev_archdata may | ||
| 47 | * be setup before the platform_notifier is called. So if a user needs to | ||
| 48 | * manipulate any relevant information in the pdev_archdata they can do: | ||
| 49 | * | ||
| 50 | * platform_device_alloc() | ||
| 51 | * ... manipulate ... | ||
| 52 | * platform_device_add() | ||
| 53 | * | ||
| 54 | * And if they don't care they can just call platform_device_register() and | ||
| 55 | * everything will just work out. | ||
| 56 | */ | ||
| 57 | void __weak arch_setup_pdev_archdata(struct platform_device *pdev) | ||
| 58 | { | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | 42 | /** |
| 62 | * platform_get_resource - get a resource for a device | 43 | * platform_get_resource - get a resource for a device |
| 63 | * @dev: platform device | 44 | * @dev: platform device |
| @@ -313,6 +294,20 @@ struct platform_object { · 249 unmodified lines | |||
| 313 | char name[]; | 294 | char name[]; |
| 314 | }; | 295 | }; |
| 315 | 296 | ||
| 297 | /* | ||
| 298 | * Set up default DMA mask for platform devices if the they weren't | ||
| 299 | * previously set by the architecture / DT. | ||
| 300 | */ | ||
| 301 | static void setup_pdev_dma_masks(struct platform_device *pdev) | ||
| 302 | { | ||
| 303 | if (!pdev->dev.coherent_dma_mask) | ||
| 304 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
| 305 | if (!pdev->dma_mask) | ||
| 306 | pdev->dma_mask = DMA_BIT_MASK(32); | ||
| 307 | if (!pdev->dev.dma_mask) | ||
| 308 | pdev->dev.dma_mask = &pdev->dma_mask; | ||
| 309 | }; | ||
| 310 | |||
| 316 | /** | 311 | /** |
| 317 | * platform_device_put - destroy a platform device | 312 | * platform_device_put - destroy a platform device |
| 318 | * @pdev: platform device to free | 313 | * @pdev: platform device to free |
| @@ -359,7 +354,7 @@ struct platform_device *platform_device_alloc(const char *name, int id) · 40 unmodified lines | |||
| 359 | pa->pdev.id = id; | 354 | pa->pdev.id = id; |
| 360 | device_initialize(&pa->pdev.dev); | 355 | device_initialize(&pa->pdev.dev); |
| 361 | pa->pdev.dev.release = platform_device_release; | 356 | pa->pdev.dev.release = platform_device_release; |
| 362 | arch_setup_pdev_archdata(&pa->pdev); | 357 | setup_pdev_dma_masks(&pa->pdev); |
| 363 | } | 358 | } |
| 364 | 359 | ||
| 365 | return pa ? &pa->pdev : NULL; | 360 | return pa ? &pa->pdev : NULL; |
| @@ -561,7 +556,7 @@ EXPORT_SYMBOL_GPL(platform_device_del); · 195 unmodified lines | |||
| 561 | int platform_device_register(struct platform_device *pdev) | 556 | int platform_device_register(struct platform_device *pdev) |
| 562 | { | 557 | { |
| 563 | device_initialize(&pdev->dev); | 558 | device_initialize(&pdev->dev); |
| 564 | arch_setup_pdev_archdata(pdev); | 559 | setup_pdev_dma_masks(pdev); |
| 565 | return platform_device_add(pdev); | 560 | return platform_device_add(pdev); |
| 566 | } | 561 | } |
| 567 | EXPORT_SYMBOL_GPL(platform_device_register); | 562 | EXPORT_SYMBOL_GPL(platform_device_register); |
| @@ -1105,7 +1105,6 @@ config MFD_SI476X_CORE · 1104 unmodified lines | |||
| 1105 | config MFD_SM501 | 1105 | config MFD_SM501 |
| 1106 | tristate "Silicon Motion SM501" | 1106 | tristate "Silicon Motion SM501" |
| 1107 | depends on HAS_DMA | 1107 | depends on HAS_DMA |
| 1108 | select DMA_DECLARE_COHERENT | ||
| 1109 | ---help--- | 1108 | ---help--- |
| 1110 | This is the core driver for the Silicon Motion SM501 multimedia | 1109 | This is the core driver for the Silicon Motion SM501 multimedia |
| 1111 | companion chip. This device is a multifunction device which may | 1110 | companion chip. This device is a multifunction device which may |
| @@ -1714,7 +1713,6 @@ config MFD_TC6393XB · 602 unmodified lines | |||
| 1714 | select GPIOLIB | 1713 | select GPIOLIB |
| 1715 | select MFD_CORE | 1714 | select MFD_CORE |
| 1716 | select MFD_TMIO | 1715 | select MFD_TMIO |
| 1717 | select DMA_DECLARE_COHERENT | ||
| 1718 | help | 1716 | help |
| 1719 | Support for Toshiba Mobile IO Controller TC6393XB | 1717 | Support for Toshiba Mobile IO Controller TC6393XB |
| 1720 | 1718 | ||
| @@ -120,4 +120,7 @@ source "drivers/staging/kpc2000/Kconfig" · 119 unmodified lines | |||
| 120 | 120 | ||
| 121 | source "drivers/staging/isdn/Kconfig" | 121 | source "drivers/staging/isdn/Kconfig" |
| 122 | 122 | ||
| 123 | source "drivers/staging/wusbcore/Kconfig" | ||
| 124 | source "drivers/staging/uwb/Kconfig" | ||
| 125 | |||
| 123 | endif # STAGING | 126 | endif # STAGING |
| @@ -50,3 +50,5 @@ obj-$(CONFIG_EROFS_FS) += erofs/ · 49 unmodified lines | |||
| 50 | obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ | 50 | obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ |
| 51 | obj-$(CONFIG_KPC2000) += kpc2000/ | 51 | obj-$(CONFIG_KPC2000) += kpc2000/ |
| 52 | obj-$(CONFIG_ISDN_CAPI) += isdn/ | 52 | obj-$(CONFIG_ISDN_CAPI) += isdn/ |
| 53 | obj-$(CONFIG_UWB) += uwb/ | ||
| 54 | obj-$(CONFIG_USB_WUSB) += wusbcore/ | ||
| @@ -3512,7 +3512,7 @@ static const struct hc_driver octeon_hc_driver = { · 3511 unmodified lines | |||
| 3512 | .product_desc = "Octeon Host Controller", | 3512 | .product_desc = "Octeon Host Controller", |
| 3513 | .hcd_priv_size = sizeof(struct octeon_hcd), | 3513 | .hcd_priv_size = sizeof(struct octeon_hcd), |
| 3514 | .irq = octeon_usb_irq, | 3514 | .irq = octeon_usb_irq, |
| 3515 | .flags = HCD_MEMORY | HCD_USB2, | 3515 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, |
| 3516 | .start = octeon_usb_start, | 3516 | .start = octeon_usb_start, |
| 3517 | .stop = octeon_usb_stop, | 3517 | .stop = octeon_usb_stop, |
| 3518 | .urb_enqueue = octeon_usb_urb_enqueue, | 3518 | .urb_enqueue = octeon_usb_urb_enqueue, |
File renamed without changes.
File renamed without changes.
| @@ -0,0 +1,8 @@ | |||
| 1 | TODO: Remove in late 2019 unless there are users | ||
| 2 | |||
| 3 | There seems to not be any real wireless USB devices anywhere in the wild | ||
| 4 | anymore. It turned out to be a failed technology :( | ||
| 5 | |||
| 6 | This will be removed from the tree if no one objects. | ||
| 7 | |||
| 8 | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
File renamed without changes.
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
| 9 | #include <linux/uwb.h> | 9 | #include "uwb.h" |
| 10 | 10 | ||
| 11 | #include "uwb-internal.h" | 11 | #include "uwb-internal.h" |
| 12 | 12 | ||
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -8,8 +8,8 @@ · 7 unmodified lines | |||
| 8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
| 9 | #include <linux/random.h> | 9 | #include <linux/random.h> |
| 10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 11 | #include <linux/uwb.h> | ||
| 12 | 11 | ||
| 12 | #include "uwb.h" | ||
| 13 | #include "uwb-internal.h" | 13 | #include "uwb-internal.h" |
| 14 | 14 | ||
| 15 | 15 | ||
File renamed without changes.
File renamed without changes.
| @@ -38,9 +38,9 @@ · 37 unmodified lines | |||
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
| 40 | #include <linux/usb.h> | 40 | #include <linux/usb.h> |
| 41 | #include <linux/usb/wusb.h> | 41 | #include "../wusbcore/include/wusb.h" |
| 42 | #include <linux/usb/wusb-wa.h> | 42 | #include "../wusbcore/include/wusb-wa.h" |
| 43 | #include <linux/uwb.h> | 43 | #include "uwb.h" |
| 44 | 44 | ||
| 45 | #include "uwb-internal.h" | 45 | #include "uwb-internal.h" |
| 46 | 46 | ||
File renamed without changes.
File renamed without changes.
| @@ -17,9 +17,9 @@ · 16 unmodified lines | |||
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
| 19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
| 20 | #include <linux/uwb.h> | ||
| 21 | #include <linux/random.h> | 20 | #include <linux/random.h> |
| 22 | #include <linux/export.h> | 21 | #include <linux/export.h> |
| 22 | #include "../../uwb.h" | ||
| 23 | 23 | ||
| 24 | /* | 24 | /* |
| 25 | * i1480_rceb_check - Check RCEB for expected field values | 25 | * i1480_rceb_check - Check RCEB for expected field values |
| @@ -50,9 +50,9 @@ · 49 unmodified lines | |||
| 50 | #ifndef __i1480_DFU_H__ | 50 | #ifndef __i1480_DFU_H__ |
| 51 | #define __i1480_DFU_H__ | 51 | #define __i1480_DFU_H__ |
| 52 | 52 | ||
| 53 | #include <linux/uwb/spec.h> | ||
| 54 | #include <linux/types.h> | 53 | #include <linux/types.h> |
| 55 | #include <linux/completion.h> | 54 | #include <linux/completion.h> |
| 55 | #include "../../include/spec.h" | ||
| 56 | 56 | ||
| 57 | #define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) | 57 | #define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) |
| 58 | 58 | ||
| @@ -15,7 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/firmware.h> | 16 | #include <linux/firmware.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/uwb.h> | 18 | #include "../../uwb.h" |
| 19 | #include "i1480-dfu.h" | 19 | #include "i1480-dfu.h" |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/firmware.h> | 17 | #include <linux/firmware.h> |
| 18 | #include <linux/usb/wusb.h> | 18 | #include "../../../wusbcore/include/wusb.h" |
| 19 | #include "i1480-dfu.h" | 19 | #include "i1480-dfu.h" |
| 20 | 20 | ||
| 21 | 21 | ||
| @@ -25,9 +25,9 @@ · 24 unmodified lines | |||
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include <linux/uwb.h> | 28 | #include "../../uwb.h" |
| 29 | #include <linux/usb/wusb.h> | 29 | #include "../../../wusbcore/include/wusb.h" |
| 30 | #include <linux/usb/wusb-wa.h> | 30 | #include "../../../wusbcore/include/wusb-wa.h" |
| 31 | #include "i1480-dfu.h" | 31 | #include "i1480-dfu.h" |
| 32 | 32 | ||
| 33 | struct i1480_usb { | 33 | struct i1480_usb { |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/usb.h> | 14 | #include <linux/usb.h> |
| 15 | #include <linux/uwb.h> | 15 | #include "../uwb.h" |
| 16 | #include "dfu/i1480-dfu.h" | 16 | #include "dfu/i1480-dfu.h" |
| 17 | 17 | ||
| 18 | 18 | ||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -6,9 +6,9 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/debugfs.h> | 8 | #include <linux/debugfs.h> |
| 9 | #include <linux/uwb.h> | ||
| 10 | #include <linux/export.h> | 9 | #include <linux/export.h> |
| 11 | 10 | ||
| 11 | #include "uwb.h" | ||
| 12 | #include "uwb-internal.h" | 12 | #include "uwb-internal.h" |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| @@ -5,9 +5,9 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | 5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. |
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/uwb.h> | ||
| 9 | #include <linux/export.h> | 8 | #include <linux/export.h> |
| 10 | 9 | ||
| 10 | #include "uwb.h" | ||
| 11 | #include "uwb-internal.h" | 11 | #include "uwb-internal.h" |
| 12 | 12 | ||
| 13 | 13 | ||
File renamed without changes.
| @@ -5,11 +5,11 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | 5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. |
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/uwb.h> | ||
| 9 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
| 10 | #include <linux/random.h> | 9 | #include <linux/random.h> |
| 11 | #include <linux/export.h> | 10 | #include <linux/export.h> |
| 12 | 11 | ||
| 12 | #include "uwb.h" | ||
| 13 | #include "uwb-internal.h" | 13 | #include "uwb-internal.h" |
| 14 | 14 | ||
| 15 | static void uwb_rsv_timer(struct timer_list *t); | 15 | static void uwb_rsv_timer(struct timer_list *t); |
File renamed without changes.
| @@ -8,8 +8,8 @@ · 7 unmodified lines | |||
| 8 | #include <linux/sysfs.h> | 8 | #include <linux/sysfs.h> |
| 9 | #include <linux/workqueue.h> | 9 | #include <linux/workqueue.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/uwb/umc.h> | ||
| 12 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
| 12 | #include "include/umc.h" | ||
| 13 | 13 | ||
| 14 | static int umc_bus_pre_reset_helper(struct device *dev, void *data) | 14 | static int umc_bus_pre_reset_helper(struct device *dev, void *data) |
| 15 | { | 15 | { |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/export.h> | 8 | #include <linux/export.h> |
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/uwb/umc.h> | 10 | #include "include/umc.h" |
| 11 | 11 | ||
| 12 | static void umc_device_release(struct device *dev) | 12 | static void umc_device_release(struct device *dev) |
| 13 | { | 13 | { |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/export.h> | 8 | #include <linux/export.h> |
| 9 | #include <linux/uwb/umc.h> | 9 | #include "include/umc.h" |
| 10 | 10 | ||
| 11 | int __umc_driver_register(struct umc_driver *umc_drv, struct module *module, | 11 | int __umc_driver_register(struct umc_driver *umc_drv, struct module *module, |
| 12 | const char *mod_name) | 12 | const char *mod_name) |
| @@ -19,8 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
| 21 | 21 | ||
| 22 | #include <linux/uwb/debug-cmd.h> | 22 | #include "include/debug-cmd.h" |
| 23 | |||
| 24 | #include "uwb-internal.h" | 23 | #include "uwb-internal.h" |
| 25 | 24 | ||
| 26 | /* | 25 | /* |
| @@ -17,8 +17,8 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
| 20 | #include <linux/uwb.h> | ||
| 21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
| 21 | #include "uwb.h" | ||
| 22 | 22 | ||
| 23 | struct uwb_beca_e; | 23 | struct uwb_beca_e; |
| 24 | 24 | ||
| @@ -18,8 +18,8 @@ · 17 unmodified lines | |||
| 18 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
| 19 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
| 20 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
| 21 | #include <linux/uwb/spec.h> | ||
| 22 | #include <asm/page.h> | 21 | #include <asm/page.h> |
| 22 | #include "include/spec.h" | ||
| 23 | 23 | ||
| 24 | struct uwb_dev; | 24 | struct uwb_dev; |
| 25 | struct uwb_beca_e; | 25 | struct uwb_beca_e; |
File renamed without changes.
| @@ -33,9 +33,9 @@ · 32 unmodified lines | |||
| 33 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
| 36 | #include <linux/uwb.h> | 36 | #include "uwb.h" |
| 37 | #include <linux/uwb/whci.h> | 37 | #include "include/whci.h" |
| 38 | #include <linux/uwb/umc.h> | 38 | #include "include/umc.h" |
| 39 | 39 | ||
| 40 | #include "uwb-internal.h" | 40 | #include "uwb-internal.h" |
| 41 | 41 | ||
| @@ -10,8 +10,8 @@ · 9 unmodified lines | |||
| 10 | #include <linux/pci.h> | 10 | #include <linux/pci.h> |
| 11 | #include <linux/dma-mapping.h> | 11 | #include <linux/dma-mapping.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/uwb/whci.h> | 13 | #include "include/whci.h" |
| 14 | #include <linux/uwb/umc.h> | 14 | #include "include/umc.h" |
| 15 | 15 | ||
| 16 | struct whci_card { | 16 | struct whci_card { |
| 17 | struct pci_dev *pci; | 17 | struct pci_dev *pci; |
File renamed without changes.
File renamed without changes.
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | config USB_WUSB | 5 | config USB_WUSB |
| 6 | tristate "Enable Wireless USB extensions" | 6 | tristate "Enable Wireless USB extensions" |
| 7 | depends on UWB | 7 | depends on UWB && USB |
| 8 | select CRYPTO | 8 | select CRYPTO |
| 9 | select CRYPTO_AES | 9 | select CRYPTO_AES |
| 10 | select CRYPTO_CCM | 10 | select CRYPTO_CCM |
| @@ -36,3 +36,4 @@ config USB_WUSB_CBAF_DEBUG · 25 unmodified lines | |||
| 36 | to the system log. Select this if you are having a problem with | 36 | to the system log. Select this if you are having a problem with |
| 37 | CBA support and want to see more of what is going on. | 37 | CBA support and want to see more of what is going on. |
| 38 | 38 | ||
| 39 | source "drivers/staging/wusbcore/host/Kconfig" | ||
| @@ -24,3 +24,5 @@ wusb-wa-y := \ · 23 unmodified lines | |||
| 24 | wa-nep.o \ | 24 | wa-nep.o \ |
| 25 | wa-rpipe.o \ | 25 | wa-rpipe.o \ |
| 26 | wa-xfer.o | 26 | wa-xfer.o |
| 27 | |||
| 28 | obj-y += host/ | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | TODO: Remove in late 2019 unless there are users | ||
| 2 | |||
| 3 | There seems to not be any real wireless USB devices anywhere in the wild | ||
| 4 | anymore. It turned out to be a failed technology :( | ||
| 5 | |||
| 6 | This will be removed from the tree if no one objects. | ||
| 7 | |||
| 8 | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
| @@ -80,9 +80,9 @@ · 79 unmodified lines | |||
| 80 | #include <linux/random.h> | 80 | #include <linux/random.h> |
| 81 | #include <linux/slab.h> | 81 | #include <linux/slab.h> |
| 82 | #include <linux/mutex.h> | 82 | #include <linux/mutex.h> |
| 83 | #include <linux/uwb.h> | 83 | #include "../uwb/uwb.h" |
| 84 | #include <linux/usb/wusb.h> | 84 | #include "include/wusb.h" |
| 85 | #include <linux/usb/association.h> | 85 | #include "include/association.h" |
| 86 | 86 | ||
| 87 | #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */ | 87 | #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */ |
| 88 | 88 | ||
| @@ -38,10 +38,10 @@ · 37 unmodified lines | |||
| 38 | #include <linux/crypto.h> | 38 | #include <linux/crypto.h> |
| 39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <linux/err.h> | 40 | #include <linux/err.h> |
| 41 | #include <linux/uwb.h> | ||
| 42 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 43 | #include <linux/usb/wusb.h> | ||
| 44 | #include <linux/scatterlist.h> | 42 | #include <linux/scatterlist.h> |
| 43 | #include "../uwb/uwb.h" | ||
| 44 | #include "include/wusb.h" | ||
| 45 | 45 | ||
| 46 | static int debug_crypto_verify; | 46 | static int debug_crypto_verify; |
| 47 | 47 | ||
File renamed without changes.
| @@ -49,7 +49,7 @@ · 48 unmodified lines | |||
| 49 | * for processing a DN_Alive pong from a device. | 49 | * for processing a DN_Alive pong from a device. |
| 50 | * | 50 | * |
| 51 | * wusb_handle_dn_disconnect()Called by notif.c:wusb_handle_dn() to | 51 | * wusb_handle_dn_disconnect()Called by notif.c:wusb_handle_dn() to |
| 52 | * process a disconenct request from a | 52 | * process a disconnect request from a |
| 53 | * device. | 53 | * device. |
| 54 | * | 54 | * |
| 55 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when | 55 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when |
| @@ -0,0 +1,28 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | config USB_WHCI_HCD | ||
| 4 | tristate "Wireless USB Host Controller Interface (WHCI) driver" | ||
| 5 | depends on USB_PCI && USB && UWB | ||
| 6 | select USB_WUSB | ||
| 7 | select UWB_WHCI | ||
| 8 | help | ||
| 9 | A driver for PCI-based Wireless USB Host Controllers that are | ||
| 10 | compliant with the WHCI specification. | ||
| 11 | |||
| 12 | To compile this driver a module, choose M here: the module | ||
| 13 | will be called "whci-hcd". | ||
| 14 | |||
| 15 | config USB_HWA_HCD | ||
| 16 | tristate "Host Wire Adapter (HWA) driver" | ||
| 17 | depends on USB && UWB | ||
| 18 | select USB_WUSB | ||
| 19 | select UWB_HWA | ||
| 20 | help | ||
| 21 | This driver enables you to connect Wireless USB devices to | ||
| 22 | your system using a Host Wire Adaptor USB dongle. This is an | ||
| 23 | UWB Radio Controller and WUSB Host Controller connected to | ||
| 24 | your machine via USB (specified in WUSB1.0). | ||
| 25 | |||
| 26 | To compile this driver a module, choose M here: the module | ||
| 27 | will be called "hwa-hc". | ||
| 28 | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ | ||
| 3 | obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o | ||
| @@ -45,8 +45,8 @@ · 44 unmodified lines | |||
| 45 | #include <linux/workqueue.h> | 45 | #include <linux/workqueue.h> |
| 46 | #include <linux/wait.h> | 46 | #include <linux/wait.h> |
| 47 | #include <linux/completion.h> | 47 | #include <linux/completion.h> |
| 48 | #include "../wusbcore/wa-hc.h" | 48 | #include "../wa-hc.h" |
| 49 | #include "../wusbcore/wusbhc.h" | 49 | #include "../wusbhc.h" |
| 50 | 50 | ||
| 51 | struct hwahc { | 51 | struct hwahc { |
| 52 | struct wusbhc wusbhc; /* has to be 1st */ | 52 | struct wusbhc wusbhc; /* has to be 1st */ |
File renamed without changes.
| @@ -7,10 +7,10 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/gfp.h> | 8 | #include <linux/gfp.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/uwb/umc.h> | ||
| 11 | #include <linux/usb.h> | 10 | #include <linux/usb.h> |
| 12 | 11 | ||
| 13 | #include "../../wusbcore/wusbhc.h" | 12 | #include "../../../uwb/include/umc.h" |
| 13 | #include "../../wusbhc.h" | ||
| 14 | 14 | ||
| 15 | #include "whcd.h" | 15 | #include "whcd.h" |
| 16 | 16 | ||
| @@ -10,7 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/seq_file.h> | 10 | #include <linux/seq_file.h> |
| 11 | #include <linux/export.h> | 11 | #include <linux/export.h> |
| 12 | 12 | ||
| 13 | #include "../../wusbcore/wusbhc.h" | 13 | #include "../../wusbhc.h" |
| 14 | 14 | ||
| 15 | #include "whcd.h" | 15 | #include "whcd.h" |
| 16 | 16 | ||
| @@ -7,9 +7,9 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/uwb/umc.h> | ||
| 11 | 10 | ||
| 12 | #include "../../wusbcore/wusbhc.h" | 11 | #include "../../../uwb/include/umc.h" |
| 12 | #include "../../wusbhc.h" | ||
| 13 | 13 | ||
| 14 | #include "whcd.h" | 14 | #include "whcd.h" |
| 15 | 15 | ||
| @@ -6,9 +6,9 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/dma-mapping.h> | 8 | #include <linux/dma-mapping.h> |
| 9 | #include <linux/uwb/umc.h> | ||
| 10 | 9 | ||
| 11 | #include "../../wusbcore/wusbhc.h" | 10 | #include "../../../uwb/include/umc.h" |
| 11 | #include "../../wusbhc.h" | ||
| 12 | 12 | ||
| 13 | #include "whcd.h" | 13 | #include "whcd.h" |
| 14 | 14 | ||
| @@ -7,9 +7,9 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/gfp.h> | 8 | #include <linux/gfp.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/uwb/umc.h> | ||
| 11 | 10 | ||
| 12 | #include "../../wusbcore/wusbhc.h" | 11 | #include "../../../uwb/include/umc.h" |
| 12 | #include "../../wusbhc.h" | ||
| 13 | 13 | ||
| 14 | #include "whcd.h" | 14 | #include "whcd.h" |
| 15 | 15 | ||
| @@ -5,9 +5,9 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. | 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. |
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/uwb/umc.h> | ||
| 9 | 8 | ||
| 10 | #include "../../wusbcore/wusbhc.h" | 9 | #include "../../../uwb/include/umc.h" |
| 10 | #include "../../wusbhc.h" | ||
| 11 | 11 | ||
| 12 | #include "whcd.h" | 12 | #include "whcd.h" |
| 13 | 13 | ||
| @@ -7,10 +7,10 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/gfp.h> | 8 | #include <linux/gfp.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/uwb/umc.h> | ||
| 11 | #include <linux/usb.h> | 10 | #include <linux/usb.h> |
| 12 | 11 | ||
| 13 | #include "../../wusbcore/wusbhc.h" | 12 | #include "../../../uwb/include/umc.h" |
| 13 | #include "../../wusbhc.h" | ||
| 14 | 14 | ||
| 15 | #include "whcd.h" | 15 | #include "whcd.h" |
| 16 | 16 | ||
| @@ -7,10 +7,10 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/dma-mapping.h> | 8 | #include <linux/dma-mapping.h> |
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/uwb/umc.h> | ||
| 11 | #include <linux/usb.h> | 10 | #include <linux/usb.h> |
| 12 | 11 | ||
| 13 | #include "../../wusbcore/wusbhc.h" | 12 | #include "../../../uwb/include/umc.h" |
| 13 | #include "../../wusbhc.h" | ||
| 14 | 14 | ||
| 15 | #include "whcd.h" | 15 | #include "whcd.h" |
| 16 | 16 | ||
| @@ -7,10 +7,10 @@ · 6 unmodified lines | |||
| 7 | #ifndef __WHCD_H | 7 | #ifndef __WHCD_H |
| 8 | #define __WHCD_H | 8 | #define __WHCD_H |
| 9 | 9 | ||
| 10 | #include <linux/uwb/whci.h> | ||
| 11 | #include <linux/uwb/umc.h> | ||
| 12 | #include <linux/workqueue.h> | 10 | #include <linux/workqueue.h> |
| 13 | 11 | ||
| 12 | #include "../../../uwb/include/whci.h" | ||
| 13 | #include "../../../uwb/include/umc.h" | ||
| 14 | #include "whci-hc.h" | 14 | #include "whci-hc.h" |
| 15 | 15 | ||
| 16 | /* Generic command timeout. */ | 16 | /* Generic command timeout. */ |
File renamed without changes.
| @@ -5,9 +5,9 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. | 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. |
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/uwb/umc.h> | ||
| 9 | 8 | ||
| 10 | #include "../../wusbcore/wusbhc.h" | 9 | #include "../../../uwb/include/umc.h" |
| 10 | #include "../../wusbhc.h" | ||
| 11 | 11 | ||
| 12 | #include "whcd.h" | 12 | #include "whcd.h" |
| 13 | 13 | ||
File renamed without changes.
File renamed without changes.
| @@ -33,9 +33,9 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
| 35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 36 | #include <linux/uwb/spec.h> | ||
| 37 | #include <linux/usb/ch9.h> | 36 | #include <linux/usb/ch9.h> |
| 38 | #include <linux/param.h> | 37 | #include <linux/param.h> |
| 38 | #include "../../uwb/include/spec.h" | ||
| 39 | 39 | ||
| 40 | /** | 40 | /** |
| 41 | * WUSB Information Element header | 41 | * WUSB Information Element header |
| @@ -22,9 +22,9 @@ · 21 unmodified lines | |||
| 22 | * FIXME: | 22 | * FIXME: |
| 23 | * - add timers that autoremove intervalled IEs? | 23 | * - add timers that autoremove intervalled IEs? |
| 24 | */ | 24 | */ |
| 25 | #include <linux/usb/wusb.h> | ||
| 26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 27 | #include <linux/export.h> | 26 | #include <linux/export.h> |
| 27 | #include "include/wusb.h" | ||
| 28 | #include "wusbhc.h" | 28 | #include "wusbhc.h" |
| 29 | 29 | ||
| 30 | /* Initialize the MMCIEs handling mechanism */ | 30 | /* Initialize the MMCIEs handling mechanism */ |
File renamed without changes.
| @@ -5,8 +5,8 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. | 5 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. |
| 6 | */ | 6 | */ |
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/uwb.h> | ||
| 9 | 8 | ||
| 9 | #include "../uwb/uwb.h" | ||
| 10 | #include "wusbhc.h" | 10 | #include "wusbhc.h" |
| 11 | 11 | ||
| 12 | /* | 12 | /* |
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -70,9 +70,9 @@ · 69 unmodified lines | |||
| 70 | #include <linux/usb.h> | 70 | #include <linux/usb.h> |
| 71 | #include <linux/mutex.h> | 71 | #include <linux/mutex.h> |
| 72 | #include <linux/spinlock.h> | 72 | #include <linux/spinlock.h> |
| 73 | #include <linux/uwb.h> | 73 | #include "../uwb/uwb.h" |
| 74 | #include <linux/usb/wusb.h> | 74 | #include "include/wusb.h" |
| 75 | #include <linux/usb/wusb-wa.h> | 75 | #include "include/wusb-wa.h" |
| 76 | 76 | ||
| 77 | struct wusbhc; | 77 | struct wusbhc; |
| 78 | struct wahc; | 78 | struct wahc; |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -45,8 +45,8 @@ · 44 unmodified lines | |||
| 45 | #include <linux/kref.h> | 45 | #include <linux/kref.h> |
| 46 | #include <linux/workqueue.h> | 46 | #include <linux/workqueue.h> |
| 47 | #include <linux/usb/hcd.h> | 47 | #include <linux/usb/hcd.h> |
| 48 | #include <linux/uwb.h> | 48 | #include "../uwb/uwb.h" |
| 49 | #include <linux/usb/wusb.h> | 49 | #include "include/wusb.h" |
| 50 | 50 | ||
| 51 | /* | 51 | /* |
| 52 | * Time from a WUSB channel stop request to the last transmitted MMC. | 52 | * Time from a WUSB channel stop request to the last transmitted MMC. |
| @@ -36,8 +36,7 @@ menuconfig USB_SUPPORT · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | if USB_SUPPORT | 37 | if USB_SUPPORT |
| 38 | 38 | ||
| 39 | config USB_COMMON | 39 | source "drivers/usb/common/Kconfig" |
| 40 | tristate | ||
| 41 | 40 | ||
| 42 | config USB_ARCH_HAS_HCD | 41 | config USB_ARCH_HAS_HCD |
| 43 | def_bool y | 42 | def_bool y |
| @@ -98,8 +97,6 @@ source "drivers/usb/core/Kconfig" · 54 unmodified lines | |||
| 98 | 97 | ||
| 99 | source "drivers/usb/mon/Kconfig" | 98 | source "drivers/usb/mon/Kconfig" |
| 100 | 99 | ||
| 101 | source "drivers/usb/wusbcore/Kconfig" | ||
| 102 | |||
| 103 | source "drivers/usb/host/Kconfig" | 100 | source "drivers/usb/host/Kconfig" |
| 104 | 101 | ||
| 105 | source "drivers/usb/renesas_usbhs/Kconfig" | 102 | source "drivers/usb/renesas_usbhs/Kconfig" |
| @@ -114,6 +111,8 @@ source "drivers/usb/usbip/Kconfig" · 8 unmodified lines | |||
| 114 | 111 | ||
| 115 | endif | 112 | endif |
| 116 | 113 | ||
| 114 | source "drivers/usb/cdns3/Kconfig" | ||
| 115 | |||
| 117 | source "drivers/usb/mtu3/Kconfig" | 116 | source "drivers/usb/mtu3/Kconfig" |
| 118 | 117 | ||
| 119 | source "drivers/usb/musb/Kconfig" | 118 | source "drivers/usb/musb/Kconfig" |
| @@ -175,36 +174,4 @@ source "drivers/usb/typec/Kconfig" · 55 unmodified lines | |||
| 175 | 174 | ||
| 176 | source "drivers/usb/roles/Kconfig" | 175 | source "drivers/usb/roles/Kconfig" |
| 177 | 176 | ||
| 178 | config USB_LED_TRIG | ||
| 179 | bool "USB LED Triggers" | ||
| 180 | depends on LEDS_CLASS && LEDS_TRIGGERS | ||
| 181 | select USB_COMMON | ||
| 182 | help | ||
| 183 | This option adds LED triggers for USB host and/or gadget activity. | ||
| 184 | |||
| 185 | Say Y here if you are working on a system with led-class supported | ||
| 186 | LEDs and you want to use them as activity indicators for USB host or | ||
| 187 | gadget. | ||
| 188 | |||
| 189 | config USB_ULPI_BUS | ||
| 190 | tristate "USB ULPI PHY interface support" | ||
| 191 | select USB_COMMON | ||
| 192 | help | ||
| 193 | UTMI+ Low Pin Interface (ULPI) is specification for a commonly used | ||
| 194 | USB 2.0 PHY interface. The ULPI specification defines a standard set | ||
| 195 | of registers that can be used to detect the vendor and product which | ||
| 196 | allows ULPI to be handled as a bus. This module is the driver for that | ||
| 197 | bus. | ||
| 198 | |||
| 199 | The ULPI interfaces (the buses) are registered by the drivers for USB | ||
| 200 | controllers which support ULPI register access and have ULPI PHY | ||
| 201 | attached to them. The ULPI PHY drivers themselves are normal PHY | ||
| 202 | drivers. | ||
| 203 | |||
| 204 | ULPI PHYs provide often functions such as ADP sensing/probing (OTG | ||
| 205 | protocol) and USB charger detection. | ||
| 206 | |||
| 207 | To compile this driver as a module, choose M here: the module will | ||
| 208 | be called ulpi. | ||
| 209 | |||
| 210 | endif # USB_SUPPORT | 177 | endif # USB_SUPPORT |
| @@ -13,6 +13,8 @@ obj-$(CONFIG_USB_DWC3) += dwc3/ · 12 unmodified lines | |||
| 13 | obj-$(CONFIG_USB_DWC2) += dwc2/ | 13 | obj-$(CONFIG_USB_DWC2) += dwc2/ |
| 14 | obj-$(CONFIG_USB_ISP1760) += isp1760/ | 14 | obj-$(CONFIG_USB_ISP1760) += isp1760/ |
| 15 | 15 | ||
| 16 | obj-$(CONFIG_USB_CDNS3) += cdns3/ | ||
| 17 | |||
| 16 | obj-$(CONFIG_USB_MON) += mon/ | 18 | obj-$(CONFIG_USB_MON) += mon/ |
| 17 | obj-$(CONFIG_USB_MTU3) += mtu3/ | 19 | obj-$(CONFIG_USB_MTU3) += mtu3/ |
| 18 | 20 | ||
| @@ -35,8 +37,6 @@ obj-$(CONFIG_USB_MAX3421_HCD) += host/ · 16 unmodified lines | |||
| 35 | 37 | ||
| 36 | obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ | 38 | obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ |
| 37 | 39 | ||
| 38 | obj-$(CONFIG_USB_WUSB) += wusbcore/ | ||
| 39 | |||
| 40 | obj-$(CONFIG_USB_ACM) += class/ | 40 | obj-$(CONFIG_USB_ACM) += class/ |
| 41 | obj-$(CONFIG_USB_PRINTER) += class/ | 41 | obj-$(CONFIG_USB_PRINTER) += class/ |
| 42 | obj-$(CONFIG_USB_WDM) += class/ | 42 | obj-$(CONFIG_USB_WDM) += class/ |
| @@ -539,6 +539,37 @@ CXACRU_SET_##_action( adsl_config); · 538 unmodified lines | |||
| 539 | 539 | ||
| 540 | CXACRU_ALL_FILES(INIT); | 540 | CXACRU_ALL_FILES(INIT); |
| 541 | 541 | ||
| 542 | static struct attribute *cxacru_attrs[] = { | ||
| 543 | &dev_attr_adsl_config.attr, | ||
| 544 | &dev_attr_adsl_state.attr, | ||
| 545 | &dev_attr_adsl_controller_version.attr, | ||
| 546 | &dev_attr_adsl_headend_environment.attr, | ||
| 547 | &dev_attr_adsl_headend.attr, | ||
| 548 | &dev_attr_modulation.attr, | ||
| 549 | &dev_attr_line_startable.attr, | ||
| 550 | &dev_attr_downstream_hec_errors.attr, | ||
| 551 | &dev_attr_upstream_hec_errors.attr, | ||
| 552 | &dev_attr_downstream_fec_errors.attr, | ||
| 553 | &dev_attr_upstream_fec_errors.attr, | ||
| 554 | &dev_attr_downstream_crc_errors.attr, | ||
| 555 | &dev_attr_upstream_crc_errors.attr, | ||
| 556 | &dev_attr_startup_attempts.attr, | ||
| 557 | &dev_attr_downstream_bits_per_frame.attr, | ||
| 558 | &dev_attr_upstream_bits_per_frame.attr, | ||
| 559 | &dev_attr_transmitter_power.attr, | ||
| 560 | &dev_attr_downstream_attenuation.attr, | ||
| 561 | &dev_attr_upstream_attenuation.attr, | ||
| 562 | &dev_attr_downstream_snr_margin.attr, | ||
| 563 | &dev_attr_upstream_snr_margin.attr, | ||
| 564 | &dev_attr_mac_address.attr, | ||
| 565 | &dev_attr_line_status.attr, | ||
| 566 | &dev_attr_link_status.attr, | ||
| 567 | &dev_attr_upstream_rate.attr, | ||
| 568 | &dev_attr_downstream_rate.attr, | ||
| 569 | NULL, | ||
| 570 | }; | ||
| 571 | ATTRIBUTE_GROUPS(cxacru); | ||
| 572 | |||
| 542 | /* the following three functions are stolen from drivers/usb/core/message.c */ | 573 | /* the following three functions are stolen from drivers/usb/core/message.c */ |
| 543 | static void cxacru_blocking_completion(struct urb *urb) | 574 | static void cxacru_blocking_completion(struct urb *urb) |
| 544 | { | 575 | { |
| @@ -736,17 +767,6 @@ static int cxacru_card_status(struct cxacru_data *instance) · 191 unmodified lines | |||
| 736 | return 0; | 767 | return 0; |
| 737 | } | 768 | } |
| 738 | 769 | ||
| 739 | static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance, | ||
| 740 | struct atm_dev *atm_dev) | ||
| 741 | { | ||
| 742 | struct usb_interface *intf = usbatm_instance->usb_intf; | ||
| 743 | |||
| 744 | #define CXACRU_DEVICE_REMOVE_FILE(_name) \ | ||
| 745 | device_remove_file(&intf->dev, &dev_attr_##_name); | ||
| 746 | CXACRU_ALL_FILES(REMOVE); | ||
| 747 | #undef CXACRU_DEVICE_REMOVE_FILE | ||
| 748 | } | ||
| 749 | |||
| 750 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, | 770 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, |
| 751 | struct atm_dev *atm_dev) | 771 | struct atm_dev *atm_dev) |
| 752 | { | 772 | { |
| @@ -765,13 +785,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, · 12 unmodified lines | |||
| 765 | return ret; | 785 | return ret; |
| 766 | } | 786 | } |
| 767 | 787 | ||
| 768 | #define CXACRU_DEVICE_CREATE_FILE(_name) \ | ||
| 769 | ret = device_create_file(&intf->dev, &dev_attr_##_name); \ | ||
| 770 | if (unlikely(ret)) \ | ||
| 771 | goto fail_sysfs; | ||
| 772 | CXACRU_ALL_FILES(CREATE); | ||
| 773 | #undef CXACRU_DEVICE_CREATE_FILE | ||
| 774 | |||
| 775 | /* start ADSL */ | 788 | /* start ADSL */ |
| 776 | mutex_lock(&instance->adsl_state_serialize); | 789 | mutex_lock(&instance->adsl_state_serialize); |
| 777 | ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); | 790 | ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); |
| @@ -804,11 +817,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, · 26 unmodified lines | |||
| 804 | if (start_polling) | 817 | if (start_polling) |
| 805 | cxacru_poll_status(&instance->poll_work.work); | 818 | cxacru_poll_status(&instance->poll_work.work); |
| 806 | return 0; | 819 | return 0; |
| 807 | |||
| 808 | fail_sysfs: | ||
| 809 | usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret); | ||
| 810 | cxacru_remove_device_files(usbatm_instance, atm_dev); | ||
| 811 | return ret; | ||
| 812 | } | 820 | } |
| 813 | 821 | ||
| 814 | static void cxacru_poll_status(struct work_struct *work) | 822 | static void cxacru_poll_status(struct work_struct *work) |
| @@ -1332,7 +1340,6 @@ static struct usbatm_driver cxacru_driver = { · 517 unmodified lines | |||
| 1332 | .heavy_init = cxacru_heavy_init, | 1340 | .heavy_init = cxacru_heavy_init, |
| 1333 | .unbind = cxacru_unbind, | 1341 | .unbind = cxacru_unbind, |
| 1334 | .atm_start = cxacru_atm_start, | 1342 | .atm_start = cxacru_atm_start, |
| 1335 | .atm_stop = cxacru_remove_device_files, | ||
| 1336 | .bulk_in = CXACRU_EP_DATA, | 1343 | .bulk_in = CXACRU_EP_DATA, |
| 1337 | .bulk_out = CXACRU_EP_DATA, | 1344 | .bulk_out = CXACRU_EP_DATA, |
| 1338 | .rx_padding = 3, | 1345 | .rx_padding = 3, |
| @@ -1364,7 +1371,8 @@ static struct usb_driver cxacru_usb_driver = { · 25 unmodified lines | |||
| 1364 | .name = cxacru_driver_name, | 1371 | .name = cxacru_driver_name, |
| 1365 | .probe = cxacru_usb_probe, | 1372 | .probe = cxacru_usb_probe, |
| 1366 | .disconnect = usbatm_usb_disconnect, | 1373 | .disconnect = usbatm_usb_disconnect, |
| 1367 | .id_table = cxacru_usb_ids | 1374 | .id_table = cxacru_usb_ids, |
| 1375 | .dev_groups = cxacru_groups, | ||
| 1368 | }; | 1376 | }; |
| 1369 | 1377 | ||
| 1370 | module_usb_driver(cxacru_usb_driver); | 1378 | module_usb_driver(cxacru_usb_driver); |
| @@ -2458,7 +2458,7 @@ static int claim_interface(struct usb_device *usb_dev, · 2457 unmodified lines | |||
| 2458 | return ret; | 2458 | return ret; |
| 2459 | } | 2459 | } |
| 2460 | 2460 | ||
| 2461 | static struct attribute *attrs[] = { | 2461 | static struct attribute *uea_attrs[] = { |
| 2462 | &dev_attr_stat_status.attr, | 2462 | &dev_attr_stat_status.attr, |
| 2463 | &dev_attr_stat_mflags.attr, | 2463 | &dev_attr_stat_mflags.attr, |
| 2464 | &dev_attr_stat_human_status.attr, | 2464 | &dev_attr_stat_human_status.attr, |
| @@ -2479,9 +2479,7 @@ static struct attribute *attrs[] = { · 14 unmodified lines | |||
| 2479 | &dev_attr_stat_firmid.attr, | 2479 | &dev_attr_stat_firmid.attr, |
| 2480 | NULL, | 2480 | NULL, |
| 2481 | }; | 2481 | }; |
| 2482 | static const struct attribute_group attr_grp = { | 2482 | ATTRIBUTE_GROUPS(uea); |
| 2483 | .attrs = attrs, | ||
| 2484 | }; | ||
| 2485 | 2483 | ||
| 2486 | static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, | 2484 | static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, |
| 2487 | const struct usb_device_id *id) | 2485 | const struct usb_device_id *id) |
| @@ -2550,18 +2548,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, · 62 unmodified lines | |||
| 2550 | } | 2548 | } |
| 2551 | } | 2549 | } |
| 2552 | 2550 | ||
| 2553 | ret = sysfs_create_group(&intf->dev.kobj, &attr_grp); | ||
| 2554 | if (ret < 0) | ||
| 2555 | goto error; | ||
| 2556 | |||
| 2557 | ret = uea_boot(sc); | 2551 | ret = uea_boot(sc); |
| 2558 | if (ret < 0) | 2552 | if (ret < 0) |
| 2559 | goto error_rm_grp; | 2553 | goto error; |
| 2560 | 2554 | ||
| 2561 | return 0; | 2555 | return 0; |
| 2562 | 2556 | ||
| 2563 | error_rm_grp: | ||
| 2564 | sysfs_remove_group(&intf->dev.kobj, &attr_grp); | ||
| 2565 | error: | 2557 | error: |
| 2566 | kfree(sc); | 2558 | kfree(sc); |
| 2567 | return ret; | 2559 | return ret; |
| @@ -2571,7 +2563,6 @@ static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) · 3 unmodified lines | |||
| 2571 | { | 2563 | { |
| 2572 | struct uea_softc *sc = usbatm->driver_data; | 2564 | struct uea_softc *sc = usbatm->driver_data; |
| 2573 | 2565 | ||
| 2574 | sysfs_remove_group(&intf->dev.kobj, &attr_grp); | ||
| 2575 | uea_stop(sc); | 2566 | uea_stop(sc); |
| 2576 | kfree(sc); | 2567 | kfree(sc); |
| 2577 | } | 2568 | } |
| @@ -2721,6 +2712,7 @@ static struct usb_driver uea_driver = { · 143 unmodified lines | |||
| 2721 | .id_table = uea_ids, | 2712 | .id_table = uea_ids, |
| 2722 | .probe = uea_probe, | 2713 | .probe = uea_probe, |
| 2723 | .disconnect = uea_disconnect, | 2714 | .disconnect = uea_disconnect, |
| 2715 | .dev_groups = uea_groups, | ||
| 2724 | }; | 2716 | }; |
| 2725 | 2717 | ||
| 2726 | MODULE_DEVICE_TABLE(usb, uea_ids); | 2718 | MODULE_DEVICE_TABLE(usb, uea_ids); |
| @@ -0,0 +1,46 @@ | |||
| 1 | config USB_CDNS3 | ||
| 2 | tristate "Cadence USB3 Dual-Role Controller" | ||
| 3 | depends on USB_SUPPORT && (USB || USB_GADGET) && HAS_DMA | ||
| 4 | select USB_XHCI_PLATFORM if USB_XHCI_HCD | ||
| 5 | select USB_ROLE_SWITCH | ||
| 6 | help | ||
| 7 | Say Y here if your system has a Cadence USB3 dual-role controller. | ||
| 8 | It supports: dual-role switch, Host-only, and Peripheral-only. | ||
| 9 | |||
| 10 | If you choose to build this driver is a dynamically linked | ||
| 11 | as module, the module will be called cdns3.ko. | ||
| 12 | |||
| 13 | if USB_CDNS3 | ||
| 14 | |||
| 15 | config USB_CDNS3_GADGET | ||
| 16 | bool "Cadence USB3 device controller" | ||
| 17 | depends on USB_GADGET=y || USB_GADGET=USB_CDNS3 | ||
| 18 | help | ||
| 19 | Say Y here to enable device controller functionality of the | ||
| 20 | Cadence USBSS-DEV driver. | ||
| 21 | |||
| 22 | This controller supports FF, HS and SS mode. It doesn't support | ||
| 23 | LS and SSP mode. | ||
| 24 | |||
| 25 | config USB_CDNS3_HOST | ||
| 26 | bool "Cadence USB3 host controller" | ||
| 27 | depends on USB=y || USB=USB_CDNS3 | ||
| 28 | help | ||
| 29 | Say Y here to enable host controller functionality of the | ||
| 30 | Cadence driver. | ||
| 31 | |||
| 32 | Host controller is compliant with XHCI so it will use | ||
| 33 | standard XHCI driver. | ||
| 34 | |||
| 35 | config USB_CDNS3_PCI_WRAP | ||
| 36 | tristate "Cadence USB3 support on PCIe-based platforms" | ||
| 37 | depends on USB_PCI && ACPI | ||
| 38 | default USB_CDNS3 | ||
| 39 | help | ||
| 40 | If you're using the USBSS Core IP with a PCIe, please say | ||
| 41 | 'Y' or 'M' here. | ||
| 42 | |||
| 43 | If you choose to build this driver as module it will | ||
| 44 | be dynamically linked and module will be called cdns3-pci.ko | ||
| 45 | |||
| 46 | endif | ||
| @@ -0,0 +1,16 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | # define_trace.h needs to know how to find our header | ||
| 3 | CFLAGS_trace.o := -I$(src) | ||
| 4 | |||
| 5 | cdns3-y := core.o drd.o | ||
| 6 | |||
| 7 | obj-$(CONFIG_USB_CDNS3) += cdns3.o | ||
| 8 | cdns3-$(CONFIG_USB_CDNS3_GADGET) += gadget.o ep0.o | ||
| 9 | |||
| 10 | ifneq ($(CONFIG_USB_CDNS3_GADGET),) | ||
| 11 | cdns3-$(CONFIG_TRACING) += trace.o | ||
| 12 | endif | ||
| 13 | |||
| 14 | cdns3-$(CONFIG_USB_CDNS3_HOST) += host.o | ||
| 15 | |||
| 16 | obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o | ||
| @@ -0,0 +1,203 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS PCI Glue driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * | ||
| 7 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/pci.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/dma-mapping.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | |||
| 17 | struct cdns3_wrap { | ||
| 18 | struct platform_device *plat_dev; | ||
| 19 | struct resource dev_res[6]; | ||
| 20 | int devfn; | ||
| 21 | }; | ||
| 22 | |||
| 23 | #define RES_IRQ_HOST_ID 0 | ||
| 24 | #define RES_IRQ_PERIPHERAL_ID 1 | ||
| 25 | #define RES_IRQ_OTG_ID 2 | ||
| 26 | #define RES_HOST_ID 3 | ||
| 27 | #define RES_DEV_ID 4 | ||
| 28 | #define RES_DRD_ID 5 | ||
| 29 | |||
| 30 | #define PCI_BAR_HOST 0 | ||
| 31 | #define PCI_BAR_DEV 2 | ||
| 32 | #define PCI_BAR_OTG 0 | ||
| 33 | |||
| 34 | #define PCI_DEV_FN_HOST_DEVICE 0 | ||
| 35 | #define PCI_DEV_FN_OTG 1 | ||
| 36 | |||
| 37 | #define PCI_DRIVER_NAME "cdns3-pci-usbss" | ||
| 38 | #define PLAT_DRIVER_NAME "cdns-usb3" | ||
| 39 | |||
| 40 | #define CDNS_VENDOR_ID 0x17cd | ||
| 41 | #define CDNS_DEVICE_ID 0x0100 | ||
| 42 | |||
| 43 | static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev) | ||
| 44 | { | ||
| 45 | struct pci_dev *func; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Gets the second function. | ||
| 49 | * It's little tricky, but this platform has two function. | ||
| 50 | * The fist keeps resources for Host/Device while the second | ||
| 51 | * keeps resources for DRD/OTG. | ||
| 52 | */ | ||
| 53 | func = pci_get_device(pdev->vendor, pdev->device, NULL); | ||
| 54 | if (unlikely(!func)) | ||
| 55 | return NULL; | ||
| 56 | |||
| 57 | if (func->devfn == pdev->devfn) { | ||
| 58 | func = pci_get_device(pdev->vendor, pdev->device, func); | ||
| 59 | if (unlikely(!func)) | ||
| 60 | return NULL; | ||
| 61 | } | ||
| 62 | |||
| 63 | return func; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int cdns3_pci_probe(struct pci_dev *pdev, | ||
| 67 | const struct pci_device_id *id) | ||
| 68 | { | ||
| 69 | struct platform_device_info plat_info; | ||
| 70 | struct cdns3_wrap *wrap; | ||
| 71 | struct resource *res; | ||
| 72 | struct pci_dev *func; | ||
| 73 | int err; | ||
| 74 | |||
| 75 | /* | ||
| 76 | * for GADGET/HOST PCI (devfn) function number is 0, | ||
| 77 | * for OTG PCI (devfn) function number is 1 | ||
| 78 | */ | ||
| 79 | if (!id || (pdev->devfn != PCI_DEV_FN_HOST_DEVICE && | ||
| 80 | pdev->devfn != PCI_DEV_FN_OTG)) | ||
| 81 | return -EINVAL; | ||
| 82 | |||
| 83 | func = cdns3_get_second_fun(pdev); | ||
| 84 | if (unlikely(!func)) | ||
| 85 | return -EINVAL; | ||
| 86 | |||
| 87 | err = pcim_enable_device(pdev); | ||
| 88 | if (err) { | ||
| 89 | dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", err); | ||
| 90 | return err; | ||
| 91 | } | ||
| 92 | |||
| 93 | pci_set_master(pdev); | ||
| 94 | |||
| 95 | if (pci_is_enabled(func)) { | ||
| 96 | wrap = pci_get_drvdata(func); | ||
| 97 | } else { | ||
| 98 | wrap = kzalloc(sizeof(*wrap), GFP_KERNEL); | ||
| 99 | if (!wrap) { | ||
| 100 | pci_disable_device(pdev); | ||
| 101 | return -ENOMEM; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | res = wrap->dev_res; | ||
| 106 | |||
| 107 | if (pdev->devfn == PCI_DEV_FN_HOST_DEVICE) { | ||
| 108 | /* function 0: host(BAR_0) + device(BAR_1).*/ | ||
| 109 | dev_dbg(&pdev->dev, "Initialize Device resources\n"); | ||
| 110 | res[RES_DEV_ID].start = pci_resource_start(pdev, PCI_BAR_DEV); | ||
| 111 | res[RES_DEV_ID].end = pci_resource_end(pdev, PCI_BAR_DEV); | ||
| 112 | res[RES_DEV_ID].name = "dev"; | ||
| 113 | res[RES_DEV_ID].flags = IORESOURCE_MEM; | ||
| 114 | dev_dbg(&pdev->dev, "USBSS-DEV physical base addr: %pa\n", | ||
| 115 | &res[RES_DEV_ID].start); | ||
| 116 | |||
| 117 | res[RES_HOST_ID].start = pci_resource_start(pdev, PCI_BAR_HOST); | ||
| 118 | res[RES_HOST_ID].end = pci_resource_end(pdev, PCI_BAR_HOST); | ||
| 119 | res[RES_HOST_ID].name = "xhci"; | ||
| 120 | res[RES_HOST_ID].flags = IORESOURCE_MEM; | ||
| 121 | dev_dbg(&pdev->dev, "USBSS-XHCI physical base addr: %pa\n", | ||
| 122 | &res[RES_HOST_ID].start); | ||
| 123 | |||
| 124 | /* Interrupt for XHCI */ | ||
| 125 | wrap->dev_res[RES_IRQ_HOST_ID].start = pdev->irq; | ||
| 126 | wrap->dev_res[RES_IRQ_HOST_ID].name = "host"; | ||
| 127 | wrap->dev_res[RES_IRQ_HOST_ID].flags = IORESOURCE_IRQ; | ||
| 128 | |||
| 129 | /* Interrupt device. It's the same as for HOST. */ | ||
| 130 | wrap->dev_res[RES_IRQ_PERIPHERAL_ID].start = pdev->irq; | ||
| 131 | wrap->dev_res[RES_IRQ_PERIPHERAL_ID].name = "peripheral"; | ||
| 132 | wrap->dev_res[RES_IRQ_PERIPHERAL_ID].flags = IORESOURCE_IRQ; | ||
| 133 | } else { | ||
| 134 | res[RES_DRD_ID].start = pci_resource_start(pdev, PCI_BAR_OTG); | ||
| 135 | res[RES_DRD_ID].end = pci_resource_end(pdev, PCI_BAR_OTG); | ||
| 136 | res[RES_DRD_ID].name = "otg"; | ||
| 137 | res[RES_DRD_ID].flags = IORESOURCE_MEM; | ||
| 138 | dev_dbg(&pdev->dev, "USBSS-DRD physical base addr: %pa\n", | ||
| 139 | &res[RES_DRD_ID].start); | ||
| 140 | |||
| 141 | /* Interrupt for OTG/DRD. */ | ||
| 142 | wrap->dev_res[RES_IRQ_OTG_ID].start = pdev->irq; | ||
| 143 | wrap->dev_res[RES_IRQ_OTG_ID].name = "otg"; | ||
| 144 | wrap->dev_res[RES_IRQ_OTG_ID].flags = IORESOURCE_IRQ; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (pci_is_enabled(func)) { | ||
| 148 | /* set up platform device info */ | ||
| 149 | memset(&plat_info, 0, sizeof(plat_info)); | ||
| 150 | plat_info.parent = &pdev->dev; | ||
| 151 | plat_info.fwnode = pdev->dev.fwnode; | ||
| 152 | plat_info.name = PLAT_DRIVER_NAME; | ||
| 153 | plat_info.id = pdev->devfn; | ||
| 154 | wrap->devfn = pdev->devfn; | ||
| 155 | plat_info.res = wrap->dev_res; | ||
| 156 | plat_info.num_res = ARRAY_SIZE(wrap->dev_res); | ||
| 157 | plat_info.dma_mask = pdev->dma_mask; | ||
| 158 | /* register platform device */ | ||
| 159 | wrap->plat_dev = platform_device_register_full(&plat_info); | ||
| 160 | if (IS_ERR(wrap->plat_dev)) { | ||
| 161 | pci_disable_device(pdev); | ||
| 162 | kfree(wrap); | ||
| 163 | return PTR_ERR(wrap->plat_dev); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | pci_set_drvdata(pdev, wrap); | ||
| 168 | return err; | ||
| 169 | } | ||
| 170 | |||
| 171 | static void cdns3_pci_remove(struct pci_dev *pdev) | ||
| 172 | { | ||
| 173 | struct cdns3_wrap *wrap; | ||
| 174 | struct pci_dev *func; | ||
| 175 | |||
| 176 | func = cdns3_get_second_fun(pdev); | ||
| 177 | |||
| 178 | wrap = (struct cdns3_wrap *)pci_get_drvdata(pdev); | ||
| 179 | if (wrap->devfn == pdev->devfn) | ||
| 180 | platform_device_unregister(wrap->plat_dev); | ||
| 181 | |||
| 182 | if (!pci_is_enabled(func)) | ||
| 183 | kfree(wrap); | ||
| 184 | } | ||
| 185 | |||
| 186 | static const struct pci_device_id cdns3_pci_ids[] = { | ||
| 187 | { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, | ||
| 188 | { 0, } | ||
| 189 | }; | ||
| 190 | |||
| 191 | static struct pci_driver cdns3_pci_driver = { | ||
| 192 | .name = PCI_DRIVER_NAME, | ||
| 193 | .id_table = cdns3_pci_ids, | ||
| 194 | .probe = cdns3_pci_probe, | ||
| 195 | .remove = cdns3_pci_remove, | ||
| 196 | }; | ||
| 197 | |||
| 198 | module_pci_driver(cdns3_pci_driver); | ||
| 199 | MODULE_DEVICE_TABLE(pci, cdns3_pci_ids); | ||
| 200 | |||
| 201 | MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>"); | ||
| 202 | MODULE_LICENSE("GPL v2"); | ||
| 203 | MODULE_DESCRIPTION("Cadence USBSS PCI wrapperr"); | ||
| @@ -0,0 +1,651 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * Copyright (C) 2019 Texas Instruments | ||
| 8 | * | ||
| 9 | * Author: Peter Chen <peter.chen@nxp.com> | ||
| 10 | * Pawel Laszczak <pawell@cadence.com> | ||
| 11 | * Roger Quadros <rogerq@ti.com> | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/dma-mapping.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/pm_runtime.h> | ||
| 21 | |||
| 22 | #include "gadget.h" | ||
| 23 | #include "core.h" | ||
| 24 | #include "host-export.h" | ||
| 25 | #include "gadget-export.h" | ||
| 26 | #include "drd.h" | ||
| 27 | |||
| 28 | static int cdns3_idle_init(struct cdns3 *cdns); | ||
| 29 | |||
| 30 | static inline | ||
| 31 | struct cdns3_role_driver *cdns3_get_current_role_driver(struct cdns3 *cdns) | ||
| 32 | { | ||
| 33 | WARN_ON(!cdns->roles[cdns->role]); | ||
| 34 | return cdns->roles[cdns->role]; | ||
| 35 | } | ||
| 36 | |||
| 37 | static int cdns3_role_start(struct cdns3 *cdns, enum usb_role role) | ||
| 38 | { | ||
| 39 | int ret; | ||
| 40 | |||
| 41 | if (WARN_ON(role > USB_ROLE_DEVICE)) | ||
| 42 | return 0; | ||
| 43 | |||
| 44 | mutex_lock(&cdns->mutex); | ||
| 45 | cdns->role = role; | ||
| 46 | mutex_unlock(&cdns->mutex); | ||
| 47 | |||
| 48 | if (!cdns->roles[role]) | ||
| 49 | return -ENXIO; | ||
| 50 | |||
| 51 | if (cdns->roles[role]->state == CDNS3_ROLE_STATE_ACTIVE) | ||
| 52 | return 0; | ||
| 53 | |||
| 54 | mutex_lock(&cdns->mutex); | ||
| 55 | ret = cdns->roles[role]->start(cdns); | ||
| 56 | if (!ret) | ||
| 57 | cdns->roles[role]->state = CDNS3_ROLE_STATE_ACTIVE; | ||
| 58 | mutex_unlock(&cdns->mutex); | ||
| 59 | |||
| 60 | return ret; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void cdns3_role_stop(struct cdns3 *cdns) | ||
| 64 | { | ||
| 65 | enum usb_role role = cdns->role; | ||
| 66 | |||
| 67 | if (WARN_ON(role > USB_ROLE_DEVICE)) | ||
| 68 | return; | ||
| 69 | |||
| 70 | if (cdns->roles[role]->state == CDNS3_ROLE_STATE_INACTIVE) | ||
| 71 | return; | ||
| 72 | |||
| 73 | mutex_lock(&cdns->mutex); | ||
| 74 | cdns->roles[role]->stop(cdns); | ||
| 75 | cdns->roles[role]->state = CDNS3_ROLE_STATE_INACTIVE; | ||
| 76 | mutex_unlock(&cdns->mutex); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void cdns3_exit_roles(struct cdns3 *cdns) | ||
| 80 | { | ||
| 81 | cdns3_role_stop(cdns); | ||
| 82 | cdns3_drd_exit(cdns); | ||
| 83 | } | ||
| 84 | |||
| 85 | static enum usb_role cdsn3_hw_role_state_machine(struct cdns3 *cdns); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * cdns3_core_init_role - initialize role of operation | ||
| 89 | * @cdns: Pointer to cdns3 structure | ||
| 90 | * | ||
| 91 | * Returns 0 on success otherwise negative errno | ||
| 92 | */ | ||
| 93 | static int cdns3_core_init_role(struct cdns3 *cdns) | ||
| 94 | { | ||
| 95 | struct device *dev = cdns->dev; | ||
| 96 | enum usb_dr_mode best_dr_mode; | ||
| 97 | enum usb_dr_mode dr_mode; | ||
| 98 | int ret = 0; | ||
| 99 | |||
| 100 | dr_mode = usb_get_dr_mode(dev); | ||
| 101 | cdns->role = USB_ROLE_NONE; | ||
| 102 | |||
| 103 | /* | ||
| 104 | * If driver can't read mode by means of usb_get_dr_mode function then | ||
| 105 | * chooses mode according with Kernel configuration. This setting | ||
| 106 | * can be restricted later depending on strap pin configuration. | ||
| 107 | */ | ||
| 108 | if (dr_mode == USB_DR_MODE_UNKNOWN) { | ||
| 109 | if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) && | ||
| 110 | IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) | ||
| 111 | dr_mode = USB_DR_MODE_OTG; | ||
| 112 | else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST)) | ||
| 113 | dr_mode = USB_DR_MODE_HOST; | ||
| 114 | else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) | ||
| 115 | dr_mode = USB_DR_MODE_PERIPHERAL; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * At this point cdns->dr_mode contains strap configuration. | ||
| 120 | * Driver try update this setting considering kernel configuration | ||
| 121 | */ | ||
| 122 | best_dr_mode = cdns->dr_mode; | ||
| 123 | |||
| 124 | ret = cdns3_idle_init(cdns); | ||
| 125 | if (ret) | ||
| 126 | return ret; | ||
| 127 | |||
| 128 | if (dr_mode == USB_DR_MODE_OTG) { | ||
| 129 | best_dr_mode = cdns->dr_mode; | ||
| 130 | } else if (cdns->dr_mode == USB_DR_MODE_OTG) { | ||
| 131 | best_dr_mode = dr_mode; | ||
| 132 | } else if (cdns->dr_mode != dr_mode) { | ||
| 133 | dev_err(dev, "Incorrect DRD configuration\n"); | ||
| 134 | return -EINVAL; | ||
| 135 | } | ||
| 136 | |||
| 137 | dr_mode = best_dr_mode; | ||
| 138 | |||
| 139 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { | ||
| 140 | ret = cdns3_host_init(cdns); | ||
| 141 | if (ret) { | ||
| 142 | dev_err(dev, "Host initialization failed with %d\n", | ||
| 143 | ret); | ||
| 144 | goto err; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { | ||
| 149 | ret = cdns3_gadget_init(cdns); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(dev, "Device initialization failed with %d\n", | ||
| 152 | ret); | ||
| 153 | goto err; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | cdns->dr_mode = dr_mode; | ||
| 158 | |||
| 159 | ret = cdns3_drd_update_mode(cdns); | ||
| 160 | if (ret) | ||
| 161 | goto err; | ||
| 162 | |||
| 163 | if (cdns->dr_mode != USB_DR_MODE_OTG) { | ||
| 164 | ret = cdns3_hw_role_switch(cdns); | ||
| 165 | if (ret) | ||
| 166 | goto err; | ||
| 167 | } | ||
| 168 | |||
| 169 | return ret; | ||
| 170 | err: | ||
| 171 | cdns3_exit_roles(cdns); | ||
| 172 | return ret; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * cdsn3_hw_role_state_machine - role switch state machine based on hw events. | ||
| 177 | * @cdns: Pointer to controller structure. | ||
| 178 | * | ||
| 179 | * Returns next role to be entered based on hw events. | ||
| 180 | */ | ||
| 181 | static enum usb_role cdsn3_hw_role_state_machine(struct cdns3 *cdns) | ||
| 182 | { | ||
| 183 | enum usb_role role; | ||
| 184 | int id, vbus; | ||
| 185 | |||
| 186 | if (cdns->dr_mode != USB_DR_MODE_OTG) | ||
| 187 | goto not_otg; | ||
| 188 | |||
| 189 | id = cdns3_get_id(cdns); | ||
| 190 | vbus = cdns3_get_vbus(cdns); | ||
| 191 | |||
| 192 | /* | ||
| 193 | * Role change state machine | ||
| 194 | * Inputs: ID, VBUS | ||
| 195 | * Previous state: cdns->role | ||
| 196 | * Next state: role | ||
| 197 | */ | ||
| 198 | role = cdns->role; | ||
| 199 | |||
| 200 | switch (role) { | ||
| 201 | case USB_ROLE_NONE: | ||
| 202 | /* | ||
| 203 | * Driver treats USB_ROLE_NONE synonymous to IDLE state from | ||
| 204 | * controller specification. | ||
| 205 | */ | ||
| 206 | if (!id) | ||
| 207 | role = USB_ROLE_HOST; | ||
| 208 | else if (vbus) | ||
| 209 | role = USB_ROLE_DEVICE; | ||
| 210 | break; | ||
| 211 | case USB_ROLE_HOST: /* from HOST, we can only change to NONE */ | ||
| 212 | if (id) | ||
| 213 | role = USB_ROLE_NONE; | ||
| 214 | break; | ||
| 215 | case USB_ROLE_DEVICE: /* from GADGET, we can only change to NONE*/ | ||
| 216 | if (!vbus) | ||
| 217 | role = USB_ROLE_NONE; | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | |||
| 221 | dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role); | ||
| 222 | |||
| 223 | return role; | ||
| 224 | |||
| 225 | not_otg: | ||
| 226 | if (cdns3_is_host(cdns)) | ||
| 227 | role = USB_ROLE_HOST; | ||
| 228 | if (cdns3_is_device(cdns)) | ||
| 229 | role = USB_ROLE_DEVICE; | ||
| 230 | |||
| 231 | return role; | ||
| 232 | } | ||
| 233 | |||
| 234 | static int cdns3_idle_role_start(struct cdns3 *cdns) | ||
| 235 | { | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | static void cdns3_idle_role_stop(struct cdns3 *cdns) | ||
| 240 | { | ||
| 241 | /* Program Lane swap and bring PHY out of RESET */ | ||
| 242 | phy_reset(cdns->usb3_phy); | ||
| 243 | } | ||
| 244 | |||
| 245 | static int cdns3_idle_init(struct cdns3 *cdns) | ||
| 246 | { | ||
| 247 | struct cdns3_role_driver *rdrv; | ||
| 248 | |||
| 249 | rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); | ||
| 250 | if (!rdrv) | ||
| 251 | return -ENOMEM; | ||
| 252 | |||
| 253 | rdrv->start = cdns3_idle_role_start; | ||
| 254 | rdrv->stop = cdns3_idle_role_stop; | ||
| 255 | rdrv->state = CDNS3_ROLE_STATE_INACTIVE; | ||
| 256 | rdrv->suspend = NULL; | ||
| 257 | rdrv->resume = NULL; | ||
| 258 | rdrv->name = "idle"; | ||
| 259 | |||
| 260 | cdns->roles[USB_ROLE_NONE] = rdrv; | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * cdns3_hw_role_switch - switch roles based on HW state | ||
| 267 | * @cdns3: controller | ||
| 268 | */ | ||
| 269 | int cdns3_hw_role_switch(struct cdns3 *cdns) | ||
| 270 | { | ||
| 271 | enum usb_role real_role, current_role; | ||
| 272 | int ret = 0; | ||
| 273 | |||
| 274 | /* Do nothing if role based on syfs. */ | ||
| 275 | if (cdns->role_override) | ||
| 276 | return 0; | ||
| 277 | |||
| 278 | pm_runtime_get_sync(cdns->dev); | ||
| 279 | |||
| 280 | current_role = cdns->role; | ||
| 281 | real_role = cdsn3_hw_role_state_machine(cdns); | ||
| 282 | |||
| 283 | /* Do nothing if nothing changed */ | ||
| 284 | if (current_role == real_role) | ||
| 285 | goto exit; | ||
| 286 | |||
| 287 | cdns3_role_stop(cdns); | ||
| 288 | |||
| 289 | dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role); | ||
| 290 | |||
| 291 | ret = cdns3_role_start(cdns, real_role); | ||
| 292 | if (ret) { | ||
| 293 | /* Back to current role */ | ||
| 294 | dev_err(cdns->dev, "set %d has failed, back to %d\n", | ||
| 295 | real_role, current_role); | ||
| 296 | ret = cdns3_role_start(cdns, current_role); | ||
| 297 | if (ret) | ||
| 298 | dev_err(cdns->dev, "back to %d failed too\n", | ||
| 299 | current_role); | ||
| 300 | } | ||
| 301 | exit: | ||
| 302 | pm_runtime_put_sync(cdns->dev); | ||
| 303 | return ret; | ||
| 304 | } | ||
| 305 | |||
| 306 | /** | ||
| 307 | * cdsn3_role_get - get current role of controller. | ||
| 308 | * | ||
| 309 | * @dev: Pointer to device structure | ||
| 310 | * | ||
| 311 | * Returns role | ||
| 312 | */ | ||
| 313 | static enum usb_role cdns3_role_get(struct device *dev) | ||
| 314 | { | ||
| 315 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 316 | |||
| 317 | return cdns->role; | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * cdns3_role_set - set current role of controller. | ||
| 322 | * | ||
| 323 | * @dev: pointer to device object | ||
| 324 | * @role - the previous role | ||
| 325 | * Handles below events: | ||
| 326 | * - Role switch for dual-role devices | ||
| 327 | * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices | ||
| 328 | */ | ||
| 329 | static int cdns3_role_set(struct device *dev, enum usb_role role) | ||
| 330 | { | ||
| 331 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 332 | int ret = 0; | ||
| 333 | |||
| 334 | pm_runtime_get_sync(cdns->dev); | ||
| 335 | |||
| 336 | /* | ||
| 337 | * FIXME: switch role framework should be extended to meet | ||
| 338 | * requirements. Driver assumes that role can be controlled | ||
| 339 | * by SW or HW. Temporary workaround is to use USB_ROLE_NONE to | ||
| 340 | * switch from SW to HW control. | ||
| 341 | * | ||
| 342 | * For dr_mode == USB_DR_MODE_OTG: | ||
| 343 | * if user sets USB_ROLE_HOST or USB_ROLE_DEVICE then driver | ||
| 344 | * sets role_override flag and forces that role. | ||
| 345 | * if user sets USB_ROLE_NONE, driver clears role_override and lets | ||
| 346 | * HW state machine take over. | ||
| 347 | * | ||
| 348 | * For dr_mode != USB_DR_MODE_OTG: | ||
| 349 | * Assumptions: | ||
| 350 | * 1. Restricted user control between NONE and dr_mode. | ||
| 351 | * 2. Driver doesn't need to rely on role_override flag. | ||
| 352 | * 3. Driver needs to ensure that HW state machine is never called | ||
| 353 | * if dr_mode != USB_DR_MODE_OTG. | ||
| 354 | */ | ||
| 355 | if (role == USB_ROLE_NONE) | ||
| 356 | cdns->role_override = 0; | ||
| 357 | else | ||
| 358 | cdns->role_override = 1; | ||
| 359 | |||
| 360 | /* | ||
| 361 | * HW state might have changed so driver need to trigger | ||
| 362 | * HW state machine if dr_mode == USB_DR_MODE_OTG. | ||
| 363 | */ | ||
| 364 | if (!cdns->role_override && cdns->dr_mode == USB_DR_MODE_OTG) { | ||
| 365 | cdns3_hw_role_switch(cdns); | ||
| 366 | goto pm_put; | ||
| 367 | } | ||
| 368 | |||
| 369 | if (cdns->role == role) | ||
| 370 | goto pm_put; | ||
| 371 | |||
| 372 | if (cdns->dr_mode == USB_DR_MODE_HOST) { | ||
| 373 | switch (role) { | ||
| 374 | case USB_ROLE_NONE: | ||
| 375 | case USB_ROLE_HOST: | ||
| 376 | break; | ||
| 377 | default: | ||
| 378 | ret = -EPERM; | ||
| 379 | goto pm_put; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) { | ||
| 384 | switch (role) { | ||
| 385 | case USB_ROLE_NONE: | ||
| 386 | case USB_ROLE_DEVICE: | ||
| 387 | break; | ||
| 388 | default: | ||
| 389 | ret = -EPERM; | ||
| 390 | goto pm_put; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | cdns3_role_stop(cdns); | ||
| 395 | ret = cdns3_role_start(cdns, role); | ||
| 396 | if (ret) { | ||
| 397 | dev_err(cdns->dev, "set role %d has failed\n", role); | ||
| 398 | ret = -EPERM; | ||
| 399 | } | ||
| 400 | |||
| 401 | pm_put: | ||
| 402 | pm_runtime_put_sync(cdns->dev); | ||
| 403 | return ret; | ||
| 404 | } | ||
| 405 | |||
| 406 | static const struct usb_role_switch_desc cdns3_switch_desc = { | ||
| 407 | .set = cdns3_role_set, | ||
| 408 | .get = cdns3_role_get, | ||
| 409 | .allow_userspace_control = true, | ||
| 410 | }; | ||
| 411 | |||
| 412 | /** | ||
| 413 | * cdns3_probe - probe for cdns3 core device | ||
| 414 | * @pdev: Pointer to cdns3 core platform device | ||
| 415 | * | ||
| 416 | * Returns 0 on success otherwise negative errno | ||
| 417 | */ | ||
| 418 | static int cdns3_probe(struct platform_device *pdev) | ||
| 419 | { | ||
| 420 | struct device *dev = &pdev->dev; | ||
| 421 | struct resource *res; | ||
| 422 | struct cdns3 *cdns; | ||
| 423 | void __iomem *regs; | ||
| 424 | int ret; | ||
| 425 | |||
| 426 | ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); | ||
| 427 | if (ret) { | ||
| 428 | dev_err(dev, "error setting dma mask: %d\n", ret); | ||
| 429 | return -ENODEV; | ||
| 430 | } | ||
| 431 | |||
| 432 | cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); | ||
| 433 | if (!cdns) | ||
| 434 | return -ENOMEM; | ||
| 435 | |||
| 436 | cdns->dev = dev; | ||
| 437 | |||
| 438 | platform_set_drvdata(pdev, cdns); | ||
| 439 | |||
| 440 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "host"); | ||
| 441 | if (!res) { | ||
| 442 | dev_err(dev, "missing host IRQ\n"); | ||
| 443 | return -ENODEV; | ||
| 444 | } | ||
| 445 | |||
| 446 | cdns->xhci_res[0] = *res; | ||
| 447 | |||
| 448 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "xhci"); | ||
| 449 | if (!res) { | ||
| 450 | dev_err(dev, "couldn't get xhci resource\n"); | ||
| 451 | return -ENXIO; | ||
| 452 | } | ||
| 453 | |||
| 454 | cdns->xhci_res[1] = *res; | ||
| 455 | |||
| 456 | cdns->dev_irq = platform_get_irq_byname(pdev, "peripheral"); | ||
| 457 | if (cdns->dev_irq == -EPROBE_DEFER) | ||
| 458 | return cdns->dev_irq; | ||
| 459 | |||
| 460 | if (cdns->dev_irq < 0) | ||
| 461 | dev_err(dev, "couldn't get peripheral irq\n"); | ||
| 462 | |||
| 463 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dev"); | ||
| 464 | regs = devm_ioremap_resource(dev, res); | ||
| 465 | if (IS_ERR(regs)) | ||
| 466 | return PTR_ERR(regs); | ||
| 467 | cdns->dev_regs = regs; | ||
| 468 | |||
| 469 | cdns->otg_irq = platform_get_irq_byname(pdev, "otg"); | ||
| 470 | if (cdns->otg_irq == -EPROBE_DEFER) | ||
| 471 | return cdns->otg_irq; | ||
| 472 | |||
| 473 | if (cdns->otg_irq < 0) { | ||
| 474 | dev_err(dev, "couldn't get otg irq\n"); | ||
| 475 | return cdns->otg_irq; | ||
| 476 | } | ||
| 477 | |||
| 478 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otg"); | ||
| 479 | if (!res) { | ||
| 480 | dev_err(dev, "couldn't get otg resource\n"); | ||
| 481 | return -ENXIO; | ||
| 482 | } | ||
| 483 | |||
| 484 | cdns->otg_res = *res; | ||
| 485 | |||
| 486 | mutex_init(&cdns->mutex); | ||
| 487 | |||
| 488 | cdns->usb2_phy = devm_phy_optional_get(dev, "cdns3,usb2-phy"); | ||
| 489 | if (IS_ERR(cdns->usb2_phy)) | ||
| 490 | return PTR_ERR(cdns->usb2_phy); | ||
| 491 | |||
| 492 | ret = phy_init(cdns->usb2_phy); | ||
| 493 | if (ret) | ||
| 494 | return ret; | ||
| 495 | |||
| 496 | cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy"); | ||
| 497 | if (IS_ERR(cdns->usb3_phy)) | ||
| 498 | return PTR_ERR(cdns->usb3_phy); | ||
| 499 | |||
| 500 | ret = phy_init(cdns->usb3_phy); | ||
| 501 | if (ret) | ||
| 502 | goto err1; | ||
| 503 | |||
| 504 | ret = phy_power_on(cdns->usb2_phy); | ||
| 505 | if (ret) | ||
| 506 | goto err2; | ||
| 507 | |||
| 508 | ret = phy_power_on(cdns->usb3_phy); | ||
| 509 | if (ret) | ||
| 510 | goto err3; | ||
| 511 | |||
| 512 | cdns->role_sw = usb_role_switch_register(dev, &cdns3_switch_desc); | ||
| 513 | if (IS_ERR(cdns->role_sw)) { | ||
| 514 | ret = PTR_ERR(cdns->role_sw); | ||
| 515 | dev_warn(dev, "Unable to register Role Switch\n"); | ||
| 516 | goto err4; | ||
| 517 | } | ||
| 518 | |||
| 519 | ret = cdns3_drd_init(cdns); | ||
| 520 | if (ret) | ||
| 521 | goto err5; | ||
| 522 | |||
| 523 | ret = cdns3_core_init_role(cdns); | ||
| 524 | if (ret) | ||
| 525 | goto err5; | ||
| 526 | |||
| 527 | device_set_wakeup_capable(dev, true); | ||
| 528 | pm_runtime_set_active(dev); | ||
| 529 | pm_runtime_enable(dev); | ||
| 530 | |||
| 531 | /* | ||
| 532 | * The controller needs less time between bus and controller suspend, | ||
| 533 | * and we also needs a small delay to avoid frequently entering low | ||
| 534 | * power mode. | ||
| 535 | */ | ||
| 536 | pm_runtime_set_autosuspend_delay(dev, 20); | ||
| 537 | pm_runtime_mark_last_busy(dev); | ||
| 538 | pm_runtime_use_autosuspend(dev); | ||
| 539 | dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); | ||
| 540 | |||
| 541 | return 0; | ||
| 542 | err5: | ||
| 543 | cdns3_drd_exit(cdns); | ||
| 544 | usb_role_switch_unregister(cdns->role_sw); | ||
| 545 | err4: | ||
| 546 | phy_power_off(cdns->usb3_phy); | ||
| 547 | |||
| 548 | err3: | ||
| 549 | phy_power_off(cdns->usb2_phy); | ||
| 550 | err2: | ||
| 551 | phy_exit(cdns->usb3_phy); | ||
| 552 | err1: | ||
| 553 | phy_exit(cdns->usb2_phy); | ||
| 554 | |||
| 555 | return ret; | ||
| 556 | } | ||
| 557 | |||
| 558 | /** | ||
| 559 | * cdns3_remove - unbind drd driver and clean up | ||
| 560 | * @pdev: Pointer to Linux platform device | ||
| 561 | * | ||
| 562 | * Returns 0 on success otherwise negative errno | ||
| 563 | */ | ||
| 564 | static int cdns3_remove(struct platform_device *pdev) | ||
| 565 | { | ||
| 566 | struct cdns3 *cdns = platform_get_drvdata(pdev); | ||
| 567 | |||
| 568 | pm_runtime_get_sync(&pdev->dev); | ||
| 569 | pm_runtime_disable(&pdev->dev); | ||
| 570 | pm_runtime_put_noidle(&pdev->dev); | ||
| 571 | cdns3_exit_roles(cdns); | ||
| 572 | usb_role_switch_unregister(cdns->role_sw); | ||
| 573 | phy_power_off(cdns->usb2_phy); | ||
| 574 | phy_power_off(cdns->usb3_phy); | ||
| 575 | phy_exit(cdns->usb2_phy); | ||
| 576 | phy_exit(cdns->usb3_phy); | ||
| 577 | return 0; | ||
| 578 | } | ||
| 579 | |||
| 580 | #ifdef CONFIG_PM_SLEEP | ||
| 581 | |||
| 582 | static int cdns3_suspend(struct device *dev) | ||
| 583 | { | ||
| 584 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 585 | unsigned long flags; | ||
| 586 | |||
| 587 | if (cdns->role == USB_ROLE_HOST) | ||
| 588 | return 0; | ||
| 589 | |||
| 590 | if (pm_runtime_status_suspended(dev)) | ||
| 591 | pm_runtime_resume(dev); | ||
| 592 | |||
| 593 | if (cdns->roles[cdns->role]->suspend) { | ||
| 594 | spin_lock_irqsave(&cdns->gadget_dev->lock, flags); | ||
| 595 | cdns->roles[cdns->role]->suspend(cdns, false); | ||
| 596 | spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags); | ||
| 597 | } | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int cdns3_resume(struct device *dev) | ||
| 603 | { | ||
| 604 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 605 | unsigned long flags; | ||
| 606 | |||
| 607 | if (cdns->role == USB_ROLE_HOST) | ||
| 608 | return 0; | ||
| 609 | |||
| 610 | if (cdns->roles[cdns->role]->resume) { | ||
| 611 | spin_lock_irqsave(&cdns->gadget_dev->lock, flags); | ||
| 612 | cdns->roles[cdns->role]->resume(cdns, false); | ||
| 613 | spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags); | ||
| 614 | } | ||
| 615 | |||
| 616 | pm_runtime_disable(dev); | ||
| 617 | pm_runtime_set_active(dev); | ||
| 618 | pm_runtime_enable(dev); | ||
| 619 | |||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | #endif | ||
| 623 | |||
| 624 | static const struct dev_pm_ops cdns3_pm_ops = { | ||
| 625 | SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume) | ||
| 626 | }; | ||
| 627 | |||
| 628 | #ifdef CONFIG_OF | ||
| 629 | static const struct of_device_id of_cdns3_match[] = { | ||
| 630 | { .compatible = "cdns,usb3" }, | ||
| 631 | { }, | ||
| 632 | }; | ||
| 633 | MODULE_DEVICE_TABLE(of, of_cdns3_match); | ||
| 634 | #endif | ||
| 635 | |||
| 636 | static struct platform_driver cdns3_driver = { | ||
| 637 | .probe = cdns3_probe, | ||
| 638 | .remove = cdns3_remove, | ||
| 639 | .driver = { | ||
| 640 | .name = "cdns-usb3", | ||
| 641 | .of_match_table = of_match_ptr(of_cdns3_match), | ||
| 642 | .pm = &cdns3_pm_ops, | ||
| 643 | }, | ||
| 644 | }; | ||
| 645 | |||
| 646 | module_platform_driver(cdns3_driver); | ||
| 647 | |||
| 648 | MODULE_ALIAS("platform:cdns3"); | ||
| 649 | MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>"); | ||
| 650 | MODULE_LICENSE("GPL v2"); | ||
| 651 | MODULE_DESCRIPTION("Cadence USB3 DRD Controller Driver"); | ||
| @@ -0,0 +1,98 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Header File. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017-2018 NXP | ||
| 6 | * Copyright (C) 2018-2019 Cadence. | ||
| 7 | * | ||
| 8 | * Authors: Peter Chen <peter.chen@nxp.com> | ||
| 9 | * Pawel Laszczak <pawell@cadence.com> | ||
| 10 | */ | ||
| 11 | #include <linux/usb/otg.h> | ||
| 12 | #include <linux/usb/role.h> | ||
| 13 | |||
| 14 | #ifndef __LINUX_CDNS3_CORE_H | ||
| 15 | #define __LINUX_CDNS3_CORE_H | ||
| 16 | |||
| 17 | struct cdns3; | ||
| 18 | |||
| 19 | /** | ||
| 20 | * struct cdns3_role_driver - host/gadget role driver | ||
| 21 | * @start: start this role | ||
| 22 | * @stop: stop this role | ||
| 23 | * @suspend: suspend callback for this role | ||
| 24 | * @resume: resume callback for this role | ||
| 25 | * @irq: irq handler for this role | ||
| 26 | * @name: role name string (host/gadget) | ||
| 27 | * @state: current state | ||
| 28 | */ | ||
| 29 | struct cdns3_role_driver { | ||
| 30 | int (*start)(struct cdns3 *cdns); | ||
| 31 | void (*stop)(struct cdns3 *cdns); | ||
| 32 | int (*suspend)(struct cdns3 *cdns, bool do_wakeup); | ||
| 33 | int (*resume)(struct cdns3 *cdns, bool hibernated); | ||
| 34 | const char *name; | ||
| 35 | #define CDNS3_ROLE_STATE_INACTIVE 0 | ||
| 36 | #define CDNS3_ROLE_STATE_ACTIVE 1 | ||
| 37 | int state; | ||
| 38 | }; | ||
| 39 | |||
| 40 | #define CDNS3_XHCI_RESOURCES_NUM 2 | ||
| 41 | /** | ||
| 42 | * struct cdns3 - Representation of Cadence USB3 DRD controller. | ||
| 43 | * @dev: pointer to Cadence device struct | ||
| 44 | * @xhci_regs: pointer to base of xhci registers | ||
| 45 | * @xhci_res: the resource for xhci | ||
| 46 | * @dev_regs: pointer to base of dev registers | ||
| 47 | * @otg_res: the resource for otg | ||
| 48 | * @otg_v0_regs: pointer to base of v0 otg registers | ||
| 49 | * @otg_v1_regs: pointer to base of v1 otg registers | ||
| 50 | * @otg_regs: pointer to base of otg registers | ||
| 51 | * @otg_irq: irq number for otg controller | ||
| 52 | * @dev_irq: irq number for device controller | ||
| 53 | * @roles: array of supported roles for this controller | ||
| 54 | * @role: current role | ||
| 55 | * @host_dev: the child host device pointer for cdns3 core | ||
| 56 | * @gadget_dev: the child gadget device pointer for cdns3 core | ||
| 57 | * @usb2_phy: pointer to USB2 PHY | ||
| 58 | * @usb3_phy: pointer to USB3 PHY | ||
| 59 | * @mutex: the mutex for concurrent code at driver | ||
| 60 | * @dr_mode: supported mode of operation it can be only Host, only Device | ||
| 61 | * or OTG mode that allow to switch between Device and Host mode. | ||
| 62 | * This field based on firmware setting, kernel configuration | ||
| 63 | * and hardware configuration. | ||
| 64 | * @role_sw: pointer to role switch object. | ||
| 65 | * @role_override: set 1 if role rely on SW. | ||
| 66 | */ | ||
| 67 | struct cdns3 { | ||
| 68 | struct device *dev; | ||
| 69 | void __iomem *xhci_regs; | ||
| 70 | struct resource xhci_res[CDNS3_XHCI_RESOURCES_NUM]; | ||
| 71 | struct cdns3_usb_regs __iomem *dev_regs; | ||
| 72 | |||
| 73 | struct resource otg_res; | ||
| 74 | struct cdns3_otg_legacy_regs *otg_v0_regs; | ||
| 75 | struct cdns3_otg_regs *otg_v1_regs; | ||
| 76 | struct cdns3_otg_common_regs *otg_regs; | ||
| 77 | #define CDNS3_CONTROLLER_V0 0 | ||
| 78 | #define CDNS3_CONTROLLER_V1 1 | ||
| 79 | u32 version; | ||
| 80 | |||
| 81 | int otg_irq; | ||
| 82 | int dev_irq; | ||
| 83 | struct cdns3_role_driver *roles[USB_ROLE_DEVICE + 1]; | ||
| 84 | enum usb_role role; | ||
| 85 | struct platform_device *host_dev; | ||
| 86 | struct cdns3_device *gadget_dev; | ||
| 87 | struct phy *usb2_phy; | ||
| 88 | struct phy *usb3_phy; | ||
| 89 | /* mutext used in workqueue*/ | ||
| 90 | struct mutex mutex; | ||
| 91 | enum usb_dr_mode dr_mode; | ||
| 92 | struct usb_role_switch *role_sw; | ||
| 93 | int role_override; | ||
| 94 | }; | ||
| 95 | |||
| 96 | int cdns3_hw_role_switch(struct cdns3 *cdns); | ||
| 97 | |||
| 98 | #endif /* __LINUX_CDNS3_CORE_H */ | ||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver. | ||
| 4 | * Debug header file. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2018-2019 Cadence. | ||
| 7 | * | ||
| 8 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 9 | */ | ||
| 10 | #ifndef __LINUX_CDNS3_DEBUG | ||
| 11 | #define __LINUX_CDNS3_DEBUG | ||
| 12 | |||
| 13 | #include "core.h" | ||
| 14 | |||
| 15 | static inline char *cdns3_decode_usb_irq(char *str, | ||
| 16 | enum usb_device_speed speed, | ||
| 17 | u32 usb_ists) | ||
| 18 | { | ||
| 19 | int ret; | ||
| 20 | |||
| 21 | ret = sprintf(str, "IRQ %08x = ", usb_ists); | ||
| 22 | |||
| 23 | if (usb_ists & (USB_ISTS_CON2I | USB_ISTS_CONI)) { | ||
| 24 | ret += sprintf(str + ret, "Connection %s\n", | ||
| 25 | usb_speed_string(speed)); | ||
| 26 | } | ||
| 27 | if (usb_ists & USB_ISTS_DIS2I || usb_ists & USB_ISTS_DISI) | ||
| 28 | ret += sprintf(str + ret, "Disconnection "); | ||
| 29 | if (usb_ists & USB_ISTS_L2ENTI) | ||
| 30 | ret += sprintf(str + ret, "suspended "); | ||
| 31 | if (usb_ists & USB_ISTS_L1ENTI) | ||
| 32 | ret += sprintf(str + ret, "L1 enter "); | ||
| 33 | if (usb_ists & USB_ISTS_L1EXTI) | ||
| 34 | ret += sprintf(str + ret, "L1 exit "); | ||
| 35 | if (usb_ists & USB_ISTS_L2ENTI) | ||
| 36 | ret += sprintf(str + ret, "L2 enter "); | ||
| 37 | if (usb_ists & USB_ISTS_L2EXTI) | ||
| 38 | ret += sprintf(str + ret, "L2 exit "); | ||
| 39 | if (usb_ists & USB_ISTS_U3EXTI) | ||
| 40 | ret += sprintf(str + ret, "U3 exit "); | ||
| 41 | if (usb_ists & USB_ISTS_UWRESI) | ||
| 42 | ret += sprintf(str + ret, "Warm Reset "); | ||
| 43 | if (usb_ists & USB_ISTS_UHRESI) | ||
| 44 | ret += sprintf(str + ret, "Hot Reset "); | ||
| 45 | if (usb_ists & USB_ISTS_U2RESI) | ||
| 46 | ret += sprintf(str + ret, "Reset"); | ||
| 47 | |||
| 48 | return str; | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline char *cdns3_decode_ep_irq(char *str, | ||
| 52 | u32 ep_sts, | ||
| 53 | const char *ep_name) | ||
| 54 | { | ||
| 55 | int ret; | ||
| 56 | |||
| 57 | ret = sprintf(str, "IRQ for %s: %08x ", ep_name, ep_sts); | ||
| 58 | |||
| 59 | if (ep_sts & EP_STS_SETUP) | ||
| 60 | ret += sprintf(str + ret, "SETUP "); | ||
| 61 | if (ep_sts & EP_STS_IOC) | ||
| 62 | ret += sprintf(str + ret, "IOC "); | ||
| 63 | if (ep_sts & EP_STS_ISP) | ||
| 64 | ret += sprintf(str + ret, "ISP "); | ||
| 65 | if (ep_sts & EP_STS_DESCMIS) | ||
| 66 | ret += sprintf(str + ret, "DESCMIS "); | ||
| 67 | if (ep_sts & EP_STS_STREAMR) | ||
| 68 | ret += sprintf(str + ret, "STREAMR "); | ||
| 69 | if (ep_sts & EP_STS_MD_EXIT) | ||
| 70 | ret += sprintf(str + ret, "MD_EXIT "); | ||
| 71 | if (ep_sts & EP_STS_TRBERR) | ||
| 72 | ret += sprintf(str + ret, "TRBERR "); | ||
| 73 | if (ep_sts & EP_STS_NRDY) | ||
| 74 | ret += sprintf(str + ret, "NRDY "); | ||
| 75 | if (ep_sts & EP_STS_PRIME) | ||
| 76 | ret += sprintf(str + ret, "PRIME "); | ||
| 77 | if (ep_sts & EP_STS_SIDERR) | ||
| 78 | ret += sprintf(str + ret, "SIDERRT "); | ||
| 79 | if (ep_sts & EP_STS_OUTSMM) | ||
| 80 | ret += sprintf(str + ret, "OUTSMM "); | ||
| 81 | if (ep_sts & EP_STS_ISOERR) | ||
| 82 | ret += sprintf(str + ret, "ISOERR "); | ||
| 83 | if (ep_sts & EP_STS_IOT) | ||
| 84 | ret += sprintf(str + ret, "IOT "); | ||
| 85 | |||
| 86 | return str; | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline char *cdns3_decode_epx_irq(char *str, | ||
| 90 | char *ep_name, | ||
| 91 | u32 ep_sts) | ||
| 92 | { | ||
| 93 | return cdns3_decode_ep_irq(str, ep_sts, ep_name); | ||
| 94 | } | ||
| 95 | |||
| 96 | static inline char *cdns3_decode_ep0_irq(char *str, | ||
| 97 | int dir, | ||
| 98 | u32 ep_sts) | ||
| 99 | { | ||
| 100 | return cdns3_decode_ep_irq(str, ep_sts, | ||
| 101 | dir ? "ep0IN" : "ep0OUT"); | ||
| 102 | } | ||
| 103 | |||
| 104 | /** | ||
| 105 | * Debug a transfer ring. | ||
| 106 | * | ||
| 107 | * Prints out all TRBs in the endpoint ring, even those after the Link TRB. | ||
| 108 | *. | ||
| 109 | */ | ||
| 110 | static inline char *cdns3_dbg_ring(struct cdns3_endpoint *priv_ep, | ||
| 111 | struct cdns3_trb *ring, char *str) | ||
| 112 | { | ||
| 113 | dma_addr_t addr = priv_ep->trb_pool_dma; | ||
| 114 | struct cdns3_trb *trb; | ||
| 115 | int trb_per_sector; | ||
| 116 | int ret = 0; | ||
| 117 | int i; | ||
| 118 | |||
| 119 | trb_per_sector = GET_TRBS_PER_SEGMENT(priv_ep->type); | ||
| 120 | |||
| 121 | trb = &priv_ep->trb_pool[priv_ep->dequeue]; | ||
| 122 | ret += sprintf(str + ret, "\n\t\tRing contents for %s:", priv_ep->name); | ||
| 123 | |||
| 124 | ret += sprintf(str + ret, | ||
| 125 | "\n\t\tRing deq index: %d, trb: %p (virt), 0x%llx (dma)\n", | ||
| 126 | priv_ep->dequeue, trb, | ||
| 127 | (unsigned long long)cdns3_trb_virt_to_dma(priv_ep, trb)); | ||
| 128 | |||
| 129 | trb = &priv_ep->trb_pool[priv_ep->enqueue]; | ||
| 130 | ret += sprintf(str + ret, | ||
| 131 | "\t\tRing enq index: %d, trb: %p (virt), 0x%llx (dma)\n", | ||
| 132 | priv_ep->enqueue, trb, | ||
| 133 | (unsigned long long)cdns3_trb_virt_to_dma(priv_ep, trb)); | ||
| 134 | |||
| 135 | ret += sprintf(str + ret, | ||
| 136 | "\t\tfree trbs: %d, CCS=%d, PCS=%d\n", | ||
| 137 | priv_ep->free_trbs, priv_ep->ccs, priv_ep->pcs); | ||
| 138 | |||
| 139 | if (trb_per_sector > TRBS_PER_SEGMENT) | ||
| 140 | trb_per_sector = TRBS_PER_SEGMENT; | ||
| 141 | |||
| 142 | if (trb_per_sector > TRBS_PER_SEGMENT) { | ||
| 143 | sprintf(str + ret, "\t\tTo big transfer ring %d\n", | ||
| 144 | trb_per_sector); | ||
| 145 | return str; | ||
| 146 | } | ||
| 147 | |||
| 148 | for (i = 0; i < trb_per_sector; ++i) { | ||
| 149 | trb = &ring[i]; | ||
| 150 | ret += sprintf(str + ret, | ||
| 151 | "\t\t@%pad %08x %08x %08x\n", &addr, | ||
| 152 | le32_to_cpu(trb->buffer), | ||
| 153 | le32_to_cpu(trb->length), | ||
| 154 | le32_to_cpu(trb->control)); | ||
| 155 | addr += sizeof(*trb); | ||
| 156 | } | ||
| 157 | |||
| 158 | return str; | ||
| 159 | } | ||
| 160 | |||
| 161 | #endif /*__LINUX_CDNS3_DEBUG*/ | ||
| @@ -0,0 +1,381 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * Copyright (C) 2019 Texas Instruments | ||
| 7 | * | ||
| 8 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 9 | * Roger Quadros <rogerq@ti.com> | ||
| 10 | * | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/iopoll.h> | ||
| 17 | #include <linux/usb/otg.h> | ||
| 18 | |||
| 19 | #include "gadget.h" | ||
| 20 | #include "drd.h" | ||
| 21 | #include "core.h" | ||
| 22 | |||
| 23 | /** | ||
| 24 | * cdns3_set_mode - change mode of OTG Core | ||
| 25 | * @cdns: pointer to context structure | ||
| 26 | * @mode: selected mode from cdns_role | ||
| 27 | * | ||
| 28 | * Returns 0 on success otherwise negative errno | ||
| 29 | */ | ||
| 30 | int cdns3_set_mode(struct cdns3 *cdns, enum usb_dr_mode mode) | ||
| 31 | { | ||
| 32 | int ret = 0; | ||
| 33 | u32 reg; | ||
| 34 | |||
| 35 | switch (mode) { | ||
| 36 | case USB_DR_MODE_PERIPHERAL: | ||
| 37 | break; | ||
| 38 | case USB_DR_MODE_HOST: | ||
| 39 | break; | ||
| 40 | case USB_DR_MODE_OTG: | ||
| 41 | dev_dbg(cdns->dev, "Set controller to OTG mode\n"); | ||
| 42 | if (cdns->version == CDNS3_CONTROLLER_V1) { | ||
| 43 | reg = readl(&cdns->otg_v1_regs->override); | ||
| 44 | reg |= OVERRIDE_IDPULLUP; | ||
| 45 | writel(reg, &cdns->otg_v1_regs->override); | ||
| 46 | } else { | ||
| 47 | reg = readl(&cdns->otg_v0_regs->ctrl1); | ||
| 48 | reg |= OVERRIDE_IDPULLUP_V0; | ||
| 49 | writel(reg, &cdns->otg_v0_regs->ctrl1); | ||
| 50 | } | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Hardware specification says: "ID_VALUE must be valid within | ||
| 54 | * 50ms after idpullup is set to '1" so driver must wait | ||
| 55 | * 50ms before reading this pin. | ||
| 56 | */ | ||
| 57 | usleep_range(50000, 60000); | ||
| 58 | break; | ||
| 59 | default: | ||
| 60 | dev_err(cdns->dev, "Unsupported mode of operation %d\n", mode); | ||
| 61 | return -EINVAL; | ||
| 62 | } | ||
| 63 | |||
| 64 | return ret; | ||
| 65 | } | ||
| 66 | |||
| 67 | int cdns3_get_id(struct cdns3 *cdns) | ||
| 68 | { | ||
| 69 | int id; | ||
| 70 | |||
| 71 | id = readl(&cdns->otg_regs->sts) & OTGSTS_ID_VALUE; | ||
| 72 | dev_dbg(cdns->dev, "OTG ID: %d", id); | ||
| 73 | |||
| 74 | return id; | ||
| 75 | } | ||
| 76 | |||
| 77 | int cdns3_get_vbus(struct cdns3 *cdns) | ||
| 78 | { | ||
| 79 | int vbus; | ||
| 80 | |||
| 81 | vbus = !!(readl(&cdns->otg_regs->sts) & OTGSTS_VBUS_VALID); | ||
| 82 | dev_dbg(cdns->dev, "OTG VBUS: %d", vbus); | ||
| 83 | |||
| 84 | return vbus; | ||
| 85 | } | ||
| 86 | |||
| 87 | int cdns3_is_host(struct cdns3 *cdns) | ||
| 88 | { | ||
| 89 | if (cdns->dr_mode == USB_DR_MODE_HOST) | ||
| 90 | return 1; | ||
| 91 | else if (!cdns3_get_id(cdns)) | ||
| 92 | return 1; | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | int cdns3_is_device(struct cdns3 *cdns) | ||
| 98 | { | ||
| 99 | if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) | ||
| 100 | return 1; | ||
| 101 | else if (cdns->dr_mode == USB_DR_MODE_OTG) | ||
| 102 | if (cdns3_get_id(cdns)) | ||
| 103 | return 1; | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * cdns3_otg_disable_irq - Disable all OTG interrupts | ||
| 110 | * @cdns: Pointer to controller context structure | ||
| 111 | */ | ||
| 112 | static void cdns3_otg_disable_irq(struct cdns3 *cdns) | ||
| 113 | { | ||
| 114 | writel(0, &cdns->otg_regs->ien); | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * cdns3_otg_enable_irq - enable id and sess_valid interrupts | ||
| 119 | * @cdns: Pointer to controller context structure | ||
| 120 | */ | ||
| 121 | static void cdns3_otg_enable_irq(struct cdns3 *cdns) | ||
| 122 | { | ||
| 123 | writel(OTGIEN_ID_CHANGE_INT | OTGIEN_VBUSVALID_RISE_INT | | ||
| 124 | OTGIEN_VBUSVALID_FALL_INT, &cdns->otg_regs->ien); | ||
| 125 | } | ||
| 126 | |||
| 127 | /** | ||
| 128 | * cdns3_drd_switch_host - start/stop host | ||
| 129 | * @cdns: Pointer to controller context structure | ||
| 130 | * @on: 1 for start, 0 for stop | ||
| 131 | * | ||
| 132 | * Returns 0 on success otherwise negative errno | ||
| 133 | */ | ||
| 134 | int cdns3_drd_switch_host(struct cdns3 *cdns, int on) | ||
| 135 | { | ||
| 136 | int ret, val; | ||
| 137 | u32 reg = OTGCMD_OTG_DIS; | ||
| 138 | |||
| 139 | /* switch OTG core */ | ||
| 140 | if (on) { | ||
| 141 | writel(OTGCMD_HOST_BUS_REQ | reg, &cdns->otg_regs->cmd); | ||
| 142 | |||
| 143 | dev_dbg(cdns->dev, "Waiting till Host mode is turned on\n"); | ||
| 144 | ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val, | ||
| 145 | val & OTGSTS_XHCI_READY, | ||
| 146 | 1, 100000); | ||
| 147 | if (ret) { | ||
| 148 | dev_err(cdns->dev, "timeout waiting for xhci_ready\n"); | ||
| 149 | return ret; | ||
| 150 | } | ||
| 151 | } else { | ||
| 152 | writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP | | ||
| 153 | OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF, | ||
| 154 | &cdns->otg_regs->cmd); | ||
| 155 | /* Waiting till H_IDLE state.*/ | ||
| 156 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, | ||
| 157 | !(val & OTGSTATE_HOST_STATE_MASK), | ||
| 158 | 1, 2000000); | ||
| 159 | } | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | /** | ||
| 165 | * cdns3_drd_switch_gadget - start/stop gadget | ||
| 166 | * @cdns: Pointer to controller context structure | ||
| 167 | * @on: 1 for start, 0 for stop | ||
| 168 | * | ||
| 169 | * Returns 0 on success otherwise negative errno | ||
| 170 | */ | ||
| 171 | int cdns3_drd_switch_gadget(struct cdns3 *cdns, int on) | ||
| 172 | { | ||
| 173 | int ret, val; | ||
| 174 | u32 reg = OTGCMD_OTG_DIS; | ||
| 175 | |||
| 176 | /* switch OTG core */ | ||
| 177 | if (on) { | ||
| 178 | writel(OTGCMD_DEV_BUS_REQ | reg, &cdns->otg_regs->cmd); | ||
| 179 | |||
| 180 | dev_dbg(cdns->dev, "Waiting till Device mode is turned on\n"); | ||
| 181 | |||
| 182 | ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val, | ||
| 183 | val & OTGSTS_DEV_READY, | ||
| 184 | 1, 100000); | ||
| 185 | if (ret) { | ||
| 186 | dev_err(cdns->dev, "timeout waiting for dev_ready\n"); | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | } else { | ||
| 190 | /* | ||
| 191 | * driver should wait at least 10us after disabling Device | ||
| 192 | * before turning-off Device (DEV_BUS_DROP) | ||
| 193 | */ | ||
| 194 | usleep_range(20, 30); | ||
| 195 | writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP | | ||
| 196 | OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF, | ||
| 197 | &cdns->otg_regs->cmd); | ||
| 198 | /* Waiting till DEV_IDLE state.*/ | ||
| 199 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, | ||
| 200 | !(val & OTGSTATE_DEV_STATE_MASK), | ||
| 201 | 1, 2000000); | ||
| 202 | } | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | /** | ||
| 208 | * cdns3_init_otg_mode - initialize drd controller | ||
| 209 | * @cdns: Pointer to controller context structure | ||
| 210 | * | ||
| 211 | * Returns 0 on success otherwise negative errno | ||
| 212 | */ | ||
| 213 | static int cdns3_init_otg_mode(struct cdns3 *cdns) | ||
| 214 | { | ||
| 215 | int ret = 0; | ||
| 216 | |||
| 217 | cdns3_otg_disable_irq(cdns); | ||
| 218 | /* clear all interrupts */ | ||
| 219 | writel(~0, &cdns->otg_regs->ivect); | ||
| 220 | |||
| 221 | ret = cdns3_set_mode(cdns, USB_DR_MODE_OTG); | ||
| 222 | if (ret) | ||
| 223 | return ret; | ||
| 224 | |||
| 225 | cdns3_otg_enable_irq(cdns); | ||
| 226 | return ret; | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | ||
| 230 | * cdns3_drd_update_mode - initialize mode of operation | ||
| 231 | * @cdns: Pointer to controller context structure | ||
| 232 | * | ||
| 233 | * Returns 0 on success otherwise negative errno | ||
| 234 | */ | ||
| 235 | int cdns3_drd_update_mode(struct cdns3 *cdns) | ||
| 236 | { | ||
| 237 | int ret = 0; | ||
| 238 | |||
| 239 | switch (cdns->dr_mode) { | ||
| 240 | case USB_DR_MODE_PERIPHERAL: | ||
| 241 | ret = cdns3_set_mode(cdns, USB_DR_MODE_PERIPHERAL); | ||
| 242 | break; | ||
| 243 | case USB_DR_MODE_HOST: | ||
| 244 | ret = cdns3_set_mode(cdns, USB_DR_MODE_HOST); | ||
| 245 | break; | ||
| 246 | case USB_DR_MODE_OTG: | ||
| 247 | ret = cdns3_init_otg_mode(cdns); | ||
| 248 | break; | ||
| 249 | default: | ||
| 250 | dev_err(cdns->dev, "Unsupported mode of operation %d\n", | ||
| 251 | cdns->dr_mode); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | |||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | static irqreturn_t cdns3_drd_thread_irq(int irq, void *data) | ||
| 259 | { | ||
| 260 | struct cdns3 *cdns = data; | ||
| 261 | |||
| 262 | cdns3_hw_role_switch(cdns); | ||
| 263 | |||
| 264 | return IRQ_HANDLED; | ||
| 265 | } | ||
| 266 | |||
| 267 | /** | ||
| 268 | * cdns3_drd_irq - interrupt handler for OTG events | ||
| 269 | * | ||
| 270 | * @irq: irq number for cdns3 core device | ||
| 271 | * @data: structure of cdns3 | ||
| 272 | * | ||
| 273 | * Returns IRQ_HANDLED or IRQ_NONE | ||
| 274 | */ | ||
| 275 | static irqreturn_t cdns3_drd_irq(int irq, void *data) | ||
| 276 | { | ||
| 277 | irqreturn_t ret = IRQ_NONE; | ||
| 278 | struct cdns3 *cdns = data; | ||
| 279 | u32 reg; | ||
| 280 | |||
| 281 | if (cdns->dr_mode != USB_DR_MODE_OTG) | ||
| 282 | return ret; | ||
| 283 | |||
| 284 | reg = readl(&cdns->otg_regs->ivect); | ||
| 285 | |||
| 286 | if (!reg) | ||
| 287 | return ret; | ||
| 288 | |||
| 289 | if (reg & OTGIEN_ID_CHANGE_INT) { | ||
| 290 | dev_dbg(cdns->dev, "OTG IRQ: new ID: %d\n", | ||
| 291 | cdns3_get_id(cdns)); | ||
| 292 | |||
| 293 | ret = IRQ_WAKE_THREAD; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (reg & (OTGIEN_VBUSVALID_RISE_INT | OTGIEN_VBUSVALID_FALL_INT)) { | ||
| 297 | dev_dbg(cdns->dev, "OTG IRQ: new VBUS: %d\n", | ||
| 298 | cdns3_get_vbus(cdns)); | ||
| 299 | |||
| 300 | ret = IRQ_WAKE_THREAD; | ||
| 301 | } | ||
| 302 | |||
| 303 | writel(~0, &cdns->otg_regs->ivect); | ||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | |||
| 307 | int cdns3_drd_init(struct cdns3 *cdns) | ||
| 308 | { | ||
| 309 | void __iomem *regs; | ||
| 310 | int ret = 0; | ||
| 311 | u32 state; | ||
| 312 | |||
| 313 | regs = devm_ioremap_resource(cdns->dev, &cdns->otg_res); | ||
| 314 | if (IS_ERR(regs)) | ||
| 315 | return PTR_ERR(regs); | ||
| 316 | |||
| 317 | /* Detection of DRD version. Controller has been released | ||
| 318 | * in two versions. Both are similar, but they have same changes | ||
| 319 | * in register maps. | ||
| 320 | * The first register in old version is command register and it's read | ||
| 321 | * only, so driver should read 0 from it. On the other hand, in v1 | ||
| 322 | * the first register contains device ID number which is not set to 0. | ||
| 323 | * Driver uses this fact to detect the proper version of | ||
| 324 | * controller. | ||
| 325 | */ | ||
| 326 | cdns->otg_v0_regs = regs; | ||
| 327 | if (!readl(&cdns->otg_v0_regs->cmd)) { | ||
| 328 | cdns->version = CDNS3_CONTROLLER_V0; | ||
| 329 | cdns->otg_v1_regs = NULL; | ||
| 330 | cdns->otg_regs = regs; | ||
| 331 | writel(1, &cdns->otg_v0_regs->simulate); | ||
| 332 | dev_info(cdns->dev, "DRD version v0 (%08x)\n", | ||
| 333 | readl(&cdns->otg_v0_regs->version)); | ||
| 334 | } else { | ||
| 335 | cdns->otg_v0_regs = NULL; | ||
| 336 | cdns->otg_v1_regs = regs; | ||
| 337 | cdns->otg_regs = (void *)&cdns->otg_v1_regs->cmd; | ||
| 338 | cdns->version = CDNS3_CONTROLLER_V1; | ||
| 339 | writel(1, &cdns->otg_v1_regs->simulate); | ||
| 340 | dev_info(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n", | ||
| 341 | readl(&cdns->otg_v1_regs->did), | ||
| 342 | readl(&cdns->otg_v1_regs->rid)); | ||
| 343 | } | ||
| 344 | |||
| 345 | state = OTGSTS_STRAP(readl(&cdns->otg_regs->sts)); | ||
| 346 | |||
| 347 | /* Update dr_mode according to STRAP configuration. */ | ||
| 348 | cdns->dr_mode = USB_DR_MODE_OTG; | ||
| 349 | if (state == OTGSTS_STRAP_HOST) { | ||
| 350 | dev_dbg(cdns->dev, "Controller strapped to HOST\n"); | ||
| 351 | cdns->dr_mode = USB_DR_MODE_HOST; | ||
| 352 | } else if (state == OTGSTS_STRAP_GADGET) { | ||
| 353 | dev_dbg(cdns->dev, "Controller strapped to PERIPHERAL\n"); | ||
| 354 | cdns->dr_mode = USB_DR_MODE_PERIPHERAL; | ||
| 355 | } | ||
| 356 | |||
| 357 | ret = devm_request_threaded_irq(cdns->dev, cdns->otg_irq, | ||
| 358 | cdns3_drd_irq, | ||
| 359 | cdns3_drd_thread_irq, | ||
| 360 | IRQF_SHARED, | ||
| 361 | dev_name(cdns->dev), cdns); | ||
| 362 | |||
| 363 | if (ret) { | ||
| 364 | dev_err(cdns->dev, "couldn't get otg_irq\n"); | ||
| 365 | return ret; | ||
| 366 | } | ||
| 367 | |||
| 368 | state = readl(&cdns->otg_regs->sts); | ||
| 369 | if (OTGSTS_OTG_NRDY(state) != 0) { | ||
| 370 | dev_err(cdns->dev, "Cadence USB3 OTG device not ready\n"); | ||
| 371 | return -ENODEV; | ||
| 372 | } | ||
| 373 | |||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 377 | int cdns3_drd_exit(struct cdns3 *cdns) | ||
| 378 | { | ||
| 379 | cdns3_otg_disable_irq(cdns); | ||
| 380 | return 0; | ||
| 381 | } | ||
| @@ -0,0 +1,167 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Cadence USB3 DRD header file. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * | ||
| 7 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 8 | */ | ||
| 9 | #ifndef __LINUX_CDNS3_DRD | ||
| 10 | #define __LINUX_CDNS3_DRD | ||
| 11 | |||
| 12 | #include <linux/usb/otg.h> | ||
| 13 | #include <linux/phy/phy.h> | ||
| 14 | #include "core.h" | ||
| 15 | |||
| 16 | /* DRD register interface for version v1. */ | ||
| 17 | struct cdns3_otg_regs { | ||
| 18 | __le32 did; | ||
| 19 | __le32 rid; | ||
| 20 | __le32 capabilities; | ||
| 21 | __le32 reserved1; | ||
| 22 | __le32 cmd; | ||
| 23 | __le32 sts; | ||
| 24 | __le32 state; | ||
| 25 | __le32 reserved2; | ||
| 26 | __le32 ien; | ||
| 27 | __le32 ivect; | ||
| 28 | __le32 refclk; | ||
| 29 | __le32 tmr; | ||
| 30 | __le32 reserved3[4]; | ||
| 31 | __le32 simulate; | ||
| 32 | __le32 override; | ||
| 33 | __le32 susp_ctrl; | ||
| 34 | __le32 reserved4; | ||
| 35 | __le32 anasts; | ||
| 36 | __le32 adp_ramp_time; | ||
| 37 | __le32 ctrl1; | ||
| 38 | __le32 ctrl2; | ||
| 39 | }; | ||
| 40 | |||
| 41 | /* DRD register interface for version v0. */ | ||
| 42 | struct cdns3_otg_legacy_regs { | ||
| 43 | __le32 cmd; | ||
| 44 | __le32 sts; | ||
| 45 | __le32 state; | ||
| 46 | __le32 refclk; | ||
| 47 | __le32 ien; | ||
| 48 | __le32 ivect; | ||
| 49 | __le32 reserved1[3]; | ||
| 50 | __le32 tmr; | ||
| 51 | __le32 reserved2[2]; | ||
| 52 | __le32 version; | ||
| 53 | __le32 capabilities; | ||
| 54 | __le32 reserved3[2]; | ||
| 55 | __le32 simulate; | ||
| 56 | __le32 reserved4[5]; | ||
| 57 | __le32 ctrl1; | ||
| 58 | }; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Common registers interface for both version of DRD. | ||
| 62 | */ | ||
| 63 | struct cdns3_otg_common_regs { | ||
| 64 | __le32 cmd; | ||
| 65 | __le32 sts; | ||
| 66 | __le32 state; | ||
| 67 | __le32 different1; | ||
| 68 | __le32 ien; | ||
| 69 | __le32 ivect; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* CDNS_RID - bitmasks */ | ||
| 73 | #define CDNS_RID(p) ((p) & GENMASK(15, 0)) | ||
| 74 | |||
| 75 | /* CDNS_VID - bitmasks */ | ||
| 76 | #define CDNS_DID(p) ((p) & GENMASK(31, 0)) | ||
| 77 | |||
| 78 | /* OTGCMD - bitmasks */ | ||
| 79 | /* "Request the bus for Device mode. */ | ||
| 80 | #define OTGCMD_DEV_BUS_REQ BIT(0) | ||
| 81 | /* Request the bus for Host mode */ | ||
| 82 | #define OTGCMD_HOST_BUS_REQ BIT(1) | ||
| 83 | /* Enable OTG mode. */ | ||
| 84 | #define OTGCMD_OTG_EN BIT(2) | ||
| 85 | /* Disable OTG mode */ | ||
| 86 | #define OTGCMD_OTG_DIS BIT(3) | ||
| 87 | /*"Configure OTG as A-Device. */ | ||
| 88 | #define OTGCMD_A_DEV_EN BIT(4) | ||
| 89 | /*"Configure OTG as A-Device. */ | ||
| 90 | #define OTGCMD_A_DEV_DIS BIT(5) | ||
| 91 | /* Drop the bus for Device mod e. */ | ||
| 92 | #define OTGCMD_DEV_BUS_DROP BIT(8) | ||
| 93 | /* Drop the bus for Host mode*/ | ||
| 94 | #define OTGCMD_HOST_BUS_DROP BIT(9) | ||
| 95 | /* Power Down USBSS-DEV. */ | ||
| 96 | #define OTGCMD_DEV_POWER_OFF BIT(11) | ||
| 97 | /* Power Down CDNSXHCI. */ | ||
| 98 | #define OTGCMD_HOST_POWER_OFF BIT(12) | ||
| 99 | |||
| 100 | /* OTGIEN - bitmasks */ | ||
| 101 | /* ID change interrupt enable */ | ||
| 102 | #define OTGIEN_ID_CHANGE_INT BIT(0) | ||
| 103 | /* Vbusvalid fall detected interrupt enable.*/ | ||
| 104 | #define OTGIEN_VBUSVALID_RISE_INT BIT(4) | ||
| 105 | /* Vbusvalid fall detected interrupt enable */ | ||
| 106 | #define OTGIEN_VBUSVALID_FALL_INT BIT(5) | ||
| 107 | |||
| 108 | /* OTGSTS - bitmasks */ | ||
| 109 | /* | ||
| 110 | * Current value of the ID pin. It is only valid when idpullup in | ||
| 111 | * OTGCTRL1_TYPE register is set to '1'. | ||
| 112 | */ | ||
| 113 | #define OTGSTS_ID_VALUE BIT(0) | ||
| 114 | /* Current value of the vbus_valid */ | ||
| 115 | #define OTGSTS_VBUS_VALID BIT(1) | ||
| 116 | /* Current value of the b_sess_vld */ | ||
| 117 | #define OTGSTS_SESSION_VALID BIT(2) | ||
| 118 | /*Device mode is active*/ | ||
| 119 | #define OTGSTS_DEV_ACTIVE BIT(3) | ||
| 120 | /* Host mode is active. */ | ||
| 121 | #define OTGSTS_HOST_ACTIVE BIT(4) | ||
| 122 | /* OTG Controller not ready. */ | ||
| 123 | #define OTGSTS_OTG_NRDY_MASK BIT(11) | ||
| 124 | #define OTGSTS_OTG_NRDY(p) ((p) & OTGSTS_OTG_NRDY_MASK) | ||
| 125 | /* | ||
| 126 | * Value of the strap pins. | ||
| 127 | * 000 - no default configuration | ||
| 128 | * 010 - Controller initiall configured as Host | ||
| 129 | * 100 - Controller initially configured as Device | ||
| 130 | */ | ||
| 131 | #define OTGSTS_STRAP(p) (((p) & GENMASK(14, 12)) >> 12) | ||
| 132 | #define OTGSTS_STRAP_NO_DEFAULT_CFG 0x00 | ||
| 133 | #define OTGSTS_STRAP_HOST_OTG 0x01 | ||
| 134 | #define OTGSTS_STRAP_HOST 0x02 | ||
| 135 | #define OTGSTS_STRAP_GADGET 0x04 | ||
| 136 | /* Host mode is turned on. */ | ||
| 137 | #define OTGSTS_XHCI_READY BIT(26) | ||
| 138 | /* "Device mode is turned on .*/ | ||
| 139 | #define OTGSTS_DEV_READY BIT(27) | ||
| 140 | |||
| 141 | /* OTGSTATE- bitmasks */ | ||
| 142 | #define OTGSTATE_DEV_STATE_MASK GENMASK(2, 0) | ||
| 143 | #define OTGSTATE_HOST_STATE_MASK GENMASK(5, 3) | ||
| 144 | #define OTGSTATE_HOST_STATE_IDLE 0x0 | ||
| 145 | #define OTGSTATE_HOST_STATE_VBUS_FALL 0x7 | ||
| 146 | #define OTGSTATE_HOST_STATE(p) (((p) & OTGSTATE_HOST_STATE_MASK) >> 3) | ||
| 147 | |||
| 148 | /* OTGREFCLK - bitmasks */ | ||
| 149 | #define OTGREFCLK_STB_CLK_SWITCH_EN BIT(31) | ||
| 150 | |||
| 151 | /* OVERRIDE - bitmasks */ | ||
| 152 | #define OVERRIDE_IDPULLUP BIT(0) | ||
| 153 | /* Only for CDNS3_CONTROLLER_V0 version */ | ||
| 154 | #define OVERRIDE_IDPULLUP_V0 BIT(24) | ||
| 155 | |||
| 156 | int cdns3_is_host(struct cdns3 *cdns); | ||
| 157 | int cdns3_is_device(struct cdns3 *cdns); | ||
| 158 | int cdns3_get_id(struct cdns3 *cdns); | ||
| 159 | int cdns3_get_vbus(struct cdns3 *cdns); | ||
| 160 | int cdns3_drd_init(struct cdns3 *cdns); | ||
| 161 | int cdns3_drd_exit(struct cdns3 *cdns); | ||
| 162 | int cdns3_drd_update_mode(struct cdns3 *cdns); | ||
| 163 | int cdns3_drd_switch_gadget(struct cdns3 *cdns, int on); | ||
| 164 | int cdns3_drd_switch_host(struct cdns3 *cdns, int on); | ||
| 165 | int cdns3_set_mode(struct cdns3 *cdns, enum usb_dr_mode mode); | ||
| 166 | |||
| 167 | #endif /* __LINUX_CDNS3_DRD */ | ||
| @@ -0,0 +1,886 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver - gadget side. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018 Cadence Design Systems. | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * | ||
| 8 | * Authors: Pawel Jez <pjez@cadence.com>, | ||
| 9 | * Pawel Laszczak <pawell@cadence.com> | ||
| 10 | * Peter Chen <peter.chen@nxp.com> | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/usb/composite.h> | ||
| 14 | #include <linux/iopoll.h> | ||
| 15 | |||
| 16 | #include "gadget.h" | ||
| 17 | #include "trace.h" | ||
| 18 | |||
| 19 | static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = { | ||
| 20 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 21 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 22 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
| 23 | }; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * cdns3_ep0_run_transfer - Do transfer on default endpoint hardware | ||
| 27 | * @priv_dev: extended gadget object | ||
| 28 | * @dma_addr: physical address where data is/will be stored | ||
| 29 | * @length: data length | ||
| 30 | * @erdy: set it to 1 when ERDY packet should be sent - | ||
| 31 | * exit from flow control state | ||
| 32 | */ | ||
| 33 | static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, | ||
| 34 | dma_addr_t dma_addr, | ||
| 35 | unsigned int length, int erdy, int zlp) | ||
| 36 | { | ||
| 37 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; | ||
| 38 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; | ||
| 39 | |||
| 40 | priv_ep->trb_pool[0].buffer = TRB_BUFFER(dma_addr); | ||
| 41 | priv_ep->trb_pool[0].length = TRB_LEN(length); | ||
| 42 | |||
| 43 | if (zlp) { | ||
| 44 | priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_TYPE(TRB_NORMAL); | ||
| 45 | priv_ep->trb_pool[1].buffer = TRB_BUFFER(dma_addr); | ||
| 46 | priv_ep->trb_pool[1].length = TRB_LEN(0); | ||
| 47 | priv_ep->trb_pool[1].control = TRB_CYCLE | TRB_IOC | | ||
| 48 | TRB_TYPE(TRB_NORMAL); | ||
| 49 | } else { | ||
| 50 | priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_IOC | | ||
| 51 | TRB_TYPE(TRB_NORMAL); | ||
| 52 | priv_ep->trb_pool[1].control = 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | trace_cdns3_prepare_trb(priv_ep, priv_ep->trb_pool); | ||
| 56 | |||
| 57 | cdns3_select_ep(priv_dev, priv_dev->ep0_data_dir); | ||
| 58 | |||
| 59 | writel(EP_STS_TRBERR, ®s->ep_sts); | ||
| 60 | writel(EP_TRADDR_TRADDR(priv_ep->trb_pool_dma), ®s->ep_traddr); | ||
| 61 | trace_cdns3_doorbell_ep0(priv_dev->ep0_data_dir ? "ep0in" : "ep0out", | ||
| 62 | readl(®s->ep_traddr)); | ||
| 63 | |||
| 64 | /* TRB should be prepared before starting transfer. */ | ||
| 65 | writel(EP_CMD_DRDY, ®s->ep_cmd); | ||
| 66 | |||
| 67 | /* Resume controller before arming transfer. */ | ||
| 68 | __cdns3_gadget_wakeup(priv_dev); | ||
| 69 | |||
| 70 | if (erdy) | ||
| 71 | writel(EP_CMD_ERDY, &priv_dev->regs->ep_cmd); | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 75 | * cdns3_ep0_delegate_req - Returns status of handling setup packet | ||
| 76 | * Setup is handled by gadget driver | ||
| 77 | * @priv_dev: extended gadget object | ||
| 78 | * @ctrl_req: pointer to received setup packet | ||
| 79 | * | ||
| 80 | * Returns zero on success or negative value on failure | ||
| 81 | */ | ||
| 82 | static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, | ||
| 83 | struct usb_ctrlrequest *ctrl_req) | ||
| 84 | { | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | spin_unlock(&priv_dev->lock); | ||
| 88 | priv_dev->setup_pending = 1; | ||
| 89 | ret = priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); | ||
| 90 | priv_dev->setup_pending = 0; | ||
| 91 | spin_lock(&priv_dev->lock); | ||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) | ||
| 96 | { | ||
| 97 | priv_dev->ep0_data_dir = 0; | ||
| 98 | priv_dev->ep0_stage = CDNS3_SETUP_STAGE; | ||
| 99 | cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, | ||
| 100 | sizeof(struct usb_ctrlrequest), 0, 0); | ||
| 101 | } | ||
| 102 | |||
| 103 | static void cdns3_ep0_complete_setup(struct cdns3_device *priv_dev, | ||
| 104 | u8 send_stall, u8 send_erdy) | ||
| 105 | { | ||
| 106 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; | ||
| 107 | struct usb_request *request; | ||
| 108 | |||
| 109 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 110 | if (request) | ||
| 111 | list_del_init(&request->list); | ||
| 112 | |||
| 113 | if (send_stall) { | ||
| 114 | trace_cdns3_halt(priv_ep, send_stall, 0); | ||
| 115 | /* set_stall on ep0 */ | ||
| 116 | cdns3_select_ep(priv_dev, 0x00); | ||
| 117 | writel(EP_CMD_SSTALL, &priv_dev->regs->ep_cmd); | ||
| 118 | } else { | ||
| 119 | cdns3_prepare_setup_packet(priv_dev); | ||
| 120 | } | ||
| 121 | |||
| 122 | priv_dev->ep0_stage = CDNS3_SETUP_STAGE; | ||
| 123 | writel((send_erdy ? EP_CMD_ERDY : 0) | EP_CMD_REQ_CMPL, | ||
| 124 | &priv_dev->regs->ep_cmd); | ||
| 125 | |||
| 126 | cdns3_allow_enable_l1(priv_dev, 1); | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB request | ||
| 131 | * @priv_dev: extended gadget object | ||
| 132 | * @ctrl_req: pointer to received setup packet | ||
| 133 | * | ||
| 134 | * Returns 0 if success, USB_GADGET_DELAYED_STATUS on deferred status stage, | ||
| 135 | * error code on error | ||
| 136 | */ | ||
| 137 | static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, | ||
| 138 | struct usb_ctrlrequest *ctrl_req) | ||
| 139 | { | ||
| 140 | enum usb_device_state device_state = priv_dev->gadget.state; | ||
| 141 | struct cdns3_endpoint *priv_ep; | ||
| 142 | u32 config = le16_to_cpu(ctrl_req->wValue); | ||
| 143 | int result = 0; | ||
| 144 | int i; | ||
| 145 | |||
| 146 | switch (device_state) { | ||
| 147 | case USB_STATE_ADDRESS: | ||
| 148 | /* Configure non-control EPs */ | ||
| 149 | for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) { | ||
| 150 | priv_ep = priv_dev->eps[i]; | ||
| 151 | if (!priv_ep) | ||
| 152 | continue; | ||
| 153 | |||
| 154 | if (priv_ep->flags & EP_CLAIMED) | ||
| 155 | cdns3_ep_config(priv_ep); | ||
| 156 | } | ||
| 157 | |||
| 158 | result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); | ||
| 159 | |||
| 160 | if (result) | ||
| 161 | return result; | ||
| 162 | |||
| 163 | if (config) { | ||
| 164 | cdns3_set_hw_configuration(priv_dev); | ||
| 165 | } else { | ||
| 166 | cdns3_hw_reset_eps_config(priv_dev); | ||
| 167 | usb_gadget_set_state(&priv_dev->gadget, | ||
| 168 | USB_STATE_ADDRESS); | ||
| 169 | } | ||
| 170 | break; | ||
| 171 | case USB_STATE_CONFIGURED: | ||
| 172 | result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); | ||
| 173 | |||
| 174 | if (!config && !result) { | ||
| 175 | cdns3_hw_reset_eps_config(priv_dev); | ||
| 176 | usb_gadget_set_state(&priv_dev->gadget, | ||
| 177 | USB_STATE_ADDRESS); | ||
| 178 | } | ||
| 179 | break; | ||
| 180 | default: | ||
| 181 | result = -EINVAL; | ||
| 182 | } | ||
| 183 | |||
| 184 | return result; | ||
| 185 | } | ||
| 186 | |||
| 187 | /** | ||
| 188 | * cdns3_req_ep0_set_address - Handling of SET_ADDRESS standard USB request | ||
| 189 | * @priv_dev: extended gadget object | ||
| 190 | * @ctrl_req: pointer to received setup packet | ||
| 191 | * | ||
| 192 | * Returns 0 if success, error code on error | ||
| 193 | */ | ||
| 194 | static int cdns3_req_ep0_set_address(struct cdns3_device *priv_dev, | ||
| 195 | struct usb_ctrlrequest *ctrl_req) | ||
| 196 | { | ||
| 197 | enum usb_device_state device_state = priv_dev->gadget.state; | ||
| 198 | u32 reg; | ||
| 199 | u32 addr; | ||
| 200 | |||
| 201 | addr = le16_to_cpu(ctrl_req->wValue); | ||
| 202 | |||
| 203 | if (addr > USB_DEVICE_MAX_ADDRESS) { | ||
| 204 | dev_err(priv_dev->dev, | ||
| 205 | "Device address (%d) cannot be greater than %d\n", | ||
| 206 | addr, USB_DEVICE_MAX_ADDRESS); | ||
| 207 | return -EINVAL; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (device_state == USB_STATE_CONFIGURED) { | ||
| 211 | dev_err(priv_dev->dev, | ||
| 212 | "can't set_address from configured state\n"); | ||
| 213 | return -EINVAL; | ||
| 214 | } | ||
| 215 | |||
| 216 | reg = readl(&priv_dev->regs->usb_cmd); | ||
| 217 | |||
| 218 | writel(reg | USB_CMD_FADDR(addr) | USB_CMD_SET_ADDR, | ||
| 219 | &priv_dev->regs->usb_cmd); | ||
| 220 | |||
| 221 | usb_gadget_set_state(&priv_dev->gadget, | ||
| 222 | (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | /** | ||
| 228 | * cdns3_req_ep0_get_status - Handling of GET_STATUS standard USB request | ||
| 229 | * @priv_dev: extended gadget object | ||
| 230 | * @ctrl_req: pointer to received setup packet | ||
| 231 | * | ||
| 232 | * Returns 0 if success, error code on error | ||
| 233 | */ | ||
| 234 | static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev, | ||
| 235 | struct usb_ctrlrequest *ctrl) | ||
| 236 | { | ||
| 237 | __le16 *response_pkt; | ||
| 238 | u16 usb_status = 0; | ||
| 239 | u32 recip; | ||
| 240 | |||
| 241 | recip = ctrl->bRequestType & USB_RECIP_MASK; | ||
| 242 | |||
| 243 | switch (recip) { | ||
| 244 | case USB_RECIP_DEVICE: | ||
| 245 | /* self powered */ | ||
| 246 | if (priv_dev->is_selfpowered) | ||
| 247 | usb_status = BIT(USB_DEVICE_SELF_POWERED); | ||
| 248 | |||
| 249 | if (priv_dev->wake_up_flag) | ||
| 250 | usb_status |= BIT(USB_DEVICE_REMOTE_WAKEUP); | ||
| 251 | |||
| 252 | if (priv_dev->gadget.speed != USB_SPEED_SUPER) | ||
| 253 | break; | ||
| 254 | |||
| 255 | if (priv_dev->u1_allowed) | ||
| 256 | usb_status |= BIT(USB_DEV_STAT_U1_ENABLED); | ||
| 257 | |||
| 258 | if (priv_dev->u2_allowed) | ||
| 259 | usb_status |= BIT(USB_DEV_STAT_U2_ENABLED); | ||
| 260 | |||
| 261 | break; | ||
| 262 | case USB_RECIP_INTERFACE: | ||
| 263 | return cdns3_ep0_delegate_req(priv_dev, ctrl); | ||
| 264 | case USB_RECIP_ENDPOINT: | ||
| 265 | /* check if endpoint is stalled */ | ||
| 266 | cdns3_select_ep(priv_dev, ctrl->wIndex); | ||
| 267 | if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts))) | ||
| 268 | usb_status = BIT(USB_ENDPOINT_HALT); | ||
| 269 | break; | ||
| 270 | default: | ||
| 271 | return -EINVAL; | ||
| 272 | } | ||
| 273 | |||
| 274 | response_pkt = (__le16 *)priv_dev->setup_buf; | ||
| 275 | *response_pkt = cpu_to_le16(usb_status); | ||
| 276 | |||
| 277 | cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, | ||
| 278 | sizeof(*response_pkt), 1, 0); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, | ||
| 283 | struct usb_ctrlrequest *ctrl, | ||
| 284 | int set) | ||
| 285 | { | ||
| 286 | enum usb_device_state state; | ||
| 287 | enum usb_device_speed speed; | ||
| 288 | int ret = 0; | ||
| 289 | u32 wValue; | ||
| 290 | u16 tmode; | ||
| 291 | |||
| 292 | wValue = le16_to_cpu(ctrl->wValue); | ||
| 293 | state = priv_dev->gadget.state; | ||
| 294 | speed = priv_dev->gadget.speed; | ||
| 295 | |||
| 296 | switch (wValue) { | ||
| 297 | case USB_DEVICE_REMOTE_WAKEUP: | ||
| 298 | priv_dev->wake_up_flag = !!set; | ||
| 299 | break; | ||
| 300 | case USB_DEVICE_U1_ENABLE: | ||
| 301 | if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) | ||
| 302 | return -EINVAL; | ||
| 303 | |||
| 304 | priv_dev->u1_allowed = !!set; | ||
| 305 | break; | ||
| 306 | case USB_DEVICE_U2_ENABLE: | ||
| 307 | if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) | ||
| 308 | return -EINVAL; | ||
| 309 | |||
| 310 | priv_dev->u2_allowed = !!set; | ||
| 311 | break; | ||
| 312 | case USB_DEVICE_LTM_ENABLE: | ||
| 313 | ret = -EINVAL; | ||
| 314 | break; | ||
| 315 | case USB_DEVICE_TEST_MODE: | ||
| 316 | if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) | ||
| 317 | return -EINVAL; | ||
| 318 | |||
| 319 | tmode = le16_to_cpu(ctrl->wIndex); | ||
| 320 | |||
| 321 | if (!set || (tmode & 0xff) != 0) | ||
| 322 | return -EINVAL; | ||
| 323 | |||
| 324 | switch (tmode >> 8) { | ||
| 325 | case TEST_J: | ||
| 326 | case TEST_K: | ||
| 327 | case TEST_SE0_NAK: | ||
| 328 | case TEST_PACKET: | ||
| 329 | cdns3_ep0_complete_setup(priv_dev, 0, 1); | ||
| 330 | /** | ||
| 331 | * Little delay to give the controller some time | ||
| 332 | * for sending status stage. | ||
| 333 | * This time should be less then 3ms. | ||
| 334 | */ | ||
| 335 | usleep_range(1000, 2000); | ||
| 336 | cdns3_set_register_bit(&priv_dev->regs->usb_cmd, | ||
| 337 | USB_CMD_STMODE | | ||
| 338 | USB_STS_TMODE_SEL(tmode - 1)); | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | ret = -EINVAL; | ||
| 342 | } | ||
| 343 | break; | ||
| 344 | default: | ||
| 345 | ret = -EINVAL; | ||
| 346 | } | ||
| 347 | |||
| 348 | return ret; | ||
| 349 | } | ||
| 350 | |||
| 351 | static int cdns3_ep0_feature_handle_intf(struct cdns3_device *priv_dev, | ||
| 352 | struct usb_ctrlrequest *ctrl, | ||
| 353 | int set) | ||
| 354 | { | ||
| 355 | u32 wValue; | ||
| 356 | int ret = 0; | ||
| 357 | |||
| 358 | wValue = le16_to_cpu(ctrl->wValue); | ||
| 359 | |||
| 360 | switch (wValue) { | ||
| 361 | case USB_INTRF_FUNC_SUSPEND: | ||
| 362 | break; | ||
| 363 | default: | ||
| 364 | ret = -EINVAL; | ||
| 365 | } | ||
| 366 | |||
| 367 | return ret; | ||
| 368 | } | ||
| 369 | |||
| 370 | static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, | ||
| 371 | struct usb_ctrlrequest *ctrl, | ||
| 372 | int set) | ||
| 373 | { | ||
| 374 | struct cdns3_endpoint *priv_ep; | ||
| 375 | int ret = 0; | ||
| 376 | u8 index; | ||
| 377 | |||
| 378 | if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) | ||
| 379 | return -EINVAL; | ||
| 380 | |||
| 381 | if (!(ctrl->wIndex & ~USB_DIR_IN)) | ||
| 382 | return 0; | ||
| 383 | |||
| 384 | index = cdns3_ep_addr_to_index(ctrl->wIndex); | ||
| 385 | priv_ep = priv_dev->eps[index]; | ||
| 386 | |||
| 387 | cdns3_select_ep(priv_dev, ctrl->wIndex); | ||
| 388 | |||
| 389 | if (set) | ||
| 390 | __cdns3_gadget_ep_set_halt(priv_ep); | ||
| 391 | else if (!(priv_ep->flags & EP_WEDGE)) | ||
| 392 | ret = __cdns3_gadget_ep_clear_halt(priv_ep); | ||
| 393 | |||
| 394 | cdns3_select_ep(priv_dev, 0x00); | ||
| 395 | |||
| 396 | return ret; | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 400 | * cdns3_req_ep0_handle_feature - | ||
| 401 | * Handling of GET/SET_FEATURE standard USB request | ||
| 402 | * | ||
| 403 | * @priv_dev: extended gadget object | ||
| 404 | * @ctrl_req: pointer to received setup packet | ||
| 405 | * @set: must be set to 1 for SET_FEATURE request | ||
| 406 | * | ||
| 407 | * Returns 0 if success, error code on error | ||
| 408 | */ | ||
| 409 | static int cdns3_req_ep0_handle_feature(struct cdns3_device *priv_dev, | ||
| 410 | struct usb_ctrlrequest *ctrl, | ||
| 411 | int set) | ||
| 412 | { | ||
| 413 | int ret = 0; | ||
| 414 | u32 recip; | ||
| 415 | |||
| 416 | recip = ctrl->bRequestType & USB_RECIP_MASK; | ||
| 417 | |||
| 418 | switch (recip) { | ||
| 419 | case USB_RECIP_DEVICE: | ||
| 420 | ret = cdns3_ep0_feature_handle_device(priv_dev, ctrl, set); | ||
| 421 | break; | ||
| 422 | case USB_RECIP_INTERFACE: | ||
| 423 | ret = cdns3_ep0_feature_handle_intf(priv_dev, ctrl, set); | ||
| 424 | break; | ||
| 425 | case USB_RECIP_ENDPOINT: | ||
| 426 | ret = cdns3_ep0_feature_handle_endpoint(priv_dev, ctrl, set); | ||
| 427 | break; | ||
| 428 | default: | ||
| 429 | return -EINVAL; | ||
| 430 | } | ||
| 431 | |||
| 432 | return ret; | ||
| 433 | } | ||
| 434 | |||
| 435 | /** | ||
| 436 | * cdns3_req_ep0_set_sel - Handling of SET_SEL standard USB request | ||
| 437 | * @priv_dev: extended gadget object | ||
| 438 | * @ctrl_req: pointer to received setup packet | ||
| 439 | * | ||
| 440 | * Returns 0 if success, error code on error | ||
| 441 | */ | ||
| 442 | static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev, | ||
| 443 | struct usb_ctrlrequest *ctrl_req) | ||
| 444 | { | ||
| 445 | if (priv_dev->gadget.state < USB_STATE_ADDRESS) | ||
| 446 | return -EINVAL; | ||
| 447 | |||
| 448 | if (ctrl_req->wLength != 6) { | ||
| 449 | dev_err(priv_dev->dev, "Set SEL should be 6 bytes, got %d\n", | ||
| 450 | ctrl_req->wLength); | ||
| 451 | return -EINVAL; | ||
| 452 | } | ||
| 453 | |||
| 454 | cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, 6, 1, 0); | ||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | /** | ||
| 459 | * cdns3_req_ep0_set_isoch_delay - | ||
| 460 | * Handling of GET_ISOCH_DELAY standard USB request | ||
| 461 | * @priv_dev: extended gadget object | ||
| 462 | * @ctrl_req: pointer to received setup packet | ||
| 463 | * | ||
| 464 | * Returns 0 if success, error code on error | ||
| 465 | */ | ||
| 466 | static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev, | ||
| 467 | struct usb_ctrlrequest *ctrl_req) | ||
| 468 | { | ||
| 469 | if (ctrl_req->wIndex || ctrl_req->wLength) | ||
| 470 | return -EINVAL; | ||
| 471 | |||
| 472 | priv_dev->isoch_delay = ctrl_req->wValue; | ||
| 473 | |||
| 474 | return 0; | ||
| 475 | } | ||
| 476 | |||
| 477 | /** | ||
| 478 | * cdns3_ep0_standard_request - Handling standard USB requests | ||
| 479 | * @priv_dev: extended gadget object | ||
| 480 | * @ctrl_req: pointer to received setup packet | ||
| 481 | * | ||
| 482 | * Returns 0 if success, error code on error | ||
| 483 | */ | ||
| 484 | static int cdns3_ep0_standard_request(struct cdns3_device *priv_dev, | ||
| 485 | struct usb_ctrlrequest *ctrl_req) | ||
| 486 | { | ||
| 487 | int ret; | ||
| 488 | |||
| 489 | switch (ctrl_req->bRequest) { | ||
| 490 | case USB_REQ_SET_ADDRESS: | ||
| 491 | ret = cdns3_req_ep0_set_address(priv_dev, ctrl_req); | ||
| 492 | break; | ||
| 493 | case USB_REQ_SET_CONFIGURATION: | ||
| 494 | ret = cdns3_req_ep0_set_configuration(priv_dev, ctrl_req); | ||
| 495 | break; | ||
| 496 | case USB_REQ_GET_STATUS: | ||
| 497 | ret = cdns3_req_ep0_get_status(priv_dev, ctrl_req); | ||
| 498 | break; | ||
| 499 | case USB_REQ_CLEAR_FEATURE: | ||
| 500 | ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 0); | ||
| 501 | break; | ||
| 502 | case USB_REQ_SET_FEATURE: | ||
| 503 | ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 1); | ||
| 504 | break; | ||
| 505 | case USB_REQ_SET_SEL: | ||
| 506 | ret = cdns3_req_ep0_set_sel(priv_dev, ctrl_req); | ||
| 507 | break; | ||
| 508 | case USB_REQ_SET_ISOCH_DELAY: | ||
| 509 | ret = cdns3_req_ep0_set_isoch_delay(priv_dev, ctrl_req); | ||
| 510 | break; | ||
| 511 | default: | ||
| 512 | ret = cdns3_ep0_delegate_req(priv_dev, ctrl_req); | ||
| 513 | break; | ||
| 514 | } | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | ||
| 518 | |||
| 519 | static void __pending_setup_status_handler(struct cdns3_device *priv_dev) | ||
| 520 | { | ||
| 521 | struct usb_request *request = priv_dev->pending_status_request; | ||
| 522 | |||
| 523 | if (priv_dev->status_completion_no_call && request && | ||
| 524 | request->complete) { | ||
| 525 | request->complete(&priv_dev->eps[0]->endpoint, request); | ||
| 526 | priv_dev->status_completion_no_call = 0; | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | void cdns3_pending_setup_status_handler(struct work_struct *work) | ||
| 531 | { | ||
| 532 | struct cdns3_device *priv_dev = container_of(work, struct cdns3_device, | ||
| 533 | pending_status_wq); | ||
| 534 | unsigned long flags; | ||
| 535 | |||
| 536 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 537 | __pending_setup_status_handler(priv_dev); | ||
| 538 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 539 | } | ||
| 540 | |||
| 541 | /** | ||
| 542 | * cdns3_ep0_setup_phase - Handling setup USB requests | ||
| 543 | * @priv_dev: extended gadget object | ||
| 544 | */ | ||
| 545 | static void cdns3_ep0_setup_phase(struct cdns3_device *priv_dev) | ||
| 546 | { | ||
| 547 | struct usb_ctrlrequest *ctrl = priv_dev->setup_buf; | ||
| 548 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; | ||
| 549 | int result; | ||
| 550 | |||
| 551 | priv_dev->ep0_data_dir = ctrl->bRequestType & USB_DIR_IN; | ||
| 552 | |||
| 553 | trace_cdns3_ctrl_req(ctrl); | ||
| 554 | |||
| 555 | if (!list_empty(&priv_ep->pending_req_list)) { | ||
| 556 | struct usb_request *request; | ||
| 557 | |||
| 558 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 559 | priv_ep->dir = priv_dev->ep0_data_dir; | ||
| 560 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), | ||
| 561 | -ECONNRESET); | ||
| 562 | } | ||
| 563 | |||
| 564 | if (le16_to_cpu(ctrl->wLength)) | ||
| 565 | priv_dev->ep0_stage = CDNS3_DATA_STAGE; | ||
| 566 | else | ||
| 567 | priv_dev->ep0_stage = CDNS3_STATUS_STAGE; | ||
| 568 | |||
| 569 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | ||
| 570 | result = cdns3_ep0_standard_request(priv_dev, ctrl); | ||
| 571 | else | ||
| 572 | result = cdns3_ep0_delegate_req(priv_dev, ctrl); | ||
| 573 | |||
| 574 | if (result == USB_GADGET_DELAYED_STATUS) | ||
| 575 | return; | ||
| 576 | |||
| 577 | if (result < 0) | ||
| 578 | cdns3_ep0_complete_setup(priv_dev, 1, 1); | ||
| 579 | else if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) | ||
| 580 | cdns3_ep0_complete_setup(priv_dev, 0, 1); | ||
| 581 | } | ||
| 582 | |||
| 583 | static void cdns3_transfer_completed(struct cdns3_device *priv_dev) | ||
| 584 | { | ||
| 585 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; | ||
| 586 | |||
| 587 | if (!list_empty(&priv_ep->pending_req_list)) { | ||
| 588 | struct usb_request *request; | ||
| 589 | |||
| 590 | trace_cdns3_complete_trb(priv_ep, priv_ep->trb_pool); | ||
| 591 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 592 | |||
| 593 | request->actual = | ||
| 594 | TRB_LEN(le32_to_cpu(priv_ep->trb_pool->length)); | ||
| 595 | |||
| 596 | priv_ep->dir = priv_dev->ep0_data_dir; | ||
| 597 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), 0); | ||
| 598 | } | ||
| 599 | |||
| 600 | cdns3_ep0_complete_setup(priv_dev, 0, 0); | ||
| 601 | } | ||
| 602 | |||
| 603 | /** | ||
| 604 | * cdns3_check_new_setup - Check if controller receive new SETUP packet. | ||
| 605 | * @priv_dev: extended gadget object | ||
| 606 | * | ||
| 607 | * The SETUP packet can be kept in on-chip memory or in system memory. | ||
| 608 | */ | ||
| 609 | static bool cdns3_check_new_setup(struct cdns3_device *priv_dev) | ||
| 610 | { | ||
| 611 | u32 ep_sts_reg; | ||
| 612 | |||
| 613 | cdns3_select_ep(priv_dev, 0 | USB_DIR_OUT); | ||
| 614 | ep_sts_reg = readl(&priv_dev->regs->ep_sts); | ||
| 615 | |||
| 616 | return !!(ep_sts_reg & (EP_STS_SETUP | EP_STS_STPWAIT)); | ||
| 617 | } | ||
| 618 | |||
| 619 | /** | ||
| 620 | * cdns3_check_ep0_interrupt_proceed - Processes interrupt related to endpoint 0 | ||
| 621 | * @priv_dev: extended gadget object | ||
| 622 | * @dir: USB_DIR_IN for IN direction, USB_DIR_OUT for OUT direction | ||
| 623 | */ | ||
| 624 | void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir) | ||
| 625 | { | ||
| 626 | u32 ep_sts_reg; | ||
| 627 | |||
| 628 | cdns3_select_ep(priv_dev, dir); | ||
| 629 | |||
| 630 | ep_sts_reg = readl(&priv_dev->regs->ep_sts); | ||
| 631 | writel(ep_sts_reg, &priv_dev->regs->ep_sts); | ||
| 632 | |||
| 633 | trace_cdns3_ep0_irq(priv_dev, ep_sts_reg); | ||
| 634 | |||
| 635 | __pending_setup_status_handler(priv_dev); | ||
| 636 | |||
| 637 | if (ep_sts_reg & EP_STS_SETUP) | ||
| 638 | priv_dev->wait_for_setup = 1; | ||
| 639 | |||
| 640 | if (priv_dev->wait_for_setup && ep_sts_reg & EP_STS_IOC) { | ||
| 641 | priv_dev->wait_for_setup = 0; | ||
| 642 | cdns3_allow_enable_l1(priv_dev, 0); | ||
| 643 | cdns3_ep0_setup_phase(priv_dev); | ||
| 644 | } else if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { | ||
| 645 | priv_dev->ep0_data_dir = dir; | ||
| 646 | cdns3_transfer_completed(priv_dev); | ||
| 647 | } | ||
| 648 | |||
| 649 | if (ep_sts_reg & EP_STS_DESCMIS) { | ||
| 650 | if (dir == 0 && !priv_dev->setup_pending) | ||
| 651 | cdns3_prepare_setup_packet(priv_dev); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | /** | ||
| 656 | * cdns3_gadget_ep0_enable | ||
| 657 | * Function shouldn't be called by gadget driver, | ||
| 658 | * endpoint 0 is allways active | ||
| 659 | */ | ||
| 660 | static int cdns3_gadget_ep0_enable(struct usb_ep *ep, | ||
| 661 | const struct usb_endpoint_descriptor *desc) | ||
| 662 | { | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | |||
| 666 | /** | ||
| 667 | * cdns3_gadget_ep0_disable | ||
| 668 | * Function shouldn't be called by gadget driver, | ||
| 669 | * endpoint 0 is allways active | ||
| 670 | */ | ||
| 671 | static int cdns3_gadget_ep0_disable(struct usb_ep *ep) | ||
| 672 | { | ||
| 673 | return -EINVAL; | ||
| 674 | } | ||
| 675 | |||
| 676 | /** | ||
| 677 | * cdns3_gadget_ep0_set_halt | ||
| 678 | * @ep: pointer to endpoint zero object | ||
| 679 | * @value: 1 for set stall, 0 for clear stall | ||
| 680 | * | ||
| 681 | * Returns 0 | ||
| 682 | */ | ||
| 683 | static int cdns3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | ||
| 684 | { | ||
| 685 | /* TODO */ | ||
| 686 | return 0; | ||
| 687 | } | ||
| 688 | |||
| 689 | /** | ||
| 690 | * cdns3_gadget_ep0_queue Transfer data on endpoint zero | ||
| 691 | * @ep: pointer to endpoint zero object | ||
| 692 | * @request: pointer to request object | ||
| 693 | * @gfp_flags: gfp flags | ||
| 694 | * | ||
| 695 | * Returns 0 on success, error code elsewhere | ||
| 696 | */ | ||
| 697 | static int cdns3_gadget_ep0_queue(struct usb_ep *ep, | ||
| 698 | struct usb_request *request, | ||
| 699 | gfp_t gfp_flags) | ||
| 700 | { | ||
| 701 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 702 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 703 | unsigned long flags; | ||
| 704 | int erdy_sent = 0; | ||
| 705 | int ret = 0; | ||
| 706 | u8 zlp = 0; | ||
| 707 | |||
| 708 | trace_cdns3_ep0_queue(priv_dev, request); | ||
| 709 | |||
| 710 | /* cancel the request if controller receive new SETUP packet. */ | ||
| 711 | if (cdns3_check_new_setup(priv_dev)) | ||
| 712 | return -ECONNRESET; | ||
| 713 | |||
| 714 | /* send STATUS stage. Should be called only for SET_CONFIGURATION */ | ||
| 715 | if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) { | ||
| 716 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 717 | cdns3_select_ep(priv_dev, 0x00); | ||
| 718 | |||
| 719 | erdy_sent = !priv_dev->hw_configured_flag; | ||
| 720 | cdns3_set_hw_configuration(priv_dev); | ||
| 721 | |||
| 722 | if (!erdy_sent) | ||
| 723 | cdns3_ep0_complete_setup(priv_dev, 0, 1); | ||
| 724 | |||
| 725 | cdns3_allow_enable_l1(priv_dev, 1); | ||
| 726 | |||
| 727 | request->actual = 0; | ||
| 728 | priv_dev->status_completion_no_call = true; | ||
| 729 | priv_dev->pending_status_request = request; | ||
| 730 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 731 | |||
| 732 | /* | ||
| 733 | * Since there is no completion interrupt for status stage, | ||
| 734 | * it needs to call ->completion in software after | ||
| 735 | * ep0_queue is back. | ||
| 736 | */ | ||
| 737 | queue_work(system_freezable_wq, &priv_dev->pending_status_wq); | ||
| 738 | return 0; | ||
| 739 | } | ||
| 740 | |||
| 741 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 742 | if (!list_empty(&priv_ep->pending_req_list)) { | ||
| 743 | dev_err(priv_dev->dev, | ||
| 744 | "can't handle multiple requests for ep0\n"); | ||
| 745 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 746 | return -EBUSY; | ||
| 747 | } | ||
| 748 | |||
| 749 | ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, | ||
| 750 | priv_dev->ep0_data_dir); | ||
| 751 | if (ret) { | ||
| 752 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 753 | dev_err(priv_dev->dev, "failed to map request\n"); | ||
| 754 | return -EINVAL; | ||
| 755 | } | ||
| 756 | |||
| 757 | request->status = -EINPROGRESS; | ||
| 758 | list_add_tail(&request->list, &priv_ep->pending_req_list); | ||
| 759 | |||
| 760 | if (request->zero && request->length && | ||
| 761 | (request->length % ep->maxpacket == 0)) | ||
| 762 | zlp = 1; | ||
| 763 | |||
| 764 | cdns3_ep0_run_transfer(priv_dev, request->dma, request->length, 1, zlp); | ||
| 765 | |||
| 766 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 767 | |||
| 768 | return ret; | ||
| 769 | } | ||
| 770 | |||
| 771 | /** | ||
| 772 | * cdns3_gadget_ep_set_wedge Set wedge on selected endpoint | ||
| 773 | * @ep: endpoint object | ||
| 774 | * | ||
| 775 | * Returns 0 | ||
| 776 | */ | ||
| 777 | int cdns3_gadget_ep_set_wedge(struct usb_ep *ep) | ||
| 778 | { | ||
| 779 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 780 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 781 | |||
| 782 | dev_dbg(priv_dev->dev, "Wedge for %s\n", ep->name); | ||
| 783 | cdns3_gadget_ep_set_halt(ep, 1); | ||
| 784 | priv_ep->flags |= EP_WEDGE; | ||
| 785 | |||
| 786 | return 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | const struct usb_ep_ops cdns3_gadget_ep0_ops = { | ||
| 790 | .enable = cdns3_gadget_ep0_enable, | ||
| 791 | .disable = cdns3_gadget_ep0_disable, | ||
| 792 | .alloc_request = cdns3_gadget_ep_alloc_request, | ||
| 793 | .free_request = cdns3_gadget_ep_free_request, | ||
| 794 | .queue = cdns3_gadget_ep0_queue, | ||
| 795 | .dequeue = cdns3_gadget_ep_dequeue, | ||
| 796 | .set_halt = cdns3_gadget_ep0_set_halt, | ||
| 797 | .set_wedge = cdns3_gadget_ep_set_wedge, | ||
| 798 | }; | ||
| 799 | |||
| 800 | /** | ||
| 801 | * cdns3_ep0_config - Configures default endpoint | ||
| 802 | * @priv_dev: extended gadget object | ||
| 803 | * | ||
| 804 | * Functions sets parameters: maximal packet size and enables interrupts | ||
| 805 | */ | ||
| 806 | void cdns3_ep0_config(struct cdns3_device *priv_dev) | ||
| 807 | { | ||
| 808 | struct cdns3_usb_regs __iomem *regs; | ||
| 809 | struct cdns3_endpoint *priv_ep; | ||
| 810 | u32 max_packet_size = 64; | ||
| 811 | |||
| 812 | regs = priv_dev->regs; | ||
| 813 | |||
| 814 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) | ||
| 815 | max_packet_size = 512; | ||
| 816 | |||
| 817 | priv_ep = priv_dev->eps[0]; | ||
| 818 | |||
| 819 | if (!list_empty(&priv_ep->pending_req_list)) { | ||
| 820 | struct usb_request *request; | ||
| 821 | |||
| 822 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 823 | list_del_init(&request->list); | ||
| 824 | } | ||
| 825 | |||
| 826 | priv_dev->u1_allowed = 0; | ||
| 827 | priv_dev->u2_allowed = 0; | ||
| 828 | |||
| 829 | priv_dev->gadget.ep0->maxpacket = max_packet_size; | ||
| 830 | cdns3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(max_packet_size); | ||
| 831 | |||
| 832 | /* init ep out */ | ||
| 833 | cdns3_select_ep(priv_dev, USB_DIR_OUT); | ||
| 834 | |||
| 835 | if (priv_dev->dev_ver >= DEV_VER_V3) { | ||
| 836 | cdns3_set_register_bit(&priv_dev->regs->dtrans, | ||
| 837 | BIT(0) | BIT(16)); | ||
| 838 | cdns3_set_register_bit(&priv_dev->regs->tdl_from_trb, | ||
| 839 | BIT(0) | BIT(16)); | ||
| 840 | } | ||
| 841 | |||
| 842 | writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), | ||
| 843 | ®s->ep_cfg); | ||
| 844 | |||
| 845 | writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN, | ||
| 846 | ®s->ep_sts_en); | ||
| 847 | |||
| 848 | /* init ep in */ | ||
| 849 | cdns3_select_ep(priv_dev, USB_DIR_IN); | ||
| 850 | |||
| 851 | writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size), | ||
| 852 | ®s->ep_cfg); | ||
| 853 | |||
| 854 | writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, ®s->ep_sts_en); | ||
| 855 | |||
| 856 | cdns3_set_register_bit(®s->usb_conf, USB_CONF_U1DS | USB_CONF_U2DS); | ||
| 857 | } | ||
| 858 | |||
| 859 | /** | ||
| 860 | * cdns3_init_ep0 Initializes software endpoint 0 of gadget | ||
| 861 | * @priv_dev: extended gadget object | ||
| 862 | * @ep_priv: extended endpoint object | ||
| 863 | * | ||
| 864 | * Returns 0 on success else error code. | ||
| 865 | */ | ||
| 866 | int cdns3_init_ep0(struct cdns3_device *priv_dev, | ||
| 867 | struct cdns3_endpoint *priv_ep) | ||
| 868 | { | ||
| 869 | sprintf(priv_ep->name, "ep0"); | ||
| 870 | |||
| 871 | /* fill linux fields */ | ||
| 872 | priv_ep->endpoint.ops = &cdns3_gadget_ep0_ops; | ||
| 873 | priv_ep->endpoint.maxburst = 1; | ||
| 874 | usb_ep_set_maxpacket_limit(&priv_ep->endpoint, | ||
| 875 | CDNS3_EP0_MAX_PACKET_LIMIT); | ||
| 876 | priv_ep->endpoint.address = 0; | ||
| 877 | priv_ep->endpoint.caps.type_control = 1; | ||
| 878 | priv_ep->endpoint.caps.dir_in = 1; | ||
| 879 | priv_ep->endpoint.caps.dir_out = 1; | ||
| 880 | priv_ep->endpoint.name = priv_ep->name; | ||
| 881 | priv_ep->endpoint.desc = &cdns3_gadget_ep0_desc; | ||
| 882 | priv_dev->gadget.ep0 = &priv_ep->endpoint; | ||
| 883 | priv_ep->type = USB_ENDPOINT_XFER_CONTROL; | ||
| 884 | |||
| 885 | return cdns3_allocate_trb_pool(priv_ep); | ||
| 886 | } | ||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver - Gadget Export APIs. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017 NXP | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * | ||
| 8 | * Authors: Peter Chen <peter.chen@nxp.com> | ||
| 9 | */ | ||
| 10 | #ifndef __LINUX_CDNS3_GADGET_EXPORT | ||
| 11 | #define __LINUX_CDNS3_GADGET_EXPORT | ||
| 12 | |||
| 13 | #ifdef CONFIG_USB_CDNS3_GADGET | ||
| 14 | |||
| 15 | int cdns3_gadget_init(struct cdns3 *cdns); | ||
| 16 | void cdns3_gadget_exit(struct cdns3 *cdns); | ||
| 17 | #else | ||
| 18 | |||
| 19 | static inline int cdns3_gadget_init(struct cdns3 *cdns) | ||
| 20 | { | ||
| 21 | return -ENXIO; | ||
| 22 | } | ||
| 23 | |||
| 24 | static inline void cdns3_gadget_exit(struct cdns3 *cdns) { } | ||
| 25 | |||
| 26 | #endif | ||
| 27 | |||
| 28 | #endif /* __LINUX_CDNS3_GADGET_EXPORT */ | ||
| @@ -0,0 +1,2744 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver - gadget side. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence Design Systems. | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * | ||
| 8 | * Authors: Pawel Jez <pjez@cadence.com>, | ||
| 9 | * Pawel Laszczak <pawell@cadence.com> | ||
| 10 | * Peter Chen <peter.chen@nxp.com> | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* | ||
| 14 | * Work around 1: | ||
| 15 | * At some situations, the controller may get stale data address in TRB | ||
| 16 | * at below sequences: | ||
| 17 | * 1. Controller read TRB includes data address | ||
| 18 | * 2. Software updates TRBs includes data address and Cycle bit | ||
| 19 | * 3. Controller read TRB which includes Cycle bit | ||
| 20 | * 4. DMA run with stale data address | ||
| 21 | * | ||
| 22 | * To fix this problem, driver needs to make the first TRB in TD as invalid. | ||
| 23 | * After preparing all TRBs driver needs to check the position of DMA and | ||
| 24 | * if the DMA point to the first just added TRB and doorbell is 1, | ||
| 25 | * then driver must defer making this TRB as valid. This TRB will be make | ||
| 26 | * as valid during adding next TRB only if DMA is stopped or at TRBERR | ||
| 27 | * interrupt. | ||
| 28 | * | ||
| 29 | * Issue has been fixed in DEV_VER_V3 version of controller. | ||
| 30 | * | ||
| 31 | * Work around 2: | ||
| 32 | * Controller for OUT endpoints has shared on-chip buffers for all incoming | ||
| 33 | * packets, including ep0out. It's FIFO buffer, so packets must be handle by DMA | ||
| 34 | * in correct order. If the first packet in the buffer will not be handled, | ||
| 35 | * then the following packets directed for other endpoints and functions | ||
| 36 | * will be blocked. | ||
| 37 | * Additionally the packets directed to one endpoint can block entire on-chip | ||
| 38 | * buffers. In this case transfer to other endpoints also will blocked. | ||
| 39 | * | ||
| 40 | * To resolve this issue after raising the descriptor missing interrupt | ||
| 41 | * driver prepares internal usb_request object and use it to arm DMA transfer. | ||
| 42 | * | ||
| 43 | * The problematic situation was observed in case when endpoint has been enabled | ||
| 44 | * but no usb_request were queued. Driver try detects such endpoints and will | ||
| 45 | * use this workaround only for these endpoint. | ||
| 46 | * | ||
| 47 | * Driver use limited number of buffer. This number can be set by macro | ||
| 48 | * CDNS3_WA2_NUM_BUFFERS. | ||
| 49 | * | ||
| 50 | * Such blocking situation was observed on ACM gadget. For this function | ||
| 51 | * host send OUT data packet but ACM function is not prepared for this packet. | ||
| 52 | * It's cause that buffer placed in on chip memory block transfer to other | ||
| 53 | * endpoints. | ||
| 54 | * | ||
| 55 | * Issue has been fixed in DEV_VER_V2 version of controller. | ||
| 56 | * | ||
| 57 | */ | ||
| 58 | |||
| 59 | #include <linux/dma-mapping.h> | ||
| 60 | #include <linux/usb/gadget.h> | ||
| 61 | #include <linux/module.h> | ||
| 62 | #include <linux/iopoll.h> | ||
| 63 | |||
| 64 | #include "core.h" | ||
| 65 | #include "gadget-export.h" | ||
| 66 | #include "gadget.h" | ||
| 67 | #include "trace.h" | ||
| 68 | #include "drd.h" | ||
| 69 | |||
| 70 | static int __cdns3_gadget_ep_queue(struct usb_ep *ep, | ||
| 71 | struct usb_request *request, | ||
| 72 | gfp_t gfp_flags); | ||
| 73 | |||
| 74 | /** | ||
| 75 | * cdns3_set_register_bit - set bit in given register. | ||
| 76 | * @ptr: address of device controller register to be read and changed | ||
| 77 | * @mask: bits requested to set | ||
| 78 | */ | ||
| 79 | void cdns3_set_register_bit(void __iomem *ptr, u32 mask) | ||
| 80 | { | ||
| 81 | mask = readl(ptr) | mask; | ||
| 82 | writel(mask, ptr); | ||
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * cdns3_ep_addr_to_index - Macro converts endpoint address to | ||
| 87 | * index of endpoint object in cdns3_device.eps[] container | ||
| 88 | * @ep_addr: endpoint address for which endpoint object is required | ||
| 89 | * | ||
| 90 | */ | ||
| 91 | u8 cdns3_ep_addr_to_index(u8 ep_addr) | ||
| 92 | { | ||
| 93 | return (((ep_addr & 0x7F)) + ((ep_addr & USB_DIR_IN) ? 16 : 0)); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int cdns3_get_dma_pos(struct cdns3_device *priv_dev, | ||
| 97 | struct cdns3_endpoint *priv_ep) | ||
| 98 | { | ||
| 99 | int dma_index; | ||
| 100 | |||
| 101 | dma_index = readl(&priv_dev->regs->ep_traddr) - priv_ep->trb_pool_dma; | ||
| 102 | |||
| 103 | return dma_index / TRB_SIZE; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * cdns3_next_request - returns next request from list | ||
| 108 | * @list: list containing requests | ||
| 109 | * | ||
| 110 | * Returns request or NULL if no requests in list | ||
| 111 | */ | ||
| 112 | struct usb_request *cdns3_next_request(struct list_head *list) | ||
| 113 | { | ||
| 114 | return list_first_entry_or_null(list, struct usb_request, list); | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * cdns3_next_align_buf - returns next buffer from list | ||
| 119 | * @list: list containing buffers | ||
| 120 | * | ||
| 121 | * Returns buffer or NULL if no buffers in list | ||
| 122 | */ | ||
| 123 | struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) | ||
| 124 | { | ||
| 125 | return list_first_entry_or_null(list, struct cdns3_aligned_buf, list); | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * cdns3_next_priv_request - returns next request from list | ||
| 130 | * @list: list containing requests | ||
| 131 | * | ||
| 132 | * Returns request or NULL if no requests in list | ||
| 133 | */ | ||
| 134 | struct cdns3_request *cdns3_next_priv_request(struct list_head *list) | ||
| 135 | { | ||
| 136 | return list_first_entry_or_null(list, struct cdns3_request, list); | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * select_ep - selects endpoint | ||
| 141 | * @priv_dev: extended gadget object | ||
| 142 | * @ep: endpoint address | ||
| 143 | */ | ||
| 144 | void cdns3_select_ep(struct cdns3_device *priv_dev, u32 ep) | ||
| 145 | { | ||
| 146 | if (priv_dev->selected_ep == ep) | ||
| 147 | return; | ||
| 148 | |||
| 149 | priv_dev->selected_ep = ep; | ||
| 150 | writel(ep, &priv_dev->regs->ep_sel); | ||
| 151 | } | ||
| 152 | |||
| 153 | dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, | ||
| 154 | struct cdns3_trb *trb) | ||
| 155 | { | ||
| 156 | u32 offset = (char *)trb - (char *)priv_ep->trb_pool; | ||
| 157 | |||
| 158 | return priv_ep->trb_pool_dma + offset; | ||
| 159 | } | ||
| 160 | |||
| 161 | int cdns3_ring_size(struct cdns3_endpoint *priv_ep) | ||
| 162 | { | ||
| 163 | switch (priv_ep->type) { | ||
| 164 | case USB_ENDPOINT_XFER_ISOC: | ||
| 165 | return TRB_ISO_RING_SIZE; | ||
| 166 | case USB_ENDPOINT_XFER_CONTROL: | ||
| 167 | return TRB_CTRL_RING_SIZE; | ||
| 168 | default: | ||
| 169 | return TRB_RING_SIZE; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | /** | ||
| 174 | * cdns3_allocate_trb_pool - Allocates TRB's pool for selected endpoint | ||
| 175 | * @priv_ep: endpoint object | ||
| 176 | * | ||
| 177 | * Function will return 0 on success or -ENOMEM on allocation error | ||
| 178 | */ | ||
| 179 | int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) | ||
| 180 | { | ||
| 181 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 182 | int ring_size = cdns3_ring_size(priv_ep); | ||
| 183 | struct cdns3_trb *link_trb; | ||
| 184 | |||
| 185 | if (!priv_ep->trb_pool) { | ||
| 186 | priv_ep->trb_pool = dma_alloc_coherent(priv_dev->sysdev, | ||
| 187 | ring_size, | ||
| 188 | &priv_ep->trb_pool_dma, | ||
| 189 | GFP_DMA32 | GFP_ATOMIC); | ||
| 190 | if (!priv_ep->trb_pool) | ||
| 191 | return -ENOMEM; | ||
| 192 | } else { | ||
| 193 | memset(priv_ep->trb_pool, 0, ring_size); | ||
| 194 | } | ||
| 195 | |||
| 196 | if (!priv_ep->num) | ||
| 197 | return 0; | ||
| 198 | |||
| 199 | priv_ep->num_trbs = ring_size / TRB_SIZE; | ||
| 200 | /* Initialize the last TRB as Link TRB. */ | ||
| 201 | link_trb = (priv_ep->trb_pool + (priv_ep->num_trbs - 1)); | ||
| 202 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma); | ||
| 203 | link_trb->control = TRB_CYCLE | TRB_TYPE(TRB_LINK) | TRB_TOGGLE; | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) | ||
| 209 | { | ||
| 210 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 211 | |||
| 212 | if (priv_ep->trb_pool) { | ||
| 213 | dma_free_coherent(priv_dev->sysdev, | ||
| 214 | cdns3_ring_size(priv_ep), | ||
| 215 | priv_ep->trb_pool, priv_ep->trb_pool_dma); | ||
| 216 | priv_ep->trb_pool = NULL; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /** | ||
| 221 | * cdns3_ep_stall_flush - Stalls and flushes selected endpoint | ||
| 222 | * @priv_ep: endpoint object | ||
| 223 | * | ||
| 224 | * Endpoint must be selected before call to this function | ||
| 225 | */ | ||
| 226 | static void cdns3_ep_stall_flush(struct cdns3_endpoint *priv_ep) | ||
| 227 | { | ||
| 228 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 229 | int val; | ||
| 230 | |||
| 231 | trace_cdns3_halt(priv_ep, 1, 1); | ||
| 232 | |||
| 233 | writel(EP_CMD_DFLUSH | EP_CMD_ERDY | EP_CMD_SSTALL, | ||
| 234 | &priv_dev->regs->ep_cmd); | ||
| 235 | |||
| 236 | /* wait for DFLUSH cleared */ | ||
| 237 | readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, | ||
| 238 | !(val & EP_CMD_DFLUSH), 1, 1000); | ||
| 239 | priv_ep->flags |= EP_STALLED; | ||
| 240 | priv_ep->flags &= ~EP_STALL_PENDING; | ||
| 241 | } | ||
| 242 | |||
| 243 | /** | ||
| 244 | * cdns3_hw_reset_eps_config - reset endpoints configuration kept by controller. | ||
| 245 | * @priv_dev: extended gadget object | ||
| 246 | */ | ||
| 247 | void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev) | ||
| 248 | { | ||
| 249 | writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf); | ||
| 250 | |||
| 251 | cdns3_allow_enable_l1(priv_dev, 0); | ||
| 252 | priv_dev->hw_configured_flag = 0; | ||
| 253 | priv_dev->onchip_used_size = 0; | ||
| 254 | priv_dev->out_mem_is_allocated = 0; | ||
| 255 | priv_dev->wait_for_setup = 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | /** | ||
| 259 | * cdns3_ep_inc_trb - increment a trb index. | ||
| 260 | * @index: Pointer to the TRB index to increment. | ||
| 261 | * @cs: Cycle state | ||
| 262 | * @trb_in_seg: number of TRBs in segment | ||
| 263 | * | ||
| 264 | * The index should never point to the link TRB. After incrementing, | ||
| 265 | * if it is point to the link TRB, wrap around to the beginning and revert | ||
| 266 | * cycle state bit The | ||
| 267 | * link TRB is always at the last TRB entry. | ||
| 268 | */ | ||
| 269 | static void cdns3_ep_inc_trb(int *index, u8 *cs, int trb_in_seg) | ||
| 270 | { | ||
| 271 | (*index)++; | ||
| 272 | if (*index == (trb_in_seg - 1)) { | ||
| 273 | *index = 0; | ||
| 274 | *cs ^= 1; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | /** | ||
| 279 | * cdns3_ep_inc_enq - increment endpoint's enqueue pointer | ||
| 280 | * @priv_ep: The endpoint whose enqueue pointer we're incrementing | ||
| 281 | */ | ||
| 282 | static void cdns3_ep_inc_enq(struct cdns3_endpoint *priv_ep) | ||
| 283 | { | ||
| 284 | priv_ep->free_trbs--; | ||
| 285 | cdns3_ep_inc_trb(&priv_ep->enqueue, &priv_ep->pcs, priv_ep->num_trbs); | ||
| 286 | } | ||
| 287 | |||
| 288 | /** | ||
| 289 | * cdns3_ep_inc_deq - increment endpoint's dequeue pointer | ||
| 290 | * @priv_ep: The endpoint whose dequeue pointer we're incrementing | ||
| 291 | */ | ||
| 292 | static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) | ||
| 293 | { | ||
| 294 | priv_ep->free_trbs++; | ||
| 295 | cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); | ||
| 296 | } | ||
| 297 | |||
| 298 | void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) | ||
| 299 | { | ||
| 300 | struct cdns3_endpoint *priv_ep = priv_req->priv_ep; | ||
| 301 | int current_trb = priv_req->start_trb; | ||
| 302 | |||
| 303 | while (current_trb != priv_req->end_trb) { | ||
| 304 | cdns3_ep_inc_deq(priv_ep); | ||
| 305 | current_trb = priv_ep->dequeue; | ||
| 306 | } | ||
| 307 | |||
| 308 | cdns3_ep_inc_deq(priv_ep); | ||
| 309 | } | ||
| 310 | |||
| 311 | /** | ||
| 312 | * cdns3_allow_enable_l1 - enable/disable permits to transition to L1. | ||
| 313 | * @priv_dev: Extended gadget object | ||
| 314 | * @enable: Enable/disable permit to transition to L1. | ||
| 315 | * | ||
| 316 | * If bit USB_CONF_L1EN is set and device receive Extended Token packet, | ||
| 317 | * then controller answer with ACK handshake. | ||
| 318 | * If bit USB_CONF_L1DS is set and device receive Extended Token packet, | ||
| 319 | * then controller answer with NYET handshake. | ||
| 320 | */ | ||
| 321 | void cdns3_allow_enable_l1(struct cdns3_device *priv_dev, int enable) | ||
| 322 | { | ||
| 323 | if (enable) | ||
| 324 | writel(USB_CONF_L1EN, &priv_dev->regs->usb_conf); | ||
| 325 | else | ||
| 326 | writel(USB_CONF_L1DS, &priv_dev->regs->usb_conf); | ||
| 327 | } | ||
| 328 | |||
| 329 | enum usb_device_speed cdns3_get_speed(struct cdns3_device *priv_dev) | ||
| 330 | { | ||
| 331 | u32 reg; | ||
| 332 | |||
| 333 | reg = readl(&priv_dev->regs->usb_sts); | ||
| 334 | |||
| 335 | if (DEV_SUPERSPEED(reg)) | ||
| 336 | return USB_SPEED_SUPER; | ||
| 337 | else if (DEV_HIGHSPEED(reg)) | ||
| 338 | return USB_SPEED_HIGH; | ||
| 339 | else if (DEV_FULLSPEED(reg)) | ||
| 340 | return USB_SPEED_FULL; | ||
| 341 | else if (DEV_LOWSPEED(reg)) | ||
| 342 | return USB_SPEED_LOW; | ||
| 343 | return USB_SPEED_UNKNOWN; | ||
| 344 | } | ||
| 345 | |||
| 346 | /** | ||
| 347 | * cdns3_start_all_request - add to ring all request not started | ||
| 348 | * @priv_dev: Extended gadget object | ||
| 349 | * @priv_ep: The endpoint for whom request will be started. | ||
| 350 | * | ||
| 351 | * Returns return ENOMEM if transfer ring i not enough TRBs to start | ||
| 352 | * all requests. | ||
| 353 | */ | ||
| 354 | static int cdns3_start_all_request(struct cdns3_device *priv_dev, | ||
| 355 | struct cdns3_endpoint *priv_ep) | ||
| 356 | { | ||
| 357 | struct usb_request *request; | ||
| 358 | int ret = 0; | ||
| 359 | |||
| 360 | while (!list_empty(&priv_ep->deferred_req_list)) { | ||
| 361 | request = cdns3_next_request(&priv_ep->deferred_req_list); | ||
| 362 | |||
| 363 | ret = cdns3_ep_run_transfer(priv_ep, request); | ||
| 364 | if (ret) | ||
| 365 | return ret; | ||
| 366 | |||
| 367 | list_del(&request->list); | ||
| 368 | list_add_tail(&request->list, | ||
| 369 | &priv_ep->pending_req_list); | ||
| 370 | } | ||
| 371 | |||
| 372 | priv_ep->flags &= ~EP_RING_FULL; | ||
| 373 | return ret; | ||
| 374 | } | ||
| 375 | |||
| 376 | /* | ||
| 377 | * WA2: Set flag for all not ISOC OUT endpoints. If this flag is set | ||
| 378 | * driver try to detect whether endpoint need additional internal | ||
| 379 | * buffer for unblocking on-chip FIFO buffer. This flag will be cleared | ||
| 380 | * if before first DESCMISS interrupt the DMA will be armed. | ||
| 381 | */ | ||
| 382 | #define cdns3_wa2_enable_detection(priv_dev, ep_priv, reg) do { \ | ||
| 383 | if (!priv_ep->dir && priv_ep->type != USB_ENDPOINT_XFER_ISOC) { \ | ||
| 384 | priv_ep->flags |= EP_QUIRK_EXTRA_BUF_DET; \ | ||
| 385 | (reg) |= EP_STS_EN_DESCMISEN; \ | ||
| 386 | } } while (0) | ||
| 387 | |||
| 388 | /** | ||
| 389 | * cdns3_wa2_descmiss_copy_data copy data from internal requests to | ||
| 390 | * request queued by class driver. | ||
| 391 | * @priv_ep: extended endpoint object | ||
| 392 | * @request: request object | ||
| 393 | */ | ||
| 394 | static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, | ||
| 395 | struct usb_request *request) | ||
| 396 | { | ||
| 397 | struct usb_request *descmiss_req; | ||
| 398 | struct cdns3_request *descmiss_priv_req; | ||
| 399 | |||
| 400 | while (!list_empty(&priv_ep->wa2_descmiss_req_list)) { | ||
| 401 | int chunk_end; | ||
| 402 | int length; | ||
| 403 | |||
| 404 | descmiss_priv_req = | ||
| 405 | cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); | ||
| 406 | descmiss_req = &descmiss_priv_req->request; | ||
| 407 | |||
| 408 | /* driver can't touch pending request */ | ||
| 409 | if (descmiss_priv_req->flags & REQUEST_PENDING) | ||
| 410 | break; | ||
| 411 | |||
| 412 | chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; | ||
| 413 | length = request->actual + descmiss_req->actual; | ||
| 414 | |||
| 415 | request->status = descmiss_req->status; | ||
| 416 | |||
| 417 | if (length <= request->length) { | ||
| 418 | memcpy(&((u8 *)request->buf)[request->actual], | ||
| 419 | descmiss_req->buf, | ||
| 420 | descmiss_req->actual); | ||
| 421 | request->actual = length; | ||
| 422 | } else { | ||
| 423 | /* It should never occures */ | ||
| 424 | request->status = -ENOMEM; | ||
| 425 | } | ||
| 426 | |||
| 427 | list_del_init(&descmiss_priv_req->list); | ||
| 428 | |||
| 429 | kfree(descmiss_req->buf); | ||
| 430 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, descmiss_req); | ||
| 431 | --priv_ep->wa2_counter; | ||
| 432 | |||
| 433 | if (!chunk_end) | ||
| 434 | break; | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, | ||
| 439 | struct cdns3_endpoint *priv_ep, | ||
| 440 | struct cdns3_request *priv_req) | ||
| 441 | { | ||
| 442 | if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN && | ||
| 443 | priv_req->flags & REQUEST_INTERNAL) { | ||
| 444 | struct usb_request *req; | ||
| 445 | |||
| 446 | req = cdns3_next_request(&priv_ep->deferred_req_list); | ||
| 447 | |||
| 448 | priv_ep->descmis_req = NULL; | ||
| 449 | |||
| 450 | if (!req) | ||
| 451 | return NULL; | ||
| 452 | |||
| 453 | cdns3_wa2_descmiss_copy_data(priv_ep, req); | ||
| 454 | if (!(priv_ep->flags & EP_QUIRK_END_TRANSFER) && | ||
| 455 | req->length != req->actual) { | ||
| 456 | /* wait for next part of transfer */ | ||
| 457 | return NULL; | ||
| 458 | } | ||
| 459 | |||
| 460 | if (req->status == -EINPROGRESS) | ||
| 461 | req->status = 0; | ||
| 462 | |||
| 463 | list_del_init(&req->list); | ||
| 464 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 465 | return req; | ||
| 466 | } | ||
| 467 | |||
| 468 | return &priv_req->request; | ||
| 469 | } | ||
| 470 | |||
| 471 | int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev, | ||
| 472 | struct cdns3_endpoint *priv_ep, | ||
| 473 | struct cdns3_request *priv_req) | ||
| 474 | { | ||
| 475 | int deferred = 0; | ||
| 476 | |||
| 477 | /* | ||
| 478 | * If transfer was queued before DESCMISS appear than we | ||
| 479 | * can disable handling of DESCMISS interrupt. Driver assumes that it | ||
| 480 | * can disable special treatment for this endpoint. | ||
| 481 | */ | ||
| 482 | if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { | ||
| 483 | u32 reg; | ||
| 484 | |||
| 485 | cdns3_select_ep(priv_dev, priv_ep->num | priv_ep->dir); | ||
| 486 | priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; | ||
| 487 | reg = readl(&priv_dev->regs->ep_sts_en); | ||
| 488 | reg &= ~EP_STS_EN_DESCMISEN; | ||
| 489 | trace_cdns3_wa2(priv_ep, "workaround disabled\n"); | ||
| 490 | writel(reg, &priv_dev->regs->ep_sts_en); | ||
| 491 | } | ||
| 492 | |||
| 493 | if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { | ||
| 494 | u8 pending_empty = list_empty(&priv_ep->pending_req_list); | ||
| 495 | u8 descmiss_empty = list_empty(&priv_ep->wa2_descmiss_req_list); | ||
| 496 | |||
| 497 | /* | ||
| 498 | * DESCMISS transfer has been finished, so data will be | ||
| 499 | * directly copied from internal allocated usb_request | ||
| 500 | * objects. | ||
| 501 | */ | ||
| 502 | if (pending_empty && !descmiss_empty && | ||
| 503 | !(priv_req->flags & REQUEST_INTERNAL)) { | ||
| 504 | cdns3_wa2_descmiss_copy_data(priv_ep, | ||
| 505 | &priv_req->request); | ||
| 506 | |||
| 507 | trace_cdns3_wa2(priv_ep, "get internal stored data"); | ||
| 508 | |||
| 509 | list_add_tail(&priv_req->request.list, | ||
| 510 | &priv_ep->pending_req_list); | ||
| 511 | cdns3_gadget_giveback(priv_ep, priv_req, | ||
| 512 | priv_req->request.status); | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Intentionally driver returns positive value as | ||
| 516 | * correct value. It informs that transfer has | ||
| 517 | * been finished. | ||
| 518 | */ | ||
| 519 | return EINPROGRESS; | ||
| 520 | } | ||
| 521 | |||
| 522 | /* | ||
| 523 | * Driver will wait for completion DESCMISS transfer, | ||
| 524 | * before starts new, not DESCMISS transfer. | ||
| 525 | */ | ||
| 526 | if (!pending_empty && !descmiss_empty) { | ||
| 527 | trace_cdns3_wa2(priv_ep, "wait for pending transfer\n"); | ||
| 528 | deferred = 1; | ||
| 529 | } | ||
| 530 | |||
| 531 | if (priv_req->flags & REQUEST_INTERNAL) | ||
| 532 | list_add_tail(&priv_req->list, | ||
| 533 | &priv_ep->wa2_descmiss_req_list); | ||
| 534 | } | ||
| 535 | |||
| 536 | return deferred; | ||
| 537 | } | ||
| 538 | |||
| 539 | static void cdns3_wa2_remove_old_request(struct cdns3_endpoint *priv_ep) | ||
| 540 | { | ||
| 541 | struct cdns3_request *priv_req; | ||
| 542 | |||
| 543 | while (!list_empty(&priv_ep->wa2_descmiss_req_list)) { | ||
| 544 | u8 chain; | ||
| 545 | |||
| 546 | priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); | ||
| 547 | chain = !!(priv_req->flags & REQUEST_INTERNAL_CH); | ||
| 548 | |||
| 549 | trace_cdns3_wa2(priv_ep, "removes eldest request"); | ||
| 550 | |||
| 551 | kfree(priv_req->request.buf); | ||
| 552 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, | ||
| 553 | &priv_req->request); | ||
| 554 | list_del_init(&priv_req->list); | ||
| 555 | --priv_ep->wa2_counter; | ||
| 556 | |||
| 557 | if (!chain) | ||
| 558 | break; | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | /** | ||
| 563 | * cdns3_wa2_descmissing_packet - handles descriptor missing event. | ||
| 564 | * @priv_dev: extended gadget object | ||
| 565 | * | ||
| 566 | * This function is used only for WA2. For more information see Work around 2 | ||
| 567 | * description. | ||
| 568 | */ | ||
| 569 | static void cdns3_wa2_descmissing_packet(struct cdns3_endpoint *priv_ep) | ||
| 570 | { | ||
| 571 | struct cdns3_request *priv_req; | ||
| 572 | struct usb_request *request; | ||
| 573 | |||
| 574 | if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { | ||
| 575 | priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; | ||
| 576 | priv_ep->flags |= EP_QUIRK_EXTRA_BUF_EN; | ||
| 577 | } | ||
| 578 | |||
| 579 | trace_cdns3_wa2(priv_ep, "Description Missing detected\n"); | ||
| 580 | |||
| 581 | if (priv_ep->wa2_counter >= CDNS3_WA2_NUM_BUFFERS) | ||
| 582 | cdns3_wa2_remove_old_request(priv_ep); | ||
| 583 | |||
| 584 | request = cdns3_gadget_ep_alloc_request(&priv_ep->endpoint, | ||
| 585 | GFP_ATOMIC); | ||
| 586 | if (!request) | ||
| 587 | goto err; | ||
| 588 | |||
| 589 | priv_req = to_cdns3_request(request); | ||
| 590 | priv_req->flags |= REQUEST_INTERNAL; | ||
| 591 | |||
| 592 | /* if this field is still assigned it indicate that transfer related | ||
| 593 | * with this request has not been finished yet. Driver in this | ||
| 594 | * case simply allocate next request and assign flag REQUEST_INTERNAL_CH | ||
| 595 | * flag to previous one. It will indicate that current request is | ||
| 596 | * part of the previous one. | ||
| 597 | */ | ||
| 598 | if (priv_ep->descmis_req) | ||
| 599 | priv_ep->descmis_req->flags |= REQUEST_INTERNAL_CH; | ||
| 600 | |||
| 601 | priv_req->request.buf = kzalloc(CDNS3_DESCMIS_BUF_SIZE, | ||
| 602 | GFP_ATOMIC); | ||
| 603 | priv_ep->wa2_counter++; | ||
| 604 | |||
| 605 | if (!priv_req->request.buf) { | ||
| 606 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); | ||
| 607 | goto err; | ||
| 608 | } | ||
| 609 | |||
| 610 | priv_req->request.length = CDNS3_DESCMIS_BUF_SIZE; | ||
| 611 | priv_ep->descmis_req = priv_req; | ||
| 612 | |||
| 613 | __cdns3_gadget_ep_queue(&priv_ep->endpoint, | ||
| 614 | &priv_ep->descmis_req->request, | ||
| 615 | GFP_ATOMIC); | ||
| 616 | |||
| 617 | return; | ||
| 618 | |||
| 619 | err: | ||
| 620 | dev_err(priv_ep->cdns3_dev->dev, | ||
| 621 | "Failed: No sufficient memory for DESCMIS\n"); | ||
| 622 | } | ||
| 623 | |||
| 624 | /** | ||
| 625 | * cdns3_gadget_giveback - call struct usb_request's ->complete callback | ||
| 626 | * @priv_ep: The endpoint to whom the request belongs to | ||
| 627 | * @priv_req: The request we're giving back | ||
| 628 | * @status: completion code for the request | ||
| 629 | * | ||
| 630 | * Must be called with controller's lock held and interrupts disabled. This | ||
| 631 | * function will unmap @req and call its ->complete() callback to notify upper | ||
| 632 | * layers that it has completed. | ||
| 633 | */ | ||
| 634 | void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, | ||
| 635 | struct cdns3_request *priv_req, | ||
| 636 | int status) | ||
| 637 | { | ||
| 638 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 639 | struct usb_request *request = &priv_req->request; | ||
| 640 | |||
| 641 | list_del_init(&request->list); | ||
| 642 | |||
| 643 | if (request->status == -EINPROGRESS) | ||
| 644 | request->status = status; | ||
| 645 | |||
| 646 | usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, | ||
| 647 | priv_ep->dir); | ||
| 648 | |||
| 649 | if ((priv_req->flags & REQUEST_UNALIGNED) && | ||
| 650 | priv_ep->dir == USB_DIR_OUT && !request->status) | ||
| 651 | memcpy(request->buf, priv_req->aligned_buf->buf, | ||
| 652 | request->length); | ||
| 653 | |||
| 654 | priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); | ||
| 655 | trace_cdns3_gadget_giveback(priv_req); | ||
| 656 | |||
| 657 | if (priv_dev->dev_ver < DEV_VER_V2) { | ||
| 658 | request = cdns3_wa2_gadget_giveback(priv_dev, priv_ep, | ||
| 659 | priv_req); | ||
| 660 | if (!request) | ||
| 661 | return; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (request->complete) { | ||
| 665 | spin_unlock(&priv_dev->lock); | ||
| 666 | usb_gadget_giveback_request(&priv_ep->endpoint, | ||
| 667 | request); | ||
| 668 | spin_lock(&priv_dev->lock); | ||
| 669 | } | ||
| 670 | |||
| 671 | if (request->buf == priv_dev->zlp_buf) | ||
| 672 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); | ||
| 673 | } | ||
| 674 | |||
| 675 | void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) | ||
| 676 | { | ||
| 677 | /* Work around for stale data address in TRB*/ | ||
| 678 | if (priv_ep->wa1_set) { | ||
| 679 | trace_cdns3_wa1(priv_ep, "restore cycle bit"); | ||
| 680 | |||
| 681 | priv_ep->wa1_set = 0; | ||
| 682 | priv_ep->wa1_trb_index = 0xFFFF; | ||
| 683 | if (priv_ep->wa1_cycle_bit) { | ||
| 684 | priv_ep->wa1_trb->control = | ||
| 685 | priv_ep->wa1_trb->control | 0x1; | ||
| 686 | } else { | ||
| 687 | priv_ep->wa1_trb->control = | ||
| 688 | priv_ep->wa1_trb->control & ~0x1; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 693 | static void cdns3_free_aligned_request_buf(struct work_struct *work) | ||
| 694 | { | ||
| 695 | struct cdns3_device *priv_dev = container_of(work, struct cdns3_device, | ||
| 696 | aligned_buf_wq); | ||
| 697 | struct cdns3_aligned_buf *buf, *tmp; | ||
| 698 | unsigned long flags; | ||
| 699 | |||
| 700 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 701 | |||
| 702 | list_for_each_entry_safe(buf, tmp, &priv_dev->aligned_buf_list, list) { | ||
| 703 | if (!buf->in_use) { | ||
| 704 | list_del(&buf->list); | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Re-enable interrupts to free DMA capable memory. | ||
| 708 | * Driver can't free this memory with disabled | ||
| 709 | * interrupts. | ||
| 710 | */ | ||
| 711 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 712 | dma_free_coherent(priv_dev->sysdev, buf->size, | ||
| 713 | buf->buf, buf->dma); | ||
| 714 | kfree(buf); | ||
| 715 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 716 | } | ||
| 717 | } | ||
| 718 | |||
| 719 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 720 | } | ||
| 721 | |||
| 722 | static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) | ||
| 723 | { | ||
| 724 | struct cdns3_endpoint *priv_ep = priv_req->priv_ep; | ||
| 725 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 726 | struct cdns3_aligned_buf *buf; | ||
| 727 | |||
| 728 | /* check if buffer is aligned to 8. */ | ||
| 729 | if (!((uintptr_t)priv_req->request.buf & 0x7)) | ||
| 730 | return 0; | ||
| 731 | |||
| 732 | buf = priv_req->aligned_buf; | ||
| 733 | |||
| 734 | if (!buf || priv_req->request.length > buf->size) { | ||
| 735 | buf = kzalloc(sizeof(*buf), GFP_ATOMIC); | ||
| 736 | if (!buf) | ||
| 737 | return -ENOMEM; | ||
| 738 | |||
| 739 | buf->size = priv_req->request.length; | ||
| 740 | |||
| 741 | buf->buf = dma_alloc_coherent(priv_dev->sysdev, | ||
| 742 | buf->size, | ||
| 743 | &buf->dma, | ||
| 744 | GFP_ATOMIC); | ||
| 745 | if (!buf->buf) { | ||
| 746 | kfree(buf); | ||
| 747 | return -ENOMEM; | ||
| 748 | } | ||
| 749 | |||
| 750 | if (priv_req->aligned_buf) { | ||
| 751 | trace_cdns3_free_aligned_request(priv_req); | ||
| 752 | priv_req->aligned_buf->in_use = 0; | ||
| 753 | queue_work(system_freezable_wq, | ||
| 754 | &priv_dev->aligned_buf_wq); | ||
| 755 | } | ||
| 756 | |||
| 757 | buf->in_use = 1; | ||
| 758 | priv_req->aligned_buf = buf; | ||
| 759 | |||
| 760 | list_add_tail(&buf->list, | ||
| 761 | &priv_dev->aligned_buf_list); | ||
| 762 | } | ||
| 763 | |||
| 764 | if (priv_ep->dir == USB_DIR_IN) { | ||
| 765 | memcpy(buf->buf, priv_req->request.buf, | ||
| 766 | priv_req->request.length); | ||
| 767 | } | ||
| 768 | |||
| 769 | priv_req->flags |= REQUEST_UNALIGNED; | ||
| 770 | trace_cdns3_prepare_aligned_request(priv_req); | ||
| 771 | |||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | static int cdns3_wa1_update_guard(struct cdns3_endpoint *priv_ep, | ||
| 776 | struct cdns3_trb *trb) | ||
| 777 | { | ||
| 778 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 779 | |||
| 780 | if (!priv_ep->wa1_set) { | ||
| 781 | u32 doorbell; | ||
| 782 | |||
| 783 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); | ||
| 784 | |||
| 785 | if (doorbell) { | ||
| 786 | priv_ep->wa1_cycle_bit = priv_ep->pcs ? TRB_CYCLE : 0; | ||
| 787 | priv_ep->wa1_set = 1; | ||
| 788 | priv_ep->wa1_trb = trb; | ||
| 789 | priv_ep->wa1_trb_index = priv_ep->enqueue; | ||
| 790 | trace_cdns3_wa1(priv_ep, "set guard"); | ||
| 791 | return 0; | ||
| 792 | } | ||
| 793 | } | ||
| 794 | return 1; | ||
| 795 | } | ||
| 796 | |||
| 797 | static void cdns3_wa1_tray_restore_cycle_bit(struct cdns3_device *priv_dev, | ||
| 798 | struct cdns3_endpoint *priv_ep) | ||
| 799 | { | ||
| 800 | int dma_index; | ||
| 801 | u32 doorbell; | ||
| 802 | |||
| 803 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); | ||
| 804 | dma_index = cdns3_get_dma_pos(priv_dev, priv_ep); | ||
| 805 | |||
| 806 | if (!doorbell || dma_index != priv_ep->wa1_trb_index) | ||
| 807 | cdns3_wa1_restore_cycle_bit(priv_ep); | ||
| 808 | } | ||
| 809 | |||
| 810 | /** | ||
| 811 | * cdns3_ep_run_transfer - start transfer on no-default endpoint hardware | ||
| 812 | * @priv_ep: endpoint object | ||
| 813 | * | ||
| 814 | * Returns zero on success or negative value on failure | ||
| 815 | */ | ||
| 816 | int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, | ||
| 817 | struct usb_request *request) | ||
| 818 | { | ||
| 819 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 820 | struct cdns3_request *priv_req; | ||
| 821 | struct cdns3_trb *trb; | ||
| 822 | dma_addr_t trb_dma; | ||
| 823 | u32 togle_pcs = 1; | ||
| 824 | int sg_iter = 0; | ||
| 825 | int num_trb; | ||
| 826 | int address; | ||
| 827 | u32 control; | ||
| 828 | int pcs; | ||
| 829 | |||
| 830 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) | ||
| 831 | num_trb = priv_ep->interval; | ||
| 832 | else | ||
| 833 | num_trb = request->num_sgs ? request->num_sgs : 1; | ||
| 834 | |||
| 835 | if (num_trb > priv_ep->free_trbs) { | ||
| 836 | priv_ep->flags |= EP_RING_FULL; | ||
| 837 | return -ENOBUFS; | ||
| 838 | } | ||
| 839 | |||
| 840 | priv_req = to_cdns3_request(request); | ||
| 841 | address = priv_ep->endpoint.desc->bEndpointAddress; | ||
| 842 | |||
| 843 | priv_ep->flags |= EP_PENDING_REQUEST; | ||
| 844 | |||
| 845 | /* must allocate buffer aligned to 8 */ | ||
| 846 | if (priv_req->flags & REQUEST_UNALIGNED) | ||
| 847 | trb_dma = priv_req->aligned_buf->dma; | ||
| 848 | else | ||
| 849 | trb_dma = request->dma; | ||
| 850 | |||
| 851 | trb = priv_ep->trb_pool + priv_ep->enqueue; | ||
| 852 | priv_req->start_trb = priv_ep->enqueue; | ||
| 853 | priv_req->trb = trb; | ||
| 854 | |||
| 855 | cdns3_select_ep(priv_ep->cdns3_dev, address); | ||
| 856 | |||
| 857 | /* prepare ring */ | ||
| 858 | if ((priv_ep->enqueue + num_trb) >= (priv_ep->num_trbs - 1)) { | ||
| 859 | struct cdns3_trb *link_trb; | ||
| 860 | int doorbell, dma_index; | ||
| 861 | u32 ch_bit = 0; | ||
| 862 | |||
| 863 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); | ||
| 864 | dma_index = cdns3_get_dma_pos(priv_dev, priv_ep); | ||
| 865 | |||
| 866 | /* Driver can't update LINK TRB if it is current processed. */ | ||
| 867 | if (doorbell && dma_index == priv_ep->num_trbs - 1) { | ||
| 868 | priv_ep->flags |= EP_DEFERRED_DRDY; | ||
| 869 | return -ENOBUFS; | ||
| 870 | } | ||
| 871 | |||
| 872 | /*updating C bt in Link TRB before starting DMA*/ | ||
| 873 | link_trb = priv_ep->trb_pool + (priv_ep->num_trbs - 1); | ||
| 874 | /* | ||
| 875 | * For TRs size equal 2 enabling TRB_CHAIN for epXin causes | ||
| 876 | * that DMA stuck at the LINK TRB. | ||
| 877 | * On the other hand, removing TRB_CHAIN for longer TRs for | ||
| 878 | * epXout cause that DMA stuck after handling LINK TRB. | ||
| 879 | * To eliminate this strange behavioral driver set TRB_CHAIN | ||
| 880 | * bit only for TR size > 2. | ||
| 881 | */ | ||
| 882 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC || | ||
| 883 | TRBS_PER_SEGMENT > 2) | ||
| 884 | ch_bit = TRB_CHAIN; | ||
| 885 | |||
| 886 | link_trb->control = ((priv_ep->pcs) ? TRB_CYCLE : 0) | | ||
| 887 | TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit; | ||
| 888 | } | ||
| 889 | |||
| 890 | if (priv_dev->dev_ver <= DEV_VER_V2) | ||
| 891 | togle_pcs = cdns3_wa1_update_guard(priv_ep, trb); | ||
| 892 | |||
| 893 | /* set incorrect Cycle Bit for first trb*/ | ||
| 894 | control = priv_ep->pcs ? 0 : TRB_CYCLE; | ||
| 895 | |||
| 896 | do { | ||
| 897 | u32 length; | ||
| 898 | u16 td_size = 0; | ||
| 899 | |||
| 900 | /* fill TRB */ | ||
| 901 | control |= TRB_TYPE(TRB_NORMAL); | ||
| 902 | trb->buffer = TRB_BUFFER(request->num_sgs == 0 | ||
| 903 | ? trb_dma : request->sg[sg_iter].dma_address); | ||
| 904 | |||
| 905 | if (likely(!request->num_sgs)) | ||
| 906 | length = request->length; | ||
| 907 | else | ||
| 908 | length = request->sg[sg_iter].length; | ||
| 909 | |||
| 910 | if (likely(priv_dev->dev_ver >= DEV_VER_V2)) | ||
| 911 | td_size = DIV_ROUND_UP(length, | ||
| 912 | priv_ep->endpoint.maxpacket); | ||
| 913 | |||
| 914 | trb->length = TRB_BURST_LEN(priv_ep->trb_burst_size) | | ||
| 915 | TRB_LEN(length); | ||
| 916 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) | ||
| 917 | trb->length |= TRB_TDL_SS_SIZE(td_size); | ||
| 918 | else | ||
| 919 | control |= TRB_TDL_HS_SIZE(td_size); | ||
| 920 | |||
| 921 | pcs = priv_ep->pcs ? TRB_CYCLE : 0; | ||
| 922 | |||
| 923 | /* | ||
| 924 | * first trb should be prepared as last to avoid processing | ||
| 925 | * transfer to early | ||
| 926 | */ | ||
| 927 | if (sg_iter != 0) | ||
| 928 | control |= pcs; | ||
| 929 | |||
| 930 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir) { | ||
| 931 | control |= TRB_IOC | TRB_ISP; | ||
| 932 | } else { | ||
| 933 | /* for last element in TD or in SG list */ | ||
| 934 | if (sg_iter == (num_trb - 1) && sg_iter != 0) | ||
| 935 | control |= pcs | TRB_IOC | TRB_ISP; | ||
| 936 | } | ||
| 937 | |||
| 938 | if (sg_iter) | ||
| 939 | trb->control = control; | ||
| 940 | else | ||
| 941 | priv_req->trb->control = control; | ||
| 942 | |||
| 943 | control = 0; | ||
| 944 | ++sg_iter; | ||
| 945 | priv_req->end_trb = priv_ep->enqueue; | ||
| 946 | cdns3_ep_inc_enq(priv_ep); | ||
| 947 | trb = priv_ep->trb_pool + priv_ep->enqueue; | ||
| 948 | } while (sg_iter < num_trb); | ||
| 949 | |||
| 950 | trb = priv_req->trb; | ||
| 951 | |||
| 952 | priv_req->flags |= REQUEST_PENDING; | ||
| 953 | |||
| 954 | if (sg_iter == 1) | ||
| 955 | trb->control |= TRB_IOC | TRB_ISP; | ||
| 956 | |||
| 957 | /* | ||
| 958 | * Memory barrier - cycle bit must be set before other filds in trb. | ||
| 959 | */ | ||
| 960 | wmb(); | ||
| 961 | |||
| 962 | /* give the TD to the consumer*/ | ||
| 963 | if (togle_pcs) | ||
| 964 | trb->control = trb->control ^ 1; | ||
| 965 | |||
| 966 | if (priv_dev->dev_ver <= DEV_VER_V2) | ||
| 967 | cdns3_wa1_tray_restore_cycle_bit(priv_dev, priv_ep); | ||
| 968 | |||
| 969 | trace_cdns3_prepare_trb(priv_ep, priv_req->trb); | ||
| 970 | |||
| 971 | /* | ||
| 972 | * Memory barrier - Cycle Bit must be set before trb->length and | ||
| 973 | * trb->buffer fields. | ||
| 974 | */ | ||
| 975 | wmb(); | ||
| 976 | |||
| 977 | /* | ||
| 978 | * For DMULT mode we can set address to transfer ring only once after | ||
| 979 | * enabling endpoint. | ||
| 980 | */ | ||
| 981 | if (priv_ep->flags & EP_UPDATE_EP_TRBADDR) { | ||
| 982 | /* | ||
| 983 | * Until SW is not ready to handle the OUT transfer the ISO OUT | ||
| 984 | * Endpoint should be disabled (EP_CFG.ENABLE = 0). | ||
| 985 | * EP_CFG_ENABLE must be set before updating ep_traddr. | ||
| 986 | */ | ||
| 987 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir && | ||
| 988 | !(priv_ep->flags & EP_QUIRK_ISO_OUT_EN)) { | ||
| 989 | priv_ep->flags |= EP_QUIRK_ISO_OUT_EN; | ||
| 990 | cdns3_set_register_bit(&priv_dev->regs->ep_cfg, | ||
| 991 | EP_CFG_ENABLE); | ||
| 992 | } | ||
| 993 | |||
| 994 | writel(EP_TRADDR_TRADDR(priv_ep->trb_pool_dma + | ||
| 995 | priv_req->start_trb * TRB_SIZE), | ||
| 996 | &priv_dev->regs->ep_traddr); | ||
| 997 | |||
| 998 | priv_ep->flags &= ~EP_UPDATE_EP_TRBADDR; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | if (!priv_ep->wa1_set && !(priv_ep->flags & EP_STALLED)) { | ||
| 1002 | trace_cdns3_ring(priv_ep); | ||
| 1003 | /*clearing TRBERR and EP_STS_DESCMIS before seting DRDY*/ | ||
| 1004 | writel(EP_STS_TRBERR | EP_STS_DESCMIS, &priv_dev->regs->ep_sts); | ||
| 1005 | writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd); | ||
| 1006 | trace_cdns3_doorbell_epx(priv_ep->name, | ||
| 1007 | readl(&priv_dev->regs->ep_traddr)); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | /* WORKAROUND for transition to L0 */ | ||
| 1011 | __cdns3_gadget_wakeup(priv_dev); | ||
| 1012 | |||
| 1013 | return 0; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) | ||
| 1017 | { | ||
| 1018 | struct cdns3_endpoint *priv_ep; | ||
| 1019 | struct usb_ep *ep; | ||
| 1020 | int val; | ||
| 1021 | |||
| 1022 | if (priv_dev->hw_configured_flag) | ||
| 1023 | return; | ||
| 1024 | |||
| 1025 | writel(USB_CONF_CFGSET, &priv_dev->regs->usb_conf); | ||
| 1026 | writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); | ||
| 1027 | |||
| 1028 | cdns3_set_register_bit(&priv_dev->regs->usb_conf, | ||
| 1029 | USB_CONF_U1EN | USB_CONF_U2EN); | ||
| 1030 | |||
| 1031 | /* wait until configuration set */ | ||
| 1032 | readl_poll_timeout_atomic(&priv_dev->regs->usb_sts, val, | ||
| 1033 | val & USB_STS_CFGSTS_MASK, 1, 100); | ||
| 1034 | |||
| 1035 | priv_dev->hw_configured_flag = 1; | ||
| 1036 | |||
| 1037 | list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) { | ||
| 1038 | if (ep->enabled) { | ||
| 1039 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 1040 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 1041 | } | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | /** | ||
| 1046 | * cdns3_request_handled - check whether request has been handled by DMA | ||
| 1047 | * | ||
| 1048 | * @priv_ep: extended endpoint object. | ||
| 1049 | * @priv_req: request object for checking | ||
| 1050 | * | ||
| 1051 | * Endpoint must be selected before invoking this function. | ||
| 1052 | * | ||
| 1053 | * Returns false if request has not been handled by DMA, else returns true. | ||
| 1054 | * | ||
| 1055 | * SR - start ring | ||
| 1056 | * ER - end ring | ||
| 1057 | * DQ = priv_ep->dequeue - dequeue position | ||
| 1058 | * EQ = priv_ep->enqueue - enqueue position | ||
| 1059 | * ST = priv_req->start_trb - index of first TRB in transfer ring | ||
| 1060 | * ET = priv_req->end_trb - index of last TRB in transfer ring | ||
| 1061 | * CI = current_index - index of processed TRB by DMA. | ||
| 1062 | * | ||
| 1063 | * As first step, function checks if cycle bit for priv_req->start_trb is | ||
| 1064 | * correct. | ||
| 1065 | * | ||
| 1066 | * some rules: | ||
| 1067 | * 1. priv_ep->dequeue never exceed current_index. | ||
| 1068 | * 2 priv_ep->enqueue never exceed priv_ep->dequeue | ||
| 1069 | * 3. exception: priv_ep->enqueue == priv_ep->dequeue | ||
| 1070 | * and priv_ep->free_trbs is zero. | ||
| 1071 | * This case indicate that TR is full. | ||
| 1072 | * | ||
| 1073 | * Then We can split recognition into two parts: | ||
| 1074 | * Case 1 - priv_ep->dequeue < current_index | ||
| 1075 | * SR ... EQ ... DQ ... CI ... ER | ||
| 1076 | * SR ... DQ ... CI ... EQ ... ER | ||
| 1077 | * | ||
| 1078 | * Request has been handled by DMA if ST and ET is between DQ and CI. | ||
| 1079 | * | ||
| 1080 | * Case 2 - priv_ep->dequeue > current_index | ||
| 1081 | * This situation take place when CI go through the LINK TRB at the end of | ||
| 1082 | * transfer ring. | ||
| 1083 | * SR ... CI ... EQ ... DQ ... ER | ||
| 1084 | * | ||
| 1085 | * Request has been handled by DMA if ET is less then CI or | ||
| 1086 | * ET is greater or equal DQ. | ||
| 1087 | */ | ||
| 1088 | static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep, | ||
| 1089 | struct cdns3_request *priv_req) | ||
| 1090 | { | ||
| 1091 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 1092 | struct cdns3_trb *trb = priv_req->trb; | ||
| 1093 | int current_index = 0; | ||
| 1094 | int handled = 0; | ||
| 1095 | int doorbell; | ||
| 1096 | |||
| 1097 | current_index = cdns3_get_dma_pos(priv_dev, priv_ep); | ||
| 1098 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); | ||
| 1099 | |||
| 1100 | trb = &priv_ep->trb_pool[priv_req->start_trb]; | ||
| 1101 | |||
| 1102 | if ((trb->control & TRB_CYCLE) != priv_ep->ccs) | ||
| 1103 | goto finish; | ||
| 1104 | |||
| 1105 | if (doorbell == 1 && current_index == priv_ep->dequeue) | ||
| 1106 | goto finish; | ||
| 1107 | |||
| 1108 | /* The corner case for TRBS_PER_SEGMENT equal 2). */ | ||
| 1109 | if (TRBS_PER_SEGMENT == 2 && priv_ep->type != USB_ENDPOINT_XFER_ISOC) { | ||
| 1110 | handled = 1; | ||
| 1111 | goto finish; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | if (priv_ep->enqueue == priv_ep->dequeue && | ||
| 1115 | priv_ep->free_trbs == 0) { | ||
| 1116 | handled = 1; | ||
| 1117 | } else if (priv_ep->dequeue < current_index) { | ||
| 1118 | if ((current_index == (priv_ep->num_trbs - 1)) && | ||
| 1119 | !priv_ep->dequeue) | ||
| 1120 | goto finish; | ||
| 1121 | |||
| 1122 | if (priv_req->end_trb >= priv_ep->dequeue && | ||
| 1123 | priv_req->end_trb < current_index) | ||
| 1124 | handled = 1; | ||
| 1125 | } else if (priv_ep->dequeue > current_index) { | ||
| 1126 | if (priv_req->end_trb < current_index || | ||
| 1127 | priv_req->end_trb >= priv_ep->dequeue) | ||
| 1128 | handled = 1; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | finish: | ||
| 1132 | trace_cdns3_request_handled(priv_req, current_index, handled); | ||
| 1133 | |||
| 1134 | return handled; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | static void cdns3_transfer_completed(struct cdns3_device *priv_dev, | ||
| 1138 | struct cdns3_endpoint *priv_ep) | ||
| 1139 | { | ||
| 1140 | struct cdns3_request *priv_req; | ||
| 1141 | struct usb_request *request; | ||
| 1142 | struct cdns3_trb *trb; | ||
| 1143 | |||
| 1144 | while (!list_empty(&priv_ep->pending_req_list)) { | ||
| 1145 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 1146 | priv_req = to_cdns3_request(request); | ||
| 1147 | |||
| 1148 | /* Re-select endpoint. It could be changed by other CPU during | ||
| 1149 | * handling usb_gadget_giveback_request. | ||
| 1150 | */ | ||
| 1151 | cdns3_select_ep(priv_dev, priv_ep->endpoint.address); | ||
| 1152 | |||
| 1153 | if (!cdns3_request_handled(priv_ep, priv_req)) | ||
| 1154 | goto prepare_next_td; | ||
| 1155 | |||
| 1156 | trb = priv_ep->trb_pool + priv_ep->dequeue; | ||
| 1157 | trace_cdns3_complete_trb(priv_ep, trb); | ||
| 1158 | |||
| 1159 | if (trb != priv_req->trb) | ||
| 1160 | dev_warn(priv_dev->dev, | ||
| 1161 | "request_trb=0x%p, queue_trb=0x%p\n", | ||
| 1162 | priv_req->trb, trb); | ||
| 1163 | |||
| 1164 | request->actual = TRB_LEN(le32_to_cpu(trb->length)); | ||
| 1165 | cdns3_move_deq_to_next_trb(priv_req); | ||
| 1166 | cdns3_gadget_giveback(priv_ep, priv_req, 0); | ||
| 1167 | |||
| 1168 | if (priv_ep->type != USB_ENDPOINT_XFER_ISOC && | ||
| 1169 | TRBS_PER_SEGMENT == 2) | ||
| 1170 | break; | ||
| 1171 | } | ||
| 1172 | priv_ep->flags &= ~EP_PENDING_REQUEST; | ||
| 1173 | |||
| 1174 | prepare_next_td: | ||
| 1175 | if (!(priv_ep->flags & EP_STALLED) && | ||
| 1176 | !(priv_ep->flags & EP_STALL_PENDING)) | ||
| 1177 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | void cdns3_rearm_transfer(struct cdns3_endpoint *priv_ep, u8 rearm) | ||
| 1181 | { | ||
| 1182 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 1183 | |||
| 1184 | cdns3_wa1_restore_cycle_bit(priv_ep); | ||
| 1185 | |||
| 1186 | if (rearm) { | ||
| 1187 | trace_cdns3_ring(priv_ep); | ||
| 1188 | |||
| 1189 | /* Cycle Bit must be updated before arming DMA. */ | ||
| 1190 | wmb(); | ||
| 1191 | writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd); | ||
| 1192 | |||
| 1193 | __cdns3_gadget_wakeup(priv_dev); | ||
| 1194 | |||
| 1195 | trace_cdns3_doorbell_epx(priv_ep->name, | ||
| 1196 | readl(&priv_dev->regs->ep_traddr)); | ||
| 1197 | } | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | /** | ||
| 1201 | * cdns3_check_ep_interrupt_proceed - Processes interrupt related to endpoint | ||
| 1202 | * @priv_ep: endpoint object | ||
| 1203 | * | ||
| 1204 | * Returns 0 | ||
| 1205 | */ | ||
| 1206 | static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) | ||
| 1207 | { | ||
| 1208 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 1209 | u32 ep_sts_reg; | ||
| 1210 | |||
| 1211 | cdns3_select_ep(priv_dev, priv_ep->endpoint.address); | ||
| 1212 | |||
| 1213 | trace_cdns3_epx_irq(priv_dev, priv_ep); | ||
| 1214 | |||
| 1215 | ep_sts_reg = readl(&priv_dev->regs->ep_sts); | ||
| 1216 | writel(ep_sts_reg, &priv_dev->regs->ep_sts); | ||
| 1217 | |||
| 1218 | if (ep_sts_reg & EP_STS_TRBERR) { | ||
| 1219 | if (priv_ep->flags & EP_STALL_PENDING && | ||
| 1220 | !(ep_sts_reg & EP_STS_DESCMIS && | ||
| 1221 | priv_dev->dev_ver < DEV_VER_V2)) { | ||
| 1222 | cdns3_ep_stall_flush(priv_ep); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | /* | ||
| 1226 | * For isochronous transfer driver completes request on | ||
| 1227 | * IOC or on TRBERR. IOC appears only when device receive | ||
| 1228 | * OUT data packet. If host disable stream or lost some packet | ||
| 1229 | * then the only way to finish all queued transfer is to do it | ||
| 1230 | * on TRBERR event. | ||
| 1231 | */ | ||
| 1232 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && | ||
| 1233 | !priv_ep->wa1_set) { | ||
| 1234 | if (!priv_ep->dir) { | ||
| 1235 | u32 ep_cfg = readl(&priv_dev->regs->ep_cfg); | ||
| 1236 | |||
| 1237 | ep_cfg &= ~EP_CFG_ENABLE; | ||
| 1238 | writel(ep_cfg, &priv_dev->regs->ep_cfg); | ||
| 1239 | priv_ep->flags &= ~EP_QUIRK_ISO_OUT_EN; | ||
| 1240 | } | ||
| 1241 | cdns3_transfer_completed(priv_dev, priv_ep); | ||
| 1242 | } else if (!(priv_ep->flags & EP_STALLED) && | ||
| 1243 | !(priv_ep->flags & EP_STALL_PENDING)) { | ||
| 1244 | if (priv_ep->flags & EP_DEFERRED_DRDY) { | ||
| 1245 | priv_ep->flags &= ~EP_DEFERRED_DRDY; | ||
| 1246 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 1247 | } else { | ||
| 1248 | cdns3_rearm_transfer(priv_ep, | ||
| 1249 | priv_ep->wa1_set); | ||
| 1250 | } | ||
| 1251 | } | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { | ||
| 1255 | if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { | ||
| 1256 | if (ep_sts_reg & EP_STS_ISP) | ||
| 1257 | priv_ep->flags |= EP_QUIRK_END_TRANSFER; | ||
| 1258 | else | ||
| 1259 | priv_ep->flags &= ~EP_QUIRK_END_TRANSFER; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | cdns3_transfer_completed(priv_dev, priv_ep); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | /* | ||
| 1266 | * WA2: this condition should only be meet when | ||
| 1267 | * priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET or | ||
| 1268 | * priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN. | ||
| 1269 | * In other cases this interrupt will be disabled/ | ||
| 1270 | */ | ||
| 1271 | if (ep_sts_reg & EP_STS_DESCMIS && priv_dev->dev_ver < DEV_VER_V2 && | ||
| 1272 | !(priv_ep->flags & EP_STALLED)) | ||
| 1273 | cdns3_wa2_descmissing_packet(priv_ep); | ||
| 1274 | |||
| 1275 | return 0; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev) | ||
| 1279 | { | ||
| 1280 | if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect) { | ||
| 1281 | spin_unlock(&priv_dev->lock); | ||
| 1282 | priv_dev->gadget_driver->disconnect(&priv_dev->gadget); | ||
| 1283 | spin_lock(&priv_dev->lock); | ||
| 1284 | } | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | /** | ||
| 1288 | * cdns3_check_usb_interrupt_proceed - Processes interrupt related to device | ||
| 1289 | * @priv_dev: extended gadget object | ||
| 1290 | * @usb_ists: bitmap representation of device's reported interrupts | ||
| 1291 | * (usb_ists register value) | ||
| 1292 | */ | ||
| 1293 | static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev, | ||
| 1294 | u32 usb_ists) | ||
| 1295 | { | ||
| 1296 | int speed = 0; | ||
| 1297 | |||
| 1298 | trace_cdns3_usb_irq(priv_dev, usb_ists); | ||
| 1299 | if (usb_ists & USB_ISTS_L1ENTI) { | ||
| 1300 | /* | ||
| 1301 | * WORKAROUND: CDNS3 controller has issue with hardware resuming | ||
| 1302 | * from L1. To fix it, if any DMA transfer is pending driver | ||
| 1303 | * must starts driving resume signal immediately. | ||
| 1304 | */ | ||
| 1305 | if (readl(&priv_dev->regs->drbl)) | ||
| 1306 | __cdns3_gadget_wakeup(priv_dev); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | /* Connection detected */ | ||
| 1310 | if (usb_ists & (USB_ISTS_CON2I | USB_ISTS_CONI)) { | ||
| 1311 | speed = cdns3_get_speed(priv_dev); | ||
| 1312 | priv_dev->gadget.speed = speed; | ||
| 1313 | usb_gadget_set_state(&priv_dev->gadget, USB_STATE_POWERED); | ||
| 1314 | cdns3_ep0_config(priv_dev); | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | /* Disconnection detected */ | ||
| 1318 | if (usb_ists & (USB_ISTS_DIS2I | USB_ISTS_DISI)) { | ||
| 1319 | cdns3_disconnect_gadget(priv_dev); | ||
| 1320 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 1321 | usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED); | ||
| 1322 | cdns3_hw_reset_eps_config(priv_dev); | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | if (usb_ists & (USB_ISTS_L2ENTI | USB_ISTS_U3ENTI)) { | ||
| 1326 | if (priv_dev->gadget_driver && | ||
| 1327 | priv_dev->gadget_driver->suspend) { | ||
| 1328 | spin_unlock(&priv_dev->lock); | ||
| 1329 | priv_dev->gadget_driver->suspend(&priv_dev->gadget); | ||
| 1330 | spin_lock(&priv_dev->lock); | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | if (usb_ists & (USB_ISTS_L2EXTI | USB_ISTS_U3EXTI)) { | ||
| 1335 | if (priv_dev->gadget_driver && | ||
| 1336 | priv_dev->gadget_driver->resume) { | ||
| 1337 | spin_unlock(&priv_dev->lock); | ||
| 1338 | priv_dev->gadget_driver->resume(&priv_dev->gadget); | ||
| 1339 | spin_lock(&priv_dev->lock); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | /* reset*/ | ||
| 1344 | if (usb_ists & (USB_ISTS_UWRESI | USB_ISTS_UHRESI | USB_ISTS_U2RESI)) { | ||
| 1345 | if (priv_dev->gadget_driver) { | ||
| 1346 | spin_unlock(&priv_dev->lock); | ||
| 1347 | usb_gadget_udc_reset(&priv_dev->gadget, | ||
| 1348 | priv_dev->gadget_driver); | ||
| 1349 | spin_lock(&priv_dev->lock); | ||
| 1350 | |||
| 1351 | /*read again to check the actual speed*/ | ||
| 1352 | speed = cdns3_get_speed(priv_dev); | ||
| 1353 | priv_dev->gadget.speed = speed; | ||
| 1354 | cdns3_hw_reset_eps_config(priv_dev); | ||
| 1355 | cdns3_ep0_config(priv_dev); | ||
| 1356 | } | ||
| 1357 | } | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | /** | ||
| 1361 | * cdns3_device_irq_handler- interrupt handler for device part of controller | ||
| 1362 | * | ||
| 1363 | * @irq: irq number for cdns3 core device | ||
| 1364 | * @data: structure of cdns3 | ||
| 1365 | * | ||
| 1366 | * Returns IRQ_HANDLED or IRQ_NONE | ||
| 1367 | */ | ||
| 1368 | static irqreturn_t cdns3_device_irq_handler(int irq, void *data) | ||
| 1369 | { | ||
| 1370 | struct cdns3_device *priv_dev; | ||
| 1371 | struct cdns3 *cdns = data; | ||
| 1372 | irqreturn_t ret = IRQ_NONE; | ||
| 1373 | u32 reg; | ||
| 1374 | |||
| 1375 | priv_dev = cdns->gadget_dev; | ||
| 1376 | |||
| 1377 | /* check USB device interrupt */ | ||
| 1378 | reg = readl(&priv_dev->regs->usb_ists); | ||
| 1379 | if (reg) { | ||
| 1380 | /* After masking interrupts the new interrupts won't be | ||
| 1381 | * reported in usb_ists/ep_ists. In order to not lose some | ||
| 1382 | * of them driver disables only detected interrupts. | ||
| 1383 | * They will be enabled ASAP after clearing source of | ||
| 1384 | * interrupt. This an unusual behavior only applies to | ||
| 1385 | * usb_ists register. | ||
| 1386 | */ | ||
| 1387 | reg = ~reg & readl(&priv_dev->regs->usb_ien); | ||
| 1388 | /* mask deferred interrupt. */ | ||
| 1389 | writel(reg, &priv_dev->regs->usb_ien); | ||
| 1390 | ret = IRQ_WAKE_THREAD; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | /* check endpoint interrupt */ | ||
| 1394 | reg = readl(&priv_dev->regs->ep_ists); | ||
| 1395 | if (reg) { | ||
| 1396 | writel(0, &priv_dev->regs->ep_ien); | ||
| 1397 | ret = IRQ_WAKE_THREAD; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | return ret; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | /** | ||
| 1404 | * cdns3_device_thread_irq_handler- interrupt handler for device part | ||
| 1405 | * of controller | ||
| 1406 | * | ||
| 1407 | * @irq: irq number for cdns3 core device | ||
| 1408 | * @data: structure of cdns3 | ||
| 1409 | * | ||
| 1410 | * Returns IRQ_HANDLED or IRQ_NONE | ||
| 1411 | */ | ||
| 1412 | static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data) | ||
| 1413 | { | ||
| 1414 | struct cdns3_device *priv_dev; | ||
| 1415 | struct cdns3 *cdns = data; | ||
| 1416 | irqreturn_t ret = IRQ_NONE; | ||
| 1417 | unsigned long flags; | ||
| 1418 | int bit; | ||
| 1419 | u32 reg; | ||
| 1420 | |||
| 1421 | priv_dev = cdns->gadget_dev; | ||
| 1422 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 1423 | |||
| 1424 | reg = readl(&priv_dev->regs->usb_ists); | ||
| 1425 | if (reg) { | ||
| 1426 | writel(reg, &priv_dev->regs->usb_ists); | ||
| 1427 | writel(USB_IEN_INIT, &priv_dev->regs->usb_ien); | ||
| 1428 | cdns3_check_usb_interrupt_proceed(priv_dev, reg); | ||
| 1429 | ret = IRQ_HANDLED; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | reg = readl(&priv_dev->regs->ep_ists); | ||
| 1433 | |||
| 1434 | /* handle default endpoint OUT */ | ||
| 1435 | if (reg & EP_ISTS_EP_OUT0) { | ||
| 1436 | cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_OUT); | ||
| 1437 | ret = IRQ_HANDLED; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | /* handle default endpoint IN */ | ||
| 1441 | if (reg & EP_ISTS_EP_IN0) { | ||
| 1442 | cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_IN); | ||
| 1443 | ret = IRQ_HANDLED; | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | /* check if interrupt from non default endpoint, if no exit */ | ||
| 1447 | reg &= ~(EP_ISTS_EP_OUT0 | EP_ISTS_EP_IN0); | ||
| 1448 | if (!reg) | ||
| 1449 | goto irqend; | ||
| 1450 | |||
| 1451 | for_each_set_bit(bit, (unsigned long *)®, | ||
| 1452 | sizeof(u32) * BITS_PER_BYTE) { | ||
| 1453 | cdns3_check_ep_interrupt_proceed(priv_dev->eps[bit]); | ||
| 1454 | ret = IRQ_HANDLED; | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | irqend: | ||
| 1458 | writel(~0, &priv_dev->regs->ep_ien); | ||
| 1459 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 1460 | |||
| 1461 | return ret; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | /** | ||
| 1465 | * cdns3_ep_onchip_buffer_reserve - Try to reserve onchip buf for EP | ||
| 1466 | * | ||
| 1467 | * The real reservation will occur during write to EP_CFG register, | ||
| 1468 | * this function is used to check if the 'size' reservation is allowed. | ||
| 1469 | * | ||
| 1470 | * @priv_dev: extended gadget object | ||
| 1471 | * @size: the size (KB) for EP would like to allocate | ||
| 1472 | * @is_in: endpoint direction | ||
| 1473 | * | ||
| 1474 | * Return 0 if the required size can met or negative value on failure | ||
| 1475 | */ | ||
| 1476 | static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev, | ||
| 1477 | int size, int is_in) | ||
| 1478 | { | ||
| 1479 | int remained; | ||
| 1480 | |||
| 1481 | /* 2KB are reserved for EP0*/ | ||
| 1482 | remained = priv_dev->onchip_buffers - priv_dev->onchip_used_size - 2; | ||
| 1483 | |||
| 1484 | if (is_in) { | ||
| 1485 | if (remained < size) | ||
| 1486 | return -EPERM; | ||
| 1487 | |||
| 1488 | priv_dev->onchip_used_size += size; | ||
| 1489 | } else { | ||
| 1490 | int required; | ||
| 1491 | |||
| 1492 | /** | ||
| 1493 | * ALL OUT EPs are shared the same chunk onchip memory, so | ||
| 1494 | * driver checks if it already has assigned enough buffers | ||
| 1495 | */ | ||
| 1496 | if (priv_dev->out_mem_is_allocated >= size) | ||
| 1497 | return 0; | ||
| 1498 | |||
| 1499 | required = size - priv_dev->out_mem_is_allocated; | ||
| 1500 | |||
| 1501 | if (required > remained) | ||
| 1502 | return -EPERM; | ||
| 1503 | |||
| 1504 | priv_dev->out_mem_is_allocated += required; | ||
| 1505 | priv_dev->onchip_used_size += required; | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | return 0; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | void cdns3_configure_dmult(struct cdns3_device *priv_dev, | ||
| 1512 | struct cdns3_endpoint *priv_ep) | ||
| 1513 | { | ||
| 1514 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; | ||
| 1515 | |||
| 1516 | /* For dev_ver > DEV_VER_V2 DMULT is configured per endpoint */ | ||
| 1517 | if (priv_dev->dev_ver <= DEV_VER_V2) | ||
| 1518 | writel(USB_CONF_DMULT, ®s->usb_conf); | ||
| 1519 | |||
| 1520 | if (priv_dev->dev_ver == DEV_VER_V2) | ||
| 1521 | writel(USB_CONF2_EN_TDL_TRB, ®s->usb_conf2); | ||
| 1522 | |||
| 1523 | if (priv_dev->dev_ver >= DEV_VER_V3 && priv_ep) { | ||
| 1524 | u32 mask; | ||
| 1525 | |||
| 1526 | if (priv_ep->dir) | ||
| 1527 | mask = BIT(priv_ep->num + 16); | ||
| 1528 | else | ||
| 1529 | mask = BIT(priv_ep->num); | ||
| 1530 | |||
| 1531 | if (priv_ep->type != USB_ENDPOINT_XFER_ISOC) { | ||
| 1532 | cdns3_set_register_bit(®s->tdl_from_trb, mask); | ||
| 1533 | cdns3_set_register_bit(®s->tdl_beh, mask); | ||
| 1534 | cdns3_set_register_bit(®s->tdl_beh2, mask); | ||
| 1535 | cdns3_set_register_bit(®s->dma_adv_td, mask); | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir) | ||
| 1539 | cdns3_set_register_bit(®s->tdl_from_trb, mask); | ||
| 1540 | |||
| 1541 | cdns3_set_register_bit(®s->dtrans, mask); | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /** | ||
| 1546 | * cdns3_ep_config Configure hardware endpoint | ||
| 1547 | * @priv_ep: extended endpoint object | ||
| 1548 | */ | ||
| 1549 | void cdns3_ep_config(struct cdns3_endpoint *priv_ep) | ||
| 1550 | { | ||
| 1551 | bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC); | ||
| 1552 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 1553 | u32 bEndpointAddress = priv_ep->num | priv_ep->dir; | ||
| 1554 | u32 max_packet_size = 0; | ||
| 1555 | u8 maxburst = 0; | ||
| 1556 | u32 ep_cfg = 0; | ||
| 1557 | u8 buffering; | ||
| 1558 | u8 mult = 0; | ||
| 1559 | int ret; | ||
| 1560 | |||
| 1561 | buffering = CDNS3_EP_BUF_SIZE - 1; | ||
| 1562 | |||
| 1563 | cdns3_configure_dmult(priv_dev, priv_ep); | ||
| 1564 | |||
| 1565 | switch (priv_ep->type) { | ||
| 1566 | case USB_ENDPOINT_XFER_INT: | ||
| 1567 | ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT); | ||
| 1568 | |||
| 1569 | if ((priv_dev->dev_ver == DEV_VER_V2 && !priv_ep->dir) || | ||
| 1570 | priv_dev->dev_ver > DEV_VER_V2) | ||
| 1571 | ep_cfg |= EP_CFG_TDL_CHK; | ||
| 1572 | break; | ||
| 1573 | case USB_ENDPOINT_XFER_BULK: | ||
| 1574 | ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK); | ||
| 1575 | |||
| 1576 | if ((priv_dev->dev_ver == DEV_VER_V2 && !priv_ep->dir) || | ||
| 1577 | priv_dev->dev_ver > DEV_VER_V2) | ||
| 1578 | ep_cfg |= EP_CFG_TDL_CHK; | ||
| 1579 | break; | ||
| 1580 | default: | ||
| 1581 | ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); | ||
| 1582 | mult = CDNS3_EP_ISO_HS_MULT - 1; | ||
| 1583 | buffering = mult + 1; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | switch (priv_dev->gadget.speed) { | ||
| 1587 | case USB_SPEED_FULL: | ||
| 1588 | max_packet_size = is_iso_ep ? 1023 : 64; | ||
| 1589 | break; | ||
| 1590 | case USB_SPEED_HIGH: | ||
| 1591 | max_packet_size = is_iso_ep ? 1024 : 512; | ||
| 1592 | break; | ||
| 1593 | case USB_SPEED_SUPER: | ||
| 1594 | /* It's limitation that driver assumes in driver. */ | ||
| 1595 | mult = 0; | ||
| 1596 | max_packet_size = 1024; | ||
| 1597 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) { | ||
| 1598 | maxburst = CDNS3_EP_ISO_SS_BURST - 1; | ||
| 1599 | buffering = (mult + 1) * | ||
| 1600 | (maxburst + 1); | ||
| 1601 | |||
| 1602 | if (priv_ep->interval > 1) | ||
| 1603 | buffering++; | ||
| 1604 | } else { | ||
| 1605 | maxburst = CDNS3_EP_BUF_SIZE - 1; | ||
| 1606 | } | ||
| 1607 | break; | ||
| 1608 | default: | ||
| 1609 | /* all other speed are not supported */ | ||
| 1610 | return; | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | if (max_packet_size == 1024) | ||
| 1614 | priv_ep->trb_burst_size = 128; | ||
| 1615 | else if (max_packet_size >= 512) | ||
| 1616 | priv_ep->trb_burst_size = 64; | ||
| 1617 | else | ||
| 1618 | priv_ep->trb_burst_size = 16; | ||
| 1619 | |||
| 1620 | ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1, | ||
| 1621 | !!priv_ep->dir); | ||
| 1622 | if (ret) { | ||
| 1623 | dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n"); | ||
| 1624 | return; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) | | ||
| 1628 | EP_CFG_MULT(mult) | | ||
| 1629 | EP_CFG_BUFFERING(buffering) | | ||
| 1630 | EP_CFG_MAXBURST(maxburst); | ||
| 1631 | |||
| 1632 | cdns3_select_ep(priv_dev, bEndpointAddress); | ||
| 1633 | writel(ep_cfg, &priv_dev->regs->ep_cfg); | ||
| 1634 | |||
| 1635 | dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n", | ||
| 1636 | priv_ep->name, ep_cfg); | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | /* Find correct direction for HW endpoint according to description */ | ||
| 1640 | static int cdns3_ep_dir_is_correct(struct usb_endpoint_descriptor *desc, | ||
| 1641 | struct cdns3_endpoint *priv_ep) | ||
| 1642 | { | ||
| 1643 | return (priv_ep->endpoint.caps.dir_in && usb_endpoint_dir_in(desc)) || | ||
| 1644 | (priv_ep->endpoint.caps.dir_out && usb_endpoint_dir_out(desc)); | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | static struct | ||
| 1648 | cdns3_endpoint *cdns3_find_available_ep(struct cdns3_device *priv_dev, | ||
| 1649 | struct usb_endpoint_descriptor *desc) | ||
| 1650 | { | ||
| 1651 | struct usb_ep *ep; | ||
| 1652 | struct cdns3_endpoint *priv_ep; | ||
| 1653 | |||
| 1654 | list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) { | ||
| 1655 | unsigned long num; | ||
| 1656 | int ret; | ||
| 1657 | /* ep name pattern likes epXin or epXout */ | ||
| 1658 | char c[2] = {ep->name[2], '\0'}; | ||
| 1659 | |||
| 1660 | ret = kstrtoul(c, 10, &num); | ||
| 1661 | if (ret) | ||
| 1662 | return ERR_PTR(ret); | ||
| 1663 | |||
| 1664 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 1665 | if (cdns3_ep_dir_is_correct(desc, priv_ep)) { | ||
| 1666 | if (!(priv_ep->flags & EP_CLAIMED)) { | ||
| 1667 | priv_ep->num = num; | ||
| 1668 | return priv_ep; | ||
| 1669 | } | ||
| 1670 | } | ||
| 1671 | } | ||
| 1672 | |||
| 1673 | return ERR_PTR(-ENOENT); | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | /* | ||
| 1677 | * Cadence IP has one limitation that all endpoints must be configured | ||
| 1678 | * (Type & MaxPacketSize) before setting configuration through hardware | ||
| 1679 | * register, it means we can't change endpoints configuration after | ||
| 1680 | * set_configuration. | ||
| 1681 | * | ||
| 1682 | * This function set EP_CLAIMED flag which is added when the gadget driver | ||
| 1683 | * uses usb_ep_autoconfig to configure specific endpoint; | ||
| 1684 | * When the udc driver receives set_configurion request, | ||
| 1685 | * it goes through all claimed endpoints, and configure all endpoints | ||
| 1686 | * accordingly. | ||
| 1687 | * | ||
| 1688 | * At usb_ep_ops.enable/disable, we only enable and disable endpoint through | ||
| 1689 | * ep_cfg register which can be changed after set_configuration, and do | ||
| 1690 | * some software operation accordingly. | ||
| 1691 | */ | ||
| 1692 | static struct | ||
| 1693 | usb_ep *cdns3_gadget_match_ep(struct usb_gadget *gadget, | ||
| 1694 | struct usb_endpoint_descriptor *desc, | ||
| 1695 | struct usb_ss_ep_comp_descriptor *comp_desc) | ||
| 1696 | { | ||
| 1697 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 1698 | struct cdns3_endpoint *priv_ep; | ||
| 1699 | unsigned long flags; | ||
| 1700 | |||
| 1701 | priv_ep = cdns3_find_available_ep(priv_dev, desc); | ||
| 1702 | if (IS_ERR(priv_ep)) { | ||
| 1703 | dev_err(priv_dev->dev, "no available ep\n"); | ||
| 1704 | return NULL; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | dev_dbg(priv_dev->dev, "match endpoint: %s\n", priv_ep->name); | ||
| 1708 | |||
| 1709 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 1710 | priv_ep->endpoint.desc = desc; | ||
| 1711 | priv_ep->dir = usb_endpoint_dir_in(desc) ? USB_DIR_IN : USB_DIR_OUT; | ||
| 1712 | priv_ep->type = usb_endpoint_type(desc); | ||
| 1713 | priv_ep->flags |= EP_CLAIMED; | ||
| 1714 | priv_ep->interval = desc->bInterval ? BIT(desc->bInterval - 1) : 0; | ||
| 1715 | |||
| 1716 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 1717 | return &priv_ep->endpoint; | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | /** | ||
| 1721 | * cdns3_gadget_ep_alloc_request Allocates request | ||
| 1722 | * @ep: endpoint object associated with request | ||
| 1723 | * @gfp_flags: gfp flags | ||
| 1724 | * | ||
| 1725 | * Returns allocated request address, NULL on allocation error | ||
| 1726 | */ | ||
| 1727 | struct usb_request *cdns3_gadget_ep_alloc_request(struct usb_ep *ep, | ||
| 1728 | gfp_t gfp_flags) | ||
| 1729 | { | ||
| 1730 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 1731 | struct cdns3_request *priv_req; | ||
| 1732 | |||
| 1733 | priv_req = kzalloc(sizeof(*priv_req), gfp_flags); | ||
| 1734 | if (!priv_req) | ||
| 1735 | return NULL; | ||
| 1736 | |||
| 1737 | priv_req->priv_ep = priv_ep; | ||
| 1738 | |||
| 1739 | trace_cdns3_alloc_request(priv_req); | ||
| 1740 | return &priv_req->request; | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | /** | ||
| 1744 | * cdns3_gadget_ep_free_request Free memory occupied by request | ||
| 1745 | * @ep: endpoint object associated with request | ||
| 1746 | * @request: request to free memory | ||
| 1747 | */ | ||
| 1748 | void cdns3_gadget_ep_free_request(struct usb_ep *ep, | ||
| 1749 | struct usb_request *request) | ||
| 1750 | { | ||
| 1751 | struct cdns3_request *priv_req = to_cdns3_request(request); | ||
| 1752 | |||
| 1753 | if (priv_req->aligned_buf) | ||
| 1754 | priv_req->aligned_buf->in_use = 0; | ||
| 1755 | |||
| 1756 | trace_cdns3_free_request(priv_req); | ||
| 1757 | kfree(priv_req); | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | /** | ||
| 1761 | * cdns3_gadget_ep_enable Enable endpoint | ||
| 1762 | * @ep: endpoint object | ||
| 1763 | * @desc: endpoint descriptor | ||
| 1764 | * | ||
| 1765 | * Returns 0 on success, error code elsewhere | ||
| 1766 | */ | ||
| 1767 | static int cdns3_gadget_ep_enable(struct usb_ep *ep, | ||
| 1768 | const struct usb_endpoint_descriptor *desc) | ||
| 1769 | { | ||
| 1770 | struct cdns3_endpoint *priv_ep; | ||
| 1771 | struct cdns3_device *priv_dev; | ||
| 1772 | u32 reg = EP_STS_EN_TRBERREN; | ||
| 1773 | u32 bEndpointAddress; | ||
| 1774 | unsigned long flags; | ||
| 1775 | int enable = 1; | ||
| 1776 | int ret; | ||
| 1777 | int val; | ||
| 1778 | |||
| 1779 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 1780 | priv_dev = priv_ep->cdns3_dev; | ||
| 1781 | |||
| 1782 | if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { | ||
| 1783 | dev_dbg(priv_dev->dev, "usbss: invalid parameters\n"); | ||
| 1784 | return -EINVAL; | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | if (!desc->wMaxPacketSize) { | ||
| 1788 | dev_err(priv_dev->dev, "usbss: missing wMaxPacketSize\n"); | ||
| 1789 | return -EINVAL; | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | if (dev_WARN_ONCE(priv_dev->dev, priv_ep->flags & EP_ENABLED, | ||
| 1793 | "%s is already enabled\n", priv_ep->name)) | ||
| 1794 | return 0; | ||
| 1795 | |||
| 1796 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 1797 | |||
| 1798 | priv_ep->endpoint.desc = desc; | ||
| 1799 | priv_ep->type = usb_endpoint_type(desc); | ||
| 1800 | priv_ep->interval = desc->bInterval ? BIT(desc->bInterval - 1) : 0; | ||
| 1801 | |||
| 1802 | if (priv_ep->interval > ISO_MAX_INTERVAL && | ||
| 1803 | priv_ep->type == USB_ENDPOINT_XFER_ISOC) { | ||
| 1804 | dev_err(priv_dev->dev, "Driver is limited to %d period\n", | ||
| 1805 | ISO_MAX_INTERVAL); | ||
| 1806 | |||
| 1807 | ret = -EINVAL; | ||
| 1808 | goto exit; | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | ret = cdns3_allocate_trb_pool(priv_ep); | ||
| 1812 | |||
| 1813 | if (ret) | ||
| 1814 | goto exit; | ||
| 1815 | |||
| 1816 | bEndpointAddress = priv_ep->num | priv_ep->dir; | ||
| 1817 | cdns3_select_ep(priv_dev, bEndpointAddress); | ||
| 1818 | |||
| 1819 | trace_cdns3_gadget_ep_enable(priv_ep); | ||
| 1820 | |||
| 1821 | writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd); | ||
| 1822 | |||
| 1823 | ret = readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, | ||
| 1824 | !(val & (EP_CMD_CSTALL | EP_CMD_EPRST)), | ||
| 1825 | 1, 1000); | ||
| 1826 | |||
| 1827 | if (unlikely(ret)) { | ||
| 1828 | cdns3_free_trb_pool(priv_ep); | ||
| 1829 | ret = -EINVAL; | ||
| 1830 | goto exit; | ||
| 1831 | } | ||
| 1832 | |||
| 1833 | /* enable interrupt for selected endpoint */ | ||
| 1834 | cdns3_set_register_bit(&priv_dev->regs->ep_ien, | ||
| 1835 | BIT(cdns3_ep_addr_to_index(bEndpointAddress))); | ||
| 1836 | |||
| 1837 | if (priv_dev->dev_ver < DEV_VER_V2) | ||
| 1838 | cdns3_wa2_enable_detection(priv_dev, priv_ep, reg); | ||
| 1839 | |||
| 1840 | writel(reg, &priv_dev->regs->ep_sts_en); | ||
| 1841 | |||
| 1842 | /* | ||
| 1843 | * For some versions of controller at some point during ISO OUT traffic | ||
| 1844 | * DMA reads Transfer Ring for the EP which has never got doorbell. | ||
| 1845 | * This issue was detected only on simulation, but to avoid this issue | ||
| 1846 | * driver add protection against it. To fix it driver enable ISO OUT | ||
| 1847 | * endpoint before setting DRBL. This special treatment of ISO OUT | ||
| 1848 | * endpoints are recommended by controller specification. | ||
| 1849 | */ | ||
| 1850 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir) | ||
| 1851 | enable = 0; | ||
| 1852 | |||
| 1853 | if (enable) | ||
| 1854 | cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE); | ||
| 1855 | |||
| 1856 | ep->desc = desc; | ||
| 1857 | priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING | | ||
| 1858 | EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN); | ||
| 1859 | priv_ep->flags |= EP_ENABLED | EP_UPDATE_EP_TRBADDR; | ||
| 1860 | priv_ep->wa1_set = 0; | ||
| 1861 | priv_ep->enqueue = 0; | ||
| 1862 | priv_ep->dequeue = 0; | ||
| 1863 | reg = readl(&priv_dev->regs->ep_sts); | ||
| 1864 | priv_ep->pcs = !!EP_STS_CCS(reg); | ||
| 1865 | priv_ep->ccs = !!EP_STS_CCS(reg); | ||
| 1866 | /* one TRB is reserved for link TRB used in DMULT mode*/ | ||
| 1867 | priv_ep->free_trbs = priv_ep->num_trbs - 1; | ||
| 1868 | exit: | ||
| 1869 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 1870 | |||
| 1871 | return ret; | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | /** | ||
| 1875 | * cdns3_gadget_ep_disable Disable endpoint | ||
| 1876 | * @ep: endpoint object | ||
| 1877 | * | ||
| 1878 | * Returns 0 on success, error code elsewhere | ||
| 1879 | */ | ||
| 1880 | static int cdns3_gadget_ep_disable(struct usb_ep *ep) | ||
| 1881 | { | ||
| 1882 | struct cdns3_endpoint *priv_ep; | ||
| 1883 | struct cdns3_request *priv_req; | ||
| 1884 | struct cdns3_device *priv_dev; | ||
| 1885 | struct usb_request *request; | ||
| 1886 | unsigned long flags; | ||
| 1887 | int ret = 0; | ||
| 1888 | u32 ep_cfg; | ||
| 1889 | int val; | ||
| 1890 | |||
| 1891 | if (!ep) { | ||
| 1892 | pr_err("usbss: invalid parameters\n"); | ||
| 1893 | return -EINVAL; | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 1897 | priv_dev = priv_ep->cdns3_dev; | ||
| 1898 | |||
| 1899 | if (dev_WARN_ONCE(priv_dev->dev, !(priv_ep->flags & EP_ENABLED), | ||
| 1900 | "%s is already disabled\n", priv_ep->name)) | ||
| 1901 | return 0; | ||
| 1902 | |||
| 1903 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 1904 | |||
| 1905 | trace_cdns3_gadget_ep_disable(priv_ep); | ||
| 1906 | |||
| 1907 | cdns3_select_ep(priv_dev, ep->desc->bEndpointAddress); | ||
| 1908 | |||
| 1909 | ep_cfg = readl(&priv_dev->regs->ep_cfg); | ||
| 1910 | ep_cfg &= ~EP_CFG_ENABLE; | ||
| 1911 | writel(ep_cfg, &priv_dev->regs->ep_cfg); | ||
| 1912 | |||
| 1913 | /** | ||
| 1914 | * Driver needs some time before resetting endpoint. | ||
| 1915 | * It need waits for clearing DBUSY bit or for timeout expired. | ||
| 1916 | * 10us is enough time for controller to stop transfer. | ||
| 1917 | */ | ||
| 1918 | readl_poll_timeout_atomic(&priv_dev->regs->ep_sts, val, | ||
| 1919 | !(val & EP_STS_DBUSY), 1, 10); | ||
| 1920 | writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd); | ||
| 1921 | |||
| 1922 | readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, | ||
| 1923 | !(val & (EP_CMD_CSTALL | EP_CMD_EPRST)), | ||
| 1924 | 1, 1000); | ||
| 1925 | if (unlikely(ret)) | ||
| 1926 | dev_err(priv_dev->dev, "Timeout: %s resetting failed.\n", | ||
| 1927 | priv_ep->name); | ||
| 1928 | |||
| 1929 | while (!list_empty(&priv_ep->pending_req_list)) { | ||
| 1930 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 1931 | |||
| 1932 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), | ||
| 1933 | -ESHUTDOWN); | ||
| 1934 | } | ||
| 1935 | |||
| 1936 | while (!list_empty(&priv_ep->wa2_descmiss_req_list)) { | ||
| 1937 | priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); | ||
| 1938 | |||
| 1939 | kfree(priv_req->request.buf); | ||
| 1940 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, | ||
| 1941 | &priv_req->request); | ||
| 1942 | list_del_init(&priv_req->list); | ||
| 1943 | --priv_ep->wa2_counter; | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | while (!list_empty(&priv_ep->deferred_req_list)) { | ||
| 1947 | request = cdns3_next_request(&priv_ep->deferred_req_list); | ||
| 1948 | |||
| 1949 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), | ||
| 1950 | -ESHUTDOWN); | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | priv_ep->descmis_req = NULL; | ||
| 1954 | |||
| 1955 | ep->desc = NULL; | ||
| 1956 | priv_ep->flags &= ~EP_ENABLED; | ||
| 1957 | |||
| 1958 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 1959 | |||
| 1960 | return ret; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | /** | ||
| 1964 | * cdns3_gadget_ep_queue Transfer data on endpoint | ||
| 1965 | * @ep: endpoint object | ||
| 1966 | * @request: request object | ||
| 1967 | * @gfp_flags: gfp flags | ||
| 1968 | * | ||
| 1969 | * Returns 0 on success, error code elsewhere | ||
| 1970 | */ | ||
| 1971 | static int __cdns3_gadget_ep_queue(struct usb_ep *ep, | ||
| 1972 | struct usb_request *request, | ||
| 1973 | gfp_t gfp_flags) | ||
| 1974 | { | ||
| 1975 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 1976 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 1977 | struct cdns3_request *priv_req; | ||
| 1978 | int ret = 0; | ||
| 1979 | |||
| 1980 | request->actual = 0; | ||
| 1981 | request->status = -EINPROGRESS; | ||
| 1982 | priv_req = to_cdns3_request(request); | ||
| 1983 | trace_cdns3_ep_queue(priv_req); | ||
| 1984 | |||
| 1985 | if (priv_dev->dev_ver < DEV_VER_V2) { | ||
| 1986 | ret = cdns3_wa2_gadget_ep_queue(priv_dev, priv_ep, | ||
| 1987 | priv_req); | ||
| 1988 | |||
| 1989 | if (ret == EINPROGRESS) | ||
| 1990 | return 0; | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | ret = cdns3_prepare_aligned_request_buf(priv_req); | ||
| 1994 | if (ret < 0) | ||
| 1995 | return ret; | ||
| 1996 | |||
| 1997 | ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, | ||
| 1998 | usb_endpoint_dir_in(ep->desc)); | ||
| 1999 | if (ret) | ||
| 2000 | return ret; | ||
| 2001 | |||
| 2002 | list_add_tail(&request->list, &priv_ep->deferred_req_list); | ||
| 2003 | |||
| 2004 | /* | ||
| 2005 | * If hardware endpoint configuration has not been set yet then | ||
| 2006 | * just queue request in deferred list. Transfer will be started in | ||
| 2007 | * cdns3_set_hw_configuration. | ||
| 2008 | */ | ||
| 2009 | if (priv_dev->hw_configured_flag && !(priv_ep->flags & EP_STALLED) && | ||
| 2010 | !(priv_ep->flags & EP_STALL_PENDING)) | ||
| 2011 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 2012 | |||
| 2013 | return 0; | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | static int cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, | ||
| 2017 | gfp_t gfp_flags) | ||
| 2018 | { | ||
| 2019 | struct usb_request *zlp_request; | ||
| 2020 | struct cdns3_endpoint *priv_ep; | ||
| 2021 | struct cdns3_device *priv_dev; | ||
| 2022 | unsigned long flags; | ||
| 2023 | int ret; | ||
| 2024 | |||
| 2025 | if (!request || !ep) | ||
| 2026 | return -EINVAL; | ||
| 2027 | |||
| 2028 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 2029 | priv_dev = priv_ep->cdns3_dev; | ||
| 2030 | |||
| 2031 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2032 | |||
| 2033 | ret = __cdns3_gadget_ep_queue(ep, request, gfp_flags); | ||
| 2034 | |||
| 2035 | if (ret == 0 && request->zero && request->length && | ||
| 2036 | (request->length % ep->maxpacket == 0)) { | ||
| 2037 | struct cdns3_request *priv_req; | ||
| 2038 | |||
| 2039 | zlp_request = cdns3_gadget_ep_alloc_request(ep, GFP_ATOMIC); | ||
| 2040 | zlp_request->buf = priv_dev->zlp_buf; | ||
| 2041 | zlp_request->length = 0; | ||
| 2042 | |||
| 2043 | priv_req = to_cdns3_request(zlp_request); | ||
| 2044 | priv_req->flags |= REQUEST_ZLP; | ||
| 2045 | |||
| 2046 | dev_dbg(priv_dev->dev, "Queuing ZLP for endpoint: %s\n", | ||
| 2047 | priv_ep->name); | ||
| 2048 | ret = __cdns3_gadget_ep_queue(ep, zlp_request, gfp_flags); | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2052 | return ret; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | /** | ||
| 2056 | * cdns3_gadget_ep_dequeue Remove request from transfer queue | ||
| 2057 | * @ep: endpoint object associated with request | ||
| 2058 | * @request: request object | ||
| 2059 | * | ||
| 2060 | * Returns 0 on success, error code elsewhere | ||
| 2061 | */ | ||
| 2062 | int cdns3_gadget_ep_dequeue(struct usb_ep *ep, | ||
| 2063 | struct usb_request *request) | ||
| 2064 | { | ||
| 2065 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 2066 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 2067 | struct usb_request *req, *req_temp; | ||
| 2068 | struct cdns3_request *priv_req; | ||
| 2069 | struct cdns3_trb *link_trb; | ||
| 2070 | unsigned long flags; | ||
| 2071 | int ret = 0; | ||
| 2072 | |||
| 2073 | if (!ep || !request || !ep->desc) | ||
| 2074 | return -EINVAL; | ||
| 2075 | |||
| 2076 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2077 | |||
| 2078 | priv_req = to_cdns3_request(request); | ||
| 2079 | |||
| 2080 | trace_cdns3_ep_dequeue(priv_req); | ||
| 2081 | |||
| 2082 | cdns3_select_ep(priv_dev, ep->desc->bEndpointAddress); | ||
| 2083 | |||
| 2084 | list_for_each_entry_safe(req, req_temp, &priv_ep->pending_req_list, | ||
| 2085 | list) { | ||
| 2086 | if (request == req) | ||
| 2087 | goto found; | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | list_for_each_entry_safe(req, req_temp, &priv_ep->deferred_req_list, | ||
| 2091 | list) { | ||
| 2092 | if (request == req) | ||
| 2093 | goto found; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | goto not_found; | ||
| 2097 | |||
| 2098 | found: | ||
| 2099 | |||
| 2100 | if (priv_ep->wa1_trb == priv_req->trb) | ||
| 2101 | cdns3_wa1_restore_cycle_bit(priv_ep); | ||
| 2102 | |||
| 2103 | link_trb = priv_req->trb; | ||
| 2104 | cdns3_move_deq_to_next_trb(priv_req); | ||
| 2105 | cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET); | ||
| 2106 | |||
| 2107 | /* Update ring */ | ||
| 2108 | request = cdns3_next_request(&priv_ep->deferred_req_list); | ||
| 2109 | if (request) { | ||
| 2110 | priv_req = to_cdns3_request(request); | ||
| 2111 | |||
| 2112 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + | ||
| 2113 | (priv_req->start_trb * TRB_SIZE)); | ||
| 2114 | link_trb->control = (link_trb->control & TRB_CYCLE) | | ||
| 2115 | TRB_TYPE(TRB_LINK) | TRB_CHAIN | TRB_TOGGLE; | ||
| 2116 | } else { | ||
| 2117 | priv_ep->flags |= EP_UPDATE_EP_TRBADDR; | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | not_found: | ||
| 2121 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2122 | return ret; | ||
| 2123 | } | ||
| 2124 | |||
| 2125 | /** | ||
| 2126 | * __cdns3_gadget_ep_set_halt Sets stall on selected endpoint | ||
| 2127 | * Should be called after acquiring spin_lock and selecting ep | ||
| 2128 | * @ep: endpoint object to set stall on. | ||
| 2129 | */ | ||
| 2130 | void __cdns3_gadget_ep_set_halt(struct cdns3_endpoint *priv_ep) | ||
| 2131 | { | ||
| 2132 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 2133 | |||
| 2134 | trace_cdns3_halt(priv_ep, 1, 0); | ||
| 2135 | |||
| 2136 | if (!(priv_ep->flags & EP_STALLED)) { | ||
| 2137 | u32 ep_sts_reg = readl(&priv_dev->regs->ep_sts); | ||
| 2138 | |||
| 2139 | if (!(ep_sts_reg & EP_STS_DBUSY)) | ||
| 2140 | cdns3_ep_stall_flush(priv_ep); | ||
| 2141 | else | ||
| 2142 | priv_ep->flags |= EP_STALL_PENDING; | ||
| 2143 | } | ||
| 2144 | } | ||
| 2145 | |||
| 2146 | /** | ||
| 2147 | * __cdns3_gadget_ep_clear_halt Clears stall on selected endpoint | ||
| 2148 | * Should be called after acquiring spin_lock and selecting ep | ||
| 2149 | * @ep: endpoint object to clear stall on | ||
| 2150 | */ | ||
| 2151 | int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) | ||
| 2152 | { | ||
| 2153 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 2154 | struct usb_request *request; | ||
| 2155 | int ret; | ||
| 2156 | int val; | ||
| 2157 | |||
| 2158 | trace_cdns3_halt(priv_ep, 0, 0); | ||
| 2159 | |||
| 2160 | writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); | ||
| 2161 | |||
| 2162 | /* wait for EPRST cleared */ | ||
| 2163 | ret = readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, | ||
| 2164 | !(val & EP_CMD_EPRST), 1, 100); | ||
| 2165 | if (ret) | ||
| 2166 | return -EINVAL; | ||
| 2167 | |||
| 2168 | priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING); | ||
| 2169 | |||
| 2170 | request = cdns3_next_request(&priv_ep->pending_req_list); | ||
| 2171 | |||
| 2172 | if (request) | ||
| 2173 | cdns3_rearm_transfer(priv_ep, 1); | ||
| 2174 | |||
| 2175 | cdns3_start_all_request(priv_dev, priv_ep); | ||
| 2176 | return ret; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | /** | ||
| 2180 | * cdns3_gadget_ep_set_halt Sets/clears stall on selected endpoint | ||
| 2181 | * @ep: endpoint object to set/clear stall on | ||
| 2182 | * @value: 1 for set stall, 0 for clear stall | ||
| 2183 | * | ||
| 2184 | * Returns 0 on success, error code elsewhere | ||
| 2185 | */ | ||
| 2186 | int cdns3_gadget_ep_set_halt(struct usb_ep *ep, int value) | ||
| 2187 | { | ||
| 2188 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); | ||
| 2189 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | ||
| 2190 | unsigned long flags; | ||
| 2191 | int ret = 0; | ||
| 2192 | |||
| 2193 | if (!(priv_ep->flags & EP_ENABLED)) | ||
| 2194 | return -EPERM; | ||
| 2195 | |||
| 2196 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2197 | |||
| 2198 | cdns3_select_ep(priv_dev, ep->desc->bEndpointAddress); | ||
| 2199 | |||
| 2200 | if (!value) { | ||
| 2201 | priv_ep->flags &= ~EP_WEDGE; | ||
| 2202 | ret = __cdns3_gadget_ep_clear_halt(priv_ep); | ||
| 2203 | } else { | ||
| 2204 | __cdns3_gadget_ep_set_halt(priv_ep); | ||
| 2205 | } | ||
| 2206 | |||
| 2207 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2208 | |||
| 2209 | return ret; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | extern const struct usb_ep_ops cdns3_gadget_ep0_ops; | ||
| 2213 | |||
| 2214 | static const struct usb_ep_ops cdns3_gadget_ep_ops = { | ||
| 2215 | .enable = cdns3_gadget_ep_enable, | ||
| 2216 | .disable = cdns3_gadget_ep_disable, | ||
| 2217 | .alloc_request = cdns3_gadget_ep_alloc_request, | ||
| 2218 | .free_request = cdns3_gadget_ep_free_request, | ||
| 2219 | .queue = cdns3_gadget_ep_queue, | ||
| 2220 | .dequeue = cdns3_gadget_ep_dequeue, | ||
| 2221 | .set_halt = cdns3_gadget_ep_set_halt, | ||
| 2222 | .set_wedge = cdns3_gadget_ep_set_wedge, | ||
| 2223 | }; | ||
| 2224 | |||
| 2225 | /** | ||
| 2226 | * cdns3_gadget_get_frame Returns number of actual ITP frame | ||
| 2227 | * @gadget: gadget object | ||
| 2228 | * | ||
| 2229 | * Returns number of actual ITP frame | ||
| 2230 | */ | ||
| 2231 | static int cdns3_gadget_get_frame(struct usb_gadget *gadget) | ||
| 2232 | { | ||
| 2233 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2234 | |||
| 2235 | return readl(&priv_dev->regs->usb_itpn); | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev) | ||
| 2239 | { | ||
| 2240 | enum usb_device_speed speed; | ||
| 2241 | |||
| 2242 | speed = cdns3_get_speed(priv_dev); | ||
| 2243 | |||
| 2244 | if (speed >= USB_SPEED_SUPER) | ||
| 2245 | return 0; | ||
| 2246 | |||
| 2247 | /* Start driving resume signaling to indicate remote wakeup. */ | ||
| 2248 | writel(USB_CONF_LGO_L0, &priv_dev->regs->usb_conf); | ||
| 2249 | |||
| 2250 | return 0; | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | static int cdns3_gadget_wakeup(struct usb_gadget *gadget) | ||
| 2254 | { | ||
| 2255 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2256 | unsigned long flags; | ||
| 2257 | int ret = 0; | ||
| 2258 | |||
| 2259 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2260 | ret = __cdns3_gadget_wakeup(priv_dev); | ||
| 2261 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2262 | return ret; | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | static int cdns3_gadget_set_selfpowered(struct usb_gadget *gadget, | ||
| 2266 | int is_selfpowered) | ||
| 2267 | { | ||
| 2268 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2269 | unsigned long flags; | ||
| 2270 | |||
| 2271 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2272 | priv_dev->is_selfpowered = !!is_selfpowered; | ||
| 2273 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2274 | return 0; | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | static int cdns3_gadget_pullup(struct usb_gadget *gadget, int is_on) | ||
| 2278 | { | ||
| 2279 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2280 | |||
| 2281 | if (is_on) | ||
| 2282 | writel(USB_CONF_DEVEN, &priv_dev->regs->usb_conf); | ||
| 2283 | else | ||
| 2284 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); | ||
| 2285 | |||
| 2286 | return 0; | ||
| 2287 | } | ||
| 2288 | |||
| 2289 | static void cdns3_gadget_config(struct cdns3_device *priv_dev) | ||
| 2290 | { | ||
| 2291 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; | ||
| 2292 | u32 reg; | ||
| 2293 | |||
| 2294 | cdns3_ep0_config(priv_dev); | ||
| 2295 | |||
| 2296 | /* enable interrupts for endpoint 0 (in and out) */ | ||
| 2297 | writel(EP_IEN_EP_OUT0 | EP_IEN_EP_IN0, ®s->ep_ien); | ||
| 2298 | |||
| 2299 | /* | ||
| 2300 | * Driver needs to modify LFPS minimal U1 Exit time for DEV_VER_TI_V1 | ||
| 2301 | * revision of controller. | ||
| 2302 | */ | ||
| 2303 | if (priv_dev->dev_ver == DEV_VER_TI_V1) { | ||
| 2304 | reg = readl(®s->dbg_link1); | ||
| 2305 | |||
| 2306 | reg &= ~DBG_LINK1_LFPS_MIN_GEN_U1_EXIT_MASK; | ||
| 2307 | reg |= DBG_LINK1_LFPS_MIN_GEN_U1_EXIT(0x55) | | ||
| 2308 | DBG_LINK1_LFPS_MIN_GEN_U1_EXIT_SET; | ||
| 2309 | writel(reg, ®s->dbg_link1); | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | /* | ||
| 2313 | * By default some platforms has set protected access to memory. | ||
| 2314 | * This cause problem with cache, so driver restore non-secure | ||
| 2315 | * access to memory. | ||
| 2316 | */ | ||
| 2317 | reg = readl(®s->dma_axi_ctrl); | ||
| 2318 | reg |= DMA_AXI_CTRL_MARPROT(DMA_AXI_CTRL_NON_SECURE) | | ||
| 2319 | DMA_AXI_CTRL_MAWPROT(DMA_AXI_CTRL_NON_SECURE); | ||
| 2320 | writel(reg, ®s->dma_axi_ctrl); | ||
| 2321 | |||
| 2322 | /* enable generic interrupt*/ | ||
| 2323 | writel(USB_IEN_INIT, ®s->usb_ien); | ||
| 2324 | writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, ®s->usb_conf); | ||
| 2325 | |||
| 2326 | cdns3_configure_dmult(priv_dev, NULL); | ||
| 2327 | |||
| 2328 | cdns3_gadget_pullup(&priv_dev->gadget, 1); | ||
| 2329 | } | ||
| 2330 | |||
| 2331 | /** | ||
| 2332 | * cdns3_gadget_udc_start Gadget start | ||
| 2333 | * @gadget: gadget object | ||
| 2334 | * @driver: driver which operates on this gadget | ||
| 2335 | * | ||
| 2336 | * Returns 0 on success, error code elsewhere | ||
| 2337 | */ | ||
| 2338 | static int cdns3_gadget_udc_start(struct usb_gadget *gadget, | ||
| 2339 | struct usb_gadget_driver *driver) | ||
| 2340 | { | ||
| 2341 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2342 | unsigned long flags; | ||
| 2343 | |||
| 2344 | spin_lock_irqsave(&priv_dev->lock, flags); | ||
| 2345 | priv_dev->gadget_driver = driver; | ||
| 2346 | cdns3_gadget_config(priv_dev); | ||
| 2347 | spin_unlock_irqrestore(&priv_dev->lock, flags); | ||
| 2348 | return 0; | ||
| 2349 | } | ||
| 2350 | |||
| 2351 | /** | ||
| 2352 | * cdns3_gadget_udc_stop Stops gadget | ||
| 2353 | * @gadget: gadget object | ||
| 2354 | * | ||
| 2355 | * Returns 0 | ||
| 2356 | */ | ||
| 2357 | static int cdns3_gadget_udc_stop(struct usb_gadget *gadget) | ||
| 2358 | { | ||
| 2359 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | ||
| 2360 | struct cdns3_endpoint *priv_ep; | ||
| 2361 | u32 bEndpointAddress; | ||
| 2362 | struct usb_ep *ep; | ||
| 2363 | int ret = 0; | ||
| 2364 | int val; | ||
| 2365 | |||
| 2366 | priv_dev->gadget_driver = NULL; | ||
| 2367 | |||
| 2368 | priv_dev->onchip_used_size = 0; | ||
| 2369 | priv_dev->out_mem_is_allocated = 0; | ||
| 2370 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 2371 | |||
| 2372 | list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) { | ||
| 2373 | priv_ep = ep_to_cdns3_ep(ep); | ||
| 2374 | bEndpointAddress = priv_ep->num | priv_ep->dir; | ||
| 2375 | cdns3_select_ep(priv_dev, bEndpointAddress); | ||
| 2376 | writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd); | ||
| 2377 | readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, | ||
| 2378 | !(val & EP_CMD_EPRST), 1, 100); | ||
| 2379 | } | ||
| 2380 | |||
| 2381 | /* disable interrupt for device */ | ||
| 2382 | writel(0, &priv_dev->regs->usb_ien); | ||
| 2383 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); | ||
| 2384 | |||
| 2385 | return ret; | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | static const struct usb_gadget_ops cdns3_gadget_ops = { | ||
| 2389 | .get_frame = cdns3_gadget_get_frame, | ||
| 2390 | .wakeup = cdns3_gadget_wakeup, | ||
| 2391 | .set_selfpowered = cdns3_gadget_set_selfpowered, | ||
| 2392 | .pullup = cdns3_gadget_pullup, | ||
| 2393 | .udc_start = cdns3_gadget_udc_start, | ||
| 2394 | .udc_stop = cdns3_gadget_udc_stop, | ||
| 2395 | .match_ep = cdns3_gadget_match_ep, | ||
| 2396 | }; | ||
| 2397 | |||
| 2398 | static void cdns3_free_all_eps(struct cdns3_device *priv_dev) | ||
| 2399 | { | ||
| 2400 | int i; | ||
| 2401 | |||
| 2402 | /* ep0 OUT point to ep0 IN. */ | ||
| 2403 | priv_dev->eps[16] = NULL; | ||
| 2404 | |||
| 2405 | for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) | ||
| 2406 | if (priv_dev->eps[i]) { | ||
| 2407 | cdns3_free_trb_pool(priv_dev->eps[i]); | ||
| 2408 | devm_kfree(priv_dev->dev, priv_dev->eps[i]); | ||
| 2409 | } | ||
| 2410 | } | ||
| 2411 | |||
| 2412 | /** | ||
| 2413 | * cdns3_init_eps Initializes software endpoints of gadget | ||
| 2414 | * @cdns3: extended gadget object | ||
| 2415 | * | ||
| 2416 | * Returns 0 on success, error code elsewhere | ||
| 2417 | */ | ||
| 2418 | static int cdns3_init_eps(struct cdns3_device *priv_dev) | ||
| 2419 | { | ||
| 2420 | u32 ep_enabled_reg, iso_ep_reg; | ||
| 2421 | struct cdns3_endpoint *priv_ep; | ||
| 2422 | int ep_dir, ep_number; | ||
| 2423 | u32 ep_mask; | ||
| 2424 | int ret = 0; | ||
| 2425 | int i; | ||
| 2426 | |||
| 2427 | /* Read it from USB_CAP3 to USB_CAP5 */ | ||
| 2428 | ep_enabled_reg = readl(&priv_dev->regs->usb_cap3); | ||
| 2429 | iso_ep_reg = readl(&priv_dev->regs->usb_cap4); | ||
| 2430 | |||
| 2431 | dev_dbg(priv_dev->dev, "Initializing non-zero endpoints\n"); | ||
| 2432 | |||
| 2433 | for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) { | ||
| 2434 | ep_dir = i >> 4; /* i div 16 */ | ||
| 2435 | ep_number = i & 0xF; /* i % 16 */ | ||
| 2436 | ep_mask = BIT(i); | ||
| 2437 | |||
| 2438 | if (!(ep_enabled_reg & ep_mask)) | ||
| 2439 | continue; | ||
| 2440 | |||
| 2441 | if (ep_dir && !ep_number) { | ||
| 2442 | priv_dev->eps[i] = priv_dev->eps[0]; | ||
| 2443 | continue; | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | priv_ep = devm_kzalloc(priv_dev->dev, sizeof(*priv_ep), | ||
| 2447 | GFP_KERNEL); | ||
| 2448 | if (!priv_ep) | ||
| 2449 | goto err; | ||
| 2450 | |||
| 2451 | /* set parent of endpoint object */ | ||
| 2452 | priv_ep->cdns3_dev = priv_dev; | ||
| 2453 | priv_dev->eps[i] = priv_ep; | ||
| 2454 | priv_ep->num = ep_number; | ||
| 2455 | priv_ep->dir = ep_dir ? USB_DIR_IN : USB_DIR_OUT; | ||
| 2456 | |||
| 2457 | if (!ep_number) { | ||
| 2458 | ret = cdns3_init_ep0(priv_dev, priv_ep); | ||
| 2459 | if (ret) { | ||
| 2460 | dev_err(priv_dev->dev, "Failed to init ep0\n"); | ||
| 2461 | goto err; | ||
| 2462 | } | ||
| 2463 | } else { | ||
| 2464 | snprintf(priv_ep->name, sizeof(priv_ep->name), "ep%d%s", | ||
| 2465 | ep_number, !!ep_dir ? "in" : "out"); | ||
| 2466 | priv_ep->endpoint.name = priv_ep->name; | ||
| 2467 | |||
| 2468 | usb_ep_set_maxpacket_limit(&priv_ep->endpoint, | ||
| 2469 | CDNS3_EP_MAX_PACKET_LIMIT); | ||
| 2470 | priv_ep->endpoint.max_streams = CDNS3_EP_MAX_STREAMS; | ||
| 2471 | priv_ep->endpoint.ops = &cdns3_gadget_ep_ops; | ||
| 2472 | if (ep_dir) | ||
| 2473 | priv_ep->endpoint.caps.dir_in = 1; | ||
| 2474 | else | ||
| 2475 | priv_ep->endpoint.caps.dir_out = 1; | ||
| 2476 | |||
| 2477 | if (iso_ep_reg & ep_mask) | ||
| 2478 | priv_ep->endpoint.caps.type_iso = 1; | ||
| 2479 | |||
| 2480 | priv_ep->endpoint.caps.type_bulk = 1; | ||
| 2481 | priv_ep->endpoint.caps.type_int = 1; | ||
| 2482 | |||
| 2483 | list_add_tail(&priv_ep->endpoint.ep_list, | ||
| 2484 | &priv_dev->gadget.ep_list); | ||
| 2485 | } | ||
| 2486 | |||
| 2487 | priv_ep->flags = 0; | ||
| 2488 | |||
| 2489 | dev_info(priv_dev->dev, "Initialized %s support: %s %s\n", | ||
| 2490 | priv_ep->name, | ||
| 2491 | priv_ep->endpoint.caps.type_bulk ? "BULK, INT" : "", | ||
| 2492 | priv_ep->endpoint.caps.type_iso ? "ISO" : ""); | ||
| 2493 | |||
| 2494 | INIT_LIST_HEAD(&priv_ep->pending_req_list); | ||
| 2495 | INIT_LIST_HEAD(&priv_ep->deferred_req_list); | ||
| 2496 | INIT_LIST_HEAD(&priv_ep->wa2_descmiss_req_list); | ||
| 2497 | } | ||
| 2498 | |||
| 2499 | return 0; | ||
| 2500 | err: | ||
| 2501 | cdns3_free_all_eps(priv_dev); | ||
| 2502 | return -ENOMEM; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | void cdns3_gadget_exit(struct cdns3 *cdns) | ||
| 2506 | { | ||
| 2507 | struct cdns3_device *priv_dev; | ||
| 2508 | |||
| 2509 | priv_dev = cdns->gadget_dev; | ||
| 2510 | |||
| 2511 | devm_free_irq(cdns->dev, cdns->dev_irq, cdns); | ||
| 2512 | |||
| 2513 | pm_runtime_mark_last_busy(cdns->dev); | ||
| 2514 | pm_runtime_put_autosuspend(cdns->dev); | ||
| 2515 | |||
| 2516 | usb_del_gadget_udc(&priv_dev->gadget); | ||
| 2517 | |||
| 2518 | cdns3_free_all_eps(priv_dev); | ||
| 2519 | |||
| 2520 | while (!list_empty(&priv_dev->aligned_buf_list)) { | ||
| 2521 | struct cdns3_aligned_buf *buf; | ||
| 2522 | |||
| 2523 | buf = cdns3_next_align_buf(&priv_dev->aligned_buf_list); | ||
| 2524 | dma_free_coherent(priv_dev->sysdev, buf->size, | ||
| 2525 | buf->buf, | ||
| 2526 | buf->dma); | ||
| 2527 | |||
| 2528 | list_del(&buf->list); | ||
| 2529 | kfree(buf); | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | dma_free_coherent(priv_dev->sysdev, 8, priv_dev->setup_buf, | ||
| 2533 | priv_dev->setup_dma); | ||
| 2534 | |||
| 2535 | kfree(priv_dev->zlp_buf); | ||
| 2536 | kfree(priv_dev); | ||
| 2537 | cdns->gadget_dev = NULL; | ||
| 2538 | cdns3_drd_switch_gadget(cdns, 0); | ||
| 2539 | } | ||
| 2540 | |||
| 2541 | static int cdns3_gadget_start(struct cdns3 *cdns) | ||
| 2542 | { | ||
| 2543 | struct cdns3_device *priv_dev; | ||
| 2544 | u32 max_speed; | ||
| 2545 | int ret; | ||
| 2546 | |||
| 2547 | priv_dev = kzalloc(sizeof(*priv_dev), GFP_KERNEL); | ||
| 2548 | if (!priv_dev) | ||
| 2549 | return -ENOMEM; | ||
| 2550 | |||
| 2551 | cdns->gadget_dev = priv_dev; | ||
| 2552 | priv_dev->sysdev = cdns->dev; | ||
| 2553 | priv_dev->dev = cdns->dev; | ||
| 2554 | priv_dev->regs = cdns->dev_regs; | ||
| 2555 | |||
| 2556 | device_property_read_u16(priv_dev->dev, "cdns,on-chip-buff-size", | ||
| 2557 | &priv_dev->onchip_buffers); | ||
| 2558 | |||
| 2559 | if (priv_dev->onchip_buffers <= 0) { | ||
| 2560 | u32 reg = readl(&priv_dev->regs->usb_cap2); | ||
| 2561 | |||
| 2562 | priv_dev->onchip_buffers = USB_CAP2_ACTUAL_MEM_SIZE(reg); | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | if (!priv_dev->onchip_buffers) | ||
| 2566 | priv_dev->onchip_buffers = 256; | ||
| 2567 | |||
| 2568 | max_speed = usb_get_maximum_speed(cdns->dev); | ||
| 2569 | |||
| 2570 | /* Check the maximum_speed parameter */ | ||
| 2571 | switch (max_speed) { | ||
| 2572 | case USB_SPEED_FULL: | ||
| 2573 | writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf); | ||
| 2574 | break; | ||
| 2575 | case USB_SPEED_HIGH: | ||
| 2576 | writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf); | ||
| 2577 | break; | ||
| 2578 | case USB_SPEED_SUPER: | ||
| 2579 | break; | ||
| 2580 | default: | ||
| 2581 | dev_err(cdns->dev, "invalid maximum_speed parameter %d\n", | ||
| 2582 | max_speed); | ||
| 2583 | /* fall through */ | ||
| 2584 | case USB_SPEED_UNKNOWN: | ||
| 2585 | /* default to superspeed */ | ||
| 2586 | max_speed = USB_SPEED_SUPER; | ||
| 2587 | break; | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | /* fill gadget fields */ | ||
| 2591 | priv_dev->gadget.max_speed = max_speed; | ||
| 2592 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 2593 | priv_dev->gadget.ops = &cdns3_gadget_ops; | ||
| 2594 | priv_dev->gadget.name = "usb-ss-gadget"; | ||
| 2595 | priv_dev->gadget.sg_supported = 1; | ||
| 2596 | priv_dev->gadget.quirk_avoids_skb_reserve = 1; | ||
| 2597 | |||
| 2598 | spin_lock_init(&priv_dev->lock); | ||
| 2599 | INIT_WORK(&priv_dev->pending_status_wq, | ||
| 2600 | cdns3_pending_setup_status_handler); | ||
| 2601 | |||
| 2602 | INIT_WORK(&priv_dev->aligned_buf_wq, | ||
| 2603 | cdns3_free_aligned_request_buf); | ||
| 2604 | |||
| 2605 | /* initialize endpoint container */ | ||
| 2606 | INIT_LIST_HEAD(&priv_dev->gadget.ep_list); | ||
| 2607 | INIT_LIST_HEAD(&priv_dev->aligned_buf_list); | ||
| 2608 | |||
| 2609 | ret = cdns3_init_eps(priv_dev); | ||
| 2610 | if (ret) { | ||
| 2611 | dev_err(priv_dev->dev, "Failed to create endpoints\n"); | ||
| 2612 | goto err1; | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | /* allocate memory for setup packet buffer */ | ||
| 2616 | priv_dev->setup_buf = dma_alloc_coherent(priv_dev->sysdev, 8, | ||
| 2617 | &priv_dev->setup_dma, GFP_DMA); | ||
| 2618 | if (!priv_dev->setup_buf) { | ||
| 2619 | ret = -ENOMEM; | ||
| 2620 | goto err2; | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | priv_dev->dev_ver = readl(&priv_dev->regs->usb_cap6); | ||
| 2624 | |||
| 2625 | dev_dbg(priv_dev->dev, "Device Controller version: %08x\n", | ||
| 2626 | readl(&priv_dev->regs->usb_cap6)); | ||
| 2627 | dev_dbg(priv_dev->dev, "USB Capabilities:: %08x\n", | ||
| 2628 | readl(&priv_dev->regs->usb_cap1)); | ||
| 2629 | dev_dbg(priv_dev->dev, "On-Chip memory configuration: %08x\n", | ||
| 2630 | readl(&priv_dev->regs->usb_cap2)); | ||
| 2631 | |||
| 2632 | priv_dev->dev_ver = GET_DEV_BASE_VERSION(priv_dev->dev_ver); | ||
| 2633 | |||
| 2634 | priv_dev->zlp_buf = kzalloc(CDNS3_EP_ZLP_BUF_SIZE, GFP_KERNEL); | ||
| 2635 | if (!priv_dev->zlp_buf) { | ||
| 2636 | ret = -ENOMEM; | ||
| 2637 | goto err3; | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | /* add USB gadget device */ | ||
| 2641 | ret = usb_add_gadget_udc(priv_dev->dev, &priv_dev->gadget); | ||
| 2642 | if (ret < 0) { | ||
| 2643 | dev_err(priv_dev->dev, | ||
| 2644 | "Failed to register USB device controller\n"); | ||
| 2645 | goto err4; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | return 0; | ||
| 2649 | err4: | ||
| 2650 | kfree(priv_dev->zlp_buf); | ||
| 2651 | err3: | ||
| 2652 | dma_free_coherent(priv_dev->sysdev, 8, priv_dev->setup_buf, | ||
| 2653 | priv_dev->setup_dma); | ||
| 2654 | err2: | ||
| 2655 | cdns3_free_all_eps(priv_dev); | ||
| 2656 | err1: | ||
| 2657 | cdns->gadget_dev = NULL; | ||
| 2658 | return ret; | ||
| 2659 | } | ||
| 2660 | |||
| 2661 | static int __cdns3_gadget_init(struct cdns3 *cdns) | ||
| 2662 | { | ||
| 2663 | int ret = 0; | ||
| 2664 | |||
| 2665 | cdns3_drd_switch_gadget(cdns, 1); | ||
| 2666 | pm_runtime_get_sync(cdns->dev); | ||
| 2667 | |||
| 2668 | ret = cdns3_gadget_start(cdns); | ||
| 2669 | if (ret) | ||
| 2670 | return ret; | ||
| 2671 | |||
| 2672 | /* | ||
| 2673 | * Because interrupt line can be shared with other components in | ||
| 2674 | * driver it can't use IRQF_ONESHOT flag here. | ||
| 2675 | */ | ||
| 2676 | ret = devm_request_threaded_irq(cdns->dev, cdns->dev_irq, | ||
| 2677 | cdns3_device_irq_handler, | ||
| 2678 | cdns3_device_thread_irq_handler, | ||
| 2679 | IRQF_SHARED, dev_name(cdns->dev), cdns); | ||
| 2680 | |||
| 2681 | if (ret) | ||
| 2682 | goto err0; | ||
| 2683 | |||
| 2684 | return 0; | ||
| 2685 | err0: | ||
| 2686 | cdns3_gadget_exit(cdns); | ||
| 2687 | return ret; | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup) | ||
| 2691 | { | ||
| 2692 | struct cdns3_device *priv_dev = cdns->gadget_dev; | ||
| 2693 | |||
| 2694 | cdns3_disconnect_gadget(priv_dev); | ||
| 2695 | |||
| 2696 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 2697 | usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED); | ||
| 2698 | cdns3_hw_reset_eps_config(priv_dev); | ||
| 2699 | |||
| 2700 | /* disable interrupt for device */ | ||
| 2701 | writel(0, &priv_dev->regs->usb_ien); | ||
| 2702 | |||
| 2703 | cdns3_gadget_pullup(&priv_dev->gadget, 0); | ||
| 2704 | |||
| 2705 | return 0; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | static int cdns3_gadget_resume(struct cdns3 *cdns, bool hibernated) | ||
| 2709 | { | ||
| 2710 | struct cdns3_device *priv_dev = cdns->gadget_dev; | ||
| 2711 | |||
| 2712 | if (!priv_dev->gadget_driver) | ||
| 2713 | return 0; | ||
| 2714 | |||
| 2715 | cdns3_gadget_config(priv_dev); | ||
| 2716 | |||
| 2717 | return 0; | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | /** | ||
| 2721 | * cdns3_gadget_init - initialize device structure | ||
| 2722 | * | ||
| 2723 | * cdns: cdns3 instance | ||
| 2724 | * | ||
| 2725 | * This function initializes the gadget. | ||
| 2726 | */ | ||
| 2727 | int cdns3_gadget_init(struct cdns3 *cdns) | ||
| 2728 | { | ||
| 2729 | struct cdns3_role_driver *rdrv; | ||
| 2730 | |||
| 2731 | rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); | ||
| 2732 | if (!rdrv) | ||
| 2733 | return -ENOMEM; | ||
| 2734 | |||
| 2735 | rdrv->start = __cdns3_gadget_init; | ||
| 2736 | rdrv->stop = cdns3_gadget_exit; | ||
| 2737 | rdrv->suspend = cdns3_gadget_suspend; | ||
| 2738 | rdrv->resume = cdns3_gadget_resume; | ||
| 2739 | rdrv->state = CDNS3_ROLE_STATE_INACTIVE; | ||
| 2740 | rdrv->name = "gadget"; | ||
| 2741 | cdns->roles[USB_ROLE_DEVICE] = rdrv; | ||
| 2742 | |||
| 2743 | return 0; | ||
| 2744 | } | ||
| @@ -0,0 +1,1338 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * USBSS device controller driver header file | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * | ||
| 8 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 9 | * Pawel Jez <pjez@cadence.com> | ||
| 10 | * Peter Chen <peter.chen@nxp.com> | ||
| 11 | */ | ||
| 12 | #ifndef __LINUX_CDNS3_GADGET | ||
| 13 | #define __LINUX_CDNS3_GADGET | ||
| 14 | #include <linux/usb/gadget.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * USBSS-DEV register interface. | ||
| 18 | * This corresponds to the USBSS Device Controller Interface | ||
| 19 | */ | ||
| 20 | |||
| 21 | /** | ||
| 22 | * struct cdns3_usb_regs - device controller registers. | ||
| 23 | * @usb_conf: Global Configuration. | ||
| 24 | * @usb_sts: Global Status. | ||
| 25 | * @usb_cmd: Global Command. | ||
| 26 | * @usb_itpn: ITP/SOF number. | ||
| 27 | * @usb_lpm: Global Command. | ||
| 28 | * @usb_ien: USB Interrupt Enable. | ||
| 29 | * @usb_ists: USB Interrupt Status. | ||
| 30 | * @ep_sel: Endpoint Select. | ||
| 31 | * @ep_traddr: Endpoint Transfer Ring Address. | ||
| 32 | * @ep_cfg: Endpoint Configuration. | ||
| 33 | * @ep_cmd: Endpoint Command. | ||
| 34 | * @ep_sts: Endpoint Status. | ||
| 35 | * @ep_sts_sid: Endpoint Status. | ||
| 36 | * @ep_sts_en: Endpoint Status Enable. | ||
| 37 | * @drbl: Doorbell. | ||
| 38 | * @ep_ien: EP Interrupt Enable. | ||
| 39 | * @ep_ists: EP Interrupt Status. | ||
| 40 | * @usb_pwr: Global Power Configuration. | ||
| 41 | * @usb_conf2: Global Configuration 2. | ||
| 42 | * @usb_cap1: Capability 1. | ||
| 43 | * @usb_cap2: Capability 2. | ||
| 44 | * @usb_cap3: Capability 3. | ||
| 45 | * @usb_cap4: Capability 4. | ||
| 46 | * @usb_cap5: Capability 5. | ||
| 47 | * @usb_cap6: Capability 6. | ||
| 48 | * @usb_cpkt1: Custom Packet 1. | ||
| 49 | * @usb_cpkt2: Custom Packet 2. | ||
| 50 | * @usb_cpkt3: Custom Packet 3. | ||
| 51 | * @ep_dma_ext_addr: Upper address for DMA operations. | ||
| 52 | * @buf_addr: Address for On-chip Buffer operations. | ||
| 53 | * @buf_data: Data for On-chip Buffer operations. | ||
| 54 | * @buf_ctrl: On-chip Buffer Access Control. | ||
| 55 | * @dtrans: DMA Transfer Mode. | ||
| 56 | * @tdl_from_trb: Source of TD Configuration. | ||
| 57 | * @tdl_beh: TDL Behavior Configuration. | ||
| 58 | * @ep_tdl: Endpoint TDL. | ||
| 59 | * @tdl_beh2: TDL Behavior 2 Configuration. | ||
| 60 | * @dma_adv_td: DMA Advance TD Configuration. | ||
| 61 | * @reserved1: Reserved. | ||
| 62 | * @cfg_regs: Configuration. | ||
| 63 | * @reserved2: Reserved. | ||
| 64 | * @dma_axi_ctrl: AXI Control. | ||
| 65 | * @dma_axi_id: AXI ID register. | ||
| 66 | * @dma_axi_cap: AXI Capability. | ||
| 67 | * @dma_axi_ctrl0: AXI Control 0. | ||
| 68 | * @dma_axi_ctrl1: AXI Control 1. | ||
| 69 | */ | ||
| 70 | struct cdns3_usb_regs { | ||
| 71 | __le32 usb_conf; | ||
| 72 | __le32 usb_sts; | ||
| 73 | __le32 usb_cmd; | ||
| 74 | __le32 usb_itpn; | ||
| 75 | __le32 usb_lpm; | ||
| 76 | __le32 usb_ien; | ||
| 77 | __le32 usb_ists; | ||
| 78 | __le32 ep_sel; | ||
| 79 | __le32 ep_traddr; | ||
| 80 | __le32 ep_cfg; | ||
| 81 | __le32 ep_cmd; | ||
| 82 | __le32 ep_sts; | ||
| 83 | __le32 ep_sts_sid; | ||
| 84 | __le32 ep_sts_en; | ||
| 85 | __le32 drbl; | ||
| 86 | __le32 ep_ien; | ||
| 87 | __le32 ep_ists; | ||
| 88 | __le32 usb_pwr; | ||
| 89 | __le32 usb_conf2; | ||
| 90 | __le32 usb_cap1; | ||
| 91 | __le32 usb_cap2; | ||
| 92 | __le32 usb_cap3; | ||
| 93 | __le32 usb_cap4; | ||
| 94 | __le32 usb_cap5; | ||
| 95 | __le32 usb_cap6; | ||
| 96 | __le32 usb_cpkt1; | ||
| 97 | __le32 usb_cpkt2; | ||
| 98 | __le32 usb_cpkt3; | ||
| 99 | __le32 ep_dma_ext_addr; | ||
| 100 | __le32 buf_addr; | ||
| 101 | __le32 buf_data; | ||
| 102 | __le32 buf_ctrl; | ||
| 103 | __le32 dtrans; | ||
| 104 | __le32 tdl_from_trb; | ||
| 105 | __le32 tdl_beh; | ||
| 106 | __le32 ep_tdl; | ||
| 107 | __le32 tdl_beh2; | ||
| 108 | __le32 dma_adv_td; | ||
| 109 | __le32 reserved1[26]; | ||
| 110 | __le32 cfg_reg1; | ||
| 111 | __le32 dbg_link1; | ||
| 112 | __le32 dbg_link2; | ||
| 113 | __le32 cfg_regs[74]; | ||
| 114 | __le32 reserved2[51]; | ||
| 115 | __le32 dma_axi_ctrl; | ||
| 116 | __le32 dma_axi_id; | ||
| 117 | __le32 dma_axi_cap; | ||
| 118 | __le32 dma_axi_ctrl0; | ||
| 119 | __le32 dma_axi_ctrl1; | ||
| 120 | }; | ||
| 121 | |||
| 122 | /* USB_CONF - bitmasks */ | ||
| 123 | /* Reset USB device configuration. */ | ||
| 124 | #define USB_CONF_CFGRST BIT(0) | ||
| 125 | /* Set Configuration. */ | ||
| 126 | #define USB_CONF_CFGSET BIT(1) | ||
| 127 | /* Disconnect USB device in SuperSpeed. */ | ||
| 128 | #define USB_CONF_USB3DIS BIT(3) | ||
| 129 | /* Disconnect USB device in HS/FS */ | ||
| 130 | #define USB_CONF_USB2DIS BIT(4) | ||
| 131 | /* Little Endian access - default */ | ||
| 132 | #define USB_CONF_LENDIAN BIT(5) | ||
| 133 | /* | ||
| 134 | * Big Endian access. Driver assume that byte order for | ||
| 135 | * SFRs access always is as Little Endian so this bit | ||
| 136 | * is not used. | ||
| 137 | */ | ||
| 138 | #define USB_CONF_BENDIAN BIT(6) | ||
| 139 | /* Device software reset. */ | ||
| 140 | #define USB_CONF_SWRST BIT(7) | ||
| 141 | /* Singular DMA transfer mode. Only for VER < DEV_VER_V3*/ | ||
| 142 | #define USB_CONF_DSING BIT(8) | ||
| 143 | /* Multiple DMA transfers mode. Only for VER < DEV_VER_V3 */ | ||
| 144 | #define USB_CONF_DMULT BIT(9) | ||
| 145 | /* DMA clock turn-off enable. */ | ||
| 146 | #define USB_CONF_DMAOFFEN BIT(10) | ||
| 147 | /* DMA clock turn-off disable. */ | ||
| 148 | #define USB_CONF_DMAOFFDS BIT(11) | ||
| 149 | /* Clear Force Full Speed. */ | ||
| 150 | #define USB_CONF_CFORCE_FS BIT(12) | ||
| 151 | /* Set Force Full Speed. */ | ||
| 152 | #define USB_CONF_SFORCE_FS BIT(13) | ||
| 153 | /* Device enable. */ | ||
| 154 | #define USB_CONF_DEVEN BIT(14) | ||
| 155 | /* Device disable. */ | ||
| 156 | #define USB_CONF_DEVDS BIT(15) | ||
| 157 | /* L1 LPM state entry enable (used in HS/FS mode). */ | ||
| 158 | #define USB_CONF_L1EN BIT(16) | ||
| 159 | /* L1 LPM state entry disable (used in HS/FS mode). */ | ||
| 160 | #define USB_CONF_L1DS BIT(17) | ||
| 161 | /* USB 2.0 clock gate disable. */ | ||
| 162 | #define USB_CONF_CLK2OFFEN BIT(18) | ||
| 163 | /* USB 2.0 clock gate enable. */ | ||
| 164 | #define USB_CONF_CLK2OFFDS BIT(19) | ||
| 165 | /* L0 LPM state entry request (used in HS/FS mode). */ | ||
| 166 | #define USB_CONF_LGO_L0 BIT(20) | ||
| 167 | /* USB 3.0 clock gate disable. */ | ||
| 168 | #define USB_CONF_CLK3OFFEN BIT(21) | ||
| 169 | /* USB 3.0 clock gate enable. */ | ||
| 170 | #define USB_CONF_CLK3OFFDS BIT(22) | ||
| 171 | /* Bit 23 is reserved*/ | ||
| 172 | /* U1 state entry enable (used in SS mode). */ | ||
| 173 | #define USB_CONF_U1EN BIT(24) | ||
| 174 | /* U1 state entry disable (used in SS mode). */ | ||
| 175 | #define USB_CONF_U1DS BIT(25) | ||
| 176 | /* U2 state entry enable (used in SS mode). */ | ||
| 177 | #define USB_CONF_U2EN BIT(26) | ||
| 178 | /* U2 state entry disable (used in SS mode). */ | ||
| 179 | #define USB_CONF_U2DS BIT(27) | ||
| 180 | /* U0 state entry request (used in SS mode). */ | ||
| 181 | #define USB_CONF_LGO_U0 BIT(28) | ||
| 182 | /* U1 state entry request (used in SS mode). */ | ||
| 183 | #define USB_CONF_LGO_U1 BIT(29) | ||
| 184 | /* U2 state entry request (used in SS mode). */ | ||
| 185 | #define USB_CONF_LGO_U2 BIT(30) | ||
| 186 | /* SS.Inactive state entry request (used in SS mode) */ | ||
| 187 | #define USB_CONF_LGO_SSINACT BIT(31) | ||
| 188 | |||
| 189 | /* USB_STS - bitmasks */ | ||
| 190 | /* | ||
| 191 | * Configuration status. | ||
| 192 | * 1 - device is in the configured state. | ||
| 193 | * 0 - device is not configured. | ||
| 194 | */ | ||
| 195 | #define USB_STS_CFGSTS_MASK BIT(0) | ||
| 196 | #define USB_STS_CFGSTS(p) ((p) & USB_STS_CFGSTS_MASK) | ||
| 197 | /* | ||
| 198 | * On-chip memory overflow. | ||
| 199 | * 0 - On-chip memory status OK. | ||
| 200 | * 1 - On-chip memory overflow. | ||
| 201 | */ | ||
| 202 | #define USB_STS_OV_MASK BIT(1) | ||
| 203 | #define USB_STS_OV(p) ((p) & USB_STS_OV_MASK) | ||
| 204 | /* | ||
| 205 | * SuperSpeed connection status. | ||
| 206 | * 0 - USB in SuperSpeed mode disconnected. | ||
| 207 | * 1 - USB in SuperSpeed mode connected. | ||
| 208 | */ | ||
| 209 | #define USB_STS_USB3CONS_MASK BIT(2) | ||
| 210 | #define USB_STS_USB3CONS(p) ((p) & USB_STS_USB3CONS_MASK) | ||
| 211 | /* | ||
| 212 | * DMA transfer configuration status. | ||
| 213 | * 0 - single request. | ||
| 214 | * 1 - multiple TRB chain | ||
| 215 | * Supported only for controller version < DEV_VER_V3 | ||
| 216 | */ | ||
| 217 | #define USB_STS_DTRANS_MASK BIT(3) | ||
| 218 | #define USB_STS_DTRANS(p) ((p) & USB_STS_DTRANS_MASK) | ||
| 219 | /* | ||
| 220 | * Device speed. | ||
| 221 | * 0 - Undefined (value after reset). | ||
| 222 | * 1 - Low speed | ||
| 223 | * 2 - Full speed | ||
| 224 | * 3 - High speed | ||
| 225 | * 4 - Super speed | ||
| 226 | */ | ||
| 227 | #define USB_STS_USBSPEED_MASK GENMASK(6, 4) | ||
| 228 | #define USB_STS_USBSPEED(p) (((p) & USB_STS_USBSPEED_MASK) >> 4) | ||
| 229 | #define USB_STS_LS (0x1 << 4) | ||
| 230 | #define USB_STS_FS (0x2 << 4) | ||
| 231 | #define USB_STS_HS (0x3 << 4) | ||
| 232 | #define USB_STS_SS (0x4 << 4) | ||
| 233 | #define DEV_UNDEFSPEED(p) (((p) & USB_STS_USBSPEED_MASK) == (0x0 << 4)) | ||
| 234 | #define DEV_LOWSPEED(p) (((p) & USB_STS_USBSPEED_MASK) == USB_STS_LS) | ||
| 235 | #define DEV_FULLSPEED(p) (((p) & USB_STS_USBSPEED_MASK) == USB_STS_FS) | ||
| 236 | #define DEV_HIGHSPEED(p) (((p) & USB_STS_USBSPEED_MASK) == USB_STS_HS) | ||
| 237 | #define DEV_SUPERSPEED(p) (((p) & USB_STS_USBSPEED_MASK) == USB_STS_SS) | ||
| 238 | /* | ||
| 239 | * Endianness for SFR access. | ||
| 240 | * 0 - Little Endian order (default after hardware reset). | ||
| 241 | * 1 - Big Endian order | ||
| 242 | */ | ||
| 243 | #define USB_STS_ENDIAN_MASK BIT(7) | ||
| 244 | #define USB_STS_ENDIAN(p) ((p) & USB_STS_ENDIAN_MASK) | ||
| 245 | /* | ||
| 246 | * HS/FS clock turn-off status. | ||
| 247 | * 0 - hsfs clock is always on. | ||
| 248 | * 1 - hsfs clock turn-off in L2 (HS/FS mode) is enabled | ||
| 249 | * (default after hardware reset). | ||
| 250 | */ | ||
| 251 | #define USB_STS_CLK2OFF_MASK BIT(8) | ||
| 252 | #define USB_STS_CLK2OFF(p) ((p) & USB_STS_CLK2OFF_MASK) | ||
| 253 | /* | ||
| 254 | * PCLK clock turn-off status. | ||
| 255 | * 0 - pclk clock is always on. | ||
| 256 | * 1 - pclk clock turn-off in U3 (SS mode) is enabled | ||
| 257 | * (default after hardware reset). | ||
| 258 | */ | ||
| 259 | #define USB_STS_CLK3OFF_MASK BIT(9) | ||
| 260 | #define USB_STS_CLK3OFF(p) ((p) & USB_STS_CLK3OFF_MASK) | ||
| 261 | /* | ||
| 262 | * Controller in reset state. | ||
| 263 | * 0 - Internal reset is active. | ||
| 264 | * 1 - Internal reset is not active and controller is fully operational. | ||
| 265 | */ | ||
| 266 | #define USB_STS_IN_RST_MASK BIT(10) | ||
| 267 | #define USB_STS_IN_RST(p) ((p) & USB_STS_IN_RST_MASK) | ||
| 268 | /* | ||
| 269 | * Status of the "TDL calculation basing on TRB" feature. | ||
| 270 | * 0 - disabled | ||
| 271 | * 1 - enabled | ||
| 272 | * Supported only for DEV_VER_V2 controller version. | ||
| 273 | */ | ||
| 274 | #define USB_STS_TDL_TRB_ENABLED BIT(11) | ||
| 275 | /* | ||
| 276 | * Device enable Status. | ||
| 277 | * 0 - USB device is disabled (VBUS input is disconnected from internal logic). | ||
| 278 | * 1 - USB device is enabled (VBUS input is connected to the internal logic). | ||
| 279 | */ | ||
| 280 | #define USB_STS_DEVS_MASK BIT(14) | ||
| 281 | #define USB_STS_DEVS(p) ((p) & USB_STS_DEVS_MASK) | ||
| 282 | /* | ||
| 283 | * Address status. | ||
| 284 | * 0 - USB device is default state. | ||
| 285 | * 1 - USB device is at least in address state. | ||
| 286 | */ | ||
| 287 | #define USB_STS_ADDRESSED_MASK BIT(15) | ||
| 288 | #define USB_STS_ADDRESSED(p) ((p) & USB_STS_ADDRESSED_MASK) | ||
| 289 | /* | ||
| 290 | * L1 LPM state enable status (used in HS/FS mode). | ||
| 291 | * 0 - Entering to L1 LPM state disabled. | ||
| 292 | * 1 - Entering to L1 LPM state enabled. | ||
| 293 | */ | ||
| 294 | #define USB_STS_L1ENS_MASK BIT(16) | ||
| 295 | #define USB_STS_L1ENS(p) ((p) & USB_STS_L1ENS_MASK) | ||
| 296 | /* | ||
| 297 | * Internal VBUS connection status (used both in HS/FS and SS mode). | ||
| 298 | * 0 - internal VBUS is not detected. | ||
| 299 | * 1 - internal VBUS is detected. | ||
| 300 | */ | ||
| 301 | #define USB_STS_VBUSS_MASK BIT(17) | ||
| 302 | #define USB_STS_VBUSS(p) ((p) & USB_STS_VBUSS_MASK) | ||
| 303 | /* | ||
| 304 | * HS/FS LPM state (used in FS/HS mode). | ||
| 305 | * 0 - L0 State | ||
| 306 | * 1 - L1 State | ||
| 307 | * 2 - L2 State | ||
| 308 | * 3 - L3 State | ||
| 309 | */ | ||
| 310 | #define USB_STS_LPMST_MASK GENMASK(19, 18) | ||
| 311 | #define DEV_L0_STATE(p) (((p) & USB_STS_LPMST_MASK) == (0x0 << 18)) | ||
| 312 | #define DEV_L1_STATE(p) (((p) & USB_STS_LPMST_MASK) == (0x1 << 18)) | ||
| 313 | #define DEV_L2_STATE(p) (((p) & USB_STS_LPMST_MASK) == (0x2 << 18)) | ||
| 314 | #define DEV_L3_STATE(p) (((p) & USB_STS_LPMST_MASK) == (0x3 << 18)) | ||
| 315 | /* | ||
| 316 | * Disable HS status (used in FS/HS mode). | ||
| 317 | * 0 - the disconnect bit for HS/FS mode is set . | ||
| 318 | * 1 - the disconnect bit for HS/FS mode is not set. | ||
| 319 | */ | ||
| 320 | #define USB_STS_USB2CONS_MASK BIT(20) | ||
| 321 | #define USB_STS_USB2CONS(p) ((p) & USB_STS_USB2CONS_MASK) | ||
| 322 | /* | ||
| 323 | * HS/FS mode connection status (used in FS/HS mode). | ||
| 324 | * 0 - High Speed operations in USB2.0 (FS/HS) mode not disabled. | ||
| 325 | * 1 - High Speed operations in USB2.0 (FS/HS). | ||
| 326 | */ | ||
| 327 | #define USB_STS_DISABLE_HS_MASK BIT(21) | ||
| 328 | #define USB_STS_DISABLE_HS(p) ((p) & USB_STS_DISABLE_HS_MASK) | ||
| 329 | /* | ||
| 330 | * U1 state enable status (used in SS mode). | ||
| 331 | * 0 - Entering to U1 state disabled. | ||
| 332 | * 1 - Entering to U1 state enabled. | ||
| 333 | */ | ||
| 334 | #define USB_STS_U1ENS_MASK BIT(24) | ||
| 335 | #define USB_STS_U1ENS(p) ((p) & USB_STS_U1ENS_MASK) | ||
| 336 | /* | ||
| 337 | * U2 state enable status (used in SS mode). | ||
| 338 | * 0 - Entering to U2 state disabled. | ||
| 339 | * 1 - Entering to U2 state enabled. | ||
| 340 | */ | ||
| 341 | #define USB_STS_U2ENS_MASK BIT(25) | ||
| 342 | #define USB_STS_U2ENS(p) ((p) & USB_STS_U2ENS_MASK) | ||
| 343 | /* | ||
| 344 | * SuperSpeed Link LTSSM state. This field reflects USBSS-DEV current | ||
| 345 | * SuperSpeed link state | ||
| 346 | */ | ||
| 347 | #define USB_STS_LST_MASK GENMASK(29, 26) | ||
| 348 | #define DEV_LST_U0 (((p) & USB_STS_LST_MASK) == (0x0 << 26)) | ||
| 349 | #define DEV_LST_U1 (((p) & USB_STS_LST_MASK) == (0x1 << 26)) | ||
| 350 | #define DEV_LST_U2 (((p) & USB_STS_LST_MASK) == (0x2 << 26)) | ||
| 351 | #define DEV_LST_U3 (((p) & USB_STS_LST_MASK) == (0x3 << 26)) | ||
| 352 | #define DEV_LST_DISABLED (((p) & USB_STS_LST_MASK) == (0x4 << 26)) | ||
| 353 | #define DEV_LST_RXDETECT (((p) & USB_STS_LST_MASK) == (0x5 << 26)) | ||
| 354 | #define DEV_LST_INACTIVE (((p) & USB_STS_LST_MASK) == (0x6 << 26)) | ||
| 355 | #define DEV_LST_POLLING (((p) & USB_STS_LST_MASK) == (0x7 << 26)) | ||
| 356 | #define DEV_LST_RECOVERY (((p) & USB_STS_LST_MASK) == (0x8 << 26)) | ||
| 357 | #define DEV_LST_HOT_RESET (((p) & USB_STS_LST_MASK) == (0x9 << 26)) | ||
| 358 | #define DEV_LST_COMP_MODE (((p) & USB_STS_LST_MASK) == (0xa << 26)) | ||
| 359 | #define DEV_LST_LB_STATE (((p) & USB_STS_LST_MASK) == (0xb << 26)) | ||
| 360 | /* | ||
| 361 | * DMA clock turn-off status. | ||
| 362 | * 0 - DMA clock is always on (default after hardware reset). | ||
| 363 | * 1 - DMA clock turn-off in U1, U2 and U3 (SS mode) is enabled. | ||
| 364 | */ | ||
| 365 | #define USB_STS_DMAOFF_MASK BIT(30) | ||
| 366 | #define USB_STS_DMAOFF(p) ((p) & USB_STS_DMAOFF_MASK) | ||
| 367 | /* | ||
| 368 | * SFR Endian status. | ||
| 369 | * 0 - Little Endian order (default after hardware reset). | ||
| 370 | * 1 - Big Endian order. | ||
| 371 | */ | ||
| 372 | #define USB_STS_ENDIAN2_MASK BIT(31) | ||
| 373 | #define USB_STS_ENDIAN2(p) ((p) & USB_STS_ENDIAN2_MASK) | ||
| 374 | |||
| 375 | /* USB_CMD - bitmasks */ | ||
| 376 | /* Set Function Address */ | ||
| 377 | #define USB_CMD_SET_ADDR BIT(0) | ||
| 378 | /* | ||
| 379 | * Function Address This field is saved to the device only when the field | ||
| 380 | * SET_ADDR is set '1 ' during write to USB_CMD register. | ||
| 381 | * Software is responsible for entering the address of the device during | ||
| 382 | * SET_ADDRESS request service. This field should be set immediately after | ||
| 383 | * the SETUP packet is decoded, and prior to confirmation of the status phase | ||
| 384 | */ | ||
| 385 | #define USB_CMD_FADDR_MASK GENMASK(7, 1) | ||
| 386 | #define USB_CMD_FADDR(p) (((p) << 1) & USB_CMD_FADDR_MASK) | ||
| 387 | /* Send Function Wake Device Notification TP (used only in SS mode). */ | ||
| 388 | #define USB_CMD_SDNFW BIT(8) | ||
| 389 | /* Set Test Mode (used only in HS/FS mode). */ | ||
| 390 | #define USB_CMD_STMODE BIT(9) | ||
| 391 | /* Test mode selector (used only in HS/FS mode) */ | ||
| 392 | #define USB_STS_TMODE_SEL_MASK GENMASK(11, 10) | ||
| 393 | #define USB_STS_TMODE_SEL(p) (((p) << 10) & USB_STS_TMODE_SEL_MASK) | ||
| 394 | /* | ||
| 395 | * Send Latency Tolerance Message Device Notification TP (used only | ||
| 396 | * in SS mode). | ||
| 397 | */ | ||
| 398 | #define USB_CMD_SDNLTM BIT(12) | ||
| 399 | /* Send Custom Transaction Packet (used only in SS mode) */ | ||
| 400 | #define USB_CMD_SPKT BIT(13) | ||
| 401 | /*Device Notification 'Function Wake' - Interface value (only in SS mode. */ | ||
| 402 | #define USB_CMD_DNFW_INT_MASK GENMASK(23, 16) | ||
| 403 | #define USB_STS_DNFW_INT(p) (((p) << 16) & USB_CMD_DNFW_INT_MASK) | ||
| 404 | /* | ||
| 405 | * Device Notification 'Latency Tolerance Message' -373 BELT value [7:0] | ||
| 406 | * (used only in SS mode). | ||
| 407 | */ | ||
| 408 | #define USB_CMD_DNLTM_BELT_MASK GENMASK(27, 16) | ||
| 409 | #define USB_STS_DNLTM_BELT(p) (((p) << 16) & USB_CMD_DNLTM_BELT_MASK) | ||
| 410 | |||
| 411 | /* USB_ITPN - bitmasks */ | ||
| 412 | /* | ||
| 413 | * ITP(SS) / SOF (HS/FS) number | ||
| 414 | * In SS mode this field represent number of last ITP received from host. | ||
| 415 | * In HS/FS mode this field represent number of last SOF received from host. | ||
| 416 | */ | ||
| 417 | #define USB_ITPN_MASK GENMASK(13, 0) | ||
| 418 | #define USB_ITPN(p) ((p) & USB_ITPN_MASK) | ||
| 419 | |||
| 420 | /* USB_LPM - bitmasks */ | ||
| 421 | /* Host Initiated Resume Duration. */ | ||
| 422 | #define USB_LPM_HIRD_MASK GENMASK(3, 0) | ||
| 423 | #define USB_LPM_HIRD(p) ((p) & USB_LPM_HIRD_MASK) | ||
| 424 | /* Remote Wakeup Enable (bRemoteWake). */ | ||
| 425 | #define USB_LPM_BRW BIT(4) | ||
| 426 | |||
| 427 | /* USB_IEN - bitmasks */ | ||
| 428 | /* SS connection interrupt enable */ | ||
| 429 | #define USB_IEN_CONIEN BIT(0) | ||
| 430 | /* SS disconnection interrupt enable. */ | ||
| 431 | #define USB_IEN_DISIEN BIT(1) | ||
| 432 | /* USB SS warm reset interrupt enable. */ | ||
| 433 | #define USB_IEN_UWRESIEN BIT(2) | ||
| 434 | /* USB SS hot reset interrupt enable */ | ||
| 435 | #define USB_IEN_UHRESIEN BIT(3) | ||
| 436 | /* SS link U3 state enter interrupt enable (suspend).*/ | ||
| 437 | #define USB_IEN_U3ENTIEN BIT(4) | ||
| 438 | /* SS link U3 state exit interrupt enable (wakeup). */ | ||
| 439 | #define USB_IEN_U3EXTIEN BIT(5) | ||
| 440 | /* SS link U2 state enter interrupt enable.*/ | ||
| 441 | #define USB_IEN_U2ENTIEN BIT(6) | ||
| 442 | /* SS link U2 state exit interrupt enable.*/ | ||
| 443 | #define USB_IEN_U2EXTIEN BIT(7) | ||
| 444 | /* SS link U1 state enter interrupt enable.*/ | ||
| 445 | #define USB_IEN_U1ENTIEN BIT(8) | ||
| 446 | /* SS link U1 state exit interrupt enable.*/ | ||
| 447 | #define USB_IEN_U1EXTIEN BIT(9) | ||
| 448 | /* ITP/SOF packet detected interrupt enable.*/ | ||
| 449 | #define USB_IEN_ITPIEN BIT(10) | ||
| 450 | /* Wakeup interrupt enable.*/ | ||
| 451 | #define USB_IEN_WAKEIEN BIT(11) | ||
| 452 | /* Send Custom Packet interrupt enable.*/ | ||
| 453 | #define USB_IEN_SPKTIEN BIT(12) | ||
| 454 | /* HS/FS mode connection interrupt enable.*/ | ||
| 455 | #define USB_IEN_CON2IEN BIT(16) | ||
| 456 | /* HS/FS mode disconnection interrupt enable.*/ | ||
| 457 | #define USB_IEN_DIS2IEN BIT(17) | ||
| 458 | /* USB reset (HS/FS mode) interrupt enable.*/ | ||
| 459 | #define USB_IEN_U2RESIEN BIT(18) | ||
| 460 | /* LPM L2 state enter interrupt enable.*/ | ||
| 461 | #define USB_IEN_L2ENTIEN BIT(20) | ||
| 462 | /* LPM L2 state exit interrupt enable.*/ | ||
| 463 | #define USB_IEN_L2EXTIEN BIT(21) | ||
| 464 | /* LPM L1 state enter interrupt enable.*/ | ||
| 465 | #define USB_IEN_L1ENTIEN BIT(24) | ||
| 466 | /* LPM L1 state exit interrupt enable.*/ | ||
| 467 | #define USB_IEN_L1EXTIEN BIT(25) | ||
| 468 | /* Configuration reset interrupt enable.*/ | ||
| 469 | #define USB_IEN_CFGRESIEN BIT(26) | ||
| 470 | /* Start of the USB SS warm reset interrupt enable.*/ | ||
| 471 | #define USB_IEN_UWRESSIEN BIT(28) | ||
| 472 | /* End of the USB SS warm reset interrupt enable.*/ | ||
| 473 | #define USB_IEN_UWRESEIEN BIT(29) | ||
| 474 | |||
| 475 | #define USB_IEN_INIT (USB_IEN_U2RESIEN | USB_ISTS_DIS2I | USB_IEN_CON2IEN \ | ||
| 476 | | USB_IEN_UHRESIEN | USB_IEN_UWRESIEN | USB_IEN_DISIEN \ | ||
| 477 | | USB_IEN_CONIEN | USB_IEN_U3EXTIEN | USB_IEN_L2ENTIEN \ | ||
| 478 | | USB_IEN_L2EXTIEN | USB_IEN_L1ENTIEN | USB_IEN_U3ENTIEN) | ||
| 479 | |||
| 480 | /* USB_ISTS - bitmasks */ | ||
| 481 | /* SS Connection detected. */ | ||
| 482 | #define USB_ISTS_CONI BIT(0) | ||
| 483 | /* SS Disconnection detected. */ | ||
| 484 | #define USB_ISTS_DISI BIT(1) | ||
| 485 | /* UUSB warm reset detectede. */ | ||
| 486 | #define USB_ISTS_UWRESI BIT(2) | ||
| 487 | /* USB hot reset detected. */ | ||
| 488 | #define USB_ISTS_UHRESI BIT(3) | ||
| 489 | /* U3 link state enter detected (suspend).*/ | ||
| 490 | #define USB_ISTS_U3ENTI BIT(4) | ||
| 491 | /* U3 link state exit detected (wakeup). */ | ||
| 492 | #define USB_ISTS_U3EXTI BIT(5) | ||
| 493 | /* U2 link state enter detected.*/ | ||
| 494 | #define USB_ISTS_U2ENTI BIT(6) | ||
| 495 | /* U2 link state exit detected.*/ | ||
| 496 | #define USB_ISTS_U2EXTI BIT(7) | ||
| 497 | /* U1 link state enter detected.*/ | ||
| 498 | #define USB_ISTS_U1ENTI BIT(8) | ||
| 499 | /* U1 link state exit detected.*/ | ||
| 500 | #define USB_ISTS_U1EXTI BIT(9) | ||
| 501 | /* ITP/SOF packet detected.*/ | ||
| 502 | #define USB_ISTS_ITPI BIT(10) | ||
| 503 | /* Wakeup detected.*/ | ||
| 504 | #define USB_ISTS_WAKEI BIT(11) | ||
| 505 | /* Send Custom Packet detected.*/ | ||
| 506 | #define USB_ISTS_SPKTI BIT(12) | ||
| 507 | /* HS/FS mode connection detected.*/ | ||
| 508 | #define USB_ISTS_CON2I BIT(16) | ||
| 509 | /* HS/FS mode disconnection detected.*/ | ||
| 510 | #define USB_ISTS_DIS2I BIT(17) | ||
| 511 | /* USB reset (HS/FS mode) detected.*/ | ||
| 512 | #define USB_ISTS_U2RESI BIT(18) | ||
| 513 | /* LPM L2 state enter detected.*/ | ||
| 514 | #define USB_ISTS_L2ENTI BIT(20) | ||
| 515 | /* LPM L2 state exit detected.*/ | ||
| 516 | #define USB_ISTS_L2EXTI BIT(21) | ||
| 517 | /* LPM L1 state enter detected.*/ | ||
| 518 | #define USB_ISTS_L1ENTI BIT(24) | ||
| 519 | /* LPM L1 state exit detected.*/ | ||
| 520 | #define USB_ISTS_L1EXTI BIT(25) | ||
| 521 | /* USB configuration reset detected.*/ | ||
| 522 | #define USB_ISTS_CFGRESI BIT(26) | ||
| 523 | /* Start of the USB warm reset detected.*/ | ||
| 524 | #define USB_ISTS_UWRESSI BIT(28) | ||
| 525 | /* End of the USB warm reset detected.*/ | ||
| 526 | #define USB_ISTS_UWRESEI BIT(29) | ||
| 527 | |||
| 528 | /* USB_SEL - bitmasks */ | ||
| 529 | #define EP_SEL_EPNO_MASK GENMASK(3, 0) | ||
| 530 | /* Endpoint number. */ | ||
| 531 | #define EP_SEL_EPNO(p) ((p) & EP_SEL_EPNO_MASK) | ||
| 532 | /* Endpoint direction bit - 0 - OUT, 1 - IN. */ | ||
| 533 | #define EP_SEL_DIR BIT(7) | ||
| 534 | |||
| 535 | #define select_ep_in(nr) (EP_SEL_EPNO(p) | EP_SEL_DIR) | ||
| 536 | #define select_ep_out (EP_SEL_EPNO(p)) | ||
| 537 | |||
| 538 | /* EP_TRADDR - bitmasks */ | ||
| 539 | /* Transfer Ring address. */ | ||
| 540 | #define EP_TRADDR_TRADDR(p) ((p)) | ||
| 541 | |||
| 542 | /* EP_CFG - bitmasks */ | ||
| 543 | /* Endpoint enable */ | ||
| 544 | #define EP_CFG_ENABLE BIT(0) | ||
| 545 | /* | ||
| 546 | * Endpoint type. | ||
| 547 | * 1 - isochronous | ||
| 548 | * 2 - bulk | ||
| 549 | * 3 - interrupt | ||
| 550 | */ | ||
| 551 | #define EP_CFG_EPTYPE_MASK GENMASK(2, 1) | ||
| 552 | #define EP_CFG_EPTYPE(p) (((p) << 1) & EP_CFG_EPTYPE_MASK) | ||
| 553 | /* Stream support enable (only in SS mode). */ | ||
| 554 | #define EP_CFG_STREAM_EN BIT(3) | ||
| 555 | /* TDL check (only in SS mode for BULK EP). */ | ||
| 556 | #define EP_CFG_TDL_CHK BIT(4) | ||
| 557 | /* SID check (only in SS mode for BULK OUT EP). */ | ||
| 558 | #define EP_CFG_SID_CHK BIT(5) | ||
| 559 | /* DMA transfer endianness. */ | ||
| 560 | #define EP_CFG_EPENDIAN BIT(7) | ||
| 561 | /* Max burst size (used only in SS mode). */ | ||
| 562 | #define EP_CFG_MAXBURST_MASK GENMASK(11, 8) | ||
| 563 | #define EP_CFG_MAXBURST(p) (((p) << 8) & EP_CFG_MAXBURST_MASK) | ||
| 564 | /* ISO max burst. */ | ||
| 565 | #define EP_CFG_MULT_MASK GENMASK(15, 14) | ||
| 566 | #define EP_CFG_MULT(p) (((p) << 14) & EP_CFG_MULT_MASK) | ||
| 567 | /* ISO max burst. */ | ||
| 568 | #define EP_CFG_MAXPKTSIZE_MASK GENMASK(26, 16) | ||
| 569 | #define EP_CFG_MAXPKTSIZE(p) (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK) | ||
| 570 | /* Max number of buffered packets. */ | ||
| 571 | #define EP_CFG_BUFFERING_MASK GENMASK(31, 27) | ||
| 572 | #define EP_CFG_BUFFERING(p) (((p) << 27) & EP_CFG_BUFFERING_MASK) | ||
| 573 | |||
| 574 | /* EP_CMD - bitmasks */ | ||
| 575 | /* Endpoint reset. */ | ||
| 576 | #define EP_CMD_EPRST BIT(0) | ||
| 577 | /* Endpoint STALL set. */ | ||
| 578 | #define EP_CMD_SSTALL BIT(1) | ||
| 579 | /* Endpoint STALL clear. */ | ||
| 580 | #define EP_CMD_CSTALL BIT(2) | ||
| 581 | /* Send ERDY TP. */ | ||
| 582 | #define EP_CMD_ERDY BIT(3) | ||
| 583 | /* Request complete. */ | ||
| 584 | #define EP_CMD_REQ_CMPL BIT(5) | ||
| 585 | /* Transfer descriptor ready. */ | ||
| 586 | #define EP_CMD_DRDY BIT(6) | ||
| 587 | /* Data flush. */ | ||
| 588 | #define EP_CMD_DFLUSH BIT(7) | ||
| 589 | /* | ||
| 590 | * Transfer Descriptor Length write (used only for Bulk Stream capable | ||
| 591 | * endpoints in SS mode). | ||
| 592 | * Bit Removed from DEV_VER_V3 controller version. | ||
| 593 | */ | ||
| 594 | #define EP_CMD_STDL BIT(8) | ||
| 595 | /* | ||
| 596 | * Transfer Descriptor Length (used only in SS mode for bulk endpoints). | ||
| 597 | * Bits Removed from DEV_VER_V3 controller version. | ||
| 598 | */ | ||
| 599 | #define EP_CMD_TDL_MASK GENMASK(15, 9) | ||
| 600 | #define EP_CMD_TDL_SET(p) (((p) << 9) & EP_CMD_TDL_MASK) | ||
| 601 | #define EP_CMD_TDL_GET(p) (((p) & EP_CMD_TDL_MASK) >> 9) | ||
| 602 | |||
| 603 | /* ERDY Stream ID value (used in SS mode). */ | ||
| 604 | #define EP_CMD_ERDY_SID_MASK GENMASK(31, 16) | ||
| 605 | #define EP_CMD_ERDY_SID(p) (((p) << 16) & EP_CMD_ERDY_SID_MASK) | ||
| 606 | |||
| 607 | /* EP_STS - bitmasks */ | ||
| 608 | /* Setup transfer complete. */ | ||
| 609 | #define EP_STS_SETUP BIT(0) | ||
| 610 | /* Endpoint STALL status. */ | ||
| 611 | #define EP_STS_STALL(p) ((p) & BIT(1)) | ||
| 612 | /* Interrupt On Complete. */ | ||
| 613 | #define EP_STS_IOC BIT(2) | ||
| 614 | /* Interrupt on Short Packet. */ | ||
| 615 | #define EP_STS_ISP BIT(3) | ||
| 616 | /* Transfer descriptor missing. */ | ||
| 617 | #define EP_STS_DESCMIS BIT(4) | ||
| 618 | /* Stream Rejected (used only in SS mode) */ | ||
| 619 | #define EP_STS_STREAMR BIT(5) | ||
| 620 | /* EXIT from MOVE DATA State (used only for stream transfers in SS mode). */ | ||
| 621 | #define EP_STS_MD_EXIT BIT(6) | ||
| 622 | /* TRB error. */ | ||
| 623 | #define EP_STS_TRBERR BIT(7) | ||
| 624 | /* Not ready (used only in SS mode). */ | ||
| 625 | #define EP_STS_NRDY BIT(8) | ||
| 626 | /* DMA busy bit. */ | ||
| 627 | #define EP_STS_DBUSY BIT(9) | ||
| 628 | /* Endpoint Buffer Empty */ | ||
| 629 | #define EP_STS_BUFFEMPTY(p) ((p) & BIT(10)) | ||
| 630 | /* Current Cycle Status */ | ||
| 631 | #define EP_STS_CCS(p) ((p) & BIT(11)) | ||
| 632 | /* Prime (used only in SS mode. */ | ||
| 633 | #define EP_STS_PRIME BIT(12) | ||
| 634 | /* Stream error (used only in SS mode). */ | ||
| 635 | #define EP_STS_SIDERR BIT(13) | ||
| 636 | /* OUT size mismatch. */ | ||
| 637 | #define EP_STS_OUTSMM BIT(14) | ||
| 638 | /* ISO transmission error. */ | ||
| 639 | #define EP_STS_ISOERR BIT(15) | ||
| 640 | /* Host Packet Pending (only for SS mode). */ | ||
| 641 | #define EP_STS_HOSTPP(p) ((p) & BIT(16)) | ||
| 642 | /* Stream Protocol State Machine State (only for Bulk stream endpoints). */ | ||
| 643 | #define EP_STS_SPSMST_MASK GENMASK(18, 17) | ||
| 644 | #define EP_STS_SPSMST_DISABLED(p) (((p) & EP_STS_SPSMST_MASK) >> 17) | ||
| 645 | #define EP_STS_SPSMST_IDLE(p) (((p) & EP_STS_SPSMST_MASK) >> 17) | ||
| 646 | #define EP_STS_SPSMST_START_STREAM(p) (((p) & EP_STS_SPSMST_MASK) >> 17) | ||
| 647 | #define EP_STS_SPSMST_MOVE_DATA(p) (((p) & EP_STS_SPSMST_MASK) >> 17) | ||
| 648 | /* Interrupt On Transfer complete. */ | ||
| 649 | #define EP_STS_IOT BIT(19) | ||
| 650 | /* OUT queue endpoint number. */ | ||
| 651 | #define EP_STS_OUTQ_NO_MASK GENMASK(27, 24) | ||
| 652 | #define EP_STS_OUTQ_NO(p) (((p) & EP_STS_OUTQ_NO_MASK) >> 24) | ||
| 653 | /* OUT queue valid flag. */ | ||
| 654 | #define EP_STS_OUTQ_VAL_MASK BIT(28) | ||
| 655 | #define EP_STS_OUTQ_VAL(p) ((p) & EP_STS_OUTQ_VAL_MASK) | ||
| 656 | /* SETUP WAIT. */ | ||
| 657 | #define EP_STS_STPWAIT BIT(31) | ||
| 658 | |||
| 659 | /* EP_STS_SID - bitmasks */ | ||
| 660 | /* Stream ID (used only in SS mode). */ | ||
| 661 | #define EP_STS_SID_MASK GENMASK(15, 0) | ||
| 662 | #define EP_STS_SID(p) ((p) & EP_STS_SID_MASK) | ||
| 663 | |||
| 664 | /* EP_STS_EN - bitmasks */ | ||
| 665 | /* SETUP interrupt enable. */ | ||
| 666 | #define EP_STS_EN_SETUPEN BIT(0) | ||
| 667 | /* OUT transfer missing descriptor enable. */ | ||
| 668 | #define EP_STS_EN_DESCMISEN BIT(4) | ||
| 669 | /* Stream Rejected enable. */ | ||
| 670 | #define EP_STS_EN_STREAMREN BIT(5) | ||
| 671 | /* Move Data Exit enable.*/ | ||
| 672 | #define EP_STS_EN_MD_EXITEN BIT(6) | ||
| 673 | /* TRB enable. */ | ||
| 674 | #define EP_STS_EN_TRBERREN BIT(7) | ||
| 675 | /* NRDY enable. */ | ||
| 676 | #define EP_STS_EN_NRDYEN BIT(8) | ||
| 677 | /* Prime enable. */ | ||
| 678 | #define EP_STS_EN_PRIMEEEN BIT(12) | ||
| 679 | /* Stream error enable. */ | ||
| 680 | #define EP_STS_EN_SIDERREN BIT(13) | ||
| 681 | /* OUT size mismatch enable. */ | ||
| 682 | #define EP_STS_EN_OUTSMMEN BIT(14) | ||
| 683 | /* ISO transmission error enable. */ | ||
| 684 | #define EP_STS_EN_ISOERREN BIT(15) | ||
| 685 | /* Interrupt on Transmission complete enable. */ | ||
| 686 | #define EP_STS_EN_IOTEN BIT(19) | ||
| 687 | /* Setup Wait interrupt enable. */ | ||
| 688 | #define EP_STS_EN_STPWAITEN BIT(31) | ||
| 689 | |||
| 690 | /* DRBL- bitmasks */ | ||
| 691 | #define DB_VALUE_BY_INDEX(index) (1 << (index)) | ||
| 692 | #define DB_VALUE_EP0_OUT BIT(0) | ||
| 693 | #define DB_VALUE_EP0_IN BIT(16) | ||
| 694 | |||
| 695 | /* EP_IEN - bitmasks */ | ||
| 696 | #define EP_IEN(index) (1 << (index)) | ||
| 697 | #define EP_IEN_EP_OUT0 BIT(0) | ||
| 698 | #define EP_IEN_EP_IN0 BIT(16) | ||
| 699 | |||
| 700 | /* EP_ISTS - bitmasks */ | ||
| 701 | #define EP_ISTS(index) (1 << (index)) | ||
| 702 | #define EP_ISTS_EP_OUT0 BIT(0) | ||
| 703 | #define EP_ISTS_EP_IN0 BIT(16) | ||
| 704 | |||
| 705 | /* USB_PWR- bitmasks */ | ||
| 706 | /*Power Shut Off capability enable*/ | ||
| 707 | #define PUSB_PWR_PSO_EN BIT(0) | ||
| 708 | /*Power Shut Off capability disable*/ | ||
| 709 | #define PUSB_PWR_PSO_DS BIT(1) | ||
| 710 | /* | ||
| 711 | * Enables turning-off Reference Clock. | ||
| 712 | * This bit is optional and implemented only when support for OTG is | ||
| 713 | * implemented (indicated by OTG_READY bit set to '1'). | ||
| 714 | */ | ||
| 715 | #define PUSB_PWR_STB_CLK_SWITCH_EN BIT(8) | ||
| 716 | /* | ||
| 717 | * Status bit indicating that operation required by STB_CLK_SWITCH_EN write | ||
| 718 | * is completed | ||
| 719 | */ | ||
| 720 | #define PUSB_PWR_STB_CLK_SWITCH_DONE BIT(9) | ||
| 721 | /* This bit informs if Fast Registers Access is enabled. */ | ||
| 722 | #define PUSB_PWR_FST_REG_ACCESS_STAT BIT(30) | ||
| 723 | /* Fast Registers Access Enable. */ | ||
| 724 | #define PUSB_PWR_FST_REG_ACCESS BIT(31) | ||
| 725 | |||
| 726 | /* USB_CONF2- bitmasks */ | ||
| 727 | /* | ||
| 728 | * Writing 1 disables TDL calculation basing on TRB feature in controller | ||
| 729 | * for DMULT mode. | ||
| 730 | * Bit supported only for DEV_VER_V2 version. | ||
| 731 | */ | ||
| 732 | #define USB_CONF2_DIS_TDL_TRB BIT(1) | ||
| 733 | /* | ||
| 734 | * Writing 1 enables TDL calculation basing on TRB feature in controller | ||
| 735 | * for DMULT mode. | ||
| 736 | * Bit supported only for DEV_VER_V2 version. | ||
| 737 | */ | ||
| 738 | #define USB_CONF2_EN_TDL_TRB BIT(2) | ||
| 739 | |||
| 740 | /* USB_CAP1- bitmasks */ | ||
| 741 | /* | ||
| 742 | * SFR Interface type | ||
| 743 | * These field reflects type of SFR interface implemented: | ||
| 744 | * 0x0 - OCP | ||
| 745 | * 0x1 - AHB, | ||
| 746 | * 0x2 - PLB | ||
| 747 | * 0x3 - AXI | ||
| 748 | * 0x4-0xF - reserved | ||
| 749 | */ | ||
| 750 | #define USB_CAP1_SFR_TYPE_MASK GENMASK(3, 0) | ||
| 751 | #define DEV_SFR_TYPE_OCP(p) (((p) & USB_CAP1_SFR_TYPE_MASK) == 0x0) | ||
| 752 | #define DEV_SFR_TYPE_AHB(p) (((p) & USB_CAP1_SFR_TYPE_MASK) == 0x1) | ||
| 753 | #define DEV_SFR_TYPE_PLB(p) (((p) & USB_CAP1_SFR_TYPE_MASK) == 0x2) | ||
| 754 | #define DEV_SFR_TYPE_AXI(p) (((p) & USB_CAP1_SFR_TYPE_MASK) == 0x3) | ||
| 755 | /* | ||
| 756 | * SFR Interface width | ||
| 757 | * These field reflects width of SFR interface implemented: | ||
| 758 | * 0x0 - 8 bit interface, | ||
| 759 | * 0x1 - 16 bit interface, | ||
| 760 | * 0x2 - 32 bit interface | ||
| 761 | * 0x3 - 64 bit interface | ||
| 762 | * 0x4-0xF - reserved | ||
| 763 | */ | ||
| 764 | #define USB_CAP1_SFR_WIDTH_MASK GENMASK(7, 4) | ||
| 765 | #define DEV_SFR_WIDTH_8(p) (((p) & USB_CAP1_SFR_WIDTH_MASK) == (0x0 << 4)) | ||
| 766 | #define DEV_SFR_WIDTH_16(p) (((p) & USB_CAP1_SFR_WIDTH_MASK) == (0x1 << 4)) | ||
| 767 | #define DEV_SFR_WIDTH_32(p) (((p) & USB_CAP1_SFR_WIDTH_MASK) == (0x2 << 4)) | ||
| 768 | #define DEV_SFR_WIDTH_64(p) (((p) & USB_CAP1_SFR_WIDTH_MASK) == (0x3 << 4)) | ||
| 769 | /* | ||
| 770 | * DMA Interface type | ||
| 771 | * These field reflects type of DMA interface implemented: | ||
| 772 | * 0x0 - OCP | ||
| 773 | * 0x1 - AHB, | ||
| 774 | * 0x2 - PLB | ||
| 775 | * 0x3 - AXI | ||
| 776 | * 0x4-0xF - reserved | ||
| 777 | */ | ||
| 778 | #define USB_CAP1_DMA_TYPE_MASK GENMASK(11, 8) | ||
| 779 | #define DEV_DMA_TYPE_OCP(p) (((p) & USB_CAP1_DMA_TYPE_MASK) == (0x0 << 8)) | ||
| 780 | #define DEV_DMA_TYPE_AHB(p) (((p) & USB_CAP1_DMA_TYPE_MASK) == (0x1 << 8)) | ||
| 781 | #define DEV_DMA_TYPE_PLB(p) (((p) & USB_CAP1_DMA_TYPE_MASK) == (0x2 << 8)) | ||
| 782 | #define DEV_DMA_TYPE_AXI(p) (((p) & USB_CAP1_DMA_TYPE_MASK) == (0x3 << 8)) | ||
| 783 | /* | ||
| 784 | * DMA Interface width | ||
| 785 | * These field reflects width of DMA interface implemented: | ||
| 786 | * 0x0 - reserved, | ||
| 787 | * 0x1 - reserved, | ||
| 788 | * 0x2 - 32 bit interface | ||
| 789 | * 0x3 - 64 bit interface | ||
| 790 | * 0x4-0xF - reserved | ||
| 791 | */ | ||
| 792 | #define USB_CAP1_DMA_WIDTH_MASK GENMASK(15, 12) | ||
| 793 | #define DEV_DMA_WIDTH_32(p) (((p) & USB_CAP1_DMA_WIDTH_MASK) == (0x2 << 12)) | ||
| 794 | #define DEV_DMA_WIDTH_64(p) (((p) & USB_CAP1_DMA_WIDTH_MASK) == (0x3 << 12)) | ||
| 795 | /* | ||
| 796 | * USB3 PHY Interface type | ||
| 797 | * These field reflects type of USB3 PHY interface implemented: | ||
| 798 | * 0x0 - USB PIPE, | ||
| 799 | * 0x1 - RMMI, | ||
| 800 | * 0x2-0xF - reserved | ||
| 801 | */ | ||
| 802 | #define USB_CAP1_U3PHY_TYPE_MASK GENMASK(19, 16) | ||
| 803 | #define DEV_U3PHY_PIPE(p) (((p) & USB_CAP1_U3PHY_TYPE_MASK) == (0x0 << 16)) | ||
| 804 | #define DEV_U3PHY_RMMI(p) (((p) & USB_CAP1_U3PHY_TYPE_MASK) == (0x1 << 16)) | ||
| 805 | /* | ||
| 806 | * USB3 PHY Interface width | ||
| 807 | * These field reflects width of USB3 PHY interface implemented: | ||
| 808 | * 0x0 - 8 bit PIPE interface, | ||
| 809 | * 0x1 - 16 bit PIPE interface, | ||
| 810 | * 0x2 - 32 bit PIPE interface, | ||
| 811 | * 0x3 - 64 bit PIPE interface | ||
| 812 | * 0x4-0xF - reserved | ||
| 813 | * Note: When SSIC interface is implemented this field shows the width of | ||
| 814 | * internal PIPE interface. The RMMI interface is always 20bit wide. | ||
| 815 | */ | ||
| 816 | #define USB_CAP1_U3PHY_WIDTH_MASK GENMASK(23, 20) | ||
| 817 | #define DEV_U3PHY_WIDTH_8(p) \ | ||
| 818 | (((p) & USB_CAP1_U3PHY_WIDTH_MASK) == (0x0 << 20)) | ||
| 819 | #define DEV_U3PHY_WIDTH_16(p) \ | ||
| 820 | (((p) & USB_CAP1_U3PHY_WIDTH_MASK) == (0x1 << 16)) | ||
| 821 | #define DEV_U3PHY_WIDTH_32(p) \ | ||
| 822 | (((p) & USB_CAP1_U3PHY_WIDTH_MASK) == (0x2 << 20)) | ||
| 823 | #define DEV_U3PHY_WIDTH_64(p) \ | ||
| 824 | (((p) & USB_CAP1_U3PHY_WIDTH_MASK) == (0x3 << 16)) | ||
| 825 | |||
| 826 | /* | ||
| 827 | * USB2 PHY Interface enable | ||
| 828 | * These field informs if USB2 PHY interface is implemented: | ||
| 829 | * 0x0 - interface NOT implemented, | ||
| 830 | * 0x1 - interface implemented | ||
| 831 | */ | ||
| 832 | #define USB_CAP1_U2PHY_EN(p) ((p) & BIT(24)) | ||
| 833 | /* | ||
| 834 | * USB2 PHY Interface type | ||
| 835 | * These field reflects type of USB2 PHY interface implemented: | ||
| 836 | * 0x0 - UTMI, | ||
| 837 | * 0x1 - ULPI | ||
| 838 | */ | ||
| 839 | #define DEV_U2PHY_ULPI(p) ((p) & BIT(25)) | ||
| 840 | /* | ||
| 841 | * USB2 PHY Interface width | ||
| 842 | * These field reflects width of USB2 PHY interface implemented: | ||
| 843 | * 0x0 - 8 bit interface, | ||
| 844 | * 0x1 - 16 bit interface, | ||
| 845 | * Note: The ULPI interface is always 8bit wide. | ||
| 846 | */ | ||
| 847 | #define DEV_U2PHY_WIDTH_16(p) ((p) & BIT(26)) | ||
| 848 | /* | ||
| 849 | * OTG Ready | ||
| 850 | * 0x0 - pure device mode | ||
| 851 | * 0x1 - some features and ports for CDNS USB OTG controller are implemented. | ||
| 852 | */ | ||
| 853 | #define USB_CAP1_OTG_READY(p) ((p) & BIT(27)) | ||
| 854 | |||
| 855 | /* | ||
| 856 | * When set, indicates that controller supports automatic internal TDL | ||
| 857 | * calculation basing on the size provided in TRB (TRB[22:17]) for DMULT mode | ||
| 858 | * Supported only for DEV_VER_V2 controller version. | ||
| 859 | */ | ||
| 860 | #define USB_CAP1_TDL_FROM_TRB(p) ((p) & BIT(28)) | ||
| 861 | |||
| 862 | /* USB_CAP2- bitmasks */ | ||
| 863 | /* | ||
| 864 | * The actual size of the connected On-chip RAM memory in kB: | ||
| 865 | * - 0 means 256 kB (max supported mem size) | ||
| 866 | * - value other than 0 reflects the mem size in kB | ||
| 867 | */ | ||
| 868 | #define USB_CAP2_ACTUAL_MEM_SIZE(p) ((p) & GENMASK(7, 0)) | ||
| 869 | /* | ||
| 870 | * Max supported mem size | ||
| 871 | * These field reflects width of on-chip RAM address bus width, | ||
| 872 | * which determines max supported mem size: | ||
| 873 | * 0x0-0x7 - reserved, | ||
| 874 | * 0x8 - support for 4kB mem, | ||
| 875 | * 0x9 - support for 8kB mem, | ||
| 876 | * 0xA - support for 16kB mem, | ||
| 877 | * 0xB - support for 32kB mem, | ||
| 878 | * 0xC - support for 64kB mem, | ||
| 879 | * 0xD - support for 128kB mem, | ||
| 880 | * 0xE - support for 256kB mem, | ||
| 881 | * 0xF - reserved | ||
| 882 | */ | ||
| 883 | #define USB_CAP2_MAX_MEM_SIZE(p) ((p) & GENMASK(11, 8)) | ||
| 884 | |||
| 885 | /* USB_CAP3- bitmasks */ | ||
| 886 | #define EP_IS_IMPLEMENTED(reg, index) ((reg) & (1 << (index))) | ||
| 887 | |||
| 888 | /* USB_CAP4- bitmasks */ | ||
| 889 | #define EP_SUPPORT_ISO(reg, index) ((reg) & (1 << (index))) | ||
| 890 | |||
| 891 | /* USB_CAP5- bitmasks */ | ||
| 892 | #define EP_SUPPORT_STREAM(reg, index) ((reg) & (1 << (index))) | ||
| 893 | |||
| 894 | /* USB_CAP6- bitmasks */ | ||
| 895 | /* The USBSS-DEV Controller Internal build number. */ | ||
| 896 | #define GET_DEV_BASE_VERSION(p) ((p) & GENMASK(23, 0)) | ||
| 897 | /* The USBSS-DEV Controller version number. */ | ||
| 898 | #define GET_DEV_CUSTOM_VERSION(p) ((p) & GENMASK(31, 24)) | ||
| 899 | |||
| 900 | #define DEV_VER_NXP_V1 0x00024502 | ||
| 901 | #define DEV_VER_TI_V1 0x00024509 | ||
| 902 | #define DEV_VER_V2 0x0002450C | ||
| 903 | #define DEV_VER_V3 0x0002450d | ||
| 904 | |||
| 905 | /* DBG_LINK1- bitmasks */ | ||
| 906 | /* | ||
| 907 | * LFPS_MIN_DET_U1_EXIT value This parameter configures the minimum | ||
| 908 | * time required for decoding the received LFPS as an LFPS.U1_Exit. | ||
| 909 | */ | ||
| 910 | #define DBG_LINK1_LFPS_MIN_DET_U1_EXIT(p) ((p) & GENMASK(7, 0)) | ||
| 911 | /* | ||
| 912 | * LFPS_MIN_GEN_U1_EXIT value This parameter configures the minimum time for | ||
| 913 | * phytxelecidle deassertion when LFPS.U1_Exit | ||
| 914 | */ | ||
| 915 | #define DBG_LINK1_LFPS_MIN_GEN_U1_EXIT_MASK GENMASK(15, 8) | ||
| 916 | #define DBG_LINK1_LFPS_MIN_GEN_U1_EXIT(p) (((p) << 8) & GENMASK(15, 8)) | ||
| 917 | /* | ||
| 918 | * RXDET_BREAK_DIS value This parameter configures terminating the Far-end | ||
| 919 | * Receiver termination detection sequence: | ||
| 920 | * 0: it is possible that USBSS_DEV will terminate Farend receiver | ||
| 921 | * termination detection sequence | ||
| 922 | * 1: USBSS_DEV will not terminate Far-end receiver termination | ||
| 923 | * detection sequence | ||
| 924 | */ | ||
| 925 | #define DBG_LINK1_RXDET_BREAK_DIS BIT(16) | ||
| 926 | /* LFPS_GEN_PING value This parameter configures the LFPS.Ping generation */ | ||
| 927 | #define DBG_LINK1_LFPS_GEN_PING(p) (((p) << 17) & GENMASK(21, 17)) | ||
| 928 | /* | ||
| 929 | * Set the LFPS_MIN_DET_U1_EXIT value Writing '1' to this bit writes the | ||
| 930 | * LFPS_MIN_DET_U1_EXIT field value to the device. This bit is automatically | ||
| 931 | * cleared. Writing '0' has no effect | ||
| 932 | */ | ||
| 933 | #define DBG_LINK1_LFPS_MIN_DET_U1_EXIT_SET BIT(24) | ||
| 934 | /* | ||
| 935 | * Set the LFPS_MIN_GEN_U1_EXIT value. Writing '1' to this bit writes the | ||
| 936 | * LFPS_MIN_GEN_U1_EXIT field value to the device. This bit is automatically | ||
| 937 | * cleared. Writing '0' has no effect | ||
| 938 | */ | ||
| 939 | #define DBG_LINK1_LFPS_MIN_GEN_U1_EXIT_SET BIT(25) | ||
| 940 | /* | ||
| 941 | * Set the RXDET_BREAK_DIS value Writing '1' to this bit writes | ||
| 942 | * the RXDET_BREAK_DIS field value to the device. This bit is automatically | ||
| 943 | * cleared. Writing '0' has no effect | ||
| 944 | */ | ||
| 945 | #define DBG_LINK1_RXDET_BREAK_DIS_SET BIT(26) | ||
| 946 | /* | ||
| 947 | * Set the LFPS_GEN_PING_SET value Writing '1' to this bit writes | ||
| 948 | * the LFPS_GEN_PING field value to the device. This bit is automatically | ||
| 949 | * cleared. Writing '0' has no effect." | ||
| 950 | */ | ||
| 951 | #define DBG_LINK1_LFPS_GEN_PING_SET BIT(27) | ||
| 952 | |||
| 953 | /* DMA_AXI_CTRL- bitmasks */ | ||
| 954 | /* The mawprot pin configuration. */ | ||
| 955 | #define DMA_AXI_CTRL_MARPROT(p) ((p) & GENMASK(2, 0)) | ||
| 956 | /* The marprot pin configuration. */ | ||
| 957 | #define DMA_AXI_CTRL_MAWPROT(p) (((p) & GENMASK(2, 0)) << 16) | ||
| 958 | #define DMA_AXI_CTRL_NON_SECURE 0x02 | ||
| 959 | |||
| 960 | #define gadget_to_cdns3_device(g) (container_of(g, struct cdns3_device, gadget)) | ||
| 961 | |||
| 962 | #define ep_to_cdns3_ep(ep) (container_of(ep, struct cdns3_endpoint, endpoint)) | ||
| 963 | |||
| 964 | /*-------------------------------------------------------------------------*/ | ||
| 965 | /* | ||
| 966 | * USBSS-DEV DMA interface. | ||
| 967 | */ | ||
| 968 | #define TRBS_PER_SEGMENT 40 | ||
| 969 | |||
| 970 | #define ISO_MAX_INTERVAL 10 | ||
| 971 | |||
| 972 | #if TRBS_PER_SEGMENT < 2 | ||
| 973 | #error "Incorrect TRBS_PER_SEGMENT. Minimal Transfer Ring size is 2." | ||
| 974 | #endif | ||
| 975 | |||
| 976 | /* | ||
| 977 | *Only for ISOC endpoints - maximum number of TRBs is calculated as | ||
| 978 | * pow(2, bInterval-1) * number of usb requests. It is limitation made by | ||
| 979 | * driver to save memory. Controller must prepare TRB for each ITP even | ||
| 980 | * if bInterval > 1. It's the reason why driver needs so many TRBs for | ||
| 981 | * isochronous endpoints. | ||
| 982 | */ | ||
| 983 | #define TRBS_PER_ISOC_SEGMENT (ISO_MAX_INTERVAL * 8) | ||
| 984 | |||
| 985 | #define GET_TRBS_PER_SEGMENT(ep_type) ((ep_type) == USB_ENDPOINT_XFER_ISOC ? \ | ||
| 986 | TRBS_PER_ISOC_SEGMENT : TRBS_PER_SEGMENT) | ||
| 987 | /** | ||
| 988 | * struct cdns3_trb - represent Transfer Descriptor block. | ||
| 989 | * @buffer: pointer to buffer data | ||
| 990 | * @length: length of data | ||
| 991 | * @control: control flags. | ||
| 992 | * | ||
| 993 | * This structure describes transfer block serviced by DMA module. | ||
| 994 | */ | ||
| 995 | struct cdns3_trb { | ||
| 996 | __le32 buffer; | ||
| 997 | __le32 length; | ||
| 998 | __le32 control; | ||
| 999 | }; | ||
| 1000 | |||
| 1001 | #define TRB_SIZE (sizeof(struct cdns3_trb)) | ||
| 1002 | #define TRB_RING_SIZE (TRB_SIZE * TRBS_PER_SEGMENT) | ||
| 1003 | #define TRB_ISO_RING_SIZE (TRB_SIZE * TRBS_PER_ISOC_SEGMENT) | ||
| 1004 | #define TRB_CTRL_RING_SIZE (TRB_SIZE * 2) | ||
| 1005 | |||
| 1006 | /* TRB bit mask */ | ||
| 1007 | #define TRB_TYPE_BITMASK GENMASK(15, 10) | ||
| 1008 | #define TRB_TYPE(p) ((p) << 10) | ||
| 1009 | #define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) | ||
| 1010 | |||
| 1011 | /* TRB type IDs */ | ||
| 1012 | /* bulk, interrupt, isoc , and control data stage */ | ||
| 1013 | #define TRB_NORMAL 1 | ||
| 1014 | /* TRB for linking ring segments */ | ||
| 1015 | #define TRB_LINK 6 | ||
| 1016 | |||
| 1017 | /* Cycle bit - indicates TRB ownership by driver or hw*/ | ||
| 1018 | #define TRB_CYCLE BIT(0) | ||
| 1019 | /* | ||
| 1020 | * When set to '1', the device will toggle its interpretation of the Cycle bit | ||
| 1021 | */ | ||
| 1022 | #define TRB_TOGGLE BIT(1) | ||
| 1023 | |||
| 1024 | /* | ||
| 1025 | * Short Packet (SP). OUT EPs at DMULT=1 only. Indicates if the TRB was | ||
| 1026 | * processed while USB short packet was received. No more buffers defined by | ||
| 1027 | * the TD will be used. DMA will automatically advance to next TD. | ||
| 1028 | * - Shall be set to 0 by Software when putting TRB on the Transfer Ring | ||
| 1029 | * - Shall be set to 1 by Controller when Short Packet condition for this TRB | ||
| 1030 | * is detected independent if ISP is set or not. | ||
| 1031 | */ | ||
| 1032 | #define TRB_SP BIT(1) | ||
| 1033 | |||
| 1034 | /* Interrupt on short packet*/ | ||
| 1035 | #define TRB_ISP BIT(2) | ||
| 1036 | /*Setting this bit enables FIFO DMA operation mode*/ | ||
| 1037 | #define TRB_FIFO_MODE BIT(3) | ||
| 1038 | /* Set PCIe no snoop attribute */ | ||
| 1039 | #define TRB_CHAIN BIT(4) | ||
| 1040 | /* Interrupt on completion */ | ||
| 1041 | #define TRB_IOC BIT(5) | ||
| 1042 | |||
| 1043 | /* stream ID bitmasks. */ | ||
| 1044 | #define TRB_STREAM_ID_BITMASK GENMASK(31, 16) | ||
| 1045 | #define TRB_STREAM_ID(p) ((p) << 16) | ||
| 1046 | #define TRB_FIELD_TO_STREAMID(p) (((p) & TRB_STREAM_ID_BITMASK) >> 16) | ||
| 1047 | |||
| 1048 | /* Size of TD expressed in USB packets for HS/FS mode. */ | ||
| 1049 | #define TRB_TDL_HS_SIZE(p) (((p) << 16) & GENMASK(31, 16)) | ||
| 1050 | #define TRB_TDL_HS_SIZE_GET(p) (((p) & GENMASK(31, 16)) >> 16) | ||
| 1051 | |||
| 1052 | /* transfer_len bitmasks. */ | ||
| 1053 | #define TRB_LEN(p) ((p) & GENMASK(16, 0)) | ||
| 1054 | |||
| 1055 | /* Size of TD expressed in USB packets for SS mode. */ | ||
| 1056 | #define TRB_TDL_SS_SIZE(p) (((p) << 17) & GENMASK(23, 17)) | ||
| 1057 | #define TRB_TDL_SS_SIZE_GET(p) (((p) & GENMASK(23, 17)) >> 17) | ||
| 1058 | |||
| 1059 | /* transfer_len bitmasks - bits 31:24 */ | ||
| 1060 | #define TRB_BURST_LEN(p) (((p) << 24) & GENMASK(31, 24)) | ||
| 1061 | #define TRB_BURST_LEN_GET(p) (((p) & GENMASK(31, 24)) >> 24) | ||
| 1062 | |||
| 1063 | /* Data buffer pointer bitmasks*/ | ||
| 1064 | #define TRB_BUFFER(p) ((p) & GENMASK(31, 0)) | ||
| 1065 | |||
| 1066 | /*-------------------------------------------------------------------------*/ | ||
| 1067 | /* Driver numeric constants */ | ||
| 1068 | |||
| 1069 | /* Such declaration should be added to ch9.h */ | ||
| 1070 | #define USB_DEVICE_MAX_ADDRESS 127 | ||
| 1071 | |||
| 1072 | /* Endpoint init values */ | ||
| 1073 | #define CDNS3_EP_MAX_PACKET_LIMIT 1024 | ||
| 1074 | #define CDNS3_EP_MAX_STREAMS 15 | ||
| 1075 | #define CDNS3_EP0_MAX_PACKET_LIMIT 512 | ||
| 1076 | |||
| 1077 | /* All endpoints including EP0 */ | ||
| 1078 | #define CDNS3_ENDPOINTS_MAX_COUNT 32 | ||
| 1079 | #define CDNS3_EP_ZLP_BUF_SIZE 1024 | ||
| 1080 | |||
| 1081 | #define CDNS3_EP_BUF_SIZE 2 /* KB */ | ||
| 1082 | #define CDNS3_EP_ISO_HS_MULT 3 | ||
| 1083 | #define CDNS3_EP_ISO_SS_BURST 3 | ||
| 1084 | #define CDNS3_MAX_NUM_DESCMISS_BUF 32 | ||
| 1085 | #define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */ | ||
| 1086 | #define CDNS3_WA2_NUM_BUFFERS 128 | ||
| 1087 | /*-------------------------------------------------------------------------*/ | ||
| 1088 | /* Used structs */ | ||
| 1089 | |||
| 1090 | struct cdns3_device; | ||
| 1091 | |||
| 1092 | /** | ||
| 1093 | * struct cdns3_endpoint - extended device side representation of USB endpoint. | ||
| 1094 | * @endpoint: usb endpoint | ||
| 1095 | * @pending_req_list: list of requests queuing on transfer ring. | ||
| 1096 | * @deferred_req_list: list of requests waiting for queuing on transfer ring. | ||
| 1097 | * @wa2_descmiss_req_list: list of requests internally allocated by driver. | ||
| 1098 | * @trb_pool: transfer ring - array of transaction buffers | ||
| 1099 | * @trb_pool_dma: dma address of transfer ring | ||
| 1100 | * @cdns3_dev: device associated with this endpoint | ||
| 1101 | * @name: a human readable name e.g. ep1out | ||
| 1102 | * @flags: specify the current state of endpoint | ||
| 1103 | * @descmis_req: internal transfer object used for getting data from on-chip | ||
| 1104 | * buffer. It can happen only if function driver doesn't send usb_request | ||
| 1105 | * object on time. | ||
| 1106 | * @dir: endpoint direction | ||
| 1107 | * @num: endpoint number (1 - 15) | ||
| 1108 | * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK | ||
| 1109 | * @interval: interval between packets used for ISOC endpoint. | ||
| 1110 | * @free_trbs: number of free TRBs in transfer ring | ||
| 1111 | * @num_trbs: number of all TRBs in transfer ring | ||
| 1112 | * @pcs: producer cycle state | ||
| 1113 | * @ccs: consumer cycle state | ||
| 1114 | * @enqueue: enqueue index in transfer ring | ||
| 1115 | * @dequeue: dequeue index in transfer ring | ||
| 1116 | * @trb_burst_size: number of burst used in trb. | ||
| 1117 | */ | ||
| 1118 | struct cdns3_endpoint { | ||
| 1119 | struct usb_ep endpoint; | ||
| 1120 | struct list_head pending_req_list; | ||
| 1121 | struct list_head deferred_req_list; | ||
| 1122 | struct list_head wa2_descmiss_req_list; | ||
| 1123 | int wa2_counter; | ||
| 1124 | |||
| 1125 | struct cdns3_trb *trb_pool; | ||
| 1126 | dma_addr_t trb_pool_dma; | ||
| 1127 | |||
| 1128 | struct cdns3_device *cdns3_dev; | ||
| 1129 | char name[20]; | ||
| 1130 | |||
| 1131 | #define EP_ENABLED BIT(0) | ||
| 1132 | #define EP_STALLED BIT(1) | ||
| 1133 | #define EP_STALL_PENDING BIT(2) | ||
| 1134 | #define EP_WEDGE BIT(3) | ||
| 1135 | #define EP_TRANSFER_STARTED BIT(4) | ||
| 1136 | #define EP_UPDATE_EP_TRBADDR BIT(5) | ||
| 1137 | #define EP_PENDING_REQUEST BIT(6) | ||
| 1138 | #define EP_RING_FULL BIT(7) | ||
| 1139 | #define EP_CLAIMED BIT(8) | ||
| 1140 | #define EP_DEFERRED_DRDY BIT(9) | ||
| 1141 | #define EP_QUIRK_ISO_OUT_EN BIT(10) | ||
| 1142 | #define EP_QUIRK_END_TRANSFER BIT(11) | ||
| 1143 | #define EP_QUIRK_EXTRA_BUF_DET BIT(12) | ||
| 1144 | #define EP_QUIRK_EXTRA_BUF_EN BIT(13) | ||
| 1145 | u32 flags; | ||
| 1146 | |||
| 1147 | struct cdns3_request *descmis_req; | ||
| 1148 | |||
| 1149 | u8 dir; | ||
| 1150 | u8 num; | ||
| 1151 | u8 type; | ||
| 1152 | int interval; | ||
| 1153 | |||
| 1154 | int free_trbs; | ||
| 1155 | int num_trbs; | ||
| 1156 | u8 pcs; | ||
| 1157 | u8 ccs; | ||
| 1158 | int enqueue; | ||
| 1159 | int dequeue; | ||
| 1160 | u8 trb_burst_size; | ||
| 1161 | |||
| 1162 | unsigned int wa1_set:1; | ||
| 1163 | struct cdns3_trb *wa1_trb; | ||
| 1164 | unsigned int wa1_trb_index; | ||
| 1165 | unsigned int wa1_cycle_bit:1; | ||
| 1166 | }; | ||
| 1167 | |||
| 1168 | /** | ||
| 1169 | * struct cdns3_aligned_buf - represent aligned buffer used for DMA transfer | ||
| 1170 | * @buf: aligned to 8 bytes data buffer. Buffer address used in | ||
| 1171 | * TRB shall be aligned to 8. | ||
| 1172 | * @dma: dma address | ||
| 1173 | * @size: size of buffer | ||
| 1174 | * @in_use: inform if this buffer is associated with usb_request | ||
| 1175 | * @list: used to adding instance of this object to list | ||
| 1176 | */ | ||
| 1177 | struct cdns3_aligned_buf { | ||
| 1178 | void *buf; | ||
| 1179 | dma_addr_t dma; | ||
| 1180 | u32 size; | ||
| 1181 | int in_use:1; | ||
| 1182 | struct list_head list; | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | /** | ||
| 1186 | * struct cdns3_request - extended device side representation of usb_request | ||
| 1187 | * object . | ||
| 1188 | * @request: generic usb_request object describing single I/O request. | ||
| 1189 | * @priv_ep: extended representation of usb_ep object | ||
| 1190 | * @trb: the first TRB association with this request | ||
| 1191 | * @start_trb: number of the first TRB in transfer ring | ||
| 1192 | * @end_trb: number of the last TRB in transfer ring | ||
| 1193 | * @aligned_buf: object holds information about aligned buffer associated whit | ||
| 1194 | * this endpoint | ||
| 1195 | * @flags: flag specifying special usage of request | ||
| 1196 | * @list: used by internally allocated request to add to wa2_descmiss_req_list. | ||
| 1197 | */ | ||
| 1198 | struct cdns3_request { | ||
| 1199 | struct usb_request request; | ||
| 1200 | struct cdns3_endpoint *priv_ep; | ||
| 1201 | struct cdns3_trb *trb; | ||
| 1202 | int start_trb; | ||
| 1203 | int end_trb; | ||
| 1204 | struct cdns3_aligned_buf *aligned_buf; | ||
| 1205 | #define REQUEST_PENDING BIT(0) | ||
| 1206 | #define REQUEST_INTERNAL BIT(1) | ||
| 1207 | #define REQUEST_INTERNAL_CH BIT(2) | ||
| 1208 | #define REQUEST_ZLP BIT(3) | ||
| 1209 | #define REQUEST_UNALIGNED BIT(4) | ||
| 1210 | u32 flags; | ||
| 1211 | struct list_head list; | ||
| 1212 | }; | ||
| 1213 | |||
| 1214 | #define to_cdns3_request(r) (container_of(r, struct cdns3_request, request)) | ||
| 1215 | |||
| 1216 | /*Stages used during enumeration process.*/ | ||
| 1217 | #define CDNS3_SETUP_STAGE 0x0 | ||
| 1218 | #define CDNS3_DATA_STAGE 0x1 | ||
| 1219 | #define CDNS3_STATUS_STAGE 0x2 | ||
| 1220 | |||
| 1221 | /** | ||
| 1222 | * struct cdns3_device - represent USB device. | ||
| 1223 | * @dev: pointer to device structure associated whit this controller | ||
| 1224 | * @sysdev: pointer to the DMA capable device | ||
| 1225 | * @gadget: device side representation of the peripheral controller | ||
| 1226 | * @gadget_driver: pointer to the gadget driver | ||
| 1227 | * @dev_ver: device controller version. | ||
| 1228 | * @lock: for synchronizing | ||
| 1229 | * @regs: base address for device side registers | ||
| 1230 | * @setup_buf: used while processing usb control requests | ||
| 1231 | * @setup_dma: dma address for setup_buf | ||
| 1232 | * @zlp_buf - zlp buffer | ||
| 1233 | * @ep0_stage: ep0 stage during enumeration process. | ||
| 1234 | * @ep0_data_dir: direction for control transfer | ||
| 1235 | * @eps: array of pointers to all endpoints with exclusion ep0 | ||
| 1236 | * @aligned_buf_list: list of aligned buffers internally allocated by driver | ||
| 1237 | * @aligned_buf_wq: workqueue freeing no longer used aligned buf. | ||
| 1238 | * @selected_ep: actually selected endpoint. It's used only to improve | ||
| 1239 | * performance. | ||
| 1240 | * @isoch_delay: value from Set Isoch Delay request. Only valid on SS/SSP. | ||
| 1241 | * @u1_allowed: allow device transition to u1 state | ||
| 1242 | * @u2_allowed: allow device transition to u2 state | ||
| 1243 | * @is_selfpowered: device is self powered | ||
| 1244 | * @setup_pending: setup packet is processing by gadget driver | ||
| 1245 | * @hw_configured_flag: hardware endpoint configuration was set. | ||
| 1246 | * @wake_up_flag: allow device to remote up the host | ||
| 1247 | * @status_completion_no_call: indicate that driver is waiting for status s | ||
| 1248 | * stage completion. It's used in deferred SET_CONFIGURATION request. | ||
| 1249 | * @onchip_buffers: number of available on-chip buffers. | ||
| 1250 | * @onchip_used_size: actual size of on-chip memory assigned to endpoints. | ||
| 1251 | * @pending_status_wq: workqueue handling status stage for deferred requests. | ||
| 1252 | * @pending_status_request: request for which status stage was deferred | ||
| 1253 | */ | ||
| 1254 | struct cdns3_device { | ||
| 1255 | struct device *dev; | ||
| 1256 | struct device *sysdev; | ||
| 1257 | |||
| 1258 | struct usb_gadget gadget; | ||
| 1259 | struct usb_gadget_driver *gadget_driver; | ||
| 1260 | |||
| 1261 | #define CDNS_REVISION_V0 0x00024501 | ||
| 1262 | #define CDNS_REVISION_V1 0x00024509 | ||
| 1263 | u32 dev_ver; | ||
| 1264 | |||
| 1265 | /* generic spin-lock for drivers */ | ||
| 1266 | spinlock_t lock; | ||
| 1267 | |||
| 1268 | struct cdns3_usb_regs __iomem *regs; | ||
| 1269 | |||
| 1270 | struct usb_ctrlrequest *setup_buf; | ||
| 1271 | dma_addr_t setup_dma; | ||
| 1272 | void *zlp_buf; | ||
| 1273 | |||
| 1274 | u8 ep0_stage; | ||
| 1275 | int ep0_data_dir; | ||
| 1276 | |||
| 1277 | struct cdns3_endpoint *eps[CDNS3_ENDPOINTS_MAX_COUNT]; | ||
| 1278 | |||
| 1279 | struct list_head aligned_buf_list; | ||
| 1280 | struct work_struct aligned_buf_wq; | ||
| 1281 | |||
| 1282 | u32 selected_ep; | ||
| 1283 | u16 isoch_delay; | ||
| 1284 | |||
| 1285 | unsigned wait_for_setup:1; | ||
| 1286 | unsigned u1_allowed:1; | ||
| 1287 | unsigned u2_allowed:1; | ||
| 1288 | unsigned is_selfpowered:1; | ||
| 1289 | unsigned setup_pending:1; | ||
| 1290 | int hw_configured_flag:1; | ||
| 1291 | int wake_up_flag:1; | ||
| 1292 | unsigned status_completion_no_call:1; | ||
| 1293 | int out_mem_is_allocated; | ||
| 1294 | |||
| 1295 | struct work_struct pending_status_wq; | ||
| 1296 | struct usb_request *pending_status_request; | ||
| 1297 | |||
| 1298 | /*in KB */ | ||
| 1299 | u16 onchip_buffers; | ||
| 1300 | u16 onchip_used_size; | ||
| 1301 | }; | ||
| 1302 | |||
| 1303 | void cdns3_set_register_bit(void __iomem *ptr, u32 mask); | ||
| 1304 | dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, | ||
| 1305 | struct cdns3_trb *trb); | ||
| 1306 | enum usb_device_speed cdns3_get_speed(struct cdns3_device *priv_dev); | ||
| 1307 | void cdns3_pending_setup_status_handler(struct work_struct *work); | ||
| 1308 | void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev); | ||
| 1309 | void cdns3_set_hw_configuration(struct cdns3_device *priv_dev); | ||
| 1310 | void cdns3_select_ep(struct cdns3_device *priv_dev, u32 ep); | ||
| 1311 | void cdns3_allow_enable_l1(struct cdns3_device *priv_dev, int enable); | ||
| 1312 | struct usb_request *cdns3_next_request(struct list_head *list); | ||
| 1313 | int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, | ||
| 1314 | struct usb_request *request); | ||
| 1315 | void cdns3_rearm_transfer(struct cdns3_endpoint *priv_ep, u8 rearm); | ||
| 1316 | int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep); | ||
| 1317 | u8 cdns3_ep_addr_to_index(u8 ep_addr); | ||
| 1318 | int cdns3_gadget_ep_set_wedge(struct usb_ep *ep); | ||
| 1319 | int cdns3_gadget_ep_set_halt(struct usb_ep *ep, int value); | ||
| 1320 | void __cdns3_gadget_ep_set_halt(struct cdns3_endpoint *priv_ep); | ||
| 1321 | int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep); | ||
| 1322 | struct usb_request *cdns3_gadget_ep_alloc_request(struct usb_ep *ep, | ||
| 1323 | gfp_t gfp_flags); | ||
| 1324 | void cdns3_gadget_ep_free_request(struct usb_ep *ep, | ||
| 1325 | struct usb_request *request); | ||
| 1326 | int cdns3_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *request); | ||
| 1327 | void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, | ||
| 1328 | struct cdns3_request *priv_req, | ||
| 1329 | int status); | ||
| 1330 | |||
| 1331 | int cdns3_init_ep0(struct cdns3_device *priv_dev, | ||
| 1332 | struct cdns3_endpoint *priv_ep); | ||
| 1333 | void cdns3_ep0_config(struct cdns3_device *priv_dev); | ||
| 1334 | void cdns3_ep_config(struct cdns3_endpoint *priv_ep); | ||
| 1335 | void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir); | ||
| 1336 | int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev); | ||
| 1337 | |||
| 1338 | #endif /* __LINUX_CDNS3_GADGET */ | ||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver - Host Export APIs | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017-2018 NXP | ||
| 6 | * | ||
| 7 | * Authors: Peter Chen <peter.chen@nxp.com> | ||
| 8 | */ | ||
| 9 | #ifndef __LINUX_CDNS3_HOST_EXPORT | ||
| 10 | #define __LINUX_CDNS3_HOST_EXPORT | ||
| 11 | |||
| 12 | #ifdef CONFIG_USB_CDNS3_HOST | ||
| 13 | |||
| 14 | int cdns3_host_init(struct cdns3 *cdns); | ||
| 15 | void cdns3_host_exit(struct cdns3 *cdns); | ||
| 16 | |||
| 17 | #else | ||
| 18 | |||
| 19 | static inline int cdns3_host_init(struct cdns3 *cdns) | ||
| 20 | { | ||
| 21 | return -ENXIO; | ||
| 22 | } | ||
| 23 | |||
| 24 | static inline void cdns3_host_exit(struct cdns3 *cdns) { } | ||
| 25 | |||
| 26 | #endif /* CONFIG_USB_CDNS3_HOST */ | ||
| 27 | |||
| 28 | #endif /* __LINUX_CDNS3_HOST_EXPORT */ | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Cadence USBSS DRD Driver - host side | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence Design Systems. | ||
| 6 | * Copyright (C) 2017-2018 NXP | ||
| 7 | * | ||
| 8 | * Authors: Peter Chen <peter.chen@nxp.com> | ||
| 9 | * Pawel Laszczak <pawell@cadence.com> | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include "core.h" | ||
| 14 | #include "drd.h" | ||
| 15 | |||
| 16 | static int __cdns3_host_init(struct cdns3 *cdns) | ||
| 17 | { | ||
| 18 | struct platform_device *xhci; | ||
| 19 | int ret; | ||
| 20 | |||
| 21 | cdns3_drd_switch_host(cdns, 1); | ||
| 22 | |||
| 23 | xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); | ||
| 24 | if (!xhci) { | ||
| 25 | dev_err(cdns->dev, "couldn't allocate xHCI device\n"); | ||
| 26 | return -ENOMEM; | ||
| 27 | } | ||
| 28 | |||
| 29 | xhci->dev.parent = cdns->dev; | ||
| 30 | cdns->host_dev = xhci; | ||
| 31 | |||
| 32 | ret = platform_device_add_resources(xhci, cdns->xhci_res, | ||
| 33 | CDNS3_XHCI_RESOURCES_NUM); | ||
| 34 | if (ret) { | ||
| 35 | dev_err(cdns->dev, "couldn't add resources to xHCI device\n"); | ||
| 36 | goto err1; | ||
| 37 | } | ||
| 38 | |||
| 39 | ret = platform_device_add(xhci); | ||
| 40 | if (ret) { | ||
| 41 | dev_err(cdns->dev, "failed to register xHCI device\n"); | ||
| 42 | goto err1; | ||
| 43 | } | ||
| 44 | |||
| 45 | return 0; | ||
| 46 | err1: | ||
| 47 | platform_device_put(xhci); | ||
| 48 | return ret; | ||
| 49 | } | ||
| 50 | |||
| 51 | static void cdns3_host_exit(struct cdns3 *cdns) | ||
| 52 | { | ||
| 53 | platform_device_unregister(cdns->host_dev); | ||
| 54 | cdns->host_dev = NULL; | ||
| 55 | cdns3_drd_switch_host(cdns, 0); | ||
| 56 | } | ||
| 57 | |||
| 58 | int cdns3_host_init(struct cdns3 *cdns) | ||
| 59 | { | ||
| 60 | struct cdns3_role_driver *rdrv; | ||
| 61 | |||
| 62 | rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); | ||
| 63 | if (!rdrv) | ||
| 64 | return -ENOMEM; | ||
| 65 | |||
| 66 | rdrv->start = __cdns3_host_init; | ||
| 67 | rdrv->stop = cdns3_host_exit; | ||
| 68 | rdrv->state = CDNS3_ROLE_STATE_INACTIVE; | ||
| 69 | rdrv->name = "host"; | ||
| 70 | |||
| 71 | cdns->roles[USB_ROLE_HOST] = rdrv; | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * USBSS device controller driver Trace Support | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Cadence. | ||
| 6 | * | ||
| 7 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define CREATE_TRACE_POINTS | ||
| 11 | #include "trace.h" | ||
| @@ -0,0 +1,493 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * USBSS device controller driver. | ||
| 4 | * Trace support header file. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2018-2019 Cadence. | ||
| 7 | * | ||
| 8 | * Author: Pawel Laszczak <pawell@cadence.com> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #undef TRACE_SYSTEM | ||
| 12 | #define TRACE_SYSTEM cdns3 | ||
| 13 | |||
| 14 | #if !defined(__LINUX_CDNS3_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
| 15 | #define __LINUX_CDNS3_TRACE | ||
| 16 | |||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/tracepoint.h> | ||
| 19 | #include <asm/byteorder.h> | ||
| 20 | #include <linux/usb/ch9.h> | ||
| 21 | #include "core.h" | ||
| 22 | #include "gadget.h" | ||
| 23 | #include "debug.h" | ||
| 24 | |||
| 25 | #define CDNS3_MSG_MAX 500 | ||
| 26 | |||
| 27 | TRACE_EVENT(cdns3_halt, | ||
| 28 | TP_PROTO(struct cdns3_endpoint *ep_priv, u8 halt, u8 flush), | ||
| 29 | TP_ARGS(ep_priv, halt, flush), | ||
| 30 | TP_STRUCT__entry( | ||
| 31 | __string(name, ep_priv->name) | ||
| 32 | __field(u8, halt) | ||
| 33 | __field(u8, flush) | ||
| 34 | ), | ||
| 35 | TP_fast_assign( | ||
| 36 | __assign_str(name, ep_priv->name); | ||
| 37 | __entry->halt = halt; | ||
| 38 | __entry->flush = flush; | ||
| 39 | ), | ||
| 40 | TP_printk("Halt %s for %s: %s", __entry->flush ? " and flush" : "", | ||
| 41 | __get_str(name), __entry->halt ? "set" : "cleared") | ||
| 42 | ); | ||
| 43 | |||
| 44 | TRACE_EVENT(cdns3_wa1, | ||
| 45 | TP_PROTO(struct cdns3_endpoint *ep_priv, char *msg), | ||
| 46 | TP_ARGS(ep_priv, msg), | ||
| 47 | TP_STRUCT__entry( | ||
| 48 | __string(ep_name, ep_priv->name) | ||
| 49 | __string(msg, msg) | ||
| 50 | ), | ||
| 51 | TP_fast_assign( | ||
| 52 | __assign_str(ep_name, ep_priv->name); | ||
| 53 | __assign_str(msg, msg); | ||
| 54 | ), | ||
| 55 | TP_printk("WA1: %s %s", __get_str(ep_name), __get_str(msg)) | ||
| 56 | ); | ||
| 57 | |||
| 58 | TRACE_EVENT(cdns3_wa2, | ||
| 59 | TP_PROTO(struct cdns3_endpoint *ep_priv, char *msg), | ||
| 60 | TP_ARGS(ep_priv, msg), | ||
| 61 | TP_STRUCT__entry( | ||
| 62 | __string(ep_name, ep_priv->name) | ||
| 63 | __string(msg, msg) | ||
| 64 | ), | ||
| 65 | TP_fast_assign( | ||
| 66 | __assign_str(ep_name, ep_priv->name); | ||
| 67 | __assign_str(msg, msg); | ||
| 68 | ), | ||
| 69 | TP_printk("WA2: %s %s", __get_str(ep_name), __get_str(msg)) | ||
| 70 | ); | ||
| 71 | |||
| 72 | DECLARE_EVENT_CLASS(cdns3_log_doorbell, | ||
| 73 | TP_PROTO(const char *ep_name, u32 ep_trbaddr), | ||
| 74 | TP_ARGS(ep_name, ep_trbaddr), | ||
| 75 | TP_STRUCT__entry( | ||
| 76 | __string(name, ep_name) | ||
| 77 | __field(u32, ep_trbaddr) | ||
| 78 | ), | ||
| 79 | TP_fast_assign( | ||
| 80 | __assign_str(name, ep_name); | ||
| 81 | __entry->ep_trbaddr = ep_trbaddr; | ||
| 82 | ), | ||
| 83 | TP_printk("%s, ep_trbaddr %08x", __get_str(name), | ||
| 84 | __entry->ep_trbaddr) | ||
| 85 | ); | ||
| 86 | |||
| 87 | DEFINE_EVENT(cdns3_log_doorbell, cdns3_doorbell_ep0, | ||
| 88 | TP_PROTO(const char *ep_name, u32 ep_trbaddr), | ||
| 89 | TP_ARGS(ep_name, ep_trbaddr) | ||
| 90 | ); | ||
| 91 | |||
| 92 | DEFINE_EVENT(cdns3_log_doorbell, cdns3_doorbell_epx, | ||
| 93 | TP_PROTO(const char *ep_name, u32 ep_trbaddr), | ||
| 94 | TP_ARGS(ep_name, ep_trbaddr) | ||
| 95 | ); | ||
| 96 | |||
| 97 | DECLARE_EVENT_CLASS(cdns3_log_usb_irq, | ||
| 98 | TP_PROTO(struct cdns3_device *priv_dev, u32 usb_ists), | ||
| 99 | TP_ARGS(priv_dev, usb_ists), | ||
| 100 | TP_STRUCT__entry( | ||
| 101 | __field(enum usb_device_speed, speed) | ||
| 102 | __field(u32, usb_ists) | ||
| 103 | __dynamic_array(char, str, CDNS3_MSG_MAX) | ||
| 104 | ), | ||
| 105 | TP_fast_assign( | ||
| 106 | __entry->speed = cdns3_get_speed(priv_dev); | ||
| 107 | __entry->usb_ists = usb_ists; | ||
| 108 | ), | ||
| 109 | TP_printk("%s", cdns3_decode_usb_irq(__get_str(str), __entry->speed, | ||
| 110 | __entry->usb_ists)) | ||
| 111 | ); | ||
| 112 | |||
| 113 | DEFINE_EVENT(cdns3_log_usb_irq, cdns3_usb_irq, | ||
| 114 | TP_PROTO(struct cdns3_device *priv_dev, u32 usb_ists), | ||
| 115 | TP_ARGS(priv_dev, usb_ists) | ||
| 116 | ); | ||
| 117 | |||
| 118 | DECLARE_EVENT_CLASS(cdns3_log_epx_irq, | ||
| 119 | TP_PROTO(struct cdns3_device *priv_dev, struct cdns3_endpoint *priv_ep), | ||
| 120 | TP_ARGS(priv_dev, priv_ep), | ||
| 121 | TP_STRUCT__entry( | ||
| 122 | __string(ep_name, priv_ep->name) | ||
| 123 | __field(u32, ep_sts) | ||
| 124 | __field(u32, ep_traddr) | ||
| 125 | __dynamic_array(char, str, CDNS3_MSG_MAX) | ||
| 126 | ), | ||
| 127 | TP_fast_assign( | ||
| 128 | __assign_str(ep_name, priv_ep->name); | ||
| 129 | __entry->ep_sts = readl(&priv_dev->regs->ep_sts); | ||
| 130 | __entry->ep_traddr = readl(&priv_dev->regs->ep_traddr); | ||
| 131 | ), | ||
| 132 | TP_printk("%s, ep_traddr: %08x", | ||
| 133 | cdns3_decode_epx_irq(__get_str(str), | ||
| 134 | __get_str(ep_name), | ||
| 135 | __entry->ep_sts), | ||
| 136 | __entry->ep_traddr) | ||
| 137 | ); | ||
| 138 | |||
| 139 | DEFINE_EVENT(cdns3_log_epx_irq, cdns3_epx_irq, | ||
| 140 | TP_PROTO(struct cdns3_device *priv_dev, struct cdns3_endpoint *priv_ep), | ||
| 141 | TP_ARGS(priv_dev, priv_ep) | ||
| 142 | ); | ||
| 143 | |||
| 144 | DECLARE_EVENT_CLASS(cdns3_log_ep0_irq, | ||
| 145 | TP_PROTO(struct cdns3_device *priv_dev, u32 ep_sts), | ||
| 146 | TP_ARGS(priv_dev, ep_sts), | ||
| 147 | TP_STRUCT__entry( | ||
| 148 | __field(int, ep_dir) | ||
| 149 | __field(u32, ep_sts) | ||
| 150 | __dynamic_array(char, str, CDNS3_MSG_MAX) | ||
| 151 | ), | ||
| 152 | TP_fast_assign( | ||
| 153 | __entry->ep_dir = priv_dev->ep0_data_dir; | ||
| 154 | __entry->ep_sts = ep_sts; | ||
| 155 | ), | ||
| 156 | TP_printk("%s", cdns3_decode_ep0_irq(__get_str(str), | ||
| 157 | __entry->ep_dir, | ||
| 158 | __entry->ep_sts)) | ||
| 159 | ); | ||
| 160 | |||
| 161 | DEFINE_EVENT(cdns3_log_ep0_irq, cdns3_ep0_irq, | ||
| 162 | TP_PROTO(struct cdns3_device *priv_dev, u32 ep_sts), | ||
| 163 | TP_ARGS(priv_dev, ep_sts) | ||
| 164 | ); | ||
| 165 | |||
| 166 | DECLARE_EVENT_CLASS(cdns3_log_ctrl, | ||
| 167 | TP_PROTO(struct usb_ctrlrequest *ctrl), | ||
| 168 | TP_ARGS(ctrl), | ||
| 169 | TP_STRUCT__entry( | ||
| 170 | __field(u8, bRequestType) | ||
| 171 | __field(u8, bRequest) | ||
| 172 | __field(u16, wValue) | ||
| 173 | __field(u16, wIndex) | ||
| 174 | __field(u16, wLength) | ||
| 175 | __dynamic_array(char, str, CDNS3_MSG_MAX) | ||
| 176 | ), | ||
| 177 | TP_fast_assign( | ||
| 178 | __entry->bRequestType = ctrl->bRequestType; | ||
| 179 | __entry->bRequest = ctrl->bRequest; | ||
| 180 | __entry->wValue = le16_to_cpu(ctrl->wValue); | ||
| 181 | __entry->wIndex = le16_to_cpu(ctrl->wIndex); | ||
| 182 | __entry->wLength = le16_to_cpu(ctrl->wLength); | ||
| 183 | ), | ||
| 184 | TP_printk("%s", usb_decode_ctrl(__get_str(str), CDNS3_MSG_MAX, | ||
| 185 | __entry->bRequestType, | ||
| 186 | __entry->bRequest, __entry->wValue, | ||
| 187 | __entry->wIndex, __entry->wLength) | ||
| 188 | ) | ||
| 189 | ); | ||
| 190 | |||
| 191 | DEFINE_EVENT(cdns3_log_ctrl, cdns3_ctrl_req, | ||
| 192 | TP_PROTO(struct usb_ctrlrequest *ctrl), | ||
| 193 | TP_ARGS(ctrl) | ||
| 194 | ); | ||
| 195 | |||
| 196 | DECLARE_EVENT_CLASS(cdns3_log_request, | ||
| 197 | TP_PROTO(struct cdns3_request *req), | ||
| 198 | TP_ARGS(req), | ||
| 199 | TP_STRUCT__entry( | ||
| 200 | __string(name, req->priv_ep->name) | ||
| 201 | __field(struct cdns3_request *, req) | ||
| 202 | __field(void *, buf) | ||
| 203 | __field(unsigned int, actual) | ||
| 204 | __field(unsigned int, length) | ||
| 205 | __field(int, status) | ||
| 206 | __field(int, zero) | ||
| 207 | __field(int, short_not_ok) | ||
| 208 | __field(int, no_interrupt) | ||
| 209 | __field(int, start_trb) | ||
| 210 | __field(int, end_trb) | ||
| 211 | __field(struct cdns3_trb *, start_trb_addr) | ||
| 212 | __field(int, flags) | ||
| 213 | ), | ||
| 214 | TP_fast_assign( | ||
| 215 | __assign_str(name, req->priv_ep->name); | ||
| 216 | __entry->req = req; | ||
| 217 | __entry->buf = req->request.buf; | ||
| 218 | __entry->actual = req->request.actual; | ||
| 219 | __entry->length = req->request.length; | ||
| 220 | __entry->status = req->request.status; | ||
| 221 | __entry->zero = req->request.zero; | ||
| 222 | __entry->short_not_ok = req->request.short_not_ok; | ||
| 223 | __entry->no_interrupt = req->request.no_interrupt; | ||
| 224 | __entry->start_trb = req->start_trb; | ||
| 225 | __entry->end_trb = req->end_trb; | ||
| 226 | __entry->start_trb_addr = req->trb; | ||
| 227 | __entry->flags = req->flags; | ||
| 228 | ), | ||
| 229 | TP_printk("%s: req: %p, req buff %p, length: %u/%u %s%s%s, status: %d," | ||
| 230 | " trb: [start:%d, end:%d: virt addr %pa], flags:%x ", | ||
| 231 | __get_str(name), __entry->req, __entry->buf, __entry->actual, | ||
| 232 | __entry->length, | ||
| 233 | __entry->zero ? "Z" : "z", | ||
| 234 | __entry->short_not_ok ? "S" : "s", | ||
| 235 | __entry->no_interrupt ? "I" : "i", | ||
| 236 | __entry->status, | ||
| 237 | __entry->start_trb, | ||
| 238 | __entry->end_trb, | ||
| 239 | __entry->start_trb_addr, | ||
| 240 | __entry->flags | ||
| 241 | ) | ||
| 242 | ); | ||
| 243 | |||
| 244 | DEFINE_EVENT(cdns3_log_request, cdns3_alloc_request, | ||
| 245 | TP_PROTO(struct cdns3_request *req), | ||
| 246 | TP_ARGS(req) | ||
| 247 | ); | ||
| 248 | |||
| 249 | DEFINE_EVENT(cdns3_log_request, cdns3_free_request, | ||
| 250 | TP_PROTO(struct cdns3_request *req), | ||
| 251 | TP_ARGS(req) | ||
| 252 | ); | ||
| 253 | |||
| 254 | DEFINE_EVENT(cdns3_log_request, cdns3_ep_queue, | ||
| 255 | TP_PROTO(struct cdns3_request *req), | ||
| 256 | TP_ARGS(req) | ||
| 257 | ); | ||
| 258 | |||
| 259 | DEFINE_EVENT(cdns3_log_request, cdns3_ep_dequeue, | ||
| 260 | TP_PROTO(struct cdns3_request *req), | ||
| 261 | TP_ARGS(req) | ||
| 262 | ); | ||
| 263 | |||
| 264 | DEFINE_EVENT(cdns3_log_request, cdns3_gadget_giveback, | ||
| 265 | TP_PROTO(struct cdns3_request *req), | ||
| 266 | TP_ARGS(req) | ||
| 267 | ); | ||
| 268 | |||
| 269 | TRACE_EVENT(cdns3_ep0_queue, | ||
| 270 | TP_PROTO(struct cdns3_device *dev_priv, struct usb_request *request), | ||
| 271 | TP_ARGS(dev_priv, request), | ||
| 272 | TP_STRUCT__entry( | ||
| 273 | __field(int, dir) | ||
| 274 | __field(int, length) | ||
| 275 | ), | ||
| 276 | TP_fast_assign( | ||
| 277 | __entry->dir = dev_priv->ep0_data_dir; | ||
| 278 | __entry->length = request->length; | ||
| 279 | ), | ||
| 280 | TP_printk("Queue to ep0%s length: %u", __entry->dir ? "in" : "out", | ||
| 281 | __entry->length) | ||
| 282 | ); | ||
| 283 | |||
| 284 | DECLARE_EVENT_CLASS(cdns3_log_aligned_request, | ||
| 285 | TP_PROTO(struct cdns3_request *priv_req), | ||
| 286 | TP_ARGS(priv_req), | ||
| 287 | TP_STRUCT__entry( | ||
| 288 | __string(name, priv_req->priv_ep->name) | ||
| 289 | __field(struct usb_request *, req) | ||
| 290 | __field(void *, buf) | ||
| 291 | __field(dma_addr_t, dma) | ||
| 292 | __field(void *, aligned_buf) | ||
| 293 | __field(dma_addr_t, aligned_dma) | ||
| 294 | __field(u32, aligned_buf_size) | ||
| 295 | ), | ||
| 296 | TP_fast_assign( | ||
| 297 | __assign_str(name, priv_req->priv_ep->name); | ||
| 298 | __entry->req = &priv_req->request; | ||
| 299 | __entry->buf = priv_req->request.buf; | ||
| 300 | __entry->dma = priv_req->request.dma; | ||
| 301 | __entry->aligned_buf = priv_req->aligned_buf->buf; | ||
| 302 | __entry->aligned_dma = priv_req->aligned_buf->dma; | ||
| 303 | __entry->aligned_buf_size = priv_req->aligned_buf->size; | ||
| 304 | ), | ||
| 305 | TP_printk("%s: req: %p, req buf %p, dma %pad a_buf %p a_dma %pad, size %d", | ||
| 306 | __get_str(name), __entry->req, __entry->buf, &__entry->dma, | ||
| 307 | __entry->aligned_buf, &__entry->aligned_dma, | ||
| 308 | __entry->aligned_buf_size | ||
| 309 | ) | ||
| 310 | ); | ||
| 311 | |||
| 312 | DEFINE_EVENT(cdns3_log_aligned_request, cdns3_free_aligned_request, | ||
| 313 | TP_PROTO(struct cdns3_request *req), | ||
| 314 | TP_ARGS(req) | ||
| 315 | ); | ||
| 316 | |||
| 317 | DEFINE_EVENT(cdns3_log_aligned_request, cdns3_prepare_aligned_request, | ||
| 318 | TP_PROTO(struct cdns3_request *req), | ||
| 319 | TP_ARGS(req) | ||
| 320 | ); | ||
| 321 | |||
| 322 | DECLARE_EVENT_CLASS(cdns3_log_trb, | ||
| 323 | TP_PROTO(struct cdns3_endpoint *priv_ep, struct cdns3_trb *trb), | ||
| 324 | TP_ARGS(priv_ep, trb), | ||
| 325 | TP_STRUCT__entry( | ||
| 326 | __string(name, priv_ep->name) | ||
| 327 | __field(struct cdns3_trb *, trb) | ||
| 328 | __field(u32, buffer) | ||
| 329 | __field(u32, length) | ||
| 330 | __field(u32, control) | ||
| 331 | __field(u32, type) | ||
| 332 | ), | ||
| 333 | TP_fast_assign( | ||
| 334 | __assign_str(name, priv_ep->name); | ||
| 335 | __entry->trb = trb; | ||
| 336 | __entry->buffer = trb->buffer; | ||
| 337 | __entry->length = trb->length; | ||
| 338 | __entry->control = trb->control; | ||
| 339 | __entry->type = usb_endpoint_type(priv_ep->endpoint.desc); | ||
| 340 | ), | ||
| 341 | TP_printk("%s: trb %p, dma buf: 0x%08x, size: %ld, burst: %d ctrl: 0x%08x (%s%s%s%s%s%s%s)", | ||
| 342 | __get_str(name), __entry->trb, __entry->buffer, | ||
| 343 | TRB_LEN(__entry->length), | ||
| 344 | (u8)TRB_BURST_LEN_GET(__entry->length), | ||
| 345 | __entry->control, | ||
| 346 | __entry->control & TRB_CYCLE ? "C=1, " : "C=0, ", | ||
| 347 | __entry->control & TRB_TOGGLE ? "T=1, " : "T=0, ", | ||
| 348 | __entry->control & TRB_ISP ? "ISP, " : "", | ||
| 349 | __entry->control & TRB_FIFO_MODE ? "FIFO, " : "", | ||
| 350 | __entry->control & TRB_CHAIN ? "CHAIN, " : "", | ||
| 351 | __entry->control & TRB_IOC ? "IOC, " : "", | ||
| 352 | TRB_FIELD_TO_TYPE(__entry->control) == TRB_NORMAL ? "Normal" : "LINK" | ||
| 353 | ) | ||
| 354 | ); | ||
| 355 | |||
| 356 | DEFINE_EVENT(cdns3_log_trb, cdns3_prepare_trb, | ||
| 357 | TP_PROTO(struct cdns3_endpoint *priv_ep, struct cdns3_trb *trb), | ||
| 358 | TP_ARGS(priv_ep, trb) | ||
| 359 | ); | ||
| 360 | |||
| 361 | DEFINE_EVENT(cdns3_log_trb, cdns3_complete_trb, | ||
| 362 | TP_PROTO(struct cdns3_endpoint *priv_ep, struct cdns3_trb *trb), | ||
| 363 | TP_ARGS(priv_ep, trb) | ||
| 364 | ); | ||
| 365 | |||
| 366 | DECLARE_EVENT_CLASS(cdns3_log_ring, | ||
| 367 | TP_PROTO(struct cdns3_endpoint *priv_ep), | ||
| 368 | TP_ARGS(priv_ep), | ||
| 369 | TP_STRUCT__entry( | ||
| 370 | __dynamic_array(u8, ring, TRB_RING_SIZE) | ||
| 371 | __dynamic_array(u8, priv_ep, sizeof(struct cdns3_endpoint)) | ||
| 372 | __dynamic_array(char, buffer, | ||
| 373 | (TRBS_PER_SEGMENT * 65) + CDNS3_MSG_MAX) | ||
| 374 | ), | ||
| 375 | TP_fast_assign( | ||
| 376 | memcpy(__get_dynamic_array(priv_ep), priv_ep, | ||
| 377 | sizeof(struct cdns3_endpoint)); | ||
| 378 | memcpy(__get_dynamic_array(ring), priv_ep->trb_pool, | ||
| 379 | TRB_RING_SIZE); | ||
| 380 | ), | ||
| 381 | |||
| 382 | TP_printk("%s", | ||
| 383 | cdns3_dbg_ring((struct cdns3_endpoint *)__get_str(priv_ep), | ||
| 384 | (struct cdns3_trb *)__get_str(ring), | ||
| 385 | __get_str(buffer))) | ||
| 386 | ); | ||
| 387 | |||
| 388 | DEFINE_EVENT(cdns3_log_ring, cdns3_ring, | ||
| 389 | TP_PROTO(struct cdns3_endpoint *priv_ep), | ||
| 390 | TP_ARGS(priv_ep) | ||
| 391 | ); | ||
| 392 | |||
| 393 | DECLARE_EVENT_CLASS(cdns3_log_ep, | ||
| 394 | TP_PROTO(struct cdns3_endpoint *priv_ep), | ||
| 395 | TP_ARGS(priv_ep), | ||
| 396 | TP_STRUCT__entry( | ||
| 397 | __string(name, priv_ep->name) | ||
| 398 | __field(unsigned int, maxpacket) | ||
| 399 | __field(unsigned int, maxpacket_limit) | ||
| 400 | __field(unsigned int, max_streams) | ||
| 401 | __field(unsigned int, maxburst) | ||
| 402 | __field(unsigned int, flags) | ||
| 403 | __field(unsigned int, dir) | ||
| 404 | __field(u8, enqueue) | ||
| 405 | __field(u8, dequeue) | ||
| 406 | ), | ||
| 407 | TP_fast_assign( | ||
| 408 | __assign_str(name, priv_ep->name); | ||
| 409 | __entry->maxpacket = priv_ep->endpoint.maxpacket; | ||
| 410 | __entry->maxpacket_limit = priv_ep->endpoint.maxpacket_limit; | ||
| 411 | __entry->max_streams = priv_ep->endpoint.max_streams; | ||
| 412 | __entry->maxburst = priv_ep->endpoint.maxburst; | ||
| 413 | __entry->flags = priv_ep->flags; | ||
| 414 | __entry->dir = priv_ep->dir; | ||
| 415 | __entry->enqueue = priv_ep->enqueue; | ||
| 416 | __entry->dequeue = priv_ep->dequeue; | ||
| 417 | ), | ||
| 418 | TP_printk("%s: mps: %d/%d. streams: %d, burst: %d, enq idx: %d, " | ||
| 419 | "deq idx: %d, flags %s%s%s%s%s%s%s%s, dir: %s", | ||
| 420 | __get_str(name), __entry->maxpacket, | ||
| 421 | __entry->maxpacket_limit, __entry->max_streams, | ||
| 422 | __entry->maxburst, __entry->enqueue, | ||
| 423 | __entry->dequeue, | ||
| 424 | __entry->flags & EP_ENABLED ? "EN | " : "", | ||
| 425 | __entry->flags & EP_STALLED ? "STALLED | " : "", | ||
| 426 | __entry->flags & EP_WEDGE ? "WEDGE | " : "", | ||
| 427 | __entry->flags & EP_TRANSFER_STARTED ? "STARTED | " : "", | ||
| 428 | __entry->flags & EP_UPDATE_EP_TRBADDR ? "UPD TRB | " : "", | ||
| 429 | __entry->flags & EP_PENDING_REQUEST ? "REQ PEN | " : "", | ||
| 430 | __entry->flags & EP_RING_FULL ? "RING FULL |" : "", | ||
| 431 | __entry->flags & EP_CLAIMED ? "CLAIMED " : "", | ||
| 432 | __entry->dir ? "IN" : "OUT" | ||
| 433 | ) | ||
| 434 | ); | ||
| 435 | |||
| 436 | DEFINE_EVENT(cdns3_log_ep, cdns3_gadget_ep_enable, | ||
| 437 | TP_PROTO(struct cdns3_endpoint *priv_ep), | ||
| 438 | TP_ARGS(priv_ep) | ||
| 439 | ); | ||
| 440 | |||
| 441 | DEFINE_EVENT(cdns3_log_ep, cdns3_gadget_ep_disable, | ||
| 442 | TP_PROTO(struct cdns3_endpoint *priv_ep), | ||
| 443 | TP_ARGS(priv_ep) | ||
| 444 | ); | ||
| 445 | |||
| 446 | DECLARE_EVENT_CLASS(cdns3_log_request_handled, | ||
| 447 | TP_PROTO(struct cdns3_request *priv_req, int current_index, | ||
| 448 | int handled), | ||
| 449 | TP_ARGS(priv_req, current_index, handled), | ||
| 450 | TP_STRUCT__entry( | ||
| 451 | __field(struct cdns3_request *, priv_req) | ||
| 452 | __field(unsigned int, dma_position) | ||
| 453 | __field(unsigned int, handled) | ||
| 454 | __field(unsigned int, dequeue_idx) | ||
| 455 | __field(unsigned int, enqueue_idx) | ||
| 456 | __field(unsigned int, start_trb) | ||
| 457 | __field(unsigned int, end_trb) | ||
| 458 | ), | ||
| 459 | TP_fast_assign( | ||
| 460 | __entry->priv_req = priv_req; | ||
| 461 | __entry->dma_position = current_index; | ||
| 462 | __entry->handled = handled; | ||
| 463 | __entry->dequeue_idx = priv_req->priv_ep->dequeue; | ||
| 464 | __entry->enqueue_idx = priv_req->priv_ep->enqueue; | ||
| 465 | __entry->start_trb = priv_req->start_trb; | ||
| 466 | __entry->end_trb = priv_req->end_trb; | ||
| 467 | ), | ||
| 468 | TP_printk("Req: %p %s, DMA pos: %d, ep deq: %d, ep enq: %d," | ||
| 469 | " start trb: %d, end trb: %d", | ||
| 470 | __entry->priv_req, | ||
| 471 | __entry->handled ? "handled" : "not handled", | ||
| 472 | __entry->dma_position, __entry->dequeue_idx, | ||
| 473 | __entry->enqueue_idx, __entry->start_trb, | ||
| 474 | __entry->end_trb | ||
| 475 | ) | ||
| 476 | ); | ||
| 477 | |||
| 478 | DEFINE_EVENT(cdns3_log_request_handled, cdns3_request_handled, | ||
| 479 | TP_PROTO(struct cdns3_request *priv_req, int current_index, | ||
| 480 | int handled), | ||
| 481 | TP_ARGS(priv_req, current_index, handled) | ||
| 482 | ); | ||
| 483 | #endif /* __LINUX_CDNS3_TRACE */ | ||
| 484 | |||
| 485 | /* this part must be outside header guard */ | ||
| 486 | |||
| 487 | #undef TRACE_INCLUDE_PATH | ||
| 488 | #define TRACE_INCLUDE_PATH . | ||
| 489 | |||
| 490 | #undef TRACE_INCLUDE_FILE | ||
| 491 | #define TRACE_INCLUDE_FILE trace | ||
| 492 | |||
| 493 | #include <trace/define_trace.h> | ||
| @@ -6,6 +6,7 @@ config USB_CHIPIDEA · 5 unmodified lines | |||
| 6 | select EXTCON | 6 | select EXTCON |
| 7 | select RESET_CONTROLLER | 7 | select RESET_CONTROLLER |
| 8 | select USB_ULPI_BUS | 8 | select USB_ULPI_BUS |
| 9 | select USB_ROLE_SWITCH | ||
| 9 | help | 10 | help |
| 10 | Say Y here if your system has a dual role high speed USB | 11 | Say Y here if your system has a dual role high speed USB |
| 11 | controller based on ChipIdea silicon IP. It supports: | 12 | controller based on ChipIdea silicon IP. It supports: |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <linux/usb/gadget.h> | 16 | #include <linux/usb/gadget.h> |
| 17 | #include <linux/usb/otg-fsm.h> | 17 | #include <linux/usb/otg-fsm.h> |
| 18 | #include <linux/usb/otg.h> | 18 | #include <linux/usb/otg.h> |
| 19 | #include <linux/usb/role.h> | ||
| 19 | #include <linux/ulpi/interface.h> | 20 | #include <linux/ulpi/interface.h> |
| 20 | 21 | ||
| 21 | /****************************************************************************** | 22 | /****************************************************************************** |
| @@ -217,6 +218,7 @@ struct ci_hdrc { · 195 unmodified lines | |||
| 217 | ktime_t hr_timeouts[NUM_OTG_FSM_TIMERS]; | 218 | ktime_t hr_timeouts[NUM_OTG_FSM_TIMERS]; |
| 218 | unsigned enabled_otg_timer_bits; | 219 | unsigned enabled_otg_timer_bits; |
| 219 | enum otg_fsm_timer next_otg_timer; | 220 | enum otg_fsm_timer next_otg_timer; |
| 221 | struct usb_role_switch *role_switch; | ||
| 220 | struct work_struct work; | 222 | struct work_struct work; |
| 221 | struct workqueue_struct *wq; | 223 | struct workqueue_struct *wq; |
| 222 | 224 | ||
| @@ -290,6 +292,16 @@ static inline void ci_role_stop(struct ci_hdrc *ci) · 67 unmodified lines | |||
| 290 | ci->roles[role]->stop(ci); | 292 | ci->roles[role]->stop(ci); |
| 291 | } | 293 | } |
| 292 | 294 | ||
| 295 | static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci) | ||
| 296 | { | ||
| 297 | if (ci->role == CI_ROLE_HOST) | ||
| 298 | return USB_ROLE_HOST; | ||
| 299 | else if (ci->role == CI_ROLE_GADGET && ci->vbus_active) | ||
| 300 | return USB_ROLE_DEVICE; | ||
| 301 | else | ||
| 302 | return USB_ROLE_NONE; | ||
| 303 | } | ||
| 304 | |||
| 293 | /** | 305 | /** |
| 294 | * hw_read_id_reg: reads from a identification register | 306 | * hw_read_id_reg: reads from a identification register |
| 295 | * @ci: the controller | 307 | * @ci: the controller |
| @@ -216,13 +216,13 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) · 215 unmodified lines | |||
| 216 | ci->rcdev.ops = &ci_hdrc_msm_reset_ops; | 216 | ci->rcdev.ops = &ci_hdrc_msm_reset_ops; |
| 217 | ci->rcdev.of_node = pdev->dev.of_node; | 217 | ci->rcdev.of_node = pdev->dev.of_node; |
| 218 | ci->rcdev.nr_resets = 2; | 218 | ci->rcdev.nr_resets = 2; |
| 219 | ret = reset_controller_register(&ci->rcdev); | 219 | ret = devm_reset_controller_register(&pdev->dev, &ci->rcdev); |
| 220 | if (ret) | 220 | if (ret) |
| 221 | return ret; | 221 | return ret; |
| 222 | 222 | ||
| 223 | ret = clk_prepare_enable(ci->fs_clk); | 223 | ret = clk_prepare_enable(ci->fs_clk); |
| 224 | if (ret) | 224 | if (ret) |
| 225 | goto err_fs; | 225 | return ret; |
| 226 | 226 | ||
| 227 | reset_control_assert(reset); | 227 | reset_control_assert(reset); |
| 228 | usleep_range(10000, 12000); | 228 | usleep_range(10000, 12000); |
| @@ -232,7 +232,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 232 | 232 | ||
| 233 | ret = clk_prepare_enable(ci->core_clk); | 233 | ret = clk_prepare_enable(ci->core_clk); |
| 234 | if (ret) | 234 | if (ret) |
| 235 | goto err_fs; | 235 | return ret; |
| 236 | 236 | ||
| 237 | ret = clk_prepare_enable(ci->iface_clk); | 237 | ret = clk_prepare_enable(ci->iface_clk); |
| 238 | if (ret) | 238 | if (ret) |
| @@ -271,8 +271,6 @@ err_mux: · 32 unmodified lines | |||
| 271 | clk_disable_unprepare(ci->iface_clk); | 271 | clk_disable_unprepare(ci->iface_clk); |
| 272 | err_iface: | 272 | err_iface: |
| 273 | clk_disable_unprepare(ci->core_clk); | 273 | clk_disable_unprepare(ci->core_clk); |
| 274 | err_fs: | ||
| 275 | reset_controller_unregister(&ci->rcdev); | ||
| 276 | return ret; | 274 | return ret; |
| 277 | } | 275 | } |
| 278 | 276 | ||
| @@ -284,7 +282,6 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev) · 5 unmodified lines | |||
| 284 | ci_hdrc_remove_device(ci->ci); | 282 | ci_hdrc_remove_device(ci->ci); |
| 285 | clk_disable_unprepare(ci->iface_clk); | 283 | clk_disable_unprepare(ci->iface_clk); |
| 286 | clk_disable_unprepare(ci->core_clk); | 284 | clk_disable_unprepare(ci->core_clk); |
| 287 | reset_controller_unregister(&ci->rcdev); | ||
| 288 | 285 | ||
| 289 | return 0; | 286 | return 0; |
| 290 | } | 287 | } |
| @@ -600,6 +600,71 @@ static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, · 599 unmodified lines | |||
| 600 | return NOTIFY_DONE; | 600 | return NOTIFY_DONE; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | static enum usb_role ci_usb_role_switch_get(struct device *dev) | ||
| 604 | { | ||
| 605 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
| 606 | enum usb_role role; | ||
| 607 | unsigned long flags; | ||
| 608 | |||
| 609 | spin_lock_irqsave(&ci->lock, flags); | ||
| 610 | role = ci_role_to_usb_role(ci); | ||
| 611 | spin_unlock_irqrestore(&ci->lock, flags); | ||
| 612 | |||
| 613 | return role; | ||
| 614 | } | ||
| 615 | |||
| 616 | static int ci_usb_role_switch_set(struct device *dev, enum usb_role role) | ||
| 617 | { | ||
| 618 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
| 619 | struct ci_hdrc_cable *cable = NULL; | ||
| 620 | enum usb_role current_role = ci_role_to_usb_role(ci); | ||
| 621 | unsigned long flags; | ||
| 622 | |||
| 623 | if (current_role == role) | ||
| 624 | return 0; | ||
| 625 | |||
| 626 | pm_runtime_get_sync(ci->dev); | ||
| 627 | /* Stop current role */ | ||
| 628 | spin_lock_irqsave(&ci->lock, flags); | ||
| 629 | if (current_role == USB_ROLE_DEVICE) | ||
| 630 | cable = &ci->platdata->vbus_extcon; | ||
| 631 | else if (current_role == USB_ROLE_HOST) | ||
| 632 | cable = &ci->platdata->id_extcon; | ||
| 633 | |||
| 634 | if (cable) { | ||
| 635 | cable->changed = true; | ||
| 636 | cable->connected = false; | ||
| 637 | ci_irq(ci->irq, ci); | ||
| 638 | spin_unlock_irqrestore(&ci->lock, flags); | ||
| 639 | if (ci->wq && role != USB_ROLE_NONE) | ||
| 640 | flush_workqueue(ci->wq); | ||
| 641 | spin_lock_irqsave(&ci->lock, flags); | ||
| 642 | } | ||
| 643 | |||
| 644 | cable = NULL; | ||
| 645 | |||
| 646 | /* Start target role */ | ||
| 647 | if (role == USB_ROLE_DEVICE) | ||
| 648 | cable = &ci->platdata->vbus_extcon; | ||
| 649 | else if (role == USB_ROLE_HOST) | ||
| 650 | cable = &ci->platdata->id_extcon; | ||
| 651 | |||
| 652 | if (cable) { | ||
| 653 | cable->changed = true; | ||
| 654 | cable->connected = true; | ||
| 655 | ci_irq(ci->irq, ci); | ||
| 656 | } | ||
| 657 | spin_unlock_irqrestore(&ci->lock, flags); | ||
| 658 | pm_runtime_put_sync(ci->dev); | ||
| 659 | |||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 663 | static struct usb_role_switch_desc ci_role_switch = { | ||
| 664 | .set = ci_usb_role_switch_set, | ||
| 665 | .get = ci_usb_role_switch_get, | ||
| 666 | }; | ||
| 667 | |||
| 603 | static int ci_get_platdata(struct device *dev, | 668 | static int ci_get_platdata(struct device *dev, |
| 604 | struct ci_hdrc_platform_data *platdata) | 669 | struct ci_hdrc_platform_data *platdata) |
| 605 | { | 670 | { |
| @@ -726,6 +791,9 @@ static int ci_get_platdata(struct device *dev, · 120 unmodified lines | |||
| 726 | cable->connected = false; | 791 | cable->connected = false; |
| 727 | } | 792 | } |
| 728 | 793 | ||
| 794 | if (device_property_read_bool(dev, "usb-role-switch")) | ||
| 795 | ci_role_switch.fwnode = dev->fwnode; | ||
| 796 | |||
| 729 | platdata->pctl = devm_pinctrl_get(dev); | 797 | platdata->pctl = devm_pinctrl_get(dev); |
| 730 | if (!IS_ERR(platdata->pctl)) { | 798 | if (!IS_ERR(platdata->pctl)) { |
| 731 | struct pinctrl_state *p; | 799 | struct pinctrl_state *p; |
| @@ -903,10 +971,7 @@ static struct attribute *ci_attrs[] = { · 171 unmodified lines | |||
| 903 | &dev_attr_role.attr, | 971 | &dev_attr_role.attr, |
| 904 | NULL, | 972 | NULL, |
| 905 | }; | 973 | }; |
| 906 | 974 | ATTRIBUTE_GROUPS(ci); | |
| 907 | static const struct attribute_group ci_attr_group = { | ||
| 908 | .attrs = ci_attrs, | ||
| 909 | }; | ||
| 910 | 975 | ||
| 911 | static int ci_hdrc_probe(struct platform_device *pdev) | 976 | static int ci_hdrc_probe(struct platform_device *pdev) |
| 912 | { | 977 | { |
| @@ -1008,7 +1073,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) · 95 unmodified lines | |||
| 1008 | 1073 | ||
| 1009 | ci->irq = platform_get_irq(pdev, 0); | 1074 | ci->irq = platform_get_irq(pdev, 0); |
| 1010 | if (ci->irq < 0) { | 1075 | if (ci->irq < 0) { |
| 1011 | dev_err(dev, "missing IRQ\n"); | ||
| 1012 | ret = ci->irq; | 1076 | ret = ci->irq; |
| 1013 | goto deinit_phy; | 1077 | goto deinit_phy; |
| 1014 | } | 1078 | } |
| @@ -1051,6 +1115,15 @@ static int ci_hdrc_probe(struct platform_device *pdev) · 36 unmodified lines | |||
| 1051 | } | 1115 | } |
| 1052 | } | 1116 | } |
| 1053 | 1117 | ||
| 1118 | if (ci_role_switch.fwnode) { | ||
| 1119 | ci->role_switch = usb_role_switch_register(dev, | ||
| 1120 | &ci_role_switch); | ||
| 1121 | if (IS_ERR(ci->role_switch)) { | ||
| 1122 | ret = PTR_ERR(ci->role_switch); | ||
| 1123 | goto deinit_otg; | ||
| 1124 | } | ||
| 1125 | } | ||
| 1126 | |||
| 1054 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { | 1127 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { |
| 1055 | if (ci->is_otg) { | 1128 | if (ci->is_otg) { |
| 1056 | ci->role = ci_otg_role(ci); | 1129 | ci->role = ci_otg_role(ci); |
| @@ -1106,15 +1179,12 @@ static int ci_hdrc_probe(struct platform_device *pdev) · 49 unmodified lines | |||
| 1106 | device_set_wakeup_capable(&pdev->dev, true); | 1179 | device_set_wakeup_capable(&pdev->dev, true); |
| 1107 | dbg_create_files(ci); | 1180 | dbg_create_files(ci); |
| 1108 | 1181 | ||
| 1109 | ret = sysfs_create_group(&dev->kobj, &ci_attr_group); | ||
| 1110 | if (ret) | ||
| 1111 | goto remove_debug; | ||
| 1112 | |||
| 1113 | return 0; | 1182 | return 0; |
| 1114 | 1183 | ||
| 1115 | remove_debug: | ||
| 1116 | dbg_remove_files(ci); | ||
| 1117 | stop: | 1184 | stop: |
| 1185 | if (ci->role_switch) | ||
| 1186 | usb_role_switch_unregister(ci->role_switch); | ||
| 1187 | deinit_otg: | ||
| 1118 | if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) | 1188 | if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) |
| 1119 | ci_hdrc_otg_destroy(ci); | 1189 | ci_hdrc_otg_destroy(ci); |
| 1120 | deinit_gadget: | 1190 | deinit_gadget: |
| @@ -1133,6 +1203,9 @@ static int ci_hdrc_remove(struct platform_device *pdev) · 12 unmodified lines | |||
| 1133 | { | 1203 | { |
| 1134 | struct ci_hdrc *ci = platform_get_drvdata(pdev); | 1204 | struct ci_hdrc *ci = platform_get_drvdata(pdev); |
| 1135 | 1205 | ||
| 1206 | if (ci->role_switch) | ||
| 1207 | usb_role_switch_unregister(ci->role_switch); | ||
| 1208 | |||
| 1136 | if (ci->supports_runtime_pm) { | 1209 | if (ci->supports_runtime_pm) { |
| 1137 | pm_runtime_get_sync(&pdev->dev); | 1210 | pm_runtime_get_sync(&pdev->dev); |
| 1138 | pm_runtime_disable(&pdev->dev); | 1211 | pm_runtime_disable(&pdev->dev); |
| @@ -1140,7 +1213,6 @@ static int ci_hdrc_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 1140 | } | 1213 | } |
| 1141 | 1214 | ||
| 1142 | dbg_remove_files(ci); | 1215 | dbg_remove_files(ci); |
| 1143 | sysfs_remove_group(&ci->dev->kobj, &ci_attr_group); | ||
| 1144 | ci_role_destroy(ci); | 1216 | ci_role_destroy(ci); |
| 1145 | ci_hdrc_enter_lpm(ci, true); | 1217 | ci_hdrc_enter_lpm(ci, true); |
| 1146 | ci_usb_phy_exit(ci); | 1218 | ci_usb_phy_exit(ci); |
| @@ -1319,6 +1391,7 @@ static struct platform_driver ci_hdrc_driver = { · 172 unmodified lines | |||
| 1319 | .driver = { | 1391 | .driver = { |
| 1320 | .name = "ci_hdrc", | 1392 | .name = "ci_hdrc", |
| 1321 | .pm = &ci_pm_ops, | 1393 | .pm = &ci_pm_ops, |
| 1394 | .dev_groups = ci_groups, | ||
| 1322 | }, | 1395 | }, |
| 1323 | }; | 1396 | }; |
| 1324 | 1397 | ||
| @@ -35,7 +35,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) · 34 unmodified lines | |||
| 35 | * detection overwrite OTGSC register value | 35 | * detection overwrite OTGSC register value |
| 36 | */ | 36 | */ |
| 37 | cable = &ci->platdata->vbus_extcon; | 37 | cable = &ci->platdata->vbus_extcon; |
| 38 | if (!IS_ERR(cable->edev)) { | 38 | if (!IS_ERR(cable->edev) || ci->role_switch) { |
| 39 | if (cable->changed) | 39 | if (cable->changed) |
| 40 | val |= OTGSC_BSVIS; | 40 | val |= OTGSC_BSVIS; |
| 41 | else | 41 | else |
| @@ -53,7 +53,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) · 11 unmodified lines | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | cable = &ci->platdata->id_extcon; | 55 | cable = &ci->platdata->id_extcon; |
| 56 | if (!IS_ERR(cable->edev)) { | 56 | if (!IS_ERR(cable->edev) || ci->role_switch) { |
| 57 | if (cable->changed) | 57 | if (cable->changed) |
| 58 | val |= OTGSC_IDIS; | 58 | val |= OTGSC_IDIS; |
| 59 | else | 59 | else |
| @@ -83,7 +83,7 @@ void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data) · 23 unmodified lines | |||
| 83 | struct ci_hdrc_cable *cable; | 83 | struct ci_hdrc_cable *cable; |
| 84 | 84 | ||
| 85 | cable = &ci->platdata->vbus_extcon; | 85 | cable = &ci->platdata->vbus_extcon; |
| 86 | if (!IS_ERR(cable->edev)) { | 86 | if (!IS_ERR(cable->edev) || ci->role_switch) { |
| 87 | if (data & mask & OTGSC_BSVIS) | 87 | if (data & mask & OTGSC_BSVIS) |
| 88 | cable->changed = false; | 88 | cable->changed = false; |
| 89 | 89 | ||
| @@ -97,7 +97,7 @@ void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data) · 7 unmodified lines | |||
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | cable = &ci->platdata->id_extcon; | 99 | cable = &ci->platdata->id_extcon; |
| 100 | if (!IS_ERR(cable->edev)) { | 100 | if (!IS_ERR(cable->edev) || ci->role_switch) { |
| 101 | if (data & mask & OTGSC_IDIS) | 101 | if (data & mask & OTGSC_IDIS) |
| 102 | cable->changed = false; | 102 | cable->changed = false; |
| 103 | 103 | ||
| @@ -1762,12 +1762,11 @@ static int ci_udc_start(struct usb_gadget *gadget, · 1761 unmodified lines | |||
| 1762 | struct usb_gadget_driver *driver) | 1762 | struct usb_gadget_driver *driver) |
| 1763 | { | 1763 | { |
| 1764 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); | 1764 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
| 1765 | int retval = -ENOMEM; | 1765 | int retval; |
| 1766 | 1766 | ||
| 1767 | if (driver->disconnect == NULL) | 1767 | if (driver->disconnect == NULL) |
| 1768 | return -EINVAL; | 1768 | return -EINVAL; |
| 1769 | 1769 | ||
| 1770 | |||
| 1771 | ci->ep0out->ep.desc = &ctrl_endpt_out_desc; | 1770 | ci->ep0out->ep.desc = &ctrl_endpt_out_desc; |
| 1772 | retval = usb_ep_enable(&ci->ep0out->ep); | 1771 | retval = usb_ep_enable(&ci->ep0out->ep); |
| 1773 | if (retval) | 1772 | if (retval) |
| @@ -1082,6 +1082,12 @@ static ssize_t ieee1284_id_show(struct device *dev, struct device_attribute *att · 1081 unmodified lines | |||
| 1082 | 1082 | ||
| 1083 | static DEVICE_ATTR_RO(ieee1284_id); | 1083 | static DEVICE_ATTR_RO(ieee1284_id); |
| 1084 | 1084 | ||
| 1085 | static struct attribute *usblp_attrs[] = { | ||
| 1086 | &dev_attr_ieee1284_id.attr, | ||
| 1087 | NULL, | ||
| 1088 | }; | ||
| 1089 | ATTRIBUTE_GROUPS(usblp); | ||
| 1090 | |||
| 1085 | static int usblp_probe(struct usb_interface *intf, | 1091 | static int usblp_probe(struct usb_interface *intf, |
| 1086 | const struct usb_device_id *id) | 1092 | const struct usb_device_id *id) |
| 1087 | { | 1093 | { |
| @@ -1156,9 +1162,6 @@ static int usblp_probe(struct usb_interface *intf, · 68 unmodified lines | |||
| 1156 | 1162 | ||
| 1157 | /* Retrieve and store the device ID string. */ | 1163 | /* Retrieve and store the device ID string. */ |
| 1158 | usblp_cache_device_id_string(usblp); | 1164 | usblp_cache_device_id_string(usblp); |
| 1159 | retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id); | ||
| 1160 | if (retval) | ||
| 1161 | goto abort_intfdata; | ||
| 1162 | 1165 | ||
| 1163 | #ifdef DEBUG | 1166 | #ifdef DEBUG |
| 1164 | usblp_check_status(usblp, 0); | 1167 | usblp_check_status(usblp, 0); |
| @@ -1189,7 +1192,6 @@ static int usblp_probe(struct usb_interface *intf, · 24 unmodified lines | |||
| 1189 | 1192 | ||
| 1190 | abort_intfdata: | 1193 | abort_intfdata: |
| 1191 | usb_set_intfdata(intf, NULL); | 1194 | usb_set_intfdata(intf, NULL); |
| 1192 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | ||
| 1193 | abort: | 1195 | abort: |
| 1194 | kfree(usblp->readbuf); | 1196 | kfree(usblp->readbuf); |
| 1195 | kfree(usblp->statusbuf); | 1197 | kfree(usblp->statusbuf); |
| @@ -1360,8 +1362,6 @@ static void usblp_disconnect(struct usb_interface *intf) · 164 unmodified lines | |||
| 1360 | BUG(); | 1362 | BUG(); |
| 1361 | } | 1363 | } |
| 1362 | 1364 | ||
| 1363 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | ||
| 1364 | |||
| 1365 | mutex_lock(&usblp_mutex); | 1365 | mutex_lock(&usblp_mutex); |
| 1366 | mutex_lock(&usblp->mut); | 1366 | mutex_lock(&usblp->mut); |
| 1367 | usblp->present = 0; | 1367 | usblp->present = 0; |
| @@ -1421,6 +1421,7 @@ static struct usb_driver usblp_driver = { · 53 unmodified lines | |||
| 1421 | .suspend = usblp_suspend, | 1421 | .suspend = usblp_suspend, |
| 1422 | .resume = usblp_resume, | 1422 | .resume = usblp_resume, |
| 1423 | .id_table = usblp_ids, | 1423 | .id_table = usblp_ids, |
| 1424 | .dev_groups = usblp_groups, | ||
| 1424 | .supports_autosuspend = 1, | 1425 | .supports_autosuspend = 1, |
| 1425 | }; | 1426 | }; |
| 1426 | 1427 | ||
| @@ -1836,17 +1836,14 @@ capability_attribute(device_capabilities); · 1835 unmodified lines | |||
| 1836 | capability_attribute(usb488_interface_capabilities); | 1836 | capability_attribute(usb488_interface_capabilities); |
| 1837 | capability_attribute(usb488_device_capabilities); | 1837 | capability_attribute(usb488_device_capabilities); |
| 1838 | 1838 | ||
| 1839 | static struct attribute *capability_attrs[] = { | 1839 | static struct attribute *usbtmc_attrs[] = { |
| 1840 | &dev_attr_interface_capabilities.attr, | 1840 | &dev_attr_interface_capabilities.attr, |
| 1841 | &dev_attr_device_capabilities.attr, | 1841 | &dev_attr_device_capabilities.attr, |
| 1842 | &dev_attr_usb488_interface_capabilities.attr, | 1842 | &dev_attr_usb488_interface_capabilities.attr, |
| 1843 | &dev_attr_usb488_device_capabilities.attr, | 1843 | &dev_attr_usb488_device_capabilities.attr, |
| 1844 | NULL, | 1844 | NULL, |
| 1845 | }; | 1845 | }; |
| 1846 | 1846 | ATTRIBUTE_GROUPS(usbtmc); | |
| 1847 | static const struct attribute_group capability_attr_grp = { | ||
| 1848 | .attrs = capability_attrs, | ||
| 1849 | }; | ||
| 1850 | 1847 | ||
| 1851 | static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) | 1848 | static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) |
| 1852 | { | 1849 | { |
| @@ -2386,9 +2383,6 @@ static int usbtmc_probe(struct usb_interface *intf, · 533 unmodified lines | |||
| 2386 | retcode = get_capabilities(data); | 2383 | retcode = get_capabilities(data); |
| 2387 | if (retcode) | 2384 | if (retcode) |
| 2388 | dev_err(&intf->dev, "can't read capabilities\n"); | 2385 | dev_err(&intf->dev, "can't read capabilities\n"); |
| 2389 | else | ||
| 2390 | retcode = sysfs_create_group(&intf->dev.kobj, | ||
| 2391 | &capability_attr_grp); | ||
| 2392 | 2386 | ||
| 2393 | if (data->iin_ep_present) { | 2387 | if (data->iin_ep_present) { |
| 2394 | /* allocate int urb */ | 2388 | /* allocate int urb */ |
| @@ -2435,7 +2429,6 @@ static int usbtmc_probe(struct usb_interface *intf, · 40 unmodified lines | |||
| 2435 | return 0; | 2429 | return 0; |
| 2436 | 2430 | ||
| 2437 | error_register: | 2431 | error_register: |
| 2438 | sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); | ||
| 2439 | usbtmc_free_int(data); | 2432 | usbtmc_free_int(data); |
| 2440 | err_put: | 2433 | err_put: |
| 2441 | kref_put(&data->kref, usbtmc_delete); | 2434 | kref_put(&data->kref, usbtmc_delete); |
| @@ -2448,7 +2441,6 @@ static void usbtmc_disconnect(struct usb_interface *intf) · 6 unmodified lines | |||
| 2448 | struct list_head *elem; | 2441 | struct list_head *elem; |
| 2449 | 2442 | ||
| 2450 | usb_deregister_dev(intf, &usbtmc_class); | 2443 | usb_deregister_dev(intf, &usbtmc_class); |
| 2451 | sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); | ||
| 2452 | mutex_lock(&data->io_mutex); | 2444 | mutex_lock(&data->io_mutex); |
| 2453 | data->zombie = 1; | 2445 | data->zombie = 1; |
| 2454 | wake_up_interruptible_all(&data->waitq); | 2446 | wake_up_interruptible_all(&data->waitq); |
| @@ -2554,6 +2546,7 @@ static struct usb_driver usbtmc_driver = { · 99 unmodified lines | |||
| 2554 | .resume = usbtmc_resume, | 2546 | .resume = usbtmc_resume, |
| 2555 | .pre_reset = usbtmc_pre_reset, | 2547 | .pre_reset = usbtmc_pre_reset, |
| 2556 | .post_reset = usbtmc_post_reset, | 2548 | .post_reset = usbtmc_post_reset, |
| 2549 | .dev_groups = usbtmc_groups, | ||
| 2557 | }; | 2550 | }; |
| 2558 | 2551 | ||
| 2559 | module_usb_driver(usbtmc_driver); | 2552 | module_usb_driver(usbtmc_driver); |
| @@ -0,0 +1,51 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | config USB_COMMON | ||
| 4 | tristate | ||
| 5 | |||
| 6 | |||
| 7 | config USB_LED_TRIG | ||
| 8 | bool "USB LED Triggers" | ||
| 9 | depends on LEDS_CLASS && LEDS_TRIGGERS | ||
| 10 | select USB_COMMON | ||
| 11 | help | ||
| 12 | This option adds LED triggers for USB host and/or gadget activity. | ||
| 13 | |||
| 14 | Say Y here if you are working on a system with led-class supported | ||
| 15 | LEDs and you want to use them as activity indicators for USB host or | ||
| 16 | gadget. | ||
| 17 | |||
| 18 | config USB_ULPI_BUS | ||
| 19 | tristate "USB ULPI PHY interface support" | ||
| 20 | select USB_COMMON | ||
| 21 | help | ||
| 22 | UTMI+ Low Pin Interface (ULPI) is specification for a commonly used | ||
| 23 | USB 2.0 PHY interface. The ULPI specification defines a standard set | ||
| 24 | of registers that can be used to detect the vendor and product which | ||
| 25 | allows ULPI to be handled as a bus. This module is the driver for that | ||
| 26 | bus. | ||
| 27 | |||
| 28 | The ULPI interfaces (the buses) are registered by the drivers for USB | ||
| 29 | controllers which support ULPI register access and have ULPI PHY | ||
| 30 | attached to them. The ULPI PHY drivers themselves are normal PHY | ||
| 31 | drivers. | ||
| 32 | |||
| 33 | ULPI PHYs provide often functions such as ADP sensing/probing (OTG | ||
| 34 | protocol) and USB charger detection. | ||
| 35 | |||
| 36 | To compile this driver as a module, choose M here: the module will | ||
| 37 | be called ulpi. | ||
| 38 | |||
| 39 | config USB_CONN_GPIO | ||
| 40 | tristate "USB GPIO Based Connection Detection Driver" | ||
| 41 | depends on GPIOLIB | ||
| 42 | select USB_ROLE_SWITCH | ||
| 43 | help | ||
| 44 | The driver supports USB role switch between host and device via GPIO | ||
| 45 | based USB cable detection, used typically if an input GPIO is used | ||
| 46 | to detect USB ID pin, and another input GPIO may be also used to detect | ||
| 47 | Vbus pin at the same time, it also can be used to enable/disable | ||
| 48 | device if an input GPIO is only used to detect Vbus pin. | ||
| 49 | |||
| 50 | To compile the driver as a module, choose M here: the module will | ||
| 51 | be called usb-conn-gpio.ko | ||
| @@ -5,7 +5,9 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | obj-$(CONFIG_USB_COMMON) += usb-common.o | 6 | obj-$(CONFIG_USB_COMMON) += usb-common.o |
| 7 | usb-common-y += common.o | 7 | usb-common-y += common.o |
| 8 | usb-common-$(CONFIG_TRACING) += debug.o | ||
| 8 | usb-common-$(CONFIG_USB_LED_TRIG) += led.o | 9 | usb-common-$(CONFIG_USB_LED_TRIG) += led.o |
| 9 | 10 | ||
| 11 | obj-$(CONFIG_USB_CONN_GPIO) += usb-conn-gpio.o | ||
| 10 | obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o | 12 | obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o |
| 11 | obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o | 13 | obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o |
| @@ -0,0 +1,268 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /** | ||
| 3 | * Common USB debugging functions | ||
| 4 | * | ||
| 5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | ||
| 6 | * | ||
| 7 | * Authors: Felipe Balbi <balbi@ti.com>, | ||
| 8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/usb/ch9.h> | ||
| 12 | |||
| 13 | static void usb_decode_get_status(__u8 bRequestType, __u16 wIndex, | ||
| 14 | __u16 wLength, char *str, size_t size) | ||
| 15 | { | ||
| 16 | switch (bRequestType & USB_RECIP_MASK) { | ||
| 17 | case USB_RECIP_DEVICE: | ||
| 18 | snprintf(str, size, "Get Device Status(Length = %d)", wLength); | ||
| 19 | break; | ||
| 20 | case USB_RECIP_INTERFACE: | ||
| 21 | snprintf(str, size, | ||
| 22 | "Get Interface Status(Intf = %d, Length = %d)", | ||
| 23 | wIndex, wLength); | ||
| 24 | break; | ||
| 25 | case USB_RECIP_ENDPOINT: | ||
| 26 | snprintf(str, size, "Get Endpoint Status(ep%d%s)", | ||
| 27 | wIndex & ~USB_DIR_IN, | ||
| 28 | wIndex & USB_DIR_IN ? "in" : "out"); | ||
| 29 | break; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | static const char *usb_decode_device_feature(u16 wValue) | ||
| 34 | { | ||
| 35 | switch (wValue) { | ||
| 36 | case USB_DEVICE_SELF_POWERED: | ||
| 37 | return "Self Powered"; | ||
| 38 | case USB_DEVICE_REMOTE_WAKEUP: | ||
| 39 | return "Remote Wakeup"; | ||
| 40 | case USB_DEVICE_TEST_MODE: | ||
| 41 | return "Test Mode"; | ||
| 42 | case USB_DEVICE_U1_ENABLE: | ||
| 43 | return "U1 Enable"; | ||
| 44 | case USB_DEVICE_U2_ENABLE: | ||
| 45 | return "U2 Enable"; | ||
| 46 | case USB_DEVICE_LTM_ENABLE: | ||
| 47 | return "LTM Enable"; | ||
| 48 | default: | ||
| 49 | return "UNKNOWN"; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | static const char *usb_decode_test_mode(u16 wIndex) | ||
| 54 | { | ||
| 55 | switch (wIndex) { | ||
| 56 | case TEST_J: | ||
| 57 | return ": TEST_J"; | ||
| 58 | case TEST_K: | ||
| 59 | return ": TEST_K"; | ||
| 60 | case TEST_SE0_NAK: | ||
| 61 | return ": TEST_SE0_NAK"; | ||
| 62 | case TEST_PACKET: | ||
| 63 | return ": TEST_PACKET"; | ||
| 64 | case TEST_FORCE_EN: | ||
| 65 | return ": TEST_FORCE_EN"; | ||
| 66 | default: | ||
| 67 | return ": UNKNOWN"; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | static void usb_decode_set_clear_feature(__u8 bRequestType, | ||
| 72 | __u8 bRequest, __u16 wValue, | ||
| 73 | __u16 wIndex, char *str, size_t size) | ||
| 74 | { | ||
| 75 | switch (bRequestType & USB_RECIP_MASK) { | ||
| 76 | case USB_RECIP_DEVICE: | ||
| 77 | snprintf(str, size, "%s Device Feature(%s%s)", | ||
| 78 | bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 79 | usb_decode_device_feature(wValue), | ||
| 80 | wValue == USB_DEVICE_TEST_MODE ? | ||
| 81 | usb_decode_test_mode(wIndex) : ""); | ||
| 82 | break; | ||
| 83 | case USB_RECIP_INTERFACE: | ||
| 84 | snprintf(str, size, "%s Interface Feature(%s)", | ||
| 85 | bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 86 | wValue == USB_INTRF_FUNC_SUSPEND ? | ||
| 87 | "Function Suspend" : "UNKNOWN"); | ||
| 88 | break; | ||
| 89 | case USB_RECIP_ENDPOINT: | ||
| 90 | snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)", | ||
| 91 | bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 92 | wValue == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", | ||
| 93 | wIndex & ~USB_DIR_IN, | ||
| 94 | wIndex & USB_DIR_IN ? "in" : "out"); | ||
| 95 | break; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | static void usb_decode_set_address(__u16 wValue, char *str, size_t size) | ||
| 100 | { | ||
| 101 | snprintf(str, size, "Set Address(Addr = %02x)", wValue); | ||
| 102 | } | ||
| 103 | |||
| 104 | static void usb_decode_get_set_descriptor(__u8 bRequestType, __u8 bRequest, | ||
| 105 | __u16 wValue, __u16 wIndex, | ||
| 106 | __u16 wLength, char *str, size_t size) | ||
| 107 | { | ||
| 108 | char *s; | ||
| 109 | |||
| 110 | switch (wValue >> 8) { | ||
| 111 | case USB_DT_DEVICE: | ||
| 112 | s = "Device"; | ||
| 113 | break; | ||
| 114 | case USB_DT_CONFIG: | ||
| 115 | s = "Configuration"; | ||
| 116 | break; | ||
| 117 | case USB_DT_STRING: | ||
| 118 | s = "String"; | ||
| 119 | break; | ||
| 120 | case USB_DT_INTERFACE: | ||
| 121 | s = "Interface"; | ||
| 122 | break; | ||
| 123 | case USB_DT_ENDPOINT: | ||
| 124 | s = "Endpoint"; | ||
| 125 | break; | ||
| 126 | case USB_DT_DEVICE_QUALIFIER: | ||
| 127 | s = "Device Qualifier"; | ||
| 128 | break; | ||
| 129 | case USB_DT_OTHER_SPEED_CONFIG: | ||
| 130 | s = "Other Speed Config"; | ||
| 131 | break; | ||
| 132 | case USB_DT_INTERFACE_POWER: | ||
| 133 | s = "Interface Power"; | ||
| 134 | break; | ||
| 135 | case USB_DT_OTG: | ||
| 136 | s = "OTG"; | ||
| 137 | break; | ||
| 138 | case USB_DT_DEBUG: | ||
| 139 | s = "Debug"; | ||
| 140 | break; | ||
| 141 | case USB_DT_INTERFACE_ASSOCIATION: | ||
| 142 | s = "Interface Association"; | ||
| 143 | break; | ||
| 144 | case USB_DT_BOS: | ||
| 145 | s = "BOS"; | ||
| 146 | break; | ||
| 147 | case USB_DT_DEVICE_CAPABILITY: | ||
| 148 | s = "Device Capability"; | ||
| 149 | break; | ||
| 150 | case USB_DT_PIPE_USAGE: | ||
| 151 | s = "Pipe Usage"; | ||
| 152 | break; | ||
| 153 | case USB_DT_SS_ENDPOINT_COMP: | ||
| 154 | s = "SS Endpoint Companion"; | ||
| 155 | break; | ||
| 156 | case USB_DT_SSP_ISOC_ENDPOINT_COMP: | ||
| 157 | s = "SSP Isochronous Endpoint Companion"; | ||
| 158 | break; | ||
| 159 | default: | ||
| 160 | s = "UNKNOWN"; | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | |||
| 164 | snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)", | ||
| 165 | bRequest == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", | ||
| 166 | s, wValue & 0xff, wLength); | ||
| 167 | } | ||
| 168 | |||
| 169 | static void usb_decode_get_configuration(__u16 wLength, char *str, size_t size) | ||
| 170 | { | ||
| 171 | snprintf(str, size, "Get Configuration(Length = %d)", wLength); | ||
| 172 | } | ||
| 173 | |||
| 174 | static void usb_decode_set_configuration(__u8 wValue, char *str, size_t size) | ||
| 175 | { | ||
| 176 | snprintf(str, size, "Set Configuration(Config = %d)", wValue); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void usb_decode_get_intf(__u16 wIndex, __u16 wLength, char *str, | ||
| 180 | size_t size) | ||
| 181 | { | ||
| 182 | snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", | ||
| 183 | wIndex, wLength); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void usb_decode_set_intf(__u8 wValue, __u16 wIndex, char *str, | ||
| 187 | size_t size) | ||
| 188 | { | ||
| 189 | snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", | ||
| 190 | wIndex, wValue); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void usb_decode_synch_frame(__u16 wIndex, __u16 wLength, | ||
| 194 | char *str, size_t size) | ||
| 195 | { | ||
| 196 | snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", | ||
| 197 | wIndex, wLength); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void usb_decode_set_sel(__u16 wLength, char *str, size_t size) | ||
| 201 | { | ||
| 202 | snprintf(str, size, "Set SEL(Length = %d)", wLength); | ||
| 203 | } | ||
| 204 | |||
| 205 | static void usb_decode_set_isoch_delay(__u8 wValue, char *str, size_t size) | ||
| 206 | { | ||
| 207 | snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", wValue); | ||
| 208 | } | ||
| 209 | |||
| 210 | /** | ||
| 211 | * usb_decode_ctrl - returns a string representation of ctrl request | ||
| 212 | */ | ||
| 213 | const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, | ||
| 214 | __u8 bRequest, __u16 wValue, __u16 wIndex, | ||
| 215 | __u16 wLength) | ||
| 216 | { | ||
| 217 | switch (bRequest) { | ||
| 218 | case USB_REQ_GET_STATUS: | ||
| 219 | usb_decode_get_status(bRequestType, wIndex, wLength, str, size); | ||
| 220 | break; | ||
| 221 | case USB_REQ_CLEAR_FEATURE: | ||
| 222 | case USB_REQ_SET_FEATURE: | ||
| 223 | usb_decode_set_clear_feature(bRequestType, bRequest, wValue, | ||
| 224 | wIndex, str, size); | ||
| 225 | break; | ||
| 226 | case USB_REQ_SET_ADDRESS: | ||
| 227 | usb_decode_set_address(wValue, str, size); | ||
| 228 | break; | ||
| 229 | case USB_REQ_GET_DESCRIPTOR: | ||
| 230 | case USB_REQ_SET_DESCRIPTOR: | ||
| 231 | usb_decode_get_set_descriptor(bRequestType, bRequest, wValue, | ||
| 232 | wIndex, wLength, str, size); | ||
| 233 | break; | ||
| 234 | case USB_REQ_GET_CONFIGURATION: | ||
| 235 | usb_decode_get_configuration(wLength, str, size); | ||
| 236 | break; | ||
| 237 | case USB_REQ_SET_CONFIGURATION: | ||
| 238 | usb_decode_set_configuration(wValue, str, size); | ||
| 239 | break; | ||
| 240 | case USB_REQ_GET_INTERFACE: | ||
| 241 | usb_decode_get_intf(wIndex, wLength, str, size); | ||
| 242 | break; | ||
| 243 | case USB_REQ_SET_INTERFACE: | ||
| 244 | usb_decode_set_intf(wValue, wIndex, str, size); | ||
| 245 | break; | ||
| 246 | case USB_REQ_SYNCH_FRAME: | ||
| 247 | usb_decode_synch_frame(wIndex, wLength, str, size); | ||
| 248 | break; | ||
| 249 | case USB_REQ_SET_SEL: | ||
| 250 | usb_decode_set_sel(wLength, str, size); | ||
| 251 | break; | ||
| 252 | case USB_REQ_SET_ISOCH_DELAY: | ||
| 253 | usb_decode_set_isoch_delay(wValue, str, size); | ||
| 254 | break; | ||
| 255 | default: | ||
| 256 | snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", | ||
| 257 | bRequestType, bRequest, | ||
| 258 | (u8)(cpu_to_le16(wValue) & 0xff), | ||
| 259 | (u8)(cpu_to_le16(wValue) >> 8), | ||
| 260 | (u8)(cpu_to_le16(wIndex) & 0xff), | ||
| 261 | (u8)(cpu_to_le16(wIndex) >> 8), | ||
| 262 | (u8)(cpu_to_le16(wLength) & 0xff), | ||
| 263 | (u8)(cpu_to_le16(wLength) >> 8)); | ||
| 264 | } | ||
| 265 | |||
| 266 | return str; | ||
| 267 | } | ||
| 268 | EXPORT_SYMBOL_GPL(usb_decode_ctrl); | ||
| @@ -0,0 +1,284 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * USB GPIO Based Connection Detection Driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2019 MediaTek Inc. | ||
| 6 | * | ||
| 7 | * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> | ||
| 8 | * | ||
| 9 | * Some code borrowed from drivers/extcon/extcon-usb-gpio.c | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/gpio/consumer.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/irq.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/pinctrl/consumer.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/regulator/consumer.h> | ||
| 21 | #include <linux/usb/role.h> | ||
| 22 | |||
| 23 | #define USB_GPIO_DEB_MS 20 /* ms */ | ||
| 24 | #define USB_GPIO_DEB_US ((USB_GPIO_DEB_MS) * 1000) /* us */ | ||
| 25 | |||
| 26 | #define USB_CONN_IRQF \ | ||
| 27 | (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) | ||
| 28 | |||
| 29 | struct usb_conn_info { | ||
| 30 | struct device *dev; | ||
| 31 | struct usb_role_switch *role_sw; | ||
| 32 | enum usb_role last_role; | ||
| 33 | struct regulator *vbus; | ||
| 34 | struct delayed_work dw_det; | ||
| 35 | unsigned long debounce_jiffies; | ||
| 36 | |||
| 37 | struct gpio_desc *id_gpiod; | ||
| 38 | struct gpio_desc *vbus_gpiod; | ||
| 39 | int id_irq; | ||
| 40 | int vbus_irq; | ||
| 41 | }; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * "DEVICE" = VBUS and "HOST" = !ID, so we have: | ||
| 45 | * Both "DEVICE" and "HOST" can't be set as active at the same time | ||
| 46 | * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive | ||
| 47 | * even if VBUS is on. | ||
| 48 | * | ||
| 49 | * Role | ID | VBUS | ||
| 50 | * ------------------------------------ | ||
| 51 | * [1] DEVICE | H | H | ||
| 52 | * [2] NONE | H | L | ||
| 53 | * [3] HOST | L | H | ||
| 54 | * [4] HOST | L | L | ||
| 55 | * | ||
| 56 | * In case we have only one of these signals: | ||
| 57 | * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 | ||
| 58 | * - ID only - we want to distinguish between [1] and [4], so VBUS = ID | ||
| 59 | */ | ||
| 60 | static void usb_conn_detect_cable(struct work_struct *work) | ||
| 61 | { | ||
| 62 | struct usb_conn_info *info; | ||
| 63 | enum usb_role role; | ||
| 64 | int id, vbus, ret; | ||
| 65 | |||
| 66 | info = container_of(to_delayed_work(work), | ||
| 67 | struct usb_conn_info, dw_det); | ||
| 68 | |||
| 69 | /* check ID and VBUS */ | ||
| 70 | id = info->id_gpiod ? | ||
| 71 | gpiod_get_value_cansleep(info->id_gpiod) : 1; | ||
| 72 | vbus = info->vbus_gpiod ? | ||
| 73 | gpiod_get_value_cansleep(info->vbus_gpiod) : id; | ||
| 74 | |||
| 75 | if (!id) | ||
| 76 | role = USB_ROLE_HOST; | ||
| 77 | else if (vbus) | ||
| 78 | role = USB_ROLE_DEVICE; | ||
| 79 | else | ||
| 80 | role = USB_ROLE_NONE; | ||
| 81 | |||
| 82 | dev_dbg(info->dev, "role %d/%d, gpios: id %d, vbus %d\n", | ||
| 83 | info->last_role, role, id, vbus); | ||
| 84 | |||
| 85 | if (info->last_role == role) { | ||
| 86 | dev_warn(info->dev, "repeated role: %d\n", role); | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (info->last_role == USB_ROLE_HOST) | ||
| 91 | regulator_disable(info->vbus); | ||
| 92 | |||
| 93 | ret = usb_role_switch_set_role(info->role_sw, role); | ||
| 94 | if (ret) | ||
| 95 | dev_err(info->dev, "failed to set role: %d\n", ret); | ||
| 96 | |||
| 97 | if (role == USB_ROLE_HOST) { | ||
| 98 | ret = regulator_enable(info->vbus); | ||
| 99 | if (ret) | ||
| 100 | dev_err(info->dev, "enable vbus regulator failed\n"); | ||
| 101 | } | ||
| 102 | |||
| 103 | info->last_role = role; | ||
| 104 | |||
| 105 | dev_dbg(info->dev, "vbus regulator is %s\n", | ||
| 106 | regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void usb_conn_queue_dwork(struct usb_conn_info *info, | ||
| 110 | unsigned long delay) | ||
| 111 | { | ||
| 112 | queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay); | ||
| 113 | } | ||
| 114 | |||
| 115 | static irqreturn_t usb_conn_isr(int irq, void *dev_id) | ||
| 116 | { | ||
| 117 | struct usb_conn_info *info = dev_id; | ||
| 118 | |||
| 119 | usb_conn_queue_dwork(info, info->debounce_jiffies); | ||
| 120 | |||
| 121 | return IRQ_HANDLED; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int usb_conn_probe(struct platform_device *pdev) | ||
| 125 | { | ||
| 126 | struct device *dev = &pdev->dev; | ||
| 127 | struct usb_conn_info *info; | ||
| 128 | int ret = 0; | ||
| 129 | |||
| 130 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
| 131 | if (!info) | ||
| 132 | return -ENOMEM; | ||
| 133 | |||
| 134 | info->dev = dev; | ||
| 135 | info->id_gpiod = devm_gpiod_get_optional(dev, "id", GPIOD_IN); | ||
| 136 | if (IS_ERR(info->id_gpiod)) | ||
| 137 | return PTR_ERR(info->id_gpiod); | ||
| 138 | |||
| 139 | info->vbus_gpiod = devm_gpiod_get_optional(dev, "vbus", GPIOD_IN); | ||
| 140 | if (IS_ERR(info->vbus_gpiod)) | ||
| 141 | return PTR_ERR(info->vbus_gpiod); | ||
| 142 | |||
| 143 | if (!info->id_gpiod && !info->vbus_gpiod) { | ||
| 144 | dev_err(dev, "failed to get gpios\n"); | ||
| 145 | return -ENODEV; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (info->id_gpiod) | ||
| 149 | ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US); | ||
| 150 | if (!ret && info->vbus_gpiod) | ||
| 151 | ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US); | ||
| 152 | if (ret < 0) | ||
| 153 | info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS); | ||
| 154 | |||
| 155 | INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable); | ||
| 156 | |||
| 157 | info->vbus = devm_regulator_get(dev, "vbus"); | ||
| 158 | if (IS_ERR(info->vbus)) { | ||
| 159 | dev_err(dev, "failed to get vbus\n"); | ||
| 160 | return PTR_ERR(info->vbus); | ||
| 161 | } | ||
| 162 | |||
| 163 | info->role_sw = usb_role_switch_get(dev); | ||
| 164 | if (IS_ERR(info->role_sw)) { | ||
| 165 | if (PTR_ERR(info->role_sw) != -EPROBE_DEFER) | ||
| 166 | dev_err(dev, "failed to get role switch\n"); | ||
| 167 | |||
| 168 | return PTR_ERR(info->role_sw); | ||
| 169 | } | ||
| 170 | |||
| 171 | if (info->id_gpiod) { | ||
| 172 | info->id_irq = gpiod_to_irq(info->id_gpiod); | ||
| 173 | if (info->id_irq < 0) { | ||
| 174 | dev_err(dev, "failed to get ID IRQ\n"); | ||
| 175 | ret = info->id_irq; | ||
| 176 | goto put_role_sw; | ||
| 177 | } | ||
| 178 | |||
| 179 | ret = devm_request_threaded_irq(dev, info->id_irq, NULL, | ||
| 180 | usb_conn_isr, USB_CONN_IRQF, | ||
| 181 | pdev->name, info); | ||
| 182 | if (ret < 0) { | ||
| 183 | dev_err(dev, "failed to request ID IRQ\n"); | ||
| 184 | goto put_role_sw; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | if (info->vbus_gpiod) { | ||
| 189 | info->vbus_irq = gpiod_to_irq(info->vbus_gpiod); | ||
| 190 | if (info->vbus_irq < 0) { | ||
| 191 | dev_err(dev, "failed to get VBUS IRQ\n"); | ||
| 192 | ret = info->vbus_irq; | ||
| 193 | goto put_role_sw; | ||
| 194 | } | ||
| 195 | |||
| 196 | ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL, | ||
| 197 | usb_conn_isr, USB_CONN_IRQF, | ||
| 198 | pdev->name, info); | ||
| 199 | if (ret < 0) { | ||
| 200 | dev_err(dev, "failed to request VBUS IRQ\n"); | ||
| 201 | goto put_role_sw; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | platform_set_drvdata(pdev, info); | ||
| 206 | |||
| 207 | /* Perform initial detection */ | ||
| 208 | usb_conn_queue_dwork(info, 0); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | |||
| 212 | put_role_sw: | ||
| 213 | usb_role_switch_put(info->role_sw); | ||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int usb_conn_remove(struct platform_device *pdev) | ||
| 218 | { | ||
| 219 | struct usb_conn_info *info = platform_get_drvdata(pdev); | ||
| 220 | |||
| 221 | cancel_delayed_work_sync(&info->dw_det); | ||
| 222 | |||
| 223 | if (info->last_role == USB_ROLE_HOST) | ||
| 224 | regulator_disable(info->vbus); | ||
| 225 | |||
| 226 | usb_role_switch_put(info->role_sw); | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int __maybe_unused usb_conn_suspend(struct device *dev) | ||
| 232 | { | ||
| 233 | struct usb_conn_info *info = dev_get_drvdata(dev); | ||
| 234 | |||
| 235 | if (info->id_gpiod) | ||
| 236 | disable_irq(info->id_irq); | ||
| 237 | if (info->vbus_gpiod) | ||
| 238 | disable_irq(info->vbus_irq); | ||
| 239 | |||
| 240 | pinctrl_pm_select_sleep_state(dev); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int __maybe_unused usb_conn_resume(struct device *dev) | ||
| 246 | { | ||
| 247 | struct usb_conn_info *info = dev_get_drvdata(dev); | ||
| 248 | |||
| 249 | pinctrl_pm_select_default_state(dev); | ||
| 250 | |||
| 251 | if (info->id_gpiod) | ||
| 252 | enable_irq(info->id_irq); | ||
| 253 | if (info->vbus_gpiod) | ||
| 254 | enable_irq(info->vbus_irq); | ||
| 255 | |||
| 256 | usb_conn_queue_dwork(info, 0); | ||
| 257 | |||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops, | ||
| 262 | usb_conn_suspend, usb_conn_resume); | ||
| 263 | |||
| 264 | static const struct of_device_id usb_conn_dt_match[] = { | ||
| 265 | { .compatible = "gpio-usb-b-connector", }, | ||
| 266 | { } | ||
| 267 | }; | ||
| 268 | MODULE_DEVICE_TABLE(of, usb_conn_dt_match); | ||
| 269 | |||
| 270 | static struct platform_driver usb_conn_driver = { | ||
| 271 | .probe = usb_conn_probe, | ||
| 272 | .remove = usb_conn_remove, | ||
| 273 | .driver = { | ||
| 274 | .name = "usb-conn-gpio", | ||
| 275 | .pm = &usb_conn_pm_ops, | ||
| 276 | .of_match_table = usb_conn_dt_match, | ||
| 277 | }, | ||
| 278 | }; | ||
| 279 | |||
| 280 | module_platform_driver(usb_conn_driver); | ||
| 281 | |||
| 282 | MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); | ||
| 283 | MODULE_DESCRIPTION("USB GPIO based connection detection driver"); | ||
| 284 | MODULE_LICENSE("GPL v2"); | ||
| @@ -921,7 +921,7 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 920 unmodified lines | |||
| 921 | struct usb_bos_descriptor *bos; | 921 | struct usb_bos_descriptor *bos; |
| 922 | struct usb_dev_cap_header *cap; | 922 | struct usb_dev_cap_header *cap; |
| 923 | struct usb_ssp_cap_descriptor *ssp_cap; | 923 | struct usb_ssp_cap_descriptor *ssp_cap; |
| 924 | unsigned char *buffer; | 924 | unsigned char *buffer, *buffer0; |
| 925 | int length, total_len, num, i, ssac; | 925 | int length, total_len, num, i, ssac; |
| 926 | __u8 cap_type; | 926 | __u8 cap_type; |
| 927 | int ret; | 927 | int ret; |
| @@ -966,10 +966,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 38 unmodified lines | |||
| 966 | ret = -ENOMSG; | 966 | ret = -ENOMSG; |
| 967 | goto err; | 967 | goto err; |
| 968 | } | 968 | } |
| 969 | |||
| 970 | buffer0 = buffer; | ||
| 969 | total_len -= length; | 971 | total_len -= length; |
| 972 | buffer += length; | ||
| 970 | 973 | ||
| 971 | for (i = 0; i < num; i++) { | 974 | for (i = 0; i < num; i++) { |
| 972 | buffer += length; | ||
| 973 | cap = (struct usb_dev_cap_header *)buffer; | 975 | cap = (struct usb_dev_cap_header *)buffer; |
| 974 | 976 | ||
| 975 | if (total_len < sizeof(*cap) || total_len < cap->bLength) { | 977 | if (total_len < sizeof(*cap) || total_len < cap->bLength) { |
| @@ -983,8 +985,6 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 7 unmodified lines | |||
| 983 | break; | 985 | break; |
| 984 | } | 986 | } |
| 985 | 987 | ||
| 986 | total_len -= length; | ||
| 987 | |||
| 988 | if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { | 988 | if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { |
| 989 | dev_warn(ddev, "descriptor type invalid, skip\n"); | 989 | dev_warn(ddev, "descriptor type invalid, skip\n"); |
| 990 | continue; | 990 | continue; |
| @@ -1019,7 +1019,11 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 28 unmodified lines | |||
| 1019 | default: | 1019 | default: |
| 1020 | break; | 1020 | break; |
| 1021 | } | 1021 | } |
| 1022 | |||
| 1023 | total_len -= length; | ||
| 1024 | buffer += length; | ||
| 1022 | } | 1025 | } |
| 1026 | dev->bos->desc->wTotalLength = cpu_to_le16(buffer - buffer0); | ||
| 1023 | 1027 | ||
| 1024 | return 0; | 1028 | return 0; |
| 1025 | 1029 | ||
| @@ -44,10 +44,19 @@ · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | #include "usb.h" | 45 | #include "usb.h" |
| 46 | 46 | ||
| 47 | #ifdef CONFIG_PM | ||
| 48 | #define MAYBE_CAP_SUSPEND USBDEVFS_CAP_SUSPEND | ||
| 49 | #else | ||
| 50 | #define MAYBE_CAP_SUSPEND 0 | ||
| 51 | #endif | ||
| 52 | |||
| 47 | #define USB_MAXBUS 64 | 53 | #define USB_MAXBUS 64 |
| 48 | #define USB_DEVICE_MAX (USB_MAXBUS * 128) | 54 | #define USB_DEVICE_MAX (USB_MAXBUS * 128) |
| 49 | #define USB_SG_SIZE 16384 /* split-size for large txs */ | 55 | #define USB_SG_SIZE 16384 /* split-size for large txs */ |
| 50 | 56 | ||
| 57 | /* Mutual exclusion for ps->list in resume vs. release and remove */ | ||
| 58 | static DEFINE_MUTEX(usbfs_mutex); | ||
| 59 | |||
| 51 | struct usb_dev_state { | 60 | struct usb_dev_state { |
| 52 | struct list_head list; /* state list */ | 61 | struct list_head list; /* state list */ |
| 53 | struct usb_device *dev; | 62 | struct usb_device *dev; |
| @@ -57,14 +66,17 @@ struct usb_dev_state { · 3 unmodified lines | |||
| 57 | struct list_head async_completed; | 66 | struct list_head async_completed; |
| 58 | struct list_head memory_list; | 67 | struct list_head memory_list; |
| 59 | wait_queue_head_t wait; /* wake up if a request completed */ | 68 | wait_queue_head_t wait; /* wake up if a request completed */ |
| 69 | wait_queue_head_t wait_for_resume; /* wake up upon runtime resume */ | ||
| 60 | unsigned int discsignr; | 70 | unsigned int discsignr; |
| 61 | struct pid *disc_pid; | 71 | struct pid *disc_pid; |
| 62 | const struct cred *cred; | 72 | const struct cred *cred; |
| 63 | sigval_t disccontext; | 73 | sigval_t disccontext; |
| 64 | unsigned long ifclaimed; | 74 | unsigned long ifclaimed; |
| 65 | u32 disabled_bulk_eps; | 75 | u32 disabled_bulk_eps; |
| 66 | bool privileges_dropped; | ||
| 67 | unsigned long interface_allowed_mask; | 76 | unsigned long interface_allowed_mask; |
| 77 | int not_yet_resumed; | ||
| 78 | bool suspend_allowed; | ||
| 79 | bool privileges_dropped; | ||
| 68 | }; | 80 | }; |
| 69 | 81 | ||
| 70 | struct usb_memory { | 82 | struct usb_memory { |
| @@ -694,9 +706,7 @@ static void driver_disconnect(struct usb_interface *intf) · 623 unmodified lines | |||
| 694 | destroy_async_on_interface(ps, ifnum); | 706 | destroy_async_on_interface(ps, ifnum); |
| 695 | } | 707 | } |
| 696 | 708 | ||
| 697 | /* The following routines are merely placeholders. There is no way | 709 | /* We don't care about suspend/resume of claimed interfaces */ |
| 698 | * to inform a user task about suspend or resumes. | ||
| 699 | */ | ||
| 700 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) | 710 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) |
| 701 | { | 711 | { |
| 702 | return 0; | 712 | return 0; |
| @@ -707,12 +717,32 @@ static int driver_resume(struct usb_interface *intf) · 4 unmodified lines | |||
| 707 | return 0; | 717 | return 0; |
| 708 | } | 718 | } |
| 709 | 719 | ||
| 720 | /* The following routines apply to the entire device, not interfaces */ | ||
| 721 | void usbfs_notify_suspend(struct usb_device *udev) | ||
| 722 | { | ||
| 723 | /* We don't need to handle this */ | ||
| 724 | } | ||
| 725 | |||
| 726 | void usbfs_notify_resume(struct usb_device *udev) | ||
| 727 | { | ||
| 728 | struct usb_dev_state *ps; | ||
| 729 | |||
| 730 | /* Protect against simultaneous remove or release */ | ||
| 731 | mutex_lock(&usbfs_mutex); | ||
| 732 | list_for_each_entry(ps, &udev->filelist, list) { | ||
| 733 | WRITE_ONCE(ps->not_yet_resumed, 0); | ||
| 734 | wake_up_all(&ps->wait_for_resume); | ||
| 735 | } | ||
| 736 | mutex_unlock(&usbfs_mutex); | ||
| 737 | } | ||
| 738 | |||
| 710 | struct usb_driver usbfs_driver = { | 739 | struct usb_driver usbfs_driver = { |
| 711 | .name = "usbfs", | 740 | .name = "usbfs", |
| 712 | .probe = driver_probe, | 741 | .probe = driver_probe, |
| 713 | .disconnect = driver_disconnect, | 742 | .disconnect = driver_disconnect, |
| 714 | .suspend = driver_suspend, | 743 | .suspend = driver_suspend, |
| 715 | .resume = driver_resume, | 744 | .resume = driver_resume, |
| 745 | .supports_autosuspend = 1, | ||
| 716 | }; | 746 | }; |
| 717 | 747 | ||
| 718 | static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) | 748 | static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) |
| @@ -991,9 +1021,12 @@ static int usbdev_open(struct inode *inode, struct file *file) · 272 unmodified lines | |||
| 991 | INIT_LIST_HEAD(&ps->async_completed); | 1021 | INIT_LIST_HEAD(&ps->async_completed); |
| 992 | INIT_LIST_HEAD(&ps->memory_list); | 1022 | INIT_LIST_HEAD(&ps->memory_list); |
| 993 | init_waitqueue_head(&ps->wait); | 1023 | init_waitqueue_head(&ps->wait); |
| 1024 | init_waitqueue_head(&ps->wait_for_resume); | ||
| 994 | ps->disc_pid = get_pid(task_pid(current)); | 1025 | ps->disc_pid = get_pid(task_pid(current)); |
| 995 | ps->cred = get_current_cred(); | 1026 | ps->cred = get_current_cred(); |
| 996 | smp_wmb(); | 1027 | smp_wmb(); |
| 1028 | |||
| 1029 | /* Can't race with resume; the device is already active */ | ||
| 997 | list_add_tail(&ps->list, &dev->filelist); | 1030 | list_add_tail(&ps->list, &dev->filelist); |
| 998 | file->private_data = ps; | 1031 | file->private_data = ps; |
| 999 | usb_unlock_device(dev); | 1032 | usb_unlock_device(dev); |
| @@ -1019,7 +1052,10 @@ static int usbdev_release(struct inode *inode, struct file *file) · 19 unmodified lines | |||
| 1019 | usb_lock_device(dev); | 1052 | usb_lock_device(dev); |
| 1020 | usb_hub_release_all_ports(dev, ps); | 1053 | usb_hub_release_all_ports(dev, ps); |
| 1021 | 1054 | ||
| 1055 | /* Protect against simultaneous resume */ | ||
| 1056 | mutex_lock(&usbfs_mutex); | ||
| 1022 | list_del_init(&ps->list); | 1057 | list_del_init(&ps->list); |
| 1058 | mutex_unlock(&usbfs_mutex); | ||
| 1023 | 1059 | ||
| 1024 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); | 1060 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
| 1025 | ifnum++) { | 1061 | ifnum++) { |
| @@ -1027,7 +1063,8 @@ static int usbdev_release(struct inode *inode, struct file *file) · 1 unmodified line | |||
| 1027 | releaseintf(ps, ifnum); | 1063 | releaseintf(ps, ifnum); |
| 1028 | } | 1064 | } |
| 1029 | destroy_all_async(ps); | 1065 | destroy_all_async(ps); |
| 1030 | usb_autosuspend_device(dev); | 1066 | if (!ps->suspend_allowed) |
| 1067 | usb_autosuspend_device(dev); | ||
| 1031 | usb_unlock_device(dev); | 1068 | usb_unlock_device(dev); |
| 1032 | usb_put_dev(dev); | 1069 | usb_put_dev(dev); |
| 1033 | put_pid(ps->disc_pid); | 1070 | put_pid(ps->disc_pid); |
| @@ -1621,7 +1658,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb · 587 unmodified lines | |||
| 1621 | if (as->usbm) | 1658 | if (as->usbm) |
| 1622 | num_sgs = 0; | 1659 | num_sgs = 0; |
| 1623 | 1660 | ||
| 1624 | u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + | 1661 | u += sizeof(struct async) + sizeof(struct urb) + |
| 1662 | (as->usbm ? 0 : uurb->buffer_length) + | ||
| 1625 | num_sgs * sizeof(struct scatterlist); | 1663 | num_sgs * sizeof(struct scatterlist); |
| 1626 | ret = usbfs_increase_memory_usage(u); | 1664 | ret = usbfs_increase_memory_usage(u); |
| 1627 | if (ret) | 1665 | if (ret) |
| @@ -2273,7 +2311,8 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) · 645 unmodified lines | |||
| 2273 | 2311 | ||
| 2274 | caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | | 2312 | caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | |
| 2275 | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | | 2313 | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | |
| 2276 | USBDEVFS_CAP_DROP_PRIVILEGES | USBDEVFS_CAP_CONNINFO_EX; | 2314 | USBDEVFS_CAP_DROP_PRIVILEGES | |
| 2315 | USBDEVFS_CAP_CONNINFO_EX | MAYBE_CAP_SUSPEND; | ||
| 2277 | if (!ps->dev->bus->no_stop_on_short) | 2316 | if (!ps->dev->bus->no_stop_on_short) |
| 2278 | caps |= USBDEVFS_CAP_BULK_CONTINUATION; | 2317 | caps |= USBDEVFS_CAP_BULK_CONTINUATION; |
| 2279 | if (ps->dev->bus->sg_tablesize) | 2318 | if (ps->dev->bus->sg_tablesize) |
| @@ -2376,6 +2415,47 @@ static int proc_drop_privileges(struct usb_dev_state *ps, void __user *arg) · 96 unmodified lines | |||
| 2376 | return 0; | 2415 | return 0; |
| 2377 | } | 2416 | } |
| 2378 | 2417 | ||
| 2418 | static int proc_forbid_suspend(struct usb_dev_state *ps) | ||
| 2419 | { | ||
| 2420 | int ret = 0; | ||
| 2421 | |||
| 2422 | if (ps->suspend_allowed) { | ||
| 2423 | ret = usb_autoresume_device(ps->dev); | ||
| 2424 | if (ret == 0) | ||
| 2425 | ps->suspend_allowed = false; | ||
| 2426 | else if (ret != -ENODEV) | ||
| 2427 | ret = -EIO; | ||
| 2428 | } | ||
| 2429 | return ret; | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | static int proc_allow_suspend(struct usb_dev_state *ps) | ||
| 2433 | { | ||
| 2434 | if (!connected(ps)) | ||
| 2435 | return -ENODEV; | ||
| 2436 | |||
| 2437 | WRITE_ONCE(ps->not_yet_resumed, 1); | ||
| 2438 | if (!ps->suspend_allowed) { | ||
| 2439 | usb_autosuspend_device(ps->dev); | ||
| 2440 | ps->suspend_allowed = true; | ||
| 2441 | } | ||
| 2442 | return 0; | ||
| 2443 | } | ||
| 2444 | |||
| 2445 | static int proc_wait_for_resume(struct usb_dev_state *ps) | ||
| 2446 | { | ||
| 2447 | int ret; | ||
| 2448 | |||
| 2449 | usb_unlock_device(ps->dev); | ||
| 2450 | ret = wait_event_interruptible(ps->wait_for_resume, | ||
| 2451 | READ_ONCE(ps->not_yet_resumed) == 0); | ||
| 2452 | usb_lock_device(ps->dev); | ||
| 2453 | |||
| 2454 | if (ret != 0) | ||
| 2455 | return -EINTR; | ||
| 2456 | return proc_forbid_suspend(ps); | ||
| 2457 | } | ||
| 2458 | |||
| 2379 | /* | 2459 | /* |
| 2380 | * NOTE: All requests here that have interface numbers as parameters | 2460 | * NOTE: All requests here that have interface numbers as parameters |
| 2381 | * are assuming that somehow the configuration has been prevented from | 2461 | * are assuming that somehow the configuration has been prevented from |
| @@ -2570,6 +2650,15 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, · 188 unmodified lines | |||
| 2570 | case USBDEVFS_GET_SPEED: | 2650 | case USBDEVFS_GET_SPEED: |
| 2571 | ret = ps->dev->speed; | 2651 | ret = ps->dev->speed; |
| 2572 | break; | 2652 | break; |
| 2653 | case USBDEVFS_FORBID_SUSPEND: | ||
| 2654 | ret = proc_forbid_suspend(ps); | ||
| 2655 | break; | ||
| 2656 | case USBDEVFS_ALLOW_SUSPEND: | ||
| 2657 | ret = proc_allow_suspend(ps); | ||
| 2658 | break; | ||
| 2659 | case USBDEVFS_WAIT_FOR_RESUME: | ||
| 2660 | ret = proc_wait_for_resume(ps); | ||
| 2661 | break; | ||
| 2573 | } | 2662 | } |
| 2574 | 2663 | ||
| 2575 | /* Handle variable-length commands */ | 2664 | /* Handle variable-length commands */ |
| @@ -2643,15 +2732,20 @@ static void usbdev_remove(struct usb_device *udev) · 67 unmodified lines | |||
| 2643 | { | 2732 | { |
| 2644 | struct usb_dev_state *ps; | 2733 | struct usb_dev_state *ps; |
| 2645 | 2734 | ||
| 2735 | /* Protect against simultaneous resume */ | ||
| 2736 | mutex_lock(&usbfs_mutex); | ||
| 2646 | while (!list_empty(&udev->filelist)) { | 2737 | while (!list_empty(&udev->filelist)) { |
| 2647 | ps = list_entry(udev->filelist.next, struct usb_dev_state, list); | 2738 | ps = list_entry(udev->filelist.next, struct usb_dev_state, list); |
| 2648 | destroy_all_async(ps); | 2739 | destroy_all_async(ps); |
| 2649 | wake_up_all(&ps->wait); | 2740 | wake_up_all(&ps->wait); |
| 2741 | WRITE_ONCE(ps->not_yet_resumed, 0); | ||
| 2742 | wake_up_all(&ps->wait_for_resume); | ||
| 2650 | list_del_init(&ps->list); | 2743 | list_del_init(&ps->list); |
| 2651 | if (ps->discsignr) | 2744 | if (ps->discsignr) |
| 2652 | kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext, | 2745 | kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext, |
| 2653 | ps->disc_pid, ps->cred); | 2746 | ps->disc_pid, ps->cred); |
| 2654 | } | 2747 | } |
| 2748 | mutex_unlock(&usbfs_mutex); | ||
| 2655 | } | 2749 | } |
| 2656 | 2750 | ||
| 2657 | static int usbdev_notify(struct notifier_block *self, | 2751 | static int usbdev_notify(struct notifier_block *self, |
| @@ -892,6 +892,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, · 891 unmodified lines | |||
| 892 | new_udriver->drvwrap.driver.probe = usb_probe_device; | 892 | new_udriver->drvwrap.driver.probe = usb_probe_device; |
| 893 | new_udriver->drvwrap.driver.remove = usb_unbind_device; | 893 | new_udriver->drvwrap.driver.remove = usb_unbind_device; |
| 894 | new_udriver->drvwrap.driver.owner = owner; | 894 | new_udriver->drvwrap.driver.owner = owner; |
| 895 | new_udriver->drvwrap.driver.dev_groups = new_udriver->dev_groups; | ||
| 895 | 896 | ||
| 896 | retval = driver_register(&new_udriver->drvwrap.driver); | 897 | retval = driver_register(&new_udriver->drvwrap.driver); |
| 897 | 898 | ||
| @@ -954,6 +955,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, · 56 unmodified lines | |||
| 954 | new_driver->drvwrap.driver.remove = usb_unbind_interface; | 955 | new_driver->drvwrap.driver.remove = usb_unbind_interface; |
| 955 | new_driver->drvwrap.driver.owner = owner; | 956 | new_driver->drvwrap.driver.owner = owner; |
| 956 | new_driver->drvwrap.driver.mod_name = mod_name; | 957 | new_driver->drvwrap.driver.mod_name = mod_name; |
| 958 | new_driver->drvwrap.driver.dev_groups = new_driver->dev_groups; | ||
| 957 | spin_lock_init(&new_driver->dynids.lock); | 959 | spin_lock_init(&new_driver->dynids.lock); |
| 958 | INIT_LIST_HEAD(&new_driver->dynids.list); | 960 | INIT_LIST_HEAD(&new_driver->dynids.list); |
| 959 | 961 | ||
| @@ -257,6 +257,8 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) · 256 unmodified lines | |||
| 257 | else | 257 | else |
| 258 | rc = usb_port_suspend(udev, msg); | 258 | rc = usb_port_suspend(udev, msg); |
| 259 | 259 | ||
| 260 | if (rc == 0) | ||
| 261 | usbfs_notify_suspend(udev); | ||
| 260 | return rc; | 262 | return rc; |
| 261 | } | 263 | } |
| 262 | 264 | ||
| @@ -273,6 +275,9 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg) · 10 unmodified lines | |||
| 273 | rc = hcd_bus_resume(udev, msg); | 275 | rc = hcd_bus_resume(udev, msg); |
| 274 | else | 276 | else |
| 275 | rc = usb_port_resume(udev, msg); | 277 | rc = usb_port_resume(udev, msg); |
| 278 | |||
| 279 | if (rc == 0) | ||
| 280 | usbfs_notify_resume(udev); | ||
| 276 | return rc; | 281 | return rc; |
| 277 | } | 282 | } |
| 278 | 283 | ||
| @@ -393,8 +393,7 @@ static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable) · 392 unmodified lines | |||
| 393 | 393 | ||
| 394 | static int check_root_hub_suspended(struct device *dev) | 394 | static int check_root_hub_suspended(struct device *dev) |
| 395 | { | 395 | { |
| 396 | struct pci_dev *pci_dev = to_pci_dev(dev); | 396 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 397 | struct usb_hcd *hcd = pci_get_drvdata(pci_dev); | ||
| 398 | 397 | ||
| 399 | if (HCD_RH_RUNNING(hcd)) { | 398 | if (HCD_RH_RUNNING(hcd)) { |
| 400 | dev_warn(dev, "Root hub is not suspended\n"); | 399 | dev_warn(dev, "Root hub is not suspended\n"); |
| @@ -1249,9 +1249,6 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); · 1248 unmodified lines | |||
| 1249 | * To support host controllers with limited dma capabilities we provide dma | 1249 | * To support host controllers with limited dma capabilities we provide dma |
| 1250 | * bounce buffers. This feature can be enabled by initializing | 1250 | * bounce buffers. This feature can be enabled by initializing |
| 1251 | * hcd->localmem_pool using usb_hcd_setup_local_mem(). | 1251 | * hcd->localmem_pool using usb_hcd_setup_local_mem(). |
| 1252 | * For this to work properly the host controller code must first use the | ||
| 1253 | * function dma_declare_coherent_memory() to point out which memory area | ||
| 1254 | * that should be used for dma allocations. | ||
| 1255 | * | 1252 | * |
| 1256 | * The initialized hcd->localmem_pool then tells the usb code to allocate all | 1253 | * The initialized hcd->localmem_pool then tells the usb code to allocate all |
| 1257 | * data for dma using the genalloc API. | 1254 | * data for dma using the genalloc API. |
| @@ -2191,6 +2188,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) · 933 unmodified lines | |||
| 2191 | hcd->state = HC_STATE_RESUMING; | 2188 | hcd->state = HC_STATE_RESUMING; |
| 2192 | status = hcd->driver->bus_resume(hcd); | 2189 | status = hcd->driver->bus_resume(hcd); |
| 2193 | clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); | 2190 | clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); |
| 2191 | if (status == 0) | ||
| 2192 | status = usb_phy_roothub_calibrate(hcd->phy_roothub); | ||
| 2193 | |||
| 2194 | if (status == 0) { | 2194 | if (status == 0) { |
| 2195 | struct usb_device *udev; | 2195 | struct usb_device *udev; |
| 2196 | int port1; | 2196 | int port1; |
| @@ -2454,7 +2454,6 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, · 257 unmodified lines | |||
| 2454 | hcd->self.controller = dev; | 2454 | hcd->self.controller = dev; |
| 2455 | hcd->self.sysdev = sysdev; | 2455 | hcd->self.sysdev = sysdev; |
| 2456 | hcd->self.bus_name = bus_name; | 2456 | hcd->self.bus_name = bus_name; |
| 2457 | hcd->self.uses_dma = (sysdev->dma_mask != NULL); | ||
| 2458 | 2457 | ||
| 2459 | timer_setup(&hcd->rh_timer, rh_timer_func, 0); | 2458 | timer_setup(&hcd->rh_timer, rh_timer_func, 0); |
| 2460 | #ifdef CONFIG_PM | 2459 | #ifdef CONFIG_PM |
| @@ -2764,6 +2763,10 @@ int usb_add_hcd(struct usb_hcd *hcd, · 303 unmodified lines | |||
| 2764 | } | 2763 | } |
| 2765 | hcd->rh_pollable = 1; | 2764 | hcd->rh_pollable = 1; |
| 2766 | 2765 | ||
| 2766 | retval = usb_phy_roothub_calibrate(hcd->phy_roothub); | ||
| 2767 | if (retval) | ||
| 2768 | goto err_hcd_driver_setup; | ||
| 2769 | |||
| 2767 | /* NOTE: root hub and controller capabilities may not be the same */ | 2770 | /* NOTE: root hub and controller capabilities may not be the same */ |
| 2768 | if (device_can_wakeup(hcd->self.controller) | 2771 | if (device_can_wakeup(hcd->self.controller) |
| 2769 | && device_can_wakeup(&hcd->self.root_hub->dev)) | 2772 | && device_can_wakeup(&hcd->self.root_hub->dev)) |
| @@ -151,6 +151,27 @@ err_out: · 150 unmodified lines | |||
| 151 | } | 151 | } |
| 152 | EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode); | 152 | EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode); |
| 153 | 153 | ||
| 154 | int usb_phy_roothub_calibrate(struct usb_phy_roothub *phy_roothub) | ||
| 155 | { | ||
| 156 | struct usb_phy_roothub *roothub_entry; | ||
| 157 | struct list_head *head; | ||
| 158 | int err; | ||
| 159 | |||
| 160 | if (!phy_roothub) | ||
| 161 | return 0; | ||
| 162 | |||
| 163 | head = &phy_roothub->list; | ||
| 164 | |||
| 165 | list_for_each_entry(roothub_entry, head, list) { | ||
| 166 | err = phy_calibrate(roothub_entry->phy); | ||
| 167 | if (err) | ||
| 168 | return err; | ||
| 169 | } | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | EXPORT_SYMBOL_GPL(usb_phy_roothub_calibrate); | ||
| 174 | |||
| 154 | int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub) | 175 | int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub) |
| 155 | { | 176 | { |
| 156 | struct usb_phy_roothub *roothub_entry; | 177 | struct usb_phy_roothub *roothub_entry; |
| @@ -18,6 +18,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub); · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | int usb_phy_roothub_set_mode(struct usb_phy_roothub *phy_roothub, | 19 | int usb_phy_roothub_set_mode(struct usb_phy_roothub *phy_roothub, |
| 20 | enum phy_mode mode); | 20 | enum phy_mode mode); |
| 21 | int usb_phy_roothub_calibrate(struct usb_phy_roothub *phy_roothub); | ||
| 21 | int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); | 22 | int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); |
| 22 | void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub); | 23 | void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub); |
| 23 | 24 | ||
| @@ -285,6 +285,14 @@ static int usb_port_runtime_suspend(struct device *dev) · 284 unmodified lines | |||
| 285 | } | 285 | } |
| 286 | #endif | 286 | #endif |
| 287 | 287 | ||
| 288 | static void usb_port_shutdown(struct device *dev) | ||
| 289 | { | ||
| 290 | struct usb_port *port_dev = to_usb_port(dev); | ||
| 291 | |||
| 292 | if (port_dev->child) | ||
| 293 | usb_disable_usb2_hardware_lpm(port_dev->child); | ||
| 294 | } | ||
| 295 | |||
| 288 | static const struct dev_pm_ops usb_port_pm_ops = { | 296 | static const struct dev_pm_ops usb_port_pm_ops = { |
| 289 | #ifdef CONFIG_PM | 297 | #ifdef CONFIG_PM |
| 290 | .runtime_suspend = usb_port_runtime_suspend, | 298 | .runtime_suspend = usb_port_runtime_suspend, |
| @@ -301,6 +309,7 @@ struct device_type usb_port_device_type = { · 10 unmodified lines | |||
| 301 | static struct device_driver usb_port_driver = { | 309 | static struct device_driver usb_port_driver = { |
| 302 | .name = "usb", | 310 | .name = "usb", |
| 303 | .owner = THIS_MODULE, | 311 | .owner = THIS_MODULE, |
| 312 | .shutdown = usb_port_shutdown, | ||
| 304 | }; | 313 | }; |
| 305 | 314 | ||
| 306 | static int link_peers(struct usb_port *left, struct usb_port *right) | 315 | static int link_peers(struct usb_port *left, struct usb_port *right) |
| @@ -933,228 +933,6 @@ void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, · 932 unmodified lines | |||
| 933 | } | 933 | } |
| 934 | EXPORT_SYMBOL_GPL(usb_free_coherent); | 934 | EXPORT_SYMBOL_GPL(usb_free_coherent); |
| 935 | 935 | ||
| 936 | /** | ||
| 937 | * usb_buffer_map - create DMA mapping(s) for an urb | ||
| 938 | * @urb: urb whose transfer_buffer/setup_packet will be mapped | ||
| 939 | * | ||
| 940 | * URB_NO_TRANSFER_DMA_MAP is added to urb->transfer_flags if the operation | ||
| 941 | * succeeds. If the device is connected to this system through a non-DMA | ||
| 942 | * controller, this operation always succeeds. | ||
| 943 | * | ||
| 944 | * This call would normally be used for an urb which is reused, perhaps | ||
| 945 | * as the target of a large periodic transfer, with usb_buffer_dmasync() | ||
| 946 | * calls to synchronize memory and dma state. | ||
| 947 | * | ||
| 948 | * Reverse the effect of this call with usb_buffer_unmap(). | ||
| 949 | * | ||
| 950 | * Return: Either %NULL (indicating no buffer could be mapped), or @urb. | ||
| 951 | * | ||
| 952 | */ | ||
| 953 | #if 0 | ||
| 954 | struct urb *usb_buffer_map(struct urb *urb) | ||
| 955 | { | ||
| 956 | struct usb_bus *bus; | ||
| 957 | struct device *controller; | ||
| 958 | |||
| 959 | if (!urb | ||
| 960 | || !urb->dev | ||
| 961 | || !(bus = urb->dev->bus) | ||
| 962 | || !(controller = bus->sysdev)) | ||
| 963 | return NULL; | ||
| 964 | |||
| 965 | if (controller->dma_mask) { | ||
| 966 | urb->transfer_dma = dma_map_single(controller, | ||
| 967 | urb->transfer_buffer, urb->transfer_buffer_length, | ||
| 968 | usb_pipein(urb->pipe) | ||
| 969 | ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 970 | /* FIXME generic api broken like pci, can't report errors */ | ||
| 971 | /* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */ | ||
| 972 | } else | ||
| 973 | urb->transfer_dma = ~0; | ||
| 974 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 975 | return urb; | ||
| 976 | } | ||
| 977 | EXPORT_SYMBOL_GPL(usb_buffer_map); | ||
| 978 | #endif /* 0 */ | ||
| 979 | |||
| 980 | /* XXX DISABLED, no users currently. If you wish to re-enable this | ||
| 981 | * XXX please determine whether the sync is to transfer ownership of | ||
| 982 | * XXX the buffer from device to cpu or vice verse, and thusly use the | ||
| 983 | * XXX appropriate _for_{cpu,device}() method. -DaveM | ||
| 984 | */ | ||
| 985 | #if 0 | ||
| 986 | |||
| 987 | /** | ||
| 988 | * usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s) | ||
| 989 | * @urb: urb whose transfer_buffer/setup_packet will be synchronized | ||
| 990 | */ | ||
| 991 | void usb_buffer_dmasync(struct urb *urb) | ||
| 992 | { | ||
| 993 | struct usb_bus *bus; | ||
| 994 | struct device *controller; | ||
| 995 | |||
| 996 | if (!urb | ||
| 997 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | ||
| 998 | || !urb->dev | ||
| 999 | || !(bus = urb->dev->bus) | ||
| 1000 | || !(controller = bus->sysdev)) | ||
| 1001 | return; | ||
| 1002 | |||
| 1003 | if (controller->dma_mask) { | ||
| 1004 | dma_sync_single_for_cpu(controller, | ||
| 1005 | urb->transfer_dma, urb->transfer_buffer_length, | ||
| 1006 | usb_pipein(urb->pipe) | ||
| 1007 | ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1008 | if (usb_pipecontrol(urb->pipe)) | ||
| 1009 | dma_sync_single_for_cpu(controller, | ||
| 1010 | urb->setup_dma, | ||
| 1011 | sizeof(struct usb_ctrlrequest), | ||
| 1012 | DMA_TO_DEVICE); | ||
| 1013 | } | ||
| 1014 | } | ||
| 1015 | EXPORT_SYMBOL_GPL(usb_buffer_dmasync); | ||
| 1016 | #endif | ||
| 1017 | |||
| 1018 | /** | ||
| 1019 | * usb_buffer_unmap - free DMA mapping(s) for an urb | ||
| 1020 | * @urb: urb whose transfer_buffer will be unmapped | ||
| 1021 | * | ||
| 1022 | * Reverses the effect of usb_buffer_map(). | ||
| 1023 | */ | ||
| 1024 | #if 0 | ||
| 1025 | void usb_buffer_unmap(struct urb *urb) | ||
| 1026 | { | ||
| 1027 | struct usb_bus *bus; | ||
| 1028 | struct device *controller; | ||
| 1029 | |||
| 1030 | if (!urb | ||
| 1031 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | ||
| 1032 | || !urb->dev | ||
| 1033 | || !(bus = urb->dev->bus) | ||
| 1034 | || !(controller = bus->sysdev)) | ||
| 1035 | return; | ||
| 1036 | |||
| 1037 | if (controller->dma_mask) { | ||
| 1038 | dma_unmap_single(controller, | ||
| 1039 | urb->transfer_dma, urb->transfer_buffer_length, | ||
| 1040 | usb_pipein(urb->pipe) | ||
| 1041 | ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1042 | } | ||
| 1043 | urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; | ||
| 1044 | } | ||
| 1045 | EXPORT_SYMBOL_GPL(usb_buffer_unmap); | ||
| 1046 | #endif /* 0 */ | ||
| 1047 | |||
| 1048 | #if 0 | ||
| 1049 | /** | ||
| 1050 | * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint | ||
| 1051 | * @dev: device to which the scatterlist will be mapped | ||
| 1052 | * @is_in: mapping transfer direction | ||
| 1053 | * @sg: the scatterlist to map | ||
| 1054 | * @nents: the number of entries in the scatterlist | ||
| 1055 | * | ||
| 1056 | * Return: Either < 0 (indicating no buffers could be mapped), or the | ||
| 1057 | * number of DMA mapping array entries in the scatterlist. | ||
| 1058 | * | ||
| 1059 | * Note: | ||
| 1060 | * The caller is responsible for placing the resulting DMA addresses from | ||
| 1061 | * the scatterlist into URB transfer buffer pointers, and for setting the | ||
| 1062 | * URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs. | ||
| 1063 | * | ||
| 1064 | * Top I/O rates come from queuing URBs, instead of waiting for each one | ||
| 1065 | * to complete before starting the next I/O. This is particularly easy | ||
| 1066 | * to do with scatterlists. Just allocate and submit one URB for each DMA | ||
| 1067 | * mapping entry returned, stopping on the first error or when all succeed. | ||
| 1068 | * Better yet, use the usb_sg_*() calls, which do that (and more) for you. | ||
| 1069 | * | ||
| 1070 | * This call would normally be used when translating scatterlist requests, | ||
| 1071 | * rather than usb_buffer_map(), since on some hardware (with IOMMUs) it | ||
| 1072 | * may be able to coalesce mappings for improved I/O efficiency. | ||
| 1073 | * | ||
| 1074 | * Reverse the effect of this call with usb_buffer_unmap_sg(). | ||
| 1075 | */ | ||
| 1076 | int usb_buffer_map_sg(const struct usb_device *dev, int is_in, | ||
| 1077 | struct scatterlist *sg, int nents) | ||
| 1078 | { | ||
| 1079 | struct usb_bus *bus; | ||
| 1080 | struct device *controller; | ||
| 1081 | |||
| 1082 | if (!dev | ||
| 1083 | || !(bus = dev->bus) | ||
| 1084 | || !(controller = bus->sysdev) | ||
| 1085 | || !controller->dma_mask) | ||
| 1086 | return -EINVAL; | ||
| 1087 | |||
| 1088 | /* FIXME generic api broken like pci, can't report errors */ | ||
| 1089 | return dma_map_sg(controller, sg, nents, | ||
| 1090 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM; | ||
| 1091 | } | ||
| 1092 | EXPORT_SYMBOL_GPL(usb_buffer_map_sg); | ||
| 1093 | #endif | ||
| 1094 | |||
| 1095 | /* XXX DISABLED, no users currently. If you wish to re-enable this | ||
| 1096 | * XXX please determine whether the sync is to transfer ownership of | ||
| 1097 | * XXX the buffer from device to cpu or vice verse, and thusly use the | ||
| 1098 | * XXX appropriate _for_{cpu,device}() method. -DaveM | ||
| 1099 | */ | ||
| 1100 | #if 0 | ||
| 1101 | |||
| 1102 | /** | ||
| 1103 | * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s) | ||
| 1104 | * @dev: device to which the scatterlist will be mapped | ||
| 1105 | * @is_in: mapping transfer direction | ||
| 1106 | * @sg: the scatterlist to synchronize | ||
| 1107 | * @n_hw_ents: the positive return value from usb_buffer_map_sg | ||
| 1108 | * | ||
| 1109 | * Use this when you are re-using a scatterlist's data buffers for | ||
| 1110 | * another USB request. | ||
| 1111 | */ | ||
| 1112 | void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in, | ||
| 1113 | struct scatterlist *sg, int n_hw_ents) | ||
| 1114 | { | ||
| 1115 | struct usb_bus *bus; | ||
| 1116 | struct device *controller; | ||
| 1117 | |||
| 1118 | if (!dev | ||
| 1119 | || !(bus = dev->bus) | ||
| 1120 | || !(controller = bus->sysdev) | ||
| 1121 | || !controller->dma_mask) | ||
| 1122 | return; | ||
| 1123 | |||
| 1124 | dma_sync_sg_for_cpu(controller, sg, n_hw_ents, | ||
| 1125 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1126 | } | ||
| 1127 | EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg); | ||
| 1128 | #endif | ||
| 1129 | |||
| 1130 | #if 0 | ||
| 1131 | /** | ||
| 1132 | * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist | ||
| 1133 | * @dev: device to which the scatterlist will be mapped | ||
| 1134 | * @is_in: mapping transfer direction | ||
| 1135 | * @sg: the scatterlist to unmap | ||
| 1136 | * @n_hw_ents: the positive return value from usb_buffer_map_sg | ||
| 1137 | * | ||
| 1138 | * Reverses the effect of usb_buffer_map_sg(). | ||
| 1139 | */ | ||
| 1140 | void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in, | ||
| 1141 | struct scatterlist *sg, int n_hw_ents) | ||
| 1142 | { | ||
| 1143 | struct usb_bus *bus; | ||
| 1144 | struct device *controller; | ||
| 1145 | |||
| 1146 | if (!dev | ||
| 1147 | || !(bus = dev->bus) | ||
| 1148 | || !(controller = bus->sysdev) | ||
| 1149 | || !controller->dma_mask) | ||
| 1150 | return; | ||
| 1151 | |||
| 1152 | dma_unmap_sg(controller, sg, n_hw_ents, | ||
| 1153 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1154 | } | ||
| 1155 | EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg); | ||
| 1156 | #endif | ||
| 1157 | |||
| 1158 | /* | 936 | /* |
| 1159 | * Notifications of device and interface registration | 937 | * Notifications of device and interface registration |
| 1160 | */ | 938 | */ |
| @@ -95,6 +95,9 @@ extern int usb_runtime_idle(struct device *dev); · 94 unmodified lines | |||
| 95 | extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev); | 95 | extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev); |
| 96 | extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev); | 96 | extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev); |
| 97 | 97 | ||
| 98 | extern void usbfs_notify_suspend(struct usb_device *udev); | ||
| 99 | extern void usbfs_notify_resume(struct usb_device *udev); | ||
| 100 | |||
| 98 | #else | 101 | #else |
| 99 | 102 | ||
| 100 | static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | 103 | static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
| @@ -3224,14 +3224,15 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, · 3223 unmodified lines | |||
| 3224 | struct dwc2_hsotg_ep *ep, | 3224 | struct dwc2_hsotg_ep *ep, |
| 3225 | int result) | 3225 | int result) |
| 3226 | { | 3226 | { |
| 3227 | struct dwc2_hsotg_req *req, *treq; | ||
| 3228 | unsigned int size; | 3227 | unsigned int size; |
| 3229 | 3228 | ||
| 3230 | ep->req = NULL; | 3229 | ep->req = NULL; |
| 3231 | 3230 | ||
| 3232 | list_for_each_entry_safe(req, treq, &ep->queue, queue) | 3231 | while (!list_empty(&ep->queue)) { |
| 3233 | dwc2_hsotg_complete_request(hsotg, ep, req, | 3232 | struct dwc2_hsotg_req *req = get_ep_head(ep); |
| 3234 | result); | 3233 | |
| 3234 | dwc2_hsotg_complete_request(hsotg, ep, req, result); | ||
| 3235 | } | ||
| 3235 | 3236 | ||
| 3236 | if (!hsotg->dedicated_fifos) | 3237 | if (!hsotg->dedicated_fifos) |
| 3237 | return; | 3238 | return; |
| @@ -5062,13 +5062,13 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) · 5061 unmodified lines | |||
| 5062 | dwc2_hc_driver.reset_device = dwc2_reset_device; | 5062 | dwc2_hc_driver.reset_device = dwc2_reset_device; |
| 5063 | } | 5063 | } |
| 5064 | 5064 | ||
| 5065 | if (hsotg->params.host_dma) | ||
| 5066 | dwc2_hc_driver.flags |= HCD_DMA; | ||
| 5067 | |||
| 5065 | hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); | 5068 | hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); |
| 5066 | if (!hcd) | 5069 | if (!hcd) |
| 5067 | goto error1; | 5070 | goto error1; |
| 5068 | 5071 | ||
| 5069 | if (!hsotg->params.host_dma) | ||
| 5070 | hcd->self.uses_dma = 0; | ||
| 5071 | |||
| 5072 | hcd->has_tt = 1; | 5072 | hcd->has_tt = 1; |
| 5073 | 5073 | ||
| 5074 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 5074 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -404,10 +404,7 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) · 403 unmodified lines | |||
| 404 | device_property_read_u32(hsotg->dev, "g-np-tx-fifo-size", | 404 | device_property_read_u32(hsotg->dev, "g-np-tx-fifo-size", |
| 405 | &p->g_np_tx_fifo_size); | 405 | &p->g_np_tx_fifo_size); |
| 406 | 406 | ||
| 407 | num = device_property_read_u32_array(hsotg->dev, | 407 | num = device_property_count_u32(hsotg->dev, "g-tx-fifo-size"); |
| 408 | "g-tx-fifo-size", | ||
| 409 | NULL, 0); | ||
| 410 | |||
| 411 | if (num > 0) { | 408 | if (num > 0) { |
| 412 | num = min(num, 15); | 409 | num = min(num, 15); |
| 413 | memset(p->g_tx_fifo_size, 0, | 410 | memset(p->g_tx_fifo_size, 0, |
| @@ -407,10 +407,8 @@ static int dwc2_driver_probe(struct platform_device *dev) · 406 unmodified lines | |||
| 407 | spin_lock_init(&hsotg->lock); | 407 | spin_lock_init(&hsotg->lock); |
| 408 | 408 | ||
| 409 | hsotg->irq = platform_get_irq(dev, 0); | 409 | hsotg->irq = platform_get_irq(dev, 0); |
| 410 | if (hsotg->irq < 0) { | 410 | if (hsotg->irq < 0) |
| 411 | dev_err(&dev->dev, "missing IRQ resource\n"); | ||
| 412 | return hsotg->irq; | 411 | return hsotg->irq; |
| 413 | } | ||
| 414 | 412 | ||
| 415 | dev_dbg(hsotg->dev, "registering common handler for irq%d\n", | 413 | dev_dbg(hsotg->dev, "registering common handler for irq%d\n", |
| 416 | hsotg->irq); | 414 | hsotg->irq); |
| @@ -168,7 +168,6 @@ static void __dwc3_set_mode(struct work_struct *work) · 167 unmodified lines | |||
| 168 | otg_set_vbus(dwc->usb2_phy->otg, true); | 168 | otg_set_vbus(dwc->usb2_phy->otg, true); |
| 169 | phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); | 169 | phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); |
| 170 | phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); | 170 | phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); |
| 171 | phy_calibrate(dwc->usb2_generic_phy); | ||
| 172 | } | 171 | } |
| 173 | break; | 172 | break; |
| 174 | case DWC3_GCTL_PRTCAP_DEVICE: | 173 | case DWC3_GCTL_PRTCAP_DEVICE: |
| @@ -252,12 +251,25 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) · 77 unmodified lines | |||
| 252 | reg |= DWC3_DCTL_CSFTRST; | 251 | reg |= DWC3_DCTL_CSFTRST; |
| 253 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); | 252 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
| 254 | 253 | ||
| 254 | /* | ||
| 255 | * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit | ||
| 256 | * is cleared only after all the clocks are synchronized. This can | ||
| 257 | * take a little more than 50ms. Set the polling rate at 20ms | ||
| 258 | * for 10 times instead. | ||
| 259 | */ | ||
| 260 | if (dwc3_is_usb31(dwc) && dwc->revision >= DWC3_USB31_REVISION_190A) | ||
| 261 | retries = 10; | ||
| 262 | |||
| 255 | do { | 263 | do { |
| 256 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 264 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 257 | if (!(reg & DWC3_DCTL_CSFTRST)) | 265 | if (!(reg & DWC3_DCTL_CSFTRST)) |
| 258 | goto done; | 266 | goto done; |
| 259 | 267 | ||
| 260 | udelay(1); | 268 | if (dwc3_is_usb31(dwc) && |
| 269 | dwc->revision >= DWC3_USB31_REVISION_190A) | ||
| 270 | msleep(20); | ||
| 271 | else | ||
| 272 | udelay(1); | ||
| 261 | } while (--retries); | 273 | } while (--retries); |
| 262 | 274 | ||
| 263 | phy_exit(dwc->usb3_generic_phy); | 275 | phy_exit(dwc->usb3_generic_phy); |
| @@ -267,11 +279,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) · 3 unmodified lines | |||
| 267 | 279 | ||
| 268 | done: | 280 | done: |
| 269 | /* | 281 | /* |
| 270 | * For DWC_usb31 controller, once DWC3_DCTL_CSFTRST bit is cleared, | 282 | * For DWC_usb31 controller 1.80a and prior, once DCTL.CSFRST bit |
| 271 | * we must wait at least 50ms before accessing the PHY domain | 283 | * is cleared, we must wait at least 50ms before accessing the PHY |
| 272 | * (synchronization delay). DWC_usb31 programming guide section 1.3.2. | 284 | * domain (synchronization delay). |
| 273 | */ | 285 | */ |
| 274 | if (dwc3_is_usb31(dwc)) | 286 | if (dwc3_is_usb31(dwc) && dwc->revision <= DWC3_USB31_REVISION_180A) |
| 275 | msleep(50); | 287 | msleep(50); |
| 276 | 288 | ||
| 277 | return 0; | 289 | return 0; |
| @@ -686,8 +698,7 @@ static void dwc3_core_exit(struct dwc3 *dwc) · 408 unmodified lines | |||
| 686 | usb_phy_set_suspend(dwc->usb3_phy, 1); | 698 | usb_phy_set_suspend(dwc->usb3_phy, 1); |
| 687 | phy_power_off(dwc->usb2_generic_phy); | 699 | phy_power_off(dwc->usb2_generic_phy); |
| 688 | phy_power_off(dwc->usb3_generic_phy); | 700 | phy_power_off(dwc->usb3_generic_phy); |
| 689 | clk_bulk_disable(dwc->num_clks, dwc->clks); | 701 | clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); |
| 690 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); | ||
| 691 | reset_control_assert(dwc->reset); | 702 | reset_control_assert(dwc->reset); |
| 692 | } | 703 | } |
| 693 | 704 | ||
| @@ -813,8 +824,7 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) · 119 unmodified lines | |||
| 813 | * result = 1, means INCRx burst mode supported. | 824 | * result = 1, means INCRx burst mode supported. |
| 814 | * result > 1, means undefined length burst mode supported. | 825 | * result > 1, means undefined length burst mode supported. |
| 815 | */ | 826 | */ |
| 816 | ntype = device_property_read_u32_array(dev, | 827 | ntype = device_property_count_u32(dev, "snps,incr-burst-type-adjustment"); |
| 817 | "snps,incr-burst-type-adjustment", NULL, 0); | ||
| 818 | if (ntype <= 0) | 828 | if (ntype <= 0) |
| 819 | return; | 829 | return; |
| 820 | 830 | ||
| @@ -1166,7 +1176,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) · 345 unmodified lines | |||
| 1166 | dev_err(dev, "failed to initialize host\n"); | 1176 | dev_err(dev, "failed to initialize host\n"); |
| 1167 | return ret; | 1177 | return ret; |
| 1168 | } | 1178 | } |
| 1169 | phy_calibrate(dwc->usb2_generic_phy); | ||
| 1170 | break; | 1179 | break; |
| 1171 | case USB_DR_MODE_OTG: | 1180 | case USB_DR_MODE_OTG: |
| 1172 | INIT_WORK(&dwc->drd_work, __dwc3_set_mode); | 1181 | INIT_WORK(&dwc->drd_work, __dwc3_set_mode); |
| @@ -1310,8 +1319,7 @@ static void dwc3_get_properties(struct dwc3 *dwc) · 137 unmodified lines | |||
| 1310 | dwc->lpm_nyet_threshold = lpm_nyet_threshold; | 1319 | dwc->lpm_nyet_threshold = lpm_nyet_threshold; |
| 1311 | dwc->tx_de_emphasis = tx_de_emphasis; | 1320 | dwc->tx_de_emphasis = tx_de_emphasis; |
| 1312 | 1321 | ||
| 1313 | dwc->hird_threshold = hird_threshold | 1322 | dwc->hird_threshold = hird_threshold; |
| 1314 | | (dwc->is_utmi_l1_suspend << 4); | ||
| 1315 | 1323 | ||
| 1316 | dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd; | 1324 | dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd; |
| 1317 | dwc->rx_max_burst_prd = rx_max_burst_prd; | 1325 | dwc->rx_max_burst_prd = rx_max_burst_prd; |
| @@ -1436,7 +1444,7 @@ static int dwc3_probe(struct platform_device *pdev) · 118 unmodified lines | |||
| 1436 | if (dev->of_node) { | 1444 | if (dev->of_node) { |
| 1437 | dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); | 1445 | dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); |
| 1438 | 1446 | ||
| 1439 | ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); | 1447 | ret = devm_clk_bulk_get(dev, dwc->num_clks, dwc->clks); |
| 1440 | if (ret == -EPROBE_DEFER) | 1448 | if (ret == -EPROBE_DEFER) |
| 1441 | return ret; | 1449 | return ret; |
| 1442 | /* | 1450 | /* |
| @@ -1449,16 +1457,12 @@ static int dwc3_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 1449 | 1457 | ||
| 1450 | ret = reset_control_deassert(dwc->reset); | 1458 | ret = reset_control_deassert(dwc->reset); |
| 1451 | if (ret) | 1459 | if (ret) |
| 1452 | goto put_clks; | 1460 | return ret; |
| 1453 | 1461 | ||
| 1454 | ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); | 1462 | ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); |
| 1455 | if (ret) | 1463 | if (ret) |
| 1456 | goto assert_reset; | 1464 | goto assert_reset; |
| 1457 | 1465 | ||
| 1458 | ret = clk_bulk_enable(dwc->num_clks, dwc->clks); | ||
| 1459 | if (ret) | ||
| 1460 | goto unprepare_clks; | ||
| 1461 | |||
| 1462 | if (!dwc3_core_is_valid(dwc)) { | 1466 | if (!dwc3_core_is_valid(dwc)) { |
| 1463 | dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); | 1467 | dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); |
| 1464 | ret = -ENODEV; | 1468 | ret = -ENODEV; |
| @@ -1531,13 +1535,9 @@ err1: · 66 unmodified lines | |||
| 1531 | pm_runtime_disable(&pdev->dev); | 1535 | pm_runtime_disable(&pdev->dev); |
| 1532 | 1536 | ||
| 1533 | disable_clks: | 1537 | disable_clks: |
| 1534 | clk_bulk_disable(dwc->num_clks, dwc->clks); | 1538 | clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); |
| 1535 | unprepare_clks: | ||
| 1536 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); | ||
| 1537 | assert_reset: | 1539 | assert_reset: |
| 1538 | reset_control_assert(dwc->reset); | 1540 | reset_control_assert(dwc->reset); |
| 1539 | put_clks: | ||
| 1540 | clk_bulk_put(dwc->num_clks, dwc->clks); | ||
| 1541 | 1541 | ||
| 1542 | return ret; | 1542 | return ret; |
| 1543 | } | 1543 | } |
| @@ -1560,7 +1560,6 @@ static int dwc3_remove(struct platform_device *pdev) · 16 unmodified lines | |||
| 1560 | 1560 | ||
| 1561 | dwc3_free_event_buffers(dwc); | 1561 | dwc3_free_event_buffers(dwc); |
| 1562 | dwc3_free_scratch_buffers(dwc); | 1562 | dwc3_free_scratch_buffers(dwc); |
| 1563 | clk_bulk_put(dwc->num_clks, dwc->clks); | ||
| 1564 | 1563 | ||
| 1565 | return 0; | 1564 | return 0; |
| 1566 | } | 1565 | } |
| @@ -1574,14 +1573,10 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) · 7 unmodified lines | |||
| 1574 | if (ret) | 1573 | if (ret) |
| 1575 | return ret; | 1574 | return ret; |
| 1576 | 1575 | ||
| 1577 | ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); | 1576 | ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); |
| 1578 | if (ret) | 1577 | if (ret) |
| 1579 | goto assert_reset; | 1578 | goto assert_reset; |
| 1580 | 1579 | ||
| 1581 | ret = clk_bulk_enable(dwc->num_clks, dwc->clks); | ||
| 1582 | if (ret) | ||
| 1583 | goto unprepare_clks; | ||
| 1584 | |||
| 1585 | ret = dwc3_core_init(dwc); | 1580 | ret = dwc3_core_init(dwc); |
| 1586 | if (ret) | 1581 | if (ret) |
| 1587 | goto disable_clks; | 1582 | goto disable_clks; |
| @@ -1589,9 +1584,7 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) · 1 unmodified line | |||
| 1589 | return 0; | 1584 | return 0; |
| 1590 | 1585 | ||
| 1591 | disable_clks: | 1586 | disable_clks: |
| 1592 | clk_bulk_disable(dwc->num_clks, dwc->clks); | 1587 | clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); |
| 1593 | unprepare_clks: | ||
| 1594 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); | ||
| 1595 | assert_reset: | 1588 | assert_reset: |
| 1596 | reset_control_assert(dwc->reset); | 1589 | reset_control_assert(dwc->reset); |
| 1597 | 1590 | ||
| @@ -1137,6 +1137,8 @@ struct dwc3 { · 1136 unmodified lines | |||
| 1137 | #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) | 1137 | #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) |
| 1138 | #define DWC3_USB31_REVISION_160A (0x3136302a | DWC3_REVISION_IS_DWC31) | 1138 | #define DWC3_USB31_REVISION_160A (0x3136302a | DWC3_REVISION_IS_DWC31) |
| 1139 | #define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) | 1139 | #define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) |
| 1140 | #define DWC3_USB31_REVISION_180A (0x3138302a | DWC3_REVISION_IS_DWC31) | ||
| 1141 | #define DWC3_USB31_REVISION_190A (0x3139302a | DWC3_REVISION_IS_DWC31) | ||
| 1140 | 1142 | ||
| 1141 | u32 version_type; | 1143 | u32 version_type; |
| 1142 | 1144 | ||
| @@ -246,258 +246,6 @@ static inline const char *dwc3_gadget_event_string(char *str, size_t size, · 245 unmodified lines | |||
| 246 | return str; | 246 | return str; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str, | ||
| 250 | size_t size) | ||
| 251 | { | ||
| 252 | switch (t & USB_RECIP_MASK) { | ||
| 253 | case USB_RECIP_DEVICE: | ||
| 254 | snprintf(str, size, "Get Device Status(Length = %d)", l); | ||
| 255 | break; | ||
| 256 | case USB_RECIP_INTERFACE: | ||
| 257 | snprintf(str, size, "Get Interface Status(Intf = %d, Length = %d)", | ||
| 258 | i, l); | ||
| 259 | break; | ||
| 260 | case USB_RECIP_ENDPOINT: | ||
| 261 | snprintf(str, size, "Get Endpoint Status(ep%d%s)", | ||
| 262 | i & ~USB_DIR_IN, | ||
| 263 | i & USB_DIR_IN ? "in" : "out"); | ||
| 264 | break; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v, | ||
| 269 | __u16 i, char *str, size_t size) | ||
| 270 | { | ||
| 271 | switch (t & USB_RECIP_MASK) { | ||
| 272 | case USB_RECIP_DEVICE: | ||
| 273 | snprintf(str, size, "%s Device Feature(%s%s)", | ||
| 274 | b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 275 | ({char *s; | ||
| 276 | switch (v) { | ||
| 277 | case USB_DEVICE_SELF_POWERED: | ||
| 278 | s = "Self Powered"; | ||
| 279 | break; | ||
| 280 | case USB_DEVICE_REMOTE_WAKEUP: | ||
| 281 | s = "Remote Wakeup"; | ||
| 282 | break; | ||
| 283 | case USB_DEVICE_TEST_MODE: | ||
| 284 | s = "Test Mode"; | ||
| 285 | break; | ||
| 286 | case USB_DEVICE_U1_ENABLE: | ||
| 287 | s = "U1 Enable"; | ||
| 288 | break; | ||
| 289 | case USB_DEVICE_U2_ENABLE: | ||
| 290 | s = "U2 Enable"; | ||
| 291 | break; | ||
| 292 | case USB_DEVICE_LTM_ENABLE: | ||
| 293 | s = "LTM Enable"; | ||
| 294 | break; | ||
| 295 | default: | ||
| 296 | s = "UNKNOWN"; | ||
| 297 | } s; }), | ||
| 298 | v == USB_DEVICE_TEST_MODE ? | ||
| 299 | ({ char *s; | ||
| 300 | switch (i) { | ||
| 301 | case TEST_J: | ||
| 302 | s = ": TEST_J"; | ||
| 303 | break; | ||
| 304 | case TEST_K: | ||
| 305 | s = ": TEST_K"; | ||
| 306 | break; | ||
| 307 | case TEST_SE0_NAK: | ||
| 308 | s = ": TEST_SE0_NAK"; | ||
| 309 | break; | ||
| 310 | case TEST_PACKET: | ||
| 311 | s = ": TEST_PACKET"; | ||
| 312 | break; | ||
| 313 | case TEST_FORCE_EN: | ||
| 314 | s = ": TEST_FORCE_EN"; | ||
| 315 | break; | ||
| 316 | default: | ||
| 317 | s = ": UNKNOWN"; | ||
| 318 | } s; }) : ""); | ||
| 319 | break; | ||
| 320 | case USB_RECIP_INTERFACE: | ||
| 321 | snprintf(str, size, "%s Interface Feature(%s)", | ||
| 322 | b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 323 | v == USB_INTRF_FUNC_SUSPEND ? | ||
| 324 | "Function Suspend" : "UNKNOWN"); | ||
| 325 | break; | ||
| 326 | case USB_RECIP_ENDPOINT: | ||
| 327 | snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)", | ||
| 328 | b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", | ||
| 329 | v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", | ||
| 330 | i & ~USB_DIR_IN, | ||
| 331 | i & USB_DIR_IN ? "in" : "out"); | ||
| 332 | break; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | static inline void dwc3_decode_set_address(__u16 v, char *str, size_t size) | ||
| 337 | { | ||
| 338 | snprintf(str, size, "Set Address(Addr = %02x)", v); | ||
| 339 | } | ||
| 340 | |||
| 341 | static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v, | ||
| 342 | __u16 i, __u16 l, char *str, size_t size) | ||
| 343 | { | ||
| 344 | snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)", | ||
| 345 | b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", | ||
| 346 | ({ char *s; | ||
| 347 | switch (v >> 8) { | ||
| 348 | case USB_DT_DEVICE: | ||
| 349 | s = "Device"; | ||
| 350 | break; | ||
| 351 | case USB_DT_CONFIG: | ||
| 352 | s = "Configuration"; | ||
| 353 | break; | ||
| 354 | case USB_DT_STRING: | ||
| 355 | s = "String"; | ||
| 356 | break; | ||
| 357 | case USB_DT_INTERFACE: | ||
| 358 | s = "Interface"; | ||
| 359 | break; | ||
| 360 | case USB_DT_ENDPOINT: | ||
| 361 | s = "Endpoint"; | ||
| 362 | break; | ||
| 363 | case USB_DT_DEVICE_QUALIFIER: | ||
| 364 | s = "Device Qualifier"; | ||
| 365 | break; | ||
| 366 | case USB_DT_OTHER_SPEED_CONFIG: | ||
| 367 | s = "Other Speed Config"; | ||
| 368 | break; | ||
| 369 | case USB_DT_INTERFACE_POWER: | ||
| 370 | s = "Interface Power"; | ||
| 371 | break; | ||
| 372 | case USB_DT_OTG: | ||
| 373 | s = "OTG"; | ||
| 374 | break; | ||
| 375 | case USB_DT_DEBUG: | ||
| 376 | s = "Debug"; | ||
| 377 | break; | ||
| 378 | case USB_DT_INTERFACE_ASSOCIATION: | ||
| 379 | s = "Interface Association"; | ||
| 380 | break; | ||
| 381 | case USB_DT_BOS: | ||
| 382 | s = "BOS"; | ||
| 383 | break; | ||
| 384 | case USB_DT_DEVICE_CAPABILITY: | ||
| 385 | s = "Device Capability"; | ||
| 386 | break; | ||
| 387 | case USB_DT_PIPE_USAGE: | ||
| 388 | s = "Pipe Usage"; | ||
| 389 | break; | ||
| 390 | case USB_DT_SS_ENDPOINT_COMP: | ||
| 391 | s = "SS Endpoint Companion"; | ||
| 392 | break; | ||
| 393 | case USB_DT_SSP_ISOC_ENDPOINT_COMP: | ||
| 394 | s = "SSP Isochronous Endpoint Companion"; | ||
| 395 | break; | ||
| 396 | default: | ||
| 397 | s = "UNKNOWN"; | ||
| 398 | break; | ||
| 399 | } s; }), v & 0xff, l); | ||
| 400 | } | ||
| 401 | |||
| 402 | |||
| 403 | static inline void dwc3_decode_get_configuration(__u16 l, char *str, | ||
| 404 | size_t size) | ||
| 405 | { | ||
| 406 | snprintf(str, size, "Get Configuration(Length = %d)", l); | ||
| 407 | } | ||
| 408 | |||
| 409 | static inline void dwc3_decode_set_configuration(__u8 v, char *str, size_t size) | ||
| 410 | { | ||
| 411 | snprintf(str, size, "Set Configuration(Config = %d)", v); | ||
| 412 | } | ||
| 413 | |||
| 414 | static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str, | ||
| 415 | size_t size) | ||
| 416 | { | ||
| 417 | snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", i, l); | ||
| 418 | } | ||
| 419 | |||
| 420 | static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str, size_t size) | ||
| 421 | { | ||
| 422 | snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v); | ||
| 423 | } | ||
| 424 | |||
| 425 | static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str, | ||
| 426 | size_t size) | ||
| 427 | { | ||
| 428 | snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", i, l); | ||
| 429 | } | ||
| 430 | |||
| 431 | static inline void dwc3_decode_set_sel(__u16 l, char *str, size_t size) | ||
| 432 | { | ||
| 433 | snprintf(str, size, "Set SEL(Length = %d)", l); | ||
| 434 | } | ||
| 435 | |||
| 436 | static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str, size_t size) | ||
| 437 | { | ||
| 438 | snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", v); | ||
| 439 | } | ||
| 440 | |||
| 441 | /** | ||
| 442 | * dwc3_decode_ctrl - returns a string represetion of ctrl request | ||
| 443 | */ | ||
| 444 | static inline const char *dwc3_decode_ctrl(char *str, size_t size, | ||
| 445 | __u8 bRequestType, __u8 bRequest, __u16 wValue, __u16 wIndex, | ||
| 446 | __u16 wLength) | ||
| 447 | { | ||
| 448 | switch (bRequest) { | ||
| 449 | case USB_REQ_GET_STATUS: | ||
| 450 | dwc3_decode_get_status(bRequestType, wIndex, wLength, str, | ||
| 451 | size); | ||
| 452 | break; | ||
| 453 | case USB_REQ_CLEAR_FEATURE: | ||
| 454 | case USB_REQ_SET_FEATURE: | ||
| 455 | dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue, | ||
| 456 | wIndex, str, size); | ||
| 457 | break; | ||
| 458 | case USB_REQ_SET_ADDRESS: | ||
| 459 | dwc3_decode_set_address(wValue, str, size); | ||
| 460 | break; | ||
| 461 | case USB_REQ_GET_DESCRIPTOR: | ||
| 462 | case USB_REQ_SET_DESCRIPTOR: | ||
| 463 | dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue, | ||
| 464 | wIndex, wLength, str, size); | ||
| 465 | break; | ||
| 466 | case USB_REQ_GET_CONFIGURATION: | ||
| 467 | dwc3_decode_get_configuration(wLength, str, size); | ||
| 468 | break; | ||
| 469 | case USB_REQ_SET_CONFIGURATION: | ||
| 470 | dwc3_decode_set_configuration(wValue, str, size); | ||
| 471 | break; | ||
| 472 | case USB_REQ_GET_INTERFACE: | ||
| 473 | dwc3_decode_get_intf(wIndex, wLength, str, size); | ||
| 474 | break; | ||
| 475 | case USB_REQ_SET_INTERFACE: | ||
| 476 | dwc3_decode_set_intf(wValue, wIndex, str, size); | ||
| 477 | break; | ||
| 478 | case USB_REQ_SYNCH_FRAME: | ||
| 479 | dwc3_decode_synch_frame(wIndex, wLength, str, size); | ||
| 480 | break; | ||
| 481 | case USB_REQ_SET_SEL: | ||
| 482 | dwc3_decode_set_sel(wLength, str, size); | ||
| 483 | break; | ||
| 484 | case USB_REQ_SET_ISOCH_DELAY: | ||
| 485 | dwc3_decode_set_isoch_delay(wValue, str, size); | ||
| 486 | break; | ||
| 487 | default: | ||
| 488 | snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", | ||
| 489 | bRequestType, bRequest, | ||
| 490 | cpu_to_le16(wValue) & 0xff, | ||
| 491 | cpu_to_le16(wValue) >> 8, | ||
| 492 | cpu_to_le16(wIndex) & 0xff, | ||
| 493 | cpu_to_le16(wIndex) >> 8, | ||
| 494 | cpu_to_le16(wLength) & 0xff, | ||
| 495 | cpu_to_le16(wLength) >> 8); | ||
| 496 | } | ||
| 497 | |||
| 498 | return str; | ||
| 499 | } | ||
| 500 | |||
| 501 | /** | 249 | /** |
| 502 | * dwc3_ep_event_string - returns event name | 250 | * dwc3_ep_event_string - returns event name |
| 503 | * @event: then event code | 251 | * @event: then event code |
| @@ -81,7 +81,6 @@ static int kdwc3_probe(struct platform_device *pdev) · 80 unmodified lines | |||
| 81 | struct device *dev = &pdev->dev; | 81 | struct device *dev = &pdev->dev; |
| 82 | struct device_node *node = pdev->dev.of_node; | 82 | struct device_node *node = pdev->dev.of_node; |
| 83 | struct dwc3_keystone *kdwc; | 83 | struct dwc3_keystone *kdwc; |
| 84 | struct resource *res; | ||
| 85 | int error, irq; | 84 | int error, irq; |
| 86 | 85 | ||
| 87 | kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL); | 86 | kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL); |
| @@ -92,8 +91,7 @@ static int kdwc3_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 92 | 91 | ||
| 93 | kdwc->dev = dev; | 92 | kdwc->dev = dev; |
| 94 | 93 | ||
| 95 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 94 | kdwc->usbss = devm_platform_ioremap_resource(pdev, 0); |
| 96 | kdwc->usbss = devm_ioremap_resource(dev, res); | ||
| 97 | if (IS_ERR(kdwc->usbss)) | 95 | if (IS_ERR(kdwc->usbss)) |
| 98 | return PTR_ERR(kdwc->usbss); | 96 | return PTR_ERR(kdwc->usbss); |
| 99 | 97 | ||
| @@ -112,7 +110,6 @@ static int kdwc3_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 112 | 110 | ||
| 113 | irq = platform_get_irq(pdev, 0); | 111 | irq = platform_get_irq(pdev, 0); |
| 114 | if (irq < 0) { | 112 | if (irq < 0) { |
| 115 | dev_err(&pdev->dev, "missing irq\n"); | ||
| 116 | error = irq; | 113 | error = irq; |
| 117 | goto err_irq; | 114 | goto err_irq; |
| 118 | } | 115 | } |
| @@ -386,7 +386,6 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) · 385 unmodified lines | |||
| 386 | struct device *dev = &pdev->dev; | 386 | struct device *dev = &pdev->dev; |
| 387 | struct device_node *np = dev->of_node; | 387 | struct device_node *np = dev->of_node; |
| 388 | void __iomem *base; | 388 | void __iomem *base; |
| 389 | struct resource *res; | ||
| 390 | enum phy_mode otg_id; | 389 | enum phy_mode otg_id; |
| 391 | int ret, i, irq; | 390 | int ret, i, irq; |
| 392 | 391 | ||
| @@ -394,8 +393,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 394 | if (!priv) | 393 | if (!priv) |
| 395 | return -ENOMEM; | 394 | return -ENOMEM; |
| 396 | 395 | ||
| 397 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 396 | base = devm_platform_ioremap_resource(pdev, 0); |
| 398 | base = devm_ioremap_resource(dev, res); | ||
| 399 | if (IS_ERR(base)) | 397 | if (IS_ERR(base)) |
| 400 | return PTR_ERR(base); | 398 | return PTR_ERR(base); |
| 401 | 399 | ||
| @@ -564,7 +562,13 @@ static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev) · 162 unmodified lines | |||
| 564 | static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev) | 562 | static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev) |
| 565 | { | 563 | { |
| 566 | struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); | 564 | struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); |
| 567 | int i; | 565 | int i, ret; |
| 566 | |||
| 567 | if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { | ||
| 568 | ret = regulator_disable(priv->vbus); | ||
| 569 | if (ret) | ||
| 570 | return ret; | ||
| 571 | } | ||
| 568 | 572 | ||
| 569 | for (i = 0 ; i < PHY_COUNT ; ++i) { | 573 | for (i = 0 ; i < PHY_COUNT ; ++i) { |
| 570 | phy_power_off(priv->phys[i]); | 574 | phy_power_off(priv->phys[i]); |
| @@ -599,6 +603,12 @@ static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev) · 28 unmodified lines | |||
| 599 | return ret; | 603 | return ret; |
| 600 | } | 604 | } |
| 601 | 605 | ||
| 606 | if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { | ||
| 607 | ret = regulator_enable(priv->vbus); | ||
| 608 | if (ret) | ||
| 609 | return ret; | ||
| 610 | } | ||
| 611 | |||
| 602 | return 0; | 612 | return 0; |
| 603 | } | 613 | } |
| 604 | 614 | ||
| @@ -14,7 +14,6 @@ · 13 unmodified lines | |||
| 14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/platform_data/dwc3-omap.h> | ||
| 18 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
| 19 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
| 20 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
| @@ -106,6 +105,12 @@ · 85 unmodified lines | |||
| 106 | #define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) | 105 | #define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) |
| 107 | #define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) | 106 | #define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) |
| 108 | 107 | ||
| 108 | enum dwc3_omap_utmi_mode { | ||
| 109 | DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, | ||
| 110 | DWC3_OMAP_UTMI_MODE_HW, | ||
| 111 | DWC3_OMAP_UTMI_MODE_SW, | ||
| 112 | }; | ||
| 113 | |||
| 109 | struct dwc3_omap { | 114 | struct dwc3_omap { |
| 110 | struct device *dev; | 115 | struct device *dev; |
| 111 | 116 | ||
| @@ -446,7 +451,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) · 334 unmodified lines | |||
| 446 | struct device_node *node = pdev->dev.of_node; | 451 | struct device_node *node = pdev->dev.of_node; |
| 447 | 452 | ||
| 448 | struct dwc3_omap *omap; | 453 | struct dwc3_omap *omap; |
| 449 | struct resource *res; | ||
| 450 | struct device *dev = &pdev->dev; | 454 | struct device *dev = &pdev->dev; |
| 451 | struct regulator *vbus_reg = NULL; | 455 | struct regulator *vbus_reg = NULL; |
| 452 | 456 | ||
| @@ -469,13 +473,10 @@ static int dwc3_omap_probe(struct platform_device *pdev) · 16 unmodified lines | |||
| 469 | platform_set_drvdata(pdev, omap); | 473 | platform_set_drvdata(pdev, omap); |
| 470 | 474 | ||
| 471 | irq = platform_get_irq(pdev, 0); | 475 | irq = platform_get_irq(pdev, 0); |
| 472 | if (irq < 0) { | 476 | if (irq < 0) |
| 473 | dev_err(dev, "missing IRQ resource: %d\n", irq); | ||
| 474 | return irq; | 477 | return irq; |
| 475 | } | ||
| 476 | 478 | ||
| 477 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 479 | base = devm_platform_ioremap_resource(pdev, 0); |
| 478 | base = devm_ioremap_resource(dev, res); | ||
| 479 | if (IS_ERR(base)) | 480 | if (IS_ERR(base)) |
| 480 | return PTR_ERR(base); | 481 | return PTR_ERR(base); |
| 481 | 482 | ||
| @@ -255,24 +255,26 @@ static int st_dwc3_probe(struct platform_device *pdev) · 254 unmodified lines | |||
| 255 | if (!child) { | 255 | if (!child) { |
| 256 | dev_err(&pdev->dev, "failed to find dwc3 core node\n"); | 256 | dev_err(&pdev->dev, "failed to find dwc3 core node\n"); |
| 257 | ret = -ENODEV; | 257 | ret = -ENODEV; |
| 258 | goto undo_softreset; | 258 | goto err_node_put; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | /* Allocate and initialize the core */ | 261 | /* Allocate and initialize the core */ |
| 262 | ret = of_platform_populate(node, NULL, NULL, dev); | 262 | ret = of_platform_populate(node, NULL, NULL, dev); |
| 263 | if (ret) { | 263 | if (ret) { |
| 264 | dev_err(dev, "failed to add dwc3 core\n"); | 264 | dev_err(dev, "failed to add dwc3 core\n"); |
| 265 | goto undo_softreset; | 265 | goto err_node_put; |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | child_pdev = of_find_device_by_node(child); | 268 | child_pdev = of_find_device_by_node(child); |
| 269 | if (!child_pdev) { | 269 | if (!child_pdev) { |
| 270 | dev_err(dev, "failed to find dwc3 core device\n"); | 270 | dev_err(dev, "failed to find dwc3 core device\n"); |
| 271 | ret = -ENODEV; | 271 | ret = -ENODEV; |
| 272 | goto undo_softreset; | 272 | goto err_node_put; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev); | 275 | dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev); |
| 276 | of_node_put(child); | ||
| 277 | of_dev_put(child_pdev); | ||
| 276 | 278 | ||
| 277 | /* | 279 | /* |
| 278 | * Configure the USB port as device or host according to the static | 280 | * Configure the USB port as device or host according to the static |
| @@ -292,6 +294,8 @@ static int st_dwc3_probe(struct platform_device *pdev) · 13 unmodified lines | |||
| 292 | platform_set_drvdata(pdev, dwc3_data); | 294 | platform_set_drvdata(pdev, dwc3_data); |
| 293 | return 0; | 295 | return 0; |
| 294 | 296 | ||
| 297 | err_node_put: | ||
| 298 | of_node_put(child); | ||
| 295 | undo_softreset: | 299 | undo_softreset: |
| 296 | reset_control_assert(dwc3_data->rstc_rst); | 300 | reset_control_assert(dwc3_data->rstc_rst); |
| 297 | undo_powerdown: | 301 | undo_powerdown: |
| @@ -2078,6 +2078,26 @@ static void dwc3_gadget_config_params(struct usb_gadget *g, · 2077 unmodified lines | |||
| 2078 | { | 2078 | { |
| 2079 | struct dwc3 *dwc = gadget_to_dwc(g); | 2079 | struct dwc3 *dwc = gadget_to_dwc(g); |
| 2080 | 2080 | ||
| 2081 | params->besl_baseline = USB_DEFAULT_BESL_UNSPECIFIED; | ||
| 2082 | params->besl_deep = USB_DEFAULT_BESL_UNSPECIFIED; | ||
| 2083 | |||
| 2084 | /* Recommended BESL */ | ||
| 2085 | if (!dwc->dis_enblslpm_quirk) { | ||
| 2086 | /* | ||
| 2087 | * If the recommended BESL baseline is 0 or if the BESL deep is | ||
| 2088 | * less than 2, Microsoft's Windows 10 host usb stack will issue | ||
| 2089 | * a usb reset immediately after it receives the extended BOS | ||
| 2090 | * descriptor and the enumeration will fail. To maintain | ||
| 2091 | * compatibility with the Windows' usb stack, let's set the | ||
| 2092 | * recommended BESL baseline to 1 and clamp the BESL deep to be | ||
| 2093 | * within 2 to 15. | ||
| 2094 | */ | ||
| 2095 | params->besl_baseline = 1; | ||
| 2096 | if (dwc->is_utmi_l1_suspend) | ||
| 2097 | params->besl_deep = | ||
| 2098 | clamp_t(u8, dwc->hird_threshold, 2, 15); | ||
| 2099 | } | ||
| 2100 | |||
| 2081 | /* U1 Device exit Latency */ | 2101 | /* U1 Device exit Latency */ |
| 2082 | if (dwc->dis_u1_entry_quirk) | 2102 | if (dwc->dis_u1_entry_quirk) |
| 2083 | params->bU1devExitLat = 0; | 2103 | params->bU1devExitLat = 0; |
| @@ -2868,7 +2888,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) · 784 unmodified lines | |||
| 2868 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 2888 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 2869 | reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); | 2889 | reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); |
| 2870 | 2890 | ||
| 2871 | reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold); | 2891 | reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold | |
| 2892 | (dwc->is_utmi_l1_suspend << 4)); | ||
| 2872 | 2893 | ||
| 2873 | /* | 2894 | /* |
| 2874 | * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and | 2895 | * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and |
| @@ -3318,7 +3339,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 443 unmodified lines | |||
| 3318 | dwc->gadget.speed = USB_SPEED_UNKNOWN; | 3339 | dwc->gadget.speed = USB_SPEED_UNKNOWN; |
| 3319 | dwc->gadget.sg_supported = true; | 3340 | dwc->gadget.sg_supported = true; |
| 3320 | dwc->gadget.name = "dwc3-gadget"; | 3341 | dwc->gadget.name = "dwc3-gadget"; |
| 3321 | dwc->gadget.is_otg = dwc->dr_mode == USB_DR_MODE_OTG; | ||
| 3322 | dwc->gadget.lpm_capable = true; | 3342 | dwc->gadget.lpm_capable = true; |
| 3323 | 3343 | ||
| 3324 | /* | 3344 | /* |
| @@ -85,7 +85,7 @@ int dwc3_host_init(struct dwc3 *dwc) · 84 unmodified lines | |||
| 85 | DWC3_XHCI_RESOURCES_NUM); | 85 | DWC3_XHCI_RESOURCES_NUM); |
| 86 | if (ret) { | 86 | if (ret) { |
| 87 | dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); | 87 | dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); |
| 88 | goto err1; | 88 | goto err; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); | 91 | memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); |
| @@ -112,37 +112,23 @@ int dwc3_host_init(struct dwc3 *dwc) · 20 unmodified lines | |||
| 112 | ret = platform_device_add_properties(xhci, props); | 112 | ret = platform_device_add_properties(xhci, props); |
| 113 | if (ret) { | 113 | if (ret) { |
| 114 | dev_err(dwc->dev, "failed to add properties to xHCI\n"); | 114 | dev_err(dwc->dev, "failed to add properties to xHCI\n"); |
| 115 | goto err1; | 115 | goto err; |
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy", | ||
| 120 | dev_name(dwc->dev)); | ||
| 121 | phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy", | ||
| 122 | dev_name(dwc->dev)); | ||
| 123 | |||
| 124 | ret = platform_device_add(xhci); | 119 | ret = platform_device_add(xhci); |
| 125 | if (ret) { | 120 | if (ret) { |
| 126 | dev_err(dwc->dev, "failed to register xHCI device\n"); | 121 | dev_err(dwc->dev, "failed to register xHCI device\n"); |
| 127 | goto err2; | 122 | goto err; |
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | return 0; | 125 | return 0; |
| 131 | err2: | 126 | err: |
| 132 | phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", | ||
| 133 | dev_name(dwc->dev)); | ||
| 134 | phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", | ||
| 135 | dev_name(dwc->dev)); | ||
| 136 | err1: | ||
| 137 | platform_device_put(xhci); | 127 | platform_device_put(xhci); |
| 138 | return ret; | 128 | return ret; |
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | void dwc3_host_exit(struct dwc3 *dwc) | 131 | void dwc3_host_exit(struct dwc3 *dwc) |
| 142 | { | 132 | { |
| 143 | phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", | ||
| 144 | dev_name(dwc->dev)); | ||
| 145 | phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", | ||
| 146 | dev_name(dwc->dev)); | ||
| 147 | platform_device_unregister(dwc->xhci); | 133 | platform_device_unregister(dwc->xhci); |
| 148 | } | 134 | } |
| @@ -86,7 +86,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, · 85 unmodified lines | |||
| 86 | __entry->wIndex = le16_to_cpu(ctrl->wIndex); | 86 | __entry->wIndex = le16_to_cpu(ctrl->wIndex); |
| 87 | __entry->wLength = le16_to_cpu(ctrl->wLength); | 87 | __entry->wLength = le16_to_cpu(ctrl->wLength); |
| 88 | ), | 88 | ), |
| 89 | TP_printk("%s", dwc3_decode_ctrl(__get_str(str), DWC3_MSG_MAX, | 89 | TP_printk("%s", usb_decode_ctrl(__get_str(str), DWC3_MSG_MAX, |
| 90 | __entry->bRequestType, | 90 | __entry->bRequestType, |
| 91 | __entry->bRequest, __entry->wValue, | 91 | __entry->bRequest, __entry->wValue, |
| 92 | __entry->wIndex, __entry->wLength) | 92 | __entry->wIndex, __entry->wLength) |
| @@ -612,6 +612,7 @@ static int bos_desc(struct usb_composite_dev *cdev) · 611 unmodified lines | |||
| 612 | struct usb_ext_cap_descriptor *usb_ext; | 612 | struct usb_ext_cap_descriptor *usb_ext; |
| 613 | struct usb_dcd_config_params dcd_config_params; | 613 | struct usb_dcd_config_params dcd_config_params; |
| 614 | struct usb_bos_descriptor *bos = cdev->req->buf; | 614 | struct usb_bos_descriptor *bos = cdev->req->buf; |
| 615 | unsigned int besl = 0; | ||
| 615 | 616 | ||
| 616 | bos->bLength = USB_DT_BOS_SIZE; | 617 | bos->bLength = USB_DT_BOS_SIZE; |
| 617 | bos->bDescriptorType = USB_DT_BOS; | 618 | bos->bDescriptorType = USB_DT_BOS; |
| @@ -619,6 +620,29 @@ static int bos_desc(struct usb_composite_dev *cdev) · 1 unmodified line | |||
| 619 | bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE); | 620 | bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE); |
| 620 | bos->bNumDeviceCaps = 0; | 621 | bos->bNumDeviceCaps = 0; |
| 621 | 622 | ||
| 623 | /* Get Controller configuration */ | ||
| 624 | if (cdev->gadget->ops->get_config_params) { | ||
| 625 | cdev->gadget->ops->get_config_params(cdev->gadget, | ||
| 626 | &dcd_config_params); | ||
| 627 | } else { | ||
| 628 | dcd_config_params.besl_baseline = | ||
| 629 | USB_DEFAULT_BESL_UNSPECIFIED; | ||
| 630 | dcd_config_params.besl_deep = | ||
| 631 | USB_DEFAULT_BESL_UNSPECIFIED; | ||
| 632 | dcd_config_params.bU1devExitLat = | ||
| 633 | USB_DEFAULT_U1_DEV_EXIT_LAT; | ||
| 634 | dcd_config_params.bU2DevExitLat = | ||
| 635 | cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); | ||
| 636 | } | ||
| 637 | |||
| 638 | if (dcd_config_params.besl_baseline != USB_DEFAULT_BESL_UNSPECIFIED) | ||
| 639 | besl = USB_BESL_BASELINE_VALID | | ||
| 640 | USB_SET_BESL_BASELINE(dcd_config_params.besl_baseline); | ||
| 641 | |||
| 642 | if (dcd_config_params.besl_deep != USB_DEFAULT_BESL_UNSPECIFIED) | ||
| 643 | besl |= USB_BESL_DEEP_VALID | | ||
| 644 | USB_SET_BESL_DEEP(dcd_config_params.besl_deep); | ||
| 645 | |||
| 622 | /* | 646 | /* |
| 623 | * A SuperSpeed device shall include the USB2.0 extension descriptor | 647 | * A SuperSpeed device shall include the USB2.0 extension descriptor |
| 624 | * and shall support LPM when operating in USB2.0 HS mode. | 648 | * and shall support LPM when operating in USB2.0 HS mode. |
| @@ -629,7 +653,8 @@ static int bos_desc(struct usb_composite_dev *cdev) · 4 unmodified lines | |||
| 629 | usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; | 653 | usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; |
| 630 | usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; | 654 | usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; |
| 631 | usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; | 655 | usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; |
| 632 | usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT); | 656 | usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | |
| 657 | USB_BESL_SUPPORT | besl); | ||
| 633 | 658 | ||
| 634 | /* | 659 | /* |
| 635 | * The Superspeed USB Capability descriptor shall be implemented by all | 660 | * The Superspeed USB Capability descriptor shall be implemented by all |
| @@ -650,17 +675,6 @@ static int bos_desc(struct usb_composite_dev *cdev) · 14 unmodified lines | |||
| 650 | USB_HIGH_SPEED_OPERATION | | 675 | USB_HIGH_SPEED_OPERATION | |
| 651 | USB_5GBPS_OPERATION); | 676 | USB_5GBPS_OPERATION); |
| 652 | ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION; | 677 | ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION; |
| 653 | |||
| 654 | /* Get Controller configuration */ | ||
| 655 | if (cdev->gadget->ops->get_config_params) { | ||
| 656 | cdev->gadget->ops->get_config_params(cdev->gadget, | ||
| 657 | &dcd_config_params); | ||
| 658 | } else { | ||
| 659 | dcd_config_params.bU1devExitLat = | ||
| 660 | USB_DEFAULT_U1_DEV_EXIT_LAT; | ||
| 661 | dcd_config_params.bU2DevExitLat = | ||
| 662 | cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); | ||
| 663 | } | ||
| 664 | ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; | 678 | ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; |
| 665 | ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; | 679 | ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; |
| 666 | } | 680 | } |
| @@ -65,14 +65,16 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, · 64 unmodified lines | |||
| 65 | void ast_vhub_nuke(struct ast_vhub_ep *ep, int status) | 65 | void ast_vhub_nuke(struct ast_vhub_ep *ep, int status) |
| 66 | { | 66 | { |
| 67 | struct ast_vhub_req *req; | 67 | struct ast_vhub_req *req; |
| 68 | 68 | int count = 0; | |
| 69 | EPDBG(ep, "Nuking\n"); | ||
| 70 | 69 | ||
| 71 | /* Beware, lock will be dropped & req-acquired by done() */ | 70 | /* Beware, lock will be dropped & req-acquired by done() */ |
| 72 | while (!list_empty(&ep->queue)) { | 71 | while (!list_empty(&ep->queue)) { |
| 73 | req = list_first_entry(&ep->queue, struct ast_vhub_req, queue); | 72 | req = list_first_entry(&ep->queue, struct ast_vhub_req, queue); |
| 74 | ast_vhub_done(ep, req, status); | 73 | ast_vhub_done(ep, req, status); |
| 74 | count++; | ||
| 75 | } | 75 | } |
| 76 | if (count) | ||
| 77 | EPDBG(ep, "Nuked %d request(s)\n", count); | ||
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep, | 80 | struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep, |
| @@ -348,7 +350,6 @@ static int ast_vhub_probe(struct platform_device *pdev) · 269 unmodified lines | |||
| 348 | /* Find interrupt and install handler */ | 350 | /* Find interrupt and install handler */ |
| 349 | vhub->irq = platform_get_irq(pdev, 0); | 351 | vhub->irq = platform_get_irq(pdev, 0); |
| 350 | if (vhub->irq < 0) { | 352 | if (vhub->irq < 0) { |
| 351 | dev_err(&pdev->dev, "Failed to get interrupt\n"); | ||
| 352 | rc = vhub->irq; | 353 | rc = vhub->irq; |
| 353 | goto err; | 354 | goto err; |
| 354 | } | 355 | } |
| @@ -50,11 +50,14 @@ void ast_vhub_dev_irq(struct ast_vhub_dev *d) · 49 unmodified lines | |||
| 50 | 50 | ||
| 51 | static void ast_vhub_dev_enable(struct ast_vhub_dev *d) | 51 | static void ast_vhub_dev_enable(struct ast_vhub_dev *d) |
| 52 | { | 52 | { |
| 53 | u32 reg, hmsk; | 53 | u32 reg, hmsk, i; |
| 54 | 54 | ||
| 55 | if (d->enabled) | 55 | if (d->enabled) |
| 56 | return; | 56 | return; |
| 57 | 57 | ||
| 58 | /* Cleanup EP0 state */ | ||
| 59 | ast_vhub_reset_ep0(d); | ||
| 60 | |||
| 58 | /* Enable device and its EP0 interrupts */ | 61 | /* Enable device and its EP0 interrupts */ |
| 59 | reg = VHUB_DEV_EN_ENABLE_PORT | | 62 | reg = VHUB_DEV_EN_ENABLE_PORT | |
| 60 | VHUB_DEV_EN_EP0_IN_ACK_IRQEN | | 63 | VHUB_DEV_EN_EP0_IN_ACK_IRQEN | |
| @@ -73,6 +76,19 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d) · 12 unmodified lines | |||
| 73 | /* Set EP0 DMA buffer address */ | 76 | /* Set EP0 DMA buffer address */ |
| 74 | writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA); | 77 | writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA); |
| 75 | 78 | ||
| 79 | /* Clear stall on all EPs */ | ||
| 80 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { | ||
| 81 | struct ast_vhub_ep *ep = d->epns[i]; | ||
| 82 | |||
| 83 | if (ep && (ep->epn.stalled || ep->epn.wedged)) { | ||
| 84 | ep->epn.stalled = false; | ||
| 85 | ep->epn.wedged = false; | ||
| 86 | ast_vhub_update_epn_stall(ep); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | /* Additional cleanups */ | ||
| 91 | d->wakeup_en = false; | ||
| 76 | d->enabled = true; | 92 | d->enabled = true; |
| 77 | } | 93 | } |
| 78 | 94 | ||
| @@ -93,7 +109,6 @@ static void ast_vhub_dev_disable(struct ast_vhub_dev *d) · 14 unmodified lines | |||
| 93 | writel(0, d->regs + AST_VHUB_DEV_EN_CTRL); | 109 | writel(0, d->regs + AST_VHUB_DEV_EN_CTRL); |
| 94 | d->gadget.speed = USB_SPEED_UNKNOWN; | 110 | d->gadget.speed = USB_SPEED_UNKNOWN; |
| 95 | d->enabled = false; | 111 | d->enabled = false; |
| 96 | d->suspended = false; | ||
| 97 | } | 112 | } |
| 98 | 113 | ||
| 99 | static int ast_vhub_dev_feature(struct ast_vhub_dev *d, | 114 | static int ast_vhub_dev_feature(struct ast_vhub_dev *d, |
| @@ -201,14 +216,19 @@ int ast_vhub_std_dev_request(struct ast_vhub_ep *ep, · 101 unmodified lines | |||
| 201 | u16 wValue, wIndex; | 216 | u16 wValue, wIndex; |
| 202 | 217 | ||
| 203 | /* No driver, we shouldn't be enabled ... */ | 218 | /* No driver, we shouldn't be enabled ... */ |
| 204 | if (!d->driver || !d->enabled || d->suspended) { | 219 | if (!d->driver || !d->enabled) { |
| 205 | EPDBG(ep, | 220 | EPDBG(ep, |
| 206 | "Device is wrong state driver=%p enabled=%d" | 221 | "Device is wrong state driver=%p enabled=%d\n", |
| 207 | " suspended=%d\n", | 222 | d->driver, d->enabled); |
| 208 | d->driver, d->enabled, d->suspended); | ||
| 209 | return std_req_stall; | 223 | return std_req_stall; |
| 210 | } | 224 | } |
| 211 | 225 | ||
| 226 | /* | ||
| 227 | * Note: we used to reject/stall requests while suspended, | ||
| 228 | * we don't do that anymore as we seem to have cases of | ||
| 229 | * mass storage getting very upset. | ||
| 230 | */ | ||
| 231 | |||
| 212 | /* First packet, grab speed */ | 232 | /* First packet, grab speed */ |
| 213 | if (d->gadget.speed == USB_SPEED_UNKNOWN) { | 233 | if (d->gadget.speed == USB_SPEED_UNKNOWN) { |
| 214 | d->gadget.speed = ep->vhub->speed; | 234 | d->gadget.speed = ep->vhub->speed; |
| @@ -449,8 +469,7 @@ static const struct usb_gadget_ops ast_vhub_udc_ops = { · 234 unmodified lines | |||
| 449 | 469 | ||
| 450 | void ast_vhub_dev_suspend(struct ast_vhub_dev *d) | 470 | void ast_vhub_dev_suspend(struct ast_vhub_dev *d) |
| 451 | { | 471 | { |
| 452 | d->suspended = true; | 472 | if (d->driver && d->driver->suspend) { |
| 453 | if (d->driver) { | ||
| 454 | spin_unlock(&d->vhub->lock); | 473 | spin_unlock(&d->vhub->lock); |
| 455 | d->driver->suspend(&d->gadget); | 474 | d->driver->suspend(&d->gadget); |
| 456 | spin_lock(&d->vhub->lock); | 475 | spin_lock(&d->vhub->lock); |
| @@ -459,8 +478,7 @@ void ast_vhub_dev_suspend(struct ast_vhub_dev *d) · 2 unmodified lines | |||
| 459 | 478 | ||
| 460 | void ast_vhub_dev_resume(struct ast_vhub_dev *d) | 479 | void ast_vhub_dev_resume(struct ast_vhub_dev *d) |
| 461 | { | 480 | { |
| 462 | d->suspended = false; | 481 | if (d->driver && d->driver->resume) { |
| 463 | if (d->driver) { | ||
| 464 | spin_unlock(&d->vhub->lock); | 482 | spin_unlock(&d->vhub->lock); |
| 465 | d->driver->resume(&d->gadget); | 483 | d->driver->resume(&d->gadget); |
| 466 | spin_lock(&d->vhub->lock); | 484 | spin_lock(&d->vhub->lock); |
| @@ -469,46 +487,28 @@ void ast_vhub_dev_resume(struct ast_vhub_dev *d) · 2 unmodified lines | |||
| 469 | 487 | ||
| 470 | void ast_vhub_dev_reset(struct ast_vhub_dev *d) | 488 | void ast_vhub_dev_reset(struct ast_vhub_dev *d) |
| 471 | { | 489 | { |
| 472 | /* | 490 | /* No driver, just disable the device and return */ |
| 473 | * If speed is not set, we enable the port. If it is, | 491 | if (!d->driver) { |
| 474 | * send reset to the gadget and reset "speed". | 492 | ast_vhub_dev_disable(d); |
| 475 | * | 493 | return; |
| 476 | * Speed is an indication that we have got the first | ||
| 477 | * setup packet to the device. | ||
| 478 | */ | ||
| 479 | if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) { | ||
| 480 | DDBG(d, "Reset at unknown speed of disabled device, enabling...\n"); | ||
| 481 | ast_vhub_dev_enable(d); | ||
| 482 | d->suspended = false; | ||
| 483 | } | 494 | } |
| 484 | if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) { | ||
| 485 | unsigned int i; | ||
| 486 | 495 | ||
| 487 | DDBG(d, "Reset at known speed of bound device, resetting...\n"); | 496 | /* If the port isn't enabled, just enable it */ |
| 497 | if (!d->enabled) { | ||
| 498 | DDBG(d, "Reset of disabled device, enabling...\n"); | ||
| 499 | ast_vhub_dev_enable(d); | ||
| 500 | } else { | ||
| 501 | DDBG(d, "Reset of enabled device, resetting...\n"); | ||
| 488 | spin_unlock(&d->vhub->lock); | 502 | spin_unlock(&d->vhub->lock); |
| 489 | d->driver->reset(&d->gadget); | 503 | usb_gadget_udc_reset(&d->gadget, d->driver); |
| 490 | spin_lock(&d->vhub->lock); | 504 | spin_lock(&d->vhub->lock); |
| 491 | 505 | ||
| 492 | /* | 506 | /* |
| 493 | * Disable/re-enable HW, this will clear the address | 507 | * Disable and maybe re-enable HW, this will clear the address |
| 494 | * and speed setting. | 508 | * and speed setting. |
| 495 | */ | 509 | */ |
| 496 | ast_vhub_dev_disable(d); | 510 | ast_vhub_dev_disable(d); |
| 497 | ast_vhub_dev_enable(d); | 511 | ast_vhub_dev_enable(d); |
| 498 | |||
| 499 | /* Clear stall on all EPs */ | ||
| 500 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { | ||
| 501 | struct ast_vhub_ep *ep = d->epns[i]; | ||
| 502 | |||
| 503 | if (ep && ep->epn.stalled) { | ||
| 504 | ep->epn.stalled = false; | ||
| 505 | ast_vhub_update_epn_stall(ep); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | |||
| 509 | /* Additional cleanups */ | ||
| 510 | d->wakeup_en = false; | ||
| 511 | d->suspended = false; | ||
| 512 | } | 512 | } |
| 513 | } | 513 | } |
| 514 | 514 | ||
| @@ -105,18 +105,20 @@ void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep) · 104 unmodified lines | |||
| 105 | (crq.bRequestType & USB_DIR_IN) ? "in" : "out", | 105 | (crq.bRequestType & USB_DIR_IN) ? "in" : "out", |
| 106 | ep->ep0.state); | 106 | ep->ep0.state); |
| 107 | 107 | ||
| 108 | /* Check our state, cancel pending requests if needed */ | 108 | /* |
| 109 | if (ep->ep0.state != ep0_state_token) { | 109 | * Check our state, cancel pending requests if needed |
| 110 | * | ||
| 111 | * Note: Under some circumstances, we can get a new setup | ||
| 112 | * packet while waiting for the stall ack, just accept it. | ||
| 113 | * | ||
| 114 | * In any case, a SETUP packet in wrong state should have | ||
| 115 | * reset the HW state machine, so let's just log, nuke | ||
| 116 | * requests, move on. | ||
| 117 | */ | ||
| 118 | if (ep->ep0.state != ep0_state_token && | ||
| 119 | ep->ep0.state != ep0_state_stall) { | ||
| 110 | EPDBG(ep, "wrong state\n"); | 120 | EPDBG(ep, "wrong state\n"); |
| 111 | ast_vhub_nuke(ep, -EIO); | 121 | ast_vhub_nuke(ep, -EIO); |
| 112 | |||
| 113 | /* | ||
| 114 | * Accept the packet regardless, this seems to happen | ||
| 115 | * when stalling a SETUP packet that has an OUT data | ||
| 116 | * phase. | ||
| 117 | */ | ||
| 118 | ast_vhub_nuke(ep, 0); | ||
| 119 | goto stall; | ||
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | /* Calculate next state for EP0 */ | 124 | /* Calculate next state for EP0 */ |
| @@ -165,7 +167,7 @@ void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep) · 42 unmodified lines | |||
| 165 | stall: | 167 | stall: |
| 166 | EPDBG(ep, "stalling\n"); | 168 | EPDBG(ep, "stalling\n"); |
| 167 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); | 169 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); |
| 168 | ep->ep0.state = ep0_state_status; | 170 | ep->ep0.state = ep0_state_stall; |
| 169 | ep->ep0.dir_in = false; | 171 | ep->ep0.dir_in = false; |
| 170 | return; | 172 | return; |
| 171 | 173 | ||
| @@ -299,8 +301,8 @@ void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack) · 127 unmodified lines | |||
| 299 | if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) || | 301 | if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) || |
| 300 | (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) || | 302 | (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) || |
| 301 | (ep->ep0.dir_in != in_ack)) { | 303 | (ep->ep0.dir_in != in_ack)) { |
| 304 | /* In that case, ignore interrupt */ | ||
| 302 | dev_warn(dev, "irq state mismatch"); | 305 | dev_warn(dev, "irq state mismatch"); |
| 303 | stall = true; | ||
| 304 | break; | 306 | break; |
| 305 | } | 307 | } |
| 306 | /* | 308 | /* |
| @@ -335,12 +337,22 @@ void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack) · 28 unmodified lines | |||
| 335 | dev_warn(dev, "status direction mismatch\n"); | 337 | dev_warn(dev, "status direction mismatch\n"); |
| 336 | stall = true; | 338 | stall = true; |
| 337 | } | 339 | } |
| 340 | break; | ||
| 341 | case ep0_state_stall: | ||
| 342 | /* | ||
| 343 | * There shouldn't be any request left, but nuke just in case | ||
| 344 | * otherwise the stale request will block subsequent ones | ||
| 345 | */ | ||
| 346 | ast_vhub_nuke(ep, -EIO); | ||
| 347 | break; | ||
| 338 | } | 348 | } |
| 339 | 349 | ||
| 340 | /* Reset to token state */ | 350 | /* Reset to token state or stall */ |
| 341 | ep->ep0.state = ep0_state_token; | 351 | if (stall) { |
| 342 | if (stall) | ||
| 343 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); | 352 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); |
| 353 | ep->ep0.state = ep0_state_stall; | ||
| 354 | } else | ||
| 355 | ep->ep0.state = ep0_state_token; | ||
| 344 | } | 356 | } |
| 345 | 357 | ||
| 346 | static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, | 358 | static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, |
| @@ -367,7 +379,7 @@ static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, · 20 unmodified lines | |||
| 367 | return -EINVAL; | 379 | return -EINVAL; |
| 368 | 380 | ||
| 369 | /* Disabled device */ | 381 | /* Disabled device */ |
| 370 | if (ep->dev && (!ep->dev->enabled || ep->dev->suspended)) | 382 | if (ep->dev && !ep->dev->enabled) |
| 371 | return -ESHUTDOWN; | 383 | return -ESHUTDOWN; |
| 372 | 384 | ||
| 373 | /* Data, no buffer and not internal ? */ | 385 | /* Data, no buffer and not internal ? */ |
| @@ -390,8 +402,12 @@ static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, · 16 unmodified lines | |||
| 390 | spin_lock_irqsave(&vhub->lock, flags); | 402 | spin_lock_irqsave(&vhub->lock, flags); |
| 391 | 403 | ||
| 392 | /* EP0 can only support a single request at a time */ | 404 | /* EP0 can only support a single request at a time */ |
| 393 | if (!list_empty(&ep->queue) || ep->ep0.state == ep0_state_token) { | 405 | if (!list_empty(&ep->queue) || |
| 406 | ep->ep0.state == ep0_state_token || | ||
| 407 | ep->ep0.state == ep0_state_stall) { | ||
| 394 | dev_warn(dev, "EP0: Request in wrong state\n"); | 408 | dev_warn(dev, "EP0: Request in wrong state\n"); |
| 409 | EPVDBG(ep, "EP0: list_empty=%d state=%d\n", | ||
| 410 | list_empty(&ep->queue), ep->ep0.state); | ||
| 395 | spin_unlock_irqrestore(&vhub->lock, flags); | 411 | spin_unlock_irqrestore(&vhub->lock, flags); |
| 396 | return -EBUSY; | 412 | return -EBUSY; |
| 397 | } | 413 | } |
| @@ -459,6 +475,15 @@ static const struct usb_ep_ops ast_vhub_ep0_ops = { · 61 unmodified lines | |||
| 459 | .free_request = ast_vhub_free_request, | 475 | .free_request = ast_vhub_free_request, |
| 460 | }; | 476 | }; |
| 461 | 477 | ||
| 478 | void ast_vhub_reset_ep0(struct ast_vhub_dev *dev) | ||
| 479 | { | ||
| 480 | struct ast_vhub_ep *ep = &dev->ep0; | ||
| 481 | |||
| 482 | ast_vhub_nuke(ep, -EIO); | ||
| 483 | ep->ep0.state = ep0_state_token; | ||
| 484 | } | ||
| 485 | |||
| 486 | |||
| 462 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, | 487 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, |
| 463 | struct ast_vhub_dev *dev) | 488 | struct ast_vhub_dev *dev) |
| 464 | { | 489 | { |
| @@ -352,7 +352,7 @@ static int ast_vhub_epn_queue(struct usb_ep* u_ep, struct usb_request *u_req, · 351 unmodified lines | |||
| 352 | 352 | ||
| 353 | /* Endpoint enabled ? */ | 353 | /* Endpoint enabled ? */ |
| 354 | if (!ep->epn.enabled || !u_ep->desc || !ep->dev || !ep->d_idx || | 354 | if (!ep->epn.enabled || !u_ep->desc || !ep->dev || !ep->d_idx || |
| 355 | !ep->dev->enabled || ep->dev->suspended) { | 355 | !ep->dev->enabled) { |
| 356 | EPDBG(ep, "Enqueuing request on wrong or disabled EP\n"); | 356 | EPDBG(ep, "Enqueuing request on wrong or disabled EP\n"); |
| 357 | return -ESHUTDOWN; | 357 | return -ESHUTDOWN; |
| 358 | } | 358 | } |
| @@ -449,8 +449,15 @@ static void ast_vhub_change_port_stat(struct ast_vhub *vhub, · 448 unmodified lines | |||
| 449 | USB_PORT_STAT_C_OVERCURRENT | | 449 | USB_PORT_STAT_C_OVERCURRENT | |
| 450 | USB_PORT_STAT_C_RESET | | 450 | USB_PORT_STAT_C_RESET | |
| 451 | USB_PORT_STAT_C_L1; | 451 | USB_PORT_STAT_C_L1; |
| 452 | p->change |= chg; | ||
| 453 | 452 | ||
| 453 | /* | ||
| 454 | * We only set USB_PORT_STAT_C_ENABLE if we are disabling | ||
| 455 | * the port as per USB spec, otherwise MacOS gets upset | ||
| 456 | */ | ||
| 457 | if (p->status & USB_PORT_STAT_ENABLE) | ||
| 458 | chg &= ~USB_PORT_STAT_C_ENABLE; | ||
| 459 | |||
| 460 | p->change = chg; | ||
| 454 | ast_vhub_update_hub_ep1(vhub, port); | 461 | ast_vhub_update_hub_ep1(vhub, port); |
| 455 | } | 462 | } |
| 456 | } | 463 | } |
| @@ -723,6 +730,12 @@ enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep, · 266 unmodified lines | |||
| 723 | case ClearPortFeature: | 730 | case ClearPortFeature: |
| 724 | EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue); | 731 | EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue); |
| 725 | return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue); | 732 | return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue); |
| 733 | case ClearTTBuffer: | ||
| 734 | case ResetTT: | ||
| 735 | case StopTT: | ||
| 736 | return std_req_complete; | ||
| 737 | case GetTTState: | ||
| 738 | return ast_vhub_simple_reply(ep, 0, 0, 0, 0); | ||
| 726 | default: | 739 | default: |
| 727 | EPDBG(ep, "Unknown class request\n"); | 740 | EPDBG(ep, "Unknown class request\n"); |
| 728 | } | 741 | } |
| @@ -257,6 +257,7 @@ enum ep0_state { · 256 unmodified lines | |||
| 257 | ep0_state_token, | 257 | ep0_state_token, |
| 258 | ep0_state_data, | 258 | ep0_state_data, |
| 259 | ep0_state_status, | 259 | ep0_state_status, |
| 260 | ep0_state_stall, | ||
| 260 | }; | 261 | }; |
| 261 | 262 | ||
| 262 | /* | 263 | /* |
| @@ -353,7 +354,6 @@ struct ast_vhub_dev { · 90 unmodified lines | |||
| 353 | struct usb_gadget_driver *driver; | 354 | struct usb_gadget_driver *driver; |
| 354 | bool registered : 1; | 355 | bool registered : 1; |
| 355 | bool wakeup_en : 1; | 356 | bool wakeup_en : 1; |
| 356 | bool suspended : 1; | ||
| 357 | bool enabled : 1; | 357 | bool enabled : 1; |
| 358 | 358 | ||
| 359 | /* Endpoint structures */ | 359 | /* Endpoint structures */ |
| @@ -507,6 +507,7 @@ void ast_vhub_init_hw(struct ast_vhub *vhub); · 147 unmodified lines | |||
| 507 | /* ep0.c */ | 507 | /* ep0.c */ |
| 508 | void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack); | 508 | void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack); |
| 509 | void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep); | 509 | void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep); |
| 510 | void ast_vhub_reset_ep0(struct ast_vhub_dev *dev); | ||
| 510 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, | 511 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, |
| 511 | struct ast_vhub_dev *dev); | 512 | struct ast_vhub_dev *dev); |
| 512 | int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len); | 513 | int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len); |
| @@ -327,6 +327,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) · 326 unmodified lines | |||
| 327 | switch (fifo_mode) { | 327 | switch (fifo_mode) { |
| 328 | default: | 328 | default: |
| 329 | fifo_mode = 0; | 329 | fifo_mode = 0; |
| 330 | /* fall through */ | ||
| 330 | case 0: | 331 | case 0: |
| 331 | udc->fifo_cfg = NULL; | 332 | udc->fifo_cfg = NULL; |
| 332 | n = 0; | 333 | n = 0; |
| @@ -2328,10 +2328,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) · 2327 unmodified lines | |||
| 2328 | 2328 | ||
| 2329 | /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */ | 2329 | /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */ |
| 2330 | irq = platform_get_irq(pdev, 0); | 2330 | irq = platform_get_irq(pdev, 0); |
| 2331 | if (irq < 0) { | 2331 | if (irq < 0) |
| 2332 | dev_err(dev, "missing IRQ resource #0\n"); | ||
| 2333 | goto out_uninit; | 2332 | goto out_uninit; |
| 2334 | } | ||
| 2335 | if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0, | 2333 | if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0, |
| 2336 | dev_name(dev), udc) < 0) | 2334 | dev_name(dev), udc) < 0) |
| 2337 | goto report_request_failure; | 2335 | goto report_request_failure; |
| @@ -2339,10 +2337,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 2339 | /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */ | 2337 | /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */ |
| 2340 | for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { | 2338 | for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { |
| 2341 | irq = platform_get_irq(pdev, i + 1); | 2339 | irq = platform_get_irq(pdev, i + 1); |
| 2342 | if (irq < 0) { | 2340 | if (irq < 0) |
| 2343 | dev_err(dev, "missing IRQ resource #%d\n", i + 1); | ||
| 2344 | goto out_uninit; | 2341 | goto out_uninit; |
| 2345 | } | ||
| 2346 | if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0, | 2342 | if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0, |
| 2347 | dev_name(dev), &udc->iudma[i]) < 0) | 2343 | dev_name(dev), &udc->iudma[i]) < 0) |
| 2348 | goto report_request_failure; | 2344 | goto report_request_failure; |
| @@ -515,10 +515,8 @@ static int bdc_probe(struct platform_device *pdev) · 514 unmodified lines | |||
| 515 | return -ENOMEM; | 515 | return -ENOMEM; |
| 516 | } | 516 | } |
| 517 | irq = platform_get_irq(pdev, 0); | 517 | irq = platform_get_irq(pdev, 0); |
| 518 | if (irq < 0) { | 518 | if (irq < 0) |
| 519 | dev_err(dev, "platform_get_irq failed:%d\n", irq); | ||
| 520 | return irq; | 519 | return irq; |
| 521 | } | ||
| 522 | spin_lock_init(&bdc->lock); | 520 | spin_lock_init(&bdc->lock); |
| 523 | platform_set_drvdata(pdev, bdc); | 521 | platform_set_drvdata(pdev, bdc); |
| 524 | bdc->irq = irq; | 522 | bdc->irq = irq; |
| @@ -1143,7 +1143,7 @@ static int check_pending_gadget_drivers(struct usb_udc *udc) · 1142 unmodified lines | |||
| 1143 | dev_name(&udc->dev)) == 0) { | 1143 | dev_name(&udc->dev)) == 0) { |
| 1144 | ret = udc_bind_to_driver(udc, driver); | 1144 | ret = udc_bind_to_driver(udc, driver); |
| 1145 | if (ret != -EPROBE_DEFER) | 1145 | if (ret != -EPROBE_DEFER) |
| 1146 | list_del(&driver->pending); | 1146 | list_del_init(&driver->pending); |
| 1147 | break; | 1147 | break; |
| 1148 | } | 1148 | } |
| 1149 | 1149 | ||
| @@ -2134,19 +2134,15 @@ static int gr_probe(struct platform_device *pdev) · 2133 unmodified lines | |||
| 2134 | return PTR_ERR(regs); | 2134 | return PTR_ERR(regs); |
| 2135 | 2135 | ||
| 2136 | dev->irq = platform_get_irq(pdev, 0); | 2136 | dev->irq = platform_get_irq(pdev, 0); |
| 2137 | if (dev->irq <= 0) { | 2137 | if (dev->irq <= 0) |
| 2138 | dev_err(dev->dev, "No irq found\n"); | ||
| 2139 | return -ENODEV; | 2138 | return -ENODEV; |
| 2140 | } | ||
| 2141 | 2139 | ||
| 2142 | /* Some core configurations has separate irqs for IN and OUT events */ | 2140 | /* Some core configurations has separate irqs for IN and OUT events */ |
| 2143 | dev->irqi = platform_get_irq(pdev, 1); | 2141 | dev->irqi = platform_get_irq(pdev, 1); |
| 2144 | if (dev->irqi > 0) { | 2142 | if (dev->irqi > 0) { |
| 2145 | dev->irqo = platform_get_irq(pdev, 2); | 2143 | dev->irqo = platform_get_irq(pdev, 2); |
| 2146 | if (dev->irqo <= 0) { | 2144 | if (dev->irqo <= 0) |
| 2147 | dev_err(dev->dev, "Found irqi but not irqo\n"); | ||
| 2148 | return -ENODEV; | 2145 | return -ENODEV; |
| 2149 | } | ||
| 2150 | } else { | 2146 | } else { |
| 2151 | dev->irqi = 0; | 2147 | dev->irqi = 0; |
| 2152 | } | 2148 | } |
| @@ -741,7 +741,6 @@ static inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd, · 740 unmodified lines | |||
| 741 | * response data */ | 741 | * response data */ |
| 742 | static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd) | 742 | static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd) |
| 743 | { | 743 | { |
| 744 | u32 tmp; | ||
| 745 | int to = 1000; | 744 | int to = 1000; |
| 746 | 745 | ||
| 747 | /* Write a command and read data from the protocol engine */ | 746 | /* Write a command and read data from the protocol engine */ |
| @@ -751,7 +750,6 @@ static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd) · 3 unmodified lines | |||
| 751 | /* Write command code */ | 750 | /* Write command code */ |
| 752 | udc_protocol_cmd_w(udc, cmd); | 751 | udc_protocol_cmd_w(udc, cmd); |
| 753 | 752 | ||
| 754 | tmp = readl(USBD_DEVINTST(udc->udp_baseaddr)); | ||
| 755 | while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL)) | 753 | while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL)) |
| 756 | && (to > 0)) | 754 | && (to > 0)) |
| 757 | to--; | 755 | to--; |
| @@ -1991,7 +1989,7 @@ void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) · 1233 unmodified lines | |||
| 1991 | /* DMA end of transfer completion */ | 1989 | /* DMA end of transfer completion */ |
| 1992 | static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) | 1990 | static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) |
| 1993 | { | 1991 | { |
| 1994 | u32 status, epstatus; | 1992 | u32 status; |
| 1995 | struct lpc32xx_request *req; | 1993 | struct lpc32xx_request *req; |
| 1996 | struct lpc32xx_usbd_dd_gad *dd; | 1994 | struct lpc32xx_usbd_dd_gad *dd; |
| 1997 | 1995 | ||
| @@ -2085,7 +2083,7 @@ static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) · 87 unmodified lines | |||
| 2085 | if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) { | 2083 | if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) { |
| 2086 | udc_clearep_getsts(udc, ep->hwep_num); | 2084 | udc_clearep_getsts(udc, ep->hwep_num); |
| 2087 | uda_enable_hwepint(udc, ep->hwep_num); | 2085 | uda_enable_hwepint(udc, ep->hwep_num); |
| 2088 | epstatus = udc_clearep_getsts(udc, ep->hwep_num); | 2086 | udc_clearep_getsts(udc, ep->hwep_num); |
| 2089 | 2087 | ||
| 2090 | /* Let the EP interrupt handle the ZLP */ | 2088 | /* Let the EP interrupt handle the ZLP */ |
| 2091 | return; | 2089 | return; |
| @@ -2197,7 +2195,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc) · 105 unmodified lines | |||
| 2197 | struct lpc32xx_ep *ep, *ep0 = &udc->ep[0]; | 2195 | struct lpc32xx_ep *ep, *ep0 = &udc->ep[0]; |
| 2198 | struct usb_ctrlrequest ctrlpkt; | 2196 | struct usb_ctrlrequest ctrlpkt; |
| 2199 | int i, bytes; | 2197 | int i, bytes; |
| 2200 | u16 wIndex, wValue, wLength, reqtype, req, tmp; | 2198 | u16 wIndex, wValue, reqtype, req, tmp; |
| 2201 | 2199 | ||
| 2202 | /* Nuke previous transfers */ | 2200 | /* Nuke previous transfers */ |
| 2203 | nuke(ep0, -EPROTO); | 2201 | nuke(ep0, -EPROTO); |
| @@ -2213,7 +2211,6 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc) · 9 unmodified lines | |||
| 2213 | /* Native endianness */ | 2211 | /* Native endianness */ |
| 2214 | wIndex = le16_to_cpu(ctrlpkt.wIndex); | 2212 | wIndex = le16_to_cpu(ctrlpkt.wIndex); |
| 2215 | wValue = le16_to_cpu(ctrlpkt.wValue); | 2213 | wValue = le16_to_cpu(ctrlpkt.wValue); |
| 2216 | wLength = le16_to_cpu(ctrlpkt.wLength); | ||
| 2217 | reqtype = le16_to_cpu(ctrlpkt.bRequestType); | 2214 | reqtype = le16_to_cpu(ctrlpkt.bRequestType); |
| 2218 | 2215 | ||
| 2219 | /* Set direction of EP0 */ | 2216 | /* Set direction of EP0 */ |
| @@ -3060,11 +3057,8 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) · 840 unmodified lines | |||
| 3060 | /* Get IRQs */ | 3057 | /* Get IRQs */ |
| 3061 | for (i = 0; i < 4; i++) { | 3058 | for (i = 0; i < 4; i++) { |
| 3062 | udc->udp_irq[i] = platform_get_irq(pdev, i); | 3059 | udc->udp_irq[i] = platform_get_irq(pdev, i); |
| 3063 | if (udc->udp_irq[i] < 0) { | 3060 | if (udc->udp_irq[i] < 0) |
| 3064 | dev_err(udc->dev, | ||
| 3065 | "irq resource %d not available!\n", i); | ||
| 3066 | return udc->udp_irq[i]; | 3061 | return udc->udp_irq[i]; |
| 3067 | } | ||
| 3068 | } | 3062 | } |
| 3069 | 3063 | ||
| 3070 | udc->udp_baseaddr = devm_ioremap_resource(dev, res); | 3064 | udc->udp_baseaddr = devm_ioremap_resource(dev, res); |
| @@ -2244,30 +2244,40 @@ static void usb_reinit_338x(struct net2280 *dev) · 2243 unmodified lines | |||
| 2244 | } | 2244 | } |
| 2245 | 2245 | ||
| 2246 | /* Hardware Defect and Workaround */ | 2246 | /* Hardware Defect and Workaround */ |
| 2247 | val = readl(&dev->ll_lfps_regs->ll_lfps_5); | 2247 | val = readl(&dev->llregs->ll_lfps_5); |
| 2248 | val &= ~(0xf << TIMER_LFPS_6US); | 2248 | val &= ~(0xf << TIMER_LFPS_6US); |
| 2249 | val |= 0x5 << TIMER_LFPS_6US; | 2249 | val |= 0x5 << TIMER_LFPS_6US; |
| 2250 | writel(val, &dev->ll_lfps_regs->ll_lfps_5); | 2250 | writel(val, &dev->llregs->ll_lfps_5); |
| 2251 | 2251 | ||
| 2252 | val = readl(&dev->ll_lfps_regs->ll_lfps_6); | 2252 | val = readl(&dev->llregs->ll_lfps_6); |
| 2253 | val &= ~(0xffff << TIMER_LFPS_80US); | 2253 | val &= ~(0xffff << TIMER_LFPS_80US); |
| 2254 | val |= 0x0100 << TIMER_LFPS_80US; | 2254 | val |= 0x0100 << TIMER_LFPS_80US; |
| 2255 | writel(val, &dev->ll_lfps_regs->ll_lfps_6); | 2255 | writel(val, &dev->llregs->ll_lfps_6); |
| 2256 | 2256 | ||
| 2257 | /* | 2257 | /* |
| 2258 | * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB | 2258 | * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB |
| 2259 | * Hot Reset Exit Handshake may Fail in Specific Case using | 2259 | * Hot Reset Exit Handshake may Fail in Specific Case using |
| 2260 | * Default Register Settings. Workaround for Enumeration test. | 2260 | * Default Register Settings. Workaround for Enumeration test. |
| 2261 | */ | 2261 | */ |
| 2262 | val = readl(&dev->ll_tsn_regs->ll_tsn_counters_2); | 2262 | val = readl(&dev->llregs->ll_tsn_counters_2); |
| 2263 | val &= ~(0x1f << HOT_TX_NORESET_TS2); | 2263 | val &= ~(0x1f << HOT_TX_NORESET_TS2); |
| 2264 | val |= 0x10 << HOT_TX_NORESET_TS2; | 2264 | val |= 0x10 << HOT_TX_NORESET_TS2; |
| 2265 | writel(val, &dev->ll_tsn_regs->ll_tsn_counters_2); | 2265 | writel(val, &dev->llregs->ll_tsn_counters_2); |
| 2266 | 2266 | ||
| 2267 | val = readl(&dev->ll_tsn_regs->ll_tsn_counters_3); | 2267 | val = readl(&dev->llregs->ll_tsn_counters_3); |
| 2268 | val &= ~(0x1f << HOT_RX_RESET_TS2); | 2268 | val &= ~(0x1f << HOT_RX_RESET_TS2); |
| 2269 | val |= 0x3 << HOT_RX_RESET_TS2; | 2269 | val |= 0x3 << HOT_RX_RESET_TS2; |
| 2270 | writel(val, &dev->ll_tsn_regs->ll_tsn_counters_3); | 2270 | writel(val, &dev->llregs->ll_tsn_counters_3); |
| 2271 | |||
| 2272 | /* | ||
| 2273 | * AB errata. Errata 11. Workaround for Default Duration of LFPS | ||
| 2274 | * Handshake Signaling for Device-Initiated U1 Exit is too short. | ||
| 2275 | * Without this, various enumeration failures observed with | ||
| 2276 | * modern superspeed hosts. | ||
| 2277 | */ | ||
| 2278 | val = readl(&dev->llregs->ll_lfps_timers_2); | ||
| 2279 | writel((val & 0xffff0000) | LFPS_TIMERS_2_WORKAROUND_VALUE, | ||
| 2280 | &dev->llregs->ll_lfps_timers_2); | ||
| 2271 | 2281 | ||
| 2272 | /* | 2282 | /* |
| 2273 | * Set Recovery Idle to Recover bit: | 2283 | * Set Recovery Idle to Recover bit: |
| @@ -2276,10 +2286,10 @@ static void usb_reinit_338x(struct net2280 *dev) · 2 unmodified lines | |||
| 2276 | * - It is safe to set for all connection speeds; all chip revisions. | 2286 | * - It is safe to set for all connection speeds; all chip revisions. |
| 2277 | * - R-M-W to leave other bits undisturbed. | 2287 | * - R-M-W to leave other bits undisturbed. |
| 2278 | * - Reference PLX TT-7372 | 2288 | * - Reference PLX TT-7372 |
| 2279 | */ | 2289 | */ |
| 2280 | val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit); | 2290 | val = readl(&dev->llregs->ll_tsn_chicken_bit); |
| 2281 | val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW); | 2291 | val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW); |
| 2282 | writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit); | 2292 | writel(val, &dev->llregs->ll_tsn_chicken_bit); |
| 2283 | 2293 | ||
| 2284 | INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); | 2294 | INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); |
| 2285 | 2295 | ||
| @@ -3669,12 +3679,6 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 1383 unmodified lines | |||
| 3669 | (base + 0x00b4); | 3679 | (base + 0x00b4); |
| 3670 | dev->llregs = (struct usb338x_ll_regs __iomem *) | 3680 | dev->llregs = (struct usb338x_ll_regs __iomem *) |
| 3671 | (base + 0x0700); | 3681 | (base + 0x0700); |
| 3672 | dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *) | ||
| 3673 | (base + 0x0748); | ||
| 3674 | dev->ll_tsn_regs = (struct usb338x_ll_tsn_regs __iomem *) | ||
| 3675 | (base + 0x077c); | ||
| 3676 | dev->ll_chicken_reg = (struct usb338x_ll_chi_regs __iomem *) | ||
| 3677 | (base + 0x079c); | ||
| 3678 | dev->plregs = (struct usb338x_pl_regs __iomem *) | 3682 | dev->plregs = (struct usb338x_pl_regs __iomem *) |
| 3679 | (base + 0x0800); | 3683 | (base + 0x0800); |
| 3680 | usbstat = readl(&dev->usb->usbstat); | 3684 | usbstat = readl(&dev->usb->usbstat); |
| @@ -178,9 +178,6 @@ struct net2280 { · 177 unmodified lines | |||
| 178 | struct net2280_dep_regs __iomem *dep; | 178 | struct net2280_dep_regs __iomem *dep; |
| 179 | struct net2280_ep_regs __iomem *epregs; | 179 | struct net2280_ep_regs __iomem *epregs; |
| 180 | struct usb338x_ll_regs __iomem *llregs; | 180 | struct usb338x_ll_regs __iomem *llregs; |
| 181 | struct usb338x_ll_lfps_regs __iomem *ll_lfps_regs; | ||
| 182 | struct usb338x_ll_tsn_regs __iomem *ll_tsn_regs; | ||
| 183 | struct usb338x_ll_chi_regs __iomem *ll_chicken_reg; | ||
| 184 | struct usb338x_pl_regs __iomem *plregs; | 181 | struct usb338x_pl_regs __iomem *plregs; |
| 185 | 182 | ||
| 186 | struct dma_pool *requests; | 183 | struct dma_pool *requests; |
| @@ -3046,8 +3046,7 @@ static void pch_udc_remove(struct pci_dev *pdev) · 3045 unmodified lines | |||
| 3046 | #ifdef CONFIG_PM_SLEEP | 3046 | #ifdef CONFIG_PM_SLEEP |
| 3047 | static int pch_udc_suspend(struct device *d) | 3047 | static int pch_udc_suspend(struct device *d) |
| 3048 | { | 3048 | { |
| 3049 | struct pci_dev *pdev = to_pci_dev(d); | 3049 | struct pch_udc_dev *dev = dev_get_drvdata(d); |
| 3050 | struct pch_udc_dev *dev = pci_get_drvdata(pdev); | ||
| 3051 | 3050 | ||
| 3052 | pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); | 3051 | pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); |
| 3053 | pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL); | 3052 | pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL); |
| @@ -2744,10 +2744,8 @@ static int renesas_usb3_probe(struct platform_device *pdev) · 2743 unmodified lines | |||
| 2744 | priv = of_device_get_match_data(&pdev->dev); | 2744 | priv = of_device_get_match_data(&pdev->dev); |
| 2745 | 2745 | ||
| 2746 | irq = platform_get_irq(pdev, 0); | 2746 | irq = platform_get_irq(pdev, 0); |
| 2747 | if (irq < 0) { | 2747 | if (irq < 0) |
| 2748 | dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); | ||
| 2749 | return irq; | 2748 | return irq; |
| 2750 | } | ||
| 2751 | 2749 | ||
| 2752 | usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); | 2750 | usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); |
| 2753 | if (!usb3) | 2751 | if (!usb3) |
| @@ -1311,10 +1311,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) · 1310 unmodified lines | |||
| 1311 | s3c_hsudc_setup_ep(hsudc); | 1311 | s3c_hsudc_setup_ep(hsudc); |
| 1312 | 1312 | ||
| 1313 | ret = platform_get_irq(pdev, 0); | 1313 | ret = platform_get_irq(pdev, 0); |
| 1314 | if (ret < 0) { | 1314 | if (ret < 0) |
| 1315 | dev_err(dev, "unable to obtain IRQ number\n"); | ||
| 1316 | goto err_res; | 1315 | goto err_res; |
| 1317 | } | ||
| 1318 | hsudc->irq = ret; | 1316 | hsudc->irq = ret; |
| 1319 | 1317 | ||
| 1320 | ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0, | 1318 | ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0, |
| @@ -312,6 +312,7 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, · 311 unmodified lines | |||
| 312 | switch (idx) { | 312 | switch (idx) { |
| 313 | default: | 313 | default: |
| 314 | idx = 0; | 314 | idx = 0; |
| 315 | /* fall through */ | ||
| 315 | case 0: | 316 | case 0: |
| 316 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; | 317 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; |
| 317 | break; | 318 | break; |
| @@ -416,6 +417,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, · 98 unmodified lines | |||
| 416 | switch (idx) { | 417 | switch (idx) { |
| 417 | default: | 418 | default: |
| 418 | idx = 0; | 419 | idx = 0; |
| 420 | /* fall through */ | ||
| 419 | case 0: | 421 | case 0: |
| 420 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; | 422 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; |
| 421 | break; | 423 | break; |
| @@ -2074,10 +2074,8 @@ static int xudc_probe(struct platform_device *pdev) · 2073 unmodified lines | |||
| 2074 | return PTR_ERR(udc->addr); | 2074 | return PTR_ERR(udc->addr); |
| 2075 | 2075 | ||
| 2076 | irq = platform_get_irq(pdev, 0); | 2076 | irq = platform_get_irq(pdev, 0); |
| 2077 | if (irq < 0) { | 2077 | if (irq < 0) |
| 2078 | dev_err(&pdev->dev, "unable to get irq\n"); | ||
| 2079 | return irq; | 2078 | return irq; |
| 2080 | } | ||
| 2081 | ret = devm_request_irq(&pdev->dev, irq, xudc_irq, 0, | 2079 | ret = devm_request_irq(&pdev->dev, irq, xudc_irq, 0, |
| 2082 | dev_name(&pdev->dev), udc); | 2080 | dev_name(&pdev->dev), udc); |
| 2083 | if (ret < 0) { | 2081 | if (ret < 0) { |
| @@ -287,12 +287,6 @@ config USB_EHCI_MV · 286 unmodified lines | |||
| 287 | Dova, Armada 370 and Armada XP. See "Support for Marvell EBU | 287 | Dova, Armada 370 and Armada XP. See "Support for Marvell EBU |
| 288 | on-chip EHCI USB controller" for those. | 288 | on-chip EHCI USB controller" for those. |
| 289 | 289 | ||
| 290 | config USB_W90X900_EHCI | ||
| 291 | tristate "W90X900(W90P910) EHCI support" | ||
| 292 | depends on ARCH_W90X900 | ||
| 293 | ---help--- | ||
| 294 | Enables support for the W90X900 USB controller | ||
| 295 | |||
| 296 | config USB_CNS3XXX_EHCI | 290 | config USB_CNS3XXX_EHCI |
| 297 | bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" | 291 | bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" |
| 298 | depends on ARCH_CNS3XXX | 292 | depends on ARCH_CNS3XXX |
| @@ -718,32 +712,6 @@ config USB_RENESAS_USBHS_HCD · 419 unmodified lines | |||
| 718 | To compile this driver as a module, choose M here: the | 712 | To compile this driver as a module, choose M here: the |
| 719 | module will be called renesas-usbhs. | 713 | module will be called renesas-usbhs. |
| 720 | 714 | ||
| 721 | config USB_WHCI_HCD | ||
| 722 | tristate "Wireless USB Host Controller Interface (WHCI) driver" | ||
| 723 | depends on USB_PCI && USB && UWB | ||
| 724 | select USB_WUSB | ||
| 725 | select UWB_WHCI | ||
| 726 | help | ||
| 727 | A driver for PCI-based Wireless USB Host Controllers that are | ||
| 728 | compliant with the WHCI specification. | ||
| 729 | |||
| 730 | To compile this driver a module, choose M here: the module | ||
| 731 | will be called "whci-hcd". | ||
| 732 | |||
| 733 | config USB_HWA_HCD | ||
| 734 | tristate "Host Wire Adapter (HWA) driver" | ||
| 735 | depends on USB && UWB | ||
| 736 | select USB_WUSB | ||
| 737 | select UWB_HWA | ||
| 738 | help | ||
| 739 | This driver enables you to connect Wireless USB devices to | ||
| 740 | your system using a Host Wire Adaptor USB dongle. This is an | ||
| 741 | UWB Radio Controller and WUSB Host Controller connected to | ||
| 742 | your machine via USB (specified in WUSB1.0). | ||
| 743 | |||
| 744 | To compile this driver a module, choose M here: the module | ||
| 745 | will be called "hwa-hc". | ||
| 746 | |||
| 747 | config USB_IMX21_HCD | 715 | config USB_IMX21_HCD |
| 748 | tristate "i.MX21 HCD support" | 716 | tristate "i.MX21 HCD support" |
| 749 | depends on ARM && ARCH_MXC | 717 | depends on ARM && ARCH_MXC |
| @@ -35,8 +35,6 @@ ifneq ($(CONFIG_DEBUG_FS),) · 34 unmodified lines | |||
| 35 | xhci-hcd-y += xhci-debugfs.o | 35 | xhci-hcd-y += xhci-debugfs.o |
| 36 | endif | 36 | endif |
| 37 | 37 | ||
| 38 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ | ||
| 39 | |||
| 40 | obj-$(CONFIG_USB_PCI) += pci-quirks.o | 38 | obj-$(CONFIG_USB_PCI) += pci-quirks.o |
| 41 | 39 | ||
| 42 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 40 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
| @@ -51,7 +49,6 @@ obj-$(CONFIG_USB_EHCI_HCD_STI) += ehci-st.o · 8 unmodified lines | |||
| 51 | obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o | 49 | obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o |
| 52 | obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o | 50 | obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o |
| 53 | obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o | 51 | obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o |
| 54 | obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o | ||
| 55 | 52 | ||
| 56 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | 53 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o |
| 57 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 54 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
| @@ -82,7 +79,6 @@ obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o · 24 unmodified lines | |||
| 82 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o | 79 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o |
| 83 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o | 80 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o |
| 84 | obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o | 81 | obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o |
| 85 | obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o | ||
| 86 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o | 82 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o |
| 87 | obj-$(CONFIG_USB_FSL_USB2) += fsl-mph-dr-of.o | 83 | obj-$(CONFIG_USB_FSL_USB2) += fsl-mph-dr-of.o |
| 88 | obj-$(CONFIG_USB_EHCI_FSL) += fsl-mph-dr-of.o | 84 | obj-$(CONFIG_USB_EHCI_FSL) += fsl-mph-dr-of.o |
| @@ -100,9 +100,6 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) · 99 unmodified lines | |||
| 100 | 100 | ||
| 101 | irq = platform_get_irq(pdev, 0); | 101 | irq = platform_get_irq(pdev, 0); |
| 102 | if (irq <= 0) { | 102 | if (irq <= 0) { |
| 103 | dev_err(&pdev->dev, | ||
| 104 | "Found HC with no IRQ. Check %s setup!\n", | ||
| 105 | dev_name(&pdev->dev)); | ||
| 106 | retval = -ENODEV; | 103 | retval = -ENODEV; |
| 107 | goto fail_create_hcd; | 104 | goto fail_create_hcd; |
| 108 | } | 105 | } |
| @@ -41,6 +41,7 @@ struct exynos_ehci_hcd { · 40 unmodified lines | |||
| 41 | struct clk *clk; | 41 | struct clk *clk; |
| 42 | struct device_node *of_node; | 42 | struct device_node *of_node; |
| 43 | struct phy *phy[PHY_NUMBER]; | 43 | struct phy *phy[PHY_NUMBER]; |
| 44 | bool legacy_phy; | ||
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) | 47 | #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) |
| @@ -50,10 +51,22 @@ static int exynos_ehci_get_phy(struct device *dev, · 3 unmodified lines | |||
| 50 | { | 51 | { |
| 51 | struct device_node *child; | 52 | struct device_node *child; |
| 52 | struct phy *phy; | 53 | struct phy *phy; |
| 53 | int phy_number; | 54 | int phy_number, num_phys; |
| 54 | int ret; | 55 | int ret; |
| 55 | 56 | ||
| 56 | /* Get PHYs for the controller */ | 57 | /* Get PHYs for the controller */ |
| 58 | num_phys = of_count_phandle_with_args(dev->of_node, "phys", | ||
| 59 | "#phy-cells"); | ||
| 60 | for (phy_number = 0; phy_number < num_phys; phy_number++) { | ||
| 61 | phy = devm_of_phy_get_by_index(dev, dev->of_node, phy_number); | ||
| 62 | if (IS_ERR(phy)) | ||
| 63 | return PTR_ERR(phy); | ||
| 64 | exynos_ehci->phy[phy_number] = phy; | ||
| 65 | } | ||
| 66 | if (num_phys > 0) | ||
| 67 | return 0; | ||
| 68 | |||
| 69 | /* Get PHYs using legacy bindings */ | ||
| 57 | for_each_available_child_of_node(dev->of_node, child) { | 70 | for_each_available_child_of_node(dev->of_node, child) { |
| 58 | ret = of_property_read_u32(child, "reg", &phy_number); | 71 | ret = of_property_read_u32(child, "reg", &phy_number); |
| 59 | if (ret) { | 72 | if (ret) { |
| @@ -84,6 +97,7 @@ static int exynos_ehci_get_phy(struct device *dev, · 24 unmodified lines | |||
| 84 | } | 97 | } |
| 85 | } | 98 | } |
| 86 | 99 | ||
| 100 | exynos_ehci->legacy_phy = true; | ||
| 87 | return 0; | 101 | return 0; |
| 88 | } | 102 | } |
| 89 | 103 | ||
| @@ -205,11 +219,12 @@ static int exynos_ehci_probe(struct platform_device *pdev) · 115 unmodified lines | |||
| 205 | ehci->caps = hcd->regs; | 219 | ehci->caps = hcd->regs; |
| 206 | 220 | ||
| 207 | /* | 221 | /* |
| 208 | * Workaround: reset of_node pointer to avoid conflict between Exynos | 222 | * Workaround: reset of_node pointer to avoid conflict between legacy |
| 209 | * EHCI port subnodes and generic USB device bindings | 223 | * Exynos EHCI port subnodes and generic USB device bindings |
| 210 | */ | 224 | */ |
| 211 | exynos_ehci->of_node = pdev->dev.of_node; | 225 | exynos_ehci->of_node = pdev->dev.of_node; |
| 212 | pdev->dev.of_node = NULL; | 226 | if (exynos_ehci->legacy_phy) |
| 227 | pdev->dev.of_node = NULL; | ||
| 213 | 228 | ||
| 214 | /* DMA burst Enable */ | 229 | /* DMA burst Enable */ |
| 215 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); | 230 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); |
| @@ -30,7 +30,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { · 29 unmodified lines | |||
| 30 | * generic hardware linkage | 30 | * generic hardware linkage |
| 31 | */ | 31 | */ |
| 32 | .irq = ehci_irq, | 32 | .irq = ehci_irq, |
| 33 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 33 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| 36 | * basic lifecycle operations | 36 | * basic lifecycle operations |
| @@ -1193,7 +1193,7 @@ static const struct hc_driver ehci_hc_driver = { · 1192 unmodified lines | |||
| 1193 | * generic hardware linkage | 1193 | * generic hardware linkage |
| 1194 | */ | 1194 | */ |
| 1195 | .irq = ehci_irq, | 1195 | .irq = ehci_irq, |
| 1196 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 1196 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 1197 | 1197 | ||
| 1198 | /* | 1198 | /* |
| 1199 | * basic lifecycle operations | 1199 | * basic lifecycle operations |
| @@ -115,10 +115,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) · 114 unmodified lines | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | irq = platform_get_irq(pdev, 0); | 117 | irq = platform_get_irq(pdev, 0); |
| 118 | if (irq < 0) { | 118 | if (irq < 0) |
| 119 | dev_err(dev, "EHCI irq failed: %d\n", irq); | ||
| 120 | return irq; | 119 | return irq; |
| 121 | } | ||
| 122 | 120 | ||
| 123 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 121 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 124 | regs = devm_ioremap_resource(dev, res); | 122 | regs = devm_ioremap_resource(dev, res); |
| @@ -223,9 +223,6 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) · 222 unmodified lines | |||
| 223 | 223 | ||
| 224 | irq = platform_get_irq(pdev, 0); | 224 | irq = platform_get_irq(pdev, 0); |
| 225 | if (irq <= 0) { | 225 | if (irq <= 0) { |
| 226 | dev_err(&pdev->dev, | ||
| 227 | "Found HC with no IRQ. Check %s setup!\n", | ||
| 228 | dev_name(&pdev->dev)); | ||
| 229 | err = -ENODEV; | 226 | err = -ENODEV; |
| 230 | goto err; | 227 | goto err; |
| 231 | } | 228 | } |
| @@ -145,10 +145,8 @@ static int ehci_platform_probe(struct platform_device *dev) · 144 unmodified lines | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | irq = platform_get_irq(dev, 0); | 147 | irq = platform_get_irq(dev, 0); |
| 148 | if (irq < 0) { | 148 | if (irq < 0) |
| 149 | dev_err(&dev->dev, "no irq provided"); | ||
| 150 | return irq; | 149 | return irq; |
| 151 | } | ||
| 152 | 150 | ||
| 153 | hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, | 151 | hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, |
| 154 | dev_name(&dev->dev)); | 152 | dev_name(&dev->dev)); |
| @@ -250,7 +250,7 @@ static const struct hc_driver ehci_msp_hc_driver = { · 249 unmodified lines | |||
| 250 | * generic hardware linkage | 250 | * generic hardware linkage |
| 251 | */ | 251 | */ |
| 252 | .irq = ehci_irq, | 252 | .irq = ehci_irq, |
| 253 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 253 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 254 | 254 | ||
| 255 | /* | 255 | /* |
| 256 | * basic lifecycle operations | 256 | * basic lifecycle operations |
| @@ -31,7 +31,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { · 30 unmodified lines | |||
| 31 | * generic hardware linkage | 31 | * generic hardware linkage |
| 32 | */ | 32 | */ |
| 33 | .irq = ehci_irq, | 33 | .irq = ehci_irq, |
| 34 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 34 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 35 | 35 | ||
| 36 | /* | 36 | /* |
| 37 | * basic lifecycle operations | 37 | * basic lifecycle operations |
| @@ -59,7 +59,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { · 58 unmodified lines | |||
| 59 | .product_desc = "PS3 EHCI Host Controller", | 59 | .product_desc = "PS3 EHCI Host Controller", |
| 60 | .hcd_priv_size = sizeof(struct ehci_hcd), | 60 | .hcd_priv_size = sizeof(struct ehci_hcd), |
| 61 | .irq = ehci_irq, | 61 | .irq = ehci_irq, |
| 62 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 62 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 63 | .reset = ps3_ehci_hc_reset, | 63 | .reset = ps3_ehci_hc_reset, |
| 64 | .start = ehci_run, | 64 | .start = ehci_run, |
| 65 | .stop = ehci_stop, | 65 | .stop = ehci_stop, |
| @@ -33,7 +33,7 @@ static const struct hc_driver ehci_sh_hc_driver = { · 32 unmodified lines | |||
| 33 | * generic hardware linkage | 33 | * generic hardware linkage |
| 34 | */ | 34 | */ |
| 35 | .irq = ehci_irq, | 35 | .irq = ehci_irq, |
| 36 | .flags = HCD_USB2 | HCD_MEMORY | HCD_BH, | 36 | .flags = HCD_USB2 | HCD_DMA | HCD_MEMORY | HCD_BH, |
| 37 | 37 | ||
| 38 | /* | 38 | /* |
| 39 | * basic lifecycle operations | 39 | * basic lifecycle operations |
| @@ -85,9 +85,6 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) · 45 unmodified lines | |||
| 85 | 85 | ||
| 86 | irq = platform_get_irq(pdev, 0); | 86 | irq = platform_get_irq(pdev, 0); |
| 87 | if (irq <= 0) { | 87 | if (irq <= 0) { |
| 88 | dev_err(&pdev->dev, | ||
| 89 | "Found HC with no IRQ. Check %s setup!\n", | ||
| 90 | dev_name(&pdev->dev)); | ||
| 91 | ret = -ENODEV; | 88 | ret = -ENODEV; |
| 92 | goto fail_create_hcd; | 89 | goto fail_create_hcd; |
| 93 | } | 90 | } |
| @@ -158,10 +158,8 @@ static int st_ehci_platform_probe(struct platform_device *dev) · 157 unmodified lines | |||
| 158 | return -ENODEV; | 158 | return -ENODEV; |
| 159 | 159 | ||
| 160 | irq = platform_get_irq(dev, 0); | 160 | irq = platform_get_irq(dev, 0); |
| 161 | if (irq < 0) { | 161 | if (irq < 0) |
| 162 | dev_err(&dev->dev, "no irq provided"); | ||
| 163 | return irq; | 162 | return irq; |
| 164 | } | ||
| 165 | res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); | 163 | res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); |
| 166 | if (!res_mem) { | 164 | if (!res_mem) { |
| 167 | dev_err(&dev->dev, "no memory resource provided"); | 165 | dev_err(&dev->dev, "no memory resource provided"); |
| @@ -1,130 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * linux/driver/usb/host/ehci-w90x900.c | ||
| 4 | * | ||
| 5 | * Copyright (c) 2008 Nuvoton technology corporation. | ||
| 6 | * | ||
| 7 | * Wan ZongShun <mcuos.com@gmail.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/dma-mapping.h> | ||
| 11 | #include <linux/io.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/of.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/usb.h> | ||
| 17 | #include <linux/usb/hcd.h> | ||
| 18 | |||
| 19 | #include "ehci.h" | ||
| 20 | |||
| 21 | /* enable phy0 and phy1 for w90p910 */ | ||
| 22 | #define ENPHY (0x01<<8) | ||
| 23 | #define PHY0_CTR (0xA4) | ||
| 24 | #define PHY1_CTR (0xA8) | ||
| 25 | |||
| 26 | #define DRIVER_DESC "EHCI w90x900 driver" | ||
| 27 | |||
| 28 | static const char hcd_name[] = "ehci-w90x900 "; | ||
| 29 | |||
| 30 | static struct hc_driver __read_mostly ehci_w90x900_hc_driver; | ||
| 31 | |||
| 32 | static int ehci_w90x900_probe(struct platform_device *pdev) | ||
| 33 | { | ||
| 34 | struct usb_hcd *hcd; | ||
| 35 | struct ehci_hcd *ehci; | ||
| 36 | struct resource *res; | ||
| 37 | int retval = 0, irq; | ||
| 38 | unsigned long val; | ||
| 39 | |||
| 40 | hcd = usb_create_hcd(&ehci_w90x900_hc_driver, | ||
| 41 | &pdev->dev, "w90x900 EHCI"); | ||
| 42 | if (!hcd) { | ||
| 43 | retval = -ENOMEM; | ||
| 44 | goto err1; | ||
| 45 | } | ||
| 46 | |||
| 47 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 48 | hcd->regs = devm_ioremap_resource(&pdev->dev, res); | ||
| 49 | if (IS_ERR(hcd->regs)) { | ||
| 50 | retval = PTR_ERR(hcd->regs); | ||
| 51 | goto err2; | ||
| 52 | } | ||
| 53 | hcd->rsrc_start = res->start; | ||
| 54 | hcd->rsrc_len = resource_size(res); | ||
| 55 | |||
| 56 | ehci = hcd_to_ehci(hcd); | ||
| 57 | ehci->caps = hcd->regs; | ||
| 58 | ehci->regs = hcd->regs + | ||
| 59 | HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
| 60 | |||
| 61 | /* enable PHY 0,1,the regs only apply to w90p910 | ||
| 62 | * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of | ||
| 63 | * w90p910 IC relative to ehci->regs. | ||
| 64 | */ | ||
| 65 | val = __raw_readl(ehci->regs+PHY0_CTR); | ||
| 66 | val |= ENPHY; | ||
| 67 | __raw_writel(val, ehci->regs+PHY0_CTR); | ||
| 68 | |||
| 69 | val = __raw_readl(ehci->regs+PHY1_CTR); | ||
| 70 | val |= ENPHY; | ||
| 71 | __raw_writel(val, ehci->regs+PHY1_CTR); | ||
| 72 | |||
| 73 | irq = platform_get_irq(pdev, 0); | ||
| 74 | if (irq < 0) { | ||
| 75 | retval = irq; | ||
| 76 | goto err2; | ||
| 77 | } | ||
| 78 | |||
| 79 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
| 80 | if (retval != 0) | ||
| 81 | goto err2; | ||
| 82 | |||
| 83 | device_wakeup_enable(hcd->self.controller); | ||
| 84 | return retval; | ||
| 85 | err2: | ||
| 86 | usb_put_hcd(hcd); | ||
| 87 | err1: | ||
| 88 | return retval; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int ehci_w90x900_remove(struct platform_device *pdev) | ||
| 92 | { | ||
| 93 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 94 | |||
| 95 | usb_remove_hcd(hcd); | ||
| 96 | usb_put_hcd(hcd); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static struct platform_driver ehci_hcd_w90x900_driver = { | ||
| 102 | .probe = ehci_w90x900_probe, | ||
| 103 | .remove = ehci_w90x900_remove, | ||
| 104 | .driver = { | ||
| 105 | .name = "w90x900-ehci", | ||
| 106 | }, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int __init ehci_w90X900_init(void) | ||
| 110 | { | ||
| 111 | if (usb_disabled()) | ||
| 112 | return -ENODEV; | ||
| 113 | |||
| 114 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
| 115 | |||
| 116 | ehci_init_driver(&ehci_w90x900_hc_driver, NULL); | ||
| 117 | return platform_driver_register(&ehci_hcd_w90x900_driver); | ||
| 118 | } | ||
| 119 | module_init(ehci_w90X900_init); | ||
| 120 | |||
| 121 | static void __exit ehci_w90X900_cleanup(void) | ||
| 122 | { | ||
| 123 | platform_driver_unregister(&ehci_hcd_w90x900_driver); | ||
| 124 | } | ||
| 125 | module_exit(ehci_w90X900_cleanup); | ||
| 126 | |||
| 127 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 128 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
| 129 | MODULE_ALIAS("platform:w90p910-ehci"); | ||
| 130 | MODULE_LICENSE("GPL v2"); | ||
| @@ -66,7 +66,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { · 65 unmodified lines | |||
| 66 | * generic hardware linkage | 66 | * generic hardware linkage |
| 67 | */ | 67 | */ |
| 68 | .irq = ehci_irq, | 68 | .irq = ehci_irq, |
| 69 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | 69 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, |
| 70 | 70 | ||
| 71 | /* | 71 | /* |
| 72 | * basic lifecycle operations | 72 | * basic lifecycle operations |
| @@ -538,7 +538,7 @@ static const struct hc_driver fhci_driver = { · 537 unmodified lines | |||
| 538 | 538 | ||
| 539 | /* generic hardware linkage */ | 539 | /* generic hardware linkage */ |
| 540 | .irq = fhci_irq, | 540 | .irq = fhci_irq, |
| 541 | .flags = HCD_USB11 | HCD_MEMORY, | 541 | .flags = HCD_DMA | HCD_USB11 | HCD_MEMORY, |
| 542 | 542 | ||
| 543 | /* basic lifecycle operation */ | 543 | /* basic lifecycle operation */ |
| 544 | .start = fhci_start, | 544 | .start = fhci_start, |
| @@ -5508,7 +5508,7 @@ static const struct hc_driver fotg210_fotg210_hc_driver = { · 5507 unmodified lines | |||
| 5508 | * generic hardware linkage | 5508 | * generic hardware linkage |
| 5509 | */ | 5509 | */ |
| 5510 | .irq = fotg210_irq, | 5510 | .irq = fotg210_irq, |
| 5511 | .flags = HCD_MEMORY | HCD_USB2, | 5511 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, |
| 5512 | 5512 | ||
| 5513 | /* | 5513 | /* |
| 5514 | * basic lifecycle operations | 5514 | * basic lifecycle operations |
| @@ -1771,7 +1771,7 @@ static const struct hc_driver imx21_hc_driver = { · 1770 unmodified lines | |||
| 1771 | .product_desc = "IMX21 USB Host Controller", | 1771 | .product_desc = "IMX21 USB Host Controller", |
| 1772 | .hcd_priv_size = sizeof(struct imx21), | 1772 | .hcd_priv_size = sizeof(struct imx21), |
| 1773 | 1773 | ||
| 1774 | .flags = HCD_USB11, | 1774 | .flags = HCD_DMA | HCD_USB11, |
| 1775 | .irq = imx21_irq, | 1775 | .irq = imx21_irq, |
| 1776 | 1776 | ||
| 1777 | .reset = imx21_hc_reset, | 1777 | .reset = imx21_hc_reset, |
| @@ -1836,10 +1836,8 @@ static int imx21_probe(struct platform_device *pdev) · 58 unmodified lines | |||
| 1836 | if (!res) | 1836 | if (!res) |
| 1837 | return -ENODEV; | 1837 | return -ENODEV; |
| 1838 | irq = platform_get_irq(pdev, 0); | 1838 | irq = platform_get_irq(pdev, 0); |
| 1839 | if (irq < 0) { | 1839 | if (irq < 0) |
| 1840 | dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); | ||
| 1841 | return irq; | 1840 | return irq; |
| 1842 | } | ||
| 1843 | 1841 | ||
| 1844 | hcd = usb_create_hcd(&imx21_hc_driver, | 1842 | hcd = usb_create_hcd(&imx21_hc_driver, |
| 1845 | &pdev->dev, dev_name(&pdev->dev)); | 1843 | &pdev->dev, dev_name(&pdev->dev)); |
| @@ -1581,12 +1581,6 @@ static int isp116x_probe(struct platform_device *pdev) · 1580 unmodified lines | |||
| 1581 | irq = ires->start; | 1581 | irq = ires->start; |
| 1582 | irqflags = ires->flags & IRQF_TRIGGER_MASK; | 1582 | irqflags = ires->flags & IRQF_TRIGGER_MASK; |
| 1583 | 1583 | ||
| 1584 | if (pdev->dev.dma_mask) { | ||
| 1585 | DBG("DMA not supported\n"); | ||
| 1586 | ret = -EINVAL; | ||
| 1587 | goto err1; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | if (!request_mem_region(addr->start, 2, hcd_name)) { | 1584 | if (!request_mem_region(addr->start, 2, hcd_name)) { |
| 1591 | ret = -EBUSY; | 1585 | ret = -EBUSY; |
| 1592 | goto err1; | 1586 | goto err1; |
| @@ -2645,11 +2645,6 @@ static int isp1362_probe(struct platform_device *pdev) · 2644 unmodified lines | |||
| 2645 | if (pdev->num_resources < 3) | 2645 | if (pdev->num_resources < 3) |
| 2646 | return -ENODEV; | 2646 | return -ENODEV; |
| 2647 | 2647 | ||
| 2648 | if (pdev->dev.dma_mask) { | ||
| 2649 | DBG(1, "won't do DMA"); | ||
| 2650 | return -ENODEV; | ||
| 2651 | } | ||
| 2652 | |||
| 2653 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 2648 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 2654 | if (!irq_res) | 2649 | if (!irq_res) |
| 2655 | return -ENODEV; | 2650 | return -ENODEV; |
| @@ -1800,21 +1800,6 @@ max3421_bus_resume(struct usb_hcd *hcd) · 1799 unmodified lines | |||
| 1800 | return -1; | 1800 | return -1; |
| 1801 | } | 1801 | } |
| 1802 | 1802 | ||
| 1803 | /* | ||
| 1804 | * The SPI driver already takes care of DMA-mapping/unmapping, so no | ||
| 1805 | * reason to do it twice. | ||
| 1806 | */ | ||
| 1807 | static int | ||
| 1808 | max3421_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | ||
| 1809 | { | ||
| 1810 | return 0; | ||
| 1811 | } | ||
| 1812 | |||
| 1813 | static void | ||
| 1814 | max3421_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | ||
| 1815 | { | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | static const struct hc_driver max3421_hcd_desc = { | 1803 | static const struct hc_driver max3421_hcd_desc = { |
| 1819 | .description = "max3421", | 1804 | .description = "max3421", |
| 1820 | .product_desc = DRIVER_DESC, | 1805 | .product_desc = DRIVER_DESC, |
| @@ -1826,8 +1811,6 @@ static const struct hc_driver max3421_hcd_desc = { · 5 unmodified lines | |||
| 1826 | .get_frame_number = max3421_get_frame_number, | 1811 | .get_frame_number = max3421_get_frame_number, |
| 1827 | .urb_enqueue = max3421_urb_enqueue, | 1812 | .urb_enqueue = max3421_urb_enqueue, |
| 1828 | .urb_dequeue = max3421_urb_dequeue, | 1813 | .urb_dequeue = max3421_urb_dequeue, |
| 1829 | .map_urb_for_dma = max3421_map_urb_for_dma, | ||
| 1830 | .unmap_urb_for_dma = max3421_unmap_urb_for_dma, | ||
| 1831 | .endpoint_disable = max3421_endpoint_disable, | 1814 | .endpoint_disable = max3421_endpoint_disable, |
| 1832 | .hub_status_data = max3421_hub_status_data, | 1815 | .hub_status_data = max3421_hub_status_data, |
| 1833 | .hub_control = max3421_hub_control, | 1816 | .hub_control = max3421_hub_control, |
| @@ -32,6 +32,7 @@ struct exynos_ohci_hcd { · 31 unmodified lines | |||
| 32 | struct clk *clk; | 32 | struct clk *clk; |
| 33 | struct device_node *of_node; | 33 | struct device_node *of_node; |
| 34 | struct phy *phy[PHY_NUMBER]; | 34 | struct phy *phy[PHY_NUMBER]; |
| 35 | bool legacy_phy; | ||
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 37 | static int exynos_ohci_get_phy(struct device *dev, | 38 | static int exynos_ohci_get_phy(struct device *dev, |
| @@ -39,10 +40,22 @@ static int exynos_ohci_get_phy(struct device *dev, · 1 unmodified line | |||
| 39 | { | 40 | { |
| 40 | struct device_node *child; | 41 | struct device_node *child; |
| 41 | struct phy *phy; | 42 | struct phy *phy; |
| 42 | int phy_number; | 43 | int phy_number, num_phys; |
| 43 | int ret; | 44 | int ret; |
| 44 | 45 | ||
| 45 | /* Get PHYs for the controller */ | 46 | /* Get PHYs for the controller */ |
| 47 | num_phys = of_count_phandle_with_args(dev->of_node, "phys", | ||
| 48 | "#phy-cells"); | ||
| 49 | for (phy_number = 0; phy_number < num_phys; phy_number++) { | ||
| 50 | phy = devm_of_phy_get_by_index(dev, dev->of_node, phy_number); | ||
| 51 | if (IS_ERR(phy)) | ||
| 52 | return PTR_ERR(phy); | ||
| 53 | exynos_ohci->phy[phy_number] = phy; | ||
| 54 | } | ||
| 55 | if (num_phys > 0) | ||
| 56 | return 0; | ||
| 57 | |||
| 58 | /* Get PHYs using legacy bindings */ | ||
| 46 | for_each_available_child_of_node(dev->of_node, child) { | 59 | for_each_available_child_of_node(dev->of_node, child) { |
| 47 | ret = of_property_read_u32(child, "reg", &phy_number); | 60 | ret = of_property_read_u32(child, "reg", &phy_number); |
| 48 | if (ret) { | 61 | if (ret) { |
| @@ -73,6 +86,7 @@ static int exynos_ohci_get_phy(struct device *dev, · 24 unmodified lines | |||
| 73 | } | 86 | } |
| 74 | } | 87 | } |
| 75 | 88 | ||
| 89 | exynos_ohci->legacy_phy = true; | ||
| 76 | return 0; | 90 | return 0; |
| 77 | } | 91 | } |
| 78 | 92 | ||
| @@ -172,11 +186,12 @@ static int exynos_ohci_probe(struct platform_device *pdev) · 93 unmodified lines | |||
| 172 | } | 186 | } |
| 173 | 187 | ||
| 174 | /* | 188 | /* |
| 175 | * Workaround: reset of_node pointer to avoid conflict between Exynos | 189 | * Workaround: reset of_node pointer to avoid conflict between legacy |
| 176 | * OHCI port subnodes and generic USB device bindings | 190 | * Exynos OHCI port subnodes and generic USB device bindings |
| 177 | */ | 191 | */ |
| 178 | exynos_ohci->of_node = pdev->dev.of_node; | 192 | exynos_ohci->of_node = pdev->dev.of_node; |
| 179 | pdev->dev.of_node = NULL; | 193 | if (exynos_ohci->legacy_phy) |
| 194 | pdev->dev.of_node = NULL; | ||
| 180 | 195 | ||
| 181 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); | 196 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 182 | if (err) { | 197 | if (err) { |
| @@ -1187,7 +1187,7 @@ static const struct hc_driver ohci_hc_driver = { · 1186 unmodified lines | |||
| 1187 | * generic hardware linkage | 1187 | * generic hardware linkage |
| 1188 | */ | 1188 | */ |
| 1189 | .irq = ohci_irq, | 1189 | .irq = ohci_irq, |
| 1190 | .flags = HCD_MEMORY | HCD_USB11, | 1190 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, |
| 1191 | 1191 | ||
| 1192 | /* | 1192 | /* |
| 1193 | * basic lifecycle operations | 1193 | * basic lifecycle operations |
| @@ -111,10 +111,8 @@ static int ohci_platform_probe(struct platform_device *dev) · 110 unmodified lines | |||
| 111 | return err; | 111 | return err; |
| 112 | 112 | ||
| 113 | irq = platform_get_irq(dev, 0); | 113 | irq = platform_get_irq(dev, 0); |
| 114 | if (irq < 0) { | 114 | if (irq < 0) |
| 115 | dev_err(&dev->dev, "no irq provided"); | ||
| 116 | return irq; | 115 | return irq; |
| 117 | } | ||
| 118 | 116 | ||
| 119 | hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, | 117 | hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, |
| 120 | dev_name(&dev->dev)); | 118 | dev_name(&dev->dev)); |
| @@ -50,7 +50,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { · 49 unmodified lines | |||
| 50 | * generic hardware linkage | 50 | * generic hardware linkage |
| 51 | */ | 51 | */ |
| 52 | .irq = ohci_irq, | 52 | .irq = ohci_irq, |
| 53 | .flags = HCD_USB11 | HCD_MEMORY, | 53 | .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, |
| 54 | 54 | ||
| 55 | /* | 55 | /* |
| 56 | * basic lifecycle operations | 56 | * basic lifecycle operations |
| @@ -46,7 +46,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { · 45 unmodified lines | |||
| 46 | .product_desc = "PS3 OHCI Host Controller", | 46 | .product_desc = "PS3 OHCI Host Controller", |
| 47 | .hcd_priv_size = sizeof(struct ohci_hcd), | 47 | .hcd_priv_size = sizeof(struct ohci_hcd), |
| 48 | .irq = ohci_irq, | 48 | .irq = ohci_irq, |
| 49 | .flags = HCD_MEMORY | HCD_USB11, | 49 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, |
| 50 | .reset = ps3_ohci_hc_reset, | 50 | .reset = ps3_ohci_hc_reset, |
| 51 | .start = ps3_ohci_hc_start, | 51 | .start = ps3_ohci_hc_start, |
| 52 | .stop = ohci_stop, | 52 | .stop = ohci_stop, |
| @@ -148,7 +148,7 @@ static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode) · 147 unmodified lines | |||
| 148 | uhcrhda |= RH_A_NPS; | 148 | uhcrhda |= RH_A_NPS; |
| 149 | break; | 149 | break; |
| 150 | case PMM_GLOBAL_MODE: | 150 | case PMM_GLOBAL_MODE: |
| 151 | uhcrhda &= ~(RH_A_NPS & RH_A_PSM); | 151 | uhcrhda &= ~(RH_A_NPS | RH_A_PSM); |
| 152 | break; | 152 | break; |
| 153 | case PMM_PERPORT_MODE: | 153 | case PMM_PERPORT_MODE: |
| 154 | uhcrhda &= ~(RH_A_NPS); | 154 | uhcrhda &= ~(RH_A_NPS); |
| @@ -84,7 +84,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { · 83 unmodified lines | |||
| 84 | * generic hardware linkage | 84 | * generic hardware linkage |
| 85 | */ | 85 | */ |
| 86 | .irq = ohci_irq, | 86 | .irq = ohci_irq, |
| 87 | .flags = HCD_USB11 | HCD_MEMORY, | 87 | .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, |
| 88 | 88 | ||
| 89 | /* | 89 | /* |
| 90 | * basic lifecycle operations | 90 | * basic lifecycle operations |
| @@ -138,10 +138,8 @@ static int st_ohci_platform_probe(struct platform_device *dev) · 137 unmodified lines | |||
| 138 | return -ENODEV; | 138 | return -ENODEV; |
| 139 | 139 | ||
| 140 | irq = platform_get_irq(dev, 0); | 140 | irq = platform_get_irq(dev, 0); |
| 141 | if (irq < 0) { | 141 | if (irq < 0) |
| 142 | dev_err(&dev->dev, "no irq provided"); | ||
| 143 | return irq; | 142 | return irq; |
| 144 | } | ||
| 145 | 143 | ||
| 146 | res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); | 144 | res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); |
| 147 | if (!res_mem) { | 145 | if (!res_mem) { |
| @@ -97,10 +97,13 @@ static void tmio_stop_hc(struct platform_device *dev) · 96 unmodified lines | |||
| 97 | switch (ohci->num_ports) { | 97 | switch (ohci->num_ports) { |
| 98 | default: | 98 | default: |
| 99 | dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports); | 99 | dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports); |
| 100 | /* fall through */ | ||
| 100 | case 3: | 101 | case 3: |
| 101 | pm |= CCR_PM_USBPW3; | 102 | pm |= CCR_PM_USBPW3; |
| 103 | /* fall through */ | ||
| 102 | case 2: | 104 | case 2: |
| 103 | pm |= CCR_PM_USBPW2; | 105 | pm |= CCR_PM_USBPW2; |
| 106 | /* fall through */ | ||
| 104 | case 1: | 107 | case 1: |
| 105 | pm |= CCR_PM_USBPW1; | 108 | pm |= CCR_PM_USBPW1; |
| 106 | } | 109 | } |
| @@ -31,10 +31,449 @@ · 30 unmodified lines | |||
| 31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
| 32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 33 | 33 | ||
| 34 | #include "oxu210hp.h" | ||
| 35 | |||
| 36 | #define DRIVER_VERSION "0.0.50" | 34 | #define DRIVER_VERSION "0.0.50" |
| 37 | 35 | ||
| 36 | #define OXU_DEVICEID 0x00 | ||
| 37 | #define OXU_REV_MASK 0xffff0000 | ||
| 38 | #define OXU_REV_SHIFT 16 | ||
| 39 | #define OXU_REV_2100 0x2100 | ||
| 40 | #define OXU_BO_SHIFT 8 | ||
| 41 | #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) | ||
| 42 | #define OXU_MAJ_REV_SHIFT 4 | ||
| 43 | #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) | ||
| 44 | #define OXU_MIN_REV_SHIFT 0 | ||
| 45 | #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) | ||
| 46 | #define OXU_HOSTIFCONFIG 0x04 | ||
| 47 | #define OXU_SOFTRESET 0x08 | ||
| 48 | #define OXU_SRESET (1 << 0) | ||
| 49 | |||
| 50 | #define OXU_PIOBURSTREADCTRL 0x0C | ||
| 51 | |||
| 52 | #define OXU_CHIPIRQSTATUS 0x10 | ||
| 53 | #define OXU_CHIPIRQEN_SET 0x14 | ||
| 54 | #define OXU_CHIPIRQEN_CLR 0x18 | ||
| 55 | #define OXU_USBSPHLPWUI 0x00000080 | ||
| 56 | #define OXU_USBOTGLPWUI 0x00000040 | ||
| 57 | #define OXU_USBSPHI 0x00000002 | ||
| 58 | #define OXU_USBOTGI 0x00000001 | ||
| 59 | |||
| 60 | #define OXU_CLKCTRL_SET 0x1C | ||
| 61 | #define OXU_SYSCLKEN 0x00000008 | ||
| 62 | #define OXU_USBSPHCLKEN 0x00000002 | ||
| 63 | #define OXU_USBOTGCLKEN 0x00000001 | ||
| 64 | |||
| 65 | #define OXU_ASO 0x68 | ||
| 66 | #define OXU_SPHPOEN 0x00000100 | ||
| 67 | #define OXU_OVRCCURPUPDEN 0x00000800 | ||
| 68 | #define OXU_ASO_OP (1 << 10) | ||
| 69 | #define OXU_COMPARATOR 0x000004000 | ||
| 70 | |||
| 71 | #define OXU_USBMODE 0x1A8 | ||
| 72 | #define OXU_VBPS 0x00000020 | ||
| 73 | #define OXU_ES_LITTLE 0x00000000 | ||
| 74 | #define OXU_CM_HOST_ONLY 0x00000003 | ||
| 75 | |||
| 76 | /* | ||
| 77 | * Proper EHCI structs & defines | ||
| 78 | */ | ||
| 79 | |||
| 80 | /* Magic numbers that can affect system performance */ | ||
| 81 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | ||
| 82 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | ||
| 83 | #define EHCI_TUNE_RL_TT 0 | ||
| 84 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | ||
| 85 | #define EHCI_TUNE_MULT_TT 1 | ||
| 86 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | ||
| 87 | |||
| 88 | struct oxu_hcd; | ||
| 89 | |||
| 90 | /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ | ||
| 91 | |||
| 92 | /* Section 2.2 Host Controller Capability Registers */ | ||
| 93 | struct ehci_caps { | ||
| 94 | /* these fields are specified as 8 and 16 bit registers, | ||
| 95 | * but some hosts can't perform 8 or 16 bit PCI accesses. | ||
| 96 | */ | ||
| 97 | u32 hc_capbase; | ||
| 98 | #define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ | ||
| 99 | #define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ | ||
| 100 | u32 hcs_params; /* HCSPARAMS - offset 0x4 */ | ||
| 101 | #define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ | ||
| 102 | #define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ | ||
| 103 | #define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ | ||
| 104 | #define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ | ||
| 105 | #define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ | ||
| 106 | #define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ | ||
| 107 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ | ||
| 108 | |||
| 109 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ | ||
| 110 | #define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ | ||
| 111 | #define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ | ||
| 112 | #define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ | ||
| 113 | #define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ | ||
| 114 | #define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ | ||
| 115 | #define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ | ||
| 116 | u8 portroute[8]; /* nibbles for routing - offset 0xC */ | ||
| 117 | } __packed; | ||
| 118 | |||
| 119 | |||
| 120 | /* Section 2.3 Host Controller Operational Registers */ | ||
| 121 | struct ehci_regs { | ||
| 122 | /* USBCMD: offset 0x00 */ | ||
| 123 | u32 command; | ||
| 124 | /* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ | ||
| 125 | #define CMD_PARK (1<<11) /* enable "park" on async qh */ | ||
| 126 | #define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ | ||
| 127 | #define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ | ||
| 128 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ | ||
| 129 | #define CMD_ASE (1<<5) /* async schedule enable */ | ||
| 130 | #define CMD_PSE (1<<4) /* periodic schedule enable */ | ||
| 131 | /* 3:2 is periodic frame list size */ | ||
| 132 | #define CMD_RESET (1<<1) /* reset HC not bus */ | ||
| 133 | #define CMD_RUN (1<<0) /* start/stop HC */ | ||
| 134 | |||
| 135 | /* USBSTS: offset 0x04 */ | ||
| 136 | u32 status; | ||
| 137 | #define STS_ASS (1<<15) /* Async Schedule Status */ | ||
| 138 | #define STS_PSS (1<<14) /* Periodic Schedule Status */ | ||
| 139 | #define STS_RECL (1<<13) /* Reclamation */ | ||
| 140 | #define STS_HALT (1<<12) /* Not running (any reason) */ | ||
| 141 | /* some bits reserved */ | ||
| 142 | /* these STS_* flags are also intr_enable bits (USBINTR) */ | ||
| 143 | #define STS_IAA (1<<5) /* Interrupted on async advance */ | ||
| 144 | #define STS_FATAL (1<<4) /* such as some PCI access errors */ | ||
| 145 | #define STS_FLR (1<<3) /* frame list rolled over */ | ||
| 146 | #define STS_PCD (1<<2) /* port change detect */ | ||
| 147 | #define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ | ||
| 148 | #define STS_INT (1<<0) /* "normal" completion (short, ...) */ | ||
| 149 | |||
| 150 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | ||
| 151 | |||
| 152 | /* USBINTR: offset 0x08 */ | ||
| 153 | u32 intr_enable; | ||
| 154 | |||
| 155 | /* FRINDEX: offset 0x0C */ | ||
| 156 | u32 frame_index; /* current microframe number */ | ||
| 157 | /* CTRLDSSEGMENT: offset 0x10 */ | ||
| 158 | u32 segment; /* address bits 63:32 if needed */ | ||
| 159 | /* PERIODICLISTBASE: offset 0x14 */ | ||
| 160 | u32 frame_list; /* points to periodic list */ | ||
| 161 | /* ASYNCLISTADDR: offset 0x18 */ | ||
| 162 | u32 async_next; /* address of next async queue head */ | ||
| 163 | |||
| 164 | u32 reserved[9]; | ||
| 165 | |||
| 166 | /* CONFIGFLAG: offset 0x40 */ | ||
| 167 | u32 configured_flag; | ||
| 168 | #define FLAG_CF (1<<0) /* true: we'll support "high speed" */ | ||
| 169 | |||
| 170 | /* PORTSC: offset 0x44 */ | ||
| 171 | u32 port_status[0]; /* up to N_PORTS */ | ||
| 172 | /* 31:23 reserved */ | ||
| 173 | #define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ | ||
| 174 | #define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ | ||
| 175 | #define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ | ||
| 176 | /* 19:16 for port testing */ | ||
| 177 | #define PORT_LED_OFF (0<<14) | ||
| 178 | #define PORT_LED_AMBER (1<<14) | ||
| 179 | #define PORT_LED_GREEN (2<<14) | ||
| 180 | #define PORT_LED_MASK (3<<14) | ||
| 181 | #define PORT_OWNER (1<<13) /* true: companion hc owns this port */ | ||
| 182 | #define PORT_POWER (1<<12) /* true: has power (see PPC) */ | ||
| 183 | #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ | ||
| 184 | /* 11:10 for detecting lowspeed devices (reset vs release ownership) */ | ||
| 185 | /* 9 reserved */ | ||
| 186 | #define PORT_RESET (1<<8) /* reset port */ | ||
| 187 | #define PORT_SUSPEND (1<<7) /* suspend port */ | ||
| 188 | #define PORT_RESUME (1<<6) /* resume it */ | ||
| 189 | #define PORT_OCC (1<<5) /* over current change */ | ||
| 190 | #define PORT_OC (1<<4) /* over current active */ | ||
| 191 | #define PORT_PEC (1<<3) /* port enable change */ | ||
| 192 | #define PORT_PE (1<<2) /* port enable */ | ||
| 193 | #define PORT_CSC (1<<1) /* connect status change */ | ||
| 194 | #define PORT_CONNECT (1<<0) /* device connected */ | ||
| 195 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
| 196 | } __packed; | ||
| 197 | |||
| 198 | /* Appendix C, Debug port ... intended for use with special "debug devices" | ||
| 199 | * that can help if there's no serial console. (nonstandard enumeration.) | ||
| 200 | */ | ||
| 201 | struct ehci_dbg_port { | ||
| 202 | u32 control; | ||
| 203 | #define DBGP_OWNER (1<<30) | ||
| 204 | #define DBGP_ENABLED (1<<28) | ||
| 205 | #define DBGP_DONE (1<<16) | ||
| 206 | #define DBGP_INUSE (1<<10) | ||
| 207 | #define DBGP_ERRCODE(x) (((x)>>7)&0x07) | ||
| 208 | # define DBGP_ERR_BAD 1 | ||
| 209 | # define DBGP_ERR_SIGNAL 2 | ||
| 210 | #define DBGP_ERROR (1<<6) | ||
| 211 | #define DBGP_GO (1<<5) | ||
| 212 | #define DBGP_OUT (1<<4) | ||
| 213 | #define DBGP_LEN(x) (((x)>>0)&0x0f) | ||
| 214 | u32 pids; | ||
| 215 | #define DBGP_PID_GET(x) (((x)>>16)&0xff) | ||
| 216 | #define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) | ||
| 217 | u32 data03; | ||
| 218 | u32 data47; | ||
| 219 | u32 address; | ||
| 220 | #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) | ||
| 221 | } __packed; | ||
| 222 | |||
| 223 | #define QTD_NEXT(dma) cpu_to_le32((u32)dma) | ||
| 224 | |||
| 225 | /* | ||
| 226 | * EHCI Specification 0.95 Section 3.5 | ||
| 227 | * QTD: describe data transfer components (buffer, direction, ...) | ||
| 228 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". | ||
| 229 | * | ||
| 230 | * These are associated only with "QH" (Queue Head) structures, | ||
| 231 | * used with control, bulk, and interrupt transfers. | ||
| 232 | */ | ||
| 233 | struct ehci_qtd { | ||
| 234 | /* first part defined by EHCI spec */ | ||
| 235 | __le32 hw_next; /* see EHCI 3.5.1 */ | ||
| 236 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ | ||
| 237 | __le32 hw_token; /* see EHCI 3.5.3 */ | ||
| 238 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | ||
| 239 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | ||
| 240 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | ||
| 241 | #define QTD_CERR(tok) (((tok)>>10) & 0x3) | ||
| 242 | #define QTD_PID(tok) (((tok)>>8) & 0x3) | ||
| 243 | #define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ | ||
| 244 | #define QTD_STS_HALT (1 << 6) /* halted on error */ | ||
| 245 | #define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ | ||
| 246 | #define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ | ||
| 247 | #define QTD_STS_XACT (1 << 3) /* device gave illegal response */ | ||
| 248 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ | ||
| 249 | #define QTD_STS_STS (1 << 1) /* split transaction state */ | ||
| 250 | #define QTD_STS_PING (1 << 0) /* issue PING? */ | ||
| 251 | __le32 hw_buf[5]; /* see EHCI 3.5.4 */ | ||
| 252 | __le32 hw_buf_hi[5]; /* Appendix B */ | ||
| 253 | |||
| 254 | /* the rest is HCD-private */ | ||
| 255 | dma_addr_t qtd_dma; /* qtd address */ | ||
| 256 | struct list_head qtd_list; /* sw qtd list */ | ||
| 257 | struct urb *urb; /* qtd's urb */ | ||
| 258 | size_t length; /* length of buffer */ | ||
| 259 | |||
| 260 | u32 qtd_buffer_len; | ||
| 261 | void *buffer; | ||
| 262 | dma_addr_t buffer_dma; | ||
| 263 | void *transfer_buffer; | ||
| 264 | void *transfer_dma; | ||
| 265 | } __aligned(32); | ||
| 266 | |||
| 267 | /* mask NakCnt+T in qh->hw_alt_next */ | ||
| 268 | #define QTD_MASK cpu_to_le32 (~0x1f) | ||
| 269 | |||
| 270 | #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) | ||
| 271 | |||
| 272 | /* Type tag from {qh, itd, sitd, fstn}->hw_next */ | ||
| 273 | #define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) | ||
| 274 | |||
| 275 | /* values for that type tag */ | ||
| 276 | #define Q_TYPE_QH cpu_to_le32 (1 << 1) | ||
| 277 | |||
| 278 | /* next async queue entry, or pointer to interrupt/periodic QH */ | ||
| 279 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | ||
| 280 | |||
| 281 | /* for periodic/async schedules and qtd lists, mark end of list */ | ||
| 282 | #define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ | ||
| 283 | |||
| 284 | /* | ||
| 285 | * Entries in periodic shadow table are pointers to one of four kinds | ||
| 286 | * of data structure. That's dictated by the hardware; a type tag is | ||
| 287 | * encoded in the low bits of the hardware's periodic schedule. Use | ||
| 288 | * Q_NEXT_TYPE to get the tag. | ||
| 289 | * | ||
| 290 | * For entries in the async schedule, the type tag always says "qh". | ||
| 291 | */ | ||
| 292 | union ehci_shadow { | ||
| 293 | struct ehci_qh *qh; /* Q_TYPE_QH */ | ||
| 294 | __le32 *hw_next; /* (all types) */ | ||
| 295 | void *ptr; | ||
| 296 | }; | ||
| 297 | |||
| 298 | /* | ||
| 299 | * EHCI Specification 0.95 Section 3.6 | ||
| 300 | * QH: describes control/bulk/interrupt endpoints | ||
| 301 | * See Fig 3-7 "Queue Head Structure Layout". | ||
| 302 | * | ||
| 303 | * These appear in both the async and (for interrupt) periodic schedules. | ||
| 304 | */ | ||
| 305 | |||
| 306 | struct ehci_qh { | ||
| 307 | /* first part defined by EHCI spec */ | ||
| 308 | __le32 hw_next; /* see EHCI 3.6.1 */ | ||
| 309 | __le32 hw_info1; /* see EHCI 3.6.2 */ | ||
| 310 | #define QH_HEAD 0x00008000 | ||
| 311 | __le32 hw_info2; /* see EHCI 3.6.2 */ | ||
| 312 | #define QH_SMASK 0x000000ff | ||
| 313 | #define QH_CMASK 0x0000ff00 | ||
| 314 | #define QH_HUBADDR 0x007f0000 | ||
| 315 | #define QH_HUBPORT 0x3f800000 | ||
| 316 | #define QH_MULT 0xc0000000 | ||
| 317 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | ||
| 318 | |||
| 319 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | ||
| 320 | __le32 hw_qtd_next; | ||
| 321 | __le32 hw_alt_next; | ||
| 322 | __le32 hw_token; | ||
| 323 | __le32 hw_buf[5]; | ||
| 324 | __le32 hw_buf_hi[5]; | ||
| 325 | |||
| 326 | /* the rest is HCD-private */ | ||
| 327 | dma_addr_t qh_dma; /* address of qh */ | ||
| 328 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ | ||
| 329 | struct list_head qtd_list; /* sw qtd list */ | ||
| 330 | struct ehci_qtd *dummy; | ||
| 331 | struct ehci_qh *reclaim; /* next to reclaim */ | ||
| 332 | |||
| 333 | struct oxu_hcd *oxu; | ||
| 334 | struct kref kref; | ||
| 335 | unsigned int stamp; | ||
| 336 | |||
| 337 | u8 qh_state; | ||
| 338 | #define QH_STATE_LINKED 1 /* HC sees this */ | ||
| 339 | #define QH_STATE_UNLINK 2 /* HC may still see this */ | ||
| 340 | #define QH_STATE_IDLE 3 /* HC doesn't see this */ | ||
| 341 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ | ||
| 342 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ | ||
| 343 | |||
| 344 | /* periodic schedule info */ | ||
| 345 | u8 usecs; /* intr bandwidth */ | ||
| 346 | u8 gap_uf; /* uframes split/csplit gap */ | ||
| 347 | u8 c_usecs; /* ... split completion bw */ | ||
| 348 | u16 tt_usecs; /* tt downstream bandwidth */ | ||
| 349 | unsigned short period; /* polling interval */ | ||
| 350 | unsigned short start; /* where polling starts */ | ||
| 351 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | ||
| 352 | struct usb_device *dev; /* access to TT */ | ||
| 353 | } __aligned(32); | ||
| 354 | |||
| 355 | /* | ||
| 356 | * Proper OXU210HP structs | ||
| 357 | */ | ||
| 358 | |||
| 359 | #define OXU_OTG_CORE_OFFSET 0x00400 | ||
| 360 | #define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) | ||
| 361 | #define OXU_SPH_CORE_OFFSET 0x00800 | ||
| 362 | #define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) | ||
| 363 | |||
| 364 | #define OXU_OTG_MEM 0xE000 | ||
| 365 | #define OXU_SPH_MEM 0x16000 | ||
| 366 | |||
| 367 | /* Only how many elements & element structure are specifies here. */ | ||
| 368 | /* 2 host controllers are enabled - total size <= 28 kbytes */ | ||
| 369 | #define DEFAULT_I_TDPS 1024 | ||
| 370 | #define QHEAD_NUM 16 | ||
| 371 | #define QTD_NUM 32 | ||
| 372 | #define SITD_NUM 8 | ||
| 373 | #define MURB_NUM 8 | ||
| 374 | |||
| 375 | #define BUFFER_NUM 8 | ||
| 376 | #define BUFFER_SIZE 512 | ||
| 377 | |||
| 378 | struct oxu_info { | ||
| 379 | struct usb_hcd *hcd[2]; | ||
| 380 | }; | ||
| 381 | |||
| 382 | struct oxu_buf { | ||
| 383 | u8 buffer[BUFFER_SIZE]; | ||
| 384 | } __aligned(BUFFER_SIZE); | ||
| 385 | |||
| 386 | struct oxu_onchip_mem { | ||
| 387 | struct oxu_buf db_pool[BUFFER_NUM]; | ||
| 388 | |||
| 389 | u32 frame_list[DEFAULT_I_TDPS]; | ||
| 390 | struct ehci_qh qh_pool[QHEAD_NUM]; | ||
| 391 | struct ehci_qtd qtd_pool[QTD_NUM]; | ||
| 392 | } __aligned(4 << 10); | ||
| 393 | |||
| 394 | #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ | ||
| 395 | |||
| 396 | struct oxu_murb { | ||
| 397 | struct urb urb; | ||
| 398 | struct urb *main; | ||
| 399 | u8 last; | ||
| 400 | }; | ||
| 401 | |||
| 402 | struct oxu_hcd { /* one per controller */ | ||
| 403 | unsigned int is_otg:1; | ||
| 404 | |||
| 405 | u8 qh_used[QHEAD_NUM]; | ||
| 406 | u8 qtd_used[QTD_NUM]; | ||
| 407 | u8 db_used[BUFFER_NUM]; | ||
| 408 | u8 murb_used[MURB_NUM]; | ||
| 409 | |||
| 410 | struct oxu_onchip_mem __iomem *mem; | ||
| 411 | spinlock_t mem_lock; | ||
| 412 | |||
| 413 | struct timer_list urb_timer; | ||
| 414 | |||
| 415 | struct ehci_caps __iomem *caps; | ||
| 416 | struct ehci_regs __iomem *regs; | ||
| 417 | |||
| 418 | u32 hcs_params; /* cached register copy */ | ||
| 419 | spinlock_t lock; | ||
| 420 | |||
| 421 | /* async schedule support */ | ||
| 422 | struct ehci_qh *async; | ||
| 423 | struct ehci_qh *reclaim; | ||
| 424 | unsigned int reclaim_ready:1; | ||
| 425 | unsigned int scanning:1; | ||
| 426 | |||
| 427 | /* periodic schedule support */ | ||
| 428 | unsigned int periodic_size; | ||
| 429 | __le32 *periodic; /* hw periodic table */ | ||
| 430 | dma_addr_t periodic_dma; | ||
| 431 | unsigned int i_thresh; /* uframes HC might cache */ | ||
| 432 | |||
| 433 | union ehci_shadow *pshadow; /* mirror hw periodic table */ | ||
| 434 | int next_uframe; /* scan periodic, start here */ | ||
| 435 | unsigned int periodic_sched; /* periodic activity count */ | ||
| 436 | |||
| 437 | /* per root hub port */ | ||
| 438 | unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; | ||
| 439 | /* bit vectors (one bit per port) */ | ||
| 440 | unsigned long bus_suspended; /* which ports were | ||
| 441 | * already suspended at the | ||
| 442 | * start of a bus suspend | ||
| 443 | */ | ||
| 444 | unsigned long companion_ports;/* which ports are dedicated | ||
| 445 | * to the companion controller | ||
| 446 | */ | ||
| 447 | |||
| 448 | struct timer_list watchdog; | ||
| 449 | unsigned long actions; | ||
| 450 | unsigned int stamp; | ||
| 451 | unsigned long next_statechange; | ||
| 452 | u32 command; | ||
| 453 | |||
| 454 | /* SILICON QUIRKS */ | ||
| 455 | struct list_head urb_list; /* this is the head to urb | ||
| 456 | * queue that didn't get enough | ||
| 457 | * resources | ||
| 458 | */ | ||
| 459 | struct oxu_murb *murb_pool; /* murb per split big urb */ | ||
| 460 | unsigned int urb_len; | ||
| 461 | |||
| 462 | u8 sbrn; /* packed release number */ | ||
| 463 | }; | ||
| 464 | |||
| 465 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | ||
| 466 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | ||
| 467 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | ||
| 468 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | ||
| 469 | |||
| 470 | enum ehci_timer_action { | ||
| 471 | TIMER_IO_WATCHDOG, | ||
| 472 | TIMER_IAA_WATCHDOG, | ||
| 473 | TIMER_ASYNC_SHRINK, | ||
| 474 | TIMER_ASYNC_OFF, | ||
| 475 | }; | ||
| 476 | |||
| 38 | /* | 477 | /* |
| 39 | * Main defines | 478 | * Main defines |
| 40 | */ | 479 | */ |
| @@ -2649,9 +3088,6 @@ static int oxu_reset(struct usb_hcd *hcd) · 2608 unmodified lines | |||
| 2649 | INIT_LIST_HEAD(&oxu->urb_list); | 3088 | INIT_LIST_HEAD(&oxu->urb_list); |
| 2650 | oxu->urb_len = 0; | 3089 | oxu->urb_len = 0; |
| 2651 | 3090 | ||
| 2652 | /* FIMXE */ | ||
| 2653 | hcd->self.controller->dma_mask = NULL; | ||
| 2654 | |||
| 2655 | if (oxu->is_otg) { | 3091 | if (oxu->is_otg) { |
| 2656 | oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; | 3092 | oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; |
| 2657 | oxu->regs = hcd->regs + OXU_OTG_CAP_OFFSET + \ | 3093 | oxu->regs = hcd->regs + OXU_OTG_CAP_OFFSET + \ |
| @@ -1,448 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Host interface registers | ||
| 4 | */ | ||
| 5 | |||
| 6 | #define OXU_DEVICEID 0x00 | ||
| 7 | #define OXU_REV_MASK 0xffff0000 | ||
| 8 | #define OXU_REV_SHIFT 16 | ||
| 9 | #define OXU_REV_2100 0x2100 | ||
| 10 | #define OXU_BO_SHIFT 8 | ||
| 11 | #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) | ||
| 12 | #define OXU_MAJ_REV_SHIFT 4 | ||
| 13 | #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) | ||
| 14 | #define OXU_MIN_REV_SHIFT 0 | ||
| 15 | #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) | ||
| 16 | #define OXU_HOSTIFCONFIG 0x04 | ||
| 17 | #define OXU_SOFTRESET 0x08 | ||
| 18 | #define OXU_SRESET (1 << 0) | ||
| 19 | |||
| 20 | #define OXU_PIOBURSTREADCTRL 0x0C | ||
| 21 | |||
| 22 | #define OXU_CHIPIRQSTATUS 0x10 | ||
| 23 | #define OXU_CHIPIRQEN_SET 0x14 | ||
| 24 | #define OXU_CHIPIRQEN_CLR 0x18 | ||
| 25 | #define OXU_USBSPHLPWUI 0x00000080 | ||
| 26 | #define OXU_USBOTGLPWUI 0x00000040 | ||
| 27 | #define OXU_USBSPHI 0x00000002 | ||
| 28 | #define OXU_USBOTGI 0x00000001 | ||
| 29 | |||
| 30 | #define OXU_CLKCTRL_SET 0x1C | ||
| 31 | #define OXU_SYSCLKEN 0x00000008 | ||
| 32 | #define OXU_USBSPHCLKEN 0x00000002 | ||
| 33 | #define OXU_USBOTGCLKEN 0x00000001 | ||
| 34 | |||
| 35 | #define OXU_ASO 0x68 | ||
| 36 | #define OXU_SPHPOEN 0x00000100 | ||
| 37 | #define OXU_OVRCCURPUPDEN 0x00000800 | ||
| 38 | #define OXU_ASO_OP (1 << 10) | ||
| 39 | #define OXU_COMPARATOR 0x000004000 | ||
| 40 | |||
| 41 | #define OXU_USBMODE 0x1A8 | ||
| 42 | #define OXU_VBPS 0x00000020 | ||
| 43 | #define OXU_ES_LITTLE 0x00000000 | ||
| 44 | #define OXU_CM_HOST_ONLY 0x00000003 | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Proper EHCI structs & defines | ||
| 48 | */ | ||
| 49 | |||
| 50 | /* Magic numbers that can affect system performance */ | ||
| 51 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | ||
| 52 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | ||
| 53 | #define EHCI_TUNE_RL_TT 0 | ||
| 54 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | ||
| 55 | #define EHCI_TUNE_MULT_TT 1 | ||
| 56 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | ||
| 57 | |||
| 58 | struct oxu_hcd; | ||
| 59 | |||
| 60 | /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ | ||
| 61 | |||
| 62 | /* Section 2.2 Host Controller Capability Registers */ | ||
| 63 | struct ehci_caps { | ||
| 64 | /* these fields are specified as 8 and 16 bit registers, | ||
| 65 | * but some hosts can't perform 8 or 16 bit PCI accesses. | ||
| 66 | */ | ||
| 67 | u32 hc_capbase; | ||
| 68 | #define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ | ||
| 69 | #define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ | ||
| 70 | u32 hcs_params; /* HCSPARAMS - offset 0x4 */ | ||
| 71 | #define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ | ||
| 72 | #define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ | ||
| 73 | #define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ | ||
| 74 | #define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ | ||
| 75 | #define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ | ||
| 76 | #define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ | ||
| 77 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ | ||
| 78 | |||
| 79 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ | ||
| 80 | #define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ | ||
| 81 | #define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ | ||
| 82 | #define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ | ||
| 83 | #define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ | ||
| 84 | #define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ | ||
| 85 | #define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ | ||
| 86 | u8 portroute[8]; /* nibbles for routing - offset 0xC */ | ||
| 87 | } __attribute__ ((packed)); | ||
| 88 | |||
| 89 | |||
| 90 | /* Section 2.3 Host Controller Operational Registers */ | ||
| 91 | struct ehci_regs { | ||
| 92 | /* USBCMD: offset 0x00 */ | ||
| 93 | u32 command; | ||
| 94 | /* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ | ||
| 95 | #define CMD_PARK (1<<11) /* enable "park" on async qh */ | ||
| 96 | #define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ | ||
| 97 | #define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ | ||
| 98 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ | ||
| 99 | #define CMD_ASE (1<<5) /* async schedule enable */ | ||
| 100 | #define CMD_PSE (1<<4) /* periodic schedule enable */ | ||
| 101 | /* 3:2 is periodic frame list size */ | ||
| 102 | #define CMD_RESET (1<<1) /* reset HC not bus */ | ||
| 103 | #define CMD_RUN (1<<0) /* start/stop HC */ | ||
| 104 | |||
| 105 | /* USBSTS: offset 0x04 */ | ||
| 106 | u32 status; | ||
| 107 | #define STS_ASS (1<<15) /* Async Schedule Status */ | ||
| 108 | #define STS_PSS (1<<14) /* Periodic Schedule Status */ | ||
| 109 | #define STS_RECL (1<<13) /* Reclamation */ | ||
| 110 | #define STS_HALT (1<<12) /* Not running (any reason) */ | ||
| 111 | /* some bits reserved */ | ||
| 112 | /* these STS_* flags are also intr_enable bits (USBINTR) */ | ||
| 113 | #define STS_IAA (1<<5) /* Interrupted on async advance */ | ||
| 114 | #define STS_FATAL (1<<4) /* such as some PCI access errors */ | ||
| 115 | #define STS_FLR (1<<3) /* frame list rolled over */ | ||
| 116 | #define STS_PCD (1<<2) /* port change detect */ | ||
| 117 | #define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ | ||
| 118 | #define STS_INT (1<<0) /* "normal" completion (short, ...) */ | ||
| 119 | |||
| 120 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | ||
| 121 | |||
| 122 | /* USBINTR: offset 0x08 */ | ||
| 123 | u32 intr_enable; | ||
| 124 | |||
| 125 | /* FRINDEX: offset 0x0C */ | ||
| 126 | u32 frame_index; /* current microframe number */ | ||
| 127 | /* CTRLDSSEGMENT: offset 0x10 */ | ||
| 128 | u32 segment; /* address bits 63:32 if needed */ | ||
| 129 | /* PERIODICLISTBASE: offset 0x14 */ | ||
| 130 | u32 frame_list; /* points to periodic list */ | ||
| 131 | /* ASYNCLISTADDR: offset 0x18 */ | ||
| 132 | u32 async_next; /* address of next async queue head */ | ||
| 133 | |||
| 134 | u32 reserved[9]; | ||
| 135 | |||
| 136 | /* CONFIGFLAG: offset 0x40 */ | ||
| 137 | u32 configured_flag; | ||
| 138 | #define FLAG_CF (1<<0) /* true: we'll support "high speed" */ | ||
| 139 | |||
| 140 | /* PORTSC: offset 0x44 */ | ||
| 141 | u32 port_status[0]; /* up to N_PORTS */ | ||
| 142 | /* 31:23 reserved */ | ||
| 143 | #define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ | ||
| 144 | #define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ | ||
| 145 | #define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ | ||
| 146 | /* 19:16 for port testing */ | ||
| 147 | #define PORT_LED_OFF (0<<14) | ||
| 148 | #define PORT_LED_AMBER (1<<14) | ||
| 149 | #define PORT_LED_GREEN (2<<14) | ||
| 150 | #define PORT_LED_MASK (3<<14) | ||
| 151 | #define PORT_OWNER (1<<13) /* true: companion hc owns this port */ | ||
| 152 | #define PORT_POWER (1<<12) /* true: has power (see PPC) */ | ||
| 153 | #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ | ||
| 154 | /* 11:10 for detecting lowspeed devices (reset vs release ownership) */ | ||
| 155 | /* 9 reserved */ | ||
| 156 | #define PORT_RESET (1<<8) /* reset port */ | ||
| 157 | #define PORT_SUSPEND (1<<7) /* suspend port */ | ||
| 158 | #define PORT_RESUME (1<<6) /* resume it */ | ||
| 159 | #define PORT_OCC (1<<5) /* over current change */ | ||
| 160 | #define PORT_OC (1<<4) /* over current active */ | ||
| 161 | #define PORT_PEC (1<<3) /* port enable change */ | ||
| 162 | #define PORT_PE (1<<2) /* port enable */ | ||
| 163 | #define PORT_CSC (1<<1) /* connect status change */ | ||
| 164 | #define PORT_CONNECT (1<<0) /* device connected */ | ||
| 165 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
| 166 | } __attribute__ ((packed)); | ||
| 167 | |||
| 168 | /* Appendix C, Debug port ... intended for use with special "debug devices" | ||
| 169 | * that can help if there's no serial console. (nonstandard enumeration.) | ||
| 170 | */ | ||
| 171 | struct ehci_dbg_port { | ||
| 172 | u32 control; | ||
| 173 | #define DBGP_OWNER (1<<30) | ||
| 174 | #define DBGP_ENABLED (1<<28) | ||
| 175 | #define DBGP_DONE (1<<16) | ||
| 176 | #define DBGP_INUSE (1<<10) | ||
| 177 | #define DBGP_ERRCODE(x) (((x)>>7)&0x07) | ||
| 178 | # define DBGP_ERR_BAD 1 | ||
| 179 | # define DBGP_ERR_SIGNAL 2 | ||
| 180 | #define DBGP_ERROR (1<<6) | ||
| 181 | #define DBGP_GO (1<<5) | ||
| 182 | #define DBGP_OUT (1<<4) | ||
| 183 | #define DBGP_LEN(x) (((x)>>0)&0x0f) | ||
| 184 | u32 pids; | ||
| 185 | #define DBGP_PID_GET(x) (((x)>>16)&0xff) | ||
| 186 | #define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) | ||
| 187 | u32 data03; | ||
| 188 | u32 data47; | ||
| 189 | u32 address; | ||
| 190 | #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) | ||
| 191 | } __attribute__ ((packed)); | ||
| 192 | |||
| 193 | |||
| 194 | #define QTD_NEXT(dma) cpu_to_le32((u32)dma) | ||
| 195 | |||
| 196 | /* | ||
| 197 | * EHCI Specification 0.95 Section 3.5 | ||
| 198 | * QTD: describe data transfer components (buffer, direction, ...) | ||
| 199 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". | ||
| 200 | * | ||
| 201 | * These are associated only with "QH" (Queue Head) structures, | ||
| 202 | * used with control, bulk, and interrupt transfers. | ||
| 203 | */ | ||
| 204 | struct ehci_qtd { | ||
| 205 | /* first part defined by EHCI spec */ | ||
| 206 | __le32 hw_next; /* see EHCI 3.5.1 */ | ||
| 207 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ | ||
| 208 | __le32 hw_token; /* see EHCI 3.5.3 */ | ||
| 209 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | ||
| 210 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | ||
| 211 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | ||
| 212 | #define QTD_CERR(tok) (((tok)>>10) & 0x3) | ||
| 213 | #define QTD_PID(tok) (((tok)>>8) & 0x3) | ||
| 214 | #define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ | ||
| 215 | #define QTD_STS_HALT (1 << 6) /* halted on error */ | ||
| 216 | #define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ | ||
| 217 | #define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ | ||
| 218 | #define QTD_STS_XACT (1 << 3) /* device gave illegal response */ | ||
| 219 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ | ||
| 220 | #define QTD_STS_STS (1 << 1) /* split transaction state */ | ||
| 221 | #define QTD_STS_PING (1 << 0) /* issue PING? */ | ||
| 222 | __le32 hw_buf[5]; /* see EHCI 3.5.4 */ | ||
| 223 | __le32 hw_buf_hi[5]; /* Appendix B */ | ||
| 224 | |||
| 225 | /* the rest is HCD-private */ | ||
| 226 | dma_addr_t qtd_dma; /* qtd address */ | ||
| 227 | struct list_head qtd_list; /* sw qtd list */ | ||
| 228 | struct urb *urb; /* qtd's urb */ | ||
| 229 | size_t length; /* length of buffer */ | ||
| 230 | |||
| 231 | u32 qtd_buffer_len; | ||
| 232 | void *buffer; | ||
| 233 | dma_addr_t buffer_dma; | ||
| 234 | void *transfer_buffer; | ||
| 235 | void *transfer_dma; | ||
| 236 | } __attribute__ ((aligned(32))); | ||
| 237 | |||
| 238 | /* mask NakCnt+T in qh->hw_alt_next */ | ||
| 239 | #define QTD_MASK cpu_to_le32 (~0x1f) | ||
| 240 | |||
| 241 | #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) | ||
| 242 | |||
| 243 | /* Type tag from {qh, itd, sitd, fstn}->hw_next */ | ||
| 244 | #define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) | ||
| 245 | |||
| 246 | /* values for that type tag */ | ||
| 247 | #define Q_TYPE_QH cpu_to_le32 (1 << 1) | ||
| 248 | |||
| 249 | /* next async queue entry, or pointer to interrupt/periodic QH */ | ||
| 250 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | ||
| 251 | |||
| 252 | /* for periodic/async schedules and qtd lists, mark end of list */ | ||
| 253 | #define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ | ||
| 254 | |||
| 255 | /* | ||
| 256 | * Entries in periodic shadow table are pointers to one of four kinds | ||
| 257 | * of data structure. That's dictated by the hardware; a type tag is | ||
| 258 | * encoded in the low bits of the hardware's periodic schedule. Use | ||
| 259 | * Q_NEXT_TYPE to get the tag. | ||
| 260 | * | ||
| 261 | * For entries in the async schedule, the type tag always says "qh". | ||
| 262 | */ | ||
| 263 | union ehci_shadow { | ||
| 264 | struct ehci_qh *qh; /* Q_TYPE_QH */ | ||
| 265 | __le32 *hw_next; /* (all types) */ | ||
| 266 | void *ptr; | ||
| 267 | }; | ||
| 268 | |||
| 269 | /* | ||
| 270 | * EHCI Specification 0.95 Section 3.6 | ||
| 271 | * QH: describes control/bulk/interrupt endpoints | ||
| 272 | * See Fig 3-7 "Queue Head Structure Layout". | ||
| 273 | * | ||
| 274 | * These appear in both the async and (for interrupt) periodic schedules. | ||
| 275 | */ | ||
| 276 | |||
| 277 | struct ehci_qh { | ||
| 278 | /* first part defined by EHCI spec */ | ||
| 279 | __le32 hw_next; /* see EHCI 3.6.1 */ | ||
| 280 | __le32 hw_info1; /* see EHCI 3.6.2 */ | ||
| 281 | #define QH_HEAD 0x00008000 | ||
| 282 | __le32 hw_info2; /* see EHCI 3.6.2 */ | ||
| 283 | #define QH_SMASK 0x000000ff | ||
| 284 | #define QH_CMASK 0x0000ff00 | ||
| 285 | #define QH_HUBADDR 0x007f0000 | ||
| 286 | #define QH_HUBPORT 0x3f800000 | ||
| 287 | #define QH_MULT 0xc0000000 | ||
| 288 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | ||
| 289 | |||
| 290 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | ||
| 291 | __le32 hw_qtd_next; | ||
| 292 | __le32 hw_alt_next; | ||
| 293 | __le32 hw_token; | ||
| 294 | __le32 hw_buf[5]; | ||
| 295 | __le32 hw_buf_hi[5]; | ||
| 296 | |||
| 297 | /* the rest is HCD-private */ | ||
| 298 | dma_addr_t qh_dma; /* address of qh */ | ||
| 299 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ | ||
| 300 | struct list_head qtd_list; /* sw qtd list */ | ||
| 301 | struct ehci_qtd *dummy; | ||
| 302 | struct ehci_qh *reclaim; /* next to reclaim */ | ||
| 303 | |||
| 304 | struct oxu_hcd *oxu; | ||
| 305 | struct kref kref; | ||
| 306 | unsigned stamp; | ||
| 307 | |||
| 308 | u8 qh_state; | ||
| 309 | #define QH_STATE_LINKED 1 /* HC sees this */ | ||
| 310 | #define QH_STATE_UNLINK 2 /* HC may still see this */ | ||
| 311 | #define QH_STATE_IDLE 3 /* HC doesn't see this */ | ||
| 312 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ | ||
| 313 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ | ||
| 314 | |||
| 315 | /* periodic schedule info */ | ||
| 316 | u8 usecs; /* intr bandwidth */ | ||
| 317 | u8 gap_uf; /* uframes split/csplit gap */ | ||
| 318 | u8 c_usecs; /* ... split completion bw */ | ||
| 319 | u16 tt_usecs; /* tt downstream bandwidth */ | ||
| 320 | unsigned short period; /* polling interval */ | ||
| 321 | unsigned short start; /* where polling starts */ | ||
| 322 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | ||
| 323 | struct usb_device *dev; /* access to TT */ | ||
| 324 | } __attribute__ ((aligned(32))); | ||
| 325 | |||
| 326 | /* | ||
| 327 | * Proper OXU210HP structs | ||
| 328 | */ | ||
| 329 | |||
| 330 | #define OXU_OTG_CORE_OFFSET 0x00400 | ||
| 331 | #define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) | ||
| 332 | #define OXU_SPH_CORE_OFFSET 0x00800 | ||
| 333 | #define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) | ||
| 334 | |||
| 335 | #define OXU_OTG_MEM 0xE000 | ||
| 336 | #define OXU_SPH_MEM 0x16000 | ||
| 337 | |||
| 338 | /* Only how many elements & element structure are specifies here. */ | ||
| 339 | /* 2 host controllers are enabled - total size <= 28 kbytes */ | ||
| 340 | #define DEFAULT_I_TDPS 1024 | ||
| 341 | #define QHEAD_NUM 16 | ||
| 342 | #define QTD_NUM 32 | ||
| 343 | #define SITD_NUM 8 | ||
| 344 | #define MURB_NUM 8 | ||
| 345 | |||
| 346 | #define BUFFER_NUM 8 | ||
| 347 | #define BUFFER_SIZE 512 | ||
| 348 | |||
| 349 | struct oxu_info { | ||
| 350 | struct usb_hcd *hcd[2]; | ||
| 351 | }; | ||
| 352 | |||
| 353 | struct oxu_buf { | ||
| 354 | u8 buffer[BUFFER_SIZE]; | ||
| 355 | } __attribute__ ((aligned(BUFFER_SIZE))); | ||
| 356 | |||
| 357 | struct oxu_onchip_mem { | ||
| 358 | struct oxu_buf db_pool[BUFFER_NUM]; | ||
| 359 | |||
| 360 | u32 frame_list[DEFAULT_I_TDPS]; | ||
| 361 | struct ehci_qh qh_pool[QHEAD_NUM]; | ||
| 362 | struct ehci_qtd qtd_pool[QTD_NUM]; | ||
| 363 | } __attribute__ ((aligned(4 << 10))); | ||
| 364 | |||
| 365 | #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ | ||
| 366 | |||
| 367 | struct oxu_murb { | ||
| 368 | struct urb urb; | ||
| 369 | struct urb *main; | ||
| 370 | u8 last; | ||
| 371 | }; | ||
| 372 | |||
| 373 | struct oxu_hcd { /* one per controller */ | ||
| 374 | unsigned int is_otg:1; | ||
| 375 | |||
| 376 | u8 qh_used[QHEAD_NUM]; | ||
| 377 | u8 qtd_used[QTD_NUM]; | ||
| 378 | u8 db_used[BUFFER_NUM]; | ||
| 379 | u8 murb_used[MURB_NUM]; | ||
| 380 | |||
| 381 | struct oxu_onchip_mem __iomem *mem; | ||
| 382 | spinlock_t mem_lock; | ||
| 383 | |||
| 384 | struct timer_list urb_timer; | ||
| 385 | |||
| 386 | struct ehci_caps __iomem *caps; | ||
| 387 | struct ehci_regs __iomem *regs; | ||
| 388 | |||
| 389 | __u32 hcs_params; /* cached register copy */ | ||
| 390 | spinlock_t lock; | ||
| 391 | |||
| 392 | /* async schedule support */ | ||
| 393 | struct ehci_qh *async; | ||
| 394 | struct ehci_qh *reclaim; | ||
| 395 | unsigned reclaim_ready:1; | ||
| 396 | unsigned scanning:1; | ||
| 397 | |||
| 398 | /* periodic schedule support */ | ||
| 399 | unsigned periodic_size; | ||
| 400 | __le32 *periodic; /* hw periodic table */ | ||
| 401 | dma_addr_t periodic_dma; | ||
| 402 | unsigned i_thresh; /* uframes HC might cache */ | ||
| 403 | |||
| 404 | union ehci_shadow *pshadow; /* mirror hw periodic table */ | ||
| 405 | int next_uframe; /* scan periodic, start here */ | ||
| 406 | unsigned periodic_sched; /* periodic activity count */ | ||
| 407 | |||
| 408 | /* per root hub port */ | ||
| 409 | unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; | ||
| 410 | /* bit vectors (one bit per port) */ | ||
| 411 | unsigned long bus_suspended; /* which ports were | ||
| 412 | * already suspended at the | ||
| 413 | * start of a bus suspend | ||
| 414 | */ | ||
| 415 | unsigned long companion_ports;/* which ports are dedicated | ||
| 416 | * to the companion controller | ||
| 417 | */ | ||
| 418 | |||
| 419 | struct timer_list watchdog; | ||
| 420 | unsigned long actions; | ||
| 421 | unsigned stamp; | ||
| 422 | unsigned long next_statechange; | ||
| 423 | u32 command; | ||
| 424 | |||
| 425 | /* SILICON QUIRKS */ | ||
| 426 | struct list_head urb_list; /* this is the head to urb | ||
| 427 | * queue that didn't get enough | ||
| 428 | * resources | ||
| 429 | */ | ||
| 430 | struct oxu_murb *murb_pool; /* murb per split big urb */ | ||
| 431 | unsigned urb_len; | ||
| 432 | |||
| 433 | u8 sbrn; /* packed release number */ | ||
| 434 | }; | ||
| 435 | |||
| 436 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | ||
| 437 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | ||
| 438 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | ||
| 439 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | ||
| 440 | |||
| 441 | enum ehci_timer_action { | ||
| 442 | TIMER_IO_WATCHDOG, | ||
| 443 | TIMER_IAA_WATCHDOG, | ||
| 444 | TIMER_ASYNC_SHRINK, | ||
| 445 | TIMER_ASYNC_OFF, | ||
| 446 | }; | ||
| 447 | |||
| 448 | #include <linux/oxu210hp.h> | ||
| @@ -2411,12 +2411,6 @@ static int r8a66597_probe(struct platform_device *pdev) · 2410 unmodified lines | |||
| 2411 | if (usb_disabled()) | 2411 | if (usb_disabled()) |
| 2412 | return -ENODEV; | 2412 | return -ENODEV; |
| 2413 | 2413 | ||
| 2414 | if (pdev->dev.dma_mask) { | ||
| 2415 | ret = -EINVAL; | ||
| 2416 | dev_err(&pdev->dev, "dma not supported\n"); | ||
| 2417 | goto clean_up; | ||
| 2418 | } | ||
| 2419 | |||
| 2420 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2414 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2421 | if (!res) { | 2415 | if (!res) { |
| 2422 | ret = -ENODEV; | 2416 | ret = -ENODEV; |
| @@ -1632,12 +1632,6 @@ sl811h_probe(struct platform_device *dev) · 1631 unmodified lines | |||
| 1632 | irq = ires->start; | 1632 | irq = ires->start; |
| 1633 | irqflags = ires->flags & IRQF_TRIGGER_MASK; | 1633 | irqflags = ires->flags & IRQF_TRIGGER_MASK; |
| 1634 | 1634 | ||
| 1635 | /* refuse to confuse usbcore */ | ||
| 1636 | if (dev->dev.dma_mask) { | ||
| 1637 | dev_dbg(&dev->dev, "no we won't dma\n"); | ||
| 1638 | return -EINVAL; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | /* the chip may be wired for either kind of addressing */ | 1635 | /* the chip may be wired for either kind of addressing */ |
| 1642 | addr = platform_get_resource(dev, IORESOURCE_MEM, 0); | 1636 | addr = platform_get_resource(dev, IORESOURCE_MEM, 0); |
| 1643 | data = platform_get_resource(dev, IORESOURCE_MEM, 1); | 1637 | data = platform_get_resource(dev, IORESOURCE_MEM, 1); |
| @@ -3077,8 +3077,6 @@ static int u132_probe(struct platform_device *pdev) · 3076 unmodified lines | |||
| 3077 | retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); | 3077 | retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); |
| 3078 | if (retval) | 3078 | if (retval) |
| 3079 | return retval; | 3079 | return retval; |
| 3080 | if (pdev->dev.dma_mask) | ||
| 3081 | return -EINVAL; | ||
| 3082 | 3080 | ||
| 3083 | hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev)); | 3081 | hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev)); |
| 3084 | if (!hcd) { | 3082 | if (!hcd) { |
| @@ -63,7 +63,7 @@ static const struct hc_driver uhci_grlib_hc_driver = { · 62 unmodified lines | |||
| 63 | 63 | ||
| 64 | /* Generic hardware linkage */ | 64 | /* Generic hardware linkage */ |
| 65 | .irq = uhci_irq, | 65 | .irq = uhci_irq, |
| 66 | .flags = HCD_MEMORY | HCD_USB11, | 66 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, |
| 67 | 67 | ||
| 68 | /* Basic lifecycle operations */ | 68 | /* Basic lifecycle operations */ |
| 69 | .reset = uhci_grlib_init, | 69 | .reset = uhci_grlib_init, |
| @@ -261,7 +261,7 @@ static const struct hc_driver uhci_driver = { · 260 unmodified lines | |||
| 261 | 261 | ||
| 262 | /* Generic hardware linkage */ | 262 | /* Generic hardware linkage */ |
| 263 | .irq = uhci_irq, | 263 | .irq = uhci_irq, |
| 264 | .flags = HCD_USB11, | 264 | .flags = HCD_DMA | HCD_USB11, |
| 265 | 265 | ||
| 266 | /* Basic lifecycle operations */ | 266 | /* Basic lifecycle operations */ |
| 267 | .reset = uhci_pci_init, | 267 | .reset = uhci_pci_init, |
| @@ -41,7 +41,7 @@ static const struct hc_driver uhci_platform_hc_driver = { · 40 unmodified lines | |||
| 41 | 41 | ||
| 42 | /* Generic hardware linkage */ | 42 | /* Generic hardware linkage */ |
| 43 | .irq = uhci_irq, | 43 | .irq = uhci_irq, |
| 44 | .flags = HCD_MEMORY | HCD_USB11, | 44 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, |
| 45 | 45 | ||
| 46 | /* Basic lifecycle operations */ | 46 | /* Basic lifecycle operations */ |
| 47 | .reset = uhci_platform_init, | 47 | .reset = uhci_platform_init, |
| @@ -22,7 +22,6 @@ dbc_dma_alloc_coherent(struct xhci_hcd *xhci, size_t size, · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | vaddr = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev, | 23 | vaddr = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev, |
| 24 | size, dma_handle, flags); | 24 | size, dma_handle, flags); |
| 25 | memset(vaddr, 0, size); | ||
| 26 | return vaddr; | 25 | return vaddr; |
| 27 | } | 26 | } |
| 28 | 27 | ||
| @@ -139,14 +139,14 @@ xhci_dbc_alloc_requests(struct dbc_ep *dep, struct list_head *head, · 138 unmodified lines | |||
| 139 | struct dbc_request *req; | 139 | struct dbc_request *req; |
| 140 | 140 | ||
| 141 | for (i = 0; i < DBC_QUEUE_SIZE; i++) { | 141 | for (i = 0; i < DBC_QUEUE_SIZE; i++) { |
| 142 | req = dbc_alloc_request(dep, GFP_ATOMIC); | 142 | req = dbc_alloc_request(dep, GFP_KERNEL); |
| 143 | if (!req) | 143 | if (!req) |
| 144 | break; | 144 | break; |
| 145 | 145 | ||
| 146 | req->length = DBC_MAX_PACKET; | 146 | req->length = DBC_MAX_PACKET; |
| 147 | req->buf = kmalloc(req->length, GFP_KERNEL); | 147 | req->buf = kmalloc(req->length, GFP_KERNEL); |
| 148 | if (!req->buf) { | 148 | if (!req->buf) { |
| 149 | xhci_dbc_free_req(dep, req); | 149 | dbc_free_request(dep, req); |
| 150 | break; | 150 | break; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| @@ -6,11 +6,20 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
| 9 | #include <linux/property.h> | ||
| 10 | #include <linux/pci.h> | ||
| 9 | #include "xhci.h" | 11 | #include "xhci.h" |
| 10 | 12 | ||
| 11 | #define USB_SW_DRV_NAME "intel_xhci_usb_sw" | 13 | #define USB_SW_DRV_NAME "intel_xhci_usb_sw" |
| 12 | #define USB_SW_RESOURCE_SIZE 0x400 | 14 | #define USB_SW_RESOURCE_SIZE 0x400 |
| 13 | 15 | ||
| 16 | #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5 | ||
| 17 | |||
| 18 | static const struct property_entry role_switch_props[] = { | ||
| 19 | PROPERTY_ENTRY_BOOL("sw_switch_disable"), | ||
| 20 | {}, | ||
| 21 | }; | ||
| 22 | |||
| 14 | static void xhci_intel_unregister_pdev(void *arg) | 23 | static void xhci_intel_unregister_pdev(void *arg) |
| 15 | { | 24 | { |
| 16 | platform_device_unregister(arg); | 25 | platform_device_unregister(arg); |
| @@ -21,6 +30,7 @@ static int xhci_create_intel_xhci_sw_pdev(struct xhci_hcd *xhci, u32 cap_offset) · 4 unmodified lines | |||
| 21 | struct usb_hcd *hcd = xhci_to_hcd(xhci); | 30 | struct usb_hcd *hcd = xhci_to_hcd(xhci); |
| 22 | struct device *dev = hcd->self.controller; | 31 | struct device *dev = hcd->self.controller; |
| 23 | struct platform_device *pdev; | 32 | struct platform_device *pdev; |
| 33 | struct pci_dev *pci = to_pci_dev(dev); | ||
| 24 | struct resource res = { 0, }; | 34 | struct resource res = { 0, }; |
| 25 | int ret; | 35 | int ret; |
| 26 | 36 | ||
| @@ -43,6 +53,14 @@ static int xhci_create_intel_xhci_sw_pdev(struct xhci_hcd *xhci, u32 cap_offset) · 16 unmodified lines | |||
| 43 | return ret; | 53 | return ret; |
| 44 | } | 54 | } |
| 45 | 55 | ||
| 56 | if (pci->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { | ||
| 57 | ret = platform_device_add_properties(pdev, role_switch_props); | ||
| 58 | if (ret) { | ||
| 59 | dev_err(dev, "failed to register device properties\n"); | ||
| 60 | return ret; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 46 | pdev->dev.parent = dev; | 64 | pdev->dev.parent = dev; |
| 47 | 65 | ||
| 48 | ret = platform_device_add(pdev); | 66 | ret = platform_device_add(pdev); |
| @@ -1149,7 +1149,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 1148 unmodified lines | |||
| 1149 | } | 1149 | } |
| 1150 | port_li = readl(ports[wIndex]->addr + PORTLI); | 1150 | port_li = readl(ports[wIndex]->addr + PORTLI); |
| 1151 | status = xhci_get_ext_port_status(temp, port_li); | 1151 | status = xhci_get_ext_port_status(temp, port_li); |
| 1152 | put_unaligned_le32(cpu_to_le32(status), &buf[4]); | 1152 | put_unaligned_le32(status, &buf[4]); |
| 1153 | } | 1153 | } |
| 1154 | break; | 1154 | break; |
| 1155 | case SetPortFeature: | 1155 | case SetPortFeature: |
| @@ -2399,7 +2399,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) · 2398 unmodified lines | |||
| 2399 | flags); | 2399 | flags); |
| 2400 | if (!xhci->dcbaa) | 2400 | if (!xhci->dcbaa) |
| 2401 | goto fail; | 2401 | goto fail; |
| 2402 | memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); | ||
| 2403 | xhci->dcbaa->dma = dma; | 2402 | xhci->dcbaa->dma = dma; |
| 2404 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2403 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
| 2405 | "// Device context base array address = 0x%llx (DMA), %p (virt)", | 2404 | "// Device context base array address = 0x%llx (DMA), %p (virt)", |
| @@ -216,6 +216,10 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk) · 215 unmodified lines | |||
| 216 | return PTR_ERR(mtk->sys_clk); | 216 | return PTR_ERR(mtk->sys_clk); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | mtk->xhci_clk = devm_clk_get_optional(dev, "xhci_ck"); | ||
| 220 | if (IS_ERR(mtk->xhci_clk)) | ||
| 221 | return PTR_ERR(mtk->xhci_clk); | ||
| 222 | |||
| 219 | mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck"); | 223 | mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck"); |
| 220 | if (IS_ERR(mtk->ref_clk)) | 224 | if (IS_ERR(mtk->ref_clk)) |
| 221 | return PTR_ERR(mtk->ref_clk); | 225 | return PTR_ERR(mtk->ref_clk); |
| @@ -244,6 +248,12 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) · 22 unmodified lines | |||
| 244 | goto sys_clk_err; | 248 | goto sys_clk_err; |
| 245 | } | 249 | } |
| 246 | 250 | ||
| 251 | ret = clk_prepare_enable(mtk->xhci_clk); | ||
| 252 | if (ret) { | ||
| 253 | dev_err(mtk->dev, "failed to enable xhci_clk\n"); | ||
| 254 | goto xhci_clk_err; | ||
| 255 | } | ||
| 256 | |||
| 247 | ret = clk_prepare_enable(mtk->mcu_clk); | 257 | ret = clk_prepare_enable(mtk->mcu_clk); |
| 248 | if (ret) { | 258 | if (ret) { |
| 249 | dev_err(mtk->dev, "failed to enable mcu_clk\n"); | 259 | dev_err(mtk->dev, "failed to enable mcu_clk\n"); |
| @@ -261,6 +271,8 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) · 11 unmodified lines | |||
| 261 | dma_clk_err: | 271 | dma_clk_err: |
| 262 | clk_disable_unprepare(mtk->mcu_clk); | 272 | clk_disable_unprepare(mtk->mcu_clk); |
| 263 | mcu_clk_err: | 273 | mcu_clk_err: |
| 274 | clk_disable_unprepare(mtk->xhci_clk); | ||
| 275 | xhci_clk_err: | ||
| 264 | clk_disable_unprepare(mtk->sys_clk); | 276 | clk_disable_unprepare(mtk->sys_clk); |
| 265 | sys_clk_err: | 277 | sys_clk_err: |
| 266 | clk_disable_unprepare(mtk->ref_clk); | 278 | clk_disable_unprepare(mtk->ref_clk); |
| @@ -272,6 +284,7 @@ static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) · 5 unmodified lines | |||
| 272 | { | 284 | { |
| 273 | clk_disable_unprepare(mtk->dma_clk); | 285 | clk_disable_unprepare(mtk->dma_clk); |
| 274 | clk_disable_unprepare(mtk->mcu_clk); | 286 | clk_disable_unprepare(mtk->mcu_clk); |
| 287 | clk_disable_unprepare(mtk->xhci_clk); | ||
| 275 | clk_disable_unprepare(mtk->sys_clk); | 288 | clk_disable_unprepare(mtk->sys_clk); |
| 276 | clk_disable_unprepare(mtk->ref_clk); | 289 | clk_disable_unprepare(mtk->ref_clk); |
| 277 | } | 290 | } |
| @@ -139,6 +139,7 @@ struct xhci_hcd_mtk { · 138 unmodified lines | |||
| 139 | struct regulator *vusb33; | 139 | struct regulator *vusb33; |
| 140 | struct regulator *vbus; | 140 | struct regulator *vbus; |
| 141 | struct clk *sys_clk; /* sys and mac clock */ | 141 | struct clk *sys_clk; /* sys and mac clock */ |
| 142 | struct clk *xhci_clk; | ||
| 142 | struct clk *ref_clk; | 143 | struct clk *ref_clk; |
| 143 | struct clk *mcu_clk; | 144 | struct clk *mcu_clk; |
| 144 | struct clk *dma_clk; | 145 | struct clk *dma_clk; |
| @@ -66,12 +66,14 @@ static int xhci_priv_resume_quirk(struct usb_hcd *hcd) · 65 unmodified lines | |||
| 66 | 66 | ||
| 67 | static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) | 67 | static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) |
| 68 | { | 68 | { |
| 69 | struct xhci_plat_priv *priv = xhci_to_priv(xhci); | ||
| 70 | |||
| 69 | /* | 71 | /* |
| 70 | * As of now platform drivers don't provide MSI support so we ensure | 72 | * As of now platform drivers don't provide MSI support so we ensure |
| 71 | * here that the generic code does not try to make a pci_dev from our | 73 | * here that the generic code does not try to make a pci_dev from our |
| 72 | * dev struct in order to setup MSI | 74 | * dev struct in order to setup MSI |
| 73 | */ | 75 | */ |
| 74 | xhci->quirks |= XHCI_PLAT; | 76 | xhci->quirks |= XHCI_PLAT | priv->quirks; |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | /* called during probe() after chip reset completes */ | 79 | /* called during probe() after chip reset completes */ |
| @@ -103,17 +105,11 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { · 25 unmodified lines | |||
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 105 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = { | 107 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = { |
| 106 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1, | 108 | SET_XHCI_PLAT_PRIV_FOR_RCAR(XHCI_RCAR_FIRMWARE_NAME_V1) |
| 107 | .init_quirk = xhci_rcar_init_quirk, | ||
| 108 | .plat_start = xhci_rcar_start, | ||
| 109 | .resume_quirk = xhci_rcar_resume_quirk, | ||
| 110 | }; | 109 | }; |
| 111 | 110 | ||
| 112 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { | 111 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { |
| 113 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3, | 112 | SET_XHCI_PLAT_PRIV_FOR_RCAR(XHCI_RCAR_FIRMWARE_NAME_V3) |
| 114 | .init_quirk = xhci_rcar_init_quirk, | ||
| 115 | .plat_start = xhci_rcar_start, | ||
| 116 | .resume_quirk = xhci_rcar_resume_quirk, | ||
| 117 | }; | 113 | }; |
| 118 | 114 | ||
| 119 | static const struct of_device_id usb_xhci_of_match[] = { | 115 | static const struct of_device_id usb_xhci_of_match[] = { |
| @@ -307,7 +303,6 @@ static int xhci_plat_probe(struct platform_device *pdev) · 187 unmodified lines | |||
| 307 | ret = usb_phy_init(hcd->usb_phy); | 303 | ret = usb_phy_init(hcd->usb_phy); |
| 308 | if (ret) | 304 | if (ret) |
| 309 | goto put_usb3_hcd; | 305 | goto put_usb3_hcd; |
| 310 | hcd->skip_phy_initialization = 1; | ||
| 311 | } | 306 | } |
| 312 | 307 | ||
| 313 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); | 308 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); |
| @@ -12,10 +12,12 @@ · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | struct xhci_plat_priv { | 13 | struct xhci_plat_priv { |
| 14 | const char *firmware_name; | 14 | const char *firmware_name; |
| 15 | unsigned long long quirks; | ||
| 15 | void (*plat_start)(struct usb_hcd *); | 16 | void (*plat_start)(struct usb_hcd *); |
| 16 | int (*init_quirk)(struct usb_hcd *); | 17 | int (*init_quirk)(struct usb_hcd *); |
| 17 | int (*resume_quirk)(struct usb_hcd *); | 18 | int (*resume_quirk)(struct usb_hcd *); |
| 18 | }; | 19 | }; |
| 19 | 20 | ||
| 20 | #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) | 21 | #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) |
| 22 | #define xhci_to_priv(x) ((struct xhci_plat_priv *)(x)->priv) | ||
| 21 | #endif /* _XHCI_PLAT_H */ | 23 | #endif /* _XHCI_PLAT_H */ |
| @@ -107,15 +107,6 @@ static int xhci_rcar_is_gen2(struct device *dev) · 106 unmodified lines | |||
| 107 | of_device_is_compatible(node, "renesas,rcar-gen2-xhci"); | 107 | of_device_is_compatible(node, "renesas,rcar-gen2-xhci"); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static int xhci_rcar_is_gen3(struct device *dev) | ||
| 111 | { | ||
| 112 | struct device_node *node = dev->of_node; | ||
| 113 | |||
| 114 | return of_device_is_compatible(node, "renesas,xhci-r8a7795") || | ||
| 115 | of_device_is_compatible(node, "renesas,xhci-r8a7796") || | ||
| 116 | of_device_is_compatible(node, "renesas,rcar-gen3-xhci"); | ||
| 117 | } | ||
| 118 | |||
| 119 | void xhci_rcar_start(struct usb_hcd *hcd) | 110 | void xhci_rcar_start(struct usb_hcd *hcd) |
| 120 | { | 111 | { |
| 121 | u32 temp; | 112 | u32 temp; |
| @@ -226,32 +217,13 @@ static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd) · 104 unmodified lines | |||
| 226 | /* This function needs to initialize a "phy" of usb before */ | 217 | /* This function needs to initialize a "phy" of usb before */ |
| 227 | int xhci_rcar_init_quirk(struct usb_hcd *hcd) | 218 | int xhci_rcar_init_quirk(struct usb_hcd *hcd) |
| 228 | { | 219 | { |
| 229 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
| 230 | |||
| 231 | /* If hcd->regs is NULL, we don't just call the following function */ | 220 | /* If hcd->regs is NULL, we don't just call the following function */ |
| 232 | if (!hcd->regs) | 221 | if (!hcd->regs) |
| 233 | return 0; | 222 | return 0; |
| 234 | 223 | ||
| 235 | /* | ||
| 236 | * On R-Car Gen2 and Gen3, the AC64 bit (bit 0) of HCCPARAMS1 is set | ||
| 237 | * to 1. However, these SoCs don't support 64-bit address memory | ||
| 238 | * pointers. So, this driver clears the AC64 bit of xhci->hcc_params | ||
| 239 | * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in | ||
| 240 | * xhci_gen_setup(). | ||
| 241 | * | ||
| 242 | * And, since the firmware/internal CPU control the USBSTS.STS_HALT | ||
| 243 | * and the process speed is down when the roothub port enters U3, | ||
| 244 | * long delay for the handshake of STS_HALT is neeed in xhci_suspend(). | ||
| 245 | */ | ||
| 246 | if (xhci_rcar_is_gen2(hcd->self.controller) || | ||
| 247 | xhci_rcar_is_gen3(hcd->self.controller)) { | ||
| 248 | xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (!xhci_rcar_wait_for_pll_active(hcd)) | 224 | if (!xhci_rcar_wait_for_pll_active(hcd)) |
| 252 | return -ETIMEDOUT; | 225 | return -ETIMEDOUT; |
| 253 | 226 | ||
| 254 | xhci->quirks |= XHCI_TRUST_TX_LENGTH; | ||
| 255 | return xhci_rcar_download_firmware(hcd); | 227 | return xhci_rcar_download_firmware(hcd); |
| 256 | } | 228 | } |
| 257 | 229 | ||
| @@ -31,4 +31,25 @@ static inline int xhci_rcar_resume_quirk(struct usb_hcd *hcd) · 30 unmodified lines | |||
| 31 | return 0; | 31 | return 0; |
| 32 | } | 32 | } |
| 33 | #endif | 33 | #endif |
| 34 | |||
| 35 | /* | ||
| 36 | * On R-Car Gen2 and Gen3, the AC64 bit (bit 0) of HCCPARAMS1 is set | ||
| 37 | * to 1. However, these SoCs don't support 64-bit address memory | ||
| 38 | * pointers. So, this driver clears the AC64 bit of xhci->hcc_params | ||
| 39 | * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in | ||
| 40 | * xhci_gen_setup() by using the XHCI_NO_64BIT_SUPPORT quirk. | ||
| 41 | * | ||
| 42 | * And, since the firmware/internal CPU control the USBSTS.STS_HALT | ||
| 43 | * and the process speed is down when the roothub port enters U3, | ||
| 44 | * long delay for the handshake of STS_HALT is neeed in xhci_suspend() | ||
| 45 | * by using the XHCI_SLOW_SUSPEND quirk. | ||
| 46 | */ | ||
| 47 | #define SET_XHCI_PLAT_PRIV_FOR_RCAR(firmware) \ | ||
| 48 | .firmware_name = firmware, \ | ||
| 49 | .quirks = XHCI_NO_64BIT_SUPPORT | XHCI_TRUST_TX_LENGTH | \ | ||
| 50 | XHCI_SLOW_SUSPEND, \ | ||
| 51 | .init_quirk = xhci_rcar_init_quirk, \ | ||
| 52 | .plat_start = xhci_rcar_start, \ | ||
| 53 | .resume_quirk = xhci_rcar_resume_quirk, | ||
| 54 | |||
| 34 | #endif /* _XHCI_RCAR_H */ | 55 | #endif /* _XHCI_RCAR_H */ |
| @@ -3814,7 +3814,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) · 3813 unmodified lines | |||
| 3814 | virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; | 3814 | virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; |
| 3815 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); | 3815 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); |
| 3816 | } | 3816 | } |
| 3817 | xhci_debugfs_remove_slot(xhci, udev->slot_id); | ||
| 3818 | virt_dev->udev = NULL; | 3817 | virt_dev->udev = NULL; |
| 3819 | ret = xhci_disable_slot(xhci, udev->slot_id); | 3818 | ret = xhci_disable_slot(xhci, udev->slot_id); |
| 3820 | if (ret) | 3819 | if (ret) |
| @@ -3832,6 +3831,8 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 11 unmodified lines | |||
| 3832 | if (!command) | 3831 | if (!command) |
| 3833 | return -ENOMEM; | 3832 | return -ENOMEM; |
| 3834 | 3833 | ||
| 3834 | xhci_debugfs_remove_slot(xhci, slot_id); | ||
| 3835 | |||
| 3835 | spin_lock_irqsave(&xhci->lock, flags); | 3836 | spin_lock_irqsave(&xhci->lock, flags); |
| 3836 | /* Don't disable the slot if the host controller is dead. */ | 3837 | /* Don't disable the slot if the host controller is dead. */ |
| 3837 | state = readl(&xhci->op_regs->status); | 3838 | state = readl(&xhci->op_regs->status); |
| @@ -5217,7 +5218,7 @@ static const struct hc_driver xhci_hc_driver = { · 1379 unmodified lines | |||
| 5217 | * generic hardware linkage | 5218 | * generic hardware linkage |
| 5218 | */ | 5219 | */ |
| 5219 | .irq = xhci_irq, | 5220 | .irq = xhci_irq, |
| 5220 | .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, | 5221 | .flags = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED, |
| 5221 | 5222 | ||
| 5222 | /* | 5223 | /* |
| 5223 | * basic lifecycle operations | 5224 | * basic lifecycle operations |
| @@ -2337,12 +2337,13 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, · 2336 unmodified lines | |||
| 2337 | break; | 2337 | break; |
| 2338 | case TRB_RESET_EP: | 2338 | case TRB_RESET_EP: |
| 2339 | sprintf(str, | 2339 | sprintf(str, |
| 2340 | "%s: ctx %08x%08x slot %d ep %d flags %c", | 2340 | "%s: ctx %08x%08x slot %d ep %d flags %c:%c", |
| 2341 | xhci_trb_type_string(type), | 2341 | xhci_trb_type_string(type), |
| 2342 | field1, field0, | 2342 | field1, field0, |
| 2343 | TRB_TO_SLOT_ID(field3), | 2343 | TRB_TO_SLOT_ID(field3), |
| 2344 | /* Macro decrements 1, maybe it shouldn't?!? */ | 2344 | /* Macro decrements 1, maybe it shouldn't?!? */ |
| 2345 | TRB_TO_EP_INDEX(field3) + 1, | 2345 | TRB_TO_EP_INDEX(field3) + 1, |
| 2346 | field3 & TRB_TSP ? 'T' : 't', | ||
| 2346 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2347 | field3 & TRB_CYCLE ? 'C' : 'c'); |
| 2347 | break; | 2348 | break; |
| 2348 | case TRB_STOP_RING: | 2349 | case TRB_STOP_RING: |
| @@ -120,9 +120,6 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, · 119 unmodified lines | |||
| 120 | (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled)) | 120 | (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled)) |
| 121 | return -ENODEV; | 121 | return -ENODEV; |
| 122 | 122 | ||
| 123 | /* prevent usb-core allocating DMA pages */ | ||
| 124 | dev->dma_mask = NULL; | ||
| 125 | |||
| 126 | isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); | 123 | isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); |
| 127 | if (!isp) | 124 | if (!isp) |
| 128 | return -ENOMEM; | 125 | return -ENOMEM; |
| @@ -139,7 +139,6 @@ static int isp1761_pci_probe(struct pci_dev *dev, · 138 unmodified lines | |||
| 139 | 139 | ||
| 140 | pci_set_master(dev); | 140 | pci_set_master(dev); |
| 141 | 141 | ||
| 142 | dev->dev.dma_mask = NULL; | ||
| 143 | ret = isp1760_register(&dev->resource[3], dev->irq, 0, &dev->dev, | 142 | ret = isp1760_register(&dev->resource[3], dev->irq, 0, &dev->dev, |
| 144 | devflags); | 143 | devflags); |
| 145 | if (ret < 0) | 144 | if (ret < 0) |
| @@ -183,6 +183,7 @@ static ssize_t port0_show(struct device *dev, · 182 unmodified lines | |||
| 183 | { | 183 | { |
| 184 | return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0); | 184 | return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0); |
| 185 | } | 185 | } |
| 186 | static DEVICE_ATTR_RW(port0); | ||
| 186 | 187 | ||
| 187 | /* attribute callback handler (read) */ | 188 | /* attribute callback handler (read) */ |
| 188 | static ssize_t port1_show(struct device *dev, | 189 | static ssize_t port1_show(struct device *dev, |
| @@ -190,11 +191,14 @@ static ssize_t port1_show(struct device *dev, · 1 unmodified line | |||
| 190 | { | 191 | { |
| 191 | return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); | 192 | return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); |
| 192 | } | 193 | } |
| 193 | |||
| 194 | static DEVICE_ATTR_RW(port0); | ||
| 195 | |||
| 196 | static DEVICE_ATTR_RW(port1); | 194 | static DEVICE_ATTR_RW(port1); |
| 197 | 195 | ||
| 196 | static struct attribute *cypress_attrs[] = { | ||
| 197 | &dev_attr_port0.attr, | ||
| 198 | &dev_attr_port1.attr, | ||
| 199 | NULL, | ||
| 200 | }; | ||
| 201 | ATTRIBUTE_GROUPS(cypress); | ||
| 198 | 202 | ||
| 199 | static int cypress_probe(struct usb_interface *interface, | 203 | static int cypress_probe(struct usb_interface *interface, |
| 200 | const struct usb_device_id *id) | 204 | const struct usb_device_id *id) |
| @@ -212,26 +216,11 @@ static int cypress_probe(struct usb_interface *interface, · 11 unmodified lines | |||
| 212 | /* save our data pointer in this interface device */ | 216 | /* save our data pointer in this interface device */ |
| 213 | usb_set_intfdata(interface, dev); | 217 | usb_set_intfdata(interface, dev); |
| 214 | 218 | ||
| 215 | /* create device attribute files */ | ||
| 216 | retval = device_create_file(&interface->dev, &dev_attr_port0); | ||
| 217 | if (retval) | ||
| 218 | goto error; | ||
| 219 | retval = device_create_file(&interface->dev, &dev_attr_port1); | ||
| 220 | if (retval) | ||
| 221 | goto error; | ||
| 222 | |||
| 223 | /* let the user know that the device is now attached */ | 219 | /* let the user know that the device is now attached */ |
| 224 | dev_info(&interface->dev, | 220 | dev_info(&interface->dev, |
| 225 | "Cypress CY7C63xxx device now attached\n"); | 221 | "Cypress CY7C63xxx device now attached\n"); |
| 226 | return 0; | 222 | return 0; |
| 227 | 223 | ||
| 228 | error: | ||
| 229 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
| 230 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
| 231 | usb_set_intfdata(interface, NULL); | ||
| 232 | usb_put_dev(dev->udev); | ||
| 233 | kfree(dev); | ||
| 234 | |||
| 235 | error_mem: | 224 | error_mem: |
| 236 | return retval; | 225 | return retval; |
| 237 | } | 226 | } |
| @@ -242,9 +231,6 @@ static void cypress_disconnect(struct usb_interface *interface) · 4 unmodified lines | |||
| 242 | 231 | ||
| 243 | dev = usb_get_intfdata(interface); | 232 | dev = usb_get_intfdata(interface); |
| 244 | 233 | ||
| 245 | /* remove device attribute files */ | ||
| 246 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
| 247 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
| 248 | /* the intfdata can be set to NULL only after the | 234 | /* the intfdata can be set to NULL only after the |
| 249 | * device files have been removed */ | 235 | * device files have been removed */ |
| 250 | usb_set_intfdata(interface, NULL); | 236 | usb_set_intfdata(interface, NULL); |
| @@ -262,6 +248,7 @@ static struct usb_driver cypress_driver = { · 11 unmodified lines | |||
| 262 | .probe = cypress_probe, | 248 | .probe = cypress_probe, |
| 263 | .disconnect = cypress_disconnect, | 249 | .disconnect = cypress_disconnect, |
| 264 | .id_table = cypress_table, | 250 | .id_table = cypress_table, |
| 251 | .dev_groups = cypress_groups, | ||
| 265 | }; | 252 | }; |
| 266 | 253 | ||
| 267 | module_usb_driver(cypress_driver); | 254 | module_usb_driver(cypress_driver); |
| @@ -36,20 +36,6 @@ struct usb_cytherm { · 35 unmodified lines | |||
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | /* local function prototypes */ | ||
| 40 | static int cytherm_probe(struct usb_interface *interface, | ||
| 41 | const struct usb_device_id *id); | ||
| 42 | static void cytherm_disconnect(struct usb_interface *interface); | ||
| 43 | |||
| 44 | |||
| 45 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 46 | static struct usb_driver cytherm_driver = { | ||
| 47 | .name = "cytherm", | ||
| 48 | .probe = cytherm_probe, | ||
| 49 | .disconnect = cytherm_disconnect, | ||
| 50 | .id_table = id_table, | ||
| 51 | }; | ||
| 52 | |||
| 53 | /* Vendor requests */ | 39 | /* Vendor requests */ |
| 54 | /* They all operate on one byte at a time */ | 40 | /* They all operate on one byte at a time */ |
| 55 | #define PING 0x00 | 41 | #define PING 0x00 |
| @@ -304,6 +290,15 @@ static ssize_t port1_store(struct device *dev, struct device_attribute *attr, co · 248 unmodified lines | |||
| 304 | } | 290 | } |
| 305 | static DEVICE_ATTR_RW(port1); | 291 | static DEVICE_ATTR_RW(port1); |
| 306 | 292 | ||
| 293 | static struct attribute *cytherm_attrs[] = { | ||
| 294 | &dev_attr_brightness.attr, | ||
| 295 | &dev_attr_temp.attr, | ||
| 296 | &dev_attr_button.attr, | ||
| 297 | &dev_attr_port0.attr, | ||
| 298 | &dev_attr_port1.attr, | ||
| 299 | NULL, | ||
| 300 | }; | ||
| 301 | ATTRIBUTE_GROUPS(cytherm); | ||
| 307 | 302 | ||
| 308 | static int cytherm_probe(struct usb_interface *interface, | 303 | static int cytherm_probe(struct usb_interface *interface, |
| 309 | const struct usb_device_id *id) | 304 | const struct usb_device_id *id) |
| @@ -322,34 +317,10 @@ static int cytherm_probe(struct usb_interface *interface, · 12 unmodified lines | |||
| 322 | 317 | ||
| 323 | dev->brightness = 0xFF; | 318 | dev->brightness = 0xFF; |
| 324 | 319 | ||
| 325 | retval = device_create_file(&interface->dev, &dev_attr_brightness); | ||
| 326 | if (retval) | ||
| 327 | goto error; | ||
| 328 | retval = device_create_file(&interface->dev, &dev_attr_temp); | ||
| 329 | if (retval) | ||
| 330 | goto error; | ||
| 331 | retval = device_create_file(&interface->dev, &dev_attr_button); | ||
| 332 | if (retval) | ||
| 333 | goto error; | ||
| 334 | retval = device_create_file(&interface->dev, &dev_attr_port0); | ||
| 335 | if (retval) | ||
| 336 | goto error; | ||
| 337 | retval = device_create_file(&interface->dev, &dev_attr_port1); | ||
| 338 | if (retval) | ||
| 339 | goto error; | ||
| 340 | |||
| 341 | dev_info (&interface->dev, | 320 | dev_info (&interface->dev, |
| 342 | "Cypress thermometer device now attached\n"); | 321 | "Cypress thermometer device now attached\n"); |
| 343 | return 0; | 322 | return 0; |
| 344 | error: | 323 | |
| 345 | device_remove_file(&interface->dev, &dev_attr_brightness); | ||
| 346 | device_remove_file(&interface->dev, &dev_attr_temp); | ||
| 347 | device_remove_file(&interface->dev, &dev_attr_button); | ||
| 348 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
| 349 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
| 350 | usb_set_intfdata (interface, NULL); | ||
| 351 | usb_put_dev(dev->udev); | ||
| 352 | kfree(dev); | ||
| 353 | error_mem: | 324 | error_mem: |
| 354 | return retval; | 325 | return retval; |
| 355 | } | 326 | } |
| @@ -360,12 +331,6 @@ static void cytherm_disconnect(struct usb_interface *interface) · 4 unmodified lines | |||
| 360 | 331 | ||
| 361 | dev = usb_get_intfdata (interface); | 332 | dev = usb_get_intfdata (interface); |
| 362 | 333 | ||
| 363 | device_remove_file(&interface->dev, &dev_attr_brightness); | ||
| 364 | device_remove_file(&interface->dev, &dev_attr_temp); | ||
| 365 | device_remove_file(&interface->dev, &dev_attr_button); | ||
| 366 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
| 367 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
| 368 | |||
| 369 | /* first remove the files, then NULL the pointer */ | 334 | /* first remove the files, then NULL the pointer */ |
| 370 | usb_set_intfdata (interface, NULL); | 335 | usb_set_intfdata (interface, NULL); |
| 371 | 336 | ||
| @@ -376,6 +341,15 @@ static void cytherm_disconnect(struct usb_interface *interface) · 4 unmodified lines | |||
| 376 | dev_info(&interface->dev, "Cypress thermometer now disconnected\n"); | 341 | dev_info(&interface->dev, "Cypress thermometer now disconnected\n"); |
| 377 | } | 342 | } |
| 378 | 343 | ||
| 344 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 345 | static struct usb_driver cytherm_driver = { | ||
| 346 | .name = "cytherm", | ||
| 347 | .probe = cytherm_probe, | ||
| 348 | .disconnect = cytherm_disconnect, | ||
| 349 | .id_table = id_table, | ||
| 350 | .dev_groups = cytherm_groups, | ||
| 351 | }; | ||
| 352 | |||
| 379 | module_usb_driver(cytherm_driver); | 353 | module_usb_driver(cytherm_driver); |
| 380 | 354 | ||
| 381 | MODULE_AUTHOR(DRIVER_AUTHOR); | 355 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| @@ -310,7 +310,7 @@ static ssize_t enable_compliance_store(struct device *dev, · 309 unmodified lines | |||
| 310 | } | 310 | } |
| 311 | static DEVICE_ATTR_WO(enable_compliance); | 311 | static DEVICE_ATTR_WO(enable_compliance); |
| 312 | 312 | ||
| 313 | static struct attribute *lvs_attributes[] = { | 313 | static struct attribute *lvs_attrs[] = { |
| 314 | &dev_attr_get_dev_desc.attr, | 314 | &dev_attr_get_dev_desc.attr, |
| 315 | &dev_attr_u1_timeout.attr, | 315 | &dev_attr_u1_timeout.attr, |
| 316 | &dev_attr_u2_timeout.attr, | 316 | &dev_attr_u2_timeout.attr, |
| @@ -321,10 +321,7 @@ static struct attribute *lvs_attributes[] = { · 4 unmodified lines | |||
| 321 | &dev_attr_enable_compliance.attr, | 321 | &dev_attr_enable_compliance.attr, |
| 322 | NULL | 322 | NULL |
| 323 | }; | 323 | }; |
| 324 | 324 | ATTRIBUTE_GROUPS(lvs); | |
| 325 | static const struct attribute_group lvs_attr_group = { | ||
| 326 | .attrs = lvs_attributes, | ||
| 327 | }; | ||
| 328 | 325 | ||
| 329 | static void lvs_rh_work(struct work_struct *work) | 326 | static void lvs_rh_work(struct work_struct *work) |
| 330 | { | 327 | { |
| @@ -439,12 +436,6 @@ static int lvs_rh_probe(struct usb_interface *intf, · 108 unmodified lines | |||
| 439 | 436 | ||
| 440 | INIT_WORK(&lvs->rh_work, lvs_rh_work); | 437 | INIT_WORK(&lvs->rh_work, lvs_rh_work); |
| 441 | 438 | ||
| 442 | ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group); | ||
| 443 | if (ret < 0) { | ||
| 444 | dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret); | ||
| 445 | goto free_urb; | ||
| 446 | } | ||
| 447 | |||
| 448 | pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); | 439 | pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); |
| 449 | maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); | 440 | maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); |
| 450 | usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp, | 441 | usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp, |
| @@ -453,13 +444,11 @@ static int lvs_rh_probe(struct usb_interface *intf, · 2 unmodified lines | |||
| 453 | ret = usb_submit_urb(lvs->urb, GFP_KERNEL); | 444 | ret = usb_submit_urb(lvs->urb, GFP_KERNEL); |
| 454 | if (ret < 0) { | 445 | if (ret < 0) { |
| 455 | dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret); | 446 | dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret); |
| 456 | goto sysfs_remove; | 447 | goto free_urb; |
| 457 | } | 448 | } |
| 458 | 449 | ||
| 459 | return ret; | 450 | return ret; |
| 460 | 451 | ||
| 461 | sysfs_remove: | ||
| 462 | sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); | ||
| 463 | free_urb: | 452 | free_urb: |
| 464 | usb_free_urb(lvs->urb); | 453 | usb_free_urb(lvs->urb); |
| 465 | return ret; | 454 | return ret; |
| @@ -469,7 +458,6 @@ static void lvs_rh_disconnect(struct usb_interface *intf) · 3 unmodified lines | |||
| 469 | { | 458 | { |
| 470 | struct lvs_rh *lvs = usb_get_intfdata(intf); | 459 | struct lvs_rh *lvs = usb_get_intfdata(intf); |
| 471 | 460 | ||
| 472 | sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); | ||
| 473 | usb_poison_urb(lvs->urb); /* used in scheduled work */ | 461 | usb_poison_urb(lvs->urb); /* used in scheduled work */ |
| 474 | flush_work(&lvs->rh_work); | 462 | flush_work(&lvs->rh_work); |
| 475 | usb_free_urb(lvs->urb); | 463 | usb_free_urb(lvs->urb); |
| @@ -479,6 +467,7 @@ static struct usb_driver lvs_driver = { · 3 unmodified lines | |||
| 479 | .name = "lvs", | 467 | .name = "lvs", |
| 480 | .probe = lvs_rh_probe, | 468 | .probe = lvs_rh_probe, |
| 481 | .disconnect = lvs_rh_disconnect, | 469 | .disconnect = lvs_rh_disconnect, |
| 470 | .dev_groups = lvs_groups, | ||
| 482 | }; | 471 | }; |
| 483 | 472 | ||
| 484 | module_usb_driver(lvs_driver); | 473 | module_usb_driver(lvs_driver); |
| @@ -51,7 +51,6 @@ struct rio_usb_data { · 50 unmodified lines | |||
| 51 | char *obuf, *ibuf; /* transfer buffers */ | 51 | char *obuf, *ibuf; /* transfer buffers */ |
| 52 | char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ | 52 | char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ |
| 53 | wait_queue_head_t wait_q; /* for timeouts */ | 53 | wait_queue_head_t wait_q; /* for timeouts */ |
| 54 | struct mutex lock; /* general race avoidance */ | ||
| 55 | }; | 54 | }; |
| 56 | 55 | ||
| 57 | static DEFINE_MUTEX(rio500_mutex); | 56 | static DEFINE_MUTEX(rio500_mutex); |
| @@ -63,10 +62,8 @@ static int open_rio(struct inode *inode, struct file *file) · 5 unmodified lines | |||
| 63 | 62 | ||
| 64 | /* against disconnect() */ | 63 | /* against disconnect() */ |
| 65 | mutex_lock(&rio500_mutex); | 64 | mutex_lock(&rio500_mutex); |
| 66 | mutex_lock(&(rio->lock)); | ||
| 67 | 65 | ||
| 68 | if (rio->isopen || !rio->present) { | 66 | if (rio->isopen || !rio->present) { |
| 69 | mutex_unlock(&(rio->lock)); | ||
| 70 | mutex_unlock(&rio500_mutex); | 67 | mutex_unlock(&rio500_mutex); |
| 71 | return -EBUSY; | 68 | return -EBUSY; |
| 72 | } | 69 | } |
| @@ -74,7 +71,6 @@ static int open_rio(struct inode *inode, struct file *file) · 1 unmodified line | |||
| 74 | 71 | ||
| 75 | init_waitqueue_head(&rio->wait_q); | 72 | init_waitqueue_head(&rio->wait_q); |
| 76 | 73 | ||
| 77 | mutex_unlock(&(rio->lock)); | ||
| 78 | 74 | ||
| 79 | dev_info(&rio->rio_dev->dev, "Rio opened.\n"); | 75 | dev_info(&rio->rio_dev->dev, "Rio opened.\n"); |
| 80 | mutex_unlock(&rio500_mutex); | 76 | mutex_unlock(&rio500_mutex); |
| @@ -88,7 +84,6 @@ static int close_rio(struct inode *inode, struct file *file) · 7 unmodified lines | |||
| 88 | 84 | ||
| 89 | /* against disconnect() */ | 85 | /* against disconnect() */ |
| 90 | mutex_lock(&rio500_mutex); | 86 | mutex_lock(&rio500_mutex); |
| 91 | mutex_lock(&(rio->lock)); | ||
| 92 | 87 | ||
| 93 | rio->isopen = 0; | 88 | rio->isopen = 0; |
| 94 | if (!rio->present) { | 89 | if (!rio->present) { |
| @@ -100,7 +95,6 @@ static int close_rio(struct inode *inode, struct file *file) · 5 unmodified lines | |||
| 100 | } else { | 95 | } else { |
| 101 | dev_info(&rio->rio_dev->dev, "Rio closed.\n"); | 96 | dev_info(&rio->rio_dev->dev, "Rio closed.\n"); |
| 102 | } | 97 | } |
| 103 | mutex_unlock(&(rio->lock)); | ||
| 104 | mutex_unlock(&rio500_mutex); | 98 | mutex_unlock(&rio500_mutex); |
| 105 | return 0; | 99 | return 0; |
| 106 | } | 100 | } |
| @@ -115,7 +109,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) · 8 unmodified lines | |||
| 115 | int retries; | 109 | int retries; |
| 116 | int retval=0; | 110 | int retval=0; |
| 117 | 111 | ||
| 118 | mutex_lock(&(rio->lock)); | 112 | mutex_lock(&rio500_mutex); |
| 119 | /* Sanity check to make sure rio is connected, powered, etc */ | 113 | /* Sanity check to make sure rio is connected, powered, etc */ |
| 120 | if (rio->present == 0 || rio->rio_dev == NULL) { | 114 | if (rio->present == 0 || rio->rio_dev == NULL) { |
| 121 | retval = -ENODEV; | 115 | retval = -ENODEV; |
| @@ -259,7 +253,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) · 137 unmodified lines | |||
| 259 | 253 | ||
| 260 | 254 | ||
| 261 | err_out: | 255 | err_out: |
| 262 | mutex_unlock(&(rio->lock)); | 256 | mutex_unlock(&rio500_mutex); |
| 263 | return retval; | 257 | return retval; |
| 264 | } | 258 | } |
| 265 | 259 | ||
| @@ -279,12 +273,12 @@ write_rio(struct file *file, const char __user *buffer, · 13 unmodified lines | |||
| 279 | int errn = 0; | 273 | int errn = 0; |
| 280 | int intr; | 274 | int intr; |
| 281 | 275 | ||
| 282 | intr = mutex_lock_interruptible(&(rio->lock)); | 276 | intr = mutex_lock_interruptible(&rio500_mutex); |
| 283 | if (intr) | 277 | if (intr) |
| 284 | return -EINTR; | 278 | return -EINTR; |
| 285 | /* Sanity check to make sure rio is connected, powered, etc */ | 279 | /* Sanity check to make sure rio is connected, powered, etc */ |
| 286 | if (rio->present == 0 || rio->rio_dev == NULL) { | 280 | if (rio->present == 0 || rio->rio_dev == NULL) { |
| 287 | mutex_unlock(&(rio->lock)); | 281 | mutex_unlock(&rio500_mutex); |
| 288 | return -ENODEV; | 282 | return -ENODEV; |
| 289 | } | 283 | } |
| 290 | 284 | ||
| @@ -307,7 +301,7 @@ write_rio(struct file *file, const char __user *buffer, · 16 unmodified lines | |||
| 307 | goto error; | 301 | goto error; |
| 308 | } | 302 | } |
| 309 | if (signal_pending(current)) { | 303 | if (signal_pending(current)) { |
| 310 | mutex_unlock(&(rio->lock)); | 304 | mutex_unlock(&rio500_mutex); |
| 311 | return bytes_written ? bytes_written : -EINTR; | 305 | return bytes_written ? bytes_written : -EINTR; |
| 312 | } | 306 | } |
| 313 | 307 | ||
| @@ -345,12 +339,12 @@ write_rio(struct file *file, const char __user *buffer, · 31 unmodified lines | |||
| 345 | buffer += copy_size; | 339 | buffer += copy_size; |
| 346 | } while (count > 0); | 340 | } while (count > 0); |
| 347 | 341 | ||
| 348 | mutex_unlock(&(rio->lock)); | 342 | mutex_unlock(&rio500_mutex); |
| 349 | 343 | ||
| 350 | return bytes_written ? bytes_written : -EIO; | 344 | return bytes_written ? bytes_written : -EIO; |
| 351 | 345 | ||
| 352 | error: | 346 | error: |
| 353 | mutex_unlock(&(rio->lock)); | 347 | mutex_unlock(&rio500_mutex); |
| 354 | return errn; | 348 | return errn; |
| 355 | } | 349 | } |
| 356 | 350 | ||
| @@ -367,12 +361,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) · 10 unmodified lines | |||
| 367 | char *ibuf; | 361 | char *ibuf; |
| 368 | int intr; | 362 | int intr; |
| 369 | 363 | ||
| 370 | intr = mutex_lock_interruptible(&(rio->lock)); | 364 | intr = mutex_lock_interruptible(&rio500_mutex); |
| 371 | if (intr) | 365 | if (intr) |
| 372 | return -EINTR; | 366 | return -EINTR; |
| 373 | /* Sanity check to make sure rio is connected, powered, etc */ | 367 | /* Sanity check to make sure rio is connected, powered, etc */ |
| 374 | if (rio->present == 0 || rio->rio_dev == NULL) { | 368 | if (rio->present == 0 || rio->rio_dev == NULL) { |
| 375 | mutex_unlock(&(rio->lock)); | 369 | mutex_unlock(&rio500_mutex); |
| 376 | return -ENODEV; | 370 | return -ENODEV; |
| 377 | } | 371 | } |
| 378 | 372 | ||
| @@ -383,11 +377,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) · 4 unmodified lines | |||
| 383 | 377 | ||
| 384 | while (count > 0) { | 378 | while (count > 0) { |
| 385 | if (signal_pending(current)) { | 379 | if (signal_pending(current)) { |
| 386 | mutex_unlock(&(rio->lock)); | 380 | mutex_unlock(&rio500_mutex); |
| 387 | return read_count ? read_count : -EINTR; | 381 | return read_count ? read_count : -EINTR; |
| 388 | } | 382 | } |
| 389 | if (!rio->rio_dev) { | 383 | if (!rio->rio_dev) { |
| 390 | mutex_unlock(&(rio->lock)); | 384 | mutex_unlock(&rio500_mutex); |
| 391 | return -ENODEV; | 385 | return -ENODEV; |
| 392 | } | 386 | } |
| 393 | this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; | 387 | this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; |
| @@ -405,7 +399,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) · 11 unmodified lines | |||
| 405 | count = this_read = partial; | 399 | count = this_read = partial; |
| 406 | } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ | 400 | } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ |
| 407 | if (!maxretry--) { | 401 | if (!maxretry--) { |
| 408 | mutex_unlock(&(rio->lock)); | 402 | mutex_unlock(&rio500_mutex); |
| 409 | dev_err(&rio->rio_dev->dev, | 403 | dev_err(&rio->rio_dev->dev, |
| 410 | "read_rio: maxretry timeout\n"); | 404 | "read_rio: maxretry timeout\n"); |
| 411 | return -ETIME; | 405 | return -ETIME; |
| @@ -415,19 +409,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) · 3 unmodified lines | |||
| 415 | finish_wait(&rio->wait_q, &wait); | 409 | finish_wait(&rio->wait_q, &wait); |
| 416 | continue; | 410 | continue; |
| 417 | } else if (result != -EREMOTEIO) { | 411 | } else if (result != -EREMOTEIO) { |
| 418 | mutex_unlock(&(rio->lock)); | 412 | mutex_unlock(&rio500_mutex); |
| 419 | dev_err(&rio->rio_dev->dev, | 413 | dev_err(&rio->rio_dev->dev, |
| 420 | "Read Whoops - result:%d partial:%u this_read:%u\n", | 414 | "Read Whoops - result:%d partial:%u this_read:%u\n", |
| 421 | result, partial, this_read); | 415 | result, partial, this_read); |
| 422 | return -EIO; | 416 | return -EIO; |
| 423 | } else { | 417 | } else { |
| 424 | mutex_unlock(&(rio->lock)); | 418 | mutex_unlock(&rio500_mutex); |
| 425 | return (0); | 419 | return (0); |
| 426 | } | 420 | } |
| 427 | 421 | ||
| 428 | if (this_read) { | 422 | if (this_read) { |
| 429 | if (copy_to_user(buffer, ibuf, this_read)) { | 423 | if (copy_to_user(buffer, ibuf, this_read)) { |
| 430 | mutex_unlock(&(rio->lock)); | 424 | mutex_unlock(&rio500_mutex); |
| 431 | return -EFAULT; | 425 | return -EFAULT; |
| 432 | } | 426 | } |
| 433 | count -= this_read; | 427 | count -= this_read; |
| @@ -435,7 +429,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) · 1 unmodified line | |||
| 435 | buffer += this_read; | 429 | buffer += this_read; |
| 436 | } | 430 | } |
| 437 | } | 431 | } |
| 438 | mutex_unlock(&(rio->lock)); | 432 | mutex_unlock(&rio500_mutex); |
| 439 | return read_count; | 433 | return read_count; |
| 440 | } | 434 | } |
| 441 | 435 | ||
| @@ -460,53 +454,55 @@ static int probe_rio(struct usb_interface *intf, · 18 unmodified lines | |||
| 460 | { | 454 | { |
| 461 | struct usb_device *dev = interface_to_usbdev(intf); | 455 | struct usb_device *dev = interface_to_usbdev(intf); |
| 462 | struct rio_usb_data *rio = &rio_instance; | 456 | struct rio_usb_data *rio = &rio_instance; |
| 463 | int retval = 0; | 457 | int retval = -ENOMEM; |
| 458 | char *ibuf, *obuf; | ||
| 464 | 459 | ||
| 465 | mutex_lock(&rio500_mutex); | ||
| 466 | if (rio->present) { | 460 | if (rio->present) { |
| 467 | dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); | 461 | dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); |
| 468 | retval = -EBUSY; | 462 | return -EBUSY; |
| 469 | goto bail_out; | ||
| 470 | } else { | ||
| 471 | dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); | ||
| 472 | } | 463 | } |
| 464 | dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); | ||
| 473 | 465 | ||
| 474 | retval = usb_register_dev(intf, &usb_rio_class); | 466 | obuf = kmalloc(OBUF_SIZE, GFP_KERNEL); |
| 475 | if (retval) { | 467 | if (!obuf) { |
| 476 | dev_err(&dev->dev, | ||
| 477 | "Not able to get a minor for this device.\n"); | ||
| 478 | retval = -ENOMEM; | ||
| 479 | goto bail_out; | ||
| 480 | } | ||
| 481 | |||
| 482 | rio->rio_dev = dev; | ||
| 483 | |||
| 484 | if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) { | ||
| 485 | dev_err(&dev->dev, | 468 | dev_err(&dev->dev, |
| 486 | "probe_rio: Not enough memory for the output buffer\n"); | 469 | "probe_rio: Not enough memory for the output buffer\n"); |
| 487 | usb_deregister_dev(intf, &usb_rio_class); | 470 | goto err_obuf; |
| 488 | retval = -ENOMEM; | ||
| 489 | goto bail_out; | ||
| 490 | } | 471 | } |
| 491 | dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); | 472 | dev_dbg(&intf->dev, "obuf address: %p\n", obuf); |
| 492 | 473 | ||
| 493 | if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) { | 474 | ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL); |
| 475 | if (!ibuf) { | ||
| 494 | dev_err(&dev->dev, | 476 | dev_err(&dev->dev, |
| 495 | "probe_rio: Not enough memory for the input buffer\n"); | 477 | "probe_rio: Not enough memory for the input buffer\n"); |
| 496 | usb_deregister_dev(intf, &usb_rio_class); | 478 | goto err_ibuf; |
| 497 | kfree(rio->obuf); | ||
| 498 | retval = -ENOMEM; | ||
| 499 | goto bail_out; | ||
| 500 | } | 479 | } |
| 501 | dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); | 480 | dev_dbg(&intf->dev, "ibuf address: %p\n", ibuf); |
| 502 | |||
| 503 | mutex_init(&(rio->lock)); | ||
| 504 | 481 | ||
| 505 | usb_set_intfdata (intf, rio); | 482 | mutex_lock(&rio500_mutex); |
| 483 | rio->rio_dev = dev; | ||
| 484 | rio->ibuf = ibuf; | ||
| 485 | rio->obuf = obuf; | ||
| 506 | rio->present = 1; | 486 | rio->present = 1; |
| 507 | bail_out: | ||
| 508 | mutex_unlock(&rio500_mutex); | 487 | mutex_unlock(&rio500_mutex); |
| 509 | 488 | ||
| 489 | retval = usb_register_dev(intf, &usb_rio_class); | ||
| 490 | if (retval) { | ||
| 491 | dev_err(&dev->dev, | ||
| 492 | "Not able to get a minor for this device.\n"); | ||
| 493 | goto err_register; | ||
| 494 | } | ||
| 495 | |||
| 496 | usb_set_intfdata(intf, rio); | ||
| 497 | return retval; | ||
| 498 | |||
| 499 | err_register: | ||
| 500 | mutex_lock(&rio500_mutex); | ||
| 501 | rio->present = 0; | ||
| 502 | mutex_unlock(&rio500_mutex); | ||
| 503 | err_ibuf: | ||
| 504 | kfree(obuf); | ||
| 505 | err_obuf: | ||
| 510 | return retval; | 506 | return retval; |
| 511 | } | 507 | } |
| 512 | 508 | ||
| @@ -515,16 +511,14 @@ static void disconnect_rio(struct usb_interface *intf) · 2 unmodified lines | |||
| 515 | struct rio_usb_data *rio = usb_get_intfdata (intf); | 511 | struct rio_usb_data *rio = usb_get_intfdata (intf); |
| 516 | 512 | ||
| 517 | usb_set_intfdata (intf, NULL); | 513 | usb_set_intfdata (intf, NULL); |
| 518 | mutex_lock(&rio500_mutex); | ||
| 519 | if (rio) { | 514 | if (rio) { |
| 520 | usb_deregister_dev(intf, &usb_rio_class); | 515 | usb_deregister_dev(intf, &usb_rio_class); |
| 521 | 516 | ||
| 522 | mutex_lock(&(rio->lock)); | 517 | mutex_lock(&rio500_mutex); |
| 523 | if (rio->isopen) { | 518 | if (rio->isopen) { |
| 524 | rio->isopen = 0; | 519 | rio->isopen = 0; |
| 525 | /* better let it finish - the release will do whats needed */ | 520 | /* better let it finish - the release will do whats needed */ |
| 526 | rio->rio_dev = NULL; | 521 | rio->rio_dev = NULL; |
| 527 | mutex_unlock(&(rio->lock)); | ||
| 528 | mutex_unlock(&rio500_mutex); | 522 | mutex_unlock(&rio500_mutex); |
| 529 | return; | 523 | return; |
| 530 | } | 524 | } |
| @@ -534,9 +528,8 @@ static void disconnect_rio(struct usb_interface *intf) · 3 unmodified lines | |||
| 534 | dev_info(&intf->dev, "USB Rio disconnected.\n"); | 528 | dev_info(&intf->dev, "USB Rio disconnected.\n"); |
| 535 | 529 | ||
| 536 | rio->present = 0; | 530 | rio->present = 0; |
| 537 | mutex_unlock(&(rio->lock)); | 531 | mutex_unlock(&rio500_mutex); |
| 538 | } | 532 | } |
| 539 | mutex_unlock(&rio500_mutex); | ||
| 540 | } | 533 | } |
| 541 | 534 | ||
| 542 | static const struct usb_device_id rio_table[] = { | 535 | static const struct usb_device_id rio_table[] = { |
| @@ -71,9 +71,14 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr, · 70 unmodified lines | |||
| 71 | } | 71 | } |
| 72 | return count; | 72 | return count; |
| 73 | } | 73 | } |
| 74 | |||
| 75 | static DEVICE_ATTR_RW(speed); | 74 | static DEVICE_ATTR_RW(speed); |
| 76 | 75 | ||
| 76 | static struct attribute *tv_attrs[] = { | ||
| 77 | &dev_attr_speed.attr, | ||
| 78 | NULL, | ||
| 79 | }; | ||
| 80 | ATTRIBUTE_GROUPS(tv); | ||
| 81 | |||
| 77 | static int tv_probe(struct usb_interface *interface, | 82 | static int tv_probe(struct usb_interface *interface, |
| 78 | const struct usb_device_id *id) | 83 | const struct usb_device_id *id) |
| 79 | { | 84 | { |
| @@ -89,15 +94,9 @@ static int tv_probe(struct usb_interface *interface, · 9 unmodified lines | |||
| 89 | 94 | ||
| 90 | dev->udev = usb_get_dev(udev); | 95 | dev->udev = usb_get_dev(udev); |
| 91 | usb_set_intfdata(interface, dev); | 96 | usb_set_intfdata(interface, dev); |
| 92 | retval = device_create_file(&interface->dev, &dev_attr_speed); | ||
| 93 | if (retval) | ||
| 94 | goto error_create_file; | ||
| 95 | 97 | ||
| 96 | return 0; | 98 | return 0; |
| 97 | 99 | ||
| 98 | error_create_file: | ||
| 99 | usb_put_dev(udev); | ||
| 100 | usb_set_intfdata(interface, NULL); | ||
| 101 | error: | 100 | error: |
| 102 | kfree(dev); | 101 | kfree(dev); |
| 103 | return retval; | 102 | return retval; |
| @@ -108,7 +107,6 @@ static void tv_disconnect(struct usb_interface *interface) · 4 unmodified lines | |||
| 108 | struct trancevibrator *dev; | 107 | struct trancevibrator *dev; |
| 109 | 108 | ||
| 110 | dev = usb_get_intfdata (interface); | 109 | dev = usb_get_intfdata (interface); |
| 111 | device_remove_file(&interface->dev, &dev_attr_speed); | ||
| 112 | usb_set_intfdata(interface, NULL); | 110 | usb_set_intfdata(interface, NULL); |
| 113 | usb_put_dev(dev->udev); | 111 | usb_put_dev(dev->udev); |
| 114 | kfree(dev); | 112 | kfree(dev); |
| @@ -120,6 +118,7 @@ static struct usb_driver tv_driver = { · 5 unmodified lines | |||
| 120 | .probe = tv_probe, | 118 | .probe = tv_probe, |
| 121 | .disconnect = tv_disconnect, | 119 | .disconnect = tv_disconnect, |
| 122 | .id_table = id_table, | 120 | .id_table = id_table, |
| 121 | .dev_groups = tv_groups, | ||
| 123 | }; | 122 | }; |
| 124 | 123 | ||
| 125 | module_usb_driver(tv_driver); | 124 | module_usb_driver(tv_driver); |
| @@ -316,7 +316,7 @@ MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered); · 315 unmodified lines | |||
| 316 | MYDEV_ATTR_SIMPLE_UNSIGNED(mode_msb, update_display_mode); | 316 | MYDEV_ATTR_SIMPLE_UNSIGNED(mode_msb, update_display_mode); |
| 317 | MYDEV_ATTR_SIMPLE_UNSIGNED(mode_lsb, update_display_mode); | 317 | MYDEV_ATTR_SIMPLE_UNSIGNED(mode_lsb, update_display_mode); |
| 318 | 318 | ||
| 319 | static struct attribute *dev_attrs[] = { | 319 | static struct attribute *sevseg_attrs[] = { |
| 320 | &dev_attr_powered.attr, | 320 | &dev_attr_powered.attr, |
| 321 | &dev_attr_text.attr, | 321 | &dev_attr_text.attr, |
| 322 | &dev_attr_textmode.attr, | 322 | &dev_attr_textmode.attr, |
| @@ -325,10 +325,7 @@ static struct attribute *dev_attrs[] = { · 2 unmodified lines | |||
| 325 | &dev_attr_mode_lsb.attr, | 325 | &dev_attr_mode_lsb.attr, |
| 326 | NULL | 326 | NULL |
| 327 | }; | 327 | }; |
| 328 | 328 | ATTRIBUTE_GROUPS(sevseg); | |
| 329 | static const struct attribute_group dev_attr_grp = { | ||
| 330 | .attrs = dev_attrs, | ||
| 331 | }; | ||
| 332 | 329 | ||
| 333 | static int sevseg_probe(struct usb_interface *interface, | 330 | static int sevseg_probe(struct usb_interface *interface, |
| 334 | const struct usb_device_id *id) | 331 | const struct usb_device_id *id) |
| @@ -354,17 +351,9 @@ static int sevseg_probe(struct usb_interface *interface, · 19 unmodified lines | |||
| 354 | mydev->mode_msb = 0x06; /* 6 characters */ | 351 | mydev->mode_msb = 0x06; /* 6 characters */ |
| 355 | mydev->mode_lsb = 0x3f; /* scanmode for 6 chars */ | 352 | mydev->mode_lsb = 0x3f; /* scanmode for 6 chars */ |
| 356 | 353 | ||
| 357 | rc = sysfs_create_group(&interface->dev.kobj, &dev_attr_grp); | ||
| 358 | if (rc) | ||
| 359 | goto error; | ||
| 360 | |||
| 361 | dev_info(&interface->dev, "USB 7 Segment device now attached\n"); | 354 | dev_info(&interface->dev, "USB 7 Segment device now attached\n"); |
| 362 | return 0; | 355 | return 0; |
| 363 | 356 | ||
| 364 | error: | ||
| 365 | usb_set_intfdata(interface, NULL); | ||
| 366 | usb_put_dev(mydev->udev); | ||
| 367 | kfree(mydev); | ||
| 368 | error_mem: | 357 | error_mem: |
| 369 | return rc; | 358 | return rc; |
| 370 | } | 359 | } |
| @@ -374,7 +363,6 @@ static void sevseg_disconnect(struct usb_interface *interface) · 3 unmodified lines | |||
| 374 | struct usb_sevsegdev *mydev; | 363 | struct usb_sevsegdev *mydev; |
| 375 | 364 | ||
| 376 | mydev = usb_get_intfdata(interface); | 365 | mydev = usb_get_intfdata(interface); |
| 377 | sysfs_remove_group(&interface->dev.kobj, &dev_attr_grp); | ||
| 378 | usb_set_intfdata(interface, NULL); | 366 | usb_set_intfdata(interface, NULL); |
| 379 | usb_put_dev(mydev->udev); | 367 | usb_put_dev(mydev->udev); |
| 380 | kfree(mydev); | 368 | kfree(mydev); |
| @@ -423,6 +411,7 @@ static struct usb_driver sevseg_driver = { · 42 unmodified lines | |||
| 423 | .resume = sevseg_resume, | 411 | .resume = sevseg_resume, |
| 424 | .reset_resume = sevseg_reset_resume, | 412 | .reset_resume = sevseg_reset_resume, |
| 425 | .id_table = id_table, | 413 | .id_table = id_table, |
| 414 | .dev_groups = sevseg_groups, | ||
| 426 | .supports_autosuspend = 1, | 415 | .supports_autosuspend = 1, |
| 427 | }; | 416 | }; |
| 428 | 417 | ||
| @@ -44,6 +44,7 @@ config USB_MTU3_DUAL_ROLE · 43 unmodified lines | |||
| 44 | bool "Dual Role mode" | 44 | bool "Dual Role mode" |
| 45 | depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) | 45 | depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) |
| 46 | depends on (EXTCON=y || EXTCON=USB_MTU3) | 46 | depends on (EXTCON=y || EXTCON=USB_MTU3) |
| 47 | select USB_ROLE_SWITCH | ||
| 47 | help | 48 | help |
| 48 | This is the default mode of working of MTU3 controller where | 49 | This is the default mode of working of MTU3 controller where |
| 49 | both host and gadget features are enabled. | 50 | both host and gadget features are enabled. |
| @@ -199,6 +199,9 @@ struct mtu3_gpd_ring { · 198 unmodified lines | |||
| 199 | * @id_nb : notifier for iddig(idpin) detection | 199 | * @id_nb : notifier for iddig(idpin) detection |
| 200 | * @id_work : work of iddig detection notifier | 200 | * @id_work : work of iddig detection notifier |
| 201 | * @id_event : event of iddig detecion notifier | 201 | * @id_event : event of iddig detecion notifier |
| 202 | * @role_sw : use USB Role Switch to support dual-role switch, can't use | ||
| 203 | * extcon at the same time, and extcon is deprecated. | ||
| 204 | * @role_sw_used : true when the USB Role Switch is used. | ||
| 202 | * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not | 205 | * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not |
| 203 | * @manual_drd_enabled: it's true when supports dual-role device by debugfs | 206 | * @manual_drd_enabled: it's true when supports dual-role device by debugfs |
| 204 | * to switch host/device modes depending on user input. | 207 | * to switch host/device modes depending on user input. |
| @@ -212,6 +215,8 @@ struct otg_switch_mtk { · 7 unmodified lines | |||
| 212 | struct notifier_block id_nb; | 215 | struct notifier_block id_nb; |
| 213 | struct work_struct id_work; | 216 | struct work_struct id_work; |
| 214 | unsigned long id_event; | 217 | unsigned long id_event; |
| 218 | struct usb_role_switch *role_sw; | ||
| 219 | bool role_sw_used; | ||
| 215 | bool is_u3_drd; | 220 | bool is_u3_drd; |
| 216 | bool manual_drd_enabled; | 221 | bool manual_drd_enabled; |
| 217 | }; | 222 | }; |
| @@ -835,10 +835,8 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) · 834 unmodified lines | |||
| 835 | return -ENOMEM; | 835 | return -ENOMEM; |
| 836 | 836 | ||
| 837 | mtu->irq = platform_get_irq(pdev, 0); | 837 | mtu->irq = platform_get_irq(pdev, 0); |
| 838 | if (mtu->irq < 0) { | 838 | if (mtu->irq < 0) |
| 839 | dev_err(dev, "fail to get irq number\n"); | ||
| 840 | return mtu->irq; | 839 | return mtu->irq; |
| 841 | } | ||
| 842 | dev_info(dev, "irq %d\n", mtu->irq); | 840 | dev_info(dev, "irq %d\n", mtu->irq); |
| 843 | 841 | ||
| 844 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); | 842 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); |
| @@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, · 452 unmodified lines | |||
| 453 | return -EFAULT; | 453 | return -EFAULT; |
| 454 | 454 | ||
| 455 | if (!strncmp(buf, "host", 4) && !ssusb->is_host) { | 455 | if (!strncmp(buf, "host", 4) && !ssusb->is_host) { |
| 456 | ssusb_mode_manual_switch(ssusb, 1); | 456 | ssusb_mode_switch(ssusb, 1); |
| 457 | } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { | 457 | } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { |
| 458 | ssusb_mode_manual_switch(ssusb, 0); | 458 | ssusb_mode_switch(ssusb, 0); |
| 459 | } else { | 459 | } else { |
| 460 | dev_err(ssusb->dev, "wrong or duplicated setting\n"); | 460 | dev_err(ssusb->dev, "wrong or duplicated setting\n"); |
| 461 | return -EINVAL; | 461 | return -EINVAL; |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | |||
| 7 | * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> | 7 | * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/usb/role.h> | ||
| 11 | |||
| 10 | #include "mtu3.h" | 12 | #include "mtu3.h" |
| 11 | #include "mtu3_dr.h" | 13 | #include "mtu3_dr.h" |
| 12 | #include "mtu3_debug.h" | 14 | #include "mtu3_debug.h" |
| @@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) · 267 unmodified lines | |||
| 280 | * This is useful in special cases, such as uses TYPE-A receptacle but also | 282 | * This is useful in special cases, such as uses TYPE-A receptacle but also |
| 281 | * wants to support dual-role mode. | 283 | * wants to support dual-role mode. |
| 282 | */ | 284 | */ |
| 283 | void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) | 285 | void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) |
| 284 | { | 286 | { |
| 285 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; | 287 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; |
| 286 | 288 | ||
| @@ -318,6 +320,47 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, · 31 unmodified lines | |||
| 318 | mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); | 320 | mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); |
| 319 | } | 321 | } |
| 320 | 322 | ||
| 323 | static int ssusb_role_sw_set(struct device *dev, enum usb_role role) | ||
| 324 | { | ||
| 325 | struct ssusb_mtk *ssusb = dev_get_drvdata(dev); | ||
| 326 | bool to_host = false; | ||
| 327 | |||
| 328 | if (role == USB_ROLE_HOST) | ||
| 329 | to_host = true; | ||
| 330 | |||
| 331 | if (to_host ^ ssusb->is_host) | ||
| 332 | ssusb_mode_switch(ssusb, to_host); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static enum usb_role ssusb_role_sw_get(struct device *dev) | ||
| 338 | { | ||
| 339 | struct ssusb_mtk *ssusb = dev_get_drvdata(dev); | ||
| 340 | enum usb_role role; | ||
| 341 | |||
| 342 | role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; | ||
| 343 | |||
| 344 | return role; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) | ||
| 348 | { | ||
| 349 | struct usb_role_switch_desc role_sx_desc = { 0 }; | ||
| 350 | struct ssusb_mtk *ssusb = | ||
| 351 | container_of(otg_sx, struct ssusb_mtk, otg_switch); | ||
| 352 | |||
| 353 | if (!otg_sx->role_sw_used) | ||
| 354 | return 0; | ||
| 355 | |||
| 356 | role_sx_desc.set = ssusb_role_sw_set; | ||
| 357 | role_sx_desc.get = ssusb_role_sw_get; | ||
| 358 | role_sx_desc.fwnode = dev_fwnode(ssusb->dev); | ||
| 359 | otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc); | ||
| 360 | |||
| 361 | return PTR_ERR_OR_ZERO(otg_sx->role_sw); | ||
| 362 | } | ||
| 363 | |||
| 321 | int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) | 364 | int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) |
| 322 | { | 365 | { |
| 323 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; | 366 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; |
| @@ -328,6 +371,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) · 4 unmodified lines | |||
| 328 | 371 | ||
| 329 | if (otg_sx->manual_drd_enabled) | 372 | if (otg_sx->manual_drd_enabled) |
| 330 | ssusb_dr_debugfs_init(ssusb); | 373 | ssusb_dr_debugfs_init(ssusb); |
| 374 | else if (otg_sx->role_sw_used) | ||
| 375 | ret = ssusb_role_sw_register(otg_sx); | ||
| 331 | else | 376 | else |
| 332 | ret = ssusb_extcon_register(otg_sx); | 377 | ret = ssusb_extcon_register(otg_sx); |
| 333 | 378 | ||
| @@ -340,4 +385,5 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) · 6 unmodified lines | |||
| 340 | 385 | ||
| 341 | cancel_work_sync(&otg_sx->id_work); | 386 | cancel_work_sync(&otg_sx->id_work); |
| 342 | cancel_work_sync(&otg_sx->vbus_work); | 387 | cancel_work_sync(&otg_sx->vbus_work); |
| 388 | usb_role_switch_unregister(otg_sx->role_sw); | ||
| 343 | } | 389 | } |
| @@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb) · 70 unmodified lines | |||
| 71 | #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE) | 71 | #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE) |
| 72 | int ssusb_otg_switch_init(struct ssusb_mtk *ssusb); | 72 | int ssusb_otg_switch_init(struct ssusb_mtk *ssusb); |
| 73 | void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb); | 73 | void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb); |
| 74 | void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host); | 74 | void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host); |
| 75 | int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on); | 75 | int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on); |
| 76 | void ssusb_set_force_mode(struct ssusb_mtk *ssusb, | 76 | void ssusb_set_force_mode(struct ssusb_mtk *ssusb, |
| 77 | enum mtu3_dr_force_mode mode); | 77 | enum mtu3_dr_force_mode mode); |
| @@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) · 8 unmodified lines | |||
| 86 | static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) | 86 | static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) |
| 87 | {} | 87 | {} |
| 88 | 88 | ||
| 89 | static inline void | 89 | static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) |
| 90 | ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {} | 90 | {} |
| 91 | 91 | ||
| 92 | static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) | 92 | static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) |
| 93 | { | 93 | { |
| @@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) · 298 unmodified lines | |||
| 299 | otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); | 299 | otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); |
| 300 | otg_sx->manual_drd_enabled = | 300 | otg_sx->manual_drd_enabled = |
| 301 | of_property_read_bool(node, "enable-manual-drd"); | 301 | of_property_read_bool(node, "enable-manual-drd"); |
| 302 | otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch"); | ||
| 302 | 303 | ||
| 303 | if (of_property_read_bool(node, "extcon")) { | 304 | if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) { |
| 304 | otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); | 305 | otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); |
| 305 | if (IS_ERR(otg_sx->edev)) { | 306 | if (IS_ERR(otg_sx->edev)) { |
| 306 | dev_err(ssusb->dev, "couldn't get extcon device\n"); | 307 | dev_err(ssusb->dev, "couldn't get extcon device\n"); |
| @@ -1721,7 +1721,7 @@ mode_show(struct device *dev, struct device_attribute *attr, char *buf) · 1720 unmodified lines | |||
| 1721 | { | 1721 | { |
| 1722 | struct musb *musb = dev_to_musb(dev); | 1722 | struct musb *musb = dev_to_musb(dev); |
| 1723 | unsigned long flags; | 1723 | unsigned long flags; |
| 1724 | int ret = -EINVAL; | 1724 | int ret; |
| 1725 | 1725 | ||
| 1726 | spin_lock_irqsave(&musb->lock, flags); | 1726 | spin_lock_irqsave(&musb->lock, flags); |
| 1727 | ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->otg->state)); | 1727 | ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->otg->state)); |
| @@ -1829,16 +1829,13 @@ static ssize_t srp_store(struct device *dev, struct device_attribute *attr, · 101 unmodified lines | |||
| 1829 | } | 1829 | } |
| 1830 | static DEVICE_ATTR_WO(srp); | 1830 | static DEVICE_ATTR_WO(srp); |
| 1831 | 1831 | ||
| 1832 | static struct attribute *musb_attributes[] = { | 1832 | static struct attribute *musb_attrs[] = { |
| 1833 | &dev_attr_mode.attr, | 1833 | &dev_attr_mode.attr, |
| 1834 | &dev_attr_vbus.attr, | 1834 | &dev_attr_vbus.attr, |
| 1835 | &dev_attr_srp.attr, | 1835 | &dev_attr_srp.attr, |
| 1836 | NULL | 1836 | NULL |
| 1837 | }; | 1837 | }; |
| 1838 | 1838 | ATTRIBUTE_GROUPS(musb); | |
| 1839 | static const struct attribute_group musb_attr_group = { | ||
| 1840 | .attrs = musb_attributes, | ||
| 1841 | }; | ||
| 1842 | 1839 | ||
| 1843 | #define MUSB_QUIRK_B_INVALID_VBUS_91 (MUSB_DEVCTL_BDEVICE | \ | 1840 | #define MUSB_QUIRK_B_INVALID_VBUS_91 (MUSB_DEVCTL_BDEVICE | \ |
| 1844 | (2 << MUSB_DEVCTL_VBUS_SHIFT) | \ | 1841 | (2 << MUSB_DEVCTL_VBUS_SHIFT) | \ |
| @@ -2038,10 +2035,6 @@ static void musb_free(struct musb *musb) · 193 unmodified lines | |||
| 2038 | * cleanup after everything's been de-activated. | 2035 | * cleanup after everything's been de-activated. |
| 2039 | */ | 2036 | */ |
| 2040 | 2037 | ||
| 2041 | #ifdef CONFIG_SYSFS | ||
| 2042 | sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); | ||
| 2043 | #endif | ||
| 2044 | |||
| 2045 | if (musb->nIrq >= 0) { | 2038 | if (musb->nIrq >= 0) { |
| 2046 | if (musb->irq_wake) | 2039 | if (musb->irq_wake) |
| 2047 | disable_irq_wake(musb->nIrq); | 2040 | disable_irq_wake(musb->nIrq); |
| @@ -2390,22 +2383,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) · 342 unmodified lines | |||
| 2390 | 2383 | ||
| 2391 | musb_init_debugfs(musb); | 2384 | musb_init_debugfs(musb); |
| 2392 | 2385 | ||
| 2393 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); | ||
| 2394 | if (status) | ||
| 2395 | goto fail5; | ||
| 2396 | |||
| 2397 | musb->is_initialized = 1; | 2386 | musb->is_initialized = 1; |
| 2398 | pm_runtime_mark_last_busy(musb->controller); | 2387 | pm_runtime_mark_last_busy(musb->controller); |
| 2399 | pm_runtime_put_autosuspend(musb->controller); | 2388 | pm_runtime_put_autosuspend(musb->controller); |
| 2400 | 2389 | ||
| 2401 | return 0; | 2390 | return 0; |
| 2402 | 2391 | ||
| 2403 | fail5: | ||
| 2404 | musb_exit_debugfs(musb); | ||
| 2405 | |||
| 2406 | musb_gadget_cleanup(musb); | ||
| 2407 | musb_host_cleanup(musb); | ||
| 2408 | |||
| 2409 | fail3: | 2392 | fail3: |
| 2410 | cancel_delayed_work_sync(&musb->irq_work); | 2393 | cancel_delayed_work_sync(&musb->irq_work); |
| 2411 | cancel_delayed_work_sync(&musb->finish_resume_work); | 2394 | cancel_delayed_work_sync(&musb->finish_resume_work); |
| @@ -2798,6 +2781,7 @@ static struct platform_driver musb_driver = { · 386 unmodified lines | |||
| 2798 | .name = (char *)musb_driver_name, | 2781 | .name = (char *)musb_driver_name, |
| 2799 | .bus = &platform_bus_type, | 2782 | .bus = &platform_bus_type, |
| 2800 | .pm = MUSB_DEV_PM_OPS, | 2783 | .pm = MUSB_DEV_PM_OPS, |
| 2784 | .dev_groups = musb_groups, | ||
| 2801 | }, | 2785 | }, |
| 2802 | .probe = musb_probe, | 2786 | .probe = musb_probe, |
| 2803 | .remove = musb_remove, | 2787 | .remove = musb_remove, |
| @@ -2689,7 +2689,7 @@ static const struct hc_driver musb_hc_driver = { · 2688 unmodified lines | |||
| 2689 | .description = "musb-hcd", | 2689 | .description = "musb-hcd", |
| 2690 | .product_desc = "MUSB HDRC host driver", | 2690 | .product_desc = "MUSB HDRC host driver", |
| 2691 | .hcd_priv_size = sizeof(struct musb *), | 2691 | .hcd_priv_size = sizeof(struct musb *), |
| 2692 | .flags = HCD_USB2 | HCD_MEMORY, | 2692 | .flags = HCD_USB2 | HCD_DMA | HCD_MEMORY, |
| 2693 | 2693 | ||
| 2694 | /* not using irq handler or reset hooks from usbcore, since | 2694 | /* not using irq handler or reset hooks from usbcore, since |
| 2695 | * those must be shared with peripheral code for OTG configs | 2695 | * those must be shared with peripheral code for OTG configs |
| @@ -330,6 +330,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, · 329 unmodified lines | |||
| 330 | switch (lsts) { | 330 | switch (lsts) { |
| 331 | case USB_LINK_ACA_RID_B_8505: | 331 | case USB_LINK_ACA_RID_B_8505: |
| 332 | event = UX500_MUSB_RIDB; | 332 | event = UX500_MUSB_RIDB; |
| 333 | /* Fall through */ | ||
| 333 | case USB_LINK_NOT_CONFIGURED_8505: | 334 | case USB_LINK_NOT_CONFIGURED_8505: |
| 334 | case USB_LINK_RESERVED0_8505: | 335 | case USB_LINK_RESERVED0_8505: |
| 335 | case USB_LINK_RESERVED1_8505: | 336 | case USB_LINK_RESERVED1_8505: |
| @@ -350,6 +351,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, · 14 unmodified lines | |||
| 350 | 351 | ||
| 351 | case USB_LINK_ACA_RID_C_NM_8505: | 352 | case USB_LINK_ACA_RID_C_NM_8505: |
| 352 | event = UX500_MUSB_RIDC; | 353 | event = UX500_MUSB_RIDC; |
| 354 | /* Fall through */ | ||
| 353 | case USB_LINK_STD_HOST_NC_8505: | 355 | case USB_LINK_STD_HOST_NC_8505: |
| 354 | case USB_LINK_STD_HOST_C_NS_8505: | 356 | case USB_LINK_STD_HOST_C_NS_8505: |
| 355 | case USB_LINK_STD_HOST_C_S_8505: | 357 | case USB_LINK_STD_HOST_C_S_8505: |
| @@ -368,6 +370,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, · 12 unmodified lines | |||
| 368 | case USB_LINK_ACA_RID_A_8505: | 370 | case USB_LINK_ACA_RID_A_8505: |
| 369 | case USB_LINK_ACA_DOCK_CHGR_8505: | 371 | case USB_LINK_ACA_DOCK_CHGR_8505: |
| 370 | event = UX500_MUSB_RIDA; | 372 | event = UX500_MUSB_RIDA; |
| 373 | /* Fall through */ | ||
| 371 | case USB_LINK_HM_IDGND_8505: | 374 | case USB_LINK_HM_IDGND_8505: |
| 372 | if (ab->mode == USB_IDLE) { | 375 | if (ab->mode == USB_IDLE) { |
| 373 | ab->mode = USB_HOST; | 376 | ab->mode = USB_HOST; |
| @@ -422,6 +425,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, · 48 unmodified lines | |||
| 422 | switch (lsts) { | 425 | switch (lsts) { |
| 423 | case USB_LINK_ACA_RID_B_8500: | 426 | case USB_LINK_ACA_RID_B_8500: |
| 424 | event = UX500_MUSB_RIDB; | 427 | event = UX500_MUSB_RIDB; |
| 428 | /* Fall through */ | ||
| 425 | case USB_LINK_NOT_CONFIGURED_8500: | 429 | case USB_LINK_NOT_CONFIGURED_8500: |
| 426 | case USB_LINK_NOT_VALID_LINK_8500: | 430 | case USB_LINK_NOT_VALID_LINK_8500: |
| 427 | ab->mode = USB_IDLE; | 431 | ab->mode = USB_IDLE; |
| @@ -438,6 +442,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, · 10 unmodified lines | |||
| 438 | case USB_LINK_ACA_RID_C_HS_8500: | 442 | case USB_LINK_ACA_RID_C_HS_8500: |
| 439 | case USB_LINK_ACA_RID_C_HS_CHIRP_8500: | 443 | case USB_LINK_ACA_RID_C_HS_CHIRP_8500: |
| 440 | event = UX500_MUSB_RIDC; | 444 | event = UX500_MUSB_RIDC; |
| 445 | /* Fall through */ | ||
| 441 | case USB_LINK_STD_HOST_NC_8500: | 446 | case USB_LINK_STD_HOST_NC_8500: |
| 442 | case USB_LINK_STD_HOST_C_NS_8500: | 447 | case USB_LINK_STD_HOST_C_NS_8500: |
| 443 | case USB_LINK_STD_HOST_C_S_8500: | 448 | case USB_LINK_STD_HOST_C_S_8500: |
| @@ -457,6 +462,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, · 13 unmodified lines | |||
| 457 | 462 | ||
| 458 | case USB_LINK_ACA_RID_A_8500: | 463 | case USB_LINK_ACA_RID_A_8500: |
| 459 | event = UX500_MUSB_RIDA; | 464 | event = UX500_MUSB_RIDA; |
| 465 | /* Fall through */ | ||
| 460 | case USB_LINK_HM_IDGND_8500: | 466 | case USB_LINK_HM_IDGND_8500: |
| 461 | if (ab->mode == USB_IDLE) { | 467 | if (ab->mode == USB_IDLE) { |
| 462 | ab->mode = USB_HOST; | 468 | ab->mode = USB_HOST; |
| @@ -712,10 +718,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, · 249 unmodified lines | |||
| 712 | 718 | ||
| 713 | if (ab->flags & AB8500_USB_FLAG_USE_LINK_STATUS_IRQ) { | 719 | if (ab->flags & AB8500_USB_FLAG_USE_LINK_STATUS_IRQ) { |
| 714 | irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); | 720 | irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); |
| 715 | if (irq < 0) { | 721 | if (irq < 0) |
| 716 | dev_err(&pdev->dev, "Link status irq not found\n"); | ||
| 717 | return irq; | 722 | return irq; |
| 718 | } | ||
| 719 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 723 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
| 720 | ab8500_usb_link_status_irq, | 724 | ab8500_usb_link_status_irq, |
| 721 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, | 725 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
| @@ -728,10 +732,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, · 6 unmodified lines | |||
| 728 | 732 | ||
| 729 | if (ab->flags & AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ) { | 733 | if (ab->flags & AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ) { |
| 730 | irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); | 734 | irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); |
| 731 | if (irq < 0) { | 735 | if (irq < 0) |
| 732 | dev_err(&pdev->dev, "ID fall irq not found\n"); | ||
| 733 | return irq; | 736 | return irq; |
| 734 | } | ||
| 735 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 737 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
| 736 | ab8500_usb_disconnect_irq, | 738 | ab8500_usb_disconnect_irq, |
| 737 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, | 739 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
| @@ -744,10 +746,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, · 6 unmodified lines | |||
| 744 | 746 | ||
| 745 | if (ab->flags & AB8500_USB_FLAG_USE_VBUS_DET_IRQ) { | 747 | if (ab->flags & AB8500_USB_FLAG_USE_VBUS_DET_IRQ) { |
| 746 | irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); | 748 | irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); |
| 747 | if (irq < 0) { | 749 | if (irq < 0) |
| 748 | dev_err(&pdev->dev, "VBUS fall irq not found\n"); | ||
| 749 | return irq; | 750 | return irq; |
| 750 | } | ||
| 751 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 751 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
| 752 | ab8500_usb_disconnect_irq, | 752 | ab8500_usb_disconnect_irq, |
| 753 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, | 753 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
| @@ -65,7 +65,7 @@ struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, · 64 unmodified lines | |||
| 65 | 65 | ||
| 66 | static struct list_head active_timers; | 66 | static struct list_head active_timers; |
| 67 | 67 | ||
| 68 | static struct fsl_otg_config fsl_otg_initdata = { | 68 | static const struct fsl_otg_config fsl_otg_initdata = { |
| 69 | .otg_port = 1, | 69 | .otg_port = 1, |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| @@ -1043,6 +1043,11 @@ static ssize_t show_fsl_usb2_otg_state(struct device *dev, · 971 unmodified lines | |||
| 1043 | 1043 | ||
| 1044 | static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL); | 1044 | static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL); |
| 1045 | 1045 | ||
| 1046 | static struct attribute *fsl_otg_attrs[] = { | ||
| 1047 | &dev_attr_fsl_usb2_otg_state.attr, | ||
| 1048 | NULL, | ||
| 1049 | }; | ||
| 1050 | ATTRIBUTE_GROUPS(fsl_otg); | ||
| 1046 | 1051 | ||
| 1047 | /* Char driver interface to control some OTG input */ | 1052 | /* Char driver interface to control some OTG input */ |
| 1048 | 1053 | ||
| @@ -1132,10 +1137,6 @@ static int fsl_otg_probe(struct platform_device *pdev) · 83 unmodified lines | |||
| 1132 | return ret; | 1137 | return ret; |
| 1133 | } | 1138 | } |
| 1134 | 1139 | ||
| 1135 | ret = device_create_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); | ||
| 1136 | if (ret) | ||
| 1137 | dev_warn(&pdev->dev, "Can't register sysfs attribute\n"); | ||
| 1138 | |||
| 1139 | return ret; | 1140 | return ret; |
| 1140 | } | 1141 | } |
| 1141 | 1142 | ||
| @@ -1152,8 +1153,6 @@ static int fsl_otg_remove(struct platform_device *pdev) · 10 unmodified lines | |||
| 1152 | kfree(fsl_otg_dev->phy.otg); | 1153 | kfree(fsl_otg_dev->phy.otg); |
| 1153 | kfree(fsl_otg_dev); | 1154 | kfree(fsl_otg_dev); |
| 1154 | 1155 | ||
| 1155 | device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); | ||
| 1156 | |||
| 1157 | unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); | 1156 | unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); |
| 1158 | 1157 | ||
| 1159 | if (pdata->exit) | 1158 | if (pdata->exit) |
| @@ -1168,6 +1167,7 @@ struct platform_driver fsl_otg_driver = { · 8 unmodified lines | |||
| 1168 | .driver = { | 1167 | .driver = { |
| 1169 | .name = driver_name, | 1168 | .name = driver_name, |
| 1170 | .owner = THIS_MODULE, | 1169 | .owner = THIS_MODULE, |
| 1170 | .dev_groups = fsl_otg_groups, | ||
| 1171 | }, | 1171 | }, |
| 1172 | }; | 1172 | }; |
| 1173 | 1173 | ||
| @@ -641,12 +641,15 @@ static const struct attribute_group inputs_attr_group = { · 640 unmodified lines | |||
| 641 | .attrs = inputs_attrs, | 641 | .attrs = inputs_attrs, |
| 642 | }; | 642 | }; |
| 643 | 643 | ||
| 644 | static const struct attribute_group *mv_otg_groups[] = { | ||
| 645 | &inputs_attr_group, | ||
| 646 | NULL, | ||
| 647 | }; | ||
| 648 | |||
| 644 | static int mv_otg_remove(struct platform_device *pdev) | 649 | static int mv_otg_remove(struct platform_device *pdev) |
| 645 | { | 650 | { |
| 646 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | 651 | struct mv_otg *mvotg = platform_get_drvdata(pdev); |
| 647 | 652 | ||
| 648 | sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); | ||
| 649 | |||
| 650 | if (mvotg->qwork) { | 653 | if (mvotg->qwork) { |
| 651 | flush_workqueue(mvotg->qwork); | 654 | flush_workqueue(mvotg->qwork); |
| 652 | destroy_workqueue(mvotg->qwork); | 655 | destroy_workqueue(mvotg->qwork); |
| @@ -809,13 +812,6 @@ static int mv_otg_probe(struct platform_device *pdev) · 156 unmodified lines | |||
| 809 | goto err_disable_clk; | 812 | goto err_disable_clk; |
| 810 | } | 813 | } |
| 811 | 814 | ||
| 812 | retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group); | ||
| 813 | if (retval < 0) { | ||
| 814 | dev_dbg(&pdev->dev, | ||
| 815 | "Can't register sysfs attr group: %d\n", retval); | ||
| 816 | goto err_remove_phy; | ||
| 817 | } | ||
| 818 | |||
| 819 | spin_lock_init(&mvotg->wq_lock); | 815 | spin_lock_init(&mvotg->wq_lock); |
| 820 | if (spin_trylock(&mvotg->wq_lock)) { | 816 | if (spin_trylock(&mvotg->wq_lock)) { |
| 821 | mv_otg_run_state_machine(mvotg, 2 * HZ); | 817 | mv_otg_run_state_machine(mvotg, 2 * HZ); |
| @@ -828,8 +824,6 @@ static int mv_otg_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 828 | 824 | ||
| 829 | return 0; | 825 | return 0; |
| 830 | 826 | ||
| 831 | err_remove_phy: | ||
| 832 | usb_remove_phy(&mvotg->phy); | ||
| 833 | err_disable_clk: | 827 | err_disable_clk: |
| 834 | mv_otg_disable_internal(mvotg); | 828 | mv_otg_disable_internal(mvotg); |
| 835 | err_destroy_workqueue: | 829 | err_destroy_workqueue: |
| @@ -883,6 +877,7 @@ static struct platform_driver mv_otg_driver = { · 47 unmodified lines | |||
| 883 | .remove = mv_otg_remove, | 877 | .remove = mv_otg_remove, |
| 884 | .driver = { | 878 | .driver = { |
| 885 | .name = driver_name, | 879 | .name = driver_name, |
| 880 | .dev_groups = mv_otg_groups, | ||
| 886 | }, | 881 | }, |
| 887 | #ifdef CONFIG_PM | 882 | #ifdef CONFIG_PM |
| 888 | .suspend = mv_otg_suspend, | 883 | .suspend = mv_otg_suspend, |
| @@ -312,15 +312,12 @@ static ssize_t otg_mode_store(struct device *device, · 311 unmodified lines | |||
| 312 | } | 312 | } |
| 313 | static DEVICE_ATTR_RW(otg_mode); | 313 | static DEVICE_ATTR_RW(otg_mode); |
| 314 | 314 | ||
| 315 | static struct attribute *tahvo_attributes[] = { | 315 | static struct attribute *tahvo_attrs[] = { |
| 316 | &dev_attr_vbus.attr, | 316 | &dev_attr_vbus.attr, |
| 317 | &dev_attr_otg_mode.attr, | 317 | &dev_attr_otg_mode.attr, |
| 318 | NULL | 318 | NULL |
| 319 | }; | 319 | }; |
| 320 | 320 | ATTRIBUTE_GROUPS(tahvo); | |
| 321 | static const struct attribute_group tahvo_attr_group = { | ||
| 322 | .attrs = tahvo_attributes, | ||
| 323 | }; | ||
| 324 | 321 | ||
| 325 | static int tahvo_usb_probe(struct platform_device *pdev) | 322 | static int tahvo_usb_probe(struct platform_device *pdev) |
| 326 | { | 323 | { |
| @@ -406,17 +403,8 @@ static int tahvo_usb_probe(struct platform_device *pdev) · 79 unmodified lines | |||
| 406 | goto err_remove_phy; | 403 | goto err_remove_phy; |
| 407 | } | 404 | } |
| 408 | 405 | ||
| 409 | /* Attributes */ | ||
| 410 | ret = sysfs_create_group(&pdev->dev.kobj, &tahvo_attr_group); | ||
| 411 | if (ret) { | ||
| 412 | dev_err(&pdev->dev, "cannot create sysfs group: %d\n", ret); | ||
| 413 | goto err_free_irq; | ||
| 414 | } | ||
| 415 | |||
| 416 | return 0; | 406 | return 0; |
| 417 | 407 | ||
| 418 | err_free_irq: | ||
| 419 | free_irq(tu->irq, tu); | ||
| 420 | err_remove_phy: | 408 | err_remove_phy: |
| 421 | usb_remove_phy(&tu->phy); | 409 | usb_remove_phy(&tu->phy); |
| 422 | err_disable_clk: | 410 | err_disable_clk: |
| @@ -430,7 +418,6 @@ static int tahvo_usb_remove(struct platform_device *pdev) · 7 unmodified lines | |||
| 430 | { | 418 | { |
| 431 | struct tahvo_usb *tu = platform_get_drvdata(pdev); | 419 | struct tahvo_usb *tu = platform_get_drvdata(pdev); |
| 432 | 420 | ||
| 433 | sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group); | ||
| 434 | free_irq(tu->irq, tu); | 421 | free_irq(tu->irq, tu); |
| 435 | usb_remove_phy(&tu->phy); | 422 | usb_remove_phy(&tu->phy); |
| 436 | if (!IS_ERR(tu->ick)) | 423 | if (!IS_ERR(tu->ick)) |
| @@ -444,6 +431,7 @@ static struct platform_driver tahvo_usb_driver = { · 7 unmodified lines | |||
| 444 | .remove = tahvo_usb_remove, | 431 | .remove = tahvo_usb_remove, |
| 445 | .driver = { | 432 | .driver = { |
| 446 | .name = "tahvo-usb", | 433 | .name = "tahvo-usb", |
| 434 | .dev_groups = tahvo_groups, | ||
| 447 | }, | 435 | }, |
| 448 | }; | 436 | }; |
| 449 | module_platform_driver(tahvo_usb_driver); | 437 | module_platform_driver(tahvo_usb_driver); |
| @@ -196,6 +196,12 @@ static ssize_t vbus_show(struct device *dev, · 195 unmodified lines | |||
| 196 | } | 196 | } |
| 197 | static DEVICE_ATTR_RO(vbus); | 197 | static DEVICE_ATTR_RO(vbus); |
| 198 | 198 | ||
| 199 | static struct attribute *twl6030_attrs[] = { | ||
| 200 | &dev_attr_vbus.attr, | ||
| 201 | NULL, | ||
| 202 | }; | ||
| 203 | ATTRIBUTE_GROUPS(twl6030); | ||
| 204 | |||
| 199 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | 205 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) |
| 200 | { | 206 | { |
| 201 | struct twl6030_usb *twl = _twl; | 207 | struct twl6030_usb *twl = _twl; |
| @@ -361,8 +367,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 159 unmodified lines | |||
| 361 | } | 367 | } |
| 362 | 368 | ||
| 363 | platform_set_drvdata(pdev, twl); | 369 | platform_set_drvdata(pdev, twl); |
| 364 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | ||
| 365 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
| 366 | 370 | ||
| 367 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); | 371 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
| 368 | INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work); | 372 | INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work); |
| @@ -373,7 +377,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 373 | if (status < 0) { | 377 | if (status < 0) { |
| 374 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 378 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 375 | twl->irq1, status); | 379 | twl->irq1, status); |
| 376 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
| 377 | return status; | 380 | return status; |
| 378 | } | 381 | } |
| 379 | 382 | ||
| @@ -384,7 +387,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 384 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 387 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 385 | twl->irq2, status); | 388 | twl->irq2, status); |
| 386 | free_irq(twl->irq1, twl); | 389 | free_irq(twl->irq1, twl); |
| 387 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
| 388 | return status; | 390 | return status; |
| 389 | } | 391 | } |
| 390 | 392 | ||
| @@ -408,7 +410,6 @@ static int twl6030_usb_remove(struct platform_device *pdev) · 17 unmodified lines | |||
| 408 | free_irq(twl->irq1, twl); | 410 | free_irq(twl->irq1, twl); |
| 409 | free_irq(twl->irq2, twl); | 411 | free_irq(twl->irq2, twl); |
| 410 | regulator_put(twl->usb3v3); | 412 | regulator_put(twl->usb3v3); |
| 411 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
| 412 | cancel_work_sync(&twl->set_vbus_work); | 413 | cancel_work_sync(&twl->set_vbus_work); |
| 413 | 414 | ||
| 414 | return 0; | 415 | return 0; |
| @@ -426,6 +427,7 @@ static struct platform_driver twl6030_usb_driver = { · 11 unmodified lines | |||
| 426 | .driver = { | 427 | .driver = { |
| 427 | .name = "twl6030_usb", | 428 | .name = "twl6030_usb", |
| 428 | .of_match_table = of_match_ptr(twl6030_usb_id_table), | 429 | .of_match_table = of_match_ptr(twl6030_usb_id_table), |
| 430 | .dev_groups = twl6030_groups, | ||
| 429 | }, | 431 | }, |
| 430 | }; | 432 | }; |
| 431 | 433 | ||
| @@ -1283,7 +1283,7 @@ static const struct hc_driver usbhsh_driver = { · 1282 unmodified lines | |||
| 1283 | /* | 1283 | /* |
| 1284 | * generic hardware linkage | 1284 | * generic hardware linkage |
| 1285 | */ | 1285 | */ |
| 1286 | .flags = HCD_USB2, | 1286 | .flags = HCD_DMA | HCD_USB2, |
| 1287 | 1287 | ||
| 1288 | .start = usbhsh_host_start, | 1288 | .start = usbhsh_host_start, |
| 1289 | .stop = usbhsh_host_stop, | 1289 | .stop = usbhsh_host_stop, |
| @@ -102,6 +102,19 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, · 101 unmodified lines | |||
| 102 | return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); | 102 | return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static struct usb_role_switch * | ||
| 106 | usb_role_switch_is_parent(struct fwnode_handle *fwnode) | ||
| 107 | { | ||
| 108 | struct fwnode_handle *parent = fwnode_get_parent(fwnode); | ||
| 109 | struct device *dev; | ||
| 110 | |||
| 111 | if (!parent || !fwnode_property_present(parent, "usb-role-switch")) | ||
| 112 | return NULL; | ||
| 113 | |||
| 114 | dev = class_find_device_by_fwnode(role_class, parent); | ||
| 115 | return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); | ||
| 116 | } | ||
| 117 | |||
| 105 | /** | 118 | /** |
| 106 | * usb_role_switch_get - Find USB role switch linked with the caller | 119 | * usb_role_switch_get - Find USB role switch linked with the caller |
| 107 | * @dev: The caller device | 120 | * @dev: The caller device |
| @@ -113,8 +126,10 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) · 5 unmodified lines | |||
| 113 | { | 126 | { |
| 114 | struct usb_role_switch *sw; | 127 | struct usb_role_switch *sw; |
| 115 | 128 | ||
| 116 | sw = device_connection_find_match(dev, "usb-role-switch", NULL, | 129 | sw = usb_role_switch_is_parent(dev_fwnode(dev)); |
| 117 | usb_role_switch_match); | 130 | if (!sw) |
| 131 | sw = device_connection_find_match(dev, "usb-role-switch", NULL, | ||
| 132 | usb_role_switch_match); | ||
| 118 | 133 | ||
| 119 | if (!IS_ERR_OR_NULL(sw)) | 134 | if (!IS_ERR_OR_NULL(sw)) |
| 120 | WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); | 135 | WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); |
| @@ -123,6 +138,28 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) · 2 unmodified lines | |||
| 123 | } | 138 | } |
| 124 | EXPORT_SYMBOL_GPL(usb_role_switch_get); | 139 | EXPORT_SYMBOL_GPL(usb_role_switch_get); |
| 125 | 140 | ||
| 141 | /** | ||
| 142 | * fwnode_usb_role_switch_get - Find USB role switch linked with the caller | ||
| 143 | * @fwnode: The caller device node | ||
| 144 | * | ||
| 145 | * This is similar to the usb_role_switch_get() function above, but it searches | ||
| 146 | * the switch using fwnode instead of device entry. | ||
| 147 | */ | ||
| 148 | struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) | ||
| 149 | { | ||
| 150 | struct usb_role_switch *sw; | ||
| 151 | |||
| 152 | sw = usb_role_switch_is_parent(fwnode); | ||
| 153 | if (!sw) | ||
| 154 | sw = fwnode_connection_find_match(fwnode, "usb-role-switch", | ||
| 155 | NULL, usb_role_switch_match); | ||
| 156 | if (!IS_ERR_OR_NULL(sw)) | ||
| 157 | WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); | ||
| 158 | |||
| 159 | return sw; | ||
| 160 | } | ||
| 161 | EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); | ||
| 162 | |||
| 126 | /** | 163 | /** |
| 127 | * usb_role_switch_put - Release handle to a switch | 164 | * usb_role_switch_put - Release handle to a switch |
| 128 | * @sw: USB Role Switch | 165 | * @sw: USB Role Switch |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/pm_runtime.h> | 21 | #include <linux/pm_runtime.h> |
| 22 | #include <linux/property.h> | ||
| 22 | #include <linux/usb/role.h> | 23 | #include <linux/usb/role.h> |
| 23 | 24 | ||
| 24 | /* register definition */ | 25 | /* register definition */ |
| @@ -26,6 +27,12 @@ · 1 unmodified line | |||
| 26 | #define SW_VBUS_VALID BIT(24) | 27 | #define SW_VBUS_VALID BIT(24) |
| 27 | #define SW_IDPIN_EN BIT(21) | 28 | #define SW_IDPIN_EN BIT(21) |
| 28 | #define SW_IDPIN BIT(20) | 29 | #define SW_IDPIN BIT(20) |
| 30 | #define SW_SWITCH_EN BIT(16) | ||
| 31 | |||
| 32 | #define DRD_CONFIG_DYNAMIC 0 | ||
| 33 | #define DRD_CONFIG_STATIC_HOST 1 | ||
| 34 | #define DRD_CONFIG_STATIC_DEVICE 2 | ||
| 35 | #define DRD_CONFIG_MASK 3 | ||
| 29 | 36 | ||
| 30 | #define DUAL_ROLE_CFG1 0x6c | 37 | #define DUAL_ROLE_CFG1 0x6c |
| 31 | #define HOST_MODE BIT(29) | 38 | #define HOST_MODE BIT(29) |
| @@ -37,6 +44,7 @@ · 5 unmodified lines | |||
| 37 | struct intel_xhci_usb_data { | 44 | struct intel_xhci_usb_data { |
| 38 | struct usb_role_switch *role_sw; | 45 | struct usb_role_switch *role_sw; |
| 39 | void __iomem *base; | 46 | void __iomem *base; |
| 47 | bool enable_sw_switch; | ||
| 40 | }; | 48 | }; |
| 41 | 49 | ||
| 42 | static const struct software_node intel_xhci_usb_node = { | 50 | static const struct software_node intel_xhci_usb_node = { |
| @@ -49,6 +57,7 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) · 6 unmodified lines | |||
| 49 | unsigned long timeout; | 57 | unsigned long timeout; |
| 50 | acpi_status status; | 58 | acpi_status status; |
| 51 | u32 glk, val; | 59 | u32 glk, val; |
| 60 | u32 drd_config = DRD_CONFIG_DYNAMIC; | ||
| 52 | 61 | ||
| 53 | /* | 62 | /* |
| 54 | * On many CHT devices ACPI event (_AEI) handlers read / modify / | 63 | * On many CHT devices ACPI event (_AEI) handlers read / modify / |
| @@ -63,24 +72,35 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) · 8 unmodified lines | |||
| 63 | 72 | ||
| 64 | pm_runtime_get_sync(dev); | 73 | pm_runtime_get_sync(dev); |
| 65 | 74 | ||
| 66 | /* Set idpin value as requested */ | 75 | /* |
| 76 | * Set idpin value as requested. | ||
| 77 | * Since some devices rely on firmware setting DRD_CONFIG and | ||
| 78 | * SW_SWITCH_EN bits to be zero for role switch, | ||
| 79 | * do not set these bits for those devices. | ||
| 80 | */ | ||
| 67 | val = readl(data->base + DUAL_ROLE_CFG0); | 81 | val = readl(data->base + DUAL_ROLE_CFG0); |
| 68 | switch (role) { | 82 | switch (role) { |
| 69 | case USB_ROLE_NONE: | 83 | case USB_ROLE_NONE: |
| 70 | val |= SW_IDPIN; | 84 | val |= SW_IDPIN; |
| 71 | val &= ~SW_VBUS_VALID; | 85 | val &= ~SW_VBUS_VALID; |
| 86 | drd_config = DRD_CONFIG_DYNAMIC; | ||
| 72 | break; | 87 | break; |
| 73 | case USB_ROLE_HOST: | 88 | case USB_ROLE_HOST: |
| 74 | val &= ~SW_IDPIN; | 89 | val &= ~SW_IDPIN; |
| 75 | val &= ~SW_VBUS_VALID; | 90 | val &= ~SW_VBUS_VALID; |
| 91 | drd_config = DRD_CONFIG_STATIC_HOST; | ||
| 76 | break; | 92 | break; |
| 77 | case USB_ROLE_DEVICE: | 93 | case USB_ROLE_DEVICE: |
| 78 | val |= SW_IDPIN; | 94 | val |= SW_IDPIN; |
| 79 | val |= SW_VBUS_VALID; | 95 | val |= SW_VBUS_VALID; |
| 96 | drd_config = DRD_CONFIG_STATIC_DEVICE; | ||
| 80 | break; | 97 | break; |
| 81 | } | 98 | } |
| 82 | val |= SW_IDPIN_EN; | 99 | val |= SW_IDPIN_EN; |
| 83 | 100 | if (data->enable_sw_switch) { | |
| 101 | val &= ~DRD_CONFIG_MASK; | ||
| 102 | val |= SW_SWITCH_EN | drd_config; | ||
| 103 | } | ||
| 84 | writel(val, data->base + DUAL_ROLE_CFG0); | 104 | writel(val, data->base + DUAL_ROLE_CFG0); |
| 85 | 105 | ||
| 86 | acpi_release_global_lock(glk); | 106 | acpi_release_global_lock(glk); |
| @@ -156,6 +176,9 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) · 69 unmodified lines | |||
| 156 | sw_desc.allow_userspace_control = true, | 176 | sw_desc.allow_userspace_control = true, |
| 157 | sw_desc.fwnode = software_node_fwnode(&intel_xhci_usb_node); | 177 | sw_desc.fwnode = software_node_fwnode(&intel_xhci_usb_node); |
| 158 | 178 | ||
| 179 | data->enable_sw_switch = !device_property_read_bool(dev, | ||
| 180 | "sw_switch_disable"); | ||
| 181 | |||
| 159 | data->role_sw = usb_role_switch_register(dev, &sw_desc); | 182 | data->role_sw = usb_role_switch_register(dev, &sw_desc); |
| 160 | if (IS_ERR(data->role_sw)) { | 183 | if (IS_ERR(data->role_sw)) { |
| 161 | fwnode_handle_put(sw_desc.fwnode); | 184 | fwnode_handle_put(sw_desc.fwnode); |
| @@ -2023,6 +2023,46 @@ static int ftdi_read_eeprom(struct usb_serial *serial, void *dst, u16 addr, · 2022 unmodified lines | |||
| 2023 | return 0; | 2023 | return 0; |
| 2024 | } | 2024 | } |
| 2025 | 2025 | ||
| 2026 | static int ftdi_gpio_init_ft232h(struct usb_serial_port *port) | ||
| 2027 | { | ||
| 2028 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
| 2029 | u16 cbus_config; | ||
| 2030 | u8 *buf; | ||
| 2031 | int ret; | ||
| 2032 | int i; | ||
| 2033 | |||
| 2034 | buf = kmalloc(4, GFP_KERNEL); | ||
| 2035 | if (!buf) | ||
| 2036 | return -ENOMEM; | ||
| 2037 | |||
| 2038 | ret = ftdi_read_eeprom(port->serial, buf, 0x1a, 4); | ||
| 2039 | if (ret < 0) | ||
| 2040 | goto out_free; | ||
| 2041 | |||
| 2042 | /* | ||
| 2043 | * FT232H CBUS Memory Map | ||
| 2044 | * | ||
| 2045 | * 0x1a: X- (upper nibble -> AC5) | ||
| 2046 | * 0x1b: -X (lower nibble -> AC6) | ||
| 2047 | * 0x1c: XX (upper nibble -> AC9 | lower nibble -> AC8) | ||
| 2048 | */ | ||
| 2049 | cbus_config = buf[2] << 8 | (buf[1] & 0xf) << 4 | (buf[0] & 0xf0) >> 4; | ||
| 2050 | |||
| 2051 | priv->gc.ngpio = 4; | ||
| 2052 | priv->gpio_altfunc = 0xff; | ||
| 2053 | |||
| 2054 | for (i = 0; i < priv->gc.ngpio; ++i) { | ||
| 2055 | if ((cbus_config & 0xf) == FTDI_FTX_CBUS_MUX_GPIO) | ||
| 2056 | priv->gpio_altfunc &= ~BIT(i); | ||
| 2057 | cbus_config >>= 4; | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | out_free: | ||
| 2061 | kfree(buf); | ||
| 2062 | |||
| 2063 | return ret; | ||
| 2064 | } | ||
| 2065 | |||
| 2026 | static int ftdi_gpio_init_ft232r(struct usb_serial_port *port) | 2066 | static int ftdi_gpio_init_ft232r(struct usb_serial_port *port) |
| 2027 | { | 2067 | { |
| 2028 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2068 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| @@ -2098,6 +2138,9 @@ static int ftdi_gpio_init(struct usb_serial_port *port) · 69 unmodified lines | |||
| 2098 | int result; | 2138 | int result; |
| 2099 | 2139 | ||
| 2100 | switch (priv->chip_type) { | 2140 | switch (priv->chip_type) { |
| 2141 | case FT232H: | ||
| 2142 | result = ftdi_gpio_init_ft232h(port); | ||
| 2143 | break; | ||
| 2101 | case FT232RL: | 2144 | case FT232RL: |
| 2102 | result = ftdi_gpio_init_ft232r(port); | 2145 | result = ftdi_gpio_init_ft232r(port); |
| 2103 | break; | 2146 | break; |
| @@ -29,8 +29,6 @@ · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | 31 | ||
| 32 | #define USB_STORAGE "usb-storage: " | ||
| 33 | |||
| 34 | #ifdef CONFIG_USB_STORAGE_DEBUG | 32 | #ifdef CONFIG_USB_STORAGE_DEBUG |
| 35 | void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb); | 33 | void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb); |
| 36 | void usb_stor_show_sense(const struct us_data *us, unsigned char key, | 34 | void usb_stor_show_sense(const struct us_data *us, unsigned char key, |
| @@ -1511,7 +1511,7 @@ static int isd200_Initialization(struct us_data *us) · 1510 unmodified lines | |||
| 1511 | 1511 | ||
| 1512 | static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) | 1512 | static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) |
| 1513 | { | 1513 | { |
| 1514 | int sendToTransport = 1, orig_bufflen; | 1514 | int sendToTransport, orig_bufflen; |
| 1515 | union ata_cdb ataCdb; | 1515 | union ata_cdb ataCdb; |
| 1516 | 1516 | ||
| 1517 | /* Make sure driver was initialized */ | 1517 | /* Make sure driver was initialized */ |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | |||
| 40 | #include <scsi/scsi_eh.h> | 40 | #include <scsi/scsi_eh.h> |
| 41 | 41 | ||
| 42 | #include "usb.h" | 42 | #include "usb.h" |
| 43 | #include <linux/usb/hcd.h> | ||
| 43 | #include "scsiglue.h" | 44 | #include "scsiglue.h" |
| 44 | #include "debug.h" | 45 | #include "debug.h" |
| 45 | #include "transport.h" | 46 | #include "transport.h" |
| @@ -141,11 +142,10 @@ static int slave_configure(struct scsi_device *sdev) · 95 unmodified lines | |||
| 141 | 142 | ||
| 142 | /* | 143 | /* |
| 143 | * Some USB host controllers can't do DMA; they have to use PIO. | 144 | * Some USB host controllers can't do DMA; they have to use PIO. |
| 144 | * They indicate this by setting their dma_mask to NULL. For | 145 | * For such controllers we need to make sure the block layer sets |
| 145 | * such controllers we need to make sure the block layer sets | ||
| 146 | * up bounce buffers in addressable memory. | 146 | * up bounce buffers in addressable memory. |
| 147 | */ | 147 | */ |
| 148 | if (!us->pusb_dev->bus->controller->dma_mask) | 148 | if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus))) |
| 149 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); | 149 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); |
| 150 | 150 | ||
| 151 | /* | 151 | /* |
| @@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb, · 227 unmodified lines | |||
| 379 | 379 | ||
| 380 | /* check for state-transition errors */ | 380 | /* check for state-transition errors */ |
| 381 | if (us->srb != NULL) { | 381 | if (us->srb != NULL) { |
| 382 | printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", | 382 | printk(KERN_ERR "usb-storage: Error in %s: us->srb = %p\n", |
| 383 | __func__, us->srb); | 383 | __func__, us->srb); |
| 384 | return SCSI_MLQUEUE_HOST_BUSY; | 384 | return SCSI_MLQUEUE_HOST_BUSY; |
| 385 | } | 385 | } |
| @@ -53,6 +53,7 @@ source "drivers/usb/typec/ucsi/Kconfig" · 52 unmodified lines | |||
| 53 | config TYPEC_TPS6598X | 53 | config TYPEC_TPS6598X |
| 54 | tristate "TI TPS6598x USB Power Delivery controller driver" | 54 | tristate "TI TPS6598x USB Power Delivery controller driver" |
| 55 | depends on I2C | 55 | depends on I2C |
| 56 | select REGMAP_I2C | ||
| 56 | help | 57 | help |
| 57 | Say Y or M here if your system has TI TPS65982 or TPS65983 USB Power | 58 | Say Y or M here if your system has TI TPS65982 or TPS65983 USB Power |
| 58 | Delivery controller. | 59 | Delivery controller. |
| @@ -215,7 +215,7 @@ static void *typec_mux_match(struct device_connection *con, int ep, void *data) · 214 unmodified lines | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | /* Alternate Mode muxes */ | 217 | /* Alternate Mode muxes */ |
| 218 | nval = fwnode_property_read_u16_array(con->fwnode, "svid", NULL, 0); | 218 | nval = fwnode_property_count_u16(con->fwnode, "svid"); |
| 219 | if (nval <= 0) | 219 | if (nval <= 0) |
| 220 | return NULL; | 220 | return NULL; |
| 221 | 221 | ||
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
| 27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
| 29 | #include <linux/usb.h> | ||
| 29 | #include <linux/usb/typec.h> | 30 | #include <linux/usb/typec.h> |
| 30 | #include <linux/usb/tcpm.h> | 31 | #include <linux/usb/tcpm.h> |
| 31 | #include <linux/usb/pd.h> | 32 | #include <linux/usb/pd.h> |
| @@ -75,7 +76,6 @@ struct fusb302_chip { · 43 unmodified lines | |||
| 75 | struct i2c_client *i2c_client; | 76 | struct i2c_client *i2c_client; |
| 76 | struct tcpm_port *tcpm_port; | 77 | struct tcpm_port *tcpm_port; |
| 77 | struct tcpc_dev tcpc_dev; | 78 | struct tcpc_dev tcpc_dev; |
| 78 | struct tcpc_config tcpc_config; | ||
| 79 | 79 | ||
| 80 | struct regulator *vbus; | 80 | struct regulator *vbus; |
| 81 | 81 | ||
| @@ -207,23 +207,19 @@ static int fusb302_debug_show(struct seq_file *s, void *v) · 125 unmodified lines | |||
| 207 | } | 207 | } |
| 208 | DEFINE_SHOW_ATTRIBUTE(fusb302_debug); | 208 | DEFINE_SHOW_ATTRIBUTE(fusb302_debug); |
| 209 | 209 | ||
| 210 | static struct dentry *rootdir; | ||
| 211 | |||
| 212 | static void fusb302_debugfs_init(struct fusb302_chip *chip) | 210 | static void fusb302_debugfs_init(struct fusb302_chip *chip) |
| 213 | { | 211 | { |
| 214 | mutex_init(&chip->logbuffer_lock); | 212 | char name[NAME_MAX]; |
| 215 | if (!rootdir) | ||
| 216 | rootdir = debugfs_create_dir("fusb302", NULL); | ||
| 217 | 213 | ||
| 218 | chip->dentry = debugfs_create_file(dev_name(chip->dev), | 214 | mutex_init(&chip->logbuffer_lock); |
| 219 | S_IFREG | 0444, rootdir, | 215 | snprintf(name, NAME_MAX, "fusb302-%s", dev_name(chip->dev)); |
| 216 | chip->dentry = debugfs_create_file(name, S_IFREG | 0444, usb_debug_root, | ||
| 220 | chip, &fusb302_debug_fops); | 217 | chip, &fusb302_debug_fops); |
| 221 | } | 218 | } |
| 222 | 219 | ||
| 223 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) | 220 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) |
| 224 | { | 221 | { |
| 225 | debugfs_remove(chip->dentry); | 222 | debugfs_remove(chip->dentry); |
| 226 | debugfs_remove(rootdir); | ||
| 227 | } | 223 | } |
| 228 | 224 | ||
| 229 | #else | 225 | #else |
| @@ -1110,23 +1106,6 @@ done: · 880 unmodified lines | |||
| 1110 | mutex_unlock(&chip->lock); | 1106 | mutex_unlock(&chip->lock); |
| 1111 | } | 1107 | } |
| 1112 | 1108 | ||
| 1113 | #define PDO_FIXED_FLAGS \ | ||
| 1114 | (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) | ||
| 1115 | |||
| 1116 | static const u32 src_pdo[] = { | ||
| 1117 | PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), | ||
| 1118 | }; | ||
| 1119 | |||
| 1120 | static const struct tcpc_config fusb302_tcpc_config = { | ||
| 1121 | .src_pdo = src_pdo, | ||
| 1122 | .nr_src_pdo = ARRAY_SIZE(src_pdo), | ||
| 1123 | .operating_snk_mw = 2500, | ||
| 1124 | .type = TYPEC_PORT_DRP, | ||
| 1125 | .data = TYPEC_PORT_DRD, | ||
| 1126 | .default_role = TYPEC_SINK, | ||
| 1127 | .alt_modes = NULL, | ||
| 1128 | }; | ||
| 1129 | |||
| 1130 | static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev) | 1109 | static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev) |
| 1131 | { | 1110 | { |
| 1132 | fusb302_tcpc_dev->init = tcpm_init; | 1111 | fusb302_tcpc_dev->init = tcpm_init; |
| @@ -1670,27 +1649,36 @@ static int init_gpio(struct fusb302_chip *chip) · 537 unmodified lines | |||
| 1670 | return 0; | 1649 | return 0; |
| 1671 | } | 1650 | } |
| 1672 | 1651 | ||
| 1673 | static int fusb302_composite_snk_pdo_array(struct fusb302_chip *chip) | 1652 | #define PDO_FIXED_FLAGS \ |
| 1674 | { | 1653 | (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) |
| 1675 | struct device *dev = chip->dev; | ||
| 1676 | u32 max_uv, max_ua; | ||
| 1677 | 1654 | ||
| 1678 | chip->snk_pdo[0] = PDO_FIXED(5000, 400, PDO_FIXED_FLAGS); | 1655 | static const u32 src_pdo[] = { |
| 1656 | PDO_FIXED(5000, 400, PDO_FIXED_FLAGS) | ||
| 1657 | }; | ||
| 1679 | 1658 | ||
| 1680 | /* | 1659 | static const u32 snk_pdo[] = { |
| 1681 | * As max_snk_ma/mv/mw is not needed for tcpc_config, | 1660 | PDO_FIXED(5000, 400, PDO_FIXED_FLAGS) |
| 1682 | * those settings should be passed in via sink PDO, so | 1661 | }; |
| 1683 | * "fcs, max-sink-*" properties will be deprecated, to | 1662 | |
| 1684 | * perserve compatibility with existing users of them, | 1663 | static const struct property_entry port_props[] = { |
| 1685 | * we read those properties to convert them to be a var | 1664 | PROPERTY_ENTRY_STRING("data-role", "dual"), |
| 1686 | * PDO. | 1665 | PROPERTY_ENTRY_STRING("power-role", "dual"), |
| 1687 | */ | 1666 | PROPERTY_ENTRY_STRING("try-power-role", "sink"), |
| 1688 | if (device_property_read_u32(dev, "fcs,max-sink-microvolt", &max_uv) || | 1667 | PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo), |
| 1689 | device_property_read_u32(dev, "fcs,max-sink-microamp", &max_ua)) | 1668 | PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo), |
| 1690 | return 1; | 1669 | PROPERTY_ENTRY_U32("op-sink-microwatt", 2500), |
| 1670 | { } | ||
| 1671 | }; | ||
| 1691 | 1672 | ||
| 1692 | chip->snk_pdo[1] = PDO_VAR(5000, max_uv / 1000, max_ua / 1000); | 1673 | static struct fwnode_handle *fusb302_fwnode_get(struct device *dev) |
| 1693 | return 2; | 1674 | { |
| 1675 | struct fwnode_handle *fwnode; | ||
| 1676 | |||
| 1677 | fwnode = device_get_named_child_node(dev, "connector"); | ||
| 1678 | if (!fwnode) | ||
| 1679 | fwnode = fwnode_create_software_node(port_props, NULL); | ||
| 1680 | |||
| 1681 | return fwnode; | ||
| 1694 | } | 1682 | } |
| 1695 | 1683 | ||
| 1696 | static int fusb302_probe(struct i2c_client *client, | 1684 | static int fusb302_probe(struct i2c_client *client, |
| @@ -1701,7 +1689,6 @@ static int fusb302_probe(struct i2c_client *client, · 4 unmodified lines | |||
| 1701 | struct device *dev = &client->dev; | 1689 | struct device *dev = &client->dev; |
| 1702 | const char *name; | 1690 | const char *name; |
| 1703 | int ret = 0; | 1691 | int ret = 0; |
| 1704 | u32 v; | ||
| 1705 | 1692 | ||
| 1706 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { | 1693 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { |
| 1707 | dev_err(&client->dev, | 1694 | dev_err(&client->dev, |
| @@ -1714,20 +1701,8 @@ static int fusb302_probe(struct i2c_client *client, · 6 unmodified lines | |||
| 1714 | 1701 | ||
| 1715 | chip->i2c_client = client; | 1702 | chip->i2c_client = client; |
| 1716 | chip->dev = &client->dev; | 1703 | chip->dev = &client->dev; |
| 1717 | chip->tcpc_config = fusb302_tcpc_config; | ||
| 1718 | chip->tcpc_dev.config = &chip->tcpc_config; | ||
| 1719 | mutex_init(&chip->lock); | 1704 | mutex_init(&chip->lock); |
| 1720 | 1705 | ||
| 1721 | chip->tcpc_dev.fwnode = | ||
| 1722 | device_get_named_child_node(dev, "connector"); | ||
| 1723 | |||
| 1724 | if (!device_property_read_u32(dev, "fcs,operating-sink-microwatt", &v)) | ||
| 1725 | chip->tcpc_config.operating_snk_mw = v / 1000; | ||
| 1726 | |||
| 1727 | /* Composite sink PDO */ | ||
| 1728 | chip->tcpc_config.nr_snk_pdo = fusb302_composite_snk_pdo_array(chip); | ||
| 1729 | chip->tcpc_config.snk_pdo = chip->snk_pdo; | ||
| 1730 | |||
| 1731 | /* | 1706 | /* |
| 1732 | * Devicetree platforms should get extcon via phandle (not yet | 1707 | * Devicetree platforms should get extcon via phandle (not yet |
| 1733 | * supported). On ACPI platforms, we get the name from a device prop. | 1708 | * supported). On ACPI platforms, we get the name from a device prop. |
| @@ -1753,6 +1728,7 @@ static int fusb302_probe(struct i2c_client *client, · 19 unmodified lines | |||
| 1753 | INIT_WORK(&chip->irq_work, fusb302_irq_work); | 1728 | INIT_WORK(&chip->irq_work, fusb302_irq_work); |
| 1754 | INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); | 1729 | INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); |
| 1755 | init_tcpc_dev(&chip->tcpc_dev); | 1730 | init_tcpc_dev(&chip->tcpc_dev); |
| 1731 | fusb302_debugfs_init(chip); | ||
| 1756 | 1732 | ||
| 1757 | if (client->irq) { | 1733 | if (client->irq) { |
| 1758 | chip->gpio_int_n_irq = client->irq; | 1734 | chip->gpio_int_n_irq = client->irq; |
| @@ -1762,8 +1738,15 @@ static int fusb302_probe(struct i2c_client *client, · 3 unmodified lines | |||
| 1762 | goto destroy_workqueue; | 1738 | goto destroy_workqueue; |
| 1763 | } | 1739 | } |
| 1764 | 1740 | ||
| 1741 | chip->tcpc_dev.fwnode = fusb302_fwnode_get(dev); | ||
| 1742 | if (IS_ERR(chip->tcpc_dev.fwnode)) { | ||
| 1743 | ret = PTR_ERR(chip->tcpc_dev.fwnode); | ||
| 1744 | goto destroy_workqueue; | ||
| 1745 | } | ||
| 1746 | |||
| 1765 | chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); | 1747 | chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); |
| 1766 | if (IS_ERR(chip->tcpm_port)) { | 1748 | if (IS_ERR(chip->tcpm_port)) { |
| 1749 | fwnode_handle_put(chip->tcpc_dev.fwnode); | ||
| 1767 | ret = PTR_ERR(chip->tcpm_port); | 1750 | ret = PTR_ERR(chip->tcpm_port); |
| 1768 | if (ret != -EPROBE_DEFER) | 1751 | if (ret != -EPROBE_DEFER) |
| 1769 | dev_err(dev, "cannot register tcpm port, ret=%d", ret); | 1752 | dev_err(dev, "cannot register tcpm port, ret=%d", ret); |
| @@ -1778,14 +1761,15 @@ static int fusb302_probe(struct i2c_client *client, · 8 unmodified lines | |||
| 1778 | goto tcpm_unregister_port; | 1761 | goto tcpm_unregister_port; |
| 1779 | } | 1762 | } |
| 1780 | enable_irq_wake(chip->gpio_int_n_irq); | 1763 | enable_irq_wake(chip->gpio_int_n_irq); |
| 1781 | fusb302_debugfs_init(chip); | ||
| 1782 | i2c_set_clientdata(client, chip); | 1764 | i2c_set_clientdata(client, chip); |
| 1783 | 1765 | ||
| 1784 | return ret; | 1766 | return ret; |
| 1785 | 1767 | ||
| 1786 | tcpm_unregister_port: | 1768 | tcpm_unregister_port: |
| 1787 | tcpm_unregister_port(chip->tcpm_port); | 1769 | tcpm_unregister_port(chip->tcpm_port); |
| 1770 | fwnode_handle_put(chip->tcpc_dev.fwnode); | ||
| 1788 | destroy_workqueue: | 1771 | destroy_workqueue: |
| 1772 | fusb302_debugfs_exit(chip); | ||
| 1789 | destroy_workqueue(chip->wq); | 1773 | destroy_workqueue(chip->wq); |
| 1790 | 1774 | ||
| 1791 | return ret; | 1775 | return ret; |
| @@ -1800,6 +1784,7 @@ static int fusb302_remove(struct i2c_client *client) · 8 unmodified lines | |||
| 1800 | cancel_work_sync(&chip->irq_work); | 1784 | cancel_work_sync(&chip->irq_work); |
| 1801 | cancel_delayed_work_sync(&chip->bc_lvl_handler); | 1785 | cancel_delayed_work_sync(&chip->bc_lvl_handler); |
| 1802 | tcpm_unregister_port(chip->tcpm_port); | 1786 | tcpm_unregister_port(chip->tcpm_port); |
| 1787 | fwnode_handle_put(chip->tcpc_dev.fwnode); | ||
| 1803 | destroy_workqueue(chip->wq); | 1788 | destroy_workqueue(chip->wq); |
| 1804 | fusb302_debugfs_exit(chip); | 1789 | fusb302_debugfs_exit(chip); |
| 1805 | 1790 | ||
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| 22 | #include <linux/usb.h> | ||
| 22 | #include <linux/usb/pd.h> | 23 | #include <linux/usb/pd.h> |
| 23 | #include <linux/usb/pd_ado.h> | 24 | #include <linux/usb/pd_ado.h> |
| 24 | #include <linux/usb/pd_bdo.h> | 25 | #include <linux/usb/pd_bdo.h> |
| @@ -571,17 +572,13 @@ static int tcpm_debug_show(struct seq_file *s, void *v) · 546 unmodified lines | |||
| 571 | } | 572 | } |
| 572 | DEFINE_SHOW_ATTRIBUTE(tcpm_debug); | 573 | DEFINE_SHOW_ATTRIBUTE(tcpm_debug); |
| 573 | 574 | ||
| 574 | static struct dentry *rootdir; | ||
| 575 | |||
| 576 | static void tcpm_debugfs_init(struct tcpm_port *port) | 575 | static void tcpm_debugfs_init(struct tcpm_port *port) |
| 577 | { | 576 | { |
| 578 | mutex_init(&port->logbuffer_lock); | 577 | char name[NAME_MAX]; |
| 579 | /* /sys/kernel/debug/tcpm/usbcX */ | ||
| 580 | if (!rootdir) | ||
| 581 | rootdir = debugfs_create_dir("tcpm", NULL); | ||
| 582 | 578 | ||
| 583 | port->dentry = debugfs_create_file(dev_name(port->dev), | 579 | mutex_init(&port->logbuffer_lock); |
| 584 | S_IFREG | 0444, rootdir, | 580 | snprintf(name, NAME_MAX, "tcpm-%s", dev_name(port->dev)); |
| 581 | port->dentry = debugfs_create_file(name, S_IFREG | 0444, usb_debug_root, | ||
| 585 | port, &tcpm_debug_fops); | 582 | port, &tcpm_debug_fops); |
| 586 | } | 583 | } |
| 587 | 584 | ||
| @@ -597,10 +594,6 @@ static void tcpm_debugfs_exit(struct tcpm_port *port) · 9 unmodified lines | |||
| 597 | mutex_unlock(&port->logbuffer_lock); | 594 | mutex_unlock(&port->logbuffer_lock); |
| 598 | 595 | ||
| 599 | debugfs_remove(port->dentry); | 596 | debugfs_remove(port->dentry); |
| 600 | if (list_empty(&rootdir->d_subdirs)) { | ||
| 601 | debugfs_remove(rootdir); | ||
| 602 | rootdir = NULL; | ||
| 603 | } | ||
| 604 | } | 597 | } |
| 605 | 598 | ||
| 606 | #else | 599 | #else |
| @@ -4434,8 +4427,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, · 3827 unmodified lines | |||
| 4434 | goto sink; | 4427 | goto sink; |
| 4435 | 4428 | ||
| 4436 | /* Get source pdos */ | 4429 | /* Get source pdos */ |
| 4437 | ret = fwnode_property_read_u32_array(fwnode, "source-pdos", | 4430 | ret = fwnode_property_count_u32(fwnode, "source-pdos"); |
| 4438 | NULL, 0); | ||
| 4439 | if (ret <= 0) | 4431 | if (ret <= 0) |
| 4440 | return -EINVAL; | 4432 | return -EINVAL; |
| 4441 | 4433 | ||
| @@ -4459,8 +4451,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, · 17 unmodified lines | |||
| 4459 | return -EINVAL; | 4451 | return -EINVAL; |
| 4460 | sink: | 4452 | sink: |
| 4461 | /* Get sink pdos */ | 4453 | /* Get sink pdos */ |
| 4462 | ret = fwnode_property_read_u32_array(fwnode, "sink-pdos", | 4454 | ret = fwnode_property_count_u32(fwnode, "sink-pdos"); |
| 4463 | NULL, 0); | ||
| 4464 | if (ret <= 0) | 4455 | if (ret <= 0) |
| 4465 | return -EINVAL; | 4456 | return -EINVAL; |
| 4466 | 4457 | ||
| @@ -617,10 +617,8 @@ static int wcove_typec_probe(struct platform_device *pdev) · 616 unmodified lines | |||
| 617 | wcove->regmap = pmic->regmap; | 617 | wcove->regmap = pmic->regmap; |
| 618 | 618 | ||
| 619 | irq = platform_get_irq(pdev, 0); | 619 | irq = platform_get_irq(pdev, 0); |
| 620 | if (irq < 0) { | 620 | if (irq < 0) |
| 621 | dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); | ||
| 622 | return irq; | 621 | return irq; |
| 623 | } | ||
| 624 | 622 | ||
| 625 | irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq); | 623 | irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq); |
| 626 | if (irq < 0) | 624 | if (irq < 0) |
| @@ -1104,14 +1104,11 @@ static ssize_t do_flash_store(struct device *dev, · 1103 unmodified lines | |||
| 1104 | 1104 | ||
| 1105 | static DEVICE_ATTR_WO(do_flash); | 1105 | static DEVICE_ATTR_WO(do_flash); |
| 1106 | 1106 | ||
| 1107 | static struct attribute *ucsi_ccg_sysfs_attrs[] = { | 1107 | static struct attribute *ucsi_ccg_attrs[] = { |
| 1108 | &dev_attr_do_flash.attr, | 1108 | &dev_attr_do_flash.attr, |
| 1109 | NULL, | 1109 | NULL, |
| 1110 | }; | 1110 | }; |
| 1111 | 1111 | ATTRIBUTE_GROUPS(ucsi_ccg); | |
| 1112 | static struct attribute_group ucsi_ccg_attr_group = { | ||
| 1113 | .attrs = ucsi_ccg_sysfs_attrs, | ||
| 1114 | }; | ||
| 1115 | 1112 | ||
| 1116 | static int ucsi_ccg_probe(struct i2c_client *client, | 1113 | static int ucsi_ccg_probe(struct i2c_client *client, |
| 1117 | const struct i2c_device_id *id) | 1114 | const struct i2c_device_id *id) |
| @@ -1189,10 +1186,6 @@ static int ucsi_ccg_probe(struct i2c_client *client, · 71 unmodified lines | |||
| 1189 | 1186 | ||
| 1190 | i2c_set_clientdata(client, uc); | 1187 | i2c_set_clientdata(client, uc); |
| 1191 | 1188 | ||
| 1192 | status = sysfs_create_group(&uc->dev->kobj, &ucsi_ccg_attr_group); | ||
| 1193 | if (status) | ||
| 1194 | dev_err(uc->dev, "cannot create sysfs group: %d\n", status); | ||
| 1195 | |||
| 1196 | pm_runtime_set_active(uc->dev); | 1189 | pm_runtime_set_active(uc->dev); |
| 1197 | pm_runtime_enable(uc->dev); | 1190 | pm_runtime_enable(uc->dev); |
| 1198 | pm_runtime_idle(uc->dev); | 1191 | pm_runtime_idle(uc->dev); |
| @@ -1209,7 +1202,6 @@ static int ucsi_ccg_remove(struct i2c_client *client) · 10 unmodified lines | |||
| 1209 | ucsi_unregister_ppm(uc->ucsi); | 1202 | ucsi_unregister_ppm(uc->ucsi); |
| 1210 | pm_runtime_disable(uc->dev); | 1203 | pm_runtime_disable(uc->dev); |
| 1211 | free_irq(uc->irq, uc); | 1204 | free_irq(uc->irq, uc); |
| 1212 | sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group); | ||
| 1213 | 1205 | ||
| 1214 | return 0; | 1206 | return 0; |
| 1215 | } | 1207 | } |
| @@ -1270,6 +1262,7 @@ static struct i2c_driver ucsi_ccg_driver = { · 54 unmodified lines | |||
| 1270 | .driver = { | 1262 | .driver = { |
| 1271 | .name = "ucsi_ccg", | 1263 | .name = "ucsi_ccg", |
| 1272 | .pm = &ucsi_ccg_pm, | 1264 | .pm = &ucsi_ccg_pm, |
| 1265 | .dev_groups = ucsi_ccg_groups, | ||
| 1273 | }, | 1266 | }, |
| 1274 | .probe = ucsi_ccg_probe, | 1267 | .probe = ucsi_ccg_probe, |
| 1275 | .remove = ucsi_ccg_remove, | 1268 | .remove = ucsi_ccg_remove, |
| @@ -35,9 +35,11 @@ MODULE_DEVICE_TABLE(usb, skel_table); · 34 unmodified lines | |||
| 35 | 35 | ||
| 36 | /* our private defines. if this grows any larger, use your own .h file */ | 36 | /* our private defines. if this grows any larger, use your own .h file */ |
| 37 | #define MAX_TRANSFER (PAGE_SIZE - 512) | 37 | #define MAX_TRANSFER (PAGE_SIZE - 512) |
| 38 | /* MAX_TRANSFER is chosen so that the VM is not stressed by | 38 | /* |
| 39 | allocations > PAGE_SIZE and the number of packets in a page | 39 | * MAX_TRANSFER is chosen so that the VM is not stressed by |
| 40 | is an integer 512 is the largest possible packet on EHCI */ | 40 | * allocations > PAGE_SIZE and the number of packets in a page |
| 41 | * is an integer 512 is the largest possible packet on EHCI | ||
| 42 | */ | ||
| 41 | #define WRITES_IN_FLIGHT 8 | 43 | #define WRITES_IN_FLIGHT 8 |
| 42 | /* arbitrarily chosen */ | 44 | /* arbitrarily chosen */ |
| 43 | 45 | ||
| @@ -52,7 +52,11 @@ struct stub_priv { · 51 unmodified lines | |||
| 52 | unsigned long seqnum; | 52 | unsigned long seqnum; |
| 53 | struct list_head list; | 53 | struct list_head list; |
| 54 | struct stub_device *sdev; | 54 | struct stub_device *sdev; |
| 55 | struct urb *urb; | 55 | struct urb **urbs; |
| 56 | struct scatterlist *sgl; | ||
| 57 | int num_urbs; | ||
| 58 | int completed_urbs; | ||
| 59 | int urb_status; | ||
| 56 | 60 | ||
| 57 | int unlinking; | 61 | int unlinking; |
| 58 | }; | 62 | }; |
| @@ -86,6 +90,7 @@ extern struct usb_device_driver stub_driver; · 27 unmodified lines | |||
| 86 | struct bus_id_priv *get_busid_priv(const char *busid); | 90 | struct bus_id_priv *get_busid_priv(const char *busid); |
| 87 | void put_busid_priv(struct bus_id_priv *bid); | 91 | void put_busid_priv(struct bus_id_priv *bid); |
| 88 | int del_match_busid(char *busid); | 92 | int del_match_busid(char *busid); |
| 93 | void stub_free_priv_and_urb(struct stub_priv *priv); | ||
| 89 | void stub_device_cleanup_urbs(struct stub_device *sdev); | 94 | void stub_device_cleanup_urbs(struct stub_device *sdev); |
| 90 | 95 | ||
| 91 | /* stub_rx.c */ | 96 | /* stub_rx.c */ |
| @@ -106,38 +106,13 @@ err: · 105 unmodified lines | |||
| 106 | } | 106 | } |
| 107 | static DEVICE_ATTR_WO(usbip_sockfd); | 107 | static DEVICE_ATTR_WO(usbip_sockfd); |
| 108 | 108 | ||
| 109 | static int stub_add_files(struct device *dev) | 109 | static struct attribute *usbip_attrs[] = { |
| 110 | { | 110 | &dev_attr_usbip_status.attr, |
| 111 | int err = 0; | 111 | &dev_attr_usbip_sockfd.attr, |
| 112 | 112 | &dev_attr_usbip_debug.attr, | |
| 113 | err = device_create_file(dev, &dev_attr_usbip_status); | 113 | NULL, |
| 114 | if (err) | 114 | }; |
| 115 | goto err_status; | 115 | ATTRIBUTE_GROUPS(usbip); |
| 116 | |||
| 117 | err = device_create_file(dev, &dev_attr_usbip_sockfd); | ||
| 118 | if (err) | ||
| 119 | goto err_sockfd; | ||
| 120 | |||
| 121 | err = device_create_file(dev, &dev_attr_usbip_debug); | ||
| 122 | if (err) | ||
| 123 | goto err_debug; | ||
| 124 | |||
| 125 | return 0; | ||
| 126 | |||
| 127 | err_debug: | ||
| 128 | device_remove_file(dev, &dev_attr_usbip_sockfd); | ||
| 129 | err_sockfd: | ||
| 130 | device_remove_file(dev, &dev_attr_usbip_status); | ||
| 131 | err_status: | ||
| 132 | return err; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void stub_remove_files(struct device *dev) | ||
| 136 | { | ||
| 137 | device_remove_file(dev, &dev_attr_usbip_status); | ||
| 138 | device_remove_file(dev, &dev_attr_usbip_sockfd); | ||
| 139 | device_remove_file(dev, &dev_attr_usbip_debug); | ||
| 140 | } | ||
| 141 | 116 | ||
| 142 | static void stub_shutdown_connection(struct usbip_device *ud) | 117 | static void stub_shutdown_connection(struct usbip_device *ud) |
| 143 | { | 118 | { |
| @@ -379,17 +354,8 @@ static int stub_probe(struct usb_device *udev) · 235 unmodified lines | |||
| 379 | goto err_port; | 354 | goto err_port; |
| 380 | } | 355 | } |
| 381 | 356 | ||
| 382 | rc = stub_add_files(&udev->dev); | ||
| 383 | if (rc) { | ||
| 384 | dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); | ||
| 385 | goto err_files; | ||
| 386 | } | ||
| 387 | |||
| 388 | return 0; | 357 | return 0; |
| 389 | 358 | ||
| 390 | err_files: | ||
| 391 | usb_hub_release_port(udev->parent, udev->portnum, | ||
| 392 | (struct usb_dev_state *) udev); | ||
| 393 | err_port: | 359 | err_port: |
| 394 | dev_set_drvdata(&udev->dev, NULL); | 360 | dev_set_drvdata(&udev->dev, NULL); |
| 395 | usb_put_dev(udev); | 361 | usb_put_dev(udev); |
| @@ -457,7 +423,6 @@ static void stub_disconnect(struct usb_device *udev) · 61 unmodified lines | |||
| 457 | /* | 423 | /* |
| 458 | * NOTE: rx/tx threads are invoked for each usb_device. | 424 | * NOTE: rx/tx threads are invoked for each usb_device. |
| 459 | */ | 425 | */ |
| 460 | stub_remove_files(&udev->dev); | ||
| 461 | 426 | ||
| 462 | /* release port */ | 427 | /* release port */ |
| 463 | rc = usb_hub_release_port(udev->parent, udev->portnum, | 428 | rc = usb_hub_release_port(udev->parent, udev->portnum, |
| @@ -526,4 +491,5 @@ struct usb_device_driver stub_driver = { · 62 unmodified lines | |||
| 526 | .resume = stub_resume, | 491 | .resume = stub_resume, |
| 527 | #endif | 492 | #endif |
| 528 | .supports_autosuspend = 0, | 493 | .supports_autosuspend = 0, |
| 494 | .dev_groups = usbip_groups, | ||
| 529 | }; | 495 | }; |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 9 | #include <linux/scatterlist.h> | ||
| 9 | 10 | ||
| 10 | #include "usbip_common.h" | 11 | #include "usbip_common.h" |
| 11 | #include "stub.h" | 12 | #include "stub.h" |
| @@ -281,13 +282,49 @@ static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) · 269 unmodified lines | |||
| 281 | struct stub_priv *priv, *tmp; | 282 | struct stub_priv *priv, *tmp; |
| 282 | 283 | ||
| 283 | list_for_each_entry_safe(priv, tmp, listhead, list) { | 284 | list_for_each_entry_safe(priv, tmp, listhead, list) { |
| 284 | list_del(&priv->list); | 285 | list_del_init(&priv->list); |
| 285 | return priv; | 286 | return priv; |
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | return NULL; | 289 | return NULL; |
| 289 | } | 290 | } |
| 290 | 291 | ||
| 292 | void stub_free_priv_and_urb(struct stub_priv *priv) | ||
| 293 | { | ||
| 294 | struct urb *urb; | ||
| 295 | int i; | ||
| 296 | |||
| 297 | for (i = 0; i < priv->num_urbs; i++) { | ||
| 298 | urb = priv->urbs[i]; | ||
| 299 | |||
| 300 | if (!urb) | ||
| 301 | return; | ||
| 302 | |||
| 303 | kfree(urb->setup_packet); | ||
| 304 | urb->setup_packet = NULL; | ||
| 305 | |||
| 306 | |||
| 307 | if (urb->transfer_buffer && !priv->sgl) { | ||
| 308 | kfree(urb->transfer_buffer); | ||
| 309 | urb->transfer_buffer = NULL; | ||
| 310 | } | ||
| 311 | |||
| 312 | if (urb->num_sgs) { | ||
| 313 | sgl_free(urb->sg); | ||
| 314 | urb->sg = NULL; | ||
| 315 | urb->num_sgs = 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | usb_free_urb(urb); | ||
| 319 | } | ||
| 320 | if (!list_empty(&priv->list)) | ||
| 321 | list_del(&priv->list); | ||
| 322 | if (priv->sgl) | ||
| 323 | sgl_free(priv->sgl); | ||
| 324 | kfree(priv->urbs); | ||
| 325 | kmem_cache_free(stub_priv_cache, priv); | ||
| 326 | } | ||
| 327 | |||
| 291 | static struct stub_priv *stub_priv_pop(struct stub_device *sdev) | 328 | static struct stub_priv *stub_priv_pop(struct stub_device *sdev) |
| 292 | { | 329 | { |
| 293 | unsigned long flags; | 330 | unsigned long flags; |
| @@ -314,25 +351,15 @@ done: · 20 unmodified lines | |||
| 314 | void stub_device_cleanup_urbs(struct stub_device *sdev) | 351 | void stub_device_cleanup_urbs(struct stub_device *sdev) |
| 315 | { | 352 | { |
| 316 | struct stub_priv *priv; | 353 | struct stub_priv *priv; |
| 317 | struct urb *urb; | 354 | int i; |
| 318 | 355 | ||
| 319 | dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n"); | 356 | dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n"); |
| 320 | 357 | ||
| 321 | while ((priv = stub_priv_pop(sdev))) { | 358 | while ((priv = stub_priv_pop(sdev))) { |
| 322 | urb = priv->urb; | 359 | for (i = 0; i < priv->num_urbs; i++) |
| 323 | dev_dbg(&sdev->udev->dev, "free urb seqnum %lu\n", | 360 | usb_kill_urb(priv->urbs[i]); |
| 324 | priv->seqnum); | ||
| 325 | usb_kill_urb(urb); | ||
| 326 | |||
| 327 | kmem_cache_free(stub_priv_cache, priv); | ||
| 328 | 361 | ||
| 329 | kfree(urb->transfer_buffer); | 362 | stub_free_priv_and_urb(priv); |
| 330 | urb->transfer_buffer = NULL; | ||
| 331 | |||
| 332 | kfree(urb->setup_packet); | ||
| 333 | urb->setup_packet = NULL; | ||
| 334 | |||
| 335 | usb_free_urb(urb); | ||
| 336 | } | 363 | } |
| 337 | } | 364 | } |
| 338 | 365 | ||
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kthread.h> | 7 | #include <linux/kthread.h> |
| 8 | #include <linux/usb.h> | 8 | #include <linux/usb.h> |
| 9 | #include <linux/usb/hcd.h> | 9 | #include <linux/usb/hcd.h> |
| 10 | #include <linux/scatterlist.h> | ||
| 10 | 11 | ||
| 11 | #include "usbip_common.h" | 12 | #include "usbip_common.h" |
| 12 | #include "stub.h" | 13 | #include "stub.h" |
| @@ -201,7 +202,7 @@ static void tweak_special_requests(struct urb *urb) · 188 unmodified lines | |||
| 201 | static int stub_recv_cmd_unlink(struct stub_device *sdev, | 202 | static int stub_recv_cmd_unlink(struct stub_device *sdev, |
| 202 | struct usbip_header *pdu) | 203 | struct usbip_header *pdu) |
| 203 | { | 204 | { |
| 204 | int ret; | 205 | int ret, i; |
| 205 | unsigned long flags; | 206 | unsigned long flags; |
| 206 | struct stub_priv *priv; | 207 | struct stub_priv *priv; |
| 207 | 208 | ||
| @@ -246,12 +247,14 @@ static int stub_recv_cmd_unlink(struct stub_device *sdev, · 38 unmodified lines | |||
| 246 | * so a driver in a client host will know the failure | 247 | * so a driver in a client host will know the failure |
| 247 | * of the unlink request ? | 248 | * of the unlink request ? |
| 248 | */ | 249 | */ |
| 249 | ret = usb_unlink_urb(priv->urb); | 250 | for (i = priv->completed_urbs; i < priv->num_urbs; i++) { |
| 250 | if (ret != -EINPROGRESS) | 251 | ret = usb_unlink_urb(priv->urbs[i]); |
| 251 | dev_err(&priv->urb->dev->dev, | 252 | if (ret != -EINPROGRESS) |
| 252 | "failed to unlink a urb # %lu, ret %d\n", | 253 | dev_err(&priv->urbs[i]->dev->dev, |
| 253 | priv->seqnum, ret); | 254 | "failed to unlink %d/%d urb of seqnum %lu, ret %d\n", |
| 254 | 255 | i + 1, priv->num_urbs, | |
| 256 | priv->seqnum, ret); | ||
| 257 | } | ||
| 255 | return 0; | 258 | return 0; |
| 256 | } | 259 | } |
| 257 | 260 | ||
| @@ -433,14 +436,36 @@ static void masking_bogus_flags(struct urb *urb) · 175 unmodified lines | |||
| 433 | urb->transfer_flags &= allowed; | 436 | urb->transfer_flags &= allowed; |
| 434 | } | 437 | } |
| 435 | 438 | ||
| 439 | static int stub_recv_xbuff(struct usbip_device *ud, struct stub_priv *priv) | ||
| 440 | { | ||
| 441 | int ret; | ||
| 442 | int i; | ||
| 443 | |||
| 444 | for (i = 0; i < priv->num_urbs; i++) { | ||
| 445 | ret = usbip_recv_xbuff(ud, priv->urbs[i]); | ||
| 446 | if (ret < 0) | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | |||
| 450 | return ret; | ||
| 451 | } | ||
| 452 | |||
| 436 | static void stub_recv_cmd_submit(struct stub_device *sdev, | 453 | static void stub_recv_cmd_submit(struct stub_device *sdev, |
| 437 | struct usbip_header *pdu) | 454 | struct usbip_header *pdu) |
| 438 | { | 455 | { |
| 439 | int ret; | ||
| 440 | struct stub_priv *priv; | 456 | struct stub_priv *priv; |
| 441 | struct usbip_device *ud = &sdev->ud; | 457 | struct usbip_device *ud = &sdev->ud; |
| 442 | struct usb_device *udev = sdev->udev; | 458 | struct usb_device *udev = sdev->udev; |
| 459 | struct scatterlist *sgl = NULL, *sg; | ||
| 460 | void *buffer = NULL; | ||
| 461 | unsigned long long buf_len; | ||
| 462 | int nents; | ||
| 463 | int num_urbs = 1; | ||
| 443 | int pipe = get_pipe(sdev, pdu); | 464 | int pipe = get_pipe(sdev, pdu); |
| 465 | int use_sg = pdu->u.cmd_submit.transfer_flags & URB_DMA_MAP_SG; | ||
| 466 | int support_sg = 1; | ||
| 467 | int np = 0; | ||
| 468 | int ret, i; | ||
| 444 | 469 | ||
| 445 | if (pipe == -1) | 470 | if (pipe == -1) |
| 446 | return; | 471 | return; |
| @@ -449,76 +474,139 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, · 2 unmodified lines | |||
| 449 | if (!priv) | 474 | if (!priv) |
| 450 | return; | 475 | return; |
| 451 | 476 | ||
| 452 | /* setup a urb */ | 477 | buf_len = (unsigned long long)pdu->u.cmd_submit.transfer_buffer_length; |
| 453 | if (usb_pipeisoc(pipe)) | ||
| 454 | priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, | ||
| 455 | GFP_KERNEL); | ||
| 456 | else | ||
| 457 | priv->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 458 | 478 | ||
| 459 | if (!priv->urb) { | 479 | /* allocate urb transfer buffer, if needed */ |
| 460 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | 480 | if (buf_len) { |
| 461 | return; | 481 | if (use_sg) { |
| 482 | sgl = sgl_alloc(buf_len, GFP_KERNEL, &nents); | ||
| 483 | if (!sgl) | ||
| 484 | goto err_malloc; | ||
| 485 | } else { | ||
| 486 | buffer = kzalloc(buf_len, GFP_KERNEL); | ||
| 487 | if (!buffer) | ||
| 488 | goto err_malloc; | ||
| 489 | } | ||
| 462 | } | 490 | } |
| 463 | 491 | ||
| 464 | /* allocate urb transfer buffer, if needed */ | 492 | /* Check if the server's HCD supports SG */ |
| 465 | if (pdu->u.cmd_submit.transfer_buffer_length > 0) { | 493 | if (use_sg && !udev->bus->sg_tablesize) { |
| 466 | priv->urb->transfer_buffer = | 494 | /* |
| 467 | kzalloc(pdu->u.cmd_submit.transfer_buffer_length, | 495 | * If the server's HCD doesn't support SG, break a single SG |
| 468 | GFP_KERNEL); | 496 | * request into several URBs and map each SG list entry to |
| 469 | if (!priv->urb->transfer_buffer) { | 497 | * corresponding URB buffer. The previously allocated SG |
| 498 | * list is stored in priv->sgl (If the server's HCD support SG, | ||
| 499 | * SG list is stored only in urb->sg) and it is used as an | ||
| 500 | * indicator that the server split single SG request into | ||
| 501 | * several URBs. Later, priv->sgl is used by stub_complete() and | ||
| 502 | * stub_send_ret_submit() to reassemble the divied URBs. | ||
| 503 | */ | ||
| 504 | support_sg = 0; | ||
| 505 | num_urbs = nents; | ||
| 506 | priv->completed_urbs = 0; | ||
| 507 | pdu->u.cmd_submit.transfer_flags &= ~URB_DMA_MAP_SG; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* allocate urb array */ | ||
| 511 | priv->num_urbs = num_urbs; | ||
| 512 | priv->urbs = kmalloc_array(num_urbs, sizeof(*priv->urbs), GFP_KERNEL); | ||
| 513 | if (!priv->urbs) | ||
| 514 | goto err_urbs; | ||
| 515 | |||
| 516 | /* setup a urb */ | ||
| 517 | if (support_sg) { | ||
| 518 | if (usb_pipeisoc(pipe)) | ||
| 519 | np = pdu->u.cmd_submit.number_of_packets; | ||
| 520 | |||
| 521 | priv->urbs[0] = usb_alloc_urb(np, GFP_KERNEL); | ||
| 522 | if (!priv->urbs[0]) | ||
| 523 | goto err_urb; | ||
| 524 | |||
| 525 | if (buf_len) { | ||
| 526 | if (use_sg) { | ||
| 527 | priv->urbs[0]->sg = sgl; | ||
| 528 | priv->urbs[0]->num_sgs = nents; | ||
| 529 | priv->urbs[0]->transfer_buffer = NULL; | ||
| 530 | } else { | ||
| 531 | priv->urbs[0]->transfer_buffer = buffer; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | |||
| 535 | /* copy urb setup packet */ | ||
| 536 | priv->urbs[0]->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, | ||
| 537 | 8, GFP_KERNEL); | ||
| 538 | if (!priv->urbs[0]->setup_packet) { | ||
| 470 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | 539 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); |
| 471 | return; | 540 | return; |
| 472 | } | 541 | } |
| 473 | } | ||
| 474 | 542 | ||
| 475 | /* copy urb setup packet */ | 543 | usbip_pack_pdu(pdu, priv->urbs[0], USBIP_CMD_SUBMIT, 0); |
| 476 | priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8, | 544 | } else { |
| 477 | GFP_KERNEL); | 545 | for_each_sg(sgl, sg, nents, i) { |
| 478 | if (!priv->urb->setup_packet) { | 546 | priv->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); |
| 479 | dev_err(&udev->dev, "allocate setup_packet\n"); | 547 | /* The URBs which is previously allocated will be freed |
| 480 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | 548 | * in stub_device_cleanup_urbs() if error occurs. |
| 481 | return; | 549 | */ |
| 550 | if (!priv->urbs[i]) | ||
| 551 | goto err_urb; | ||
| 552 | |||
| 553 | usbip_pack_pdu(pdu, priv->urbs[i], USBIP_CMD_SUBMIT, 0); | ||
| 554 | priv->urbs[i]->transfer_buffer = sg_virt(sg); | ||
| 555 | priv->urbs[i]->transfer_buffer_length = sg->length; | ||
| 556 | } | ||
| 557 | priv->sgl = sgl; | ||
| 482 | } | 558 | } |
| 483 | 559 | ||
| 484 | /* set other members from the base header of pdu */ | 560 | for (i = 0; i < num_urbs; i++) { |
| 485 | priv->urb->context = (void *) priv; | 561 | /* set other members from the base header of pdu */ |
| 486 | priv->urb->dev = udev; | 562 | priv->urbs[i]->context = (void *) priv; |
| 487 | priv->urb->pipe = pipe; | 563 | priv->urbs[i]->dev = udev; |
| 488 | priv->urb->complete = stub_complete; | 564 | priv->urbs[i]->pipe = pipe; |
| 565 | priv->urbs[i]->complete = stub_complete; | ||
| 489 | 566 | ||
| 490 | usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); | 567 | /* no need to submit an intercepted request, but harmless? */ |
| 568 | tweak_special_requests(priv->urbs[i]); | ||
| 491 | 569 | ||
| 570 | masking_bogus_flags(priv->urbs[i]); | ||
| 571 | } | ||
| 492 | 572 | ||
| 493 | if (usbip_recv_xbuff(ud, priv->urb) < 0) | 573 | if (stub_recv_xbuff(ud, priv) < 0) |
| 494 | return; | 574 | return; |
| 495 | 575 | ||
| 496 | if (usbip_recv_iso(ud, priv->urb) < 0) | 576 | if (usbip_recv_iso(ud, priv->urbs[0]) < 0) |
| 497 | return; | 577 | return; |
| 498 | 578 | ||
| 499 | /* no need to submit an intercepted request, but harmless? */ | ||
| 500 | tweak_special_requests(priv->urb); | ||
| 501 | |||
| 502 | masking_bogus_flags(priv->urb); | ||
| 503 | /* urb is now ready to submit */ | 579 | /* urb is now ready to submit */ |
| 504 | ret = usb_submit_urb(priv->urb, GFP_KERNEL); | 580 | for (i = 0; i < priv->num_urbs; i++) { |
| 505 | 581 | ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL); | |
| 506 | if (ret == 0) | 582 | |
| 507 | usbip_dbg_stub_rx("submit urb ok, seqnum %u\n", | 583 | if (ret == 0) |
| 508 | pdu->base.seqnum); | 584 | usbip_dbg_stub_rx("submit urb ok, seqnum %u\n", |
| 509 | else { | 585 | pdu->base.seqnum); |
| 510 | dev_err(&udev->dev, "submit_urb error, %d\n", ret); | 586 | else { |
| 511 | usbip_dump_header(pdu); | 587 | dev_err(&udev->dev, "submit_urb error, %d\n", ret); |
| 512 | usbip_dump_urb(priv->urb); | 588 | usbip_dump_header(pdu); |
| 513 | 589 | usbip_dump_urb(priv->urbs[i]); | |
| 514 | /* | 590 | |
| 515 | * Pessimistic. | 591 | /* |
| 516 | * This connection will be discarded. | 592 | * Pessimistic. |
| 517 | */ | 593 | * This connection will be discarded. |
| 518 | usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); | 594 | */ |
| 595 | usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); | ||
| 596 | break; | ||
| 597 | } | ||
| 519 | } | 598 | } |
| 520 | 599 | ||
| 521 | usbip_dbg_stub_rx("Leave\n"); | 600 | usbip_dbg_stub_rx("Leave\n"); |
| 601 | return; | ||
| 602 | |||
| 603 | err_urb: | ||
| 604 | kfree(priv->urbs); | ||
| 605 | err_urbs: | ||
| 606 | kfree(buffer); | ||
| 607 | sgl_free(sgl); | ||
| 608 | err_malloc: | ||
| 609 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | ||
| 522 | } | 610 | } |
| 523 | 611 | ||
| 524 | /* recv a pdu */ | 612 | /* recv a pdu */ |
| @@ -5,25 +5,11 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
| 7 | #include <linux/socket.h> | 7 | #include <linux/socket.h> |
| 8 | #include <linux/scatterlist.h> | ||
| 8 | 9 | ||
| 9 | #include "usbip_common.h" | 10 | #include "usbip_common.h" |
| 10 | #include "stub.h" | 11 | #include "stub.h" |
| 11 | 12 | ||
| 12 | static void stub_free_priv_and_urb(struct stub_priv *priv) | ||
| 13 | { | ||
| 14 | struct urb *urb = priv->urb; | ||
| 15 | |||
| 16 | kfree(urb->setup_packet); | ||
| 17 | urb->setup_packet = NULL; | ||
| 18 | |||
| 19 | kfree(urb->transfer_buffer); | ||
| 20 | urb->transfer_buffer = NULL; | ||
| 21 | |||
| 22 | list_del(&priv->list); | ||
| 23 | kmem_cache_free(stub_priv_cache, priv); | ||
| 24 | usb_free_urb(urb); | ||
| 25 | } | ||
| 26 | |||
| 27 | /* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ | 13 | /* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ |
| 28 | void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, | 14 | void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, |
| 29 | __u32 status) | 15 | __u32 status) |
| @@ -85,6 +71,22 @@ void stub_complete(struct urb *urb) · 55 unmodified lines | |||
| 85 | break; | 71 | break; |
| 86 | } | 72 | } |
| 87 | 73 | ||
| 74 | /* | ||
| 75 | * If the server breaks single SG request into the several URBs, the | ||
| 76 | * URBs must be reassembled before sending completed URB to the vhci. | ||
| 77 | * Don't wake up the tx thread until all the URBs are completed. | ||
| 78 | */ | ||
| 79 | if (priv->sgl) { | ||
| 80 | priv->completed_urbs++; | ||
| 81 | |||
| 82 | /* Only save the first error status */ | ||
| 83 | if (urb->status && !priv->urb_status) | ||
| 84 | priv->urb_status = urb->status; | ||
| 85 | |||
| 86 | if (priv->completed_urbs < priv->num_urbs) | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 88 | /* link a urb to the queue of tx. */ | 90 | /* link a urb to the queue of tx. */ |
| 89 | spin_lock_irqsave(&sdev->priv_lock, flags); | 91 | spin_lock_irqsave(&sdev->priv_lock, flags); |
| 90 | if (sdev->ud.tcp_socket == NULL) { | 92 | if (sdev->ud.tcp_socket == NULL) { |
| @@ -156,18 +158,22 @@ static int stub_send_ret_submit(struct stub_device *sdev) · 65 unmodified lines | |||
| 156 | size_t total_size = 0; | 158 | size_t total_size = 0; |
| 157 | 159 | ||
| 158 | while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { | 160 | while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { |
| 159 | int ret; | 161 | struct urb *urb = priv->urbs[0]; |
| 160 | struct urb *urb = priv->urb; | ||
| 161 | struct usbip_header pdu_header; | 162 | struct usbip_header pdu_header; |
| 162 | struct usbip_iso_packet_descriptor *iso_buffer = NULL; | 163 | struct usbip_iso_packet_descriptor *iso_buffer = NULL; |
| 163 | struct kvec *iov = NULL; | 164 | struct kvec *iov = NULL; |
| 165 | struct scatterlist *sg; | ||
| 166 | u32 actual_length = 0; | ||
| 164 | int iovnum = 0; | 167 | int iovnum = 0; |
| 168 | int ret; | ||
| 169 | int i; | ||
| 165 | 170 | ||
| 166 | txsize = 0; | 171 | txsize = 0; |
| 167 | memset(&pdu_header, 0, sizeof(pdu_header)); | 172 | memset(&pdu_header, 0, sizeof(pdu_header)); |
| 168 | memset(&msg, 0, sizeof(msg)); | 173 | memset(&msg, 0, sizeof(msg)); |
| 169 | 174 | ||
| 170 | if (urb->actual_length > 0 && !urb->transfer_buffer) { | 175 | if (urb->actual_length > 0 && !urb->transfer_buffer && |
| 176 | !urb->num_sgs) { | ||
| 171 | dev_err(&sdev->udev->dev, | 177 | dev_err(&sdev->udev->dev, |
| 172 | "urb: actual_length %d transfer_buffer null\n", | 178 | "urb: actual_length %d transfer_buffer null\n", |
| 173 | urb->actual_length); | 179 | urb->actual_length); |
| @@ -176,6 +182,11 @@ static int stub_send_ret_submit(struct stub_device *sdev) · 2 unmodified lines | |||
| 176 | 182 | ||
| 177 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) | 183 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) |
| 178 | iovnum = 2 + urb->number_of_packets; | 184 | iovnum = 2 + urb->number_of_packets; |
| 185 | else if (usb_pipein(urb->pipe) && urb->actual_length > 0 && | ||
| 186 | urb->num_sgs) | ||
| 187 | iovnum = 1 + urb->num_sgs; | ||
| 188 | else if (usb_pipein(urb->pipe) && priv->sgl) | ||
| 189 | iovnum = 1 + priv->num_urbs; | ||
| 179 | else | 190 | else |
| 180 | iovnum = 2; | 191 | iovnum = 2; |
| 181 | 192 | ||
| @@ -192,6 +203,15 @@ static int stub_send_ret_submit(struct stub_device *sdev) · 10 unmodified lines | |||
| 192 | setup_ret_submit_pdu(&pdu_header, urb); | 203 | setup_ret_submit_pdu(&pdu_header, urb); |
| 193 | usbip_dbg_stub_tx("setup txdata seqnum: %d\n", | 204 | usbip_dbg_stub_tx("setup txdata seqnum: %d\n", |
| 194 | pdu_header.base.seqnum); | 205 | pdu_header.base.seqnum); |
| 206 | |||
| 207 | if (priv->sgl) { | ||
| 208 | for (i = 0; i < priv->num_urbs; i++) | ||
| 209 | actual_length += priv->urbs[i]->actual_length; | ||
| 210 | |||
| 211 | pdu_header.u.ret_submit.status = priv->urb_status; | ||
| 212 | pdu_header.u.ret_submit.actual_length = actual_length; | ||
| 213 | } | ||
| 214 | |||
| 195 | usbip_header_correct_endian(&pdu_header, 1); | 215 | usbip_header_correct_endian(&pdu_header, 1); |
| 196 | 216 | ||
| 197 | iov[iovnum].iov_base = &pdu_header; | 217 | iov[iovnum].iov_base = &pdu_header; |
| @@ -200,12 +220,47 @@ static int stub_send_ret_submit(struct stub_device *sdev) · 2 unmodified lines | |||
| 200 | txsize += sizeof(pdu_header); | 220 | txsize += sizeof(pdu_header); |
| 201 | 221 | ||
| 202 | /* 2. setup transfer buffer */ | 222 | /* 2. setup transfer buffer */ |
| 203 | if (usb_pipein(urb->pipe) && | 223 | if (usb_pipein(urb->pipe) && priv->sgl) { |
| 224 | /* If the server split a single SG request into several | ||
| 225 | * URBs because the server's HCD doesn't support SG, | ||
| 226 | * reassemble the split URB buffers into a single | ||
| 227 | * return command. | ||
| 228 | */ | ||
| 229 | for (i = 0; i < priv->num_urbs; i++) { | ||
| 230 | iov[iovnum].iov_base = | ||
| 231 | priv->urbs[i]->transfer_buffer; | ||
| 232 | iov[iovnum].iov_len = | ||
| 233 | priv->urbs[i]->actual_length; | ||
| 234 | iovnum++; | ||
| 235 | } | ||
| 236 | txsize += actual_length; | ||
| 237 | } else if (usb_pipein(urb->pipe) && | ||
| 204 | usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS && | 238 | usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS && |
| 205 | urb->actual_length > 0) { | 239 | urb->actual_length > 0) { |
| 206 | iov[iovnum].iov_base = urb->transfer_buffer; | 240 | if (urb->num_sgs) { |
| 207 | iov[iovnum].iov_len = urb->actual_length; | 241 | unsigned int copy = urb->actual_length; |
| 208 | iovnum++; | 242 | int size; |
| 243 | |||
| 244 | for_each_sg(urb->sg, sg, urb->num_sgs, i) { | ||
| 245 | if (copy == 0) | ||
| 246 | break; | ||
| 247 | |||
| 248 | if (copy < sg->length) | ||
| 249 | size = copy; | ||
| 250 | else | ||
| 251 | size = sg->length; | ||
| 252 | |||
| 253 | iov[iovnum].iov_base = sg_virt(sg); | ||
| 254 | iov[iovnum].iov_len = size; | ||
| 255 | |||
| 256 | iovnum++; | ||
| 257 | copy -= size; | ||
| 258 | } | ||
| 259 | } else { | ||
| 260 | iov[iovnum].iov_base = urb->transfer_buffer; | ||
| 261 | iov[iovnum].iov_len = urb->actual_length; | ||
| 262 | iovnum++; | ||
| 263 | } | ||
| 209 | txsize += urb->actual_length; | 264 | txsize += urb->actual_length; |
| 210 | } else if (usb_pipein(urb->pipe) && | 265 | } else if (usb_pipein(urb->pipe) && |
| 211 | usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | 266 | usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { |
| @@ -680,8 +680,12 @@ EXPORT_SYMBOL_GPL(usbip_pad_iso); · 679 unmodified lines | |||
| 680 | /* some members of urb must be substituted before. */ | 680 | /* some members of urb must be substituted before. */ |
| 681 | int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) | 681 | int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) |
| 682 | { | 682 | { |
| 683 | int ret; | 683 | struct scatterlist *sg; |
| 684 | int ret = 0; | ||
| 685 | int recv; | ||
| 684 | int size; | 686 | int size; |
| 687 | int copy; | ||
| 688 | int i; | ||
| 685 | 689 | ||
| 686 | if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) { | 690 | if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) { |
| 687 | /* the direction of urb must be OUT. */ | 691 | /* the direction of urb must be OUT. */ |
| @@ -701,29 +705,48 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) · 13 unmodified lines | |||
| 701 | if (!(size > 0)) | 705 | if (!(size > 0)) |
| 702 | return 0; | 706 | return 0; |
| 703 | 707 | ||
| 704 | if (size > urb->transfer_buffer_length) { | 708 | if (size > urb->transfer_buffer_length) |
| 705 | /* should not happen, probably malicious packet */ | 709 | /* should not happen, probably malicious packet */ |
| 706 | if (ud->side == USBIP_STUB) { | 710 | goto error; |
| 707 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | ||
| 708 | return 0; | ||
| 709 | } else { | ||
| 710 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | ||
| 711 | return -EPIPE; | ||
| 712 | } | ||
| 713 | } | ||
| 714 | 711 | ||
| 715 | ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); | 712 | if (urb->num_sgs) { |
| 716 | if (ret != size) { | 713 | copy = size; |
| 717 | dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); | 714 | for_each_sg(urb->sg, sg, urb->num_sgs, i) { |
| 718 | if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) { | 715 | int recv_size; |
| 719 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | 716 | |
| 720 | } else { | 717 | if (copy < sg->length) |
| 721 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | 718 | recv_size = copy; |
| 722 | return -EPIPE; | 719 | else |
| 720 | recv_size = sg->length; | ||
| 721 | |||
| 722 | recv = usbip_recv(ud->tcp_socket, sg_virt(sg), | ||
| 723 | recv_size); | ||
| 724 | |||
| 725 | if (recv != recv_size) | ||
| 726 | goto error; | ||
| 727 | |||
| 728 | copy -= recv; | ||
| 729 | ret += recv; | ||
| 723 | } | 730 | } |
| 731 | |||
| 732 | if (ret != size) | ||
| 733 | goto error; | ||
| 734 | } else { | ||
| 735 | ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); | ||
| 736 | if (ret != size) | ||
| 737 | goto error; | ||
| 724 | } | 738 | } |
| 725 | 739 | ||
| 726 | return ret; | 740 | return ret; |
| 741 | |||
| 742 | error: | ||
| 743 | dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); | ||
| 744 | if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) | ||
| 745 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | ||
| 746 | else | ||
| 747 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | ||
| 748 | |||
| 749 | return -EPIPE; | ||
| 727 | } | 750 | } |
| 728 | EXPORT_SYMBOL_GPL(usbip_recv_xbuff); | 751 | EXPORT_SYMBOL_GPL(usbip_recv_xbuff); |
| 729 | 752 | ||
| @@ -697,7 +697,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag · 696 unmodified lines | |||
| 697 | } | 697 | } |
| 698 | vdev = &vhci_hcd->vdev[portnum-1]; | 698 | vdev = &vhci_hcd->vdev[portnum-1]; |
| 699 | 699 | ||
| 700 | if (!urb->transfer_buffer && urb->transfer_buffer_length) { | 700 | if (!urb->transfer_buffer && !urb->num_sgs && |
| 701 | urb->transfer_buffer_length) { | ||
| 701 | dev_dbg(dev, "Null URB transfer buffer\n"); | 702 | dev_dbg(dev, "Null URB transfer buffer\n"); |
| 702 | return -EINVAL; | 703 | return -EINVAL; |
| 703 | } | 704 | } |
| @@ -1143,6 +1144,15 @@ static int vhci_setup(struct usb_hcd *hcd) · 439 unmodified lines | |||
| 1143 | hcd->speed = HCD_USB3; | 1144 | hcd->speed = HCD_USB3; |
| 1144 | hcd->self.root_hub->speed = USB_SPEED_SUPER; | 1145 | hcd->self.root_hub->speed = USB_SPEED_SUPER; |
| 1145 | } | 1146 | } |
| 1147 | |||
| 1148 | /* | ||
| 1149 | * Support SG. | ||
| 1150 | * sg_tablesize is an arbitrary value to alleviate memory pressure | ||
| 1151 | * on the host. | ||
| 1152 | */ | ||
| 1153 | hcd->self.sg_tablesize = 32; | ||
| 1154 | hcd->self.no_sg_constraint = 1; | ||
| 1155 | |||
| 1146 | return 0; | 1156 | return 0; |
| 1147 | } | 1157 | } |
| 1148 | 1158 | ||
| @@ -90,6 +90,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, · 89 unmodified lines | |||
| 90 | if (usbip_dbg_flag_vhci_rx) | 90 | if (usbip_dbg_flag_vhci_rx) |
| 91 | usbip_dump_urb(urb); | 91 | usbip_dump_urb(urb); |
| 92 | 92 | ||
| 93 | if (urb->num_sgs) | ||
| 94 | urb->transfer_flags &= ~URB_DMA_MAP_SG; | ||
| 95 | |||
| 93 | usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum); | 96 | usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum); |
| 94 | 97 | ||
| 95 | spin_lock_irqsave(&vhci->lock, flags); | 98 | spin_lock_irqsave(&vhci->lock, flags); |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
| 7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
| 8 | #include <linux/scatterlist.h> | ||
| 8 | 9 | ||
| 9 | #include "usbip_common.h" | 10 | #include "usbip_common.h" |
| 10 | #include "vhci.h" | 11 | #include "vhci.h" |
| @@ -50,19 +51,23 @@ static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) · 39 unmodified lines | |||
| 50 | 51 | ||
| 51 | static int vhci_send_cmd_submit(struct vhci_device *vdev) | 52 | static int vhci_send_cmd_submit(struct vhci_device *vdev) |
| 52 | { | 53 | { |
| 54 | struct usbip_iso_packet_descriptor *iso_buffer = NULL; | ||
| 53 | struct vhci_priv *priv = NULL; | 55 | struct vhci_priv *priv = NULL; |
| 56 | struct scatterlist *sg; | ||
| 54 | 57 | ||
| 55 | struct msghdr msg; | 58 | struct msghdr msg; |
| 56 | struct kvec iov[3]; | 59 | struct kvec *iov; |
| 57 | size_t txsize; | 60 | size_t txsize; |
| 58 | 61 | ||
| 59 | size_t total_size = 0; | 62 | size_t total_size = 0; |
| 63 | int iovnum; | ||
| 64 | int err = -ENOMEM; | ||
| 65 | int i; | ||
| 60 | 66 | ||
| 61 | while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { | 67 | while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { |
| 62 | int ret; | 68 | int ret; |
| 63 | struct urb *urb = priv->urb; | 69 | struct urb *urb = priv->urb; |
| 64 | struct usbip_header pdu_header; | 70 | struct usbip_header pdu_header; |
| 65 | struct usbip_iso_packet_descriptor *iso_buffer = NULL; | ||
| 66 | 71 | ||
| 67 | txsize = 0; | 72 | txsize = 0; |
| 68 | memset(&pdu_header, 0, sizeof(pdu_header)); | 73 | memset(&pdu_header, 0, sizeof(pdu_header)); |
| @@ -72,18 +77,45 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) · 3 unmodified lines | |||
| 72 | usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n", | 77 | usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n", |
| 73 | priv->seqnum); | 78 | priv->seqnum); |
| 74 | 79 | ||
| 80 | if (urb->num_sgs && usb_pipeout(urb->pipe)) | ||
| 81 | iovnum = 2 + urb->num_sgs; | ||
| 82 | else | ||
| 83 | iovnum = 3; | ||
| 84 | |||
| 85 | iov = kcalloc(iovnum, sizeof(*iov), GFP_KERNEL); | ||
| 86 | if (!iov) { | ||
| 87 | usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC); | ||
| 88 | return -ENOMEM; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (urb->num_sgs) | ||
| 92 | urb->transfer_flags |= URB_DMA_MAP_SG; | ||
| 93 | |||
| 75 | /* 1. setup usbip_header */ | 94 | /* 1. setup usbip_header */ |
| 76 | setup_cmd_submit_pdu(&pdu_header, urb); | 95 | setup_cmd_submit_pdu(&pdu_header, urb); |
| 77 | usbip_header_correct_endian(&pdu_header, 1); | 96 | usbip_header_correct_endian(&pdu_header, 1); |
| 97 | iovnum = 0; | ||
| 78 | 98 | ||
| 79 | iov[0].iov_base = &pdu_header; | 99 | iov[iovnum].iov_base = &pdu_header; |
| 80 | iov[0].iov_len = sizeof(pdu_header); | 100 | iov[iovnum].iov_len = sizeof(pdu_header); |
| 81 | txsize += sizeof(pdu_header); | 101 | txsize += sizeof(pdu_header); |
| 102 | iovnum++; | ||
| 82 | 103 | ||
| 83 | /* 2. setup transfer buffer */ | 104 | /* 2. setup transfer buffer */ |
| 84 | if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { | 105 | if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { |
| 85 | iov[1].iov_base = urb->transfer_buffer; | 106 | if (urb->num_sgs && |
| 86 | iov[1].iov_len = urb->transfer_buffer_length; | 107 | !usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
| 108 | for_each_sg(urb->sg, sg, urb->num_sgs, i) { | ||
| 109 | iov[iovnum].iov_base = sg_virt(sg); | ||
| 110 | iov[iovnum].iov_len = sg->length; | ||
| 111 | iovnum++; | ||
| 112 | } | ||
| 113 | } else { | ||
| 114 | iov[iovnum].iov_base = urb->transfer_buffer; | ||
| 115 | iov[iovnum].iov_len = | ||
| 116 | urb->transfer_buffer_length; | ||
| 117 | iovnum++; | ||
| 118 | } | ||
| 87 | txsize += urb->transfer_buffer_length; | 119 | txsize += urb->transfer_buffer_length; |
| 88 | } | 120 | } |
| 89 | 121 | ||
| @@ -95,23 +127,26 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) · 5 unmodified lines | |||
| 95 | if (!iso_buffer) { | 127 | if (!iso_buffer) { |
| 96 | usbip_event_add(&vdev->ud, | 128 | usbip_event_add(&vdev->ud, |
| 97 | SDEV_EVENT_ERROR_MALLOC); | 129 | SDEV_EVENT_ERROR_MALLOC); |
| 98 | return -1; | 130 | goto err_iso_buffer; |
| 99 | } | 131 | } |
| 100 | 132 | ||
| 101 | iov[2].iov_base = iso_buffer; | 133 | iov[iovnum].iov_base = iso_buffer; |
| 102 | iov[2].iov_len = len; | 134 | iov[iovnum].iov_len = len; |
| 135 | iovnum++; | ||
| 103 | txsize += len; | 136 | txsize += len; |
| 104 | } | 137 | } |
| 105 | 138 | ||
| 106 | ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); | 139 | ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, iovnum, |
| 140 | txsize); | ||
| 107 | if (ret != txsize) { | 141 | if (ret != txsize) { |
| 108 | pr_err("sendmsg failed!, ret=%d for %zd\n", ret, | 142 | pr_err("sendmsg failed!, ret=%d for %zd\n", ret, |
| 109 | txsize); | 143 | txsize); |
| 110 | kfree(iso_buffer); | ||
| 111 | usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); | 144 | usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); |
| 112 | return -1; | 145 | err = -EPIPE; |
| 146 | goto err_tx; | ||
| 113 | } | 147 | } |
| 114 | 148 | ||
| 149 | kfree(iov); | ||
| 115 | kfree(iso_buffer); | 150 | kfree(iso_buffer); |
| 116 | usbip_dbg_vhci_tx("send txdata\n"); | 151 | usbip_dbg_vhci_tx("send txdata\n"); |
| 117 | 152 | ||
| @@ -119,6 +154,13 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) · 1 unmodified line | |||
| 119 | } | 154 | } |
| 120 | 155 | ||
| 121 | return total_size; | 156 | return total_size; |
| 157 | |||
| 158 | err_tx: | ||
| 159 | kfree(iso_buffer); | ||
| 160 | err_iso_buffer: | ||
| 161 | kfree(iov); | ||
| 162 | |||
| 163 | return err; | ||
| 122 | } | 164 | } |
| 123 | 165 | ||
| 124 | static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) | 166 | static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) |
| @@ -115,7 +115,7 @@ struct vudc_device { · 114 unmodified lines | |||
| 115 | struct list_head dev_entry; | 115 | struct list_head dev_entry; |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | extern const struct attribute_group vudc_attr_group; | 118 | extern const struct attribute_group *vudc_groups[]; |
| 119 | 119 | ||
| 120 | /* visible everywhere */ | 120 | /* visible everywhere */ |
| 121 | 121 | ||
| @@ -616,18 +616,10 @@ int vudc_probe(struct platform_device *pdev) · 615 unmodified lines | |||
| 616 | if (ret < 0) | 616 | if (ret < 0) |
| 617 | goto err_add_udc; | 617 | goto err_add_udc; |
| 618 | 618 | ||
| 619 | ret = sysfs_create_group(&pdev->dev.kobj, &vudc_attr_group); | ||
| 620 | if (ret) { | ||
| 621 | dev_err(&udc->pdev->dev, "create sysfs files\n"); | ||
| 622 | goto err_sysfs; | ||
| 623 | } | ||
| 624 | |||
| 625 | platform_set_drvdata(pdev, udc); | 619 | platform_set_drvdata(pdev, udc); |
| 626 | 620 | ||
| 627 | return ret; | 621 | return ret; |
| 628 | 622 | ||
| 629 | err_sysfs: | ||
| 630 | usb_del_gadget_udc(&udc->gadget); | ||
| 631 | err_add_udc: | 623 | err_add_udc: |
| 632 | cleanup_vudc_hw(udc); | 624 | cleanup_vudc_hw(udc); |
| 633 | err_init_vudc_hw: | 625 | err_init_vudc_hw: |
| @@ -640,7 +632,6 @@ int vudc_remove(struct platform_device *pdev) · 6 unmodified lines | |||
| 640 | { | 632 | { |
| 641 | struct vudc *udc = platform_get_drvdata(pdev); | 633 | struct vudc *udc = platform_get_drvdata(pdev); |
| 642 | 634 | ||
| 643 | sysfs_remove_group(&pdev->dev.kobj, &vudc_attr_group); | ||
| 644 | usb_del_gadget_udc(&udc->gadget); | 635 | usb_del_gadget_udc(&udc->gadget); |
| 645 | cleanup_vudc_hw(udc); | 636 | cleanup_vudc_hw(udc); |
| 646 | kfree(udc); | 637 | kfree(udc); |
| @@ -22,6 +22,7 @@ static struct platform_driver vudc_driver = { · 21 unmodified lines | |||
| 22 | .remove = vudc_remove, | 22 | .remove = vudc_remove, |
| 23 | .driver = { | 23 | .driver = { |
| 24 | .name = GADGET_NAME, | 24 | .name = GADGET_NAME, |
| 25 | .dev_groups = vudc_groups, | ||
| 25 | }, | 26 | }, |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| @@ -215,7 +215,12 @@ static struct bin_attribute *dev_bin_attrs[] = { · 214 unmodified lines | |||
| 215 | NULL, | 215 | NULL, |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | const struct attribute_group vudc_attr_group = { | 218 | static const struct attribute_group vudc_attr_group = { |
| 219 | .attrs = dev_attrs, | 219 | .attrs = dev_attrs, |
| 220 | .bin_attrs = dev_bin_attrs, | 220 | .bin_attrs = dev_bin_attrs, |
| 221 | }; | 221 | }; |
| 222 | |||
| 223 | const struct attribute_group *vudc_groups[] = { | ||
| 224 | &vudc_attr_group, | ||
| 225 | NULL, | ||
| 226 | }; | ||
| @@ -1014,10 +1014,14 @@ struct device_connection { · 1013 unmodified lines | |||
| 1014 | struct list_head list; | 1014 | struct list_head list; |
| 1015 | }; | 1015 | }; |
| 1016 | 1016 | ||
| 1017 | typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, | ||
| 1018 | void *data); | ||
| 1019 | |||
| 1020 | void *fwnode_connection_find_match(struct fwnode_handle *fwnode, | ||
| 1021 | const char *con_id, void *data, | ||
| 1022 | devcon_match_fn_t match); | ||
| 1017 | void *device_connection_find_match(struct device *dev, const char *con_id, | 1023 | void *device_connection_find_match(struct device *dev, const char *con_id, |
| 1018 | void *data, | 1024 | void *data, devcon_match_fn_t match); |
| 1019 | void *(*match)(struct device_connection *con, | ||
| 1020 | int ep, void *data)); | ||
| 1021 | 1025 | ||
| 1022 | struct device *device_connection_find(struct device *dev, const char *con_id); | 1026 | struct device *device_connection_find(struct device *dev, const char *con_id); |
| 1023 | 1027 | ||
| @@ -149,11 +149,6 @@ static inline int valid_dma_direction(int dma_direction) · 148 unmodified lines | |||
| 149 | (dma_direction == DMA_FROM_DEVICE)); | 149 | (dma_direction == DMA_FROM_DEVICE)); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static inline int is_device_dma_capable(struct device *dev) | ||
| 153 | { | ||
| 154 | return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE; | ||
| 155 | } | ||
| 156 | |||
| 157 | #ifdef CONFIG_DMA_DECLARE_COHERENT | 152 | #ifdef CONFIG_DMA_DECLARE_COHERENT |
| 158 | /* | 153 | /* |
| 159 | * These three functions are only for dma allocator. | 154 | * These three functions are only for dma allocator. |
| @@ -1,8 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* platform data for the OXU210HP HCD */ | ||
| 3 | |||
| 4 | struct oxu210hp_platform_data { | ||
| 5 | unsigned int bus16:1; | ||
| 6 | unsigned int use_hcd_otg:1; | ||
| 7 | unsigned int use_hcd_sph:1; | ||
| 8 | }; | ||
| @@ -1,43 +0,0 @@ | |||
| 1 | /** | ||
| 2 | * dwc3-omap.h - OMAP Specific Glue layer, header. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Author: Felipe Balbi <balbi@ti.com> | ||
| 8 | * | ||
| 9 | * Redistribution and use in source and binary forms, with or without | ||
| 10 | * modification, are permitted provided that the following conditions | ||
| 11 | * are met: | ||
| 12 | * 1. Redistributions of source code must retain the above copyright | ||
| 13 | * notice, this list of conditions, and the following disclaimer, | ||
| 14 | * without modification. | ||
| 15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 16 | * notice, this list of conditions and the following disclaimer in the | ||
| 17 | * documentation and/or other materials provided with the distribution. | ||
| 18 | * 3. The names of the above-listed copyright holders may not be used | ||
| 19 | * to endorse or promote products derived from this software without | ||
| 20 | * specific prior written permission. | ||
| 21 | * | ||
| 22 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 23 | * GNU General Public License ("GPL") version 2, as published by the Free | ||
| 24 | * Software Foundation. | ||
| 25 | * | ||
| 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 27 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
| 28 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| 30 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| 31 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| 32 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| 33 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
| 34 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
| 35 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 36 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 37 | */ | ||
| 38 | |||
| 39 | enum dwc3_omap_utmi_mode { | ||
| 40 | DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, | ||
| 41 | DWC3_OMAP_UTMI_MODE_HW, | ||
| 42 | DWC3_OMAP_UTMI_MODE_SW, | ||
| 43 | }; | ||
| @@ -24,6 +24,7 @@ struct platform_device { · 23 unmodified lines | |||
| 24 | int id; | 24 | int id; |
| 25 | bool id_auto; | 25 | bool id_auto; |
| 26 | struct device dev; | 26 | struct device dev; |
| 27 | u64 dma_mask; | ||
| 27 | u32 num_resources; | 28 | u32 num_resources; |
| 28 | struct resource *resource; | 29 | struct resource *resource; |
| 29 | 30 | ||
| @@ -48,7 +49,6 @@ extern void platform_device_unregister(struct platform_device *); · 18 unmodified lines | |||
| 48 | extern struct bus_type platform_bus_type; | 49 | extern struct bus_type platform_bus_type; |
| 49 | extern struct device platform_bus; | 50 | extern struct device platform_bus; |
| 50 | 51 | ||
| 51 | extern void arch_setup_pdev_archdata(struct platform_device *); | ||
| 52 | extern struct resource *platform_get_resource(struct platform_device *, | 52 | extern struct resource *platform_get_resource(struct platform_device *, |
| 53 | unsigned int, unsigned int); | 53 | unsigned int, unsigned int); |
| 54 | extern struct device * | 54 | extern struct device * |
| @@ -426,7 +426,6 @@ struct usb_bus { · 425 unmodified lines | |||
| 426 | struct device *sysdev; /* as seen from firmware or bus */ | 426 | struct device *sysdev; /* as seen from firmware or bus */ |
| 427 | int busnum; /* Bus number (in order of reg) */ | 427 | int busnum; /* Bus number (in order of reg) */ |
| 428 | const char *bus_name; /* stable id (PCI slot_name etc) */ | 428 | const char *bus_name; /* stable id (PCI slot_name etc) */ |
| 429 | u8 uses_dma; /* Does the host controller use DMA? */ | ||
| 430 | u8 uses_pio_for_control; /* | 429 | u8 uses_pio_for_control; /* |
| 431 | * Does the host controller use PIO | 430 | * Does the host controller use PIO |
| 432 | * for control transfers? | 431 | * for control transfers? |
| @@ -1151,6 +1150,8 @@ struct usbdrv_wrap { · 718 unmodified lines | |||
| 1151 | * @id_table: USB drivers use ID table to support hotplugging. | 1150 | * @id_table: USB drivers use ID table to support hotplugging. |
| 1152 | * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set | 1151 | * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set |
| 1153 | * or your driver's probe function will never get called. | 1152 | * or your driver's probe function will never get called. |
| 1153 | * @dev_groups: Attributes attached to the device that will be created once it | ||
| 1154 | * is bound to the driver. | ||
| 1154 | * @dynids: used internally to hold the list of dynamically added device | 1155 | * @dynids: used internally to hold the list of dynamically added device |
| 1155 | * ids for this driver. | 1156 | * ids for this driver. |
| 1156 | * @drvwrap: Driver-model core structure wrapper. | 1157 | * @drvwrap: Driver-model core structure wrapper. |
| @@ -1198,6 +1199,7 @@ struct usb_driver { · 41 unmodified lines | |||
| 1198 | int (*post_reset)(struct usb_interface *intf); | 1199 | int (*post_reset)(struct usb_interface *intf); |
| 1199 | 1200 | ||
| 1200 | const struct usb_device_id *id_table; | 1201 | const struct usb_device_id *id_table; |
| 1202 | const struct attribute_group **dev_groups; | ||
| 1201 | 1203 | ||
| 1202 | struct usb_dynids dynids; | 1204 | struct usb_dynids dynids; |
| 1203 | struct usbdrv_wrap drvwrap; | 1205 | struct usbdrv_wrap drvwrap; |
| @@ -1221,6 +1223,8 @@ struct usb_driver { · 17 unmodified lines | |||
| 1221 | * module is being unloaded. | 1223 | * module is being unloaded. |
| 1222 | * @suspend: Called when the device is going to be suspended by the system. | 1224 | * @suspend: Called when the device is going to be suspended by the system. |
| 1223 | * @resume: Called when the device is being resumed by the system. | 1225 | * @resume: Called when the device is being resumed by the system. |
| 1226 | * @dev_groups: Attributes attached to the device that will be created once it | ||
| 1227 | * is bound to the driver. | ||
| 1224 | * @drvwrap: Driver-model core structure wrapper. | 1228 | * @drvwrap: Driver-model core structure wrapper. |
| 1225 | * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend | 1229 | * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend |
| 1226 | * for devices bound to this driver. | 1230 | * for devices bound to this driver. |
| @@ -1235,6 +1239,7 @@ struct usb_device_driver { · 8 unmodified lines | |||
| 1235 | 1239 | ||
| 1236 | int (*suspend) (struct usb_device *udev, pm_message_t message); | 1240 | int (*suspend) (struct usb_device *udev, pm_message_t message); |
| 1237 | int (*resume) (struct usb_device *udev, pm_message_t message); | 1241 | int (*resume) (struct usb_device *udev, pm_message_t message); |
| 1242 | const struct attribute_group **dev_groups; | ||
| 1238 | struct usbdrv_wrap drvwrap; | 1243 | struct usbdrv_wrap drvwrap; |
| 1239 | unsigned int supports_autosuspend:1; | 1244 | unsigned int supports_autosuspend:1; |
| 1240 | }; | 1245 | }; |
| @@ -70,4 +70,31 @@ extern enum usb_device_speed usb_get_maximum_speed(struct device *dev); · 69 unmodified lines | |||
| 70 | */ | 70 | */ |
| 71 | extern const char *usb_state_string(enum usb_device_state state); | 71 | extern const char *usb_state_string(enum usb_device_state state); |
| 72 | 72 | ||
| 73 | #ifdef CONFIG_TRACING | ||
| 74 | /** | ||
| 75 | * usb_decode_ctrl - Returns human readable representation of control request. | ||
| 76 | * @str: buffer to return a human-readable representation of control request. | ||
| 77 | * This buffer should have about 200 bytes. | ||
| 78 | * @size: size of str buffer. | ||
| 79 | * @bRequestType: matches the USB bmRequestType field | ||
| 80 | * @bRequest: matches the USB bRequest field | ||
| 81 | * @wValue: matches the USB wValue field (CPU byte order) | ||
| 82 | * @wIndex: matches the USB wIndex field (CPU byte order) | ||
| 83 | * @wLength: matches the USB wLength field (CPU byte order) | ||
| 84 | * | ||
| 85 | * Function returns decoded, formatted and human-readable description of | ||
| 86 | * control request packet. | ||
| 87 | * | ||
| 88 | * The usage scenario for this is for tracepoints, so function as a return | ||
| 89 | * use the same value as in parameters. This approach allows to use this | ||
| 90 | * function in TP_printk | ||
| 91 | * | ||
| 92 | * Important: wValue, wIndex, wLength parameters before invoking this function | ||
| 93 | * should be processed by le16_to_cpu macro. | ||
| 94 | */ | ||
| 95 | extern const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, | ||
| 96 | __u8 bRequest, __u16 wValue, __u16 wIndex, | ||
| 97 | __u16 wLength); | ||
| 98 | #endif | ||
| 99 | |||
| 73 | #endif /* __LINUX_USB_CH9_H */ | 100 | #endif /* __LINUX_USB_CH9_H */ |
| @@ -291,6 +291,9 @@ struct usb_dcd_config_params { · 290 unmodified lines | |||
| 291 | #define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ | 291 | #define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ |
| 292 | __le16 bU2DevExitLat; /* U2 Device exit Latency */ | 292 | __le16 bU2DevExitLat; /* U2 Device exit Latency */ |
| 293 | #define USB_DEFAULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ | 293 | #define USB_DEFAULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ |
| 294 | __u8 besl_baseline; /* Recommended baseline BESL (0-15) */ | ||
| 295 | __u8 besl_deep; /* Recommended deep BESL (0-15) */ | ||
| 296 | #define USB_DEFAULT_BESL_UNSPECIFIED 0xFF /* No recommended value */ | ||
| 294 | }; | 297 | }; |
| 295 | 298 | ||
| 296 | 299 | ||
| @@ -256,6 +256,7 @@ struct hc_driver { · 255 unmodified lines | |||
| 256 | 256 | ||
| 257 | int flags; | 257 | int flags; |
| 258 | #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ | 258 | #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ |
| 259 | #define HCD_DMA 0x0002 /* HC uses DMA */ | ||
| 259 | #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ | 260 | #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ |
| 260 | #define HCD_USB11 0x0010 /* USB 1.1 */ | 261 | #define HCD_USB11 0x0010 /* USB 1.1 */ |
| 261 | #define HCD_USB2 0x0020 /* USB 2.0 */ | 262 | #define HCD_USB2 0x0020 /* USB 2.0 */ |
| @@ -422,8 +423,10 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd, · 160 unmodified lines | |||
| 422 | return hcd->high_prio_bh.completing_ep == ep; | 423 | return hcd->high_prio_bh.completing_ep == ep; |
| 423 | } | 424 | } |
| 424 | 425 | ||
| 425 | #define hcd_uses_dma(hcd) \ | 426 | static inline bool hcd_uses_dma(struct usb_hcd *hcd) |
| 426 | (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma) | 427 | { |
| 428 | return IS_ENABLED(CONFIG_HAS_DMA) && (hcd->driver->flags & HCD_DMA); | ||
| 429 | } | ||
| 427 | 430 | ||
| 428 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); | 431 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); |
| 429 | extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, | 432 | extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, |
| @@ -594,6 +597,10 @@ extern void usb_ep0_reinit(struct usb_device *); · 164 unmodified lines | |||
| 594 | #define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS) | 597 | #define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS) |
| 595 | #define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE) | 598 | #define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE) |
| 596 | #define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE) | 599 | #define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE) |
| 600 | #define ClearTTBuffer HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_CLEAR_TT_BUFFER) | ||
| 601 | #define ResetTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_RESET_TT) | ||
| 602 | #define GetTTState HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, HUB_GET_TT_STATE) | ||
| 603 | #define StopTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_STOP_TT) | ||
| 597 | 604 | ||
| 598 | 605 | ||
| 599 | /*-------------------------------------------------------------------------*/ | 606 | /*-------------------------------------------------------------------------*/ |
| @@ -42,14 +42,51 @@ struct usb_role_switch_desc { · 41 unmodified lines | |||
| 42 | bool allow_userspace_control; | 42 | bool allow_userspace_control; |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | |||
| 46 | #if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) | ||
| 45 | int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); | 47 | int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); |
| 46 | enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); | 48 | enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); |
| 47 | struct usb_role_switch *usb_role_switch_get(struct device *dev); | 49 | struct usb_role_switch *usb_role_switch_get(struct device *dev); |
| 50 | struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node); | ||
| 48 | void usb_role_switch_put(struct usb_role_switch *sw); | 51 | void usb_role_switch_put(struct usb_role_switch *sw); |
| 49 | 52 | ||
| 50 | struct usb_role_switch * | 53 | struct usb_role_switch * |
| 51 | usb_role_switch_register(struct device *parent, | 54 | usb_role_switch_register(struct device *parent, |
| 52 | const struct usb_role_switch_desc *desc); | 55 | const struct usb_role_switch_desc *desc); |
| 53 | void usb_role_switch_unregister(struct usb_role_switch *sw); | 56 | void usb_role_switch_unregister(struct usb_role_switch *sw); |
| 57 | #else | ||
| 58 | static inline int usb_role_switch_set_role(struct usb_role_switch *sw, | ||
| 59 | enum usb_role role) | ||
| 60 | { | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) | ||
| 65 | { | ||
| 66 | return USB_ROLE_NONE; | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) | ||
| 70 | { | ||
| 71 | return ERR_PTR(-ENODEV); | ||
| 72 | } | ||
| 73 | |||
| 74 | static inline struct usb_role_switch * | ||
| 75 | fwnode_usb_role_switch_get(struct fwnode_handle *node) | ||
| 76 | { | ||
| 77 | return ERR_PTR(-ENODEV); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void usb_role_switch_put(struct usb_role_switch *sw) { } | ||
| 81 | |||
| 82 | static inline struct usb_role_switch * | ||
| 83 | usb_role_switch_register(struct device *parent, | ||
| 84 | const struct usb_role_switch_desc *desc) | ||
| 85 | { | ||
| 86 | return ERR_PTR(-ENODEV); | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { } | ||
| 90 | #endif | ||
| 54 | 91 | ||
| 55 | #endif /* __LINUX_USB_ROLE_H */ | 92 | #endif /* __LINUX_USB_ROLE_H */ |
| @@ -113,7 +113,10 @@ struct usb338x_ll_regs { · 112 unmodified lines | |||
| 113 | u32 ll_ltssm_ctrl1; | 113 | u32 ll_ltssm_ctrl1; |
| 114 | u32 ll_ltssm_ctrl2; | 114 | u32 ll_ltssm_ctrl2; |
| 115 | u32 ll_ltssm_ctrl3; | 115 | u32 ll_ltssm_ctrl3; |
| 116 | u32 unused[2]; | 116 | u32 unused1; |
| 117 | |||
| 118 | /* 0x710 */ | ||
| 119 | u32 unused2; | ||
| 117 | u32 ll_general_ctrl0; | 120 | u32 ll_general_ctrl0; |
| 118 | u32 ll_general_ctrl1; | 121 | u32 ll_general_ctrl1; |
| 119 | #define PM_U3_AUTO_EXIT 29 | 122 | #define PM_U3_AUTO_EXIT 29 |
| @@ -136,29 +139,41 @@ struct usb338x_ll_regs { · 16 unmodified lines | |||
| 136 | u32 ll_general_ctrl2; | 139 | u32 ll_general_ctrl2; |
| 137 | #define SELECT_INVERT_LANE_POLARITY 7 | 140 | #define SELECT_INVERT_LANE_POLARITY 7 |
| 138 | #define FORCE_INVERT_LANE_POLARITY 6 | 141 | #define FORCE_INVERT_LANE_POLARITY 6 |
| 142 | |||
| 143 | /* 0x720 */ | ||
| 139 | u32 ll_general_ctrl3; | 144 | u32 ll_general_ctrl3; |
| 140 | u32 ll_general_ctrl4; | 145 | u32 ll_general_ctrl4; |
| 141 | u32 ll_error_gen; | 146 | u32 ll_error_gen; |
| 142 | } __packed; | 147 | u32 unused3; |
| 148 | |||
| 149 | /* 0x730 */ | ||
| 150 | u32 unused4[4]; | ||
| 143 | 151 | ||
| 144 | struct usb338x_ll_lfps_regs { | 152 | /* 0x740 */ |
| 145 | /* offset 0x748 */ | 153 | u32 unused5[2]; |
| 146 | u32 ll_lfps_5; | 154 | u32 ll_lfps_5; |
| 147 | #define TIMER_LFPS_6US 16 | 155 | #define TIMER_LFPS_6US 16 |
| 148 | u32 ll_lfps_6; | 156 | u32 ll_lfps_6; |
| 149 | #define TIMER_LFPS_80US 0 | 157 | #define TIMER_LFPS_80US 0 |
| 150 | } __packed; | ||
| 151 | 158 | ||
| 152 | struct usb338x_ll_tsn_regs { | 159 | /* 0x750 */ |
| 153 | /* offset 0x77C */ | 160 | u32 unused6[8]; |
| 161 | |||
| 162 | /* 0x770 */ | ||
| 163 | u32 unused7[3]; | ||
| 154 | u32 ll_tsn_counters_2; | 164 | u32 ll_tsn_counters_2; |
| 155 | #define HOT_TX_NORESET_TS2 24 | 165 | #define HOT_TX_NORESET_TS2 24 |
| 166 | |||
| 167 | /* 0x780 */ | ||
| 156 | u32 ll_tsn_counters_3; | 168 | u32 ll_tsn_counters_3; |
| 157 | #define HOT_RX_RESET_TS2 0 | 169 | #define HOT_RX_RESET_TS2 0 |
| 158 | } __packed; | 170 | u32 unused8[3]; |
| 159 | 171 | ||
| 160 | struct usb338x_ll_chi_regs { | 172 | /* 0x790 */ |
| 161 | /* offset 0x79C */ | 173 | u32 unused9; |
| 174 | u32 ll_lfps_timers_2; | ||
| 175 | #define LFPS_TIMERS_2_WORKAROUND_VALUE 0x084d | ||
| 176 | u32 unused10; | ||
| 162 | u32 ll_tsn_chicken_bit; | 177 | u32 ll_tsn_chicken_bit; |
| 163 | #define RECOVERY_IDLE_TO_RECOVER_FMW 3 | 178 | #define RECOVERY_IDLE_TO_RECOVER_FMW 3 |
| 164 | } __packed; | 179 | } __packed; |
| @@ -894,6 +894,8 @@ struct usb_ext_cap_descriptor { /* Link Power Management */ · 893 unmodified lines | |||
| 894 | #define USB_BESL_SUPPORT (1 << 2) /* supports BESL */ | 894 | #define USB_BESL_SUPPORT (1 << 2) /* supports BESL */ |
| 895 | #define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/ | 895 | #define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/ |
| 896 | #define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */ | 896 | #define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */ |
| 897 | #define USB_SET_BESL_BASELINE(p) (((p) & 0xf) << 8) | ||
| 898 | #define USB_SET_BESL_DEEP(p) (((p) & 0xf) << 12) | ||
| 897 | #define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8) | 899 | #define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8) |
| 898 | #define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12) | 900 | #define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12) |
| 899 | } __attribute__((packed)); | 901 | } __attribute__((packed)); |
| @@ -158,6 +158,7 @@ struct usbdevfs_hub_portinfo { · 157 unmodified lines | |||
| 158 | #define USBDEVFS_CAP_MMAP 0x20 | 158 | #define USBDEVFS_CAP_MMAP 0x20 |
| 159 | #define USBDEVFS_CAP_DROP_PRIVILEGES 0x40 | 159 | #define USBDEVFS_CAP_DROP_PRIVILEGES 0x40 |
| 160 | #define USBDEVFS_CAP_CONNINFO_EX 0x80 | 160 | #define USBDEVFS_CAP_CONNINFO_EX 0x80 |
| 161 | #define USBDEVFS_CAP_SUSPEND 0x100 | ||
| 161 | 162 | ||
| 162 | /* USBDEVFS_DISCONNECT_CLAIM flags & struct */ | 163 | /* USBDEVFS_DISCONNECT_CLAIM flags & struct */ |
| 163 | 164 | ||
| @@ -223,5 +224,8 @@ struct usbdevfs_streams { · 59 unmodified lines | |||
| 223 | * extending size of the data returned. | 224 | * extending size of the data returned. |
| 224 | */ | 225 | */ |
| 225 | #define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len) | 226 | #define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len) |
| 227 | #define USBDEVFS_FORBID_SUSPEND _IO('U', 33) | ||
| 228 | #define USBDEVFS_ALLOW_SUSPEND _IO('U', 34) | ||
| 229 | #define USBDEVFS_WAIT_FOR_RESUME _IO('U', 35) | ||
| 226 | 230 | ||
| 227 | #endif /* _UAPI_LINUX_USBDEVICE_FS_H */ | 231 | #endif /* _UAPI_LINUX_USBDEVICE_FS_H */ |
| @@ -226,8 +226,10 @@ int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev) · 225 unmodified lines | |||
| 226 | path = udev_device_get_syspath(sdev); | 226 | path = udev_device_get_syspath(sdev); |
| 227 | name = udev_device_get_sysname(sdev); | 227 | name = udev_device_get_sysname(sdev); |
| 228 | 228 | ||
| 229 | strncpy(udev->path, path, SYSFS_PATH_MAX); | 229 | strncpy(udev->path, path, SYSFS_PATH_MAX - 1); |
| 230 | strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE); | 230 | udev->path[SYSFS_PATH_MAX - 1] = '\0'; |
| 231 | strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE - 1); | ||
| 232 | udev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0'; | ||
| 231 | 233 | ||
| 232 | sscanf(name, "%u-%u", &busnum, &devnum); | 234 | sscanf(name, "%u-%u", &busnum, &devnum); |
| 233 | udev->busnum = busnum; | 235 | udev->busnum = busnum; |
| @@ -91,7 +91,8 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) · 90 unmodified lines | |||
| 91 | copy_descr_attr16(dev, &descr, idProduct); | 91 | copy_descr_attr16(dev, &descr, idProduct); |
| 92 | copy_descr_attr16(dev, &descr, bcdDevice); | 92 | copy_descr_attr16(dev, &descr, bcdDevice); |
| 93 | 93 | ||
| 94 | strncpy(dev->path, path, SYSFS_PATH_MAX); | 94 | strncpy(dev->path, path, SYSFS_PATH_MAX - 1); |
| 95 | dev->path[SYSFS_PATH_MAX - 1] = '\0'; | ||
| 95 | 96 | ||
| 96 | dev->speed = USB_SPEED_UNKNOWN; | 97 | dev->speed = USB_SPEED_UNKNOWN; |
| 97 | speed = udev_device_get_sysattr_value(sdev, "current_speed"); | 98 | speed = udev_device_get_sysattr_value(sdev, "current_speed"); |
| @@ -110,7 +111,8 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) · 12 unmodified lines | |||
| 110 | dev->busnum = 0; | 111 | dev->busnum = 0; |
| 111 | 112 | ||
| 112 | name = udev_device_get_sysname(plat); | 113 | name = udev_device_get_sysname(plat); |
| 113 | strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE); | 114 | strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE - 1); |
| 115 | dev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0'; | ||
| 114 | return 0; | 116 | return 0; |
| 115 | err: | 117 | err: |
| 116 | fclose(fd); | 118 | fclose(fd); |